Fix up for_in

This commit is contained in:
JT 2021-09-03 14:57:18 +12:00
parent df63490266
commit 750502c870
5 changed files with 38 additions and 27 deletions

View File

@ -1,7 +1,7 @@
use nu_engine::{eval_block, eval_expression}; use nu_engine::{eval_block, eval_expression};
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EvaluationContext}; use nu_protocol::engine::{Command, EvaluationContext};
use nu_protocol::{Signature, Span, SyntaxShape, Value}; use nu_protocol::{IntoValueStream, Signature, Span, SyntaxShape, Value};
pub struct For; pub struct For;
@ -23,7 +23,10 @@ impl Command for For {
) )
.required( .required(
"range", "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", "range of the loop",
) )
.required("block", SyntaxShape::Block, "the block to run") .required("block", SyntaxShape::Block, "the block to run")
@ -42,34 +45,30 @@ impl Command for For {
let keyword_expr = call.positional[1] let keyword_expr = call.positional[1]
.as_keyword() .as_keyword()
.expect("internal error: missing 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] let block = call.positional[2]
.as_block() .as_block()
.expect("internal error: expected block"); .expect("internal error: expected block");
let engine_state = context.engine_state.borrow(); let context = context.clone();
let block = engine_state.get_block(block);
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 { let state = context.enter_scope();
val: 0, state.add_var(var_id, x.clone());
span: Span::unknown(),
};
loop { //FIXME: DON'T UNWRAP
if x == end_val { eval_block(&state, block, input.clone()).unwrap()
break; })
} else { .into_value_stream(),
state.add_var(var_id, x.clone()); span: call.head,
eval_block(&state, block, input.clone())?; }),
} _ => Ok(Value::nothing()),
if let Value::Int { ref mut val, .. } = x {
*val += 1
}
} }
Ok(Value::Nothing {
span: call.positional[0].span,
})
} }
} }

View File

@ -40,6 +40,10 @@ impl Command for Length {
span: call.head, span: call.head,
}) })
} }
Value::Nothing { .. } => Ok(Value::Int {
val: 0,
span: call.head,
}),
_ => Ok(Value::Int { _ => Ok(Value::Int {
val: 1, val: 1,
span: call.head, span: call.head,

View File

@ -99,7 +99,7 @@ pub fn eval_expression(
output.push(eval_expression(context, expr)?); output.push(eval_expression(context, expr)?);
} }
Ok(Value::List { Ok(Value::List {
val: output.into_value_stream(), val: output.into_iter().into_value_stream(),
span: expr.span, span: expr.span,
}) })
} }

View File

@ -3,6 +3,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::{ShellError, Value, VarId}; use crate::{ShellError, Value, VarId};
#[derive(Clone)]
pub struct EvaluationContext { pub struct EvaluationContext {
pub engine_state: Rc<RefCell<EngineState>>, pub engine_state: Rc<RefCell<EngineState>>,
pub stack: Stack, pub stack: Stack,

View File

@ -5,7 +5,7 @@ use crate::{span, BlockId, Span, Type};
use crate::ShellError; use crate::ShellError;
#[derive(Clone)] #[derive(Clone)]
pub struct ValueStream(Rc<RefCell<dyn Iterator<Item = Value>>>); pub struct ValueStream(pub Rc<RefCell<dyn Iterator<Item = Value>>>);
impl ValueStream { impl ValueStream {
pub fn into_string(self) -> String { pub fn into_string(self) -> String {
@ -18,6 +18,10 @@ impl ValueStream {
.join(", ".into()) .join(", ".into())
) )
} }
pub fn from_stream(input: impl Iterator<Item = Value> + 'static) -> ValueStream {
ValueStream(Rc::new(RefCell::new(input)))
}
} }
impl Debug for ValueStream { impl Debug for ValueStream {
@ -41,9 +45,12 @@ pub trait IntoValueStream {
fn into_value_stream(self) -> ValueStream; fn into_value_stream(self) -> ValueStream;
} }
impl IntoValueStream for Vec<Value> { impl<T> IntoValueStream for T
where
T: Iterator<Item = Value> + 'static,
{
fn into_value_stream(self) -> ValueStream { fn into_value_stream(self) -> ValueStream {
ValueStream(Rc::new(RefCell::new(self.into_iter()))) ValueStream::from_stream(self)
} }
} }