From 7248580e24d635e2851e9c28d511e61dc43b4411 Mon Sep 17 00:00:00 2001 From: azur Date: Wed, 14 Dec 2022 13:32:02 +0700 Subject: [PATCH] Separate `print` and `println` --- compiler/src/lib.rs | 16 ++++++++++------ examples/a.sial | 5 +++++ examples/sim.sial | 24 ++++++++++------------- vm/src/exec.rs | 46 ++++++++++++++++++++++----------------------- vm/src/model.rs | 9 +++++++-- 5 files changed, 55 insertions(+), 45 deletions(-) diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index c2f11b4..db5c99f 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -63,12 +63,16 @@ impl Compiler { for x in xs { instrs.extend(self.compile_expr(x.0)); } - if f.0 == Expr::Sym("print".to_string()) { - instrs.push(Instr::Print); - } else { - instrs.extend(self.compile_expr(f.0)); - instrs.push(Instr::FuncApply); - } + if let Expr::Sym(fname) = &f.0 { + match fname.as_str() { + "print" => instrs.push(Instr::Print), + "println" => instrs.push(Instr::PrintLn), + _ => { + instrs.extend(self.compile_expr(f.0)); + instrs.push(Instr::FuncApply); + } + } + }; instrs } Expr::Let(binds, body) => { diff --git a/examples/a.sial b/examples/a.sial index 7be7929..48564bc 100644 --- a/examples/a.sial +++ b/examples/a.sial @@ -13,4 +13,9 @@ fun main = do let result = add(34, 35) println(result) +end + +fun main = do + let add = \x y -> x + y in + print(add(34, succ(34))) end \ No newline at end of file diff --git a/examples/sim.sial b/examples/sim.sial index 10155f2..fcf785b 100644 --- a/examples/sim.sial +++ b/examples/sim.sial @@ -1,22 +1,18 @@ -// start - fun foo x = do - 69 // unused - print("Hi") x 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 + let succ = \x -> x + 1, + n = 34, + in + println(n + succ(n)) -// end \ No newline at end of file + print("Hello ") + println("World!") + + println(foo(1)) + println(fac(5)) +end \ No newline at end of file diff --git a/vm/src/exec.rs b/vm/src/exec.rs index 7b5129a..cb4e438 100644 --- a/vm/src/exec.rs +++ b/vm/src/exec.rs @@ -101,23 +101,13 @@ impl Executor { .get(self.ip) .ok_or_else(|| self.err("invalid instruction pointer"))?; - macro_rules! impl_num_binop { - ($op:tt, $ret:ident) => { + macro_rules! impl_binop { + ($op:tt, $inp:ident, $ret:ident) => { 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)); } - _ => return Err(Error::make("can't apply operator to non-numbers", 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)), + _ => return Err(Error::make(format!("can't apply operator to non-{}", stringify!($inp)).as_str(), self.ip)), } }; } @@ -126,18 +116,18 @@ impl Executor { Instr::NumPush(x) => { self.push(Value::Num(*x))?; } - Instr::NumAdd => impl_num_binop!(+, Num), - Instr::NumSub => impl_num_binop!(-, Num), - Instr::NumMul => impl_num_binop!(*, Num), - Instr::NumDiv => impl_num_binop!(/, Num), - Instr::NumMod => impl_num_binop!(%, Num), - Instr::NumEq => impl_num_binop!(==, Bool), + Instr::NumAdd => impl_binop!(+, Num, Num), + Instr::NumSub => impl_binop!(-, Num, Num), + Instr::NumMul => impl_binop!(*, Num, Num), + Instr::NumDiv => impl_binop!(/, Num, Num), + Instr::NumMod => impl_binop!(%, Num, Num), + Instr::NumEq => impl_binop!(==, Num, Bool), Instr::BoolPush(x) => { self.push(Value::Bool(*x))?; } - Instr::BoolAnd => impl_bool_binop!(&&), - Instr::BoolOr => impl_bool_binop!(||), + Instr::BoolAnd => impl_binop!(&&, Bool, Bool), + Instr::BoolOr => impl_binop!(||, Bool, Bool), Instr::BoolNot => { if let Value::Bool(b) = self.pop()? { self.push(Value::Bool(!b))?; @@ -149,7 +139,13 @@ impl Executor { Instr::StrPush(x) => { 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 => { self.pop()?; } @@ -273,6 +269,10 @@ impl Executor { } Instr::Print => { + let v = self.pop()?; + print!("{}", v); + } + Instr::PrintLn => { let v = self.pop()?; println!("{}", v); } diff --git a/vm/src/model.rs b/vm/src/model.rs index 5dd6919..8ce6375 100644 --- a/vm/src/model.rs +++ b/vm/src/model.rs @@ -124,6 +124,7 @@ pub enum Instr { // └─╼ null delimiter // Total of 15 bytes (1 + 13 + 1) StrPush(String), // 1 + string.len() + 1 bytes + StrConcat, // 1 byte Pop, // ┐ 1 byte Dup, // ┘ @@ -163,7 +164,8 @@ pub enum Instr { Jump(usize), // ┐ 9 bytes: 1 byte for the enum, 8 bytes for the usize (64-bit) JumpIfFalse(usize), // ┘ - Print, // 1 byte + Print, // ┐ 1 byte + PrintLn, // ┘ } static mut INSTR_INDEX: Cell = Cell::new(0); @@ -183,6 +185,7 @@ impl Instr { Instr::BoolAnd | Instr::BoolOr | Instr::BoolNot => 1, Instr::StrPush(s) => 1 + s.len() + 1, + Instr::StrConcat => 1, Instr::Pop | Instr::Dup => 1, @@ -204,7 +207,7 @@ impl Instr { Instr::Jump(_) | Instr::JumpIfFalse(_) => 1 + std::mem::size_of::(), - Instr::Print => 1, + Instr::Print | Instr::PrintLn => 1, } } @@ -248,6 +251,7 @@ impl Instr { bytes.extend(s.as_bytes()); bytes.push(0x00); } + Instr::StrConcat => bytes.push(index!()), Instr::Pop => bytes.push(index!()), Instr::Dup => bytes.push(index!()), @@ -307,6 +311,7 @@ impl Instr { } Instr::Print => bytes.push(index!()), + Instr::PrintLn => bytes.push(index!()), } bytes }