diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-28 20:54:24 +0100 |
|---|---|---|
| committer | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-28 20:54:24 +0100 |
| commit | b7e480f93f8ea3feb9155df207bb308b11e79303 (patch) | |
| tree | 9042f211d7b4ae98563ab4c03edefa9b635cc332 | |
| parent | 92075e6bc23d63d62e2d0caf83acbf81ad0ccd99 (diff) | |
| download | sylt-b7e480f93f8ea3feb9155df207bb308b11e79303.tar.gz | |
Creating blobs
| -rw-r--r-- | src/compiler.rs | 19 | ||||
| -rw-r--r-- | src/error.rs | 4 | ||||
| -rw-r--r-- | src/vm.rs | 39 |
3 files changed, 54 insertions, 8 deletions
diff --git a/src/compiler.rs b/src/compiler.rs index 2302e76..4dd3517 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -65,12 +65,16 @@ pub enum Type { Bool, String, Function(Vec<Type>, Box<Type>), + Blob(usize), + BlobInstance(usize), } impl PartialEq for Type { fn eq(&self, other: &Self) -> bool { match (self, other) { (Type::Void, Type::Void) => true, + (Type::BlobInstance(a), Type::BlobInstance(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, @@ -85,6 +89,8 @@ impl PartialEq for Type { impl From<&Value> for Type { fn from(value: &Value) -> Type { match value { + Value::BlobInstance(i, _) => Type::BlobInstance(*i), + Value::Blob(i) => Type::Blob(*i), Value::Int(_) => Type::Int, Value::Float(_) => Type::Float, Value::Bool(_) => Type::Bool, @@ -106,6 +112,8 @@ impl Type { pub fn as_value(&self) -> Value { match self { Type::Void => Value::Nil, + Type::Blob(i) => Value::Blob(*i), + Type::BlobInstance(i) => Value::BlobInstance(*i, Vec::new()), Type::UnknownType => Value::Unkown, Type::Int => Value::Int(1), Type::Float => Value::Float(1.0), @@ -175,9 +183,9 @@ impl Frame { #[derive(Debug, Clone)] pub struct Blob { - name: String, + pub name: String, - name_to_field: HashMap<String, Type>, + pub name_to_field: HashMap<String, (usize, Type)>, } impl Blob { @@ -189,11 +197,12 @@ impl Blob { } pub fn add_field(&mut self, name: &str, ty: Type) -> Result<(), ()> { + let size = self.name_to_field.len(); let entry = self.name_to_field.entry(String::from(name)); if matches!(entry, Entry::Occupied(_)) { Err(()) } else { - entry.or_insert(ty); + entry.or_insert((size, ty)); Ok(()) } } @@ -645,7 +654,7 @@ impl Compiler { self.call(block); } } else if let Some(blob) = self.find_blob(&name) { - // block.add(Op::Blob(blob)); + block.add(Op::Constant(Value::Blob(blob)), self.line()); if self.peek() == Token::LeftParen { self.call(block); } @@ -976,7 +985,7 @@ impl Compiler { if self.errors.is_empty() { Ok(Prog { blocks: self.blocks.clone(), - blobs: Vec::new(), + blobs: self.blobs.iter().map(|x| Rc::new(x.clone())).collect(), }) } else { Err(self.errors.clone()) diff --git a/src/error.rs b/src/error.rs index 525dbc6..a8ea730 100644 --- a/src/error.rs +++ b/src/error.rs @@ -33,13 +33,13 @@ impl fmt::Display for ErrorKind { ErrorKind::TypeError(op, types) => { let types = types .iter() - .fold(String::new(), |a, v| { format!("{}, {:?}", a, v) }); + .fold(String::new(), |a, v| { format!("{}{:?}, ", a, v) }); write!(f, "{} Cannot apply {:?} to types {}", "Type Error".bold(), op, types) } ErrorKind::RuntimeTypeError(op, values) => { let values = values .iter() - .fold(String::new(), |a, v| { format!("{}, {:?}", a, v) }); + .fold(String::new(), |a, v| { format!("{}{:?}, ", a, v) }); write!(f, "{} Cannot apply {:?} to values {}", "Runtime Type Error".bold(), op, values) } ErrorKind::Assert => { @@ -21,6 +21,8 @@ macro_rules! error { #[derive(Clone)] pub enum Value { + Blob(usize), + BlobInstance(usize, Vec<Value>), Float(f64), Int(i64), Bool(bool), @@ -75,6 +77,8 @@ impl UpValue { 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), @@ -98,6 +102,8 @@ impl Value { 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, @@ -557,7 +563,22 @@ impl VM { Op::Call(num_args) => { let new_base = self.stack.len() - 1 - num_args; - match &self.stack[new_base] { + match self.stack[new_base].clone() { + Value::Blob(blob_id) => { + let blob = &self.blobs[blob_id]; + + let mut values = Vec::with_capacity(blob.name_to_field.len()); + for _ in 0..values.capacity() { + values.push(Value::Nil); + } + + for (slot, ty) in blob.name_to_field.values() { + values[*slot] = ty.as_value(); + } + + self.stack.pop(); + self.stack.push(Value::BlobInstance(blob_id, values)); + } Value::Function(_, block) => { let inner = block.borrow(); let args = inner.args(); @@ -751,6 +772,21 @@ 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]; + + let mut values = Vec::with_capacity(blob.name_to_field.len()); + for _ in 0..values.capacity() { + values.push(Value::Nil); + } + + for (slot, ty) in blob.name_to_field.values() { + values[*slot] = ty.as_value(); + } + + self.stack.pop(); + self.stack.push(Value::BlobInstance(blob_id, values)); + } Value::Function(_, block) => { let inner = block.borrow(); let args = inner.args(); @@ -844,6 +880,7 @@ impl VM { pub fn typecheck(&mut self, prog: &Prog) -> Result<(), Vec<Error>> { let mut errors = Vec::new(); + self.blobs = prog.blobs.clone(); for block in prog.blocks.iter() { errors.append(&mut self.typecheck_block(Rc::clone(block))); } |
