mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Implements if-else
compliation
This commit is contained in:
parent
2cf6688e39
commit
07e3af2664
|
@ -99,6 +99,21 @@ impl Compiler {
|
|||
}
|
||||
instrs
|
||||
}
|
||||
Expr::If(c, t, f) => {
|
||||
let mut instrs = self.compile_expr(c.0);
|
||||
let t = self.compile_expr(t.0);
|
||||
if let Some(f) = f {
|
||||
let f = self.compile_expr(f.0);
|
||||
instrs.push(Instr::JumpIfFalse(t.len() + 1));
|
||||
instrs.extend(t);
|
||||
instrs.push(Instr::Jump(f.len()));
|
||||
instrs.extend(f);
|
||||
} else {
|
||||
instrs.push(Instr::JumpIfFalse(t.len()));
|
||||
instrs.extend(t);
|
||||
}
|
||||
instrs
|
||||
}
|
||||
Expr::Do(es) => {
|
||||
let mut instrs = vec![];
|
||||
for e in es {
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
fun foo = \x -> x
|
||||
|
||||
fun main = do
|
||||
foo(1)
|
||||
[1, 2, 3]
|
||||
true
|
||||
print("Hello, World")
|
||||
let seven = 7 in
|
||||
print(5 - seven)
|
||||
|
||||
let a = 34 in
|
||||
let b = 35 in
|
||||
print(a + b)
|
||||
end
|
||||
let foo = if true then 10 else 5 in
|
||||
print(foo)
|
||||
end
|
||||
|
|
|
@ -44,6 +44,9 @@ pub enum Token {
|
|||
Fun,
|
||||
Let,
|
||||
In,
|
||||
If,
|
||||
Then,
|
||||
Else,
|
||||
Do,
|
||||
End,
|
||||
}
|
||||
|
@ -102,6 +105,9 @@ impl std::fmt::Display for Token {
|
|||
Token::Fun => write!(f, "fun"),
|
||||
Token::Let => write!(f, "let"),
|
||||
Token::In => write!(f, "in"),
|
||||
Token::If => write!(f, "if"),
|
||||
Token::Then => write!(f, "then"),
|
||||
Token::Else => write!(f, "else"),
|
||||
Token::Do => write!(f, "do"),
|
||||
Token::End => write!(f, "end"),
|
||||
}
|
||||
|
@ -155,6 +161,9 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
|||
"fun" => Token::Fun,
|
||||
"let" => Token::Let,
|
||||
"in" => Token::In,
|
||||
"if" => Token::If,
|
||||
"then" => Token::Then,
|
||||
"else" => Token::Else,
|
||||
"do" => Token::Do,
|
||||
"end" => Token::End,
|
||||
_ => Token::Sym(s),
|
||||
|
@ -223,6 +232,11 @@ pub enum Expr {
|
|||
Lambda(Vec<String>, Box<Spanned<Self>>),
|
||||
Call(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
Let(Vec<(String, Spanned<Self>)>, Option<Box<Spanned<Self>>>),
|
||||
If(
|
||||
Box<Spanned<Self>>,
|
||||
Box<Spanned<Self>>,
|
||||
Option<Box<Spanned<Self>>>,
|
||||
),
|
||||
Do(Vec<Spanned<Expr>>),
|
||||
}
|
||||
|
||||
|
@ -327,6 +341,15 @@ pub fn expr_parser() -> impl P<Spanned<Expr>> {
|
|||
.map(|binds| Expr::Let(binds, None))
|
||||
.labelled("let");
|
||||
|
||||
let if_ = just(Token::If)
|
||||
.ignore_then(expr.clone())
|
||||
.then_ignore(just(Token::Then))
|
||||
.then(expr.clone())
|
||||
.then(just(Token::Else).ignore_then(expr.clone()).or_not())
|
||||
.map(|((cond, then), else_)| {
|
||||
Expr::If(Box::new(cond), Box::new(then), else_.map(Box::new))
|
||||
});
|
||||
|
||||
let block = just(Token::Do)
|
||||
.ignore_then(expr.clone().repeated())
|
||||
.then_ignore(just(Token::End))
|
||||
|
@ -339,6 +362,7 @@ pub fn expr_parser() -> impl P<Spanned<Expr>> {
|
|||
.or(lam)
|
||||
.or(let_in)
|
||||
.or(let_def)
|
||||
.or(if_)
|
||||
.or(block)
|
||||
.map_with_span(|e, s| (e, s))
|
||||
.boxed()
|
||||
|
|
|
@ -31,7 +31,7 @@ impl Executor {
|
|||
}
|
||||
|
||||
pub fn run(&mut self) -> Result<(), Error> {
|
||||
for _ in 0..self.instrs.len() {
|
||||
while self.ip < self.instrs.len() {
|
||||
self.step()?;
|
||||
self.ip += 1;
|
||||
}
|
||||
|
@ -249,6 +249,19 @@ impl Executor {
|
|||
self.set(name, v)?;
|
||||
}
|
||||
|
||||
Instr::Jump(n) => {
|
||||
self.ip += n;
|
||||
}
|
||||
Instr::JumpIfFalse(n) => {
|
||||
if let Value::Bool(b) = self.pop()? {
|
||||
if !b {
|
||||
self.ip += n;
|
||||
}
|
||||
} else {
|
||||
return Err(Error::make("can't apply `if` to non-boolean", self.ip));
|
||||
}
|
||||
}
|
||||
|
||||
Instr::Print => {
|
||||
let v = self.pop()?;
|
||||
println!("{}", v);
|
||||
|
|
|
@ -159,6 +159,9 @@ pub enum Instr {
|
|||
Get(String), // ┐ 1 + string.len() + 1 bytes
|
||||
Set(String), // ┘
|
||||
|
||||
Jump(usize), // ┐ 9 bytes: 1 byte for the enum, 8 bytes for the usize (64-bit)
|
||||
JumpIfFalse(usize), // ┘
|
||||
|
||||
Print, // 1 byte
|
||||
}
|
||||
|
||||
|
@ -178,7 +181,7 @@ impl Instr {
|
|||
Instr::Pop | Instr::Dup => 1,
|
||||
|
||||
Instr::ListMake(_) | Instr::ListGet(_) | Instr::ListSet(_) => {
|
||||
std::mem::size_of::<usize>() + 1
|
||||
1 + std::mem::size_of::<usize>()
|
||||
}
|
||||
Instr::ListLen | Instr::ListJoin => 1,
|
||||
|
||||
|
@ -193,6 +196,8 @@ impl Instr {
|
|||
|
||||
Instr::Get(s) | Instr::Set(s) => 1 + s.len() + 1,
|
||||
|
||||
Instr::Jump(_) | Instr::JumpIfFalse(_) => 1 + std::mem::size_of::<usize>(),
|
||||
|
||||
Instr::Print => 1,
|
||||
}
|
||||
}
|
||||
|
@ -285,6 +290,15 @@ impl Instr {
|
|||
bytes.push(0x00);
|
||||
}
|
||||
|
||||
Instr::Jump(n) => {
|
||||
bytes.push(index!());
|
||||
bytes.extend(n.to_le_bytes());
|
||||
}
|
||||
Instr::JumpIfFalse(n) => {
|
||||
bytes.push(index!());
|
||||
bytes.extend(n.to_le_bytes());
|
||||
}
|
||||
|
||||
Instr::Print => bytes.push(index!()),
|
||||
}
|
||||
bytes
|
||||
|
|
Loading…
Reference in a new issue