Shrink the size of Expr (#12610)

# Description
Continuing from #12568, this PR further reduces the size of `Expr` from
64 to 40 bytes. It also reduces `Expression` from 128 to 96 bytes and
`Type` from 32 to 24 bytes.

This was accomplished by:
- for `Expr` with multiple fields (e.g., `Expr::Thing(A, B, C)`),
merging the fields into new AST struct types and then boxing this struct
(e.g. `Expr::Thing(Box<ABC>)`).
- replacing `Vec<T>` with `Box<[T]>` in multiple places. `Expr`s and
`Expression`s should rarely be mutated, if at all, so this optimization
makes sense.

By reducing the size of these types, I didn't notice a large performance
improvement (at least compared to #12568). But this PR does reduce the
memory usage of nushell. My config is somewhat light so I only noticed a
difference of 1.4MiB (38.9MiB vs 37.5MiB).

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
This commit is contained in:
Ian Manske
2024-04-24 15:46:35 +00:00
committed by GitHub
parent c52884b3c8
commit 9996e4a1f8
195 changed files with 688 additions and 601 deletions

View File

@ -242,7 +242,7 @@ pub fn flatten_expression(
}
}
for arg in args {
for arg in args.as_ref() {
//output.push((*arg, FlatShape::ExternalArg));
match arg {
ExternalArgument::Regular(expr) => match expr {
@ -297,9 +297,9 @@ pub fn flatten_expression(
output
}
Expr::ValueWithUnit(x, unit) => {
let mut output = flatten_expression(working_set, x);
output.push((unit.span, FlatShape::String));
Expr::ValueWithUnit(value) => {
let mut output = flatten_expression(working_set, &value.expr);
output.push((value.unit.span, FlatShape::String));
output
}
@ -346,17 +346,17 @@ pub fn flatten_expression(
Expr::Overlay(_) => {
vec![(expr.span, FlatShape::String)]
}
Expr::Range(from, next, to, op) => {
Expr::Range(range) => {
let mut output = vec![];
if let Some(f) = from {
if let Some(f) = &range.from {
output.extend(flatten_expression(working_set, f));
}
if let Some(s) = next {
output.extend(vec![(op.next_op_span, FlatShape::Operator)]);
if let Some(s) = &range.next {
output.extend(vec![(range.operator.next_op_span, FlatShape::Operator)]);
output.extend(flatten_expression(working_set, s));
}
output.extend(vec![(op.span, FlatShape::Operator)]);
if let Some(t) = to {
output.extend(vec![(range.operator.span, FlatShape::Operator)]);
if let Some(t) = &range.to {
output.extend(flatten_expression(working_set, t));
}
output
@ -495,9 +495,9 @@ pub fn flatten_expression(
output
}
Expr::Keyword(_, span, expr) => {
let mut output = vec![(*span, FlatShape::Keyword)];
output.extend(flatten_expression(working_set, expr));
Expr::Keyword(kw) => {
let mut output = vec![(kw.span, FlatShape::Keyword)];
output.extend(flatten_expression(working_set, &kw.expr));
output
}
Expr::Operator(_) => {
@ -509,12 +509,12 @@ pub fn flatten_expression(
Expr::String(_) => {
vec![(expr.span, FlatShape::String)]
}
Expr::Table(headers, cells) => {
Expr::Table(table) => {
let outer_span = expr.span;
let mut last_end = outer_span.start;
let mut output = vec![];
for e in headers {
for e in table.columns.as_ref() {
let flattened = flatten_expression(working_set, e);
if let Some(first) = flattened.first() {
if first.0.start > last_end {
@ -528,8 +528,8 @@ pub fn flatten_expression(
output.extend(flattened);
}
for row in cells {
for expr in row {
for row in table.rows.as_ref() {
for expr in row.as_ref() {
let flattened = flatten_expression(working_set, expr);
if let Some(first) = flattened.first() {
if first.0.start > last_end {

View File

@ -1041,10 +1041,10 @@ pub fn parse_alias(
// Then from the command itself
true => match alias_call.arguments.get(1) {
Some(Argument::Positional(Expression {
expr: Expr::Keyword(.., expr),
expr: Expr::Keyword(kw),
..
})) => {
let aliased = working_set.get_span_contents(expr.span);
let aliased = working_set.get_span_contents(kw.expr.span);
(
format!("Alias for `{}`", String::from_utf8_lossy(aliased)),
String::new(),

View File

@ -256,8 +256,6 @@ fn parse_external_arg(working_set: &mut StateWorkingSet, span: Span) -> External
pub fn parse_external_call(working_set: &mut StateWorkingSet, spans: &[Span]) -> Expression {
trace!("parse external");
let mut args = vec![];
let head_contents = working_set.get_span_contents(spans[0]);
let head_span = if head_contents.starts_with(b"^") {
@ -286,10 +284,10 @@ pub fn parse_external_call(working_set: &mut StateWorkingSet, spans: &[Span]) ->
})
};
for span in &spans[1..] {
let arg = parse_external_arg(working_set, *span);
args.push(arg);
}
let args = spans[1..]
.iter()
.map(|&span| parse_external_arg(working_set, span))
.collect();
Expression {
expr: Expr::ExternalCall(head, args),
@ -695,25 +693,29 @@ pub fn parse_multispan_value(
String::from_utf8_lossy(keyword).into(),
Span::new(spans[*spans_idx - 1].end, spans[*spans_idx - 1].end),
));
let keyword = Keyword {
keyword: keyword.as_slice().into(),
span: spans[*spans_idx - 1],
expr: Expression::garbage(arg_span),
};
return Expression {
expr: Expr::Keyword(
keyword.clone(),
spans[*spans_idx - 1],
Box::new(Expression::garbage(arg_span)),
),
expr: Expr::Keyword(Box::new(keyword)),
span: arg_span,
ty: Type::Any,
custom_completion: None,
};
}
let keyword_span = spans[*spans_idx - 1];
let expr = parse_multispan_value(working_set, spans, spans_idx, arg);
let ty = expr.ty.clone();
let keyword = Keyword {
keyword: keyword.as_slice().into(),
span: spans[*spans_idx - 1],
expr: parse_multispan_value(working_set, spans, spans_idx, arg),
};
Expression {
expr: Expr::Keyword(keyword.clone(), keyword_span, Box::new(expr)),
ty: keyword.expr.ty.clone(),
expr: Expr::Keyword(Box::new(keyword)),
span: arg_span,
ty,
custom_completion: None,
}
}
@ -1128,18 +1130,17 @@ pub fn parse_call(working_set: &mut StateWorkingSet, spans: &[Span], head: Span)
{
trace!("parsing: alias of external call");
let mut final_args = args.clone();
let mut head = head.clone();
head.span = spans[0]; // replacing the spans preserves syntax highlighting
for arg_span in spans.iter().skip(1) {
let mut final_args = args.clone().into_vec();
for arg_span in &spans[1..] {
let arg = parse_external_arg(working_set, *arg_span);
final_args.push(arg);
}
let mut head = head.clone();
head.span = spans[0]; // replacing the spans preserves syntax highlighting
return Expression {
expr: Expr::ExternalCall(head, final_args),
expr: Expr::ExternalCall(head, final_args.into()),
span: span(spans),
ty: ty.clone(),
custom_completion: *custom_completion,
@ -1493,22 +1494,14 @@ pub fn parse_range(working_set: &mut StateWorkingSet, span: Span) -> Expression
None
} else {
let from_span = Span::new(span.start, span.start + dotdot_pos[0]);
Some(Box::new(parse_value(
working_set,
from_span,
&SyntaxShape::Number,
)))
Some(parse_value(working_set, from_span, &SyntaxShape::Number))
};
let to = if token.ends_with(range_op_str) {
None
} else {
let to_span = Span::new(range_op_span.end, span.end);
Some(Box::new(parse_value(
working_set,
to_span,
&SyntaxShape::Number,
)))
Some(parse_value(working_set, to_span, &SyntaxShape::Number))
};
trace!("-- from: {:?} to: {:?}", from, to);
@ -1523,25 +1516,28 @@ pub fn parse_range(working_set: &mut StateWorkingSet, span: Span) -> Expression
let next_span = Span::new(next_op_span.end, range_op_span.start);
(
Some(Box::new(parse_value(
working_set,
next_span,
&SyntaxShape::Number,
))),
Some(parse_value(working_set, next_span, &SyntaxShape::Number)),
next_op_span,
)
} else {
(None, span)
};
let range_op = RangeOperator {
let operator = RangeOperator {
inclusion,
span: range_op_span,
next_op_span,
};
let range = Range {
from,
next,
to,
operator,
};
Expression {
expr: Expr::Range(from, next, to, range_op),
expr: Expr::Range(Box::new(range)),
span,
ty: Type::Range,
custom_completion: None,
@ -2317,19 +2313,20 @@ pub fn parse_unit_value<'res>(
};
trace!("-- found {} {:?}", num, unit);
let value = ValueWithUnit {
expr: Expression {
expr: Expr::Int(num),
span: lhs_span,
ty: Type::Number,
custom_completion: None,
},
unit: Spanned {
item: unit,
span: unit_span,
},
};
let expr = Expression {
expr: Expr::ValueWithUnit(
Box::new(Expression {
expr: Expr::Int(num),
span: lhs_span,
ty: Type::Number,
custom_completion: None,
}),
Spanned {
item: unit,
span: unit_span,
},
),
expr: Expr::ValueWithUnit(Box::new(value)),
span,
ty,
custom_completion: None,
@ -4007,11 +4004,16 @@ fn parse_table_expression(working_set: &mut StateWorkingSet, span: Span) -> Expr
working_set.parse_errors.extend(errs);
ty
} else {
Type::Table(vec![])
Type::table()
};
let table = Table {
columns: head.into(),
rows: rows.into_iter().map(Into::into).collect(),
};
Expression {
expr: Expr::Table(head, rows),
expr: Expr::Table(table),
span,
ty,
custom_completion: None,
@ -4057,7 +4059,7 @@ fn table_type(head: &[Expression], rows: &[Vec<Expression>]) -> (Type, Vec<Parse
ty.reverse();
(Type::Table(ty), errors)
(Type::Table(ty.into()), errors)
}
pub fn parse_block_expression(working_set: &mut StateWorkingSet, span: Span) -> Expression {
@ -5371,7 +5373,7 @@ pub fn parse_record(working_set: &mut StateWorkingSet, span: Span) -> Expression
match &inner.ty {
Type::Record(inner_fields) => {
if let Some(fields) = &mut field_types {
for (field, ty) in inner_fields {
for (field, ty) in inner_fields.as_ref() {
fields.push((field.clone(), ty.clone()));
}
}
@ -5450,7 +5452,7 @@ pub fn parse_record(working_set: &mut StateWorkingSet, span: Span) -> Expression
expr: Expr::Record(output),
span,
ty: (if let Some(fields) = field_types {
Type::Record(fields)
Type::Record(fields.into())
} else {
Type::Any
}),
@ -5988,7 +5990,7 @@ pub fn discover_captures_in_expr(
Expr::ExternalCall(head, args) => {
discover_captures_in_expr(working_set, head, seen, seen_blocks, output)?;
for ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) in args {
for ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) in args.as_ref() {
discover_captures_in_expr(working_set, expr, seen, seen_blocks, output)?;
}
}
@ -6004,8 +6006,8 @@ pub fn discover_captures_in_expr(
Expr::Nothing => {}
Expr::GlobPattern(_, _) => {}
Expr::Int(_) => {}
Expr::Keyword(_, _, expr) => {
discover_captures_in_expr(working_set, expr, seen, seen_blocks, output)?;
Expr::Keyword(kw) => {
discover_captures_in_expr(working_set, &kw.expr, seen, seen_blocks, output)?;
}
Expr::List(list) => {
for item in list {
@ -6013,15 +6015,15 @@ pub fn discover_captures_in_expr(
}
}
Expr::Operator(_) => {}
Expr::Range(expr1, expr2, expr3, _) => {
if let Some(expr) = expr1 {
discover_captures_in_expr(working_set, expr, seen, seen_blocks, output)?;
Expr::Range(range) => {
if let Some(from) = &range.from {
discover_captures_in_expr(working_set, from, seen, seen_blocks, output)?;
}
if let Some(expr) = expr2 {
discover_captures_in_expr(working_set, expr, seen, seen_blocks, output)?;
if let Some(next) = &range.next {
discover_captures_in_expr(working_set, next, seen, seen_blocks, output)?;
}
if let Some(expr) = expr3 {
discover_captures_in_expr(working_set, expr, seen, seen_blocks, output)?;
if let Some(to) = &range.to {
discover_captures_in_expr(working_set, to, seen, seen_blocks, output)?;
}
}
Expr::Record(items) => {
@ -6107,18 +6109,18 @@ pub fn discover_captures_in_expr(
}
}
}
Expr::Table(headers, values) => {
for header in headers {
Expr::Table(table) => {
for header in table.columns.as_ref() {
discover_captures_in_expr(working_set, header, seen, seen_blocks, output)?;
}
for row in values {
for cell in row {
for row in table.rows.as_ref() {
for cell in row.as_ref() {
discover_captures_in_expr(working_set, cell, seen, seen_blocks, output)?;
}
}
}
Expr::ValueWithUnit(expr, _) => {
discover_captures_in_expr(working_set, expr, seen, seen_blocks, output)?;
Expr::ValueWithUnit(value) => {
discover_captures_in_expr(working_set, &value.expr, seen, seen_blocks, output)?;
}
Expr::Var(var_id) => {
if (*var_id > ENV_VARIABLE_ID || *var_id == IN_VARIABLE_ID) && !seen.contains(var_id) {

View File

@ -90,8 +90,8 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Duration, None),
(Type::Filesize, Type::Filesize) => (Type::Filesize, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
@ -146,8 +146,8 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Duration, None),
(Type::Filesize, Type::Filesize) => (Type::Filesize, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
@ -197,8 +197,8 @@ pub fn math_result_type(
(Type::Duration, Type::Float) => (Type::Duration, None),
(Type::Float, Type::Duration) => (Type::Duration, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
@ -246,8 +246,8 @@ pub fn math_result_type(
(Type::Number, Type::Float) => (Type::Number, None),
(Type::Float, Type::Number) => (Type::Number, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
@ -296,8 +296,8 @@ pub fn math_result_type(
(Type::Duration, Type::Int) => (Type::Duration, None),
(Type::Duration, Type::Float) => (Type::Duration, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
@ -380,10 +380,8 @@ pub fn math_result_type(
match (&lhs.ty, &rhs.ty) {
(Type::Bool, Type::Bool) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => {
(Type::Custom(a.to_string()), None)
}
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
@ -434,8 +432,8 @@ pub fn math_result_type(
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Nothing, _) => (Type::Nothing, None),
(_, Type::Nothing) => (Type::Nothing, None),
@ -484,8 +482,8 @@ pub fn math_result_type(
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Nothing, _) => (Type::Nothing, None),
(_, Type::Nothing) => (Type::Nothing, None),
@ -534,8 +532,8 @@ pub fn math_result_type(
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
@ -584,8 +582,8 @@ pub fn math_result_type(
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
@ -620,14 +618,14 @@ pub fn math_result_type(
}
},
Operator::Comparison(Comparison::Equal) => match (&lhs.ty, &rhs.ty) {
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
_ => (Type::Bool, None),
},
Operator::Comparison(Comparison::NotEqual) => match (&lhs.ty, &rhs.ty) {
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
_ => (Type::Bool, None),
},
@ -636,8 +634,8 @@ pub fn math_result_type(
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::String, _) => {
*op = Expression::garbage(op.span);
@ -671,8 +669,8 @@ pub fn math_result_type(
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::String, _) => {
*op = Expression::garbage(op.span);
@ -706,8 +704,8 @@ pub fn math_result_type(
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::String, _) => {
*op = Expression::garbage(op.span);
@ -741,8 +739,8 @@ pub fn math_result_type(
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::String, _) => {
*op = Expression::garbage(op.span);
@ -777,8 +775,8 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::String, Type::Record(_)) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
@ -815,8 +813,8 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::String, Type::Record(_)) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None),
(Type::Custom(a), _) => (Type::Custom(a.clone()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),

View File

@ -1,6 +1,6 @@
use nu_parser::*;
use nu_protocol::{
ast::{Argument, Call, Expr, PathMember},
ast::{Argument, Call, Expr, PathMember, Range},
engine::{Command, EngineState, Stack, StateWorkingSet},
ParseError, PipelineData, ShellError, Signature, Span, SyntaxShape,
};
@ -311,7 +311,7 @@ pub fn parse_cell_path() {
working_set.add_variable(
"foo".to_string().into_bytes(),
Span::test_data(),
nu_protocol::Type::Record(vec![]),
nu_protocol::Type::record(),
false,
);
@ -356,7 +356,7 @@ pub fn parse_cell_path_optional() {
working_set.add_variable(
"foo".to_string().into_bytes(),
Span::test_data(),
nu_protocol::Type::Record(vec![]),
nu_protocol::Type::record(),
false,
);
@ -986,20 +986,25 @@ mod range {
assert_eq!(pipeline.len(), 1, "{tag}: expression length");
let element = &pipeline.elements[0];
assert!(element.redirection.is_none());
if let Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: the_inclusion,
..
},
) = element.expr.expr
{
assert_eq!(
the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
if let Expr::Range(range) = &element.expr.expr {
if let Range {
from: Some(_),
next: None,
to: Some(_),
operator:
RangeOperator {
inclusion: the_inclusion,
..
},
} = range.as_ref()
{
assert_eq!(
*the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
} else {
panic!("{tag}: expression mismatch.")
}
} else {
panic!("{tag}: expression mismatch.")
};
@ -1040,20 +1045,25 @@ mod range {
assert_eq!(pipeline.len(), 1, "{tag}: expression length 1");
let element = &pipeline.elements[0];
assert!(element.redirection.is_none());
if let Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: the_inclusion,
..
},
) = element.expr.expr
{
assert_eq!(
the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
if let Expr::Range(range) = &element.expr.expr {
if let Range {
from: Some(_),
next: None,
to: Some(_),
operator:
RangeOperator {
inclusion: the_inclusion,
..
},
} = range.as_ref()
{
assert_eq!(
*the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
} else {
panic!("{tag}: expression mismatch.")
}
} else {
panic!("{tag}: expression mismatch.")
};
@ -1081,20 +1091,25 @@ mod range {
assert_eq!(pipeline.len(), 1, "{tag}: expression length");
let element = &pipeline.elements[0];
assert!(element.redirection.is_none());
if let Expr::Range(
Some(_),
None,
None,
RangeOperator {
inclusion: the_inclusion,
..
},
) = element.expr.expr
{
assert_eq!(
the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
if let Expr::Range(range) = &element.expr.expr {
if let Range {
from: Some(_),
next: None,
to: None,
operator:
RangeOperator {
inclusion: the_inclusion,
..
},
} = range.as_ref()
{
assert_eq!(
*the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
} else {
panic!("{tag}: expression mismatch.")
}
} else {
panic!("{tag}: expression mismatch.")
};
@ -1122,20 +1137,25 @@ mod range {
assert_eq!(pipeline.len(), 1, "{tag}: expression length");
let element = &pipeline.elements[0];
assert!(element.redirection.is_none());
if let Expr::Range(
None,
None,
Some(_),
RangeOperator {
inclusion: the_inclusion,
..
},
) = element.expr.expr
{
assert_eq!(
the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
if let Expr::Range(range) = &element.expr.expr {
if let Range {
from: None,
next: None,
to: Some(_),
operator:
RangeOperator {
inclusion: the_inclusion,
..
},
} = range.as_ref()
{
assert_eq!(
*the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
} else {
panic!("{tag}: expression mismatch.")
}
} else {
panic!("{tag}: expression mismatch.")
};
@ -1163,20 +1183,25 @@ mod range {
assert_eq!(pipeline.len(), 1, "{tag}: expression length");
let element = &pipeline.elements[0];
assert!(element.redirection.is_none());
if let Expr::Range(
Some(_),
Some(_),
Some(_),
RangeOperator {
inclusion: the_inclusion,
..
},
) = element.expr.expr
{
assert_eq!(
the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
if let Expr::Range(range) = &element.expr.expr {
if let Range {
from: Some(_),
next: Some(_),
to: Some(_),
operator:
RangeOperator {
inclusion: the_inclusion,
..
},
} = range.as_ref()
{
assert_eq!(
*the_inclusion, inclusion,
"{tag}: wrong RangeInclusion {the_inclusion:?}"
);
} else {
panic!("{tag}: expression mismatch.")
}
} else {
panic!("{tag}: expression mismatch.")
};