aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2021-03-05 21:08:27 +0100
committerGustav Sörnäs <gustav@sornas.net>2021-03-05 21:08:27 +0100
commitba7ebb200cc5560ba0a2237df4a4985fe927b08c (patch)
tree694ef859914dadc5cb7b3f7589cbb0a5dec561ad /src
parentdd38069bc1f8b696e8f0c50f43e0e7954729acf7 (diff)
downloadsylt-ba7ebb200cc5560ba0a2237df4a4985fe927b08c.tar.gz
almost working capturing variables
Diffstat (limited to 'src')
-rw-r--r--src/compiler.rs19
-rw-r--r--src/vm.rs77
2 files changed, 63 insertions, 33 deletions
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);
diff --git a/src/vm.rs b/src/vm.rs
index d056ded..2237896 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -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,