mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Conditional Jumps
This commit is contained in:
parent
7de2e1c349
commit
53c7dfb1ce
@ -79,6 +79,7 @@ pub enum Op {
|
||||
// Control Flow
|
||||
Bang,
|
||||
Jump(usize),
|
||||
JumpIfTrue(usize),
|
||||
Noop,
|
||||
// Pending Computation
|
||||
InitThunk(usize),
|
||||
@ -139,12 +140,14 @@ impl VM {
|
||||
Op::Bang => return Err(Error {}),
|
||||
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?,
|
||||
Op::Noop => {
|
||||
self.stack.last();
|
||||
// Do nothing
|
||||
}
|
||||
Op::Return => {
|
||||
// TODO(jwall): This means we return back to the start of the frame.
|
||||
}
|
||||
Op::Jump(jp) => self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(*jp))?,
|
||||
Op::Jump(jp) => self.op_jump(*jp)?,
|
||||
Op::JumpIfTrue(jp) => self.op_jump_if_true(*jp)?,
|
||||
Op::Pop => {
|
||||
self.pop()?;
|
||||
}
|
||||
@ -152,12 +155,23 @@ impl VM {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn op_jump(&mut self, jp: usize) -> Result<(), Error> {
|
||||
self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(jp))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn op_jump_if_true(&mut self, jp: usize) -> Result<(), Error> {
|
||||
if let P(Bool(cond)) = self.pop()? {
|
||||
if cond {
|
||||
self.op_jump(jp)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn op_thunk(&mut self, idx: usize, jp: usize) -> Result<(), Error> {
|
||||
self.push(Value::T(idx))?;
|
||||
self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(jp))?;
|
||||
// TODO(jwall): Skip over the rest until we reach the return?
|
||||
Ok(())
|
||||
self.op_jump(jp)
|
||||
}
|
||||
|
||||
fn op_equal(&mut self) -> Result<(), Error> {
|
||||
|
@ -289,3 +289,55 @@ fn test_equality_ops() {
|
||||
assert_eq!(vm.pop().unwrap(), case.1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conditional_jump_ops() {
|
||||
let mut cases = vec![
|
||||
(
|
||||
vec![
|
||||
Val(Bool(false)),
|
||||
JumpIfTrue(2),
|
||||
Val(Bool(true)),
|
||||
JumpIfTrue(2),
|
||||
Val(Int(1)),
|
||||
Jump(1),
|
||||
Val(Int(2)),
|
||||
Noop,
|
||||
],
|
||||
P(Int(2)),
|
||||
),
|
||||
(
|
||||
vec![
|
||||
Val(Bool(true)),
|
||||
JumpIfTrue(2),
|
||||
Val(Bool(false)),
|
||||
JumpIfTrue(2),
|
||||
Val(Int(1)),
|
||||
Jump(1),
|
||||
Val(Int(2)),
|
||||
Noop,
|
||||
],
|
||||
P(Int(1)),
|
||||
),
|
||||
(
|
||||
vec![
|
||||
Val(Int(1)),
|
||||
Val(Int(1)),
|
||||
Equal,
|
||||
JumpIfTrue(2),
|
||||
Val(Bool(false)),
|
||||
JumpIfTrue(2),
|
||||
Val(Int(1)),
|
||||
Jump(1),
|
||||
Val(Int(2)),
|
||||
Noop,
|
||||
],
|
||||
P(Int(1)),
|
||||
),
|
||||
];
|
||||
for case in cases.drain(0..) {
|
||||
let mut vm = VM::new(case.0);
|
||||
vm.run().unwrap();
|
||||
assert_eq!(vm.pop().unwrap(), case.1);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user