diff options
| -rw-r--r-- | progs/tests/auto/constant_function_closure.sy | 2 | ||||
| -rw-r--r-- | src/compiler.rs | 19 | ||||
| -rw-r--r-- | src/vm.rs | 77 |
3 files changed, 64 insertions, 34 deletions
diff --git a/progs/tests/auto/constant_function_closure.sy b/progs/tests/auto/constant_function_closure.sy index 8c54249..6c7f0d7 100644 --- a/progs/tests/auto/constant_function_closure.sy +++ b/progs/tests/auto/constant_function_closure.sy @@ -1,4 +1,4 @@ -q := 1 +q : int = 1 f :: fn -> int { q += 1 diff --git a/src/compiler.rs b/src/compiler.rs index 16887a0..9c8f830 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -227,11 +227,13 @@ impl Variable { } } +#[derive(Debug)] enum LoopOp { Continue, Break, } +#[derive(Debug)] struct Frame { loops: Vec<Vec<(usize, usize, LoopOp)>>, stack: Vec<Variable>, @@ -1146,7 +1148,6 @@ impl Compiler { assert!(var.mutable); self.expression(block); - add_op(self, block, Op::AssignLocal(var.slot)); self.stack_mut()[var.slot].active = true; } else { // Local @@ -1684,6 +1685,10 @@ impl Compiler { } pub(crate) fn compile(&mut self, name: &str, file: &Path, functions: &[(String, RustFunction)]) -> Result<Prog, Vec<Error>> { + let main = Variable::new("/main/", false, Type::Void); + let slot = self.define(main).unwrap(); + self.frame_mut().stack[slot].read = true; + for section in 0..self.sections.len() { self.init_section(section); let section = &mut self.sections[section]; @@ -1715,7 +1720,8 @@ impl Compiler { if let Ok(ty) = self.parse_type() { let is_mut = self.peek() == Token::Equal; let var = Variable::new(&name, is_mut, ty); - let _ = self.define(var); + let slot = self.define(var).unwrap(); + self.frame_mut().stack[slot].active = true; } else { error!(self, format!("Failed to parse type global '{}'.", name)); } @@ -1724,13 +1730,15 @@ impl Compiler { (Some((Token::Identifier(name), _)), Some((Token::ColonColon, _)), ..) => { let var = Variable::new(name, false, Type::Unknown); - let _ = self.define(var); + let slot = self.define(var).unwrap(); + self.frame_mut().stack[slot].active = true; } (Some((Token::Identifier(name), _)), Some((Token::ColonEqual, _)), ..) => { let var = Variable::new(name, true, Type::Unknown); - let _ = self.define(var); + let slot = self.define(var).unwrap(); + self.frame_mut().stack[slot].active = true; } @@ -1750,9 +1758,6 @@ impl Compiler { .enumerate() .map(|(i, (s, f))| (s, (i, f))) .collect(); - let main = Variable::new("/main/", false, Type::Void); - let _ = self.define(main); - let mut block = Block::new(name, file); for section in 0..self.sections.len() { self.init_section(section); @@ -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; @@ -553,36 +553,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 +653,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 +681,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, |
