From c1cabb0de9497ce38590f49a1244453106dbe733 Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Wed, 26 Jan 2022 10:23:36 +0700 Subject: [PATCH] feat: logic jump! --- blspc/example/if.bbb | 13 ++++ blspc/example/if.blsp | 4 +- blspc/src/compiler/compile.rs | 119 ++++++++++++++++++++++++++-------- blspc/src/compiler/lib.rs | 37 ++++++----- blspc/src/main.rs | 2 +- blvm/.gitignore | 1 + 6 files changed, 132 insertions(+), 44 deletions(-) create mode 100644 blspc/example/if.bbb create mode 100644 blvm/.gitignore diff --git a/blspc/example/if.bbb b/blspc/example/if.bbb new file mode 100644 index 0000000..1c3b8c5 --- /dev/null +++ b/blspc/example/if.bbb @@ -0,0 +1,13 @@ +1: STORE r1 $true +2: JUMP_IF_FALSE r1 9 +3: STORE r2 $34 +4: STORE r3 $35 +5: IADD r2 r3 r4 +6: STORE r5 $1 +7: CALL r5 r4 +8: JUMP 12 +9: STORE r6 $"False" +10: STORE r7 $1 +11: CALL r7 r6 +12: STORE r8 $0 +13: RETURN r8 diff --git a/blspc/example/if.blsp b/blspc/example/if.blsp index f0c6555..abda693 100644 --- a/blspc/example/if.blsp +++ b/blspc/example/if.blsp @@ -1 +1,3 @@ -(if true (print "True") (print "False")) \ No newline at end of file +(if true + (print (+ 34 35)) + (print "False")) \ No newline at end of file diff --git a/blspc/src/compiler/compile.rs b/blspc/src/compiler/compile.rs index 00fcc1e..b7b6956 100644 --- a/blspc/src/compiler/compile.rs +++ b/blspc/src/compiler/compile.rs @@ -6,6 +6,7 @@ use crate::{ pub struct Compiler { pub instructions: Vec, pub register_pointer: usize, + pub label_pointer: usize, } impl Compiler { @@ -13,6 +14,7 @@ impl Compiler { Compiler { instructions: Vec::new(), register_pointer: 1, + label_pointer: 1, } } @@ -22,11 +24,21 @@ impl Compiler { r } - fn current_pointer(&self) -> Register { + fn current_register(&self) -> Register { Register { value: self.register_pointer - 1 } } + + fn next_label(&mut self) -> usize { + let l = self.label_pointer; + self.label_pointer += 1; + l + } + + fn current_label(&self) -> usize { + self.label_pointer - 1 + } - pub fn compile(&mut self, ast: Sexpr) -> Result, String> { + pub fn compile(&mut self, ast: Sexpr, depth: usize) -> Result, String> { let mut result = Vec::new(); match ast { @@ -36,24 +48,69 @@ impl Compiler { match s.as_str() { "do" => { for c in cdr { - result.append(&mut self.compile(c)?); + result.append(&mut self.compile(c, depth + 1)?); } } + "if" => { + // TODO: Remove .clone() + let mut cond = self.compile(cdr[0].clone(), depth + 1)?; + let cond_register = self.current_register(); + + result.append(&mut cond); + + result.push(Instr::JumpIfFalse { + cond: cond_register, + to: 999, // To be replaced later + label: self.next_label(), + }); + + let mut then = self.compile(cdr[1].clone(), depth + 1)?; + let jump_label = self.next_label(); + + let mut else_ = self.compile(cdr[2].clone(), depth + 1)?; + let else_label = self.current_label() - else_.len() + 1; + + let idx = result.len() - 1; + match result[idx] { + Instr::JumpIfFalse { cond: c, to: _, label: l } => { + result[idx] = Instr::JumpIfFalse { cond: c, to: else_label, label: l, }; + } + _ => unreachable!(), + } + + result.append(&mut then); + result.push(Instr::Jump { + to: self.current_label() + 1, + label: jump_label, + }); + result.append(&mut else_); + } _ => { - result.append(&mut self.compile_intrinsic(s, &cdr)?); + result.append(&mut self.compile_intrinsic(s, &cdr, depth + 1)?); } } } _ => return Err(format!("Expected symbol, got {:?}", car)), } } - _ => { dbg!(ast); unimplemented!() } + _ => { result.append(&mut self.compile_atom(&ast, depth + 1)?); }, } + if depth == 0 { + result.push(Instr::Store { + address: self.next_register(), + value: Type::Int(0), + label: self.next_label(), + }); + result.push(Instr::Return { + value: self.current_register(), + label: self.next_label(), + }); + } Ok(result) } - fn compile_atom(&mut self, atom: &Sexpr) -> Result, String> { + fn compile_atom(&mut self, atom: &Sexpr, depth: usize) -> Result, String> { let mut result = Vec::new(); match atom { @@ -62,6 +119,7 @@ impl Compiler { result.push(Instr::Store { address: r, value: Type::Int(*i), + label: self.next_label(), }); } Float(f) => { @@ -69,6 +127,7 @@ impl Compiler { result.push(Instr::Store { address: r, value: Type::Float(*f), + label: self.next_label(), }); } Boolean(b) => { @@ -76,6 +135,7 @@ impl Compiler { result.push(Instr::Store { address: r, value: Type::Boolean(*b), + label: self.next_label(), }); } Str(s) => { @@ -83,43 +143,46 @@ impl Compiler { result.push(Instr::Store { address: r, value: Type::String(s.to_string()), + label: self.next_label(), }); } _ => { - result.append(&mut self.compile(atom.clone())?); + result.append(&mut self.compile(atom.clone(), depth + 1)?); } } Ok(result) } - fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result, String> { + fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr], depth: usize) -> Result, String> { let mut result = Vec::new(); match intrinsic.as_str() { "print" => { - let mut arg = self.compile_atom(&args[0])?; + let mut arg = self.compile_atom(&args[0], depth + 1)?; result.append(&mut arg); - let arg_pointer = self.current_pointer(); + let arg_pointer = self.current_register(); let call_register = self.next_register(); result.push(Instr::Store { address: call_register, value: Type::Int(1), + label: self.next_label(), }); result.push(Instr::Call { address: call_register, args: arg_pointer, + label: self.next_label(), }); }, "add" | "+" => { - let mut lhs = self.compile_atom(&args[0])?; - let lhs_pointer = self.current_pointer(); + let mut lhs = self.compile_atom(&args[0], depth + 1)?; + let lhs_pointer = self.current_register(); result.append(&mut lhs); - let mut rhs = self.compile_atom(&args[1])?; - let rhs_pointer = self.current_pointer(); + let mut rhs = self.compile_atom(&args[1], depth + 1)?; + let rhs_pointer = self.current_register(); result.append(&mut rhs); let result_register = self.next_register(); @@ -127,15 +190,16 @@ impl Compiler { lhs: lhs_pointer, rhs: rhs_pointer, to: result_register, + label: self.next_label(), }); }, "sub" | "-" => { - let mut lhs = self.compile_atom(&args[0])?; - let lhs_pointer = self.current_pointer(); + let mut lhs = self.compile_atom(&args[0], depth + 1)?; + let lhs_pointer = self.current_register(); result.append(&mut lhs); - let mut rhs = self.compile_atom(&args[1])?; - let rhs_pointer = self.current_pointer(); + let mut rhs = self.compile_atom(&args[1], depth + 1)?; + let rhs_pointer = self.current_register(); result.append(&mut rhs); let result_register = self.next_register(); @@ -143,15 +207,16 @@ impl Compiler { lhs: lhs_pointer, rhs: rhs_pointer, to: result_register, + label: self.next_label(), }); }, "mul" | "*" => { - let mut lhs = self.compile_atom(&args[0])?; - let lhs_pointer = self.current_pointer(); + let mut lhs = self.compile_atom(&args[0], depth + 1)?; + let lhs_pointer = self.current_register(); result.append(&mut lhs); - let mut rhs = self.compile_atom(&args[1])?; - let rhs_pointer = self.current_pointer(); + let mut rhs = self.compile_atom(&args[1], depth + 1)?; + let rhs_pointer = self.current_register(); result.append(&mut rhs); let result_register = self.next_register(); @@ -159,15 +224,16 @@ impl Compiler { lhs: lhs_pointer, rhs: rhs_pointer, to: result_register, + label: self.next_label(), }); }, "div" | "/" => { - let mut lhs = self.compile_atom(&args[0])?; - let lhs_pointer = self.current_pointer(); + let mut lhs = self.compile_atom(&args[0], depth + 1)?; + let lhs_pointer = self.current_register(); result.append(&mut lhs); - let mut rhs = self.compile_atom(&args[1])?; - let rhs_pointer = self.current_pointer(); + let mut rhs = self.compile_atom(&args[1], depth + 1)?; + let rhs_pointer = self.current_register(); result.append(&mut rhs); let result_register = self.next_register(); @@ -175,6 +241,7 @@ impl Compiler { lhs: lhs_pointer, rhs: rhs_pointer, to: result_register, + label: self.next_label(), }); }, _ => return Err(format!("Unknown intrinsic: {}", intrinsic)), diff --git a/blspc/src/compiler/lib.rs b/blspc/src/compiler/lib.rs index 65001d3..3fac83b 100644 --- a/blspc/src/compiler/lib.rs +++ b/blspc/src/compiler/lib.rs @@ -33,31 +33,36 @@ impl Display for Register { #[derive(Clone, Debug)] pub enum Instr { // Load a literal value onto the stack. - Load { address: Register }, + Load { address: Register, label: usize }, // Store a literal value into a register. - Store { address: Register, value: Type }, + Store { address: Register, value: Type, label: usize }, // Call intrinsic function. - Call { address: Register, args: Register }, + Call { address: Register, args: Register, label: usize }, // Immediate arithmetic. - IAdd { lhs: Register, rhs: Register, to: Register }, - ISub { lhs: Register, rhs: Register, to: Register }, - IMul { lhs: Register, rhs: Register, to: Register }, - IDiv { lhs: Register, rhs: Register, to: Register }, + IAdd { lhs: Register, rhs: Register, to: Register, label: usize }, + ISub { lhs: Register, rhs: Register, to: Register, label: usize }, + IMul { lhs: Register, rhs: Register, to: Register, label: usize }, + IDiv { lhs: Register, rhs: Register, to: Register, label: usize }, // Jumping - JumpIfFalse { cond: Register, to: Register }, + Jump { to: usize, label: usize }, + JumpIfFalse { cond: Register, to: usize, label: usize }, + + Return { value: Register, label: usize }, } impl Display for Instr { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Instr::Load { address } => write!(f, "LOAD {}", address), - Instr::Store { address, value } => write!(f, "STORE {} {}", address, value), - Instr::Call { address, args } => write!(f, "CALL {} {}", address, args), - Instr::IAdd { lhs, rhs, to } => write!(f, "IADD {} {} {}", lhs, rhs, to), - Instr::ISub { lhs, rhs, to } => write!(f, "ISUB {} {} {}", lhs, rhs, to), - Instr::IMul { lhs, rhs, to } => write!(f, "IMUL {} {} {}", lhs, rhs, to), - Instr::IDiv { lhs, rhs, to } => write!(f, "IDIV {} {} {}", lhs, rhs, to), - Instr::JumpIfFalse { cond, to } => write!(f, "JUMP_IF_FALSE {} {}", cond, to), + Instr::Load { address, label } => write!(f, "{}: LOAD {}", label, address), + Instr::Store { address, value , label} => write!(f, "{}: STORE {} {}", label, address, value), + Instr::Call { address, args, label } => write!(f, "{}: CALL {} {}", label, address, args), + Instr::IAdd { lhs, rhs, to, label } => write!(f, "{}: IADD {} {} {}", label, lhs, rhs, to), + Instr::ISub { lhs, rhs, to, label } => write!(f, "{}: ISUB {} {} {}", label, lhs, rhs, to), + Instr::IMul { lhs, rhs, to, label } => write!(f, "{}: IMUL {} {} {}", label, lhs, rhs, to), + Instr::IDiv { lhs, rhs, to, label } => write!(f, "{}: IDIV {} {} {}", label, lhs, rhs, to), + Instr::Jump { to, label } => write!(f, "{}: JUMP {}", label, to), + Instr::JumpIfFalse { cond, to, label } => write!(f, "{}: JUMP_IF_FALSE {} {}", label, cond, to), + Instr::Return { value, label } => write!(f, "{}: RETURN {}", label, value), } } } \ No newline at end of file diff --git a/blspc/src/main.rs b/blspc/src/main.rs index 9bc6cd1..fdec7ca 100644 --- a/blspc/src/main.rs +++ b/blspc/src/main.rs @@ -29,7 +29,7 @@ fn main() { let mut file = File::create(format!("{}.bbb", file_name)).unwrap(); let mut compiler = Compiler::new(); - for instr in compiler.compile(result.unwrap()).unwrap() { + for instr in compiler.compile(result.unwrap(), 0).unwrap() { write!(file, "{}\n", instr).unwrap(); } }, diff --git a/blvm/.gitignore b/blvm/.gitignore new file mode 100644 index 0000000..c41cc9e --- /dev/null +++ b/blvm/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file