feat: logic jump!

replace/7746dba3cc6b3860afe1faf69e86ed84ee46988d
Natapat Samutpong 2022-01-26 10:23:36 +07:00
parent c8c8f202ec
commit c1cabb0de9
6 changed files with 132 additions and 44 deletions

13
blspc/example/if.bbb Normal file
View File

@ -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

View File

@ -1 +1,3 @@
(if true (print "True") (print "False"))
(if true
(print (+ 34 35))
(print "False"))

View File

@ -6,6 +6,7 @@ use crate::{
pub struct Compiler {
pub instructions: Vec<Instr>,
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<Vec<Instr>, String> {
pub fn compile(&mut self, ast: Sexpr, depth: usize) -> Result<Vec<Instr>, 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<Vec<Instr>, String> {
fn compile_atom(&mut self, atom: &Sexpr, depth: usize) -> Result<Vec<Instr>, 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<Vec<Instr>, String> {
fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr], depth: usize) -> Result<Vec<Instr>, 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)),

View File

@ -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),
}
}
}

View File

@ -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();
}
},

1
blvm/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target