Merge pull request #125 from nushell/earlier_errors

Earlier errors
This commit is contained in:
JT 2021-10-12 08:38:29 +13:00 committed by GitHub
commit 6e92812cdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 175 additions and 140 deletions

View File

@ -61,7 +61,7 @@ impl Command for If {
Ok(Value::Nothing { span }) Ok(Value::Nothing { span })
} }
} }
_ => Err(ShellError::CantConvert("bool".into(), result.span())), _ => Err(ShellError::CantConvert("bool".into(), result.span()?)),
} }
} }
} }

View File

@ -67,7 +67,7 @@ impl Command for Each {
match input { match input {
Value::Range { val, .. } => Ok(Value::Stream { Value::Range { val, .. } => Ok(Value::Stream {
stream: val stream: val
.into_iter() .into_range_iter()?
.enumerate() .enumerate()
.map(move |(idx, x)| { .map(move |(idx, x)| {
let engine_state = context.engine_state.borrow(); let engine_state = context.engine_state.borrow();

View File

@ -71,7 +71,7 @@ impl Command for FromJson {
call: &Call, call: &Call,
input: Value, input: Value,
) -> Result<nu_protocol::Value, ShellError> { ) -> Result<nu_protocol::Value, ShellError> {
let span = input.span(); let span = input.span()?;
let mut string_input = input.collect_string(); let mut string_input = input.collect_string();
string_input.push('\n'); string_input.push('\n');

View File

@ -68,8 +68,9 @@ fn split_chars(call: &Call, input: Value) -> Result<nu_protocol::Value, nu_proto
} }
fn split_chars_helper(v: &Value, name: Span) -> Vec<Value> { fn split_chars_helper(v: &Value, name: Span) -> Vec<Value> {
match v.span() {
Ok(v_span) => {
if let Ok(s) = v.as_string() { if let Ok(s) = v.as_string() {
let v_span = v.span();
s.chars() s.chars()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
@ -83,10 +84,13 @@ fn split_chars_helper(v: &Value, name: Span) -> Vec<Value> {
error: ShellError::PipelineMismatch { error: ShellError::PipelineMismatch {
expected: Type::String, expected: Type::String,
expected_span: name, expected_span: name,
origin: v.span(), origin: v_span,
}, },
}] }]
} }
}
Err(error) => vec![Value::Error { error }],
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -109,12 +109,15 @@ fn split_column_helper(
span: head, span: head,
} }
} else { } else {
Value::Error { match v.span() {
Ok(span) => Value::Error {
error: ShellError::PipelineMismatch { error: ShellError::PipelineMismatch {
expected: Type::String, expected: Type::String,
expected_span: head, expected_span: head,
origin: v.span(), origin: span,
}, },
},
Err(error) => Value::Error { error },
} }
} }
} }

View File

@ -48,6 +48,8 @@ fn split_row(
} }
fn split_row_helper(v: &Value, separator: &Spanned<String>, name: Span) -> Vec<Value> { fn split_row_helper(v: &Value, separator: &Spanned<String>, name: Span) -> Vec<Value> {
match v.span() {
Ok(v_span) => {
if let Ok(s) = v.as_string() { if let Ok(s) = v.as_string() {
let splitter = separator.item.replace("\\n", "\n"); let splitter = separator.item.replace("\\n", "\n");
s.split(&splitter) s.split(&splitter)
@ -55,7 +57,7 @@ fn split_row_helper(v: &Value, separator: &Spanned<String>, name: Span) -> Vec<V
if s.trim() != "" { if s.trim() != "" {
Some(Value::String { Some(Value::String {
val: s.into(), val: s.into(),
span: v.span(), span: v_span,
}) })
} else { } else {
None None
@ -67,10 +69,13 @@ fn split_row_helper(v: &Value, separator: &Spanned<String>, name: Span) -> Vec<V
error: ShellError::PipelineMismatch { error: ShellError::PipelineMismatch {
expected: Type::String, expected: Type::String,
expected_span: name, expected_span: name,
origin: v.span(), origin: v_span,
}, },
}] }]
} }
}
Err(error) => vec![Value::Error { error }],
}
} }
// #[cfg(test)] // #[cfg(test)]

View File

@ -45,7 +45,7 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result<V
} }
let span = if let Some(rest_item) = rest_items.first() { let span = if let Some(rest_item) = rest_items.first() {
rest_item.span() rest_item.span()?
} else { } else {
Span::unknown() Span::unknown()
}; };

