Add function yielding and resuming

Sometimes, a builtin function may need to call out to another function
(user-defined or otherwise). Previously, we were just calling the
function and popping the stack frame, leaving no room for the new
function to be called. This introduces a `FunctionResult` and
`FunctionState` that get passed between these builtin functions. A
builtin function will receive a FunctionState that tells it whether it
is currently beginning or being resumed and can act accordingly. A
builtin function will in turn return a FunctionResult, which can either
be to return and push a value to the stack, return without pushing a
value (value is already on top of the stack), or yield execution back to
the VM (implying that a new stack frame has been pushed with a new
function to execute).

Having to call a new function and resume is a bit unwieldy and
un-ergonomic, and making a macro to help write these would be nice, but
it looks like a procedural macro may be required to really enable this.
For now, we will write these yields by hand and once it becomes truly
too much, we can start looking at writing a macro library to handle this
case.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-09-24 11:34:07 -07:00
parent d69a60f42c
commit 3a7c04686a
5 changed files with 220 additions and 75 deletions

View File

@@ -116,7 +116,8 @@ pub fn init_types(builtins: &mut HashMap<String, ObjP>) {
// type definitions
Type {
// Method conversion
to_string => builtins.create_builtin_function("to_string", BaseObjInst::to_string, 1),
to_string => builtins.create_builtin_function("to_string", BaseObjInst::to_repr, 1),
to_repr => builtins.create_builtin_function("to_repr", BaseObjInst::to_repr, 1),
to_bool => builtins.create_builtin_function("to_bool", BaseObjInst::to_bool, 1),
// Operators
__add__ => builtins.create_builtin_function("__add__", BaseObjInst::add, 2),
@@ -333,73 +334,74 @@ struct BaseObjInst {
//
impl BaseObjInst {
fn add(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __add__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn add(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __add__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn sub(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __sub__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn sub(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __sub__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn mul(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __mul__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn mul(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __mul__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn div(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __div__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn div(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __div__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn and(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __and__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn and(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __and__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn or(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __or__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn or(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __or__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn ne(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __ne__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn ne(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __ne__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn eq(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __eq__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn eq(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __eq__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn gt(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __gt__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn gt(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __gt__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn ge(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __ge__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn ge(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __ge__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn lt(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __lt__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn lt(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __lt__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn le(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __le__ function (self: {:?}, rhs: {:?})", args[0].borrow(), args[1].borrow())
fn le(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __le__ function (self: {:?}, rhs: {:?})", vm.frame_stack()[0].borrow(), vm.frame_stack()[1].borrow())
}
fn pos(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __pos__ function (self: {:?})", args[0].borrow())
fn pos(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __pos__ function (self: {:?})", vm.frame_stack()[0].borrow())
}
fn neg(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __neg__ function (self: {:?})", args[0].borrow())
fn neg(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __neg__ function (self: {:?})", vm.frame_stack()[0].borrow())
}
fn not(_vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
todo!("Raise some kind of not implemented/not callable error for __not__ function (self: {:?})", args[0].borrow())
fn not(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
todo!("Raise some kind of not implemented/not callable error for __not__ function (self: {:?})", vm.frame_stack()[0].borrow())
}
fn to_bool(vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
vm.create_bool(args[0].borrow().is_truthy())
fn to_bool(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
vm.create_bool(vm.frame_stack()[0].borrow().is_truthy())
.into()
}
fn to_string(vm: &mut Vm, args: Vec<ObjP>) -> ObjP {
let str_value = format!("{}", &args[0].borrow());
vm.create_str(str_value)
fn to_repr(vm: &mut Vm, _state: FunctionState) -> FunctionResult {
let str_value = format!("{}", vm.frame_stack()[0].borrow());
vm.create_str(str_value).into()
}
}