diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-20 21:26:14 +0100 |
|---|---|---|
| committer | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-20 21:26:14 +0100 |
| commit | d13695d2452e0468168240800a4cde88f220b646 (patch) | |
| tree | 35a8ae5e9bf656bc4a3435bab1afc367757aa8a7 | |
| parent | 85411e444826fc239fb268da03572993d9c9fd83 (diff) | |
| download | sylt-d13695d2452e0468168240800a4cde88f220b646.tar.gz | |
Typecheck upvalues
| -rw-r--r-- | src/compiler.rs | 11 | ||||
| -rw-r--r-- | src/vm.rs | 18 |
2 files changed, 27 insertions, 2 deletions
diff --git a/src/compiler.rs b/src/compiler.rs index c4afbf3..b7dad75 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -107,7 +107,10 @@ struct Variable { typ: Type, scope: usize, slot: usize, + outer_slot: usize, + outer_upvalue: bool, + active: bool, upvalue: bool, captured: bool, @@ -144,6 +147,7 @@ impl Frame { fn add_upvalue(&mut self, variable: Variable) -> Variable { println!("{} - UPDOG", variable.name); let new_variable = Variable { + outer_upvalue: variable.upvalue, outer_slot: variable.slot, slot: self.upvalues.len(), active: true, @@ -549,6 +553,11 @@ impl Compiler { } self.scope(&mut function_block); + + for var in self.frame().upvalues.iter() { + function_block.ups.push((var.outer_slot, var.outer_upvalue, var.typ.clone())); + } + println!("{:?}", function_block.ups); // TODO(ed): Send the original place to find the upvalues, // so we know from where to copy them. }); @@ -596,6 +605,7 @@ impl Compiler { self.stack_mut().push(Variable { name: String::from(name), captured: false, + outer_upvalue: false, outer_slot: 0, slot, typ, @@ -833,6 +843,7 @@ impl Compiler { self.stack_mut().push(Variable { name: String::from("/main/"), typ: Type::Void, + outer_upvalue: false, outer_slot: 0, slot: 0, scope: 0, @@ -152,7 +152,7 @@ pub enum Op { #[derive(Debug)] pub struct Block { pub ty: Type, - pub ups: Vec<Type>, + pub ups: Vec<(usize, bool, Type)>, pub name: String, pub file: PathBuf, @@ -521,7 +521,7 @@ impl VM { Op::Call(num_args) => { let new_base = self.stack.len() - 1 - num_args; match &self.stack[new_base] { - Value::Function(_, block) => { + Value::Function(ups, block) => { let args = block.args(); if args.len() != num_args { error!(self, @@ -613,6 +613,19 @@ impl VM { Op::Jmp(_line) => {} + Op::ReadUpvalue(slot) => { + self.stack.push(self.frame().block.ups[slot].2.as_value()); + } + + Op::AssignUpvalue(slot) => { + let var = self.frame().block.ups[slot].2.clone(); + let up = self.stack.pop().unwrap().as_type(); + if var != up { + error!(self, ErrorKind::TypeError(op, vec![var, up]), + "Incorrect type for upvalue.".to_string()); + } + } + Op::Return => { let a = self.stack.pop().unwrap(); let ret = self.frame().block.ret(); @@ -738,6 +751,7 @@ impl VM { let mut errors = Vec::new(); for block in blocks.iter() { + let ups: Vec<_> = block.ups.iter().map(|x| x.2.as_value()).collect(); errors.append(&mut self.typecheck_block(Rc::clone(block))); } |
