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
|
// Control Flow
|
||||||
Bang,
|
Bang,
|
||||||
Jump(usize),
|
Jump(usize),
|
||||||
|
JumpIfTrue(usize),
|
||||||
Noop,
|
Noop,
|
||||||
// Pending Computation
|
// Pending Computation
|
||||||
InitThunk(usize),
|
InitThunk(usize),
|
||||||
@ -139,12 +140,14 @@ impl VM {
|
|||||||
Op::Bang => return Err(Error {}),
|
Op::Bang => return Err(Error {}),
|
||||||
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?,
|
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?,
|
||||||
Op::Noop => {
|
Op::Noop => {
|
||||||
|
self.stack.last();
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
Op::Return => {
|
Op::Return => {
|
||||||
// TODO(jwall): This means we return back to the start of the frame.
|
// 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 => {
|
Op::Pop => {
|
||||||
self.pop()?;
|
self.pop()?;
|
||||||
}
|
}
|
||||||
@ -152,12 +155,23 @@ impl VM {
|
|||||||
}
|
}
|
||||||
Ok(())
|
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> {
|
fn op_thunk(&mut self, idx: usize, jp: usize) -> Result<(), Error> {
|
||||||
self.push(Value::T(idx))?;
|
self.push(Value::T(idx))?;
|
||||||
self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(jp))?;
|
self.op_jump(jp)
|
||||||
// TODO(jwall): Skip over the rest until we reach the return?
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_equal(&mut self) -> Result<(), Error> {
|
fn op_equal(&mut self) -> Result<(), Error> {
|
||||||
|
@ -289,3 +289,55 @@ fn test_equality_ops() {
|
|||||||
assert_eq!(vm.pop().unwrap(), case.1);
|
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