1use std::collections::BTreeMap;
2use std::sync::Arc;
3
4use crate::{
5 ser_de::{SerDict, SerWord},
6 std_rt::{
7 new_runtime, ser_srw, BuiltinToken, NamedStdRuntimeWord, SerContext, StdFuncSeq,
8 StdRuntime, StdRuntimeWord, StdVecStack,
9 },
10 Error, RuntimeWord, StepResult, VerbSeqInner,
11};
12
13pub struct Dict {
14 pub bis: BTreeMap<String, BuiltinToken>,
15 pub data: BTreeMap<String, StdFuncSeq>,
16 pub(crate) shame_idx: usize,
17}
18
19impl Dict {
20 pub fn new() -> Self {
21 Self {
22 bis: BTreeMap::new(),
23 data: BTreeMap::new(),
24 shame_idx: 0,
25 }
26 }
27
28 pub fn serialize(&self) -> SerDict {
29 let mut out: BTreeMap<String, Vec<SerWord>> = BTreeMap::new();
30 let mut data_map: Vec<String> = Vec::new();
31 let mut ctxt = SerContext::new();
32
33 for (word, val) in self.data.iter() {
34 out.insert(word.to_string(), ser_srw(&mut ctxt, &word, val));
35 }
36
37 let mut data = Vec::new();
38 for word in ctxt.seqs {
39 data.push(out.get(&word).unwrap().clone());
40 data_map.push(word.clone());
41 }
42
43 SerDict {
44 data,
45 data_map: Some(data_map),
46 bis: ctxt.bis,
47 }
48 }
49}
50
51pub struct Context {
52 pub rt: StdRuntime,
53 pub dict: Dict,
54}
55
56impl Context {
57 pub fn load_ser_dict(&mut self, data: &SerDict) {
58 let data_map = if let Some(dm) = data.data_map.as_ref() {
59 dm.clone()
60 } else {
61 eprintln!("Error: dict has no name map! Refusing to load.");
62 return;
63 };
64
65 if !data.bis.iter().all(|bi| self.dict.bis.contains_key(bi)) {
66 eprintln!("Missing builtins! Refusing to load.");
67 return;
68 }
69
70 if data_map.len() != data.data.len() {
71 eprintln!("Data map size mismatch! Refusing to load.");
72 return;
73 }
74
75 for (name, word) in data_map.iter().zip(data.data.iter()) {
76 let cword = word
77 .iter()
78 .map(|x| match x {
79 SerWord::LiteralVal(v) => NamedStdRuntimeWord {
80 name: format!("LIT({})", v),
81 word: RuntimeWord::LiteralVal(*v),
82 },
83 SerWord::Verb(i) => {
84 let txt = data.bis.get(*i as usize).unwrap();
85 NamedStdRuntimeWord {
86 name: txt.clone(),
87 word: RuntimeWord::Verb(self.dict.bis.get(txt).unwrap().clone()),
88 }
89 }
90 SerWord::VerbSeq(i) => {
91 let txt = data_map.get(*i as usize).unwrap();
92 NamedStdRuntimeWord {
93 name: txt.clone(),
94 word: RuntimeWord::VerbSeq(VerbSeqInner::from_word(txt.to_string())),
95 }
96 }
97 SerWord::UncondRelativeJump { offset } => NamedStdRuntimeWord {
98 name: format!("UCRJ({})", offset),
99 word: RuntimeWord::UncondRelativeJump { offset: *offset },
100 },
101 SerWord::CondRelativeJump { offset, jump_on } => NamedStdRuntimeWord {
102 name: format!("CRJ({})", offset),
103 word: RuntimeWord::CondRelativeJump {
104 offset: *offset,
105 jump_on: *jump_on,
106 },
107 },
108 })
109 .collect::<Vec<_>>();
110
111 self.dict.data.insert(
112 name.clone(),
113 StdFuncSeq {
114 inner: Arc::new(cword),
115 },
116 );
117 }
118 }
119
120 fn compile(&mut self, data: &[String]) -> Result<Vec<NamedStdRuntimeWord>, Error> {
121 let mut vd_data: VecDeque<String> = data
122 .iter()
123 .map(String::as_str)
124 .map(str::to_lowercase)
125 .collect();
126
127 let munched = muncher(&mut vd_data);
128 assert!(vd_data.is_empty());
129
130 let conv: Vec<NamedStdRuntimeWord> = munched
131 .into_iter()
132 .map(|m| m.to_named_rt_words(&mut self.dict))
133 .flatten()
134 .collect();
135
136 Ok(conv)
137 }
138
139 pub fn evaluate(&mut self, data: Vec<String>) -> Result<(), Error> {
140 match (data.first(), data.last()) {
141 (Some(f), Some(l)) if f == ":" && l == ";" => {
142 assert!(data.len() >= 3);
144
145 let name = data[1].to_lowercase();
146
147 let relevant = &data[2..][..data.len() - 3];
149
150 let compiled = Arc::new(self.compile(relevant).unwrap());
152
153 self.dict.data.insert(name, StdFuncSeq { inner: compiled });
154 }
155 _ => {
156 if !data.is_empty() {
160 let name = format!("__{}", self.dict.shame_idx);
161 let comp = self.compile(&data).unwrap();
163 self.dict.data.insert(
164 name.clone(),
165 StdFuncSeq {
166 inner: Arc::new(comp),
167 },
168 );
169 self.dict.shame_idx += 1;
170 let temp_compiled = RuntimeWord::VerbSeq(VerbSeqInner::from_word(name));
171 self.push_exec(temp_compiled);
172 }
173 }
174 }
175
176 Ok(())
177 }
178
179 pub fn serialize(&self) -> SerDict {
180 self.dict.serialize()
181 }
182
183 pub fn step(&mut self) -> Result<StepResult<BuiltinToken, String>, Error> {
184 self.rt.step()
185 }
186
187 pub fn data_stack(&self) -> &StdVecStack<i32> {
188 &self.rt.data_stk
189 }
190
191 pub fn return_stack(&self) -> &StdVecStack<i32> {
192 &self.rt.ret_stk
193 }
194
195 pub fn flow_stack(&self) -> &StdVecStack<RuntimeWord<BuiltinToken, String>> {
196 &self.rt.flow_stk
197 }
198
199 pub fn with_builtins(bi: &[(&'static str, fn(&mut StdRuntime) -> Result<(), Error>)]) -> Self {
200 let mut new = Context {
201 rt: new_runtime(),
202 dict: Dict::new(),
203 };
204
205 for (word, func) in bi {
206 new.dict
207 .bis
208 .insert(word.to_string(), BuiltinToken::new(*func));
209 }
210
211 new
212 }
213
214 pub fn output(&mut self) -> String {
215 self.rt.exchange_output()
216 }
217
218 pub fn push_exec(&mut self, word: StdRuntimeWord) {
219 self.rt.push_exec(word)
220 }
221}
222
223fn parse_num(input: &str) -> Option<i32> {
230 input.parse::<i32>().ok()
231}
232
233#[derive(Debug)]
235enum Chunk {
236 IfThen {
237 if_body: Vec<Chunk>,
238 },
239 IfElseThen {
240 if_body: Vec<Chunk>,
241 else_body: Vec<Chunk>,
242 },
243 DoLoop {
244 do_body: Vec<Chunk>,
245 },
246 Token(String),
247 Comment {
248 contents: Vec<String>,
249 }
250}
251
252impl Chunk {
253 fn to_named_rt_words(self, dict: &mut Dict) -> Vec<NamedStdRuntimeWord> {
255 let mut ret = vec![];
256
257 match self {
258 Chunk::IfThen { if_body } => {
259 let mut conv: VecDeque<NamedStdRuntimeWord> = if_body
261 .into_iter()
262 .map(|m| m.to_named_rt_words(dict))
263 .flatten()
264 .collect();
265
266 conv.push_front(NamedStdRuntimeWord {
267 name: "CRJ".into(),
268 word: RuntimeWord::CondRelativeJump {
269 offset: conv.len() as i32,
270 jump_on: false,
271 },
272 });
273
274 let conv: Vec<NamedStdRuntimeWord> = conv.into_iter().collect();
275 ret.extend(conv);
276 }
277 Chunk::IfElseThen { if_body, else_body } => {
278 let mut if_conv: VecDeque<NamedStdRuntimeWord> = if_body
279 .into_iter()
280 .map(|m| m.to_named_rt_words(dict))
281 .flatten()
282 .collect();
283
284 let else_conv: Vec<NamedStdRuntimeWord> = else_body
285 .into_iter()
286 .map(|m| m.to_named_rt_words(dict))
287 .flatten()
288 .collect();
289
290 if_conv.push_back(NamedStdRuntimeWord {
291 name: "UCRJ".into(),
292 word: RuntimeWord::UncondRelativeJump {
293 offset: else_conv.len() as i32,
294 },
295 });
296
297 if_conv.push_front(NamedStdRuntimeWord {
298 name: "CRJ".into(),
299 word: RuntimeWord::CondRelativeJump {
300 offset: if_conv.len() as i32,
301 jump_on: false,
302 },
303 });
304
305 let conv: Vec<NamedStdRuntimeWord> =
306 if_conv.into_iter().chain(else_conv.into_iter()).collect();
307 ret.extend(conv);
308 }
309 Chunk::DoLoop { do_body } => {
310 let mut conv: VecDeque<NamedStdRuntimeWord> = do_body
312 .into_iter()
313 .map(|m| m.to_named_rt_words(dict))
314 .flatten()
315 .collect();
316
317 conv.push_back(NamedStdRuntimeWord {
318 word: RuntimeWord::Verb(BuiltinToken::new(crate::builtins::bi_priv_loop)),
319 name: "PRIV_LOOP".into(),
320 });
321
322 let len = conv.len();
323
324 conv.push_front(NamedStdRuntimeWord {
325 word: RuntimeWord::Verb(BuiltinToken::new(crate::builtins::bi_retstk_push)),
326 name: ">r".into(),
327 });
328 conv.push_front(NamedStdRuntimeWord {
329 word: RuntimeWord::Verb(BuiltinToken::new(crate::builtins::bi_retstk_push)),
330 name: ">r".into(),
331 });
332
333 conv.push_back(NamedStdRuntimeWord {
336 word: RuntimeWord::CondRelativeJump {
337 offset: -1 * len as i32 - 1,
338 jump_on: false,
339 },
340 name: "CRJ".into(),
341 });
342
343 let conv: Vec<NamedStdRuntimeWord> = conv.into_iter().collect();
344 ret.extend(conv);
345 }
346 Chunk::Token(tok) => {
347 ret.push(if let Some(bi) = dict.bis.get(&tok).cloned() {
348 NamedStdRuntimeWord {
349 name: tok,
350 word: RuntimeWord::Verb(bi.clone()),
351 }
352 } else if dict.data.contains_key(&tok) {
353 NamedStdRuntimeWord {
354 word: RuntimeWord::VerbSeq(VerbSeqInner::from_word(tok.clone())),
355 name: tok,
356 }
357 } else if let Some(num) = parse_num(&tok) {
358 NamedStdRuntimeWord {
359 word: RuntimeWord::LiteralVal(num),
360 name: format!("LIT({})", num),
361 }
362 } else {
363 panic!("{:?}", tok);
364 });
366 }
367 Chunk::Comment { .. } => {
368 }
370 }
371
372 ret
373 }
374}
375
376use std::collections::VecDeque;
377
378fn muncher(data: &mut VecDeque<String>) -> Vec<Chunk> {
379 let mut chunks = vec![];
380 loop {
381 let next = if let Some(t) = data.pop_front() {
382 t
383 } else {
384 break;
385 };
386
387 match next.as_str() {
388 "do" => {
389 chunks.push(munch_do(data));
390 }
391 "if" => {
392 chunks.push(munch_if(data));
393 }
394 "(" => {
395 chunks.push(Chunk::Comment { contents: munch_comment(data) });
396 }
397 _ => chunks.push(Chunk::Token(next)),
398 }
399 }
400
401 chunks
402}
403
404fn munch_comment(data: &mut VecDeque<String>) -> Vec<String> {
405 let mut contents = vec![];
406 loop {
407 let next = if let Some(t) = data.pop_front() {
408 t
409 } else {
410 break;
411 };
412
413 match next.as_str() {
414 "(" => {
415 contents.extend(munch_comment(data));
416 }
417 ")" => {
418 return contents;
419 }
420 _ => {
421 contents.push(next);
422 }
423 }
424 }
425
426 todo!()
428}
429
430fn munch_do(data: &mut VecDeque<String>) -> Chunk {
431 let mut chunks = vec![];
432 loop {
433 let next = if let Some(t) = data.pop_front() {
434 t
435 } else {
436 break;
437 };
438
439 match next.as_str() {
440 "do" => {
441 chunks.push(munch_do(data));
442 }
443 "if" => {
444 chunks.push(munch_if(data));
445 }
446 "loop" => return Chunk::DoLoop { do_body: chunks },
447 _ => chunks.push(Chunk::Token(next)),
448 }
449 }
450
451 todo!()
453}
454
455fn munch_if(data: &mut VecDeque<String>) -> Chunk {
456 let mut chunks = vec![];
457 loop {
458 let next = if let Some(t) = data.pop_front() {
459 t
460 } else {
461 break;
462 };
463
464 match next.as_str() {
465 "do" => {
466 chunks.push(munch_do(data));
467 }
468 "if" => {
469 chunks.push(munch_if(data));
470 }
471 "then" => return Chunk::IfThen { if_body: chunks },
472 "else" => {
473 return munch_else(data, chunks);
474 }
475 _ => chunks.push(Chunk::Token(next)),
476 }
477 }
478
479 todo!()
481}
482
483fn munch_else(data: &mut VecDeque<String>, if_body: Vec<Chunk>) -> Chunk {
484 let mut chunks = vec![];
485 loop {
486 let next = if let Some(t) = data.pop_front() {
487 t
488 } else {
489 break;
490 };
491
492 match next.as_str() {
493 "do" => {
494 chunks.push(munch_do(data));
495 }
496 "if" => {
497 chunks.push(munch_if(data));
498 }
499 "then" => {
500 return Chunk::IfElseThen {
501 if_body,
502 else_body: chunks,
503 }
504 }
505 _ => chunks.push(Chunk::Token(next)),
506 }
507 }
508
509 todo!()
511}