diff --git a/crates/nu-command/src/for_.rs b/crates/nu-command/src/for_.rs index 3cede35e8..b240d30ca 100644 --- a/crates/nu-command/src/for_.rs +++ b/crates/nu-command/src/for_.rs @@ -1,7 +1,7 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, Span, SyntaxShape, Value}; +use nu_protocol::{IntoValueStream, Signature, Span, SyntaxShape, Value}; pub struct For; @@ -23,7 +23,10 @@ impl Command for For { ) .required( "range", - SyntaxShape::Keyword(b"in".to_vec(), Box::new(SyntaxShape::Int)), + SyntaxShape::Keyword( + b"in".to_vec(), + Box::new(SyntaxShape::List(Box::new(SyntaxShape::Int))), + ), "range of the loop", ) .required("block", SyntaxShape::Block, "the block to run") @@ -42,34 +45,30 @@ impl Command for For { let keyword_expr = call.positional[1] .as_keyword() .expect("internal error: missing keyword"); - let end_val = eval_expression(context, keyword_expr)?; + let values = eval_expression(context, keyword_expr)?; let block = call.positional[2] .as_block() .expect("internal error: expected block"); - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block); + let context = context.clone(); - let state = context.enter_scope(); + match values { + Value::List { val, .. } => Ok(Value::List { + val: val + .map(move |x| { + let engine_state = context.engine_state.borrow(); + let block = engine_state.get_block(block); - let mut x = Value::Int { - val: 0, - span: Span::unknown(), - }; + let state = context.enter_scope(); + state.add_var(var_id, x.clone()); - loop { - if x == end_val { - break; - } else { - state.add_var(var_id, x.clone()); - eval_block(&state, block, input.clone())?; - } - if let Value::Int { ref mut val, .. } = x { - *val += 1 - } + //FIXME: DON'T UNWRAP + eval_block(&state, block, input.clone()).unwrap() + }) + .into_value_stream(), + span: call.head, + }), + _ => Ok(Value::nothing()), } - Ok(Value::Nothing { - span: call.positional[0].span, - }) } } diff --git a/crates/nu-command/src/length.rs b/crates/nu-command/src/length.rs index 79a92c778..270694894 100644 --- a/crates/nu-command/src/length.rs +++ b/crates/nu-command/src/length.rs @@ -40,6 +40,10 @@ impl Command for Length { span: call.head, }) } + Value::Nothing { .. } => Ok(Value::Int { + val: 0, + span: call.head, + }), _ => Ok(Value::Int { val: 1, span: call.head, diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 0a97143c2..e8e0f4c04 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -99,7 +99,7 @@ pub fn eval_expression( output.push(eval_expression(context, expr)?); } Ok(Value::List { - val: output.into_value_stream(), + val: output.into_iter().into_value_stream(), span: expr.span, }) } diff --git a/crates/nu-protocol/src/engine/evaluation_context.rs b/crates/nu-protocol/src/engine/evaluation_context.rs index f1baa9494..522965934 100644 --- a/crates/nu-protocol/src/engine/evaluation_context.rs +++ b/crates/nu-protocol/src/engine/evaluation_context.rs @@ -3,6 +3,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc}; use crate::{ShellError, Value, VarId}; +#[derive(Clone)] pub struct EvaluationContext { pub engine_state: Rc>, pub stack: Stack, diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index 3f3ce34e2..640fbe7d4 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -5,7 +5,7 @@ use crate::{span, BlockId, Span, Type}; use crate::ShellError; #[derive(Clone)] -pub struct ValueStream(Rc>>); +pub struct ValueStream(pub Rc>>); impl ValueStream { pub fn into_string(self) -> String { @@ -18,6 +18,10 @@ impl ValueStream { .join(", ".into()) ) } + + pub fn from_stream(input: impl Iterator + 'static) -> ValueStream { + ValueStream(Rc::new(RefCell::new(input))) + } } impl Debug for ValueStream { @@ -41,9 +45,12 @@ pub trait IntoValueStream { fn into_value_stream(self) -> ValueStream; } -impl IntoValueStream for Vec { +impl IntoValueStream for T +where + T: Iterator + 'static, +{ fn into_value_stream(self) -> ValueStream { - ValueStream(Rc::new(RefCell::new(self.into_iter()))) + ValueStream::from_stream(self) } }