no more function pointers
This commit is contained in:
parent
8b25bc8a9a
commit
3de30e33f5
@ -400,22 +400,18 @@ fn maybe_report<T>(&self, r: EvalResult<T>) -> EvalResult<T> {
|
|||||||
|
|
||||||
fn run(&mut self) -> EvalResult<()> {
|
fn run(&mut self) -> EvalResult<()> {
|
||||||
let mut stepper = stepper::Stepper::new(self);
|
let mut stepper = stepper::Stepper::new(self);
|
||||||
'outer: loop {
|
let mut done = false;
|
||||||
|
while !done {
|
||||||
use self::stepper::Event::*;
|
use self::stepper::Event::*;
|
||||||
trace!("// {:?}", stepper.block());
|
stepper.step(|event| match event {
|
||||||
|
Block(b) => trace!("// {:?}", b),
|
||||||
loop {
|
Assignment(a) => trace!("{:?}", a),
|
||||||
match stepper.step()? {
|
Terminator(t) => trace!("{:?}", t.kind),
|
||||||
Constant => trace!("computing a constant"),
|
Done => done = true,
|
||||||
Assignment => trace!("{:?}", stepper.stmt()),
|
_ => {},
|
||||||
Terminator => {
|
})?;
|
||||||
trace!("{:?}", stepper.term().kind);
|
|
||||||
continue 'outer;
|
|
||||||
},
|
|
||||||
Done => return Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_stack_frame(&mut self, def_id: DefId, span: codemap::Span, mir: CachedMir<'mir, 'tcx>, substs: &'tcx Substs<'tcx>,
|
fn push_stack_frame(&mut self, def_id: DefId, span: codemap::Span, mir: CachedMir<'mir, 'tcx>, substs: &'tcx Substs<'tcx>,
|
||||||
|
@ -14,16 +14,18 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use memory::Pointer;
|
use memory::Pointer;
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event<'a, 'tcx: 'a> {
|
||||||
|
Block(mir::BasicBlock),
|
||||||
|
Return,
|
||||||
|
Call,
|
||||||
Constant,
|
Constant,
|
||||||
Assignment,
|
Assignment(&'a mir::Statement<'tcx>),
|
||||||
Terminator,
|
Terminator(&'a mir::Terminator<'tcx>),
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
|
pub struct Stepper<'fncx, 'a: 'fncx, 'b: 'a + 'mir, 'mir: 'fncx, 'tcx: 'b>{
|
||||||
fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
|
fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>,
|
||||||
process: fn (&mut Stepper<'fncx, 'a, 'b, 'mir, 'tcx>) -> EvalResult<()>,
|
|
||||||
|
|
||||||
// a cache of the constants to be computed before the next statement/terminator
|
// a cache of the constants to be computed before the next statement/terminator
|
||||||
// this is an optimization, so we don't have to allocate a new vector for every statement
|
// this is an optimization, so we don't have to allocate a new vector for every statement
|
||||||
@ -34,17 +36,15 @@ 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 {
|
pub(super) fn new(fncx: &'fncx mut FnEvalContext<'a, 'b, 'mir, 'tcx>) -> Self {
|
||||||
Stepper {
|
Stepper {
|
||||||
fncx: fncx,
|
fncx: fncx,
|
||||||
process: Self::dummy,
|
|
||||||
constants: Vec::new(),
|
constants: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dummy(&mut self) -> EvalResult<()> { Ok(()) }
|
fn statement<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
|
||||||
|
|
||||||
fn statement(&mut self) -> EvalResult<()> {
|
|
||||||
let mir = self.fncx.mir();
|
let mir = self.fncx.mir();
|
||||||
let block_data = mir.basic_block_data(self.fncx.frame().next_block);
|
let block_data = mir.basic_block_data(self.fncx.frame().next_block);
|
||||||
let stmt = &block_data.statements[self.fncx.frame().stmt];
|
let stmt = &block_data.statements[self.fncx.frame().stmt];
|
||||||
|
f(Event::Assignment(stmt));
|
||||||
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
|
let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
|
||||||
let result = self.fncx.eval_assignment(lvalue, rvalue);
|
let result = self.fncx.eval_assignment(lvalue, rvalue);
|
||||||
self.fncx.maybe_report(result)?;
|
self.fncx.maybe_report(result)?;
|
||||||
@ -52,33 +52,33 @@ fn statement(&mut self) -> EvalResult<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminator(&mut self) -> EvalResult<()> {
|
fn terminator<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
|
||||||
// after a terminator we go to a new block
|
// after a terminator we go to a new block
|
||||||
self.fncx.frame_mut().stmt = 0;
|
self.fncx.frame_mut().stmt = 0;
|
||||||
let term = {
|
let term = {
|
||||||
let mir = self.fncx.mir();
|
let mir = self.fncx.mir();
|
||||||
let block_data = mir.basic_block_data(self.fncx.frame().next_block);
|
let block_data = mir.basic_block_data(self.fncx.frame().next_block);
|
||||||
let terminator = block_data.terminator();
|
let terminator = block_data.terminator();
|
||||||
|
f(Event::Terminator(terminator));
|
||||||
let result = self.fncx.eval_terminator(terminator);
|
let result = self.fncx.eval_terminator(terminator);
|
||||||
self.fncx.maybe_report(result)?
|
self.fncx.maybe_report(result)?
|
||||||
};
|
};
|
||||||
match term {
|
match term {
|
||||||
TerminatorTarget::Block => {},
|
TerminatorTarget::Block => f(Event::Block(self.fncx.frame().next_block)),
|
||||||
TerminatorTarget::Return => {
|
TerminatorTarget::Return => {
|
||||||
|
f(Event::Return);
|
||||||
self.fncx.pop_stack_frame();
|
self.fncx.pop_stack_frame();
|
||||||
},
|
},
|
||||||
TerminatorTarget::Call => {},
|
TerminatorTarget::Call => f(Event::Call),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self) -> EvalResult<Event> {
|
// returns true as long as there are more things to do
|
||||||
(self.process)(self)?;
|
pub fn step<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
|
||||||
|
|
||||||
if self.fncx.stack.is_empty() {
|
if self.fncx.stack.is_empty() {
|
||||||
// fuse the iterator
|
f(Event::Done);
|
||||||
self.process = Self::dummy;
|
return Ok(());
|
||||||
return Ok(Event::Done);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = self.fncx.frame().next_block;
|
let block = self.fncx.frame().next_block;
|
||||||
@ -97,12 +97,9 @@ pub fn step(&mut self) -> EvalResult<Event> {
|
|||||||
mir: &mir,
|
mir: &mir,
|
||||||
}.visit_statement(block, stmt);
|
}.visit_statement(block, stmt);
|
||||||
if self.constants.is_empty() {
|
if self.constants.is_empty() {
|
||||||
self.process = Self::statement;
|
return self.statement(f);
|
||||||
return Ok(Event::Assignment);
|
|
||||||
} else {
|
} else {
|
||||||
self.process = Self::statement;
|
return self.extract_constants(f);
|
||||||
self.extract_constants();
|
|
||||||
return Ok(Event::Constant);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,36 +114,21 @@ pub fn step(&mut self) -> EvalResult<Event> {
|
|||||||
mir: &mir,
|
mir: &mir,
|
||||||
}.visit_terminator(block, terminator);
|
}.visit_terminator(block, terminator);
|
||||||
if self.constants.is_empty() {
|
if self.constants.is_empty() {
|
||||||
self.process = Self::terminator;
|
self.terminator(f)
|
||||||
Ok(Event::Terminator)
|
|
||||||
} else {
|
} else {
|
||||||
self.process = Self::statement;
|
self.extract_constants(f)
|
||||||
self.extract_constants();
|
|
||||||
Ok(Event::Constant)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_constants(&mut self) {
|
fn extract_constants<F: for<'f> FnMut(Event<'f, 'tcx>)>(&mut self, mut f: F) -> EvalResult<()> {
|
||||||
assert!(!self.constants.is_empty());
|
assert!(!self.constants.is_empty());
|
||||||
for (cid, span, return_ptr, mir) in self.constants.drain(..) {
|
for (cid, span, return_ptr, mir) in self.constants.drain(..) {
|
||||||
let def_id = cid.def_id();
|
let def_id = cid.def_id();
|
||||||
let substs = cid.substs();
|
let substs = cid.substs();
|
||||||
|
f(Event::Constant);
|
||||||
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
|
self.fncx.push_stack_frame(def_id, span, mir, substs, Some(return_ptr));
|
||||||
}
|
}
|
||||||
}
|
self.step(f)
|
||||||
|
|
||||||
/// returns the statement that will be processed next
|
|
||||||
pub fn stmt(&self) -> &mir::Statement {
|
|
||||||
&self.fncx.basic_block().statements[self.fncx.frame().stmt]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the terminator of the current block
|
|
||||||
pub fn term(&self) -> &mir::Terminator {
|
|
||||||
self.fncx.basic_block().terminator()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block(&self) -> mir::BasicBlock {
|
|
||||||
self.fncx.frame().next_block
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user