Add a couple of builtin functions, and the Vm::call() method
* Builtin functions print and println have been added * If a global lookup fails, the VM will attempt to look up a builtin * Vm::call(fun, args) allows interrupting the current execution state and starting a new function instead. It will return the value left on top of the stack. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
pub mod consts;
|
||||
pub mod error; // TODO : not needed?
|
||||
pub mod error;
|
||||
pub mod frame;
|
||||
pub mod inst;
|
||||
pub mod signal;
|
||||
|
||||
use crate::{
|
||||
obj::{reserved::*, prelude::*},
|
||||
obj::{builtin::BUILTIN_OBJS, reserved::*, prelude::*},
|
||||
vm::{consts::ConstPool, frame::*, inst::*, signal::*},
|
||||
};
|
||||
|
||||
@@ -91,6 +91,13 @@ impl<'c> Vm<'c> {
|
||||
self.condition = condition;
|
||||
}
|
||||
|
||||
/// Calls a function.
|
||||
pub fn call(&mut self, fun: ObjRef, args: Vec<ObjRef>) -> ObjRef {
|
||||
self.handle_signal(Signal::Call(fun, args));
|
||||
self.resume_until_return();
|
||||
self.pop().expect("return value")
|
||||
}
|
||||
|
||||
/// Resumes execution of the current program.
|
||||
pub fn resume(&mut self) {
|
||||
while !self.frames().is_empty() {
|
||||
@@ -111,7 +118,8 @@ impl<'c> Vm<'c> {
|
||||
let signal = match frame {
|
||||
Frame::Native(fun) => {
|
||||
let callee = fun.callee().clone();
|
||||
(*fun.fun_ptr())(callee, self, vec![])
|
||||
let args = fun.args().clone();
|
||||
(*fun.fun_ptr())(callee, self, args)
|
||||
}
|
||||
Frame::User(_) => {
|
||||
self.resume_user_fun()
|
||||
@@ -200,6 +208,7 @@ impl<'c> Vm<'c> {
|
||||
}
|
||||
Inst::LoadGlobal(global) => {
|
||||
let value = self.get_global(global)
|
||||
.or_else(|| self.get_builtin(global))
|
||||
.expect("TODO: throw error for missing global");
|
||||
self.push(value);
|
||||
}
|
||||
@@ -332,7 +341,7 @@ impl<'c> Vm<'c> {
|
||||
}
|
||||
|
||||
fn get_global(&self, name: Name) -> Option<ObjRef> {
|
||||
self.frames
|
||||
self.frames()
|
||||
.first()?
|
||||
.user_frame()?
|
||||
.bindings()
|
||||
@@ -349,4 +358,15 @@ impl<'c> Vm<'c> {
|
||||
let bindings = frame.bindings_mut();
|
||||
bindings.insert(name.index(), value);
|
||||
}
|
||||
|
||||
fn get_builtin(&self, name: Name) -> Option<ObjRef> {
|
||||
read_obj!(let fun = self.frames()
|
||||
.first()?
|
||||
.user_frame()?
|
||||
.callee()
|
||||
);
|
||||
let fun: &UserFun = std::any::Any::downcast_ref(fun.as_any()).unwrap();
|
||||
let sym = fun.locals()[name.index()];
|
||||
BUILTIN_OBJS.get(&sym).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user