aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler.rs19
-rw-r--r--src/error.rs4
-rw-r--r--src/vm.rs39
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 => {
diff --git a/src/vm.rs b/src/vm.rs
index cb30704..df970db 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -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)));
}