diff --git a/src/lib.rs b/src/lib.rs index 30db747..ce5287d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ mod errors; mod gc; mod lex; mod parse; +mod util; mod vm; use crate::ast::Program; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..d94af05 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,9 @@ +/// Statically asserts that the size of the type is x bytes big (on 64-bit) +macro_rules! assert_size { + ($name:ident == $size:expr) => { + #[cfg(target_pointer_width = "64")] + const _: [(); $size] = [(); ::std::mem::size_of::<$name>()]; + }; +} + +pub(crate) use assert_size; diff --git a/src/vm.rs b/src/vm.rs index 01270bc..7db04b4 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,13 +1,16 @@ use crate::bytecode::{FnBlock, Function, Instr}; use crate::gc::{Object, RtAlloc, Symbol}; +use crate::util; use crate::Config; use std::fmt::{Debug, Display, Formatter}; use std::io::{Read, Write}; use std::ptr::NonNull; -type VmError = &'static str; +type VmError = Box<&'static str>; type VmResult = Result<(), VmError>; +util::assert_size!(VmResult == 8); + pub fn execute<'bc>( bytecode: &'bc [FnBlock<'bc>], alloc: RtAlloc, @@ -49,8 +52,7 @@ pub enum Value { NativeU(usize), } -#[cfg(target_pointer_width = "64")] -const _: [(); 24] = [(); std::mem::size_of::()]; +util::assert_size!(Value == 24); #[derive(Debug, Clone, Copy)] pub struct Ptr(NonNull<()>); @@ -114,51 +116,51 @@ impl<'bc> Vm<'bc, '_> { } Instr::BinAdd => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Num(a + b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::BinSub => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Num(a - b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::BinMul => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Num(a * b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::BinDiv => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Num(a / b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::BinMod => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Num(a % b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::BinAnd => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Bool(a), Value::Bool(b)) => Ok(Value::Bool(a && b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::BinOr => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Bool(a), Value::Bool(b)) => Ok(Value::Bool(a || b)), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::CmpGreater => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a > b)), (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() > b.as_str())), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::CmpGreaterEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a >= b)), (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() >= b.as_str())), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::CmpLess => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a < b)), (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() < b.as_str())), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::CmpLessEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a <= b)), (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() <= b.as_str())), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::CmpEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Null, Value::Null) => Ok(TRUE), @@ -166,7 +168,7 @@ impl<'bc> Vm<'bc, '_> { (Value::String(a), Value::String(b)) => Ok(Value::Bool(a == b)), (Value::Object(_a), Value::Object(_b)) => todo!(), (Value::Array, Value::Array) => Ok(TRUE), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::CmpNotEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { (Value::Null, Value::Null) => Ok(FALSE), @@ -174,7 +176,7 @@ impl<'bc> Vm<'bc, '_> { (Value::String(a), Value::String(b)) => Ok(Value::Bool(a != b)), (Value::Object(_a), Value::Object(_b)) => todo!(), (Value::Array, Value::Array) => Ok(FALSE), - _ => Err("bad type"), + _ => Err("bad type".into()), })?, Instr::Print => { let val = self.stack.pop().unwrap(); @@ -185,7 +187,7 @@ impl<'bc> Vm<'bc, '_> { match val { Value::Bool(false) => self.pc = (self.pc as isize + pos) as usize, Value::Bool(true) => {} - _ => return Err("bad type"), + _ => return Err("bad type".into()), } } Instr::Jmp(pos) => self.pc = (self.pc as isize + pos) as usize, @@ -236,14 +238,14 @@ impl<'bc> Vm<'bc, '_> { // TODO don't be recursive like this self.execute_function()?; } else { - return Err("not a function"); + return Err("not a function".into()); } Ok(()) } fn type_error(&self) -> VmError { - "bad type" + "bad type".into() } fn step_debug(&self) { diff --git a/test.dil b/test.dil index d600ad6..4462d5f 100644 --- a/test.dil +++ b/test.dil @@ -1,5 +1,5 @@ -fn hello(uwu) { - 3 + 1; -} +let i = 0; -let yeah = hello; \ No newline at end of file +while i < 100_000_000 { + i = i + 1; +} \ No newline at end of file