Refactor tail call resolution logic
The tail call resolution logic was duplicated in `Environment::call` and `VM::run`. This commit extracts the tail call resolution logic into a single method `VM::resolve_tail_calls` and uses it in both places. Additionally, this commit adds support for series indexing as a form of tail call, allowing for direct access to series elements through the `series(index)` syntax. This is useful for back-referencing in time-series data. A new example `err.myc` is added to demonstrate basic series usage and error handling.
This commit is contained in:
+8
-19
@@ -501,7 +501,10 @@ impl Environment {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!("Myc Runtime Error: {}", e),
|
||||
};
|
||||
vm.resolve_tail_calls(res)
|
||||
match vm.resolve_tail_calls(&mut crate::ast::vm::NoOpObserver, Ok(res)) {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!("Myc Runtime Error: {}", e),
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -528,7 +531,10 @@ impl Environment {
|
||||
Err(e) => panic!("Myc Runtime Error (Closure): {}", e),
|
||||
};
|
||||
}
|
||||
vm.resolve_tail_calls(final_res)
|
||||
match vm.resolve_tail_calls(&mut crate::ast::vm::NoOpObserver, Ok(final_res)) {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!("Myc Runtime Error: {}", e),
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
@@ -645,23 +651,6 @@ impl Environment {
|
||||
result = vm.run_with_observer(&mut observer, &closure.exec_node);
|
||||
}
|
||||
|
||||
while let Ok(Value::TailCallRequest(payload)) = result {
|
||||
let (next_obj, next_args) = *payload;
|
||||
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: {}",
|
||||
next_obj.type_name()
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.run_pipeline();
|
||||
|
||||
Ok((result, observer.logs))
|
||||
|
||||
Reference in New Issue
Block a user