aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler.rs33
-rw-r--r--src/lib.rs38
-rw-r--r--src/vm.rs28
3 files changed, 56 insertions, 43 deletions
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<Error>,
blocks: Vec<Rc<RefCell<Block>>>,
- blobs: Vec<Blob>,
+ blob_id: usize,
functions: HashMap<String, (usize, RustFunction)>,
constants: Vec<Value>,
strings: Vec<String>,
+
+
}
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<usize> {
- 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<Type>),
Function(Vec<Type>, Box<Type>),
- Blob(usize),
- Instance(usize),
+ Blob(Rc<Blob>),
+ Instance(Rc<Blob>),
}
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<Type> for Value {
#[derive(Clone)]
pub enum Value {
Ty(Type),
- Blob(usize),
- Instance(usize, Rc<RefCell<Vec<Value>>>),
+ Blob(Rc<Blob>),
+ Instance(Rc<Blob>, Rc<RefCell<Vec<Value>>>),
Tuple(Rc<Vec<Value>>),
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<String, (usize, Type)>,
}
+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<Rc<RefCell<Block>>>,
- pub blobs: Vec<Rc<Blob>>,
pub functions: Vec<RustFunction>,
pub constants: Vec<Value>,
pub strings: Vec<String>,
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<Value>,
frames: Vec<Frame>,
- blobs: Vec<Rc<Blob>>,
constants: Vec<Value>,
strings: Vec<String>,
@@ -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<Error>> {
let mut errors = Vec::new();
- self.blobs = prog.blobs.clone();
self.constants = prog.constants.clone();
self.strings = prog.strings.clone();
self.runtime = false;