diff options
Diffstat (limited to 'src/vm.rs')
| -rw-r--r-- | src/vm.rs | 271 |
1 files changed, 7 insertions, 264 deletions
@@ -1,16 +1,15 @@ -use owo_colors::OwoColorize; -use std::collections::HashMap; +use std::cell::RefCell; use std::collections::hash_map::Entry; +use std::collections::HashMap; use std::fmt::Debug; -use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::cell::RefCell; -pub use crate::compiler::Type; +use owo_colors::OwoColorize; -use crate::compiler::RustFunction; +use crate::{Blob, Block, Op, Prog, UpValue, Value}; use crate::error::{Error, ErrorKind}; -use crate::compiler::{Prog, Blob}; +use crate::RustFunction; +pub use crate::Type; macro_rules! error { ( $thing:expr, $kind:expr) => { @@ -21,262 +20,6 @@ macro_rules! error { }; } -#[derive(Clone)] -pub enum Value { - Blob(usize), - BlobInstance(usize, Rc<RefCell<Vec<Value>>>), - Float(f64), - Int(i64), - Bool(bool), - String(Rc<String>), - Function(Vec<Rc<RefCell<UpValue>>>, Rc<RefCell<Block>>), - ExternFunction(usize), - Unkown, - Nil, -} - -#[derive(Clone, Debug)] -pub struct UpValue { - slot: usize, - value: Value, -} - -impl UpValue { - fn new(value: usize) -> Self { - Self { - slot: value, - value: Value::Nil, - } - } - - fn get(&self, stack: &[Value]) -> Value { - if self.is_closed() { - self.value.clone() - } else { - stack[self.slot].clone() - } - } - - fn set(&mut self, stack: &mut [Value], value: Value) { - if self.is_closed() { - self.value = value; - } else { - stack[self.slot] = value; - } - } - - - fn is_closed(&self) -> bool { - self.slot == 0 - } - - fn close(&mut self, value: Value) { - self.slot = 0; - self.value = value; - } -} - -impl Debug for Value { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Value::Blob(i) => write!(fmt, "(blob {})", i), - Value::BlobInstance(i, v) => write!(fmt, "(inst {} {:?})", i, v), - Value::Float(f) => write!(fmt, "(float {})", f), - Value::Int(i) => write!(fmt, "(int {})", i), - Value::Bool(b) => write!(fmt, "(bool {})", b), - Value::String(s) => write!(fmt, "(string \"{}\")", s), - Value::Function(_, block) => write!(fmt, "(fn {}: {:?})", block.borrow().name, block.borrow().ty), - Value::ExternFunction(slot) => write!(fmt, "(extern fn {})", slot), - Value::Unkown => write!(fmt, "(unkown)"), - Value::Nil => write!(fmt, "(nil)"), - } - } -} - -impl Value { - fn identity(self) -> Self { - match self { - Value::Float(_) => Value::Float(1.0), - Value::Int(_) => Value::Int(1), - Value::Bool(_) => Value::Bool(true), - a => a, - } - } - - fn as_type(&self) -> Type { - match self { - Value::BlobInstance(i, _) => Type::BlobInstance(*i), - Value::Blob(i) => Type::Blob(*i), - Value::Float(_) => Type::Float, - Value::Int(_) => Type::Int, - Value::Bool(_) => Type::Bool, - Value::String(_) => Type::String, - Value::Function(_, block) => block.borrow().ty.clone(), - Value::ExternFunction(_) => Type::Void, //TODO - Value::Unkown => Type::UnknownType, - Value::Nil => Type::Void, - } - } -} - -#[derive(Debug, Clone)] -pub enum Op { - Illegal, - - Pop, - PopUpvalue, - Constant(Value), - - Get(String), - Set(String), - - Add, - Sub, - Mul, - Div, - Neg, - - And, - Or, - Not, - - Jmp(usize), - JmpFalse(usize), - - Equal, // == - Less, // < - Greater, // > - - Assert, - Unreachable, - - ReadLocal(usize), - AssignLocal(usize), - - ReadUpvalue(usize), - AssignUpvalue(usize), - - Define(Type), - - Call(usize), - - Print, - Return, -} - -#[derive(Debug)] -pub struct Block { - pub ty: Type, - pub ups: Vec<(usize, bool, Type)>, - - pub name: String, - pub file: PathBuf, - pub ops: Vec<Op>, - pub last_line_offset: usize, - pub line_offsets: HashMap<usize, usize>, - pub line: usize, -} - -impl Block { - pub fn new(name: &str, file: &Path, line: usize) -> Self { - Self { - ty: Type::Void, - ups: Vec::new(), - name: String::from(name), - file: file.to_owned(), - ops: Vec::new(), - last_line_offset: 0, - line_offsets: HashMap::new(), - line, - } - } - - pub fn from_type(ty: &Type) -> Self { - let mut block = Block::new("/empty/", Path::new(""), 0); - block.ty = ty.clone(); - block - } - - pub fn args(&self) -> &Vec<Type> { - if let Type::Function(ref args, _) = self.ty { - args - } else { - unreachable!() - } - } - - pub fn ret(&self) -> &Type { - if let Type::Function(_, ref ret) = self.ty { - ret - } else { - unreachable!() - } - } - - pub fn id(&self) -> (PathBuf, usize) { - (self.file.clone(), self.line) - } - - pub fn last_op(&self) -> Option<&Op> { - self.ops.last() - } - - pub fn add_line(&mut self, token_position: usize) { - if token_position != self.last_line_offset { - self.line_offsets.insert(self.curr(), token_position); - self.last_line_offset = token_position; - } - } - - pub fn line(&self, ip: usize) -> usize { - for i in (0..=ip).rev() { - if let Some(line) = self.line_offsets.get(&i) { - return *line; - } - } - return 0; - } - - pub fn debug_print(&self) { - println!(" === {} ===", self.name.blue()); - for (i, s) in self.ops.iter().enumerate() { - if self.line_offsets.contains_key(&i) { - print!("{:5} ", self.line_offsets[&i].red()); - } else { - print!(" {} ", "|".red()); - } - println!("{:05} {:?}", i.blue(), s); - } - println!(""); - } - - pub fn last_instruction(&mut self) -> &Op { - self.ops.last().unwrap() - } - - pub fn add(&mut self, op: Op, token_position: usize) -> usize { - let len = self.curr(); - self.add_line(token_position); - self.ops.push(op); - len - } - - pub fn add_from(&mut self, ops: &[Op], token_position: usize) -> usize { - let len = self.curr(); - self.add_line(token_position); - self.ops.extend_from_slice(ops); - len - } - - pub fn curr(&self) -> usize { - self.ops.len() - } - - pub fn patch(&mut self, op: Op, pos: usize) { - self.ops[pos] = op; - } -} - #[derive(Debug)] struct Frame { stack_offset: usize, @@ -973,8 +716,8 @@ impl VM { #[cfg(test)] mod tests { mod typing { - use crate::test_string; use crate::error::ErrorKind; + use crate::test_string; test_string!(uncallable_type, " f := fn i: int { |
