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)] #[derive(Debug, Clone)]
pub struct Instructions { 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 = let function_return =
self.do_run_function( self.do_run_function(
&mut function_context, &mut function_context,
&function_body.code.code, &function_body.code,
).map_err(Trap::new)?; ).map_err(Trap::new)?;
match function_return { 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 { loop {
let instruction = &instructions[function_context.position]; let instruction = iter.next().expect("instruction");
match self.run_instruction(function_context, instruction)? { match self.run_instruction(function_context, instruction)? {
InstructionOutcome::RunNextInstruction => function_context.position += 1, InstructionOutcome::RunNextInstruction => {
function_context.position = iter.position();
},
InstructionOutcome::Branch(target) => { InstructionOutcome::Branch(target) => {
function_context.position = target.dst_pc as usize; function_context.position = target.dst_pc as usize;
iter = instructions.iterate_from(function_context.position);
self.value_stack.drop_keep(target.drop_keep); self.value_stack.drop_keep(target.drop_keep);
}, },
InstructionOutcome::ExecuteCall(func_ref) => { InstructionOutcome::ExecuteCall(func_ref) => {
function_context.position += 1; function_context.position = iter.position();
return Ok(RunResult::NestedCall(func_ref)); return Ok(RunResult::NestedCall(func_ref));
}, },
InstructionOutcome::Return(drop_keep) => { InstructionOutcome::Return(drop_keep) => {

View File

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

View File

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