diff options
| -rw-r--r-- | progs/tests/boolean_ops.sy | 56 | ||||
| -rw-r--r-- | progs/tests/boolean_order.sy | 42 | ||||
| -rw-r--r-- | src/compiler.rs | 37 | ||||
| -rw-r--r-- | src/vm.rs | 2 |
4 files changed, 133 insertions, 4 deletions
diff --git a/progs/tests/boolean_ops.sy b/progs/tests/boolean_ops.sy new file mode 100644 index 0000000..368068b --- /dev/null +++ b/progs/tests/boolean_ops.sy @@ -0,0 +1,56 @@ +start :: fn { + ts := 0 + t :: fn -> bool { + ts += 1 + ret true + } + + fs := 0 + f :: fn -> bool { + fs += 1 + ret false + } + + i :: fn -> bool { + <!> + ret false + } + + if f() && i() { + <!> + } + + if t() || i() { + // Empty + } else { + <!> + } + + if f() && i() && i() { + <!> + } + + if t() || i() || i() { + // Empty + } else { + <!> + } + + fs <=> 2 + ts <=> 2 +} + + + + // if t() || i() && f() { + // // Empty + // } else { + // <!> + // } + + // if f() && t() || i() { + // // Empty + // } else { + // <!> + // } + diff --git a/progs/tests/boolean_order.sy b/progs/tests/boolean_order.sy new file mode 100644 index 0000000..ecec262 --- /dev/null +++ b/progs/tests/boolean_order.sy @@ -0,0 +1,42 @@ +start :: fn { + ts := 0 + t :: fn -> bool { + ts += 1 + ret true + } + + fs := 0 + f :: fn -> bool { + fs += 1 + ret false + } + + i :: fn -> bool { + <!> + ret false + } + + if t() || i() && i() { + // Empty + } else { + <!> + } + + if f() && i() || t() { + // Empty + } else { + <!> + } + + fs <=> 1 + fs = 0 + ts <=> 2 + ts = 0 + + f() && i() || f() <=> t() && f() || f() + f() && i() || f() <=> (t() && f()) || f() + t() && t() && f() || t() <=> t() || i() && i() && i() + + fs <=> 9 + ts <=> 6 +} diff --git a/src/compiler.rs b/src/compiler.rs index dc3bd96..2aad62b 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -182,7 +182,8 @@ macro_rules! push_scope { nextable_enum!(Prec { No, Assert, - Bool, + BoolOr, + BoolAnd, Comp, Term, Factor, @@ -615,7 +616,8 @@ impl Compiler { | Token::NotEqual => Prec::Comp, - Token::And | Token::Or => Prec::Bool, + Token::And => Prec::BoolAnd, + Token::Or => Prec::BoolOr, Token::AssertEqual => Prec::Assert, @@ -656,6 +658,9 @@ impl Compiler { | Token::NotEqual => self.binary(block), + Token::And | Token::Or + => self.binary_bool(block), + Token::LeftBracket => self.index(block), _ => { return false; }, @@ -741,6 +746,34 @@ impl Compiler { add_op(self, block, op); } + fn binary_bool(&mut self, block: &mut Block) { + let op = self.eat(); + + match op { + Token::And => { + add_op(self, block, Op::Copy); + let jump = add_op(self, block, Op::Illegal); + + self.parse_precedence(block, self.precedence(op.clone()).next()); + + block.patch(Op::JmpFalse(block.curr()), jump); + } + + Token::Or => { + add_op(self, block, Op::Copy); + let skipp = add_op(self, block, Op::Illegal); + let jump = add_op(self, block, Op::Illegal); + block.patch(Op::JmpFalse(block.curr()), skipp); + + self.parse_precedence(block, self.precedence(op.clone()).next()); + + block.patch(Op::Jmp(block.curr()), jump); + } + + _ => { error!(self, "Illegal operator"); } + } + } + fn binary(&mut self, block: &mut Block) { let op = self.eat(); @@ -101,8 +101,6 @@ impl VM { if let Entry::Occupied(entry) = self.upvalues.entry(slot) { entry.get().borrow_mut().close(value); entry.remove(); - } else { - unreachable!(); } } |
