From 2cf6688e39e9dc232b9cad77af7f08450eaf601a Mon Sep 17 00:00:00 2001 From: azur Date: Tue, 13 Dec 2022 23:33:26 +0700 Subject: [PATCH] Implements `let` compliation --- compiler/src/lib.rs | 59 ++++++++++++++++++++++++++++++++++++++++++--- entry/src/main.rs | 1 + examples/sim.sial | 6 +++++ vm/src/model.rs | 2 +- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index bb6675b..b214207 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -27,8 +27,34 @@ impl Compiler { instrs.push(Instr::ListMake(count)); instrs } - Expr::Unary(_, _) => todo!(), - Expr::Binary(_, _, _) => todo!(), + Expr::Unary(op, x) => { + let mut instrs = self.compile_expr(x.0); + instrs.extend(match op.0 { + parser::UnaryOp::Neg => vec![Instr::NumPush(-1), Instr::NumMul], + parser::UnaryOp::Not => vec![Instr::BoolNot], + }); + instrs + } + Expr::Binary(op, x, y) => { + let mut instrs = self.compile_expr(y.0); + instrs.extend(self.compile_expr(x.0)); + instrs.push(match op.0 { + parser::BinaryOp::Add => Instr::NumAdd, + parser::BinaryOp::Sub => Instr::NumSub, + parser::BinaryOp::Mul => Instr::NumMul, + parser::BinaryOp::Div => Instr::NumDiv, + // parser::BinaryOp::Eq => Instr::Eq, + // parser::BinaryOp::Ne => Instr::Neq, + // parser::BinaryOp::Lt => Instr::Lt, + // parser::BinaryOp::Gt => Instr::Gt, + // parser::BinaryOp::Le => Instr::Lte, + // parser::BinaryOp::Ge => Instr::Gte, + parser::BinaryOp::And => Instr::BoolAnd, + parser::BinaryOp::Or => Instr::BoolOr, + _ => todo!(), + }); + instrs + } Expr::Lambda(args, body) => { vec![Instr::FuncMake(args, self.compile_expr(body.0))] } @@ -45,7 +71,34 @@ impl Compiler { } instrs } - Expr::Let(_, _) => todo!(), + Expr::Let(binds, body) => { + let mut instrs = vec![]; + let binds = binds + .into_iter() + .flat_map(|(name, expr)| { + let mut instrs = self.compile_expr(expr.0); + instrs.extend(vec![Instr::Set(name)]); + instrs + }) + .collect::>(); + if let Some(e) = body { + // If there is a body then we put the bindings + // inside the closure so it gets undefined outside + // the scope + instrs.extend(vec![ + Instr::FuncMake( + vec![], + binds.into_iter().chain(self.compile_expr(e.0)).collect(), + ), + Instr::FuncApply, + ]); + } else { + // If there is no body then we just push the bindings + // to the global scope + instrs.extend(binds); + } + instrs + } Expr::Do(es) => { let mut instrs = vec![]; for e in es { diff --git a/entry/src/main.rs b/entry/src/main.rs index f3af8a6..c387a45 100644 --- a/entry/src/main.rs +++ b/entry/src/main.rs @@ -13,6 +13,7 @@ fn main() { if let Some(ast) = ast { let mut compiler = Compiler::new(); let instrs = compiler.compile_program(ast); + instrs.iter().for_each(|i| println!("{:?}", i)); let mut executor = Executor::new(instrs); match executor.run() { Ok(_) => {} diff --git a/examples/sim.sial b/examples/sim.sial index 43c7df4..25b5d21 100644 --- a/examples/sim.sial +++ b/examples/sim.sial @@ -5,4 +5,10 @@ fun main = do [1, 2, 3] true print("Hello, World") + let seven = 7 in + print(5 - seven) + + let a = 34 in + let b = 35 in + print(a + b) end \ No newline at end of file diff --git a/vm/src/model.rs b/vm/src/model.rs index f5ec740..da223aa 100644 --- a/vm/src/model.rs +++ b/vm/src/model.rs @@ -198,7 +198,7 @@ impl Instr { } pub fn to_bytes(&self) -> Vec { - // a macro that will return the next index and increment it + // A macro that will return the next index and increment it // so we don't have to rewrite all the first bytes again when // we changes the order or add new instructions macro_rules! index {