Skip to content

Commit

Permalink
stepwise interpretation
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jun 1, 2016
1 parent 5a8b0ab commit 2405c81
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 26 deletions.
92 changes: 92 additions & 0 deletions src/interpreter/iterator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use super::{
FnEvalContext,
CachedMir,
TerminatorTarget,
};
use error::EvalResult;
use rustc::mir::repr as mir;

pub enum Event<'a, 'tcx: 'a> {
Assignment(&'a mir::Statement<'tcx>),
Terminator(&'a mir::Terminator<'tcx>),
Done,
}

pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
block: mir::BasicBlock,
stmt: usize,
mir: CachedMir<'mir, 'tcx>,
process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
}

impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> {
pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
Stepper {
block: fncx.frame().next_block,
mir: fncx.mir(),
fncx: fncx,
stmt: 0,
process: Self::dummy,
}
}
fn dummy(&mut self) -> EvalResult<()> { Ok(()) }
fn statement(&mut self) -> EvalResult<()> {
let block_data = self.mir.basic_block_data(self.block);
let stmt = &block_data.statements[self.stmt];
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
let result = self.fncx.eval_assignment(lvalue, rvalue);
self.fncx.maybe_report(stmt.span, result)?;
self.stmt += 1;
Ok(())
}
fn terminator(&mut self) -> EvalResult<()> {
self.stmt = 0;
let term = {
let block_data = self.mir.basic_block_data(self.block);
let terminator = block_data.terminator();
let result = self.fncx.eval_terminator(terminator);
self.fncx.maybe_report(terminator.span, result)?
};
match term {
TerminatorTarget::Block(block) => {
self.block = block;
},
TerminatorTarget::Return => {
self.fncx.pop_stack_frame();
self.fncx.name_stack.pop();
if !self.fncx.stack.is_empty() {
self.block = self.fncx.frame().next_block;
self.mir = self.fncx.mir();
}
},
TerminatorTarget::Call => {
self.block = self.fncx.frame().next_block;
self.mir = self.fncx.mir();
},
}
Ok(())
}
pub fn step<'step>(&'step mut self) -> EvalResult<Event<'step, 'tcx>> {
(self.process)(self)?;

if self.fncx.stack.is_empty() {
// fuse the iterator
self.process = Self::dummy;
return Ok(Event::Done);
}

let basic_block = self.mir.basic_block_data(self.block);

if let Some(stmt) = basic_block.statements.get(self.stmt) {
self.process = Self::statement;
return Ok(Event::Assignment(&stmt));
}

self.process = Self::terminator;
Ok(Event::Terminator(basic_block.terminator()))
}
pub fn block(&self) -> mir::BasicBlock {
self.block
}
}
38 changes: 12 additions & 26 deletions src/interpreter.rs → src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use error::{EvalError, EvalResult};
use memory::{Memory, Pointer};
use primval::{self, PrimVal};

mod iterator;

struct GlobalEvalContext<'a, 'tcx: 'a> {
/// The results of the type checker, from rustc.
tcx: TyCtxt<'a, 'tcx, 'tcx>,
Expand Down Expand Up @@ -184,38 +186,22 @@ impl<'a, 'b, 'mir, 'tcx> FnEvalContext<'a, 'b, 'mir, 'tcx> {
}

fn run(&mut self) -> EvalResult<()> {
'outer: while !self.stack.is_empty() {
let mut current_block = self.frame().next_block;
let current_mir = self.mir();
let mut stepper = iterator::Stepper::new(self);
'outer: loop {
use self::iterator::Event::*;
trace!("// {:?}", stepper.block());

loop {
trace!("// {:?}", current_block);
let block_data = current_mir.basic_block_data(current_block);

for stmt in &block_data.statements {
trace!("{:?}", stmt);
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
let result = self.eval_assignment(lvalue, rvalue);
self.maybe_report(stmt.span, result)?;
}

let terminator = block_data.terminator();
trace!("{:?}", terminator.kind);

let result = self.eval_terminator(terminator);
match self.maybe_report(terminator.span, result)? {
TerminatorTarget::Block(block) => current_block = block,
TerminatorTarget::Return => {
self.pop_stack_frame();
self.name_stack.pop();
match stepper.step()? {
Assignment(statement) => trace!("{:?}", statement),
Terminator(terminator) => {
trace!("{:?}", terminator.kind);
continue 'outer;
}
TerminatorTarget::Call => continue 'outer,
},
Done => return Ok(()),
}
}
}

Ok(())
}

fn push_stack_frame(&mut self, mir: CachedMir<'mir, 'tcx>, substs: &'tcx Substs<'tcx>,
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
filling_drop,
question_mark,
rustc_private,
pub_restricted,
)]

// From rustc.
Expand Down

0 comments on commit 2405c81

Please sign in to comment.