View File

@ -33,7 +33,7 @@ impl FromValue for Spanned<i64> {
span: *span, span: *span,
}), }),
v => Err(ShellError::CantConvert("integer".into(), v.span())), v => Err(ShellError::CantConvert("integer".into(), v.span()?)),
} }
} }
} }
@ -51,7 +51,7 @@ impl FromValue for i64 {
*val as i64, *val as i64,
), ),
v => Err(ShellError::CantConvert("integer".into(), v.span())), v => Err(ShellError::CantConvert("integer".into(), v.span()?)),
} }
} }
} }
@ -69,7 +69,7 @@ impl FromValue for Spanned<f64> {
span: *span, span: *span,
}), }),
v => Err(ShellError::CantConvert("float".into(), v.span())), v => Err(ShellError::CantConvert("float".into(), v.span()?)),
} }
} }
} }
@ -79,7 +79,7 @@ impl FromValue for f64 {
match v { match v {
Value::Float { val, .. } => Ok(*val), Value::Float { val, .. } => Ok(*val),
Value::Int { val, .. } => Ok(*val as f64), Value::Int { val, .. } => Ok(*val as f64),
v => Err(ShellError::CantConvert("float".into(), v.span())), v => Err(ShellError::CantConvert("float".into(), v.span()?)),
} }
} }
} }
@ -95,7 +95,7 @@ impl FromValue for Spanned<String> {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
Ok(Spanned { Ok(Spanned {
item: v.clone().into_string(), item: v.clone().into_string(),
span: v.span(), span: v.span()?,
}) })
} }
} }
@ -115,7 +115,7 @@ impl FromValue for ColumnPath {
impl FromValue for CellPath { impl FromValue for CellPath {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
let span = v.span(); let span = v.span()?;
match v { match v {
Value::CellPath { val, .. } => Ok(val.clone()), Value::CellPath { val, .. } => Ok(val.clone()),
Value::String { val, .. } => Ok(CellPath { Value::String { val, .. } => Ok(CellPath {
@ -130,7 +130,7 @@ impl FromValue for CellPath {
span, span,
}], }],
}), }),
v => Err(ShellError::CantConvert("cell path".into(), v.span())), _ => Err(ShellError::CantConvert("cell path".into(), span)),
} }
} }
} }
@ -139,7 +139,7 @@ impl FromValue for bool {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
match v { match v {
Value::Bool { val, .. } => Ok(*val), Value::Bool { val, .. } => Ok(*val),
v => Err(ShellError::CantConvert("bool".into(), v.span())), v => Err(ShellError::CantConvert("bool".into(), v.span()?)),
} }
} }
} }
@ -151,7 +151,7 @@ impl FromValue for Spanned<bool> {
item: *val, item: *val,
span: *span, span: *span,
}), }),
v => Err(ShellError::CantConvert("bool".into(), v.span())), v => Err(ShellError::CantConvert("bool".into(), v.span()?)),
} }
} }
} }
@ -182,7 +182,7 @@ impl FromValue for Range {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
match v { match v {
Value::Range { val, .. } => Ok((**val).clone()), Value::Range { val, .. } => Ok((**val).clone()),
v => Err(ShellError::CantConvert("range".into(), v.span())), v => Err(ShellError::CantConvert("range".into(), v.span()?)),
} }
} }
} }
@ -194,7 +194,7 @@ impl FromValue for Spanned<Range> {
item: (**val).clone(), item: (**val).clone(),
span: *span, span: *span,
}), }),
v => Err(ShellError::CantConvert("range".into(), v.span())), v => Err(ShellError::CantConvert("range".into(), v.span()?)),
} }
} }
} }

View File

