diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-02-16 21:10:03 +0100 |
|---|---|---|
| committer | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-02-16 21:10:03 +0100 |
| commit | e86b1be782c2c2f57e968557d7f91bbcc7b8b27f (patch) | |
| tree | 22e603ce7b369b51dc1e2ceaeb63e64c51ea4bfd /src | |
| parent | ecc84fc8259ab0f2f5754718ed70e3a57048a540 (diff) | |
| download | sylt-e86b1be782c2c2f57e968557d7f91bbcc7b8b27f.tar.gz | |
fix the failing testcase
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler.rs | 3 | ||||
| -rw-r--r-- | src/lib.rs | 12 | ||||
| -rw-r--r-- | src/vm.rs | 41 |
3 files changed, 53 insertions, 3 deletions
diff --git a/src/compiler.rs b/src/compiler.rs index ec78118..361d93a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -917,6 +917,9 @@ impl Compiler { if let Entry::Occupied(entry) = self.unkowns.entry(String::from(name)) { let (_, (slot, _)) = entry.remove_entry(); self.constants[slot] = self.constants.pop().unwrap(); + add_op(self, block, Op::Link(slot)); + } else { + add_op(self, block, Op::Link(self.constants.len() - 1)); } return; } @@ -480,6 +480,12 @@ pub enum Op { /// Does not affect the stack. Define(usize), + /// Links the upvalues for the given constant + /// function. This updates the constant stack. + /// + /// Does not affect the stack. + Link(usize), + /// Calls "something" with the given number /// of arguments. The callable value is /// then replaced with the result. @@ -1275,11 +1281,11 @@ f :: fn -> fn -> { g := f() g() -q <=> 3 +q <=> 1 g() -q <=> 4 +q <=> 2 g() -q <=> 5 +q <=> 3 ", ); @@ -258,6 +258,34 @@ impl VM { self.push(value); } + Op::Link(slot) => { + let offset = self.frame().stack_offset; + let constant = self.constant(slot).clone(); + let constant = 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]) + } else { + unreachable!() + } + } else { + let slot = self.frame().stack_offset + slot; + Rc::clone(self.find_upvalue(slot)) + }; + ups.push(up); + } + Value::Function(ups, block) + }, + value => error!(self, + ErrorKind::RuntimeTypeError(op, vec![value.clone()]), + format!("Not a function {:?}.", value)), + }; + self.constants[slot] = constant; + } + Op::Index => { let slot = self.stack.pop().unwrap(); let val = self.stack.pop().unwrap(); @@ -638,6 +666,19 @@ impl VM { } } + Op::Link(slot) => { + println!("{:?}", self.constants); + println!("{:?} - {}", self.constant(slot), slot); + match self.constant(slot).clone() { + Value::Function(_, _) => {} + value => { + error!(self, + ErrorKind::TypeError(op, vec![Type::from(&value)]), + format!("Cannot link non-function {:?}.", value)); + } + }; + } + Op::Call(num_args) => { let new_base = self.stack.len() - 1 - num_args; match self.stack[new_base].clone() { |
