From 5d6b26d98dc3466f0efa8843545971110be75953 Mon Sep 17 00:00:00 2001 From: Bahex <17417311+Bahex@users.noreply.github.com> Date: Wed, 7 May 2025 18:26:39 +0300 Subject: [PATCH] feat(closure): closures that are const values --- crates/nu-protocol/src/eval_const.rs | 38 +++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/crates/nu-protocol/src/eval_const.rs b/crates/nu-protocol/src/eval_const.rs index b387de4120..e68828cfdd 100644 --- a/crates/nu-protocol/src/eval_const.rs +++ b/crates/nu-protocol/src/eval_const.rs @@ -5,8 +5,9 @@ use crate::{ ast::{Assignment, Block, Call, Expr, Expression, ExternalArgument}, debugger::{DebugContext, WithoutDebug}, - engine::{EngineState, StateWorkingSet}, + engine::{Closure, EngineState, StateWorkingSet}, eval_base::Eval, + ir::Instruction, record, BlockId, Config, HistoryFileFormat, PipelineData, Record, ShellError, Span, Value, VarId, }; @@ -548,12 +549,41 @@ impl Eval for EvalConst { } fn eval_row_condition_or_closure( - _: &StateWorkingSet, + state: &StateWorkingSet, _: &mut (), - _: BlockId, + block_id: BlockId, span: Span, ) -> Result { - Err(ShellError::NotAConstant { span }) + let block = state.get_block(block_id); + let ir_block = block + .ir_block + .as_ref() + .ok_or(ShellError::NotAConstant { span })?; + + let non_const_var_idx = ir_block.instructions.iter().position(|ins| { + let Instruction::LoadVariable { var_id, .. } = ins else { + return false; + }; + let var = state.get_variable(*var_id); + !(var.const_val.is_some() + || block + .span + .is_some_and(|b| b.contains_span(var.declaration_span))) + }); + + if let Some(idx) = non_const_var_idx { + Err(ShellError::NotAConstant { + span: ir_block.spans[idx], + }) + } else { + Ok(Value::closure( + Closure { + block_id, + captures: vec![], + }, + span, + )) + } } fn eval_overlay(_: &StateWorkingSet, span: Span) -> Result {