stepwise interpretation
This commit is contained in:
parent
5a8b0ab579
commit
2405c81c65
92
src/interpreter/iterator.rs
Normal file
92
src/interpreter/iterator.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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>,
|
||||
@ -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>,
|
@ -6,6 +6,7 @@
|
||||
filling_drop,
|
||||
question_mark,
|
||||
rustc_private,
|
||||
pub_restricted,
|
||||
)]
|
||||
|
||||
// From rustc.
|
||||
|
Loading…
x
Reference in New Issue
Block a user