1use crate::*;
2use std::io::Cursor;
3#[cfg(not(feature = "no_std"))]
4use std::collections::HashSet;
5#[cfg(feature = "no_std")]
6use hashbrown::HashSet;
7
8#[cfg(any(feature = "compiler", feature = "program"))]
9pub mod compiler;
10#[cfg(feature = "symbol_table")]
11pub mod symbol_table;
12#[cfg(feature = "program")]
13pub mod program;
14
15#[cfg(any(feature = "compiler", feature = "program"))]
16pub use self::compiler::*;
17#[cfg(feature = "symbol_table")]
18pub use self::symbol_table::*;
19#[cfg(feature = "program")]
20pub use self::program::*;
21
22pub type Dictionary = HashMap<u64,String>;
26pub type KindTable = HashMap<u64, ValueKind>;
27#[cfg(feature = "enum")]
28pub type EnumTable = HashMap<u64, MechEnum>;
29
30pub struct ProgramState {
31 #[cfg(feature = "symbol_table")]
32 pub symbol_table: SymbolTableRef,
33 #[cfg(feature = "symbol_table")]
34 pub environment: Option<SymbolTableRef>,
35 #[cfg(feature = "functions")]
36 pub functions: FunctionsRef,
37 #[cfg(feature = "functions")]
38 pub plan: Plan,
39 pub kinds: KindTable,
40 #[cfg(feature = "enum")]
41 pub enums: EnumTable,
42 pub dictionary: Ref<Dictionary>,
43}
44
45impl Clone for ProgramState {
46 fn clone(&self) -> Self {
47 ProgramState {
48 #[cfg(feature = "symbol_table")]
49 symbol_table: self.symbol_table.clone(),
50 #[cfg(feature = "symbol_table")]
51 environment: self.environment.clone(),
52 #[cfg(feature = "functions")]
53 functions: self.functions.clone(),
54 #[cfg(feature = "functions")]
55 plan: self.plan.clone(),
56 kinds: self.kinds.clone(),
57 #[cfg(feature = "enum")]
58 enums: self.enums.clone(),
59 dictionary: self.dictionary.clone(),
60 }
61 }
62}
63
64impl ProgramState {
65 pub fn new() -> ProgramState {
66 ProgramState {
67 #[cfg(feature = "symbol_table")]
68 symbol_table: Ref::new(SymbolTable::new()),
69 #[cfg(feature = "symbol_table")]
70 environment: None,
71 #[cfg(feature = "functions")]
72 functions: Ref::new(Functions::new()),
73 #[cfg(feature = "functions")]
74 plan: Plan::new(),
75 kinds: KindTable::new(),
76 #[cfg(feature = "enum")]
77 enums: EnumTable::new(),
78 dictionary: Ref::new(Dictionary::new()),
79 }
80 }
81
82 #[cfg(feature = "pretty_print")]
83 pub fn pretty_print(&self) -> String {
84 let mut output = String::new();
85 output.push_str("Program State:\n");
86 #[cfg(feature = "symbol_table")]
87 {
88 output.push_str("Symbol Table:\n");
89 output.push_str(&self.symbol_table.borrow().pretty_print());
90 }
91 #[cfg(feature = "functions")]
92 {
93 output.push_str(&self.functions.borrow().pretty_print());
94 }
95 #[cfg(feature = "functions")]
96 {
97 output.push_str("Execution Plan:\n");
98 for (i, step) in self.plan.borrow().iter().enumerate() {
99 output.push_str(&format!(" Step {}: {}\n", i, step.to_string()));
100 }
101 }
102 output
103 }
104
105 #[cfg(feature = "symbol_table")]
106 pub fn get_symbol(&self, id: u64) -> Option<Ref<Value>> {
107 let syms = self.symbol_table.borrow();
108 syms.get(id)
109 }
110
111 #[cfg(feature = "symbol_table")]
112 pub fn get_mutable_symbol(&self, id: u64) -> Option<ValRef> {
113 let syms = self.symbol_table.borrow();
114 syms.get_mutable(id)
115 }
116
117 #[cfg(feature = "symbol_table")]
118 pub fn contains_symbol(&self, id: u64) -> bool {
119 if let Some(env) = &self.environment {
120 let env_brrw = env.borrow();
121 if env_brrw.contains(id) {
122 true
123 } else {
124 let syms = self.symbol_table.borrow();
125 syms.contains(id)
126 }
127 } else {
128 let syms = self.symbol_table.borrow();
129 syms.contains(id)
130 }
131 }
132
133 #[cfg(feature = "symbol_table")]
134 pub fn get_environment(&self) -> Option<SymbolTableRef> {
135 self.environment.clone()
136 }
137
138 #[cfg(feature = "symbol_table")]
140 pub fn get_env_symbol(&self, id: u64) -> Option<Ref<Value>> {
141 if let Some(env) = &self.environment {
142 let env_brrw = env.borrow();
143 match env_brrw.get(id) {
144 Some(val) => Some(val),
145 None => {
146 let sym_brrw = self.symbol_table.borrow();
147 sym_brrw.get(id)
148 }
149 }
150 } else {
151 None
152 }
153 }
154
155 #[cfg(feature = "functions")]
156 pub fn add_plan_step(&self, step: Box<dyn MechFunction>) {
157 let mut plan_brrw = self.plan.borrow_mut();
158 plan_brrw.push(step);
159 }
160
161 #[cfg(feature = "functions")]
162 pub fn insert_function(&self, fxn: FunctionDescriptor) {
163 let mut fxns_brrw = self.functions.borrow_mut();
164 let id = hash_str(&fxn.name);
165 fxns_brrw.functions.insert(id.clone(), fxn.ptr);
166 self.dictionary.borrow_mut().insert(id, fxn.name.to_string());
167 }
168
169 #[cfg(feature = "symbol_table")]
170 pub fn save_symbol(&self, id: u64, name: String, value: Value, mutable: bool) -> ValRef {
171 let mut symbols_brrw = self.symbol_table.borrow_mut();
172 let val_ref = symbols_brrw.insert(id,value,mutable);
173 let mut dict_brrw = symbols_brrw.dictionary.borrow_mut();
174 dict_brrw.insert(id,name);
175 val_ref
176 }
177
178 #[cfg(feature = "symbol_table")]
179 pub fn save_env_symbol(&self, id: u64, name: String, value: Value, mutable: bool) -> ValRef {
180 if let Some(env) = &self.environment {
181 let mut env_brrw = env.borrow_mut();
182 let val_ref = env_brrw.insert(id,value,mutable);
183 let mut dict_brrw = env_brrw.dictionary.borrow_mut();
184 dict_brrw.insert(id,name);
185 val_ref
186 } else {
187 panic!("No environment to save variable into");
188 }
189 }
190
191}
192
193pub fn parse_version_to_u16(s: &str) -> Option<u16> {
194 let parts: Vec<&str> = s.split('.').collect();
195 if parts.len() != 3 { return None; }
196
197 let major = parts[0].parse::<u16>().ok()?;
198 let minor = parts[1].parse::<u16>().ok()?;
199 let patch = parts[2].parse::<u16>().ok()?; if major > 0b111 { return None; } if minor > 0b1_1111 { return None; } if patch > 0xFF { return None; } let encoded = (major << 13) | (minor << 8) | patch;
207 Some(encoded as u16)
208}
209
210#[derive(Debug, Clone)]
211pub struct InvalidMagicNumberError;
212
213impl MechErrorKind2 for InvalidMagicNumberError {
214 fn name(&self) -> &str { "InvalidMagicNumber" }
215 fn message(&self) -> String { "Invalid magic number".to_string() }
216}