From 0f25e98b903f6608d09ad8bfd9ca5d00fec4cec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Wed, 10 Feb 2021 20:49:06 +0100 Subject: simplify frames --- src/compiler.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'src/compiler.rs') diff --git a/src/compiler.rs b/src/compiler.rs index 7f0d32d..1f3d9d8 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -132,10 +132,17 @@ struct Frame { stack: Vec, upvalues: Vec, scope: usize, - variables_below: usize, } impl Frame { + fn new() -> Self { + Self { + stack: Vec::new(), + upvalues: Vec::new(), + scope: 0, + } + } + fn find_local(&self, name: &str) -> Option { for var in self.stack.iter().rev() { if var.name == name && var.active { @@ -189,12 +196,7 @@ pub(crate) struct Compiler { macro_rules! push_frame { ($compiler:expr, $block:expr, $code:tt) => { { - $compiler.frames.push(Frame { - stack: Vec::new(), - upvalues: Vec::new(), - scope: 0, - variables_below: $compiler.frame().variables_below + $compiler.stack().len(), - }); + $compiler.frames.push(Frame::new()); // Return value stored as a variable $compiler.define_variable("", Type::Unknown, &mut $block).unwrap(); @@ -240,12 +242,7 @@ impl Compiler { tokens, current_file: PathBuf::from(current_file), - frames: vec![Frame { - stack: Vec::new(), - upvalues: Vec::new(), - scope: 0, - variables_below: 0, - }], + frames: vec![Frame::new()], panic: false, errors: vec![], -- cgit v1.2.1 From f88b11d224ae29bd4cdc52048a116cb45322271b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Wed, 10 Feb 2021 22:07:28 +0100 Subject: add break and continue --- src/compiler.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'src/compiler.rs') diff --git a/src/compiler.rs b/src/compiler.rs index 1f3d9d8..e0b65c1 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -128,7 +128,13 @@ struct Variable { captured: bool, } +enum LoopOp { + Continue, + Break, +} + struct Frame { + loops: Vec>, stack: Vec, upvalues: Vec, scope: usize, @@ -137,12 +143,57 @@ struct Frame { impl Frame { fn new() -> Self { Self { + loops: Vec::new(), stack: Vec::new(), upvalues: Vec::new(), scope: 0, } } + fn count_this_scope(&self) -> usize { + for (i, var) in self.stack.iter().rev().enumerate() { + println!("i:{} - {} == {}", i, var.scope, self.scope); + if var.scope != self.scope { + // return i; + } + } + return self.stack.len(); + } + + fn push_loop(&mut self) { + self.loops.push(Vec::new()); + } + + fn pop_loop(&mut self, block: &mut Block, stacktarget: usize, start: usize, end: usize) { + // Compiler error if this fails + for (addr, stacksize, op) in self.loops.pop().unwrap().iter() { + let to_pop = stacksize - stacktarget; + let op = match op { + LoopOp::Continue => Op::JmpNPop(start, to_pop), + LoopOp::Break => Op::JmpNPop(end, to_pop), + }; + block.patch(op, *addr); + } + } + + fn add_continue(&mut self, addr: usize, stacksize: usize, block: &mut Block) -> Result<(), ()> { + if let Some(top) = self.loops.last_mut() { + top.push((addr, stacksize, LoopOp::Continue)); + Ok(()) + } else { + Err(()) + } + } + + fn add_break(&mut self, addr: usize, stacksize: usize, block: &mut Block) -> Result<(), ()> { + if let Some(top) = self.loops.last_mut() { + top.push((addr, stacksize, LoopOp::Break)); + Ok(()) + } else { + Err(()) + } + } + fn find_local(&self, name: &str) -> Option { for var in self.stack.iter().rev() { if var.name == name && var.active { @@ -860,6 +911,7 @@ impl Compiler { expect!(self, Token::For, "Expected 'for' at start of for-loop."); push_scope!(self, block, { + self.frame_mut().push_loop(); // Definition match self.peek_four() { // TODO(ed): Typed definitions aswell! @@ -895,6 +947,8 @@ impl Compiler { block.patch(Op::JmpFalse(block.curr()), cond_out); + let stacksize = self.frame().stack.len(); + self.frame_mut().pop_loop(block, stacksize, inc, block.curr()); }); } @@ -1132,6 +1186,24 @@ impl Compiler { self.for_loop(block); } + (Token::Break, ..) => { + self.eat(); + let addr = add_op(self, block, Op::Illegal); + let stack_size = self.frame().stack.len(); + if self.frame_mut().add_break(addr, stack_size, block).is_err() {; + error!(self, "Cannot place 'break' outside of loop."); + } + } + + (Token::Continue, ..) => { + self.eat(); + let addr = add_op(self, block, Op::Illegal); + let stack_size = self.frame().stack.len(); + if self.frame_mut().add_continue(addr, stack_size, block).is_err() { + error!(self, "Cannot place 'continue' outside of loop."); + } + } + (Token::Ret, ..) => { self.eat(); self.expression(block); -- cgit v1.2.1