From 2405c81c65586df5c65ae8670151b5237edf4398 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 1 Jun 2016 17:05:20 +0200 Subject: [PATCH] stepwise interpretation --- src/interpreter/iterator.rs | 92 ++++++++++++++++++++++ src/{interpreter.rs => interpreter/mod.rs} | 38 +++------ src/lib.rs | 1 + 3 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 src/interpreter/iterator.rs rename src/{interpreter.rs => interpreter/mod.rs} (98%) diff --git a/src/interpreter/iterator.rs b/src/interpreter/iterator.rs new file mode 100644 index 00000000000..7793c0df282 --- /dev/null +++ b/src/interpreter/iterator.rs @@ -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> { + (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 + } +} diff --git a/src/interpreter.rs b/src/interpreter/mod.rs similarity index 98% rename from src/interpreter.rs rename to src/interpreter/mod.rs index c8e6d0bbe1f..8b93edd888c 100644 --- a/src/interpreter.rs +++ b/src/interpreter/mod.rs @@ -20,6 +20,8 @@ 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } 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>, diff --git a/src/lib.rs b/src/lib.rs index 80d89c164ac..4e06a3ce38d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ filling_drop, question_mark, rustc_private, + pub_restricted, )] // From rustc. -- 2.44.0