mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Compare commits
2 commits
07e3af2664
...
0a62f14571
Author | SHA1 | Date | |
---|---|---|---|
azur | 0a62f14571 | ||
azur | a53d7b31f0 |
|
@ -43,15 +43,15 @@ impl Compiler {
|
||||||
parser::BinaryOp::Sub => Instr::NumSub,
|
parser::BinaryOp::Sub => Instr::NumSub,
|
||||||
parser::BinaryOp::Mul => Instr::NumMul,
|
parser::BinaryOp::Mul => Instr::NumMul,
|
||||||
parser::BinaryOp::Div => Instr::NumDiv,
|
parser::BinaryOp::Div => Instr::NumDiv,
|
||||||
// parser::BinaryOp::Eq => Instr::Eq,
|
parser::BinaryOp::Eq => Instr::NumEq,
|
||||||
// parser::BinaryOp::Ne => Instr::Neq,
|
parser::BinaryOp::Ne => todo!(),
|
||||||
// parser::BinaryOp::Lt => Instr::Lt,
|
parser::BinaryOp::Lt => todo!(),
|
||||||
// parser::BinaryOp::Gt => Instr::Gt,
|
parser::BinaryOp::Gt => todo!(),
|
||||||
// parser::BinaryOp::Le => Instr::Lte,
|
parser::BinaryOp::Le => todo!(),
|
||||||
// parser::BinaryOp::Ge => Instr::Gte,
|
parser::BinaryOp::Ge => todo!(),
|
||||||
parser::BinaryOp::And => Instr::BoolAnd,
|
parser::BinaryOp::And => Instr::BoolAnd,
|
||||||
parser::BinaryOp::Or => Instr::BoolOr,
|
parser::BinaryOp::Or => Instr::BoolOr,
|
||||||
_ => todo!(),
|
parser::BinaryOp::Pipe => todo!(),
|
||||||
});
|
});
|
||||||
instrs
|
instrs
|
||||||
}
|
}
|
||||||
|
@ -128,10 +128,13 @@ impl Compiler {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Fun(name, args, body) => {
|
Stmt::Fun(name, args, body) => {
|
||||||
let is_main = name == "main";
|
let is_main = name == "main";
|
||||||
let mut instrs = vec![
|
let mut instrs = match body.0 {
|
||||||
Instr::FuncMake(args, self.compile_expr(body.0)),
|
// If the body is a lambda then we don't have to compile
|
||||||
Instr::Set(name),
|
// it into a function
|
||||||
];
|
Expr::Lambda(_, _) => self.compile_expr(body.0),
|
||||||
|
_ => vec![Instr::FuncMake(args, self.compile_expr(body.0))],
|
||||||
|
};
|
||||||
|
instrs.push(Instr::Set(name));
|
||||||
if is_main {
|
if is_main {
|
||||||
instrs.pop();
|
instrs.pop();
|
||||||
instrs.push(Instr::FuncApply);
|
instrs.push(Instr::FuncApply);
|
||||||
|
|
|
@ -13,9 +13,12 @@ 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));
|
// 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_with(|exec| {
|
||||||
|
// println!("{:?}", exec.stack);
|
||||||
|
Ok(())
|
||||||
|
}) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => println!("Runtime error: {:?}", e),
|
Err(e) => println!("Runtime error: {:?}", e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,22 @@
|
||||||
fun main = do
|
// start
|
||||||
let foo = if true then 10 else 5 in
|
|
||||||
print(foo)
|
fun foo x = do
|
||||||
|
69 // unused
|
||||||
|
print("Hi")
|
||||||
|
x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/* block comment
|
||||||
|
|
||||||
|
fun invalid =
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun fac n = if n == 0 then 1 else n * fac(n - 1)
|
||||||
|
|
||||||
|
fun main = do
|
||||||
|
print(foo(1))
|
||||||
|
print(fac(5))
|
||||||
|
end
|
||||||
|
|
||||||
|
// end
|
|
@ -174,15 +174,25 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
.or(symbol)
|
.or(symbol)
|
||||||
.or(delim)
|
.or(delim)
|
||||||
.or(keyword)
|
.or(keyword)
|
||||||
|
.map_with_span(move |token, span| (token, span))
|
||||||
|
.padded()
|
||||||
.recover_with(skip_then_retry_until([]));
|
.recover_with(skip_then_retry_until([]));
|
||||||
|
|
||||||
let comment = just("--").then(take_until(just('\n'))).padded();
|
let comments = just('/')
|
||||||
|
.then_ignore(
|
||||||
|
just('*')
|
||||||
|
.ignore_then(take_until(just("*/")).ignored())
|
||||||
|
.or(just('/').ignore_then(none_of('\n').ignored().repeated().ignored())),
|
||||||
|
)
|
||||||
|
.padded()
|
||||||
|
.ignored()
|
||||||
|
.repeated();
|
||||||
|
|
||||||
token
|
token
|
||||||
.padded_by(comment.repeated())
|
.padded_by(comments)
|
||||||
.map_with_span(|token, span| (token, span))
|
|
||||||
.padded()
|
|
||||||
.repeated()
|
.repeated()
|
||||||
|
.padded()
|
||||||
|
.then_ignore(end())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lex(src: String) -> (Option<Vec<(Token, Span)>>, Vec<Simple<char>>) {
|
pub fn lex(src: String) -> (Option<Vec<(Token, Span)>>, Vec<Simple<char>>) {
|
||||||
|
|
|
@ -38,6 +38,15 @@ impl Executor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_with<F: Fn(&mut Self) -> Result<(), Error>>(&mut self, f: F) -> Result<(), Error> {
|
||||||
|
while self.ip < self.instrs.len() {
|
||||||
|
self.step()?;
|
||||||
|
self.ip += 1;
|
||||||
|
f(self)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn err(&self, msg: &str) -> Error {
|
fn err(&self, msg: &str) -> Error {
|
||||||
Error::make(msg, self.ip)
|
Error::make(msg, self.ip)
|
||||||
}
|
}
|
||||||
|
@ -93,10 +102,10 @@ impl Executor {
|
||||||
.ok_or_else(|| self.err("invalid instruction pointer"))?;
|
.ok_or_else(|| self.err("invalid instruction pointer"))?;
|
||||||
|
|
||||||
macro_rules! impl_num_binop {
|
macro_rules! impl_num_binop {
|
||||||
($op:tt) => {
|
($op:tt, $ret:ident) => {
|
||||||
match (self.pop()?, self.pop()?) {
|
match (self.pop()?, self.pop()?) {
|
||||||
(Value::Num(a), Value::Num(b)) => {
|
(Value::Num(a), Value::Num(b)) => {
|
||||||
self.stack.push(Value::Num(a $op b));
|
self.stack.push(Value::$ret(a $op b));
|
||||||
}
|
}
|
||||||
_ => return Err(Error::make("can't apply operator to non-numbers", self.ip)),
|
_ => return Err(Error::make("can't apply operator to non-numbers", self.ip)),
|
||||||
}
|
}
|
||||||
|
@ -117,11 +126,12 @@ impl Executor {
|
||||||
Instr::NumPush(x) => {
|
Instr::NumPush(x) => {
|
||||||
self.push(Value::Num(*x))?;
|
self.push(Value::Num(*x))?;
|
||||||
}
|
}
|
||||||
Instr::NumAdd => impl_num_binop!(+),
|
Instr::NumAdd => impl_num_binop!(+, Num),
|
||||||
Instr::NumSub => impl_num_binop!(-),
|
Instr::NumSub => impl_num_binop!(-, Num),
|
||||||
Instr::NumMul => impl_num_binop!(*),
|
Instr::NumMul => impl_num_binop!(*, Num),
|
||||||
Instr::NumDiv => impl_num_binop!(/),
|
Instr::NumDiv => impl_num_binop!(/, Num),
|
||||||
Instr::NumMod => impl_num_binop!(%),
|
Instr::NumMod => impl_num_binop!(%, Num),
|
||||||
|
Instr::NumEq => impl_num_binop!(==, Bool),
|
||||||
|
|
||||||
Instr::BoolPush(x) => {
|
Instr::BoolPush(x) => {
|
||||||
self.push(Value::Bool(*x))?;
|
self.push(Value::Bool(*x))?;
|
||||||
|
|
|
@ -103,7 +103,8 @@ pub enum Instr {
|
||||||
NumSub, // │ 1 byte
|
NumSub, // │ 1 byte
|
||||||
NumMul, // │
|
NumMul, // │
|
||||||
NumDiv, // │
|
NumDiv, // │
|
||||||
NumMod, // ┘
|
NumMod, // │
|
||||||
|
NumEq, // ┘
|
||||||
|
|
||||||
BoolPush(bool), // 2 bytes: 1 byte for the enum, 1 byte for the bool
|
BoolPush(bool), // 2 bytes: 1 byte for the enum, 1 byte for the bool
|
||||||
BoolAnd, // ┐ 1 byte
|
BoolAnd, // ┐ 1 byte
|
||||||
|
@ -171,7 +172,12 @@ impl Instr {
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Instr::NumPush(_) => 1 + std::mem::size_of::<i64>(),
|
Instr::NumPush(_) => 1 + std::mem::size_of::<i64>(),
|
||||||
Instr::NumAdd | Instr::NumSub | Instr::NumMul | Instr::NumDiv | Instr::NumMod => 1,
|
Instr::NumAdd
|
||||||
|
| Instr::NumSub
|
||||||
|
| Instr::NumMul
|
||||||
|
| Instr::NumDiv
|
||||||
|
| Instr::NumMod
|
||||||
|
| Instr::NumEq => 1,
|
||||||
|
|
||||||
Instr::BoolPush(_) => 1 + std::mem::size_of::<bool>(),
|
Instr::BoolPush(_) => 1 + std::mem::size_of::<bool>(),
|
||||||
Instr::BoolAnd | Instr::BoolOr | Instr::BoolNot => 1,
|
Instr::BoolAnd | Instr::BoolOr | Instr::BoolNot => 1,
|
||||||
|
@ -227,6 +233,7 @@ impl Instr {
|
||||||
Instr::NumMul => bytes.push(index!()),
|
Instr::NumMul => bytes.push(index!()),
|
||||||
Instr::NumDiv => bytes.push(index!()),
|
Instr::NumDiv => bytes.push(index!()),
|
||||||
Instr::NumMod => bytes.push(index!()),
|
Instr::NumMod => bytes.push(index!()),
|
||||||
|
Instr::NumEq => bytes.push(index!()),
|
||||||
|
|
||||||
Instr::BoolPush(b) => {
|
Instr::BoolPush(b) => {
|
||||||
bytes.push(index!());
|
bytes.push(index!());
|
||||||
|
|
Loading…
Reference in a new issue