metaemu_intrinsics/
lib.rs1use fugue::ir::il::pcode::Operand;
2use fugue::ir::AddressValue;
3
4use metaemu_state::State;
5
6use std::collections::HashMap;
7
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11pub enum Error<E: std::error::Error + 'static> {
12 #[error(transparent)]
13 State(E),
14 #[error(transparent)]
15 Other(#[from] anyhow::Error),
16}
17
18impl<E> Error<E>
19where
20 E: std::error::Error + 'static,
21{
22 pub fn state(error: E) -> Self {
23 Self::State(error)
24 }
25}
26
27#[derive(Clone)]
28pub enum IntrinsicAction<O> {
29 Pass,
30 Branch(AddressValue),
31 Halt(O),
32}
33
34pub trait IntrinsicBehaviour: dyn_clone::DynClone {
35 type Outcome;
36 type State: State;
37
38 fn intrinsic(&self) -> &str;
39
40 fn initialise(
41 &mut self,
42 #[allow(unused)] state: &Self::State,
43 ) -> Result<(), Error<<Self::State as State>::Error>> {
44 Ok(())
45 }
46
47 fn handle_intrinsic(
48 &mut self,
49 state: &mut Self::State,
50 inputs: &[Operand],
51 output: Option<&Operand>,
52 ) -> Result<IntrinsicAction<Self::Outcome>, Error<<Self::State as State>::Error>>;
53}
54dyn_clone::clone_trait_object!(<Outcome, State> IntrinsicBehaviour<Outcome=Outcome, State=State> where State: metaemu_state::State);
55
56#[derive(Clone)]
57pub struct IntrinsicHandler<O, S: State> {
58 handlers: HashMap<String, Box<dyn IntrinsicBehaviour<Outcome = O, State = S>>>,
59 default_action: IntrinsicAction<O>,
60}
61
62impl<O: Clone, S: State> Default for IntrinsicHandler<O, S> {
63 fn default() -> Self {
64 Self::new()
65 }
66}
67
68impl<O: Clone, S: State> IntrinsicHandler<O, S> {
69 pub fn new() -> Self {
70 Self::new_with(IntrinsicAction::Pass)
71 }
72
73 pub fn new_with(default_action: IntrinsicAction<O>) -> Self {
74 Self {
75 handlers: HashMap::new(),
76 default_action,
77 }
78 }
79
80 pub fn register<IN: IntrinsicBehaviour<Outcome = O, State = S> + 'static>(
81 &mut self,
82 behaviour: IN,
83 state: &S,
84 ) -> Result<(), Error<S::Error>> {
85 let mut behaviour = behaviour;
86 behaviour.initialise(state)?;
87
88 let name = behaviour.intrinsic().to_owned();
89
90 self.handlers.insert(name, Box::new(behaviour));
91
92 Ok(())
93 }
94
95 pub fn handle(
96 &mut self,
97 name: &str,
98 state: &mut S,
99 inputs: &[Operand],
100 output: Option<&Operand>,
101 ) -> Result<IntrinsicAction<O>, Error<S::Error>> {
102 if let Some(handler) = self.handlers.get_mut(name) {
103 handler.handle_intrinsic(state, inputs, output)
104 } else {
105 Ok(self.default_action.clone())
106 }
107 }
108}