@ -90,29 +90,29 @@ impl Value {
pub fn as_string(&self) -> Result<String, ShellError> { pub fn as_string(&self) -> Result<String, ShellError> {
match self { match self {
Value::String { val, .. } => Ok(val.to_string()), Value::String { val, .. } => Ok(val.to_string()),
_ => Err(ShellError::CantConvert("string".into(), self.span())), _ => Err(ShellError::CantConvert("string".into(), self.span()?)),
} }
} }
/// Get the span for the current value /// Get the span for the current value
pub fn span(&self) -> Span { pub fn span(&self) -> Result<Span, ShellError> {
match self { match self {
Value::Error { .. } => Span::unknown(), Value::Error { error } => Err(error.clone()),
Value::Bool { span, .. } => *span, Value::Bool { span, .. } => Ok(*span),
Value::Int { span, .. } => *span, Value::Int { span, .. } => Ok(*span),
Value::Float { span, .. } => *span, Value::Float { span, .. } => Ok(*span),
Value::Filesize { span, .. } => *span, Value::Filesize { span, .. } => Ok(*span),
Value::Duration { span, .. } => *span, Value::Duration { span, .. } => Ok(*span),
Value::Date { span, .. } => *span, Value::Date { span, .. } => Ok(*span),
Value::Range { span, .. } => *span, Value::Range { span, .. } => Ok(*span),
Value::String { span, .. } => *span, Value::String { span, .. } => Ok(*span),
Value::Record { span, .. } => *span, Value::Record { span, .. } => Ok(*span),
Value::List { span, .. } => *span, Value::List { span, .. } => Ok(*span),
Value::Block { span, .. } => *span, Value::Block { span, .. } => Ok(*span),
Value::Stream { span, .. } => *span, Value::Stream { span, .. } => Ok(*span),
Value::Nothing { span, .. } => *span, Value::Nothing { span, .. } => Ok(*span),
Value::Binary { span, .. } => *span, Value::Binary { span, .. } => Ok(*span),
Value::CellPath { span, .. } => *span, Value::CellPath { span, .. } => Ok(*span),
} }
} }
@ -173,15 +173,17 @@ impl Value {
Value::Filesize { val, .. } => format_filesize(val), Value::Filesize { val, .. } => format_filesize(val),
Value::Duration { val, .. } => format_duration(val), Value::Duration { val, .. } => format_duration(val),
Value::Date { val, .. } => HumanTime::from(val).to_string(), Value::Date { val, .. } => HumanTime::from(val).to_string(),
Value::Range { val, .. } => { Value::Range { val, .. } => match val.into_range_iter() {
Ok(iter) => {
format!( format!(
"range: [{}]", "range: [{}]",
val.into_iter() iter.map(|x| x.into_string())
.map(|x| x.into_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", ") .join(", ")
) )
} }
Err(error) => format!("{:?}", error),
},
Value::String { val, .. } => val, Value::String { val, .. } => val,
Value::Stream { stream, .. } => stream.into_string(), Value::Stream { stream, .. } => stream.into_string(),
Value::List { vals: val, .. } => format!( Value::List { vals: val, .. } => format!(
@ -215,11 +217,15 @@ impl Value {
Value::Filesize { val, .. } => format!("{} bytes", val), Value::Filesize { val, .. } => format!("{} bytes", val),
Value::Duration { val, .. } => format!("{} ns", val), Value::Duration { val, .. } => format!("{} ns", val),
Value::Date { val, .. } => format!("{:?}", val), Value::Date { val, .. } => format!("{:?}", val),
Value::Range { val, .. } => val Value::Range { val, .. } => match val.into_range_iter() {
.into_iter() Ok(iter) => iter
.map(|x| x.into_string()) .map(|x| x.into_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(", "), .join(", "),
Err(error) => {
format!("{:?}", error)
}
},
Value::String { val, .. } => val, Value::String { val, .. } => val,
Value::Stream { stream, .. } => stream.collect_string(), Value::Stream { stream, .. } => stream.collect_string(),
Value::List { vals: val, .. } => val Value::List { vals: val, .. } => val
@ -380,7 +386,7 @@ impl Value {
span, span,
}), }),
Value::Range { val, .. } => Ok(Value::Stream { Value::Range { val, .. } => Ok(Value::Stream {
stream: val.into_iter().map(f).into_value_stream(), stream: val.into_range_iter()?.map(f).into_value_stream(),
span, span,
}), }),
v => { v => {
@ -409,10 +415,13 @@ impl Value {
stream: stream.map(f).flatten().into_value_stream(), stream: stream.map(f).flatten().into_value_stream(),
span, span,
}, },
Value::Range { val, .. } => Value::Stream { Value::Range { val, .. } => match val.into_range_iter() {
stream: val.into_iter().map(f).flatten().into_value_stream(), Ok(iter) => Value::Stream {
stream: iter.map(f).flatten().into_value_stream(),
span, span,
}, },
Err(error) => Value::Error { error },
},
v => Value::Stream { v => Value::Stream {
stream: f(v).into_iter().into_value_stream(), stream: f(v).into_iter().into_value_stream(),
span, span,
@ -506,7 +515,7 @@ impl PartialEq for Value {
impl Value { impl Value {
pub fn add(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn add(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
@ -545,14 +554,14 @@ impl Value {
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn sub(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn sub(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
@ -587,14 +596,14 @@ impl Value {
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn mul(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn mul(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
@ -617,14 +626,14 @@ impl Value {
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn div(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn div(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
@ -678,14 +687,14 @@ impl Value {
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn lt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn lt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match self.partial_cmp(rhs) { match self.partial_cmp(rhs) {
Some(ordering) => Ok(Value::Bool { Some(ordering) => Ok(Value::Bool {
@ -695,14 +704,14 @@ impl Value {
None => Err(ShellError::OperatorMismatch { None => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn lte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn lte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match self.partial_cmp(rhs) { match self.partial_cmp(rhs) {
Some(ordering) => Ok(Value::Bool { Some(ordering) => Ok(Value::Bool {
@ -712,14 +721,14 @@ impl Value {
None => Err(ShellError::OperatorMismatch { None => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn gt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn gt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match self.partial_cmp(rhs) { match self.partial_cmp(rhs) {
Some(ordering) => Ok(Value::Bool { Some(ordering) => Ok(Value::Bool {
@ -729,14 +738,14 @@ impl Value {
None => Err(ShellError::OperatorMismatch { None => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn gte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn gte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match self.partial_cmp(rhs) { match self.partial_cmp(rhs) {
Some(ordering) => Ok(Value::Bool { Some(ordering) => Ok(Value::Bool {
@ -746,14 +755,14 @@ impl Value {
None => Err(ShellError::OperatorMismatch { None => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn eq(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn eq(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match self.partial_cmp(rhs) { match self.partial_cmp(rhs) {
Some(ordering) => Ok(Value::Bool { Some(ordering) => Ok(Value::Bool {
@ -763,14 +772,14 @@ impl Value {
None => Err(ShellError::OperatorMismatch { None => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn ne(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn ne(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match self.partial_cmp(rhs) { match self.partial_cmp(rhs) {
Some(ordering) => Ok(Value::Bool { Some(ordering) => Ok(Value::Bool {
@ -780,15 +789,15 @@ impl Value {
None => Err(ShellError::OperatorMismatch { None => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn r#in(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn r#in(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool { (lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool {
@ -814,15 +823,15 @@ impl Value {
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }
pub fn not_in(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> { pub fn not_in(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
let span = span(&[self.span(), rhs.span()]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool { (lhs, Value::Range { val: rhs, .. }) => Ok(Value::Bool {
@ -848,9 +857,9 @@ impl Value {
_ => Err(ShellError::OperatorMismatch { _ => Err(ShellError::OperatorMismatch {
op_span: op, op_span: op,
lhs_ty: self.get_type(), lhs_ty: self.get_type(),
lhs_span: self.span(), lhs_span: self.span()?,
rhs_ty: rhs.get_type(), rhs_ty: rhs.get_type(),
rhs_span: rhs.span(), rhs_span: rhs.span()?,
}), }),
} }
} }

View File

@ -122,20 +122,26 @@ impl Range {
(_, _) => false, (_, _) => false,
} }
} }
}
impl IntoIterator for Range { pub fn into_range_iter(self) -> Result<RangeIterator, ShellError> {
type Item = Value; let span = self.from.span()?;
type IntoIter = RangeIterator; Ok(RangeIterator::new(self, span))
fn into_iter(self) -> Self::IntoIter {
let span = self.from.span();
RangeIterator::new(self, span)
} }
} }
// impl IntoIterator for Range {
// type Item = Value;
// type IntoIter = RangeIterator;
// fn into_iter(self) -> Self::IntoIter {
// let span = self.from.span();
// RangeIterator::new(self, span)
// }
// }
pub struct RangeIterator { pub struct RangeIterator {
curr: Value, curr: Value,
end: Value, end: Value,

View File

@ -658,3 +658,11 @@ fn string_not_in_string() -> TestResult {
fn float_not_in_inc_range() -> TestResult { fn float_not_in_inc_range() -> TestResult {
run_test(r#"1.4 not-in 2..9.42"#, "true") run_test(r#"1.4 not-in 2..9.42"#, "true")
} }
#[test]
fn earlier_errors() -> TestResult {
fail_test(
r#"[1, "bob"] | each { $it + 3 } | each { $it / $it } | table"#,
"int",
)
}