diff options
author | Freya Murphy <freya@freyacat.org> | 2024-02-29 17:04:28 -0500 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2024-02-29 17:04:28 -0500 |
commit | 5d2747e26f51cc2344a6bd95f93457248fdfebd8 (patch) | |
tree | 8755b4068166c3854d26817683ce438a771ab319 /matrix-lang/src/vm.rs | |
parent | more mat, sys, and os stdlib functions, better matrix printing, other fixes (diff) | |
download | matrix-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) }) } } |