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:
47
src/vm/consts.rs
Normal file
47
src/vm/consts.rs
Normal 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
6
src/vm/frame.rs
Normal 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
111
src/vm/inst.rs
Normal 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
52
src/vm/mod.rs
Normal 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,
|
||||
}
|
||||
Reference in New Issue
Block a user