aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.rs
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-03-07 17:50:18 +0100
committerGitHub <noreply@github.com>2021-03-07 17:50:18 +0100
commit09c830296fdb55efbc7f590337ce72f5ec75c04b (patch)
tree2411baac44a8ce88fcb90e35db68fba018aefb81 /src/vm.rs
parenta9d943e2d93be0e741874cb1ef85488dacc6eeab (diff)
parenteab567c57dd41439ad4328a287baddda3e3270a8 (diff)
downloadsylt-09c830296fdb55efbc7f590337ce72f5ec75c04b.tar.gz
Merge pull request #91 from FredTheDino/compiler-rewrite
WIP: Rewrite the compiler
Diffstat (limited to 'src/vm.rs')
-rw-r--r--src/vm.rs135
1 files changed, 69 insertions, 66 deletions
diff --git a/src/vm.rs b/src/vm.rs
index f5e5c58..7cfc8d3 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -6,7 +6,7 @@ use std::rc::Rc;
use owo_colors::OwoColorize;
-use crate::{Block, Op, Prog, UpValue, Value, op};
+use crate::{Block, BlockLinkState, Op, Prog, UpValue, Value, op};
use crate::error::{Error, ErrorKind};
use crate::RustFunction;
use crate::Type;
@@ -236,22 +236,26 @@ impl VM {
let offset = self.frame().stack_offset;
let constant = self.constant(value).clone();
let value = match constant {
- Value::Function(_, block) => {
- let mut ups = Vec::new();
- for (slot, is_up, _) in block.borrow().upvalues.iter() {
- let up = if *is_up {
- if let Value::Function(local_ups, _) = &self.stack[offset] {
- Rc::clone(&local_ups[*slot])
+ Value::Function(ups, block) => {
+ if matches!(block.borrow().linking, BlockLinkState::Linked) {
+ Value::Function(ups.clone(), block)
+ } else {
+ let mut ups = Vec::new();
+ for (slot, is_up, _) in block.borrow().upvalues.iter() {
+ let up = if *is_up {
+ if let Value::Function(local_ups, _) = &self.stack[offset] {
+ Rc::clone(&local_ups[*slot])
+ } else {
+ unreachable!()
+ }
} else {
- unreachable!()
- }
- } else {
- let slot = self.frame().stack_offset + slot;
- Rc::clone(self.find_upvalue(slot))
- };
- ups.push(up);
+ let slot = self.frame().stack_offset + slot;
+ Rc::clone(self.find_upvalue(slot))
+ };
+ ups.push(up);
+ }
+ Value::Function(ups, block)
}
- Value::Function(ups, block)
},
value => value,
};
@@ -553,36 +557,37 @@ impl VM {
match self.constant(value).clone() {
Value::Function(_, block) => {
self.push(Value::Function(Vec::new(), block.clone()));
+ if !matches!(block.borrow().linking, BlockLinkState::Linked) {
+ if block.borrow().needs_linking() {
+ error!(self,
+ ErrorKind::InvalidProgram,
+ format!("Calling function '{}' before all captured variables are declared.",
+ block.borrow().name));
+ }
- if block.borrow().needs_linking() {
- error!(self,
- ErrorKind::InvalidProgram,
- format!("Calling function '{}' before all captured variables are declared.",
- block.borrow().name));
- }
-
- let mut types = Vec::new();
- for (slot, is_up, ty) in block.borrow().upvalues.iter() {
- if *is_up {
- types.push(ty.clone());
- } else {
- types.push(Type::from(&self.stack[*slot]));
+ let mut types = Vec::new();
+ for (slot, is_up, ty) in block.borrow().upvalues.iter() {
+ if *is_up {
+ types.push(ty.clone());
+ } else {
+ types.push(Type::from(&self.stack[*slot]));
+ }
}
- }
- let mut block_mut = block.borrow_mut();
- for (i, (_, is_up, ty)) in block_mut.upvalues.iter_mut().enumerate() {
- if *is_up { continue; }
+ let mut block_mut = block.borrow_mut();
+ for (i, (_, is_up, ty)) in block_mut.upvalues.iter_mut().enumerate() {
+ if *is_up { continue; }
- let suggestion = &types[i];
- if matches!(ty, Type::Unknown) {
- *ty = suggestion.clone();
- } else {
- if ty != suggestion {
- error!(self, ErrorKind::CannotInfer(ty.clone(), suggestion.clone()));
+ let suggestion = &types[i];
+ if matches!(ty, Type::Unknown) {
+ *ty = suggestion.clone();
+ } else {
+ if ty != suggestion {
+ error!(self, ErrorKind::CannotInfer(ty.clone(), suggestion.clone()));
+ }
}
- }
- };
+ };
+ }
},
value => {
self.push(value.clone());
@@ -652,6 +657,7 @@ impl VM {
let inner = self.frame().block.borrow();
let ret = inner.ret();
if Type::from(&a) != *ret {
+
error!(self, ErrorKind::TypeMismatch(a.into(), ret.clone()),
"Value does not match return type.");
}
@@ -679,6 +685,29 @@ impl VM {
match self.constant(slot).clone() {
Value::Function(_, block) => {
block.borrow_mut().link();
+
+ let mut types = Vec::new();
+ for (slot, is_up, ty) in block.borrow().upvalues.iter() {
+ if *is_up {
+ types.push(ty.clone());
+ } else {
+ types.push(Type::from(&self.stack[*slot]));
+ }
+ }
+
+ let mut block_mut = block.borrow_mut();
+ for (i, (_, is_up, ty)) in block_mut.upvalues.iter_mut().enumerate() {
+ if *is_up { continue; }
+
+ let suggestion = &types[i];
+ if matches!(ty, Type::Unknown) {
+ *ty = suggestion.clone();
+ } else {
+ if ty != suggestion {
+ error!(self, ErrorKind::CannotInfer(ty.clone(), suggestion.clone()));
+ }
+ }
+ }
}
value => {
error!(self,
@@ -824,29 +853,3 @@ impl VM {
}
}
}
-
-#[cfg(test)]
-mod tests {
- mod typing {
- use crate::error::ErrorKind;
- use crate::{test_string, Type};
-
- test_string!(uncallable_type, "
- f := fn i: int {
- i()
- }
- f",
- [ErrorKind::InvalidProgram]);
-
- test_string!(invalid_assign, "a := 1\na = 0.1\na",
- [ErrorKind::TypeMismatch(Type::Int, Type::Float)]);
-
- test_string!(wrong_params, "
- f : fn -> int = fn a: int -> int {}\nf",
- [ErrorKind::TypeMismatch(_, _), ErrorKind::TypeMismatch(Type::Void, Type::Int)]);
-
- test_string!(wrong_ret, "
- f : fn -> int = fn {}\nf",
- [ErrorKind::TypeMismatch(_, _)]);
- }
-}