1use core::marker::PhantomData;
2
3use crate::ser_de::SerDictFixed;
4use crate::ser_de::SerWord;
5use crate::Runtime;
6use crate::RuntimeWord;
7use crate::StepResult;
8use crate::VerbSeqInner;
9use crate::WhichToken;
10use crate::{Error, ExecutionStack, Stack};
11
12use heapless::{String, Vec};
13
14#[derive(Debug)]
15pub struct HVecStack<T, const N: usize> {
16 data: Vec<T, N>,
17 err: Error,
18}
19
20impl<T, const N: usize> HVecStack<T, N> {
21 pub fn new(err: Error) -> Self {
22 HVecStack {
23 data: Vec::new(),
24 err,
25 }
26 }
27}
28
29impl<T, const N: usize> Stack for HVecStack<T, N> {
30 type Item = T;
31
32 fn push(&mut self, data: T) {
33 self.data.push(data).map_err(drop).unwrap();
34 }
35
36 fn pop(&mut self) -> Result<T, Error> {
37 self.data.pop().ok_or(Error::DataStackUnderflow)
38 }
39
40 fn last(&self) -> Result<&Self::Item, Error> {
41 self.data.last().ok_or(Error::InternalError) }
43}
44
45impl<BuiltinTok, SeqTok, const N: usize> ExecutionStack<BuiltinTok, SeqTok>
46 for HVecStack<RuntimeWord<BuiltinTok, SeqTok>, N>
47where
48 SeqTok: Clone,
49 BuiltinTok: Clone,
50{
51 fn push(&mut self, data: RuntimeWord<BuiltinTok, SeqTok>) {
52 self.data.push(data).map_err(drop).unwrap()
54 }
55 fn pop(&mut self) -> Result<RuntimeWord<BuiltinTok, SeqTok>, Error> {
56 self.data.pop().ok_or(Error::FlowStackEmpty)
57 }
58 fn last_mut(&mut self) -> Result<&mut RuntimeWord<BuiltinTok, SeqTok>, Error> {
59 self.data.last_mut().ok_or(Error::FlowStackEmpty)
60 }
61}
62
63#[derive(Clone)]
64pub struct BuiltinToken<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize> {
65 bi: Builtin<DATA_SZ, FLOW_SZ, OUTBUF_SZ>,
66}
67
68impl<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize>
69 BuiltinToken<DATA_SZ, FLOW_SZ, OUTBUF_SZ>
70{
71 pub fn new(bi: Builtin<DATA_SZ, FLOW_SZ, OUTBUF_SZ>) -> Self {
72 Self { bi }
73 }
74
75 pub fn exec(&self, rt: &mut NoStdRuntime<DATA_SZ, FLOW_SZ, OUTBUF_SZ>) -> Result<(), Error> {
76 (self.bi)(rt)
77 }
78}
79
80pub type NoStdRuntime<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize> = Runtime<
81 BuiltinToken<DATA_SZ, FLOW_SZ, OUTBUF_SZ>,
82 usize,
83 HVecStack<i32, DATA_SZ>,
84 HVecStack<RuntimeWord<BuiltinToken<DATA_SZ, FLOW_SZ, OUTBUF_SZ>, usize>, FLOW_SZ>,
85 String<OUTBUF_SZ>,
86>;
87
88pub struct NoStdContext<
89 const DATA_SZ: usize,
90 const FLOW_SZ: usize,
91 const OUTBUF_SZ: usize,
92 const SEQS_CT: usize,
93 const SEQ_SZ: usize,
94> {
95 pub rt: NoStdRuntime<DATA_SZ, FLOW_SZ, OUTBUF_SZ>,
96 pub seq:
97 Vec<Vec<RuntimeWord<BuiltinToken<DATA_SZ, FLOW_SZ, OUTBUF_SZ>, usize>, SEQ_SZ>, SEQS_CT>,
98}
99
100impl<
101 const DATA_SZ: usize,
102 const FLOW_SZ: usize,
103 const OUTBUF_SZ: usize,
104 const SEQS_CT: usize,
105 const SEQ_SZ: usize,
106 > NoStdContext<DATA_SZ, FLOW_SZ, OUTBUF_SZ, SEQS_CT, SEQ_SZ>
107{
108 pub fn from_ser_dict<'a, const BIS_CT: usize>(
109 dict: &SerDictFixed<'a, SEQS_CT, SEQ_SZ, BIS_CT>,
110 ) -> Self {
111 let rt = new_runtime();
112 let mut bis: Vec<Builtin<DATA_SZ, FLOW_SZ, OUTBUF_SZ>, BIS_CT> = Vec::new();
113
114 for bi in dict.bis.iter() {
116 let func = nostd_builtins::<DATA_SZ, FLOW_SZ, OUTBUF_SZ>()
117 .iter()
118 .find(|(k, _v)| k == bi)
119 .map(|(_k, v)| v)
120 .unwrap();
121
122 bis.push(*func).ok();
123 }
124
125 let mut seqs_vec = Vec::new();
126
127 for seq in dict.data.iter() {
128 let mut seq_vec = Vec::new();
129
130 for seqstp in seq.iter() {
131 let proc = match seqstp {
132 SerWord::LiteralVal(lit) => RuntimeWord::LiteralVal(*lit),
133 SerWord::Verb(idx) => RuntimeWord::Verb(BuiltinToken {
134 bi: bis[*idx as usize],
135 }),
136 SerWord::VerbSeq(idx) => RuntimeWord::VerbSeq(VerbSeqInner {
137 tok: *idx as usize,
138 idx: 0,
139 }),
140 SerWord::UncondRelativeJump { offset } => {
141 RuntimeWord::UncondRelativeJump { offset: *offset }
142 }
143 SerWord::CondRelativeJump { offset, jump_on } => {
144 RuntimeWord::CondRelativeJump {
145 offset: *offset,
146 jump_on: *jump_on,
147 }
148 }
149 };
150 seq_vec.push(proc).ok();
151 }
152
153 seqs_vec.push(seq_vec).ok();
154 }
155
156 Self { rt, seq: seqs_vec }
157 }
158
159 pub fn run_blocking(&mut self) -> Result<(), Error> {
160 loop {
161 match self.rt.step() {
162 Ok(StepResult::Working(WhichToken::Single(ft))) => {
163 ft.exec(&mut self.rt).unwrap();
167 }
168 Ok(StepResult::Working(WhichToken::Ref(rtw))) => {
169 let c = self
174 .seq
175 .get(rtw.tok)
176 .and_then(|n| n.get(rtw.idx))
177 .map(|n| n.clone());
178
179 self.rt.provide_seq_tok(c).unwrap();
180 }
181 Ok(StepResult::Done) => break,
182 Err(e) => {
183 return Err(e);
185 }
186 }
187 }
188 Ok(())
189 }
190}
191
192pub type NoStdRuntimeWord<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize> =
193 RuntimeWord<BuiltinToken<DATA_SZ, FLOW_SZ, OUTBUF_SZ>, usize>;
194
195pub type Builtin<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize> =
196 fn(&mut NoStdRuntime<DATA_SZ, FLOW_SZ, OUTBUF_SZ>) -> Result<(), Error>;
197
198pub fn new_runtime<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize>(
199) -> NoStdRuntime<DATA_SZ, FLOW_SZ, OUTBUF_SZ> {
200 let ds = HVecStack::new(Error::DataStackEmpty);
203 let rs = HVecStack::new(Error::RetStackEmpty);
204 let fs = HVecStack::new(Error::FlowStackEmpty);
205
206 Runtime {
210 data_stk: ds,
211 ret_stk: rs,
212 flow_stk: fs,
213 _pd_ty_t_f: PhantomData,
214 cur_output: String::new(),
215 }
216}
217
218pub fn nostd_builtins<const DATA_SZ: usize, const FLOW_SZ: usize, const OUTBUF_SZ: usize>(
219) -> &'static [(
220 &'static str,
221 fn(&mut NoStdRuntime<DATA_SZ, FLOW_SZ, OUTBUF_SZ>) -> Result<(), Error>,
222)] {
223 &[
224 ("emit", crate::builtins::bi_emit),
225 (".", crate::builtins::bi_pop),
226 ("cr", crate::builtins::bi_cr),
227 (">r", crate::builtins::bi_retstk_push),
228 ("r>", crate::builtins::bi_retstk_pop),
229 ("=", crate::builtins::bi_eq),
230 ("<", crate::builtins::bi_lt),
231 (">", crate::builtins::bi_gt),
232 ("dup", crate::builtins::bi_dup),
233 ("+", crate::builtins::bi_add),
234 ("PRIV_LOOP", crate::builtins::bi_priv_loop),
235 ]
236}