forked from extern/nushell
Fix up for_in
This commit is contained in:
parent
df63490266
commit
750502c870
@ -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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user