From 9f7e80dae277c23f206f35cf32ecdb9b598baa74 Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Wed, 2 Feb 2022 02:57:35 +0700 Subject: [PATCH] feat: if --- README.md | 10 +++++++--- blspc/src/compiler/compile.rs | 16 +++++++++++++--- blspc/src/vm/instr.rs | 10 ++++++---- blspc/src/vm/parser.rs | 3 ++- blspc/src/vm/vm.rs | 6 +++++- example/if.blsp | 7 ++++--- 6 files changed, 37 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a3a5bae..8cc1965 100644 --- a/README.md +++ b/README.md @@ -24,12 +24,16 @@ Hello, World! DONE: - Parsing, Compiling, Running(VM) - Intrinsic: - - `fun`, `do`, `print` - - Math: + - `fun`, `do`, `print`, `if` + - Math: + - `+` , `add` + - `-` , `sub` + - `*` , `mul` + - `/` , `div` TODO: - Prove turing complete - Do the intrinsic left - Quote, Quasiquote, etc. - Optimizing -- Remove unnecessary copying in the entire codebase +- Remove unnecessary copying in the entire codebase (also with `.unwrap()`) diff --git a/blspc/src/compiler/compile.rs b/blspc/src/compiler/compile.rs index c5a8ddb..9862107 100644 --- a/blspc/src/compiler/compile.rs +++ b/blspc/src/compiler/compile.rs @@ -49,6 +49,18 @@ impl Compiler { result.append(&mut self.compile(body.clone())?); result.push(Instr::Return); }, + "if" => { + let mut cond = self.compile(cdr[0].clone())?; + result.append(&mut cond); + + let mut then = self.compile(cdr[1].clone())?; + let mut else_ = self.compile(cdr[2].clone())?; + + result.push(Instr::JumpIfFalse { to: then.len() + 1}); // +1 for the jump instr + result.append(&mut then); + result.push(Instr::Jump { to: else_.len() }); + result.append(&mut else_); + } _ => { result.append(&mut self.compile_intrinsic(call, &cdr)?); } @@ -72,8 +84,6 @@ impl Compiler { match intrinsic.as_str() { "print" => { result.append(&mut self.compile(args[0].clone())?); - let to = self.next_register(); - let call_register = self.next_register(); result.push(Instr::Push { value: Type::Int(1) }); result.push(Instr::Call); @@ -141,7 +151,7 @@ impl Compiler { }, Symbol(s) => { result.push(Instr::Comment { text: format!("{} variable", comp) }); - result.push(Instr::Jump { to: format!("function_{}", s), }); + result.push(Instr::JumpLabel { to: format!("function_{}", s), }); }, _ => { result.append(&mut self.compile(atom.clone())?); } } diff --git a/blspc/src/vm/instr.rs b/blspc/src/vm/instr.rs index 4342cb4..dff6341 100644 --- a/blspc/src/vm/instr.rs +++ b/blspc/src/vm/instr.rs @@ -189,9 +189,10 @@ pub enum Instr { // Stack arithmetic. Add, Sub, Mul, Div, - // Jumping - Jump { to: String }, - PopJumpIfFalse { to: usize }, + // Jumping. + JumpLabel { to: String }, // Jump to (function) label. + Jump { to: usize }, // Jump with offset. + JumpIfFalse { to: usize }, Return, } @@ -212,8 +213,9 @@ impl Display for Instr { Instr::Sub => write!(f, " SUB"), Instr::Mul => write!(f, " MUL"), Instr::Div => write!(f, " DIV"), + Instr::JumpLabel { to } => write!(f, " JMPL {}", to), Instr::Jump { to } => write!(f, " JMP {}", to), - Instr::PopJumpIfFalse { to } => write!(f, " PJMPF {}", to), + Instr::JumpIfFalse { to } => write!(f, " JMPF {}", to), Instr::Return => write!(f, " RET"), } } diff --git a/blspc/src/vm/parser.rs b/blspc/src/vm/parser.rs index d2bcb96..cdab8c0 100644 --- a/blspc/src/vm/parser.rs +++ b/blspc/src/vm/parser.rs @@ -28,7 +28,8 @@ pub fn parse_instr(src: &str) -> Vec { "SUB" => { result.push(Instr::Sub); }, "MUL" => { result.push(Instr::Mul); }, "DIV" => { result.push(Instr::Div); }, - "JMP" => { result.push(Instr::Jump { to: tokens[1].to_string() }); }, + "JMPL" => { result.push(Instr::JumpLabel { to: tokens[1].to_string() }); }, + "JMP" => { result.push(Instr::Jump { to: tokens[1].parse::().unwrap() }); }, "PJMPF" => todo!(), "RET" => { result.push(Instr::Return); }, _ => { diff --git a/blspc/src/vm/vm.rs b/blspc/src/vm/vm.rs index f3af8ac..1630f85 100644 --- a/blspc/src/vm/vm.rs +++ b/blspc/src/vm/vm.rs @@ -119,12 +119,16 @@ impl VM { self.push((lhs / rhs)?)?; continue 'tco; }, - Jump { to } => { + JumpLabel { to } => { let pointer = self.get_function_pointer(to.to_string())?; self.jumped_from = self.instr_pointer; self.instr_pointer = pointer; continue 'tco; }, + Jump { to } => { + self.instr_pointer += *to as isize + 1; + continue 'tco; + }, Return => { if self.jumped_from == 0 { return Ok(()); } self.instr_pointer = self.jumped_from; diff --git a/example/if.blsp b/example/if.blsp index abda693..2b008d1 100644 --- a/example/if.blsp +++ b/example/if.blsp @@ -1,3 +1,4 @@ -(if true - (print (+ 34 35)) - (print "False")) \ No newline at end of file +(fun main + (if true + (print "True") + (print "False"))) \ No newline at end of file