use super::{code, Word, Patch, Label};
use code::{Variable, Action};
pub trait Lower {
fn slots_used_mut(&mut self) -> &mut usize;
fn here(&self) -> Label;
fn patch(&mut self, patch: Patch, old_target: Option<usize>, new_target: Option<usize>);
fn steal(&mut self, loser: &mut Label, winner: &mut Label) {
let loser_target = loser.target();
for patch in loser.drain() {
self.patch(patch, loser_target, winner.target());
winner.push(patch);
}
}
fn define(&mut self, label: &mut Label) {
assert!(!label.is_defined());
let mut new = self.here();
self.steal(label, &mut new);
*label = new;
}
fn jump(&mut self, label: &mut Label);
fn prologue(&mut self);
fn epilogue(&mut self);
fn if_eq(
&mut self,
guard: (Variable, u64),
eq_label: &mut Label,
);
fn if_ne(
&mut self,
guard: (Variable, u64),
ne_label: &mut Label,
);
fn action(&mut self, action: Action);
fn actions(&mut self, actions: &[Action]) {
for &action in actions {
self.action(action);
}
}
}
pub type ExecuteFn = unsafe extern "C" fn(
*mut (),
) -> Word;
pub trait Execute: Sized + Lower {
fn execute<T>(
&mut self,
label: &Label,
callback: impl FnOnce(ExecuteFn) -> T,
) -> T;
}
pub trait Target: Default {
type Lowerer: Lower + Execute;
const NUM_REGISTERS: usize;
fn lowerer(&self) -> Self::Lowerer;
}