Initial commit
Includes: runtime base from a previous project, syn(tax) module with parser and lexer Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
111
runtime/src/obj/fun.rs
Normal file
111
runtime/src/obj/fun.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use crate::{obj::{names::*, prelude::*}, vm::{inst::Inst, Vm}};
|
||||
use once_cell::sync::Lazy;
|
||||
use shredder::{GcSafeWrapper, Scan};
|
||||
use std::fmt::{Debug, Formatter, self};
|
||||
|
||||
//
|
||||
// struct UserFun
|
||||
//
|
||||
#[derive(Scan)]
|
||||
pub struct UserFun {
|
||||
attrs: Attrs,
|
||||
// Safe because Vec<Inst> doesn't need to be scanned
|
||||
#[shredder(unsafe_skip)]
|
||||
code: Vec<Inst>,
|
||||
// Safe because this is just an interner that points to symbols, which aren't GC'd
|
||||
#[shredder(unsafe_skip)]
|
||||
locals: Locals,
|
||||
}
|
||||
|
||||
impl UserFun {
|
||||
pub fn code(&self) -> &Vec<Inst> {
|
||||
&self.code
|
||||
}
|
||||
|
||||
pub fn locals(&self) -> &Locals {
|
||||
&self.locals
|
||||
}
|
||||
}
|
||||
|
||||
impl_obj!(UserFun, attrs);
|
||||
|
||||
impl Debug for UserFun {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("UserFun")
|
||||
.field("attrs", &self.attrs)
|
||||
.field("code", &self.code)
|
||||
.field("locals", &self.locals)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// struct NativeFun
|
||||
//
|
||||
|
||||
#[derive(Scan)]
|
||||
pub struct NativeFun {
|
||||
#[shredder(skip)]
|
||||
fun: GcSafeWrapper<Box<dyn Fn(&mut Vm) + Send + Sync>>,
|
||||
attrs: Attrs,
|
||||
}
|
||||
|
||||
//
|
||||
// impl NativeFun
|
||||
//
|
||||
|
||||
impl NativeFun {
|
||||
pub fn new(fun: Box<dyn Fn(&mut Vm) + Send + Sync>) -> ObjRef<Self> {
|
||||
let obj_ref = ObjRef::new(Self {
|
||||
fun: GcSafeWrapper::new(fun),
|
||||
attrs: Default::default(),
|
||||
});
|
||||
|
||||
{
|
||||
write_obj!(let obj = obj_ref);
|
||||
obj.set_attr(*CALL_MEMBER_SYM, obj_ref.clone());
|
||||
obj.set_attr(*GET_ATTR_MEMBER_SYM, GET_ATTR_MEMBER_FUN.clone());
|
||||
}
|
||||
|
||||
obj_ref
|
||||
}
|
||||
|
||||
pub fn call(&self, vm: &mut Vm) {
|
||||
(self.fun)(vm)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// impl Debug for NativeFun
|
||||
//
|
||||
|
||||
impl Debug for NativeFun {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("NativeFun")
|
||||
.field("fun", &format!("(function at {:x})", &self.fun as *const _ as usize))
|
||||
.field("attrs", &self.attrs)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl_obj!(NativeFun, attrs);
|
||||
|
||||
//
|
||||
// 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(Box::new(|_vm| {
|
||||
/*
|
||||
* TODO - need SymObj or something like that, which can be used as an ObjRef - since that's
|
||||
* all we'll have access to at runtime anyway
|
||||
let sym_ref = vm.pop();
|
||||
let obj_ref = vm.pop();
|
||||
obj_ref.access()
|
||||
*/
|
||||
todo!("__get_attr__ function")
|
||||
}))
|
||||
});
|
||||
Reference in New Issue
Block a user