aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-01-20 21:26:14 +0100
committerEdvard Thörnros <edvard.thornros@gmail.com>2021-01-20 21:26:14 +0100
commitd13695d2452e0468168240800a4cde88f220b646 (patch)
tree35a8ae5e9bf656bc4a3435bab1afc367757aa8a7
parent85411e444826fc239fb268da03572993d9c9fd83 (diff)
downloadsylt-d13695d2452e0468168240800a4cde88f220b646.tar.gz
Typecheck upvalues
-rw-r--r--src/compiler.rs11
-rw-r--r--src/vm.rs18
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,
diff --git a/src/vm.rs b/src/vm.rs
index 7b48b4e..abe7874 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -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)));
}