From 979faf853adeadce00728877e0000a07f8baa972 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 6 Sep 2021 14:20:02 +1200 Subject: [PATCH] Block params --- crates/nu-cli/src/errors.rs | 2 +- crates/nu-engine/src/eval.rs | 2 +- crates/nu-parser/src/parser.rs | 16 +++++++++++++++- crates/nu-protocol/src/engine/engine_state.rs | 14 ++++++++++++-- crates/nu-protocol/src/shell_error.rs | 2 +- crates/nu-protocol/src/signature.rs | 2 +- src/tests.rs | 10 ++++++++++ 7 files changed, 41 insertions(+), 7 deletions(-) diff --git a/crates/nu-cli/src/errors.rs b/crates/nu-cli/src/errors.rs index ef25181cad..d35f0c9ede 100644 --- a/crates/nu-cli/src/errors.rs +++ b/crates/nu-cli/src/errors.rs @@ -297,7 +297,7 @@ pub fn report_shell_error( ShellError::InternalError(s) => { Diagnostic::error().with_message(format!("Internal error: {}", s)) } - ShellError::VariableNotFound(span) => { + ShellError::VariableNotFoundAtRuntime(span) => { let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?; Diagnostic::error() .with_message("Variable not found") diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index e629ab3034..f4042816bf 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -101,7 +101,7 @@ pub fn eval_expression( } Expr::Var(var_id) => context .get_var(*var_id) - .map_err(move |_| ShellError::VariableNotFound(expr.span)), + .map_err(move |_| ShellError::VariableNotFoundAtRuntime(expr.span)), Expr::Call(call) => eval_call(context, call, Value::nothing()), Expr::ExternalCall(_, _) => Err(ShellError::ExternalNotSupported(expr.span)), Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }), diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index d9206b1e0e..a3adc73974 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1771,6 +1771,7 @@ pub fn parse_block_expression( let (output, err) = lex(source, start, &[], &[]); error = error.or(err); + working_set.enter_scope(); // Check to see if we have parameters let (signature, amt_to_skip): (Option>, usize) = match output.first() { Some(Token { @@ -1818,13 +1819,26 @@ pub fn parse_block_expression( let (output, err) = lite_parse(&output[amt_to_skip..]); error = error.or(err); - let (mut output, err) = parse_block(working_set, &output, true); + let (mut output, err) = parse_block(working_set, &output, false); error = error.or(err); if let Some(signature) = signature { output.signature = signature; + } else if let Some(last) = working_set.delta.scope.last() { + if let Some(var_id) = last.get_var(b"$it") { + let mut signature = Signature::new(""); + signature.required_positional.push(PositionalArg { + var_id: Some(*var_id), + name: "$it".into(), + desc: String::new(), + shape: SyntaxShape::Any, + }); + output.signature = Box::new(signature); + } } + working_set.exit_scope(); + let block_id = working_set.add_block(output); ( diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 31ad6b6b2a..80d437a57c 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -13,7 +13,7 @@ pub struct EngineState { } #[derive(Debug)] -struct ScopeFrame { +pub struct ScopeFrame { vars: HashMap, VarId>, decls: HashMap, DeclId>, aliases: HashMap, Vec>, @@ -27,6 +27,16 @@ impl ScopeFrame { aliases: HashMap::new(), } } + + pub fn get_var(&self, var_name: &[u8]) -> Option<&VarId> { + self.vars.get(var_name) + } +} + +impl Default for ScopeFrame { + fn default() -> Self { + Self::new() + } } impl Default for EngineState { @@ -188,7 +198,7 @@ pub struct StateDelta { vars: Vec, // indexed by VarId decls: Vec>, // indexed by DeclId blocks: Vec, // indexed by BlockId - scope: Vec, + pub scope: Vec, } impl StateDelta { diff --git a/crates/nu-protocol/src/shell_error.rs b/crates/nu-protocol/src/shell_error.rs index a769faacf8..78f672921d 100644 --- a/crates/nu-protocol/src/shell_error.rs +++ b/crates/nu-protocol/src/shell_error.rs @@ -13,7 +13,7 @@ pub enum ShellError { UnknownOperator(String, Span), ExternalNotSupported(Span), InternalError(String), - VariableNotFound(Span), + VariableNotFoundAtRuntime(Span), CantConvert(String, Span), DivisionByZero(Span), } diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs index 2c12efd00b..0bf8fa0954 100644 --- a/crates/nu-protocol/src/signature.rs +++ b/crates/nu-protocol/src/signature.rs @@ -350,7 +350,7 @@ impl Command for BlockCommand { } fn signature(&self) -> Signature { - panic!("Internal error: can't get signature with 'signature', use block_id"); + self.signature.clone() } fn usage(&self) -> &str { diff --git a/src/tests.rs b/src/tests.rs index 97e4630689..820af046a9 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -203,3 +203,13 @@ fn alias_2() -> TestResult { "143", ) } + +#[test] +fn block_param1() -> TestResult { + run_test("[3] | each { $it + 10 }", "13") +} + +#[test] +fn block_param2() -> TestResult { + run_test("[3] | each { |y| $y + 10 }", "13") +}