From e84d99376ba669c41b38a8750f0b4411ac5d57dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 18 Jan 2021 20:35:06 +0100 Subject: Typecheck all blocks --- src/vm.rs | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'src/vm.rs') 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) -> 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) -> Vec { + 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>) -> Result<(), Vec> { + pub fn typecheck(&mut self, blocks: &Vec>) -> Result<(), Vec> { 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(_, _)]); } } -- cgit v1.2.1