mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Separate print
and println
This commit is contained in:
parent
0a62f14571
commit
7248580e24
|
@ -63,12 +63,16 @@ impl Compiler {
|
||||||
for x in xs {
|
for x in xs {
|
||||||
instrs.extend(self.compile_expr(x.0));
|
instrs.extend(self.compile_expr(x.0));
|
||||||
}
|
}
|
||||||
if f.0 == Expr::Sym("print".to_string()) {
|
if let Expr::Sym(fname) = &f.0 {
|
||||||
instrs.push(Instr::Print);
|
match fname.as_str() {
|
||||||
} else {
|
"print" => instrs.push(Instr::Print),
|
||||||
|
"println" => instrs.push(Instr::PrintLn),
|
||||||
|
_ => {
|
||||||
instrs.extend(self.compile_expr(f.0));
|
instrs.extend(self.compile_expr(f.0));
|
||||||
instrs.push(Instr::FuncApply);
|
instrs.push(Instr::FuncApply);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
instrs
|
instrs
|
||||||
}
|
}
|
||||||
Expr::Let(binds, body) => {
|
Expr::Let(binds, body) => {
|
||||||
|
|
|
@ -14,3 +14,8 @@ fun main = do
|
||||||
let result = add(34, 35)
|
let result = add(34, 35)
|
||||||
println(result)
|
println(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
fun main = do
|
||||||
|
let add = \x y -> x + y in
|
||||||
|
print(add(34, succ(34)))
|
||||||
|
end
|
|
@ -1,22 +1,18 @@
|
||||||
// start
|
|
||||||
|
|
||||||
fun foo x = do
|
fun foo x = do
|
||||||
69 // unused
|
|
||||||
print("Hi")
|
|
||||||
x
|
x
|
||||||
end
|
end
|
||||||
|
|
||||||
/* block comment
|
|
||||||
|
|
||||||
fun invalid =
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
fun fac n = if n == 0 then 1 else n * fac(n - 1)
|
fun fac n = if n == 0 then 1 else n * fac(n - 1)
|
||||||
|
|
||||||
fun main = do
|
fun main = do
|
||||||
print(foo(1))
|
let succ = \x -> x + 1,
|
||||||
print(fac(5))
|
n = 34,
|
||||||
end
|
in
|
||||||
|
println(n + succ(n))
|
||||||
|
|
||||||
// end
|
print("Hello ")
|
||||||
|
println("World!")
|
||||||
|
|
||||||
|
println(foo(1))
|
||||||
|
println(fac(5))
|
||||||
|
end
|
|
@ -101,23 +101,13 @@ impl Executor {
|
||||||
.get(self.ip)
|
.get(self.ip)
|
||||||
.ok_or_else(|| self.err("invalid instruction pointer"))?;
|
.ok_or_else(|| self.err("invalid instruction pointer"))?;
|
||||||
|
|
||||||
macro_rules! impl_num_binop {
|
macro_rules! impl_binop {
|
||||||
($op:tt, $ret:ident) => {
|
($op:tt, $inp:ident, $ret:ident) => {
|
||||||
match (self.pop()?, self.pop()?) {
|
match (self.pop()?, self.pop()?) {
|
||||||
(Value::Num(a), Value::Num(b)) => {
|
(Value::$inp(a), Value::$inp(b)) => {
|
||||||
self.stack.push(Value::$ret(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(format!("can't apply operator to non-{}", stringify!($inp)).as_str(), self.ip)),
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
macro_rules! impl_bool_binop {
|
|
||||||
($op:tt) => {
|
|
||||||
match (self.pop()?, self.pop()?) {
|
|
||||||
(Value::Bool(a), Value::Bool(b)) => {
|
|
||||||
self.stack.push(Value::Bool(a $op b));
|
|
||||||
}
|
|
||||||
_ => return Err(Error::make("can't apply operator to non-booleans", self.ip)),
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -126,18 +116,18 @@ impl Executor {
|
||||||
Instr::NumPush(x) => {
|
Instr::NumPush(x) => {
|
||||||
self.push(Value::Num(*x))?;
|
self.push(Value::Num(*x))?;
|
||||||
}
|
}
|
||||||
Instr::NumAdd => impl_num_binop!(+, Num),
|
Instr::NumAdd => impl_binop!(+, Num, Num),
|
||||||
Instr::NumSub => impl_num_binop!(-, Num),
|
Instr::NumSub => impl_binop!(-, Num, Num),
|
||||||
Instr::NumMul => impl_num_binop!(*, Num),
|
Instr::NumMul => impl_binop!(*, Num, Num),
|
||||||
Instr::NumDiv => impl_num_binop!(/, Num),
|
Instr::NumDiv => impl_binop!(/, Num, Num),
|
||||||
Instr::NumMod => impl_num_binop!(%, Num),
|
Instr::NumMod => impl_binop!(%, Num, Num),
|
||||||
Instr::NumEq => impl_num_binop!(==, Bool),
|
Instr::NumEq => impl_binop!(==, Num, Bool),
|
||||||
|
|
||||||
Instr::BoolPush(x) => {
|
Instr::BoolPush(x) => {
|
||||||
self.push(Value::Bool(*x))?;
|
self.push(Value::Bool(*x))?;
|
||||||
}
|
}
|
||||||
Instr::BoolAnd => impl_bool_binop!(&&),
|
Instr::BoolAnd => impl_binop!(&&, Bool, Bool),
|
||||||
Instr::BoolOr => impl_bool_binop!(||),
|
Instr::BoolOr => impl_binop!(||, Bool, Bool),
|
||||||
Instr::BoolNot => {
|
Instr::BoolNot => {
|
||||||
if let Value::Bool(b) = self.pop()? {
|
if let Value::Bool(b) = self.pop()? {
|
||||||
self.push(Value::Bool(!b))?;
|
self.push(Value::Bool(!b))?;
|
||||||
|
@ -149,7 +139,13 @@ impl Executor {
|
||||||
Instr::StrPush(x) => {
|
Instr::StrPush(x) => {
|
||||||
self.push(Value::Str(x.clone()))?;
|
self.push(Value::Str(x.clone()))?;
|
||||||
}
|
}
|
||||||
|
Instr::StrConcat => {
|
||||||
|
if let (Value::Str(a), Value::Str(b)) = (self.pop()?, self.pop()?) {
|
||||||
|
self.push(Value::Str(a + &b))?;
|
||||||
|
} else {
|
||||||
|
return Err(Error::make("can't concatenate non-strings", self.ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
Instr::Pop => {
|
Instr::Pop => {
|
||||||
self.pop()?;
|
self.pop()?;
|
||||||
}
|
}
|
||||||
|
@ -273,6 +269,10 @@ impl Executor {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instr::Print => {
|
Instr::Print => {
|
||||||
|
let v = self.pop()?;
|
||||||
|
print!("{}", v);
|
||||||
|
}
|
||||||
|
Instr::PrintLn => {
|
||||||
let v = self.pop()?;
|
let v = self.pop()?;
|
||||||
println!("{}", v);
|
println!("{}", v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ pub enum Instr {
|
||||||
// └─╼ null delimiter
|
// └─╼ null delimiter
|
||||||
// Total of 15 bytes (1 + 13 + 1)
|
// Total of 15 bytes (1 + 13 + 1)
|
||||||
StrPush(String), // 1 + string.len() + 1 bytes
|
StrPush(String), // 1 + string.len() + 1 bytes
|
||||||
|
StrConcat, // 1 byte
|
||||||
|
|
||||||
Pop, // ┐ 1 byte
|
Pop, // ┐ 1 byte
|
||||||
Dup, // ┘
|
Dup, // ┘
|
||||||
|
@ -163,7 +164,8 @@ pub enum Instr {
|
||||||
Jump(usize), // ┐ 9 bytes: 1 byte for the enum, 8 bytes for the usize (64-bit)
|
Jump(usize), // ┐ 9 bytes: 1 byte for the enum, 8 bytes for the usize (64-bit)
|
||||||
JumpIfFalse(usize), // ┘
|
JumpIfFalse(usize), // ┘
|
||||||
|
|
||||||
Print, // 1 byte
|
Print, // ┐ 1 byte
|
||||||
|
PrintLn, // ┘
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut INSTR_INDEX: Cell<u8> = Cell::new(0);
|
static mut INSTR_INDEX: Cell<u8> = Cell::new(0);
|
||||||
|
@ -183,6 +185,7 @@ impl Instr {
|
||||||
Instr::BoolAnd | Instr::BoolOr | Instr::BoolNot => 1,
|
Instr::BoolAnd | Instr::BoolOr | Instr::BoolNot => 1,
|
||||||
|
|
||||||
Instr::StrPush(s) => 1 + s.len() + 1,
|
Instr::StrPush(s) => 1 + s.len() + 1,
|
||||||
|
Instr::StrConcat => 1,
|
||||||
|
|
||||||
Instr::Pop | Instr::Dup => 1,
|
Instr::Pop | Instr::Dup => 1,
|
||||||
|
|
||||||
|
@ -204,7 +207,7 @@ impl Instr {
|
||||||
|
|
||||||
Instr::Jump(_) | Instr::JumpIfFalse(_) => 1 + std::mem::size_of::<usize>(),
|
Instr::Jump(_) | Instr::JumpIfFalse(_) => 1 + std::mem::size_of::<usize>(),
|
||||||
|
|
||||||
Instr::Print => 1,
|
Instr::Print | Instr::PrintLn => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +251,7 @@ impl Instr {
|
||||||
bytes.extend(s.as_bytes());
|
bytes.extend(s.as_bytes());
|
||||||
bytes.push(0x00);
|
bytes.push(0x00);
|
||||||
}
|
}
|
||||||
|
Instr::StrConcat => bytes.push(index!()),
|
||||||
|
|
||||||
Instr::Pop => bytes.push(index!()),
|
Instr::Pop => bytes.push(index!()),
|
||||||
Instr::Dup => bytes.push(index!()),
|
Instr::Dup => bytes.push(index!()),
|
||||||
|
@ -307,6 +311,7 @@ impl Instr {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instr::Print => bytes.push(index!()),
|
Instr::Print => bytes.push(index!()),
|
||||||
|
Instr::PrintLn => bytes.push(index!()),
|
||||||
}
|
}
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue