diff --git a/crates/nu-command/src/filters/find.rs b/crates/nu-command/src/filters/find.rs index f99835462..3fa4fcf3e 100644 --- a/crates/nu-command/src/filters/find.rs +++ b/crates/nu-command/src/filters/find.rs @@ -305,13 +305,13 @@ fn find_with_rest( | Value::Block { .. } | Value::Nothing { .. } | Value::Error { .. } => lower_value - .eq(span, term) + .eq(span, term, span) .map_or(false, |value| value.is_true()), Value::String { .. } | Value::List { .. } | Value::CellPath { .. } | Value::CustomValue { .. } => term - .r#in(span, &lower_value) + .r#in(span, &lower_value, span) .map_or(false, |value| value.is_true()), Value::Record { vals, .. } => vals.iter().any(|val| { if let Ok(span) = val.span() { @@ -320,10 +320,11 @@ fn find_with_rest( Span::test_data(), ); - term.r#in(span, &lower_val) + term.r#in(span, &lower_val, span) .map_or(false, |value| value.is_true()) } else { - term.r#in(span, val).map_or(false, |value| value.is_true()) + term.r#in(span, val, span) + .map_or(false, |value| value.is_true()) } }), Value::Binary { .. } => false, diff --git a/crates/nu-command/src/math/avg.rs b/crates/nu-command/src/math/avg.rs index f8d0c1118..c2a2187eb 100644 --- a/crates/nu-command/src/math/avg.rs +++ b/crates/nu-command/src/math/avg.rs @@ -67,6 +67,7 @@ pub fn average(values: &[Value], head: &Span) -> Result { val: values.len() as i64, span: *head, }, + *head, ), } } diff --git a/crates/nu-command/src/math/reducers.rs b/crates/nu-command/src/math/reducers.rs index 8f8eca2a7..5a8269868 100644 --- a/crates/nu-command/src/math/reducers.rs +++ b/crates/nu-command/src/math/reducers.rs @@ -98,7 +98,7 @@ pub fn sum(data: Vec, head: Span) -> Result { | Value::Float { .. } | Value::Filesize { .. } | Value::Duration { .. } => { - acc = acc.add(head, value)?; + acc = acc.add(head, value, head)?; } other => { return Err(ShellError::UnsupportedInput( @@ -129,7 +129,7 @@ pub fn product(data: Vec, head: Span) -> Result { for value in &data { match value { Value::Int { .. } | Value::Float { .. } => { - acc = acc.mul(head, value)?; + acc = acc.mul(head, value, head)?; } other => { return Err(ShellError::UnsupportedInput( diff --git a/crates/nu-command/src/math/variance.rs b/crates/nu-command/src/math/variance.rs index 50ca64c20..4ab0718fd 100644 --- a/crates/nu-command/src/math/variance.rs +++ b/crates/nu-command/src/math/variance.rs @@ -78,15 +78,15 @@ fn sum_of_squares(values: &[Value], span: &Span) -> Result { value.span().unwrap_or(*span), )) }?; - let v_squared = &v.mul(*span, v)?; - sum_x2 = sum_x2.add(*span, v_squared)?; - sum_x = sum_x.add(*span, v)?; + let v_squared = &v.mul(*span, v, *span)?; + sum_x2 = sum_x2.add(*span, v_squared, *span)?; + sum_x = sum_x.add(*span, v, *span)?; } - let sum_x_squared = sum_x.mul(*span, &sum_x)?; - let sum_x_squared_div_n = sum_x_squared.div(*span, &n)?; + let sum_x_squared = sum_x.mul(*span, &sum_x, *span)?; + let sum_x_squared_div_n = sum_x_squared.div(*span, &n, *span)?; - let ss = sum_x2.sub(*span, &sum_x_squared_div_n)?; + let ss = sum_x2.sub(*span, &sum_x_squared_div_n, *span)?; Ok(ss) } @@ -111,7 +111,7 @@ pub fn compute_variance(sample: bool) -> impl Fn(&[Value], &Span) -> Result Result { let decl = engine_state.get_decl(call.decl_id); - if !decl.is_known_external() && call.named_iter().any(|(flag, _)| flag.item == "help") { + if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") { let mut signature = decl.signature(); signature.usage = decl.usage().to_string(); signature.extra_usage = decl.extra_usage().to_string(); @@ -103,7 +103,7 @@ pub fn eval_call( let mut found = false; for call_named in call.named_iter() { if call_named.0.item == named.long { - if let Some(arg) = &call_named.1 { + if let Some(arg) = &call_named.2 { let result = eval_expression(engine_state, caller_stack, arg)?; callee_stack.add_var(var_id, result); @@ -211,6 +211,7 @@ fn eval_external( span: head.span, }, None, + None, )) } @@ -221,6 +222,7 @@ fn eval_external( span: head.span, }, None, + None, )) } @@ -343,7 +345,7 @@ pub fn eval_expression( }) } else { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.and(op_span, &rhs) + lhs.and(op_span, &rhs, expr.span) } } Operator::Or => { @@ -354,76 +356,76 @@ pub fn eval_expression( }) } else { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.or(op_span, &rhs) + lhs.or(op_span, &rhs, expr.span) } } Operator::Plus => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.add(op_span, &rhs) + lhs.add(op_span, &rhs, expr.span) } Operator::Minus => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.sub(op_span, &rhs) + lhs.sub(op_span, &rhs, expr.span) } Operator::Multiply => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.mul(op_span, &rhs) + lhs.mul(op_span, &rhs, expr.span) } Operator::Divide => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.div(op_span, &rhs) + lhs.div(op_span, &rhs, expr.span) } Operator::LessThan => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.lt(op_span, &rhs) + lhs.lt(op_span, &rhs, expr.span) } Operator::LessThanOrEqual => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.lte(op_span, &rhs) + lhs.lte(op_span, &rhs, expr.span) } Operator::GreaterThan => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.gt(op_span, &rhs) + lhs.gt(op_span, &rhs, expr.span) } Operator::GreaterThanOrEqual => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.gte(op_span, &rhs) + lhs.gte(op_span, &rhs, expr.span) } Operator::Equal => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.eq(op_span, &rhs) + lhs.eq(op_span, &rhs, expr.span) } Operator::NotEqual => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.ne(op_span, &rhs) + lhs.ne(op_span, &rhs, expr.span) } Operator::In => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.r#in(op_span, &rhs) + lhs.r#in(op_span, &rhs, expr.span) } Operator::NotIn => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.not_in(op_span, &rhs) + lhs.not_in(op_span, &rhs, expr.span) } Operator::RegexMatch => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.regex_match(op_span, &rhs, false) + lhs.regex_match(op_span, &rhs, false, expr.span) } Operator::NotRegexMatch => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.regex_match(op_span, &rhs, true) + lhs.regex_match(op_span, &rhs, true, expr.span) } Operator::Modulo => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.modulo(op_span, &rhs) + lhs.modulo(op_span, &rhs, expr.span) } Operator::Pow => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.pow(op_span, &rhs) + lhs.pow(op_span, &rhs, expr.span) } Operator::StartsWith => { let rhs = eval_expression(engine_state, stack, rhs)?; - lhs.starts_with(op_span, &rhs) + lhs.starts_with(op_span, &rhs, expr.span) } } } diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index 207f0e356..63184bf10 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -150,7 +150,7 @@ pub fn flatten_expression( } for named in call.named_iter() { args.push((named.0.span, FlatShape::Flag)); - if let Some(expr) = &named.1 { + if let Some(expr) = &named.2 { args.extend(flatten_expression(working_set, expr)); } } diff --git a/crates/nu-parser/src/known_external.rs b/crates/nu-parser/src/known_external.rs index d253449f9..876a965e4 100644 --- a/crates/nu-parser/src/known_external.rs +++ b/crates/nu-parser/src/known_external.rs @@ -51,8 +51,11 @@ impl Command for KnownExternal { let extern_name = working_state.get_span_contents(call.head); let extern_name = String::from_utf8(extern_name.to_vec()) .expect("this was already parsed as a command name"); + + let extern_name: Vec<_> = extern_name.split(' ').collect(); + let arg_extern_name = Expression { - expr: Expr::String(extern_name), + expr: Expr::String(extern_name[0].to_string()), span: call.head, ty: Type::String, custom_completion: None, @@ -60,10 +63,38 @@ impl Command for KnownExternal { extern_call.add_positional(arg_extern_name); + for subcommand in extern_name.into_iter().skip(1) { + extern_call.add_positional(Expression { + expr: Expr::String(subcommand.to_string()), + span: call.head, + ty: Type::String, + custom_completion: None, + }); + } + for arg in &call.arguments { match arg { Argument::Positional(positional) => extern_call.add_positional(positional.clone()), - Argument::Named(named) => extern_call.add_named(named.clone()), + Argument::Named(named) => { + if let Some(short) = &named.1 { + extern_call.add_positional(Expression { + expr: Expr::String(format!("-{}", short.item)), + span: named.0.span, + ty: Type::String, + custom_completion: None, + }); + } else { + extern_call.add_positional(Expression { + expr: Expr::String(format!("--{}", named.0.item)), + span: named.0.span, + ty: Type::String, + custom_completion: None, + }); + } + if let Some(arg) = &named.2 { + extern_call.add_positional(arg.clone()); + } + } } } @@ -74,6 +105,7 @@ impl Command for KnownExternal { span: call_span, }, None, + None, )) } @@ -84,6 +116,7 @@ impl Command for KnownExternal { span: call_span, }, None, + None, )) } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 97a44d4fe..785910c79 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -128,7 +128,7 @@ pub fn trim_quotes(bytes: &[u8]) -> &[u8] { pub fn check_call(command: Span, sig: &Signature, call: &Call) -> Option { // Allow the call to pass if they pass in the help flag - if call.named_iter().any(|(n, _)| n.item == "help") { + if call.named_iter().any(|(n, _, _)| n.item == "help") { return None; } @@ -189,7 +189,7 @@ pub fn check_call(command: Span, sig: &Signature, call: &Call) -> Option, ShellError>>()?; let mut named = Vec::with_capacity(call.named_len()); - for (string, expr) in call.named_iter() { + for (string, _, expr) in call.named_iter() { let value = match expr { None => None, Some(expr) => Some(eval_expression(engine_state, stack, expr)?), diff --git a/crates/nu-protocol/src/ast/call.rs b/crates/nu-protocol/src/ast/call.rs index b576101bd..5398207ff 100644 --- a/crates/nu-protocol/src/ast/call.rs +++ b/crates/nu-protocol/src/ast/call.rs @@ -6,7 +6,7 @@ use crate::{DeclId, Span, Spanned}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Argument { Positional(Expression), - Named((Spanned, Option)), + Named((Spanned, Option>, Option)), } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -30,7 +30,9 @@ impl Call { } } - pub fn named_iter(&self) -> impl Iterator, Option)> { + pub fn named_iter( + &self, + ) -> impl Iterator, Option>, Option)> { self.arguments.iter().filter_map(|arg| match arg { Argument::Named(named) => Some(named), Argument::Positional(_) => None, @@ -39,7 +41,8 @@ impl Call { pub fn named_iter_mut( &mut self, - ) -> impl Iterator, Option)> { + ) -> impl Iterator, Option>, Option)> + { self.arguments.iter_mut().filter_map(|arg| match arg { Argument::Named(named) => Some(named), Argument::Positional(_) => None, @@ -50,7 +53,10 @@ impl Call { self.named_iter().count() } - pub fn add_named(&mut self, named: (Spanned, Option)) { + pub fn add_named( + &mut self, + named: (Spanned, Option>, Option), + ) { self.arguments.push(Argument::Named(named)); } @@ -93,7 +99,7 @@ impl Call { pub fn get_flag_expr(&self, flag_name: &str) -> Option { for name in self.named_iter() { if flag_name == name.0.item { - return name.1.clone(); + return name.2.clone(); } } @@ -119,7 +125,7 @@ impl Call { } } - for (named, val) in self.named_iter() { + for (named, _, val) in self.named_iter() { if named.span.end > span.end { span.end = named.span.end; } diff --git a/crates/nu-protocol/src/ast/expression.rs b/crates/nu-protocol/src/ast/expression.rs index 3b243419a..f29fac827 100644 --- a/crates/nu-protocol/src/ast/expression.rs +++ b/crates/nu-protocol/src/ast/expression.rs @@ -139,7 +139,7 @@ impl Expression { } } for named in call.named_iter() { - if let Some(expr) = &named.1 { + if let Some(expr) = &named.2 { if expr.has_in_variable(working_set) { return true; } @@ -306,7 +306,7 @@ impl Expression { positional.replace_in_variable(working_set, new_var_id); } for named in call.named_iter_mut() { - if let Some(expr) = &mut named.1 { + if let Some(expr) = &mut named.2 { expr.replace_in_variable(working_set, new_var_id) } } @@ -453,7 +453,7 @@ impl Expression { positional.replace_span(working_set, replaced, new_span); } for named in call.named_iter_mut() { - if let Some(expr) = &mut named.1 { + if let Some(expr) = &mut named.2 { expr.replace_span(working_set, replaced, new_span) } } diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index c97fa12af..8b7b3069b 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -23,7 +23,7 @@ use std::path::PathBuf; use std::{cmp::Ordering, fmt::Debug}; use crate::ast::{CellPath, PathMember}; -use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type, VarId}; +use crate::{did_you_mean, BlockId, Config, Span, Spanned, Type, VarId}; use crate::ast::Operator; pub use custom_value::CustomValue; @@ -1413,9 +1413,7 @@ impl PartialEq for Value { } impl Value { - pub fn add(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn add(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { if let Some(val) = lhs.checked_add(*rhs) { @@ -1486,9 +1484,7 @@ impl Value { }), } } - pub fn sub(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn sub(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { if let Some(val) = lhs.checked_sub(*rhs) { @@ -1566,9 +1562,7 @@ impl Value { }), } } - pub fn mul(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn mul(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { if let Some(val) = lhs.checked_mul(*rhs) { @@ -1629,9 +1623,7 @@ impl Value { }), } } - pub fn div(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn div(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { if *rhs != 0 { @@ -1747,9 +1739,7 @@ impl Value { }), } } - pub fn lt(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn lt(&self, op: Span, rhs: &Value, span: Span) -> Result { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { return lhs.operation(*span, Operator::LessThan, op, rhs); } @@ -1775,9 +1765,7 @@ impl Value { }), } } - pub fn lte(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn lte(&self, op: Span, rhs: &Value, span: Span) -> Result { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { return lhs.operation(*span, Operator::LessThanOrEqual, op, rhs); } @@ -1803,9 +1791,7 @@ impl Value { }), } } - pub fn gt(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn gt(&self, op: Span, rhs: &Value, span: Span) -> Result { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { return lhs.operation(*span, Operator::GreaterThan, op, rhs); } @@ -1831,9 +1817,7 @@ impl Value { }), } } - pub fn gte(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn gte(&self, op: Span, rhs: &Value, span: Span) -> Result { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { return lhs.operation(*span, Operator::GreaterThanOrEqual, op, rhs); } @@ -1859,9 +1843,7 @@ impl Value { }), } } - pub fn eq(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn eq(&self, op: Span, rhs: &Value, span: Span) -> Result { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { return lhs.operation(*span, Operator::Equal, op, rhs); } @@ -1885,9 +1867,7 @@ impl Value { }, } } - pub fn ne(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn ne(&self, op: Span, rhs: &Value, span: Span) -> Result { if let (Value::CustomValue { val: lhs, span }, rhs) = (self, rhs) { return lhs.operation(*span, Operator::NotEqual, op, rhs); } @@ -1912,9 +1892,7 @@ impl Value { } } - pub fn r#in(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn r#in(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool { val: rhs.contains(lhs), @@ -1971,9 +1949,7 @@ impl Value { } } - pub fn not_in(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn not_in(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool { val: !rhs.contains(lhs), @@ -2030,9 +2006,13 @@ impl Value { } } - pub fn regex_match(&self, op: Span, rhs: &Value, invert: bool) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn regex_match( + &self, + op: Span, + rhs: &Value, + invert: bool, + span: Span, + ) -> Result { match (self, rhs) { ( Value::String { val: lhs, .. }, @@ -2072,9 +2052,7 @@ impl Value { } } - pub fn starts_with(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn starts_with(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool { val: lhs.starts_with(rhs), @@ -2093,9 +2071,7 @@ impl Value { } } - pub fn modulo(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn modulo(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { if *rhs != 0 { @@ -2151,9 +2127,7 @@ impl Value { } } - pub fn and(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn and(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Bool { val: lhs, .. }, Value::Bool { val: rhs, .. }) => Ok(Value::Bool { val: *lhs && *rhs, @@ -2172,9 +2146,7 @@ impl Value { } } - pub fn or(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn or(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Bool { val: lhs, .. }, Value::Bool { val: rhs, .. }) => Ok(Value::Bool { val: *lhs || *rhs, @@ -2193,9 +2165,7 @@ impl Value { } } - pub fn pow(&self, op: Span, rhs: &Value) -> Result { - let span = span(&[self.span()?, rhs.span()?]); - + pub fn pow(&self, op: Span, rhs: &Value, span: Span) -> Result { match (self, rhs) { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { if let Some(val) = lhs.checked_pow(*rhs as u32) { diff --git a/crates/nu-protocol/src/value/range.rs b/crates/nu-protocol/src/value/range.rs index 5e90303be..7e7033efe 100644 --- a/crates/nu-protocol/src/value/range.rs +++ b/crates/nu-protocol/src/value/range.rs @@ -38,7 +38,7 @@ impl Range { }; let to = if let Value::Nothing { .. } = to { - if let Ok(Value::Bool { val: true, .. }) = next.lt(expr_span, &from) { + if let Ok(Value::Bool { val: true, .. }) = next.lt(expr_span, &from, expr_span) { Value::Int { val: i64::MIN, span: expr_span, @@ -54,7 +54,10 @@ impl Range { }; // Check if the range counts up or down - let moves_up = matches!(from.lte(expr_span, &to), Ok(Value::Bool { val: true, .. })); + let moves_up = matches!( + from.lte(expr_span, &to, expr_span), + Ok(Value::Bool { val: true, .. }) + ); // Convert the next value into the inctement let incr = if let Value::Nothing { .. } = next { @@ -70,7 +73,7 @@ impl Range { } } } else { - next.sub(operator.next_op_span, &from)? + next.sub(operator.next_op_span, &from, expr_span)? }; let zero = Value::Int { @@ -79,22 +82,25 @@ impl Range { }; // Increment must be non-zero, otherwise we iterate forever - if matches!(incr.eq(expr_span, &zero), Ok(Value::Bool { val: true, .. })) { + if matches!( + incr.eq(expr_span, &zero, expr_span), + Ok(Value::Bool { val: true, .. }) + ) { return Err(ShellError::CannotCreateRange(expr_span)); } // If to > from, then incr > 0, otherwise we iterate forever if let (Value::Bool { val: true, .. }, Value::Bool { val: false, .. }) = ( - to.gt(operator.span, &from)?, - incr.gt(operator.next_op_span, &zero)?, + to.gt(operator.span, &from, expr_span)?, + incr.gt(operator.next_op_span, &zero, expr_span)?, ) { return Err(ShellError::CannotCreateRange(expr_span)); } // If to < from, then incr < 0, otherwise we iterate forever if let (Value::Bool { val: true, .. }, Value::Bool { val: false, .. }) = ( - to.lt(operator.span, &from)?, - incr.lt(operator.next_op_span, &zero)?, + to.lt(operator.span, &from, expr_span)?, + incr.lt(operator.next_op_span, &zero, expr_span)?, ) { return Err(ShellError::CannotCreateRange(expr_span)); } @@ -231,7 +237,7 @@ impl Iterator for RangeIterator { if (ordering == desired_ordering) || (self.is_end_inclusive && ordering == Ordering::Equal) { - let next_value = self.curr.add(self.span, &self.incr); + let next_value = self.curr.add(self.span, &self.incr, self.span); let mut next = match next_value { Ok(result) => result, diff --git a/crates/nu-protocol/tests/test_value.rs b/crates/nu-protocol/tests/test_value.rs index 65cbc3e33..452beae87 100644 --- a/crates/nu-protocol/tests/test_value.rs +++ b/crates/nu-protocol/tests/test_value.rs @@ -23,22 +23,22 @@ fn test_comparison_nothing() { for value in values { assert!(matches!( - value.eq(Span::test_data(), ¬hing), + value.eq(Span::test_data(), ¬hing, Span::test_data()), Ok(Value::Bool { val: false, .. }) )); assert!(matches!( - value.ne(Span::test_data(), ¬hing), + value.ne(Span::test_data(), ¬hing, Span::test_data()), Ok(Value::Bool { val: true, .. }) )); assert!(matches!( - nothing.eq(Span::test_data(), &value), + nothing.eq(Span::test_data(), &value, Span::test_data()), Ok(Value::Bool { val: false, .. }) )); assert!(matches!( - nothing.ne(Span::test_data(), &value), + nothing.ne(Span::test_data(), &value, Span::test_data()), Ok(Value::Bool { val: true, .. }) )); } diff --git a/src/tests/test_engine.rs b/src/tests/test_engine.rs index efaf9d797..db313f9a4 100644 --- a/src/tests/test_engine.rs +++ b/src/tests/test_engine.rs @@ -366,3 +366,11 @@ fn reuseable_in() -> TestResult { "6", ) } + +#[test] +fn better_operator_spans() -> TestResult { + run_test( + r#"metadata ({foo: 10} | (20 - $in.foo)) | get span | $in.start < $in.end"#, + "true", + ) +}