evm_interpreter/interpreter/
etable.rs1use alloc::vec::Vec;
2use core::ops::{Deref, DerefMut};
3
4use crate::{
5 Capture, Control, ExitError, ExitException, ExitResult, ExitSucceed, FeedbackInterpreter,
6 Interpreter, Machine, Opcode, Stack, StepInterpreter, Valids,
7 etable::Etable,
8 runtime::RuntimeState,
9 trap::{CallFeedback, CreateFeedback},
10};
11
12pub struct EtableInterpreter<'etable, S, ES> {
14 valids: Valids,
15 position: usize,
16 machine: Machine<S>,
17 etable: &'etable ES,
18}
19
20impl<'etable, S, ES> AsRef<Machine<S>> for EtableInterpreter<'etable, S, ES> {
21 fn as_ref(&self) -> &Machine<S> {
22 &self.machine
23 }
24}
25
26impl<'etable, S, ES> AsMut<Machine<S>> for EtableInterpreter<'etable, S, ES> {
27 fn as_mut(&mut self) -> &mut Machine<S> {
28 &mut self.machine
29 }
30}
31
32impl<'etable, S, ES> Deref for EtableInterpreter<'etable, S, ES> {
33 type Target = Machine<S>;
34
35 fn deref(&self) -> &Machine<S> {
36 &self.machine
37 }
38}
39
40impl<'etable, S, ES> DerefMut for EtableInterpreter<'etable, S, ES> {
41 fn deref_mut(&mut self) -> &mut Machine<S> {
42 &mut self.machine
43 }
44}
45
46impl<'etable, S, ES> EtableInterpreter<'etable, S, ES> {
47 pub const fn position(&self) -> usize {
49 self.position
50 }
51
52 pub fn new(machine: Machine<S>, etable: &'etable ES) -> Self {
54 let valids = Valids::new(&machine.code[..]);
55
56 Self {
57 machine,
58 valids,
59 position: 0,
60 etable,
61 }
62 }
63
64 pub fn deconstruct(self) -> Machine<S> {
66 self.machine
67 }
68
69 pub fn exit(&mut self) {
71 self.position = self.code.len();
72 }
73
74 pub fn inspect(&self) -> Option<(Opcode, &Stack)> {
76 self.code
77 .get(self.position)
78 .map(|v| (Opcode(*v), &self.stack))
79 }
80
81 pub fn perform<R, F: FnOnce(&mut Self) -> Result<R, ExitError>>(
84 &mut self,
85 f: F,
86 ) -> Result<R, ExitError> {
87 match f(self) {
88 Ok(r) => Ok(r),
89 Err(e) => {
90 self.exit();
91 Err(e)
92 }
93 }
94 }
95
96 pub fn peek_opcode(&self) -> Option<Opcode> {
98 self.code.get(self.position).map(|opcode| Opcode(*opcode))
99 }
100
101 pub fn advance(&mut self) {
103 if self.position == self.code.len() {
104 return;
105 }
106
107 self.position += 1;
108 }
109}
110
111impl<'etable, S, H, ES: Etable<H, State = S>> Interpreter<H> for EtableInterpreter<'etable, S, ES> {
112 type State = S;
113 type Trap = ES::Trap;
114
115 fn deconstruct(self) -> (ES::State, Vec<u8>) {
116 (self.machine.state, self.machine.retval)
117 }
118
119 fn state(&self) -> &Self::State {
120 &self.machine.state
121 }
122
123 fn state_mut(&mut self) -> &mut Self::State {
124 &mut self.machine.state
125 }
126
127 fn run(&mut self, handle: &mut H) -> Capture<ExitResult, Self::Trap> {
128 loop {
129 match self.step(handle) {
130 Ok(()) => (),
131 Err(res) => return res,
132 }
133 }
134 }
135}
136
137impl<'etable, S, H, ES: Etable<H, State = S>> FeedbackInterpreter<H, CallFeedback>
138 for EtableInterpreter<'etable, S, ES>
139where
140 S: AsRef<RuntimeState> + AsMut<RuntimeState>,
141{
142 fn feedback(&mut self, feedback: CallFeedback, _handler: &mut H) -> Result<(), ExitError> {
143 match feedback.to_machine(self) {
144 Ok(()) => {
145 self.advance();
146 Ok(())
147 }
148 Err(err) => Err(err),
149 }
150 }
151}
152
153impl<'etable, S, H, ES: Etable<H, State = S>> FeedbackInterpreter<H, CreateFeedback>
154 for EtableInterpreter<'etable, S, ES>
155where
156 S: AsRef<RuntimeState> + AsMut<RuntimeState>,
157{
158 fn feedback(&mut self, feedback: CreateFeedback, _handler: &mut H) -> Result<(), ExitError> {
159 match feedback.to_machine(self) {
160 Ok(()) => {
161 self.advance();
162 Ok(())
163 }
164 Err(err) => Err(err),
165 }
166 }
167}
168
169impl<'etable, S, H, ES: Etable<H, State = S>> StepInterpreter<H>
170 for EtableInterpreter<'etable, S, ES>
171{
172 #[inline]
173 fn step(&mut self, handle: &mut H) -> Result<(), Capture<ExitResult, ES::Trap>> {
174 let position = self.position;
175 if position >= self.code.len() {
176 return Err(Capture::Exit(ExitSucceed::Stopped.into()));
177 }
178
179 let control = self.etable.eval(&mut self.machine, handle, self.position);
180
181 match control {
182 Control::NoAction => (),
183 Control::Continue(p) => {
184 self.position = position + p;
185 }
186 Control::Exit(e) => {
187 self.position = self.code.len();
188 return Err(Capture::Exit(e));
189 }
190 Control::Jump(p) => {
191 if self.valids.is_valid(p) {
192 self.position = p;
193 } else {
194 self.position = self.code.len();
195 return Err(Capture::Exit(ExitException::InvalidJump.into()));
196 }
197 }
198 Control::Trap(opcode) => return Err(Capture::Trap(opcode)),
199 };
200
201 Ok(())
202 }
203}