Skip to content

Commit

Permalink
Added a "goto" instruction
Browse files Browse the repository at this point in the history
This will be used as a primitive for loops (e.g. a while loop).
  • Loading branch information
Yorick Peterse committed Jun 28, 2015
1 parent 930cc8c commit cd829d7
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub enum InstructionType {
Return,
GotoIfUndef,
GotoIfDef,
Goto,
DefMethod,
RunCode,
GetToplevel,
Expand Down
48 changes: 47 additions & 1 deletion src/virtual_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,25 @@ pub trait ArcMethods {
fn ins_goto_if_def(&self, RcThread, RcCompiledCode, &Instruction)
-> Result<Option<usize>, String>;

/// Jumps to a specific instruction.
///
/// This instruction takes one argument: the instruction index to jump to.
///
/// # Examples
///
/// integer_literals:
/// 0: 10
/// 1: 20
///
/// 0: goto 2
/// 1: set_integer 0, 0
/// 2: set_integer 0, 1
///
/// Here slot 0 would be set to 20.
///
fn ins_goto(&self, RcThread, RcCompiledCode, &Instruction)
-> Result<usize, String>;

/// Defines a method for an object.
///
/// This instruction requires 3 arguments:
Expand Down Expand Up @@ -564,7 +583,12 @@ impl ArcMethods for RcVirtualMachine {
let mut skip_until: Option<usize> = None;
let mut retval = None;

for (index, instruction) in code.instructions.iter().enumerate() {
let mut index = 0;
let count = code.instructions.len();

while index < count {
let ref instruction = code.instructions[index];

// TODO: this might be too expensive for every instruction.
if thread.should_stop() {
return Ok(None);
Expand All @@ -579,6 +603,10 @@ impl ArcMethods for RcVirtualMachine {
}
}

// Incremented _before_ the instructions so that the "goto"
// instruction can overwrite it.
index += 1;

match instruction.instruction_type {
InstructionType::SetInteger => {
try!(self.ins_set_integer(
Expand Down Expand Up @@ -727,6 +755,13 @@ impl ArcMethods for RcVirtualMachine {
&instruction
));
},
InstructionType::Goto => {
index = try!(self.ins_goto(
thread.clone(),
code.clone(),
&instruction
));
},
InstructionType::DefMethod => {
try!(self.ins_def_method(
thread.clone(),
Expand Down Expand Up @@ -1417,6 +1452,17 @@ impl ArcMethods for RcVirtualMachine {
Ok(matched)
}

fn ins_goto(&self, _: RcThread, _: RcCompiledCode,
instruction: &Instruction) -> Result<usize, String> {
let go_to = *try!(
instruction.arguments
.get(0)
.ok_or("goto: missing instruction index".to_string())
);

Ok(go_to)
}

fn ins_def_method(&self, thread: RcThread, code: RcCompiledCode,
instruction: &Instruction) -> Result<(), String> {
let receiver_index = *try!(
Expand Down

0 comments on commit cd829d7

Please sign in to comment.