Finish up function call implementation, it appears to be working
Functions are downcasted to a `Fun` trait, which will construct the appropriate stack frame. A few other things have been shifted around that affect internal APIs while things are still under construction. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
101
src/obj/fun.rs
101
src/obj/fun.rs
@@ -1,10 +1,16 @@
|
||||
use crate::{obj::{reserved::*, prelude::*}, vm::{consts::ConstPool, inst::Inst, signal::*, Vm}};
|
||||
use crate::{obj::{reserved::*, prelude::*}, vm::{consts::ConstPool, frame::*, inst::Inst, signal::*, Vm}};
|
||||
use once_cell::sync::Lazy;
|
||||
use shredder::{GcSafeWrapper, Scan};
|
||||
use std::{fmt::{Debug, Formatter, self}, io::{self, Write}};
|
||||
use std::{fmt::{Debug, Formatter, self}, io::{self, Write}, sync::Arc};
|
||||
|
||||
pub type FunLocals = Vec<Sym>;
|
||||
|
||||
/// A function object which can create a new stack frame.
|
||||
pub trait Fun {
|
||||
/// Creates a new `vm::Frame` from this function object.
|
||||
fn create_frame(&self, callee: ObjRef, vm: &Vm, _args: Vec<ObjRef>) -> Frame;
|
||||
}
|
||||
|
||||
//
|
||||
// struct UserFun
|
||||
//
|
||||
@@ -17,7 +23,7 @@ pub struct UserFun {
|
||||
attrs: Attrs,
|
||||
// Safe because Vec<Inst> doesn't need to be scanned
|
||||
#[shredder(unsafe_skip)]
|
||||
code: Vec<Inst>,
|
||||
code: Arc<Vec<Inst>>,
|
||||
// Safe because this is just an interner that points to symbols, which aren't GC'd
|
||||
#[shredder(unsafe_skip)]
|
||||
locals: FunLocals,
|
||||
@@ -28,7 +34,7 @@ impl UserFun {
|
||||
let obj_ref = ObjRef::new(UserFun {
|
||||
vtable: Default::default(), // this is a placeholder for the real vtable
|
||||
attrs: Default::default(),
|
||||
code,
|
||||
code: Arc::new(code),
|
||||
locals,
|
||||
});
|
||||
|
||||
@@ -81,6 +87,10 @@ impl UserFun {
|
||||
local.index().to_string(),
|
||||
global_sym_lookup(self.locals()[local.index()]).unwrap().to_string(),
|
||||
),
|
||||
Inst::LoadGlobal(global) => (
|
||||
global.index().to_string(),
|
||||
global_sym_lookup(globals[global.index()]).unwrap().to_string(),
|
||||
),
|
||||
Inst::PopLocal(local) => {
|
||||
if let Some(local) = local {
|
||||
let index = local.index();
|
||||
@@ -133,7 +143,38 @@ impl UserFun {
|
||||
}
|
||||
}
|
||||
|
||||
impl_obj!(UserFun);
|
||||
impl Obj for UserFun {
|
||||
fn vtable(&self) -> &Vtable {
|
||||
&self.vtable
|
||||
}
|
||||
|
||||
fn attrs(&self) -> &Attrs {
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
fn attrs_mut(&mut self) -> Option<&mut Attrs> {
|
||||
Some(&mut self.attrs)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_fun(&self) -> Option<&dyn Fun> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Fun for UserFun {
|
||||
fn create_frame(&self, callee: ObjRef, vm: &Vm, args: Vec<ObjRef>) -> Frame {
|
||||
let bindings: FrameBindings = args.into_iter()
|
||||
.enumerate()
|
||||
.collect();
|
||||
Frame::User(
|
||||
UserFrame::new(callee, bindings, vm.pc(), Arc::clone(&self.code))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for UserFun {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
@@ -151,7 +192,7 @@ pub static USER_FUN_TY: Lazy<ObjRef<Ty>> = Lazy::new(|| Ty::new_obj(USER_FUN_NAM
|
||||
// struct NativeFun
|
||||
//
|
||||
|
||||
pub type NativeFunPtr = Box<dyn (Fn(ObjRef, &mut Vm, Vec<ObjRef>) -> Signal) + Send + Sync>;
|
||||
pub type NativeFunPtr = fn(ObjRef, &mut Vm, Vec<ObjRef>) -> Signal;
|
||||
pub type NativeFunRef = ObjRef<NativeFun>;
|
||||
|
||||
#[derive(Scan)]
|
||||
@@ -207,24 +248,34 @@ impl Debug for NativeFun {
|
||||
}
|
||||
}
|
||||
|
||||
impl_obj!(NativeFun);
|
||||
impl Obj for NativeFun {
|
||||
fn vtable(&self) -> &Vtable {
|
||||
&self.vtable
|
||||
}
|
||||
|
||||
fn attrs(&self) -> &Attrs {
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
fn attrs_mut(&mut self) -> Option<&mut Attrs> {
|
||||
None
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_fun(&self) -> Option<&dyn Fun> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Fun for NativeFun {
|
||||
fn create_frame(&self, callee: ObjRef, _vm: &Vm, args: Vec<ObjRef>) -> Frame {
|
||||
Frame::Native(
|
||||
NativeFrame::new(callee, *self.fun, args)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub static NATIVE_FUN_TY: Lazy<ObjRef<Ty>> = Lazy::new(|| Ty::new_obj(NATIVE_FUN_NAME.sym_ref()));
|
||||
|
||||
//
|
||||
// Native function defs
|
||||
//
|
||||
|
||||
// __access__ is what the "dot" operator calls
|
||||
// __get_attr__ *should* always bypass the __access__ function and get an attribute directly
|
||||
|
||||
pub static GET_ATTR_MEMBER_FUN: Lazy<ObjRef<NativeFun>> = Lazy::new(|| {
|
||||
NativeFun::new_obj(Box::new(|_caller, _vm, _args| {
|
||||
/*
|
||||
let sym_ref = vm.pop();
|
||||
let obj_ref = vm.pop();
|
||||
obj_ref.access()
|
||||
*/
|
||||
todo!("__get_attr__ function")
|
||||
}))
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user