mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
feat: logic jump!
This commit is contained in:
parent
c8c8f202ec
commit
c1cabb0de9
13
blspc/example/if.bbb
Normal file
13
blspc/example/if.bbb
Normal 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
|
|
@ -1 +1,3 @@
|
|||
(if true (print "True") (print "False"))
|
||||
(if true
|
||||
(print (+ 34 35))
|
||||
(print "False"))
|
|
@ -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)),
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
1
blvm/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
Loading…
Reference in a new issue