diff --git a/src/compiler.rs b/src/compiler.rs index e13de29..465eca9 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -315,14 +315,10 @@ pub struct Compiler<'a> { loop_info: Vec, } -fn is_binding(expr: &Spanned) -> bool { +fn is_let(expr: &Spanned) -> bool { let (ast, _) = expr; use Ast::*; - match ast { - Let(..) | LBox(..) => true, - // Fn(name, ..) => !name.is_empty(), - _ => false, - } + matches!(ast, Let(..)) } impl<'a> Compiler<'a> { @@ -358,14 +354,6 @@ impl<'a> Compiler<'a> { } } - // pub fn kw_from(&self, kw: &str) -> Option { - // self.kw_index_from(kw).map(Value::Keyword) - // } - - // pub fn kw_index_from(&self, kw: &str) -> Option { - // self.chunk.keywords.iter().position(|s| *s == kw) - // } - pub fn visit(&mut self, node: &'static Spanned) { let root_node = self.ast; let root_span = self.span; @@ -377,18 +365,6 @@ impl<'a> Compiler<'a> { self.span = root_span; } - // fn emit_keyword(&mut self, s: &'static str) { - // // let existing_kw = self.chunk.keywords.iter().position(|kw| *kw == s); - // // let kw_index = match existing_kw { - // // Some(index) => index, - // // None => self.chunk.keywords.len(), - // // }; - // // if kw_index == self.chunk.keywords.len() { - // // self.chunk.keywords.push(s); - // // } - // self.emit_constant(Value::Keyword(s)); - // } - fn emit_constant(&mut self, val: Value) { let const_idx = if let Some(idx) = self.chunk.constants.iter().position(|v| *v == val) { idx @@ -404,11 +380,7 @@ impl<'a> Compiler<'a> { ) } self.emit_op(Op::Constant); - // self.chunk.bytecode.push(Op::Constant as u8); - // self.spans.push(self.span); self.emit_byte(const_idx); - // self.chunk.bytecode.push(constant_index as u8); - // self.spans.push(self.span); self.stack_depth += 1; } @@ -535,12 +507,6 @@ impl<'a> Compiler<'a> { self.stack_depth += 1; } String(s) => { - // let existing_str = self.chunk.strings.iter().position(|e| e == s); - // let str_index = match existing_str { - // Some(idx) => idx, - // None => self.chunk.strings.len(), - // }; - // self.chunk.strings.push(s); self.emit_constant(Value::Interned(s)); } Keyword(s) => self.emit_constant(Value::Keyword(s)), @@ -548,31 +514,37 @@ impl<'a> Compiler<'a> { self.scope_depth += 1; let stack_depth = self.stack_depth; for expr in lines.iter().take(lines.len() - 1) { - if is_binding(expr) { + if is_let(expr) { self.visit(expr); } else { self.visit(expr); self.pop(); - // self.emit_op(Op::Pop); } } let last_expr = lines.last().unwrap(); - // TODO: make sure this actually returns the RHS of the expression - if is_binding(last_expr) { - self.visit(last_expr); - self.emit_op(Op::Duplicate); - self.stack_depth += 1; - } else { - self.visit(last_expr); - self.stack_depth += 1; + match last_expr { + (Let(patt, expr), _) => { + self.match_depth = 0; + self.emit_op(Op::ResetMatch); + self.visit(expr); + let expr_pos = self.stack_depth - 1; + self.visit(patt); + self.emit_op(Op::PanicIfNoMatch); + self.emit_op(Op::PushBinding); + self.emit_byte(expr_pos); + self.stack_depth += 1; + } + _ => { + self.visit(last_expr); + } } + self.stack_depth += 1; self.emit_op(Op::Store); self.scope_depth -= 1; - // reset bindings + while let Some(binding) = self.bindings.last() { if binding.depth > self.scope_depth { - let binding = self.bindings.pop().unwrap(); - println!("popping: {:?}", binding); + self.bindings.pop(); } else { break; } @@ -670,14 +642,6 @@ impl<'a> Compiler<'a> { self.bind(word); } StringPattern(s) => { - // let existing_str = self.chunk.strings.iter().position(|e| e == s); - // let str_index = match existing_str { - // Some(idx) => idx, - // None => self.chunk.strings.len(), - // }; - // if str_index == self.chunk.strings.len() { - // self.chunk.strings.push(s) - // } self.match_constant(Value::Interned(s)); } TuplePattern(members) => { @@ -706,11 +670,6 @@ impl<'a> Compiler<'a> { self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1; } for _ in 0..members.len() { - // this only runs if there's no match - // so don't change the representation of the stack - // contingencies will be handled by the binding forms - // (i.e., `let` and `match`) - // thus: emit Op::Pop directly self.emit_op(Op::Pop); } self.chunk.bytecode[before_load_tup_idx] = @@ -743,11 +702,6 @@ impl<'a> Compiler<'a> { self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1; } for _ in 0..members.len() { - // this only runs if there's no match - // so don't change the representation of the stack - // contingencies will be handled by the binding forms - // (i.e., `let` and `match`) - // thus: emit Op::Pop directly self.emit_op(Op::Pop); } self.chunk.bytecode[before_load_list_idx] = @@ -766,15 +720,10 @@ impl<'a> Compiler<'a> { let (PairPattern(key, pattern), _) = pair else { unreachable!() }; - // algo: - // push the keyword onto the stack self.emit_constant(Value::Keyword(key)); - // pull the value out of the dict self.emit_op(Op::LoadDictValue); self.emit_byte(dict_stack_pos); - // visit the pattern self.visit(pattern); - // jump if no match self.emit_op(Op::JumpIfNoMatch); jump_idxes.push(self.len()); self.emit_byte(0xff); @@ -815,30 +764,14 @@ impl<'a> Compiler<'a> { self.bind(name); } Dict(pairs) => { - println!("Compiling dict of len {}", pairs.len()); - println!("Stack len: {}", self.stack_depth); for pair in pairs { self.visit(pair); - println!("Visited pair {:?}", pair); - println!("Current stack len: {}", self.stack_depth); } self.emit_op(Op::PushDict); self.emit_byte(pairs.len()); self.stack_depth = self.stack_depth + 1 - (pairs.len() * 2); - println!( - "Finished compiling dict, stack len now: {}", - self.stack_depth - ); } Pair(key, value) => { - // let existing_kw = self.chunk.keywords.iter().position(|kw| kw == key); - // let kw_index = match existing_kw { - // Some(index) => index, - // None => self.chunk.keywords.len(), - // }; - // if kw_index == self.chunk.keywords.len() { - // self.chunk.keywords.push(key); - // } self.emit_constant(Value::Keyword(key)); self.visit(value); } @@ -905,10 +838,6 @@ impl<'a> Compiler<'a> { self.stack_depth -= args.len() - 1; } None => { - //algo - // visit all the args - // then store them - // then call the function let arity = args.len(); for arg in args { self.visit(arg); diff --git a/src/main.rs b/src/main.rs index eb9140e..6f431b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,12 +76,12 @@ pub fn run(src: &'static str) { pub fn main() { env::set_var("RUST_BACKTRACE", "1"); let src = " +let bar = 42 let foo = { - let bar = :bar - fn baz () -> bar + let (1, 2, 3) = (1, 2, 3) } -foo () +foo "; run(src); } diff --git a/src/value.rs b/src/value.rs index f699a34..cb8fee9 100644 --- a/src/value.rs +++ b/src/value.rs @@ -6,24 +6,6 @@ use imbl::{HashMap, Vector}; use std::cell::RefCell; use std::rc::Rc; -// #[derive(Clone, Debug, PartialEq)] -// pub struct Defined { -// pub name: &'static str, -// pub doc: Option<&'static str>, -// // pub enclosing: Vec<(usize, Value)>, -// // pub has_run: bool, -// // pub input: &'static str, -// // pub src: &'static str, -// pub chunks: Vec<(u8, Chunk)>, -// pub closed: Vec, -// } - -// impl Defined { -// pub fn close(&mut self, val: Value) { -// self.closed.push(val); -// } -// } - #[derive(Clone, Debug, PartialEq)] pub enum LFn { Declared { @@ -162,7 +144,7 @@ impl std::fmt::Display for Value { .collect::>() .join(", ") ), - Box(value) => write!(f, "box {}", value.as_ref().borrow()), + Box(value) => write!(f, "box {{ {} }}", value.as_ref().borrow()), Fn(lfn) => write!(f, "fn {}", lfn.name()), BaseFn(_) => write!(f, "base fn"), }