7 use rustc::mir::repr as mir;
9 pub enum Event<'a, 'tcx: 'a> {
10 Assignment(&'a mir::Statement<'tcx>),
11 Terminator(&'a mir::Terminator<'tcx>),
15 pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
16 fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
17 block: mir::BasicBlock,
19 mir: CachedMir<'mir, 'tcx>,
20 process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
23 impl<'fncx, 'a, 'b: 'a + 'mir, 'mir, 'tcx: 'b> Stepper<'fncx, 'a, 'b, 'mir, 'tcx> {
24 pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
26 block: fncx.frame().next_block,
33 fn dummy(&mut self) -> EvalResult<()> { Ok(()) }
34 fn statement(&mut self) -> EvalResult<()> {
35 let block_data = self.mir.basic_block_data(self.block);
36 let stmt = &block_data.statements[self.stmt];
37 let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
38 let result = self.fncx.eval_assignment(lvalue, rvalue);
39 self.fncx.maybe_report(stmt.span, result)?;
43 fn terminator(&mut self) -> EvalResult<()> {
46 let block_data = self.mir.basic_block_data(self.block);
47 let terminator = block_data.terminator();
48 let result = self.fncx.eval_terminator(terminator);
49 self.fncx.maybe_report(terminator.span, result)?
52 TerminatorTarget::Block(block) => {
55 TerminatorTarget::Return => {
56 self.fncx.pop_stack_frame();
57 self.fncx.name_stack.pop();
58 if !self.fncx.stack.is_empty() {
59 self.block = self.fncx.frame().next_block;
60 self.mir = self.fncx.mir();
63 TerminatorTarget::Call => {
64 self.block = self.fncx.frame().next_block;
65 self.mir = self.fncx.mir();
70 pub fn step<'step>(&'step mut self) -> EvalResult<Event<'step, 'tcx>> {
71 (self.process)(self)?;
73 if self.fncx.stack.is_empty() {
75 self.process = Self::dummy;
76 return Ok(Event::Done);
79 let basic_block = self.mir.basic_block_data(self.block);
81 if let Some(stmt) = basic_block.statements.get(self.stmt) {
82 self.process = Self::statement;
83 return Ok(Event::Assignment(&stmt));
86 self.process = Self::terminator;
87 Ok(Event::Terminator(basic_block.terminator()))
89 pub fn block(&self) -> mir::BasicBlock {