Fold runtime/ crate into this source tree

While I like the idea of having a runtime completely decoupled from the
syntax and compiler, I don't think this is that big of a project for
that to be necessary or even useful yet.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-09-14 14:14:21 -07:00
parent 8e2cbb10a4
commit 372e58f620
21 changed files with 12 additions and 25 deletions

47
src/vm/consts.rs Normal file
View File

@@ -0,0 +1,47 @@
use crate::obj::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConstHandle(usize);
impl ConstHandle {
pub fn index(&self) -> usize {
self.0
}
pub fn new(handle: usize) -> Self {
ConstHandle(handle)
}
}
#[derive(Debug, Default)]
pub struct ConstPool {
pool: Vec<ObjRef>,
}
impl ConstPool {
pub fn new() -> Self {
Default::default()
}
pub fn push(&mut self, value: ObjRef) -> ConstHandle {
let hdl = ConstHandle::new(self.pool.len());
self.pool.push(value);
hdl
}
pub fn get(&self, hdl: ConstHandle) -> &ObjRef {
self.pool.get(hdl.index()).unwrap()
}
pub fn len(&self) -> usize {
self.pool.len()
}
}
impl std::ops::Index<ConstHandle> for ConstPool {
type Output = ObjRef;
fn index(&self, hdl: ConstHandle) -> &Self::Output {
self.get(hdl)
}
}

6
src/vm/frame.rs Normal file
View File

@@ -0,0 +1,6 @@
/// A stack call frame.
#[derive(Default, Debug, Clone)]
pub struct Frame {
last_pc: usize,
stack_base: usize,
}

111
src/vm/inst.rs Normal file
View File

@@ -0,0 +1,111 @@
use crate::{obj::prelude::*, vm::consts::ConstHandle};
#[derive(Debug, PartialEq)]
pub enum Inst {
/// Push a literal symbol object to the stack.
PushSym(Sym),
/// Push a const value reference to the stack.
PushConst(ConstHandle),
/// Looks up and pushes a local value.
PushLocal(Sym),
/// Pop a value from the stack, possibly into a local symbol.
Pop(Option<Sym>),
/// Pops a symbol value and an object reference.
///
/// This will get an attr from the object reference pointed to by the symbol.
GetAttr(Sym),
/// A target reference and a source reference from the stack.
///
/// The target reference will have the given symbol attribute assigned to the source.
///
/// In code, it would look like this:
///
/// target.symbol = source
///
SetAttr(Sym),
/// Jump to a given address in the current function unconditionally.
Jump(usize),
/// Jump to a given address in the current function if the condition flag is true.
///
/// The condition flag may be set by an internal function.
JumpTrue(usize),
/// Calls a function with the supplied number of arguments.
///
/// The stack, from bottom to top, should contain the function followed by the arguments.
///
/// After the function has returned, the VM will have popped the arguments and function
/// pointer, and the return value will be on top of the stack.
Call(usize),
/// Indexes a value, e.g. a list or a dict.
///
/// The stack, from bottom to top, should have the expression being indexed, and then the
/// indexed value.
Index,
/// Pops the top value from the stack, and returns from the function, using the popped value as
/// a return value.
Return,
/// Replaces the top stack value with its negation applied.
UnNeg,
/// Replaces the top stack value with its absolute value applied.
UnPos,
/// Pops the top two items off of the stack, and applies the binary addition operator to them,
/// pushing the result to the stack.
BinPlus,
/// Pops the top two items off of the stack, and applies the binary subtraction operator to
/// them, pushing the result to the stack.
BinMinus,
/// Pops the top two items off of the stack, and applies the binary multiplication operator to
/// them, pushing the result to the stack.
BinMul,
/// Pops the top two items off of the stack, and applies the binary division operator to them,
/// pushing the result to the stack.
BinDiv,
/// Pops the top two items off of the stack, and applies the boolean equality operator to them,
/// pushing the result to the stack.
BinEq,
/// Pops the top two items off of the stack, and applies the boolean inequality operator to
/// them, pushing the result to the stack.
BinNeq,
/// Pops the top two items off of the stack, and applies the boolean less-than operator to
/// them, pushing the result to the stack.
BinLt,
/// Pops the top two items off of the stack, and applies the binary less-than or equals
/// operator to them, pushing the result to the stack.
BinLe,
/// Pops the top two items off of the stack, and applies the boolean greater-than operator to
/// them, pushing the result to the stack.
BinGt,
/// Pops the top two items off of the stack, and applies the binary greater-than or equals
/// operator to them, pushing the result to the stack.
BinGe,
/// Pops the top two items off of the stack, and applies the boolean and operator to them,
/// pushing the result to the stack.
BinAnd,
/// Pops the top two items off of the stack, and applies the boolean or operator to them,
/// pushing the result to the stack.
BinOr,
}

52
src/vm/mod.rs Normal file
View File

@@ -0,0 +1,52 @@
mod frame;
pub mod inst;
pub mod consts;
use crate::obj::prelude::*;
use frame::*;
#[derive(Debug)]
pub struct Vm {
stack: Vec<ObjRef>,
frames: Vec<Frame>,
pc: usize,
condition: bool,
}
impl Vm {
pub fn new() -> Self {
Self {
stack: Default::default(),
frames: vec![Default::default()], // Start with a root stack frame
pc: 0,
condition: false,
}
}
pub fn stack(&self) -> &Vec<ObjRef> {
&self.stack
}
pub fn stack_mut(&mut self) -> &mut Vec<ObjRef> {
&mut self.stack
}
pub fn push(&mut self, value: ObjRef) {
self.stack_mut().push(value);
}
pub fn pop(&mut self) -> Option<ObjRef> {
self.stack_mut().pop()
}
pub fn pc(&self) -> usize {
self.pc
}
pub fn condition(&self) -> bool {
self.condition
}
//pub fn new_local(&mut self, name: String,
}