1use heapless::Vec as HVec;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
5pub enum SerWord {
6 LiteralVal(i32),
7 Verb(u16),
8 VerbSeq(u16),
9 UncondRelativeJump { offset: i32 },
10 CondRelativeJump { offset: i32, jump_on: bool },
11}
12
13#[cfg(any(test, feature = "std"))]
18#[derive(Debug, Serialize, Deserialize)]
19pub struct SerDict {
20 pub data: Vec<Vec<SerWord>>,
21 pub data_map: Option<Vec<String>>,
22 pub bis: Vec<String>,
23}
24
25#[derive(Debug, Deserialize, Serialize)]
26pub struct SerDictFixed<'a, const SEQS_CT: usize, const SEQ_SZ: usize, const BIS_CT: usize> {
27 pub data: HVec<HVec<SerWord, SEQ_SZ>, SEQS_CT>,
28
29 #[serde(borrow)]
30 pub data_map: Option<HVec<&'a str, SEQS_CT>>,
31
32 #[serde(borrow)]
33 pub bis: HVec<&'a str, BIS_CT>,
34}
35
36#[cfg(test)]
39mod test {
40 use crate::compiler::Context;
41 use crate::nostd_rt::NoStdContext;
42 use crate::ser_de::SerDictFixed;
43 use crate::std_rt::std_builtins;
44 use crate::{RuntimeWord, VerbSeqInner};
45
46 #[test]
47 fn roundtrip() {
48 let mut ctxt = Context::with_builtins(std_builtins());
49
50 ctxt.evaluate(vec![
51 ":".into(),
52 "star".into(),
53 "42".into(),
54 "emit".into(),
55 ";".into(),
56 ])
57 .unwrap();
58
59 ctxt.evaluate(vec![
60 ":".into(),
61 "mstar".into(),
62 "if".into(),
63 "star".into(),
64 "else".into(),
65 "star".into(),
66 "star".into(),
67 "then".into(),
68 ";".into(),
69 ])
70 .unwrap();
71
72 let serdict = ctxt.serialize();
73 println!("{:?}", serdict);
74
75 let mut ser = postcard::to_stdvec_cobs(&serdict).unwrap();
76 println!("{:?}", ser);
77
78 let loaded: SerDictFixed<4, 16, 4> = postcard::from_bytes_cobs(&mut ser).unwrap();
79 println!("{:?}", loaded);
80
81 for (ser_out, des_out) in serdict.data.iter().zip(loaded.data.iter()) {
82 for (ser_in, des_in) in ser_out.iter().zip(des_out.iter()) {
83 assert_eq!(ser_in, des_in);
84 }
85 }
86
87 for (ser_bis, des_bis) in serdict.bis.iter().zip(loaded.bis.iter()) {
88 assert_eq!(ser_bis, des_bis);
89 }
90
91 let mut ns_ctxt: NoStdContext<32, 16, 128, 4, 16> = NoStdContext::from_ser_dict(&loaded);
92
93 let temp_compiled = RuntimeWord::VerbSeq(VerbSeqInner::from_word(1));
94
95 ns_ctxt.rt.push_exec(temp_compiled.clone());
96 ns_ctxt.rt.push_exec(RuntimeWord::LiteralVal(0));
97
98 ns_ctxt.run_blocking().unwrap();
99
100 let out = ns_ctxt.rt.exchange_output();
101 assert_eq!(out, "**");
102
103 ns_ctxt.rt.push_exec(temp_compiled);
104 ns_ctxt.rt.push_exec(RuntimeWord::LiteralVal(-1));
105
106 ns_ctxt.run_blocking().unwrap();
107
108 let out = ns_ctxt.rt.exchange_output();
109 assert_eq!(out, "*");
110 }
111
112 #[allow(dead_code)]
114 fn roundtrip2() {
115 let mut ctxt = Context::with_builtins(std_builtins());
116
117 ctxt.evaluate(vec![":".into(), "nop".into(), ";".into()])
118 .unwrap();
119
120 ctxt.evaluate(vec![
121 ":".into(),
122 "test".into(),
123 "1000000".into(),
124 "0".into(),
125 "do".into(),
126 "nop".into(),
127 "loop".into(),
128 ";".into(),
129 ])
130 .unwrap();
131
132 let serdict = ctxt.serialize();
133 println!("{:?}", serdict);
134
135 let ser = postcard::to_stdvec_cobs(&serdict).unwrap();
136 println!("{:?}", ser);
137 }
138}