Remove vm::package module, add object attribute shortcut methods
* vm::package is no longer needed since the compiler now creates UserFunRef objects * Reserved object attributes can be accessed using get_* methods, e.g. get_plus for ease of use. * Add some implementations for operator instructions in the VM Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -25,12 +25,21 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use attrs::*;
|
use attrs::*;
|
||||||
|
use reserved::*;
|
||||||
use sym::Sym;
|
use sym::Sym;
|
||||||
|
|
||||||
//
|
//
|
||||||
// trait Obj
|
// trait Obj
|
||||||
//
|
//
|
||||||
|
|
||||||
|
macro_rules! obj_attr {
|
||||||
|
($name:ident, $attr:ident) => {
|
||||||
|
fn $name(&self) -> Option<ObjRef> {
|
||||||
|
self.get_attr($attr.sym)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Obj: Scan + std::fmt::Debug {
|
pub trait Obj: Scan + std::fmt::Debug {
|
||||||
fn vtable(&self) -> &Vtable;
|
fn vtable(&self) -> &Vtable;
|
||||||
fn attrs(&self) -> &Attrs;
|
fn attrs(&self) -> &Attrs;
|
||||||
@@ -44,6 +53,24 @@ pub trait Obj: Scan + std::fmt::Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn std::any::Any;
|
fn as_any(&self) -> &dyn std::any::Any;
|
||||||
|
|
||||||
|
obj_attr!(get_ty, TY_MEMBER_NAME);
|
||||||
|
obj_attr!(get_call, CALL_MEMBER_NAME);
|
||||||
|
obj_attr!(get_name, NAME_MEMBER_NAME);
|
||||||
|
//obj_attr!(get_get_attr, GET_ATTR_NAME);
|
||||||
|
//obj_attr!(get_set_attr, SET_ATTR_NAME);
|
||||||
|
obj_attr!(get_self, SELF_MEMBER_NAME);
|
||||||
|
obj_attr!(get_func, FUNC_MEMBER_NAME);
|
||||||
|
obj_attr!(get_eq, EQ_OP_NAME);
|
||||||
|
obj_attr!(get_ne, NE_OP_NAME);
|
||||||
|
obj_attr!(get_lt, LT_OP_NAME);
|
||||||
|
obj_attr!(get_gt, GT_OP_NAME);
|
||||||
|
obj_attr!(get_le, LT_EQ_OP_NAME);
|
||||||
|
obj_attr!(get_ge, GT_EQ_OP_NAME);
|
||||||
|
obj_attr!(get_plus, PLUS_OP_NAME);
|
||||||
|
obj_attr!(get_minus, MINUS_OP_NAME);
|
||||||
|
obj_attr!(get_mul, TIMES_OP_NAME);
|
||||||
|
obj_attr!(get_div, DIV_OP_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ name!(FUNC_MEMBER_NAME, "__func__");
|
|||||||
//
|
//
|
||||||
// Predefined VM-aware symbols
|
// Predefined VM-aware symbols
|
||||||
//
|
//
|
||||||
name!(SCOPE_NAME, "__scope__");
|
//name!(SCOPE_NAME, "__scope__");
|
||||||
|
|
||||||
//
|
//
|
||||||
// Builtin functions
|
// Builtin functions
|
||||||
@@ -64,7 +64,8 @@ name!(FALSE_NAME, "false");
|
|||||||
name!(NIL_NAME, "nil");
|
name!(NIL_NAME, "nil");
|
||||||
|
|
||||||
// Operator function names
|
// Operator function names
|
||||||
name!(EQ_EQ_OP_NAME, "__eq__");
|
name!(EQ_OP_NAME, "__eq__");
|
||||||
|
name!(NE_OP_NAME, "__ne__");
|
||||||
name!(LT_OP_NAME, "__lt__");
|
name!(LT_OP_NAME, "__lt__");
|
||||||
name!(GT_OP_NAME, "__gt__");
|
name!(GT_OP_NAME, "__gt__");
|
||||||
name!(LT_EQ_OP_NAME, "__le__");
|
name!(LT_EQ_OP_NAME, "__le__");
|
||||||
|
|||||||
@@ -2,39 +2,33 @@ pub mod consts;
|
|||||||
pub mod error; // TODO : not needed?
|
pub mod error; // TODO : not needed?
|
||||||
pub mod frame;
|
pub mod frame;
|
||||||
pub mod inst;
|
pub mod inst;
|
||||||
pub mod package;
|
|
||||||
pub(crate) mod signal;
|
pub(crate) mod signal;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::{reserved::*, prelude::*},
|
obj::{reserved::*, prelude::*},
|
||||||
vm::{frame::*, inst::*, package::*, signal::*},
|
vm::{consts::ConstPool, frame::*, inst::*, signal::*},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Vm<'p> {
|
pub struct Vm<'c> {
|
||||||
stack: Vec<ObjRef>,
|
stack: Vec<ObjRef>,
|
||||||
frames: Vec<Frame>,
|
frames: Vec<Frame>,
|
||||||
pc: usize,
|
pc: usize,
|
||||||
condition: bool,
|
condition: bool,
|
||||||
package: &'p Package,
|
const_pool: &'c ConstPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Vm<'p> {
|
impl<'c> Vm<'c> {
|
||||||
pub fn new(package: &'p Package) -> Self {
|
pub fn new(const_pool: &'c ConstPool,) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stack: Default::default(),
|
stack: Default::default(),
|
||||||
frames: vec![],
|
frames: vec![],
|
||||||
pc: 0,
|
pc: 0,
|
||||||
condition: false,
|
condition: false,
|
||||||
package,
|
const_pool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the package that is currently loaded by this VM.
|
|
||||||
pub fn package(&self) -> &'p Package {
|
|
||||||
self.package
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the current stack frame, if any.
|
/// Gets the current stack frame, if any.
|
||||||
pub fn frame(&self) -> Option<&Frame> {
|
pub fn frame(&self) -> Option<&Frame> {
|
||||||
self.frames.last()
|
self.frames.last()
|
||||||
@@ -198,10 +192,7 @@ impl<'p> Vm<'p> {
|
|||||||
self.push(sym_ref);
|
self.push(sym_ref);
|
||||||
}
|
}
|
||||||
Inst::PushConst(hdl) => {
|
Inst::PushConst(hdl) => {
|
||||||
let obj_ref = self.package()
|
let obj_ref = self.const_pool.get(hdl).clone();
|
||||||
.const_pool()
|
|
||||||
.get(hdl)
|
|
||||||
.clone();
|
|
||||||
self.push(obj_ref);
|
self.push(obj_ref);
|
||||||
}
|
}
|
||||||
Inst::LoadLocal(local) => {
|
Inst::LoadLocal(local) => {
|
||||||
@@ -277,18 +268,54 @@ impl<'p> Vm<'p> {
|
|||||||
Inst::Call(argc) => {
|
Inst::Call(argc) => {
|
||||||
let stack_top = self.stack.len() - argc;
|
let stack_top = self.stack.len() - argc;
|
||||||
let args = self.stack.split_off(stack_top);
|
let args = self.stack.split_off(stack_top);
|
||||||
let caller = self.pop().unwrap();
|
let tos = self.pop()
|
||||||
signal = Some(Signal::Call(caller, args));
|
.expect("stack underflow");
|
||||||
|
read_obj!(let tos = tos);
|
||||||
|
let callee = tos.get_call()
|
||||||
|
.expect("TODO: throw an error for missing __call__ attr");
|
||||||
|
signal = Some(Signal::Call(callee, args));
|
||||||
}
|
}
|
||||||
Inst::Index => todo!(),
|
Inst::Index => todo!(),
|
||||||
Inst::Return => { signal = Some(Signal::Return); }
|
Inst::Return => { signal = Some(Signal::Return); }
|
||||||
Inst::UnNeg => todo!(),
|
Inst::UnNeg => todo!(),
|
||||||
Inst::UnPos => todo!(),
|
Inst::UnPos => todo!(),
|
||||||
Inst::BinPlus => todo!(),
|
Inst::BinPlus => {
|
||||||
Inst::BinMinus => todo!(),
|
let rhs = self.pop().unwrap();
|
||||||
Inst::BinMul => todo!(),
|
let lhs = self.pop().unwrap();
|
||||||
|
let fun = {
|
||||||
|
read_obj!(let lhs = lhs);
|
||||||
|
lhs.get_plus().expect("TODO: throw an error for missing __plus__ attr")
|
||||||
|
};
|
||||||
|
signal = Some(Signal::Call(fun, vec![lhs, rhs]));
|
||||||
|
}
|
||||||
|
Inst::BinMinus => {
|
||||||
|
let rhs = self.pop().unwrap();
|
||||||
|
let lhs = self.pop().unwrap();
|
||||||
|
let fun = {
|
||||||
|
read_obj!(let lhs = lhs);
|
||||||
|
lhs.get_minus().expect("TODO: throw an error for missing __minus__ attr")
|
||||||
|
};
|
||||||
|
signal = Some(Signal::Call(fun, vec![lhs, rhs]));
|
||||||
|
}
|
||||||
|
Inst::BinMul => {
|
||||||
|
let rhs = self.pop().unwrap();
|
||||||
|
let lhs = self.pop().unwrap();
|
||||||
|
let fun = {
|
||||||
|
read_obj!(let lhs = lhs);
|
||||||
|
lhs.get_mul().expect("TODO: throw an error for missing __mul__ attr")
|
||||||
|
};
|
||||||
|
signal = Some(Signal::Call(fun, vec![lhs, rhs]));
|
||||||
|
}
|
||||||
Inst::BinDiv => todo!(),
|
Inst::BinDiv => todo!(),
|
||||||
Inst::BinEq => todo!(),
|
Inst::BinEq => {
|
||||||
|
let rhs = self.pop().unwrap();
|
||||||
|
let lhs = self.pop().unwrap();
|
||||||
|
let fun = {
|
||||||
|
read_obj!(let lhs = lhs);
|
||||||
|
lhs.get_eq().expect("TODO: throw an error for missing __eq__ attr")
|
||||||
|
};
|
||||||
|
signal = Some(Signal::Call(fun, vec![lhs, rhs]));
|
||||||
|
}
|
||||||
Inst::BinNeq => todo!(),
|
Inst::BinNeq => todo!(),
|
||||||
Inst::BinLt => todo!(),
|
Inst::BinLt => todo!(),
|
||||||
Inst::BinLe => todo!(),
|
Inst::BinLe => todo!(),
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
use crate::{obj::prelude::*, vm::{consts::ConstPool, inst::Inst}};
|
|
||||||
use shredder::Scan;
|
|
||||||
|
|
||||||
/// A compiled package that can be executed by a VM.
|
|
||||||
#[derive(Scan, Debug)]
|
|
||||||
pub struct Package {
|
|
||||||
names: Vec<Sym>, // local names mappings
|
|
||||||
const_pool: ConstPool,
|
|
||||||
code: Vec<Inst>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Package {
|
|
||||||
/// Creates a new VM executable package with the given local name mappings, constant pool, and
|
|
||||||
/// executable code.
|
|
||||||
pub fn new(names: Vec<Sym>, const_pool: ConstPool, code: Vec<Inst>) -> Self {
|
|
||||||
Self { names, const_pool, code, }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the local name mappings for this package.
|
|
||||||
pub fn names(&self) -> &Vec<Sym> {
|
|
||||||
&self.names
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the constant pool that is used by this package.
|
|
||||||
pub fn const_pool(&self) -> &ConstPool {
|
|
||||||
&self.const_pool
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the executable code that was compiled for this package.
|
|
||||||
pub fn code(&self) -> &Vec<Inst> {
|
|
||||||
&self.code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user