diff --git a/crates/nu-command/src/each.rs b/crates/nu-command/src/each.rs index 2ec432f0a..f2964b379 100644 --- a/crates/nu-command/src/each.rs +++ b/crates/nu-command/src/each.rs @@ -42,6 +42,22 @@ impl Command for Each { match input { Value::List { val, .. } => Ok(Value::List { val: val + .into_iter() + .map(move |x| { + let engine_state = context.engine_state.borrow(); + let block = engine_state.get_block(block); + + let state = context.enter_scope(); + state.add_var(var_id, x.clone()); + + //FIXME: DON'T UNWRAP + eval_block(&state, block, Value::nothing()).unwrap() + }) + .collect(), + span: call.head, + }), + Value::ValueStream { stream, .. } => Ok(Value::ValueStream { + stream: stream .map(move |x| { let engine_state = context.engine_state.borrow(); let block = engine_state.get_block(block); diff --git a/crates/nu-command/src/for_.rs b/crates/nu-command/src/for_.rs index c72d5b214..792a65601 100644 --- a/crates/nu-command/src/for_.rs +++ b/crates/nu-command/src/for_.rs @@ -53,8 +53,8 @@ impl Command for For { let context = context.clone(); match values { - Value::List { val, .. } => Ok(Value::List { - val: val + Value::ValueStream { stream, .. } => Ok(Value::ValueStream { + stream: stream .map(move |x| { let engine_state = context.engine_state.borrow(); let block = engine_state.get_block(block); @@ -68,6 +68,22 @@ impl Command for For { .into_value_stream(), span: call.head, }), + Value::List { val, .. } => Ok(Value::List { + val: val + .into_iter() + .map(move |x| { + let engine_state = context.engine_state.borrow(); + let block = engine_state.get_block(block); + + let state = context.enter_scope(); + state.add_var(var_id, x.clone()); + + //FIXME: DON'T UNWRAP + eval_block(&state, block, Value::nothing()).unwrap() + }) + .collect(), + span: call.head, + }), _ => Ok(Value::nothing()), } } diff --git a/crates/nu-command/src/length.rs b/crates/nu-command/src/length.rs index 270694894..00247287c 100644 --- a/crates/nu-command/src/length.rs +++ b/crates/nu-command/src/length.rs @@ -25,7 +25,7 @@ impl Command for Length { ) -> Result { match input { Value::List { val, .. } => { - let length = val.count(); + let length = val.len(); Ok(Value::Int { val: length as i64, @@ -33,7 +33,23 @@ impl Command for Length { }) } Value::Table { val, .. } => { - let length = val.count(); + let length = val.len(); + + Ok(Value::Int { + val: length as i64, + span: call.head, + }) + } + Value::ValueStream { stream, .. } => { + let length = stream.count(); + + Ok(Value::Int { + val: length as i64, + span: call.head, + }) + } + Value::RowStream { stream, .. } => { + let length = stream.count(); Ok(Value::Int { val: length as i64, diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 0ec959c6a..733fd6380 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; use nu_protocol::engine::EvaluationContext; -use nu_protocol::{IntoRowStream, IntoValueStream, ShellError, Value}; +use nu_protocol::{ShellError, Value}; pub fn eval_operator(op: &Expression) -> Result { match op { @@ -99,7 +99,7 @@ pub fn eval_expression( output.push(eval_expression(context, expr)?); } Ok(Value::List { - val: output.into_iter().into_value_stream(), + val: output, span: expr.span, }) } @@ -119,7 +119,7 @@ pub fn eval_expression( } Ok(Value::Table { headers: output_headers, - val: output_rows.into_row_stream(), + val: output_rows, span: expr.span, }) } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 9529bb141..8b9aefe65 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1688,7 +1688,14 @@ pub fn parse_value( } else if bytes.starts_with(b"(") { return parse_full_column_path(working_set, span); } else if bytes.starts_with(b"{") { - return parse_block_expression(working_set, span); + if matches!(shape, SyntaxShape::Block) || matches!(shape, SyntaxShape::Any) { + return parse_block_expression(working_set, span); + } else { + return ( + Expression::garbage(span), + Some(ParseError::Expected("non-block value".into(), span)), + ); + } } else if bytes.starts_with(b"[") { match shape { SyntaxShape::Any diff --git a/crates/nu-protocol/src/ty.rs b/crates/nu-protocol/src/ty.rs index 80cbc3b5e..ba2fe8d2e 100644 --- a/crates/nu-protocol/src/ty.rs +++ b/crates/nu-protocol/src/ty.rs @@ -15,6 +15,8 @@ pub enum Type { Number, Nothing, Table, + RowStream, + ValueStream, Unknown, } @@ -34,6 +36,8 @@ impl Display for Type { Type::Number => write!(f, "number"), Type::String => write!(f, "string"), Type::Table => write!(f, "table"), + Type::ValueStream => write!(f, "value stream"), + Type::RowStream => write!(f, "row stream"), Type::Unknown => write!(f, "unknown"), } } diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index 640fbe7d4..c88bc4be6 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -125,13 +125,22 @@ pub enum Value { val: String, span: Span, }, + ValueStream { + stream: ValueStream, + span: Span, + }, + RowStream { + headers: Vec, + stream: RowStream, + span: Span, + }, List { - val: ValueStream, + val: Vec, span: Span, }, Table { headers: Vec, - val: RowStream, + val: Vec>, span: Span, }, Block { @@ -160,6 +169,8 @@ impl Value { Value::List { span, .. } => *span, Value::Table { span, .. } => *span, Value::Block { span, .. } => *span, + Value::RowStream { span, .. } => *span, + Value::ValueStream { span, .. } => *span, Value::Nothing { span, .. } => *span, } } @@ -170,6 +181,8 @@ impl Value { Value::Int { span, .. } => *span = new_span, Value::Float { span, .. } => *span = new_span, Value::String { span, .. } => *span = new_span, + Value::RowStream { span, .. } => *span = new_span, + Value::ValueStream { span, .. } => *span = new_span, Value::List { span, .. } => *span = new_span, Value::Table { span, .. } => *span = new_span, Value::Block { span, .. } => *span = new_span, @@ -189,6 +202,8 @@ impl Value { Value::Table { .. } => Type::Table, // FIXME Value::Nothing { .. } => Type::Nothing, Value::Block { .. } => Type::Block, + Value::ValueStream { .. } => Type::ValueStream, + Value::RowStream { .. } => Type::RowStream, } } @@ -198,8 +213,25 @@ impl Value { Value::Int { val, .. } => val.to_string(), Value::Float { val, .. } => val.to_string(), Value::String { val, .. } => val, - Value::List { val, .. } => val.into_string(), - Value::Table { headers, val, .. } => val.into_string(headers), + Value::ValueStream { stream, .. } => stream.into_string(), + Value::List { val, .. } => val + .into_iter() + .map(|x| x.into_string()) + .collect::>() + .join(", "), + Value::Table { val, .. } => val + .into_iter() + .map(|x| { + x.into_iter() + .map(|x| x.into_string()) + .collect::>() + .join(", ") + }) + .collect::>() + .join("\n"), + Value::RowStream { + headers, stream, .. + } => stream.into_string(headers), Value::Block { val, .. } => format!("", val), Value::Nothing { .. } => String::new(), } @@ -517,6 +549,25 @@ impl Value { val: lhs == rhs, span, }), + (Value::List { val: lhs, .. }, Value::List { val: rhs, .. }) => Ok(Value::Bool { + val: lhs == rhs, + span, + }), + ( + Value::Table { + val: lhs, + headers: lhs_headers, + .. + }, + Value::Table { + val: rhs, + headers: rhs_headers, + .. + }, + ) => Ok(Value::Bool { + val: lhs_headers == rhs_headers && lhs == rhs, + span, + }), _ => Err(ShellError::OperatorMismatch { op_span: op, lhs_ty: self.get_type(), @@ -553,6 +604,26 @@ impl Value { val: lhs != rhs, span, }), + (Value::List { val: lhs, .. }, Value::List { val: rhs, .. }) => Ok(Value::Bool { + val: lhs != rhs, + span, + }), + ( + Value::Table { + val: lhs, + headers: lhs_headers, + .. + }, + Value::Table { + val: rhs, + headers: rhs_headers, + .. + }, + ) => Ok(Value::Bool { + val: lhs_headers != rhs_headers || lhs != rhs, + span, + }), + _ => Err(ShellError::OperatorMismatch { op_span: op, lhs_ty: self.get_type(),