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
|
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 {
|
||||||
|
|
|
@ -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
|
|
||||||
print("Hello, World")
|
|
||||||
let seven = 7 in
|
|
||||||
print(5 - seven)
|
|
||||||
|
|
||||||
let a = 34 in
|
|
||||||
let b = 35 in
|
|
||||||
print(a + b)
|
|
||||||
end
|
end
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue