1
1
Fork 0
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:
azur 2022-12-13 23:55:52 +07:00
parent 2cf6688e39
commit 07e3af2664
5 changed files with 71 additions and 15 deletions

View file

@ -99,6 +99,21 @@ impl Compiler {
} }
instrs 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) => { Expr::Do(es) => {
let mut instrs = vec![]; let mut instrs = vec![];
for e in es { for e in es {

View file

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

View file

@ -44,6 +44,9 @@ pub enum Token {
Fun, Fun,
Let, Let,
In, In,
If,
Then,
Else,
Do, Do,
End, End,
} }
@ -102,6 +105,9 @@ impl std::fmt::Display for Token {
Token::Fun => write!(f, "fun"), Token::Fun => write!(f, "fun"),
Token::Let => write!(f, "let"), Token::Let => write!(f, "let"),
Token::In => write!(f, "in"), 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::Do => write!(f, "do"),
Token::End => write!(f, "end"), Token::End => write!(f, "end"),
} }
@ -155,6 +161,9 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
"fun" => Token::Fun, "fun" => Token::Fun,
"let" => Token::Let, "let" => Token::Let,
"in" => Token::In, "in" => Token::In,
"if" => Token::If,
"then" => Token::Then,
"else" => Token::Else,
"do" => Token::Do, "do" => Token::Do,
"end" => Token::End, "end" => Token::End,
_ => Token::Sym(s), _ => Token::Sym(s),
@ -223,6 +232,11 @@ pub enum Expr {
Lambda(Vec<String>, Box<Spanned<Self>>), Lambda(Vec<String>, Box<Spanned<Self>>),
Call(Box<Spanned<Self>>, Vec<Spanned<Self>>), Call(Box<Spanned<Self>>, Vec<Spanned<Self>>),
Let(Vec<(String, Spanned<Self>)>, Option<Box<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>>), Do(Vec<Spanned<Expr>>),
} }
@ -327,6 +341,15 @@ pub fn expr_parser() -> impl P<Spanned<Expr>> {
.map(|binds| Expr::Let(binds, None)) .map(|binds| Expr::Let(binds, None))
.labelled("let"); .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) let block = just(Token::Do)
.ignore_then(expr.clone().repeated()) .ignore_then(expr.clone().repeated())
.then_ignore(just(Token::End)) .then_ignore(just(Token::End))
@ -339,6 +362,7 @@ pub fn expr_parser() -> impl P<Spanned<Expr>> {
.or(lam) .or(lam)
.or(let_in) .or(let_in)
.or(let_def) .or(let_def)
.or(if_)
.or(block) .or(block)
.map_with_span(|e, s| (e, s)) .map_with_span(|e, s| (e, s))
.boxed() .boxed()

View file

@ -31,7 +31,7 @@ impl Executor {
} }
pub fn run(&mut self) -> Result<(), Error> { pub fn run(&mut self) -> Result<(), Error> {
for _ in 0..self.instrs.len() { while self.ip < self.instrs.len() {
self.step()?; self.step()?;
self.ip += 1; self.ip += 1;
} }
@ -249,6 +249,19 @@ impl Executor {
self.set(name, v)?; 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 => { Instr::Print => {
let v = self.pop()?; let v = self.pop()?;
println!("{}", v); println!("{}", v);

View file

@ -159,6 +159,9 @@ pub enum Instr {
Get(String), // ┐ 1 + string.len() + 1 bytes Get(String), // ┐ 1 + string.len() + 1 bytes
Set(String), // ┘ Set(String), // ┘
Jump(usize), // ┐ 9 bytes: 1 byte for the enum, 8 bytes for the usize (64-bit)
JumpIfFalse(usize), // ┘
Print, // 1 byte Print, // 1 byte
} }
@ -178,7 +181,7 @@ impl Instr {
Instr::Pop | Instr::Dup => 1, Instr::Pop | Instr::Dup => 1,
Instr::ListMake(_) | Instr::ListGet(_) | Instr::ListSet(_) => { Instr::ListMake(_) | Instr::ListGet(_) | Instr::ListSet(_) => {
std::mem::size_of::<usize>() + 1 1 + std::mem::size_of::<usize>()
} }
Instr::ListLen | Instr::ListJoin => 1, Instr::ListLen | Instr::ListJoin => 1,
@ -193,6 +196,8 @@ impl Instr {
Instr::Get(s) | Instr::Set(s) => 1 + s.len() + 1, Instr::Get(s) | Instr::Set(s) => 1 + s.len() + 1,
Instr::Jump(_) | Instr::JumpIfFalse(_) => 1 + std::mem::size_of::<usize>(),
Instr::Print => 1, Instr::Print => 1,
} }
} }
@ -285,6 +290,15 @@ impl Instr {
bytes.push(0x00); 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!()), Instr::Print => bytes.push(index!()),
} }
bytes bytes