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:
2020-09-28 16:48:30 -07:00
parent 958a6caabb
commit 43c4a9c531
4 changed files with 79 additions and 57 deletions

View File

@@ -2,39 +2,33 @@ pub mod consts;
pub mod error; // TODO : not needed?
pub mod frame;
pub mod inst;
pub mod package;
pub(crate) mod signal;
use crate::{
obj::{reserved::*, prelude::*},
vm::{frame::*, inst::*, package::*, signal::*},
vm::{consts::ConstPool, frame::*, inst::*, signal::*},
};
#[derive(Debug)]
pub struct Vm<'p> {
pub struct Vm<'c> {
stack: Vec<ObjRef>,
frames: Vec<Frame>,
pc: usize,
condition: bool,
package: &'p Package,
const_pool: &'c ConstPool,
}
impl<'p> Vm<'p> {
pub fn new(package: &'p Package) -> Self {
impl<'c> Vm<'c> {
pub fn new(const_pool: &'c ConstPool,) -> Self {
Self {
stack: Default::default(),
frames: vec![],
pc: 0,
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.
pub fn frame(&self) -> Option<&Frame> {
self.frames.last()
@@ -198,10 +192,7 @@ impl<'p> Vm<'p> {
self.push(sym_ref);
}
Inst::PushConst(hdl) => {
let obj_ref = self.package()
.const_pool()
.get(hdl)
.clone();
let obj_ref = self.const_pool.get(hdl).clone();
self.push(obj_ref);
}
Inst::LoadLocal(local) => {
@@ -277,18 +268,54 @@ impl<'p> Vm<'p> {
Inst::Call(argc) => {
let stack_top = self.stack.len() - argc;
let args = self.stack.split_off(stack_top);
let caller = self.pop().unwrap();
signal = Some(Signal::Call(caller, args));
let tos = self.pop()
.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::Return => { signal = Some(Signal::Return); }
Inst::UnNeg => todo!(),
Inst::UnPos => todo!(),
Inst::BinPlus => todo!(),
Inst::BinMinus => todo!(),
Inst::BinMul => todo!(),
Inst::BinPlus => {
let rhs = self.pop().unwrap();
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::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::BinLt => todo!(),
Inst::BinLe => todo!(),