feat(tvix/compiler): implement ||
operator
Same dance as `&&` but logically inverted. Change-Id: I213e200e3836527e9abe510f354ee7cd1f70d041 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6151 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
4b920912b8
commit
c7c7ab9bd4
3 changed files with 29 additions and 6 deletions
|
@ -148,8 +148,8 @@ impl Compiler {
|
|||
// standard binary operators).
|
||||
match op.operator().unwrap() {
|
||||
BinOpKind::And => return self.compile_and(op),
|
||||
BinOpKind::Or => return self.compile_or(op),
|
||||
BinOpKind::Implication => todo!(),
|
||||
BinOpKind::Or => todo!(),
|
||||
|
||||
_ => {}
|
||||
};
|
||||
|
@ -354,15 +354,31 @@ impl Compiler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_or(&mut self, node: rnix::types::BinOp) -> EvalResult<()> {
|
||||
debug_assert!(
|
||||
matches!(node.operator(), Some(BinOpKind::Or)),
|
||||
"compile_or called with wrong operator kind: {:?}",
|
||||
node.operator(),
|
||||
);
|
||||
|
||||
// Leave left-hand side value on the stack
|
||||
self.compile(node.lhs().unwrap())?;
|
||||
|
||||
// Opposite of above: If this value is **true**, we can
|
||||
// short-circuit the right-hand side.
|
||||
let end_idx = self.chunk.add_op(OpCode::OpJumpIfTrue(0));
|
||||
self.chunk.add_op(OpCode::OpPop);
|
||||
self.compile(node.rhs().unwrap())?;
|
||||
self.patch_jump(end_idx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn patch_jump(&mut self, idx: CodeIdx) {
|
||||
let offset = self.chunk.code.len() - 1 - idx.0;
|
||||
|
||||
match &mut self.chunk.code[idx.0] {
|
||||
OpCode::OpJump(n) => {
|
||||
*n = offset;
|
||||
}
|
||||
|
||||
OpCode::OpJumpIfFalse(n) => {
|
||||
OpCode::OpJump(n) | OpCode::OpJumpIfFalse(n) | OpCode::OpJumpIfTrue(n) => {
|
||||
*n = offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ pub enum OpCode {
|
|||
|
||||
// Logical operators & generic jumps
|
||||
OpJump(usize),
|
||||
OpJumpIfTrue(usize),
|
||||
OpJumpIfFalse(usize),
|
||||
|
||||
// Attribute sets
|
||||
|
|
|
@ -176,6 +176,12 @@ impl VM {
|
|||
self.ip += offset;
|
||||
}
|
||||
|
||||
OpCode::OpJumpIfTrue(offset) => {
|
||||
if self.peek(0).as_bool()? {
|
||||
self.ip += offset;
|
||||
}
|
||||
}
|
||||
|
||||
OpCode::OpJumpIfFalse(offset) => {
|
||||
if !self.peek(0).as_bool()? {
|
||||
self.ip += offset;
|
||||
|
|
Loading…
Reference in a new issue