aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.rs
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-01-18 20:35:06 +0100
committerEdvard Thörnros <edvard.thornros@gmail.com>2021-01-18 20:35:06 +0100
commite84d99376ba669c41b38a8750f0b4411ac5d57dc (patch)
tree16f0bc0e2e32f1e16df9a7b4fab623a9439fd8b7 /src/vm.rs
parentc7fa3245f4b73e0699ccfc3d359d864247f62dcc (diff)
downloadsylt-e84d99376ba669c41b38a8750f0b4411ac5d57dc.tar.gz
Typecheck all blocks
Diffstat (limited to 'src/vm.rs')
-rw-r--r--src/vm.rs46
1 files changed, 40 insertions, 6 deletions
diff --git a/src/vm.rs b/src/vm.rs
index 71923b8..02d90a7 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -498,9 +498,10 @@ impl VM {
}
pub fn run(&mut self, block: Rc<Block>) -> Result<(), Error>{
- crate::typer::VM::new().print_ops(self.print_ops)
- .print_blocks(self.print_blocks)
- .typecheck(Type::Void, Rc::clone(&block))?;
+ self.stack.clear();
+ self.frames.clear();
+
+ self.stack.push(Value::Function(Rc::clone(&block)));
self.frames.push(Frame {
stack_offset: 0,
@@ -605,8 +606,14 @@ impl VM {
}
fn typecheck_block(&mut self, block: Rc<Block>) -> Vec<Error> {
+ self.stack.clear();
self.frames.clear();
+ self.stack.push(Value::Function(Rc::clone(&block)));
+ for arg in block.args() {
+ self.stack.push(arg.as_value());
+ }
+
self.frames.push(Frame {
stack_offset: 0,
block: block,
@@ -620,7 +627,7 @@ impl VM {
let mut errors = Vec::new();
loop {
let ip = self.frame().ip;
- if ip > self.frame().block.ops.len() {
+ if ip >= self.frame().block.ops.len() {
break;
}
@@ -630,6 +637,7 @@ impl VM {
if let Err(e) = self.check_op(self.op().clone()) {
errors.push(e);
+ self.frame_mut().ip += 1;
}
if !self.stack.is_empty() {
@@ -640,13 +648,39 @@ impl VM {
errors
}
- pub fn typecheck(&mut self, blocks: Vec<Rc<Block>>) -> Result<(), Vec<Error>> {
+ pub fn typecheck(&mut self, blocks: &Vec<Rc<Block>>) -> Result<(), Vec<Error>> {
let mut errors = Vec::new();
for block in blocks.iter() {
errors.append(&mut self.typecheck_block(Rc::clone(block)));
}
- return Ok(());
+ if errors.is_empty() {
+ Ok(())
+ } else {
+ Err(errors)
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ mod typing {
+ use crate::test_string;
+ use crate::error::ErrorKind;
+
+ test_string!(uncallable_type, "
+ f := fn i: int {
+ i()
+ }",
+ [ErrorKind::TypeError(_, _)]);
+
+ test_string!(wrong_params, "
+ f : fn -> int = fn a: int -> int {}",
+ [ErrorKind::TypeError(_, _)]);
+
+ test_string!(wrong_ret, "
+ f : fn -> int = fn {}",
+ [ErrorKind::TypeError(_, _)]);
}
}