diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-03-07 17:50:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-07 17:50:18 +0100 |
| commit | 09c830296fdb55efbc7f590337ce72f5ec75c04b (patch) | |
| tree | 2411baac44a8ce88fcb90e35db68fba018aefb81 /src/vm.rs | |
| parent | a9d943e2d93be0e741874cb1ef85488dacc6eeab (diff) | |
| parent | eab567c57dd41439ad4328a287baddda3e3270a8 (diff) | |
| download | sylt-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.rs | 135 |
1 files changed, 69 insertions, 66 deletions
@@ -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(_, _)]); - } -} |
