From 6ebf31e2a007a1e58fca5fcd84e38f7ae97bd449 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Thu, 5 Mar 2026 14:35:29 +0100 Subject: [PATCH] Refactor specializer to not fold scalars The specializer now correctly identifies when a compiled value is a scalar and avoids folding it into a constant node. Instead, it updates the callee to the specialized version if it's an object. This ensures that scalar folding does not interfere with the program's execution. --- src/ast/compiler/specializer.rs | 48 +++++++++++---------------------- src/ast/vm.rs | 2 +- 2 files changed, 16 insertions(+), 34 deletions(-) diff --git a/src/ast/compiler/specializer.rs b/src/ast/compiler/specializer.rs index 83a27c9..c64204b 100644 --- a/src/ast/compiler/specializer.rs +++ b/src/ast/compiler/specializer.rs @@ -233,39 +233,21 @@ impl Specializer { self.cache .borrow_mut() .insert(key, (compiled_val.clone(), ret_ty.clone())); - let flat_elements = match &new_args.kind { - BoundKind::Tuple { elements } => elements.clone(), - _ => vec![Rc::new(new_args.clone())], - }; - let flat_types = flat_elements - .iter() - .map(|e| e.ty.original.ty.clone()) - .collect(); - let flattened_args = Node { - identity: new_args.identity.clone(), - kind: BoundKind::Tuple { - elements: flat_elements, - }, - ty: NodeMetrics { - original: Rc::new(Node { - identity: new_args.identity.clone(), - kind: BoundKind::Tuple { elements: vec![] }, - ty: StaticType::Tuple(flat_types), - }), - purity: new_args.ty.purity, - is_recursive: new_args.ty.is_recursive, - }, - }; - - let specialized_callee = self.make_constant_node( - compiled_val, - StaticType::Function(Box::new(Signature { - params: flattened_args.ty.original.ty.clone(), - ret: ret_ty.clone(), - })), - &new_callee, - ); - return (specialized_callee, flattened_args, ret_ty); + + // Only replace the callee if the compiled value is actually a function/object. + // If it's a scalar (like 30 from folding), we DON'T fold here. + // We keep the Call but update the callee to the specialized version if it's an object. + if let Value::Object(_) | Value::Function(_) = &compiled_val { + let specialized_callee = self.make_constant_node( + compiled_val, + StaticType::Function(Box::new(Signature { + params: StaticType::Tuple(arg_types), + ret: ret_ty.clone(), + })), + &new_callee, + ); + return (specialized_callee, new_args, ret_ty); + } } (new_callee, new_args, original_ty) diff --git a/src/ast/vm.rs b/src/ast/vm.rs index 0b3eea5..40cc314 100644 --- a/src/ast/vm.rs +++ b/src/ast/vm.rs @@ -783,7 +783,7 @@ impl VM { } match &curr.kind { - BoundKind::Constant(v) => self.stack.push(v.clone()), + BoundKind::Constant(v) if !O::ACTIVE => self.stack.push(v.clone()), _ => { let val = self.eval_internal(obs, curr)?; self.stack.push(val);