Refactor VM to use trait objects for closures

The `CallFrame` struct and various VM methods now use `Rc<dyn Object>`
to hold closures, allowing for more flexibility and avoiding unnecessary
cloning.

This change also addresses the performance concern regarding deep copies
of closures, preferring `Rc<dyn Trait>` with local `downcast_ref` where
appropriate.

Additionally, a documentation note has been added to `gemini.md`
regarding this performance preference in Rust.
This commit is contained in:
Michael Schimmel
2026-02-28 14:26:29 +01:00
parent 3daf8ef94d
commit 0dfbda5e15
4 changed files with 29 additions and 21 deletions
+6 -5
View File
@@ -261,12 +261,13 @@ impl Environment {
vec![],
*positional_count,
));
let closure_obj: Rc<dyn crate::ast::types::Object> = closure;
return Rc::new(crate::ast::types::NativeFunction {
purity: Purity::Impure,
func: Rc::new(move |args| {
let mut vm = VM::new(global_values.clone());
let res = match vm.run_with_args(&closure, args) {
let res = match vm.run_with_args(closure_obj.clone(), args) {
Ok(v) => v,
Err(e) => panic!("Myc Runtime Error: {}", e),
};
@@ -287,9 +288,9 @@ impl Environment {
let mut final_res = res;
if let Value::Object(obj) = &final_res
&& let Some(closure) = obj.as_any().downcast_ref::<crate::ast::vm::Closure>()
&& obj.as_any().downcast_ref::<crate::ast::vm::Closure>().is_some()
{
final_res = match vm.run_with_args(closure, args) {
final_res = match vm.run_with_args(obj.clone(), args) {
Ok(v) => v,
Err(e) => panic!("Myc Runtime Error (Closure): {}", e),
};
@@ -396,8 +397,8 @@ impl Environment {
while let Ok(Value::TailCallRequest(payload)) = result {
let (next_obj, next_args) = *payload;
if let Some(closure) = next_obj.as_any().downcast_ref::<crate::ast::vm::Closure>() {
result = vm.run_with_args_observed(&mut observer, closure, next_args);
if next_obj.as_any().downcast_ref::<crate::ast::vm::Closure>().is_some() {
result = vm.run_with_args_observed(&mut observer, next_obj, next_args);
} else {
result = Err(format!(
"Tail call target is not a closure: {}",