summaryrefslogtreecommitdiff
path: root/matrix-lang/src/vm.rs
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-02-29 17:04:28 -0500
committerFreya Murphy <freya@freyacat.org>2024-02-29 17:04:28 -0500
commit5d2747e26f51cc2344a6bd95f93457248fdfebd8 (patch)
tree8755b4068166c3854d26817683ce438a771ab319 /matrix-lang/src/vm.rs
parentmore mat, sys, and os stdlib functions, better matrix printing, other fixes (diff)
downloadmatrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.tar.gz
matrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.tar.bz2
matrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.zip
fin prob
Diffstat (limited to '')
-rw-r--r--matrix-lang/src/vm.rs (renamed from matrix/src/vm.rs)85
1 files changed, 28 insertions, 57 deletions
diff --git a/matrix/src/vm.rs b/matrix-lang/src/vm.rs
index e511adf..bac6341 100644
--- a/matrix/src/vm.rs
+++ b/matrix-lang/src/vm.rs
@@ -1,33 +1,6 @@
-use std::{rc::Rc, fmt::{Debug, Display}, usize, ops::{Index, IndexMut}, collections::HashMap, cell::RefCell, sync::{atomic::{AtomicUsize, Ordering}, Arc}};
-use crate::{value::{Value, self, ValueMap, Matrix}, Result, gc::Gc, chunk::{Function, Instruction, Chunk, InnerFunction}, compiler::NamesTable, native};
+use std::{fmt::Display, ops::{IndexMut, Index}, sync::{atomic::{AtomicUsize, Ordering}, Arc}, collections::HashMap};
+use crate::prelude::*;
-#[derive(Debug)]
-pub enum Error {
- ValueError(value::Error),
- NotFunction(Value),
- InvArity(usize, usize, Rc<str>),
- ExecNative,
-}
-
-impl std::error::Error for Error {}
-
-impl Display for Error {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use Error::*;
- match self {
- ValueError(err) => write!(f, "{err}"),
- NotFunction(v) => write!(f, "{v:?} is not a function"),
- InvArity(wanted, had, name) => write!(f, "function {name} takes {wanted} params but was given {had}"),
- ExecNative => write!(f, "cannot execute a native function"),
- }
- }
-}
-
-impl From<value::Error> for Error {
- fn from(value: value::Error) -> Self {
- Error::ValueError(value)
- }
-}
pub struct Stack<T> {
inner: Vec<T>
}
@@ -99,12 +72,12 @@ pub struct StackFrame {
}
struct VmError {
- err: crate::Error,
+ err: Exception,
frames: Vec<StackFrame>
}
-impl From<crate::Error> for VmError {
- fn from(err: crate::Error) -> Self {
+impl From<Exception> for VmError {
+ fn from(err: Exception) -> Self {
VmError {
err,
frames: Vec::new()
@@ -112,15 +85,6 @@ impl From<crate::Error> for VmError {
}
}
-impl From<self::Error> for VmError {
- fn from(err: self::Error) -> Self {
- VmError {
- err: err.into(),
- frames: Vec::new()
- }
- }
-}
-
type VmResult<T> = std::result::Result<T, VmError>;
impl StackFrame {
@@ -166,10 +130,16 @@ pub struct Vm {
trystack: Vec<TryScope>,
globals: Rc<RefCell<HashMap<u16, Value>>>,
names: NamesTable,
- global_names: NamesTable,
+ global_names: GlobalsTable,
interupt: Arc<AtomicUsize>,
}
+macro_rules! error {
+ ($($arg:tt)*) => {
+ exception!(RUNTIME_EXCEPTION, $($arg)*)
+ };
+}
+
impl Vm {
fn push(&mut self, val: Value) {
@@ -188,7 +158,7 @@ impl Vm {
self.names.clone()
}
- pub fn global_names(&self) -> NamesTable {
+ pub fn globals(&self) -> GlobalsTable {
self.global_names.clone()
}
@@ -210,7 +180,7 @@ impl Vm {
pub fn load_global(&mut self, value: Value, name: &str) {
let idx = self.global_names.borrow().len();
- self.global_names.borrow_mut().push(name.into());
+ self.global_names.borrow_mut().push(Global { idx, name: Rc::from(name), is_const: true });
self.globals.borrow_mut().insert(idx as u16, value);
}
@@ -220,7 +190,7 @@ impl Vm {
fn init_frame(&mut self, fun: Rc<Function>) -> Result<StackFrame> {
let InnerFunction::Compiled(ref compiled_chunk) = fun.fun else {
- return Err(self::Error::ExecNative.into())
+ return Err(error!("cannot create stack frame on builtin function"))
};
Ok(StackFrame::new(
self,
@@ -240,7 +210,7 @@ impl Vm {
match ins {
I::NoOp => {},
I::CreateLocal => self.locals.push(self.stack.pop()),
- I::LoadLocal(idx) => {self.stack.push(self.locals[idx as usize].clone());},
+ I::LoadLocal(idx) => {self.stack.push(self.locals[frame.lp + idx as usize].clone());},
I::StoreLocal(idx) => self.locals[frame.bp + idx as usize] = self.pop(),
I::DiscardLocals(count) => {self.locals.truncate(self.locals.len() - count as usize)},
I::LoadGlobal(idx) => {
@@ -325,11 +295,12 @@ impl Vm {
let fun = self.pop();
let Value::Function(fun) = fun else {
- return Err(Error::NotFunction(fun).into())
+ Err(error!("cannot call {fun} (not a function)"))?
};
if !fun.variadic && arity > fun.arity {
- return Err(Error::InvArity(fun.arity, arity as usize, fun.name.clone()).into())
+ let needs = fun.arity;
+ Err(error!("function {fun} takes {needs} args, given {arity}"))?
}
let mut params = self.stack.split_off(self.stack.len() - arity).inner;
@@ -416,14 +387,14 @@ impl Vm {
Ok(None)
}
- fn stack_trace(&mut self, frames: Vec<StackFrame>) -> String {
- let mut trace = String::from("\x1b[33m\x1b[1mStack Trace:\x1b[0m\n");
+ fn stack_trace(&mut self, frames: Vec<StackFrame>, e: Exception) -> Exception {
+ let mut e = e;
for frame in frames {
let ip = frame.ip - 1;
let pos = frame.body.pos[ip];
- trace.push_str(&format!(" {} at {}:{}\n", &frame.name, pos.row, pos.col));
+ e = e.trace(frame.name, pos);
}
- trace
+ e
}
fn exec_fn(&mut self, frame: &mut StackFrame, fun: Rc<Function>, params: Vec<Value>) -> VmResult<Value> {
@@ -438,7 +409,8 @@ impl Vm {
self.stack.push(param);
}
let mut new_frame = StackFrame::new(self, name, body.clone(), params_len, frame.depth + 1);
- self.exec(&mut new_frame)
+ let res = self.exec(&mut new_frame);
+ res
},
InnerFunction::Native(native_fun) => {
Ok(native_fun((self, frame), params)?)
@@ -462,7 +434,7 @@ impl Vm {
self.stack.truncate(catch.stack_len);
self.locals.truncate(catch.locals_len);
frame.ip = catch.err_idx;
- self.stack.push(Value::Error(err.err));
+ self.stack.push(Value::Exception(err.err));
} else {
let mut err = err;
err.frames.push(frame.clone());
@@ -478,13 +450,12 @@ impl Vm {
}
pub fn run(&mut self, fun: Rc<Function>) -> Result<Value> {
- let mut frame = self.init_frame(fun)?;
self.interupt.store(0, Ordering::SeqCst);
self.stack = Stack::new();
self.locals = Stack::new();
+ let mut frame = self.init_frame(fun)?;
self.exec(&mut frame).map_err(|e| {
- let trace = self.stack_trace(e.frames);
- (e.err, trace).into()
+ self.stack_trace(e.frames, e.err)
})
}
}