Hide Instructions implementation behind an iterator

This commit is contained in:
Will Glynn 2018-10-07 11:01:00 -05:00
parent 9170303aad
commit 14857145d1
4 changed files with 55 additions and 10 deletions

View File

@ -299,5 +299,46 @@ pub enum Instruction {
#[derive(Debug, Clone)]
pub struct Instructions {
pub code: Vec<Instruction>,
vec: Vec<Instruction>,
}
impl Instructions {
pub fn new<I>(instructions: I) -> Self
where I: IntoIterator<Item=Instruction>
{
Instructions {
vec: instructions.into_iter().collect()
}
}
pub fn iterate_from(&self, position: usize) -> InstructionIter {
InstructionIter{
instructions: &self.vec,
position,
}
}
}
pub struct InstructionIter<'a> {
instructions: &'a [Instruction],
position: usize,
}
impl<'a> InstructionIter<'a> {
#[inline]
pub fn position(&self) -> usize {
self.position
}
}
impl<'a> Iterator for InstructionIter<'a> {
type Item = &'a Instruction;
#[inline]
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
self.instructions.get(self.position).map(|instruction| {
self.position += 1;
instruction
})
}
}

View File

@ -175,7 +175,7 @@ impl Interpreter {
let function_return =
self.do_run_function(
&mut function_context,
&function_body.code.code,
&function_body.code,
).map_err(Trap::new)?;
match function_return {
@ -229,18 +229,24 @@ impl Interpreter {
}
}
fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &[isa::Instruction]) -> Result<RunResult, TrapKind> {
fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &isa::Instructions)
-> Result<RunResult, TrapKind>
{
let mut iter = instructions.iterate_from(function_context.position);
loop {
let instruction = &instructions[function_context.position];
let instruction = iter.next().expect("instruction");
match self.run_instruction(function_context, instruction)? {
InstructionOutcome::RunNextInstruction => function_context.position += 1,
InstructionOutcome::RunNextInstruction => {
function_context.position = iter.position();
},
InstructionOutcome::Branch(target) => {
function_context.position = target.dst_pc as usize;
iter = instructions.iterate_from(function_context.position);
self.value_stack.drop_keep(target.drop_keep);
},
InstructionOutcome::ExecuteCall(func_ref) => {
function_context.position += 1;
function_context.position = iter.position();
return Ok(RunResult::NestedCall(func_ref));
},
InstructionOutcome::Return(drop_keep) => {

View File

@ -1406,9 +1406,7 @@ impl<'a> FunctionValidationContext<'a> {
}
fn into_code(self) -> isa::Instructions {
isa::Instructions {
code: self.sink.into_inner(),
}
isa::Instructions::new(self.sink.into_inner())
}
}

View File

@ -313,7 +313,7 @@ fn validate(wat: &str) -> ValidatedModule {
fn compile(wat: &str) -> Vec<isa::Instruction> {
let validated_module = validate(wat);
let code = &validated_module.code_map[0];
code.code.clone()
code.iterate_from(0).map(|i| i.clone()).collect()
}
#[test]