From f098c32e89626f75d83118d4d95d209299d28587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 15 Feb 2021 19:18:25 +0100 Subject: change how blobs are stored --- src/compiler.rs | 33 ++++++++++++++++++++++----------- src/lib.rs | 38 ++++++++++++++++++++++++-------------- src/vm.rs | 28 ++++++++++------------------ 3 files changed, 56 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/compiler.rs b/src/compiler.rs index e8607f7..9a29d6d 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -228,11 +228,13 @@ pub(crate) struct Compiler { errors: Vec, blocks: Vec>>, - blobs: Vec, + blob_id: usize, functions: HashMap, constants: Vec, strings: Vec, + + } macro_rules! push_frame { @@ -290,7 +292,7 @@ impl Compiler { errors: vec![], blocks: Vec::new(), - blobs: Vec::new(), + blob_id: 0, functions: HashMap::new(), @@ -309,6 +311,12 @@ impl Compiler { }).unwrap() } + fn new_blob_id(&mut self) -> usize { + let id = self.blob_id; + self.blob_id += 1; + id + } + fn add_constant(&mut self, value: Value) -> usize { self.constants.push(value); self.constants.len() - 1 @@ -612,9 +620,10 @@ impl Compiler { } fn find_blob(&self, name: &str) -> Option { - self.blobs.iter().enumerate() - .find(|(_, x)| x.name == name) - .map(|(i, _)| i) + self.constants.iter().enumerate().find_map(|(i, x)| match x { + Value::Blob(b) if b.name == name => Some(i), + _ => None, + }) } fn call(&mut self, block: &mut Block) { @@ -805,8 +814,7 @@ impl Compiler { } } } else if let Some(blob) = self.find_blob(&name) { - let string = self.add_constant(Value::Blob(blob)); - add_op(self, block, Op::Constant(string)); + add_op(self, block, Op::Constant(blob)); parse_branch!(self, block, self.call(block)); } else if let Some(slot) = self.find_extern_function(&name) { let string = self.add_constant(Value::ExternFunction(slot)); @@ -1085,7 +1093,11 @@ impl Compiler { "float" => Ok(Type::Float), "bool" => Ok(Type::Bool), "str" => Ok(Type::String), - x => self.find_blob(x).map(|blob| Type::Instance(blob)).ok_or(()), + x => { + let blob = self.find_blob(x) + .unwrap_or_else(|| { error!(self, "Unkown blob."); 0 } ); + Ok(Type::from(&self.constants[blob])) + } } } _ => Err(()), @@ -1103,7 +1115,7 @@ impl Compiler { expect!(self, Token::LeftBrace, "Expected 'blob' body. AKA '{'."); - let mut blob = Blob::new(&name); + let mut blob = Blob::new(self.new_blob_id(), &name); loop { if matches!(self.peek(), Token::EOF | Token::RightBrace) { break; } if matches!(self.peek(), Token::Newline) { self.eat(); continue; } @@ -1131,7 +1143,7 @@ impl Compiler { expect!(self, Token::RightBrace, "Expected '}' after 'blob' body. AKA '}'."); - self.blobs.push(blob); + self.constants.push(Value::Blob(Rc::new(blob))); } fn blob_field(&mut self, block: &mut Block) { @@ -1341,7 +1353,6 @@ impl Compiler { if self.errors.is_empty() { Ok(Prog { blocks: self.blocks.clone(), - blobs: self.blobs.iter().map(|x| Rc::new(x.clone())).collect(), functions: functions.iter().map(|(_, f)| *f).collect(), constants: self.constants.clone(), strings: self.strings.clone(), diff --git a/src/lib.rs b/src/lib.rs index c2aee90..497dba3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,16 +84,16 @@ pub enum Type { String, Tuple(Vec), Function(Vec, Box), - Blob(usize), - Instance(usize), + Blob(Rc), + Instance(Rc), } impl PartialEq for Type { fn eq(&self, other: &Self) -> bool { match (self, other) { (Type::Void, Type::Void) => true, - (Type::Instance(a), Type::Instance(b)) => a == b, - (Type::Blob(a), Type::Blob(b)) => a == b, + (Type::Instance(a), Type::Instance(b)) => *a == *b, + (Type::Blob(a), Type::Blob(b)) => *a == *b, (Type::Int, Type::Int) => true, (Type::Float, Type::Float) => true, (Type::Bool, Type::Bool) => true, @@ -111,8 +111,8 @@ impl PartialEq for Type { impl From<&Value> for Type { fn from(value: &Value) -> Type { match value { - Value::Instance(i, _) => Type::Instance(*i), - Value::Blob(i) => Type::Blob(*i), + Value::Instance(b, _) => Type::Instance(Rc::clone(b)), + Value::Blob(b) => Type::Blob(Rc::clone(b)), Value::Tuple(v) => { Type::Tuple(v.iter().map(|x| Type::from(x)).collect()) } @@ -136,8 +136,11 @@ impl From<&Type> for Value { fn from(ty: &Type) -> Self { match ty { Type::Void => Value::Nil, - Type::Blob(i) => Value::Blob(*i), - Type::Instance(i) => Value::Instance(*i, Rc::new(RefCell::new(Vec::new()))), + Type::Blob(b) => Value::Blob(Rc::clone(b)), + Type::Instance(b) => { + Value::Instance(Rc::clone(b), + Rc::new(RefCell::new(Vec::new()))) + } Type::Tuple(fields) => { Value::Tuple(Rc::new(fields.iter().map(Value::from).collect())) } @@ -163,8 +166,8 @@ impl From for Value { #[derive(Clone)] pub enum Value { Ty(Type), - Blob(usize), - Instance(usize, Rc>>), + Blob(Rc), + Instance(Rc, Rc>>), Tuple(Rc>), Float(f64), Int(i64), @@ -180,8 +183,8 @@ impl Debug for Value { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Value::Ty(ty) => write!(fmt, "(type {:?})", ty), - Value::Blob(i) => write!(fmt, "(blob {})", i), - Value::Instance(i, v) => write!(fmt, "(inst {} {:?})", i, v), + Value::Blob(b) => write!(fmt, "(blob {})", b.name), + Value::Instance(b, v) => write!(fmt, "(inst {} {:?})", b.name, v), Value::Float(f) => write!(fmt, "(float {})", f), Value::Int(i) => write!(fmt, "(int {})", i), Value::Bool(b) => write!(fmt, "(bool {})", b), @@ -257,14 +260,22 @@ impl UpValue { #[derive(Debug, Clone)] pub struct Blob { + pub id: usize, pub name: String, /// Maps field names to their slot and type. pub fields: HashMap, } +impl PartialEq for Blob { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + impl Blob { - fn new(name: &str) -> Self { + fn new(id: usize, name: &str) -> Self { Self { + id: id, name: String::from(name), fields: HashMap::new(), } @@ -713,7 +724,6 @@ impl Block { #[derive(Clone)] pub struct Prog { pub blocks: Vec>>, - pub blobs: Vec>, pub functions: Vec, pub constants: Vec, pub strings: Vec, diff --git a/src/vm.rs b/src/vm.rs index 2cef854..b292a79 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use owo_colors::OwoColorize; -use crate::{Blob, Block, Op, Prog, UpValue, Value, op}; +use crate::{Block, Op, Prog, UpValue, Value, op}; use crate::error::{Error, ErrorKind}; use crate::RustFunction; use crate::Type; @@ -57,7 +57,6 @@ pub struct VM { stack: Vec, frames: Vec, - blobs: Vec>, constants: Vec, strings: Vec, @@ -87,7 +86,6 @@ impl VM { stack: Vec::new(), frames: Vec::new(), - blobs: Vec::new(), constants: Vec::new(), strings: Vec::new(), @@ -284,7 +282,7 @@ impl VM { let inst = self.pop(); let field = self.string(field); if let Value::Instance(ty, values) = inst { - let slot = self.blobs[ty].fields.get(field).unwrap().0; + let slot = ty.fields.get(field).unwrap().0; self.push(values.borrow()[slot].clone()); } else { error!(self, ErrorKind::RuntimeTypeError(op, vec![inst])); @@ -295,7 +293,7 @@ impl VM { let (inst, value) = self.poppop(); let field = self.string(field); if let Value::Instance(ty, values) = inst { - let slot = self.blobs[ty].fields.get(field).unwrap().0; + let slot = ty.fields.get(field).unwrap().0; values.borrow_mut()[slot] = value; } else { error!(self, ErrorKind::RuntimeTypeError(op, vec![inst])); @@ -393,16 +391,14 @@ impl VM { Op::Call(num_args) => { let new_base = self.stack.len() - 1 - num_args; match self.stack[new_base].clone() { - Value::Blob(blob_id) => { - let blob = &self.blobs[blob_id]; - + Value::Blob(blob) => { let mut values = Vec::with_capacity(blob.fields.len()); for _ in 0..values.capacity() { values.push(Value::Nil); } self.pop(); - self.push(Value::Instance(blob_id, Rc::new(RefCell::new(values)))); + self.push(Value::Instance(blob, Rc::new(RefCell::new(values)))); } Value::Function(_, block) => { let inner = block.borrow(); @@ -483,7 +479,6 @@ impl VM { // Initalizes the VM for running. Run cannot be called before this. pub(crate) fn init(&mut self, prog: &Prog) { let block = Rc::clone(&prog.blocks[0]); - self.blobs = prog.blobs.clone(); self.constants = prog.constants.clone(); self.strings = prog.strings.clone(); @@ -570,7 +565,7 @@ impl VM { let inst = self.pop(); let field = self.string(field); if let Value::Instance(ty, _) = inst { - let value = Value::from(&self.blobs[ty].fields.get(field).unwrap().1); + let value = Value::from(ty.fields.get(field).unwrap().1.clone()); self.push(value); } else { self.push(Value::Nil); @@ -583,9 +578,9 @@ impl VM { let field = self.string(field); if let Value::Instance(ty, _) = inst { - let ty = &self.blobs[ty].fields.get(field).unwrap().1; + let ty = &ty.fields.get(field).unwrap().1; if ty != &Type::from(&value) { - error!(self, ErrorKind::RuntimeTypeError(op, vec![inst])); + error!(self, ErrorKind::RuntimeTypeError(op, vec![Value::from(ty)])); } } else { error!(self, ErrorKind::RuntimeTypeError(op, vec![inst])); @@ -646,9 +641,7 @@ impl VM { Op::Call(num_args) => { let new_base = self.stack.len() - 1 - num_args; match self.stack[new_base].clone() { - Value::Blob(blob_id) => { - let blob = &self.blobs[blob_id]; - + Value::Blob(blob) => { let mut values = Vec::with_capacity(blob.fields.len()); for _ in 0..values.capacity() { values.push(Value::Nil); @@ -659,7 +652,7 @@ impl VM { } self.pop(); - self.push(Value::Instance(blob_id, Rc::new(RefCell::new(values)))); + self.push(Value::Instance(blob, Rc::new(RefCell::new(values)))); } Value::Function(_, block) => { let inner = block.borrow(); @@ -771,7 +764,6 @@ impl VM { pub(crate) fn typecheck(&mut self, prog: &Prog) -> Result<(), Vec> { let mut errors = Vec::new(); - self.blobs = prog.blobs.clone(); self.constants = prog.constants.clone(); self.strings = prog.strings.clone(); self.runtime = false; -- cgit v1.2.1