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.
This commit is contained in:
Michael Schimmel
2026-03-05 14:35:29 +01:00
parent 831525b402
commit 6ebf31e2a0
2 changed files with 16 additions and 34 deletions
+15 -33
View File
@@ -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)
+1 -1
View File
@@ -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);