1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

Implements let compliation

This commit is contained in:
azur 2022-12-13 23:33:26 +07:00
parent 348d96ec8e
commit 2cf6688e39
4 changed files with 64 additions and 4 deletions

View file

@ -27,8 +27,34 @@ impl Compiler {
instrs.push(Instr::ListMake(count)); instrs.push(Instr::ListMake(count));
instrs instrs
} }
Expr::Unary(_, _) => todo!(), Expr::Unary(op, x) => {
Expr::Binary(_, _, _) => todo!(), 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) => { Expr::Lambda(args, body) => {
vec![Instr::FuncMake(args, self.compile_expr(body.0))] vec![Instr::FuncMake(args, self.compile_expr(body.0))]
} }
@ -45,7 +71,34 @@ impl Compiler {
} }
instrs 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::<Vec<_>>();
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) => { Expr::Do(es) => {
let mut instrs = vec![]; let mut instrs = vec![];
for e in es { for e in es {

View file

@ -13,6 +13,7 @@ fn main() {
if let Some(ast) = ast { if let Some(ast) = ast {
let mut compiler = Compiler::new(); let mut compiler = Compiler::new();
let instrs = compiler.compile_program(ast); let instrs = compiler.compile_program(ast);
instrs.iter().for_each(|i| println!("{:?}", i));
let mut executor = Executor::new(instrs); let mut executor = Executor::new(instrs);
match executor.run() { match executor.run() {
Ok(_) => {} Ok(_) => {}

View file

@ -5,4 +5,10 @@ fun main = do
[1, 2, 3] [1, 2, 3]
true true
print("Hello, World") print("Hello, World")
let seven = 7 in
print(5 - seven)
let a = 34 in
let b = 35 in
print(a + b)
end end

View file

@ -198,7 +198,7 @@ impl Instr {
} }
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
// 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 // so we don't have to rewrite all the first bytes again when
// we changes the order or add new instructions // we changes the order or add new instructions
macro_rules! index { macro_rules! index {