From debc913eeb1eabe0880fdf79278e2e99a63333fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Riegel?= Date: Sun, 13 Apr 2025 15:07:37 +0200 Subject: [PATCH] use unreachable! in run --- .../nu-cmd-lang/src/core_commands/break_.rs | 6 +- .../nu-cmd-lang/src/core_commands/const_.rs | 29 +------ .../src/core_commands/continue_.rs | 6 +- crates/nu-cmd-lang/src/core_commands/for_.rs | 81 ++---------------- crates/nu-cmd-lang/src/core_commands/if_.rs | 45 ++-------- crates/nu-cmd-lang/src/core_commands/let_.rs | 45 ++-------- crates/nu-cmd-lang/src/core_commands/loop_.rs | 33 ++------ .../nu-cmd-lang/src/core_commands/match_.rs | 60 ++------------ crates/nu-cmd-lang/src/core_commands/mut_.rs | 45 ++-------- .../nu-cmd-lang/src/core_commands/return_.rs | 15 ++-- crates/nu-cmd-lang/src/core_commands/try_.rs | 82 ++----------------- .../nu-cmd-lang/src/core_commands/while_.rs | 54 ++---------- 12 files changed, 66 insertions(+), 435 deletions(-) diff --git a/crates/nu-cmd-lang/src/core_commands/break_.rs b/crates/nu-cmd-lang/src/core_commands/break_.rs index 69c8089370..4952dade1e 100644 --- a/crates/nu-cmd-lang/src/core_commands/break_.rs +++ b/crates/nu-cmd-lang/src/core_commands/break_.rs @@ -34,10 +34,12 @@ impl Command for Break { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { - Err(ShellError::Break { span: call.head }) + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/const_.rs b/crates/nu-cmd-lang/src/core_commands/const_.rs index 5727938c84..ca0cf787a2 100644 --- a/crates/nu-cmd-lang/src/core_commands/const_.rs +++ b/crates/nu-cmd-lang/src/core_commands/const_.rs @@ -41,35 +41,14 @@ impl Command for Const { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let var_id = if let Some(id) = call.positional_nth(0).and_then(|pos| pos.as_var()) { - id - } else { - return Err(ShellError::NushellFailedSpanned { - msg: "Could not get variable".to_string(), - label: "variable not added by the parser".to_string(), - span: call.head, - }); - }; - - if let Some(constval) = &engine_state.get_var(var_id).const_val { - stack.add_var(var_id, constval.clone()); - - Ok(PipelineData::empty()) - } else { - Err(ShellError::NushellFailedSpanned { - msg: "Missing Constant".to_string(), - label: "constant not added by the parser".to_string(), - span: call.head, - }) - } + unreachable!() } fn run_const( diff --git a/crates/nu-cmd-lang/src/core_commands/continue_.rs b/crates/nu-cmd-lang/src/core_commands/continue_.rs index 1c070286d2..27b550ee56 100644 --- a/crates/nu-cmd-lang/src/core_commands/continue_.rs +++ b/crates/nu-cmd-lang/src/core_commands/continue_.rs @@ -33,10 +33,12 @@ impl Command for Continue { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { - Err(ShellError::Continue { span: call.head }) + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/for_.rs b/crates/nu-cmd-lang/src/core_commands/for_.rs index 912d738524..7f37b5dc41 100644 --- a/crates/nu-cmd-lang/src/core_commands/for_.rs +++ b/crates/nu-cmd-lang/src/core_commands/for_.rs @@ -1,5 +1,5 @@ -use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression}; -use nu_protocol::{engine::CommandType, Signals}; +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; #[derive(Clone)] pub struct For; @@ -43,83 +43,14 @@ impl Command for For { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let head = call.head; - let var_id = call - .positional_nth(0) - .expect("checked through parser") - .as_var() - .expect("internal error: missing variable"); - - let keyword_expr = call - .positional_nth(1) - .expect("checked through parser") - .as_keyword() - .expect("internal error: missing keyword"); - - let block_id = call - .positional_nth(2) - .expect("checked through parser") - .as_block() - .expect("internal error: missing block"); - - let eval_expression = get_eval_expression(engine_state); - let eval_block = get_eval_block(engine_state); - - let value = eval_expression(engine_state, stack, keyword_expr)?; - - let engine_state = engine_state.clone(); - let block = engine_state.get_block(block_id); - - let stack = &mut stack.push_redirection(None, None); - - let span = value.span(); - match value { - Value::List { vals, .. } => { - for x in vals.into_iter() { - engine_state.signals().check(head)?; - - // with_env() is used here to ensure that each iteration uses - // a different set of environment variables. - // Hence, a 'cd' in the first loop won't affect the next loop. - - stack.add_var(var_id, x); - - match eval_block(&engine_state, stack, block, PipelineData::empty()) { - Err(ShellError::Break { .. }) => break, - Err(ShellError::Continue { .. }) => continue, - Err(err) => return Err(err), - Ok(data) => data.drain()?, - } - } - } - Value::Range { val, .. } => { - for x in val.into_range_iter(span, Signals::empty()) { - engine_state.signals().check(head)?; - stack.add_var(var_id, x); - - match eval_block(&engine_state, stack, block, PipelineData::empty()) { - Err(ShellError::Break { .. }) => break, - Err(ShellError::Continue { .. }) => continue, - Err(err) => return Err(err), - Ok(data) => data.drain()?, - } - } - } - x => { - stack.add_var(var_id, x); - - eval_block(&engine_state, stack, block, PipelineData::empty())?.into_value(head)?; - } - } - Ok(PipelineData::empty()) + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/if_.rs b/crates/nu-cmd-lang/src/core_commands/if_.rs index e40bb13b82..e787dcf6e4 100644 --- a/crates/nu-cmd-lang/src/core_commands/if_.rs +++ b/crates/nu-cmd-lang/src/core_commands/if_.rs @@ -1,6 +1,4 @@ -use nu_engine::{ - command_prelude::*, get_eval_block, get_eval_expression, get_eval_expression_with_input, -}; +use nu_engine::command_prelude::*; use nu_protocol::{ engine::{CommandType, StateWorkingSet}, eval_const::{eval_const_subexpression, eval_constant, eval_constant_with_input}, @@ -60,8 +58,6 @@ impl Command for If { call: &Call, input: PipelineData, ) -> Result { - // This is compiled specially by the IR compiler. The code here is never used when - // running in IR mode. let call = call.assert_ast_call()?; let cond = call.positional_nth(0).expect("checked through parser"); let then_block = call @@ -97,43 +93,14 @@ impl Command for If { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - input: PipelineData, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let cond = call.positional_nth(0).expect("checked through parser"); - let then_block = call - .positional_nth(1) - .expect("checked through parser") - .as_block() - .expect("internal error: missing block"); - let else_case = call.positional_nth(2); - - let eval_expression = get_eval_expression(engine_state); - let eval_expression_with_input = get_eval_expression_with_input(engine_state); - let eval_block = get_eval_block(engine_state); - - if eval_expression(engine_state, stack, cond)?.as_bool()? { - let block = engine_state.get_block(then_block); - eval_block(engine_state, stack, block, input) - } else if let Some(else_case) = else_case { - if let Some(else_expr) = else_case.as_keyword() { - if let Some(block_id) = else_expr.as_block() { - let block = engine_state.get_block(block_id); - eval_block(engine_state, stack, block, input) - } else { - eval_expression_with_input(engine_state, stack, else_expr, input) - } - } else { - eval_expression_with_input(engine_state, stack, else_case, input) - } - } else { - Ok(PipelineData::empty()) - } + unreachable!() } fn search_terms(&self) -> Vec<&str> { diff --git a/crates/nu-cmd-lang/src/core_commands/let_.rs b/crates/nu-cmd-lang/src/core_commands/let_.rs index b7deca5b81..40614e4fa3 100644 --- a/crates/nu-cmd-lang/src/core_commands/let_.rs +++ b/crates/nu-cmd-lang/src/core_commands/let_.rs @@ -1,4 +1,4 @@ -use nu_engine::{command_prelude::*, get_eval_block}; +use nu_engine::command_prelude::*; use nu_protocol::engine::CommandType; #[derive(Clone)] @@ -41,47 +41,14 @@ impl Command for Let { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - input: PipelineData, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let var_id = call - .positional_nth(0) - .expect("checked through parser") - .as_var() - .expect("internal error: missing variable"); - - let block_id = call - .positional_nth(1) - .expect("checked through parser") - .as_block() - .expect("internal error: missing right hand side"); - - let block = engine_state.get_block(block_id); - let eval_block = get_eval_block(engine_state); - let stack = &mut stack.start_collect_value(); - let pipeline_data = eval_block(engine_state, stack, block, input)?; - let value = pipeline_data.into_value(call.head)?; - - // if given variable type is Glob, and our result is string - // then nushell need to convert from Value::String to Value::Glob - // it's assigned by demand, then it's not quoted, and it's required to expand - // if we pass it to other commands. - let var_type = &engine_state.get_var(var_id).ty; - let val_span = value.span(); - let value = match value { - Value::String { val, .. } if var_type == &Type::Glob => { - Value::glob(val, false, val_span) - } - value => value, - }; - - stack.add_var(var_id, value); - Ok(PipelineData::empty()) + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/loop_.rs b/crates/nu-cmd-lang/src/core_commands/loop_.rs index b799d32141..8804766129 100644 --- a/crates/nu-cmd-lang/src/core_commands/loop_.rs +++ b/crates/nu-cmd-lang/src/core_commands/loop_.rs @@ -1,4 +1,4 @@ -use nu_engine::{command_prelude::*, get_eval_block}; +use nu_engine::command_prelude::*; use nu_protocol::engine::CommandType; #[derive(Clone)] @@ -32,37 +32,14 @@ impl Command for Loop { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let head = call.head; - let block_id = call - .positional_nth(0) - .expect("checked through parser") - .as_block() - .expect("internal error: missing block"); - - let block = engine_state.get_block(block_id); - let eval_block = get_eval_block(engine_state); - - let stack = &mut stack.push_redirection(None, None); - - loop { - engine_state.signals().check(head)?; - - match eval_block(engine_state, stack, block, PipelineData::empty()) { - Err(ShellError::Break { .. }) => break, - Err(ShellError::Continue { .. }) => continue, - Err(err) => return Err(err), - Ok(data) => data.drain()?, - } - } - Ok(PipelineData::empty()) + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/match_.rs b/crates/nu-cmd-lang/src/core_commands/match_.rs index a7bebeb857..a36c64e917 100644 --- a/crates/nu-cmd-lang/src/core_commands/match_.rs +++ b/crates/nu-cmd-lang/src/core_commands/match_.rs @@ -1,7 +1,5 @@ -use nu_engine::{ - command_prelude::*, get_eval_block, get_eval_expression, get_eval_expression_with_input, -}; -use nu_protocol::engine::{CommandType, Matcher}; +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; #[derive(Clone)] pub struct Match; @@ -38,58 +36,14 @@ impl Command for Match { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - input: PipelineData, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let value: Value = call.req(engine_state, stack, 0)?; - let matches = call - .positional_nth(1) - .expect("checked through parser") - .as_match_block() - .expect("missing match block"); - - let eval_expression = get_eval_expression(engine_state); - let eval_expression_with_input = get_eval_expression_with_input(engine_state); - let eval_block = get_eval_block(engine_state); - - let mut match_variables = vec![]; - for (pattern, expr) in matches { - if pattern.match_value(&value, &mut match_variables) { - // This case does match, go ahead and return the evaluated expression - for (id, value) in match_variables.drain(..) { - stack.add_var(id, value); - } - - let guard_matches = if let Some(guard) = &pattern.guard { - let Value::Bool { val, .. } = eval_expression(engine_state, stack, guard)? - else { - return Err(ShellError::MatchGuardNotBool { span: guard.span }); - }; - - val - } else { - true - }; - - if guard_matches { - return if let Some(block_id) = expr.as_block() { - let block = engine_state.get_block(block_id); - eval_block(engine_state, stack, block, input) - } else { - eval_expression_with_input(engine_state, stack, expr, input) - }; - } - } else { - match_variables.clear(); - } - } - - Ok(PipelineData::Empty) + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/mut_.rs b/crates/nu-cmd-lang/src/core_commands/mut_.rs index 785a47f943..a5feacfd85 100644 --- a/crates/nu-cmd-lang/src/core_commands/mut_.rs +++ b/crates/nu-cmd-lang/src/core_commands/mut_.rs @@ -1,4 +1,4 @@ -use nu_engine::{command_prelude::*, get_eval_block}; +use nu_engine::command_prelude::*; use nu_protocol::engine::CommandType; #[derive(Clone)] @@ -41,47 +41,14 @@ impl Command for Mut { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - input: PipelineData, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let var_id = call - .positional_nth(0) - .expect("checked through parser") - .as_var() - .expect("internal error: missing variable"); - - let block_id = call - .positional_nth(1) - .expect("checked through parser") - .as_block() - .expect("internal error: missing right hand side"); - - let block = engine_state.get_block(block_id); - let eval_block = get_eval_block(engine_state); - let stack = &mut stack.start_collect_value(); - let pipeline_data = eval_block(engine_state, stack, block, input)?; - let value = pipeline_data.into_value(call.head)?; - - // if given variable type is Glob, and our result is string - // then nushell need to convert from Value::String to Value::Glob - // it's assigned by demand, then it's not quoted, and it's required to expand - // if we pass it to other commands. - let var_type = &engine_state.get_var(var_id).ty; - let val_span = value.span(); - let value = match value { - Value::String { val, .. } if var_type == &Type::Glob => { - Value::glob(val, false, val_span) - } - value => value, - }; - - stack.add_var(var_id, value); - Ok(PipelineData::empty()) + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/return_.rs b/crates/nu-cmd-lang/src/core_commands/return_.rs index 2569d81dfe..114d6e796a 100644 --- a/crates/nu-cmd-lang/src/core_commands/return_.rs +++ b/crates/nu-cmd-lang/src/core_commands/return_.rs @@ -35,17 +35,14 @@ impl Command for Return { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, _input: PipelineData, ) -> Result { - let return_value: Option = call.opt(engine_state, stack, 0)?; - let value = return_value.unwrap_or(Value::nothing(call.head)); - Err(ShellError::Return { - span: call.head, - value: Box::new(value), - }) + // This is compiled specially by the IR compiler. The code here is never used when + // running in IR mode. + unreachable!() } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/try_.rs b/crates/nu-cmd-lang/src/core_commands/try_.rs index 4b5361c681..b99255337b 100644 --- a/crates/nu-cmd-lang/src/core_commands/try_.rs +++ b/crates/nu-cmd-lang/src/core_commands/try_.rs @@ -1,5 +1,5 @@ -use nu_engine::{command_prelude::*, get_eval_block, EvalBlockFn}; -use nu_protocol::engine::{Closure, CommandType}; +use nu_engine::command_prelude::*; +use nu_protocol::engine::CommandType; #[derive(Clone)] pub struct Try; @@ -42,36 +42,14 @@ impl Command for Try { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - input: PipelineData, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, + _input: PipelineData, ) -> Result { - let head = call.head; // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let try_block = call - .positional_nth(0) - .expect("checked through parser") - .as_block() - .expect("internal error: missing block"); - - let catch_block: Option = call.opt(engine_state, stack, 1)?; - - let try_block = engine_state.get_block(try_block); - let eval_block = get_eval_block(engine_state); - - let result = eval_block(engine_state, stack, try_block, input) - .and_then(|pipeline| pipeline.drain_to_out_dests(engine_state, stack)); - - match result { - Err(err) => run_catch(err, head, catch_block, engine_state, stack, eval_block), - Ok(PipelineData::Value(Value::Error { error, .. }, ..)) => { - run_catch(*error, head, catch_block, engine_state, stack, eval_block) - } - Ok(pipeline) => Ok(pipeline), - } + unreachable!(); } fn examples(&self) -> Vec { @@ -95,52 +73,6 @@ impl Command for Try { } } -fn run_catch( - error: ShellError, - span: Span, - catch: Option, - engine_state: &EngineState, - stack: &mut Stack, - eval_block: EvalBlockFn, -) -> Result { - let error = intercept_block_control(error)?; - - if let Some(catch) = catch { - stack.set_last_error(&error); - let error = error.into_value(&StateWorkingSet::new(engine_state), span); - let block = engine_state.get_block(catch.block_id); - // Put the error value in the positional closure var - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - stack.add_var(*var_id, error.clone()); - } - } - - eval_block( - engine_state, - stack, - block, - // Make the error accessible with $in, too - error.into_pipeline_data(), - ) - } else { - Ok(PipelineData::empty()) - } -} - -/// The flow control commands `break`/`continue`/`return` emit their own [`ShellError`] variants -/// We need to ignore those in `try` and bubble them through -/// -/// `Err` when flow control to bubble up with `?` -fn intercept_block_control(error: ShellError) -> Result { - match error { - ShellError::Break { .. } => Err(error), - ShellError::Continue { .. } => Err(error), - ShellError::Return { .. } => Err(error), - _ => Ok(error), - } -} - #[cfg(test)] mod test { use super::*; diff --git a/crates/nu-cmd-lang/src/core_commands/while_.rs b/crates/nu-cmd-lang/src/core_commands/while_.rs index e9578ae6f5..b8a63f6c35 100644 --- a/crates/nu-cmd-lang/src/core_commands/while_.rs +++ b/crates/nu-cmd-lang/src/core_commands/while_.rs @@ -1,4 +1,4 @@ -use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression}; +use nu_engine::command_prelude::*; use nu_protocol::engine::CommandType; #[derive(Clone)] @@ -41,58 +41,14 @@ impl Command for While { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, + _engine_state: &EngineState, + _stack: &mut Stack, + _call: &Call, _input: PipelineData, ) -> Result { // This is compiled specially by the IR compiler. The code here is never used when // running in IR mode. - let call = call.assert_ast_call()?; - let head = call.head; - let cond = call.positional_nth(0).expect("checked through parser"); - let block_id = call - .positional_nth(1) - .expect("checked through parser") - .as_block() - .expect("internal error: missing block"); - - let eval_expression = get_eval_expression(engine_state); - let eval_block = get_eval_block(engine_state); - - let stack = &mut stack.push_redirection(None, None); - - loop { - engine_state.signals().check(head)?; - - let result = eval_expression(engine_state, stack, cond)?; - - match &result { - Value::Bool { val, .. } => { - if *val { - let block = engine_state.get_block(block_id); - - match eval_block(engine_state, stack, block, PipelineData::empty()) { - Err(ShellError::Break { .. }) => break, - Err(ShellError::Continue { .. }) => continue, - Err(err) => return Err(err), - Ok(data) => data.drain()?, - } - } else { - break; - } - } - x => { - return Err(ShellError::CantConvert { - to_type: "bool".into(), - from_type: x.get_type().to_string(), - span: result.span(), - help: None, - }) - } - } - } - Ok(PipelineData::empty()) + unreachable!() } fn examples(&self) -> Vec {