1use crate::types::*;
2use crate::value::*;
3use crate::nodes::*;
4use crate::*;
5
6use std::collections::HashMap;
7#[cfg(feature = "functions")]
8use indexmap::map::IndexMap;
9use std::rc::Rc;
10use std::cell::RefCell;
11#[cfg(feature = "pretty_print")]
12use tabled::{
13 builder::Builder,
14 settings::{object::Rows,Panel, Span, Alignment, Modify, Style},
15 Tabled,
16};
17use std::fmt;
18
19pub type FunctionsRef = Ref<Functions>;
22pub type FunctionTable = HashMap<u64, fn(FunctionArgs) -> MResult<Box<dyn MechFunction>>>;
23pub type FunctionCompilerTable = HashMap<u64, &'static dyn NativeFunctionCompiler>;
24pub type UserFunctionTable = HashMap<u64, FunctionDefinition>;
25
26#[derive(Clone,Debug)]
27pub enum FunctionArgs {
28 Nullary(Value),
29 Unary(Value, Value),
30 Binary(Value, Value, Value),
31 Ternary(Value, Value, Value, Value),
32 Quaternary(Value, Value, Value, Value, Value),
33 Variadic(Value, Vec<Value>),
34}
35
36impl FunctionArgs {
37 pub fn len(&self) -> usize {
38 match self {
39 FunctionArgs::Nullary(_) => 0,
40 FunctionArgs::Unary(_, _) => 1,
41 FunctionArgs::Binary(_, _, _) => 2,
42 FunctionArgs::Ternary(_, _, _, _) => 3,
43 FunctionArgs::Quaternary(_, _, _, _, _) => 4,
44 FunctionArgs::Variadic(_, args) => args.len(),
45 }
46 }
47}
48
49#[repr(C)]
50#[derive(Clone)]
51pub struct FunctionDescriptor {
52 pub name: &'static str,
53 pub ptr: fn(FunctionArgs) -> MResult<Box<dyn MechFunction>>,
54}
55
56impl Debug for FunctionDescriptor {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(f, "{{ name: {:?}, ptr: {:?} }}", self.name, self.ptr)
59 }
60}
61
62unsafe impl Sync for FunctionDescriptor {}
63
64#[repr(C)]
65pub struct FunctionCompilerDescriptor {
66 pub name: &'static str,
67 pub ptr: &'static dyn NativeFunctionCompiler,
68}
69
70impl Debug for FunctionCompilerDescriptor {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(f, "{:?}", self.name)
73 }
74}
75
76unsafe impl Sync for FunctionCompilerDescriptor {}
77
78pub trait MechFunctionFactory {
79 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>>;
80}
81
82pub trait MechFunctionImpl {
83 fn solve(&self);
84 fn out(&self) -> Value;
85 fn to_string(&self) -> String;
86}
87
88#[cfg(feature = "compiler")]
89pub trait MechFunctionCompiler {
90 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register>;
91}
92
93#[cfg(feature = "compiler")]
94pub trait MechFunction: MechFunctionImpl + MechFunctionCompiler {}
95#[cfg(feature = "compiler")]
96impl<T> MechFunction for T where T: MechFunctionImpl + MechFunctionCompiler {}
97
98#[cfg(not(feature = "compiler"))]
99pub trait MechFunction: MechFunctionImpl {}
100#[cfg(not(feature = "compiler"))]
101impl<T> MechFunction for T where T: MechFunctionImpl {}
102
103pub trait NativeFunctionCompiler {
104 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>>;
105}
106
107#[derive(Clone)]
108pub struct Functions {
109 pub functions: FunctionTable,
110 pub function_compilers: FunctionCompilerTable,
111 pub user_functions: UserFunctionTable,
112 pub dictionary: Ref<Dictionary>,
113}
114
115impl Functions {
116 pub fn new() -> Self {
117 Self {
118 functions: HashMap::new(),
119 function_compilers: HashMap::new(),
120 user_functions: HashMap::new(),
121 dictionary: Ref::new(Dictionary::new()),
122 }
123 }
124
125 pub fn insert_function(&mut self, fxn: FunctionDescriptor) {
126 let id = hash_str(&fxn.name);
127 self.functions.insert(id.clone(), fxn.ptr);
128 self.dictionary.borrow_mut().insert(id, fxn.name.to_string());
129 }
130
131 #[cfg(feature = "pretty_print")]
132 pub fn pretty_print(&self) -> String {
133 let mut output = String::new();
134 output.push_str("\nFunctions:\n");
135 output.push_str(&format!("Total Functions: {}\n", self.functions.len()));
137 output.push_str(&format!("User Functions: {}\n", self.user_functions.len()));
138 output
144 }
145
146}
147
148#[derive(Clone)]
149pub struct FunctionDefinition {
150 pub code: FunctionDefine,
151 pub id: u64,
152 pub name: String,
153 pub input: IndexMap<u64, KindAnnotation>,
154 pub output: IndexMap<u64, KindAnnotation>,
155 pub symbols: SymbolTableRef,
156 pub out: Ref<Value>,
157 pub plan: Plan,
158}
159
160impl fmt::Debug for FunctionDefinition {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 if cfg!(feature = "pretty_print") {
163 #[cfg(feature = "pretty_print")]
164 return fmt::Display::fmt(&self.pretty_print(), f);
165 fmt::Display::fmt(&"".to_string(), f)
166 } else {
167 write!(f, "FunctionDefinition {{ id: {}, name: {}, input: {:?}, output: {:?}, symbols: {:?} }}",
168 self.id, self.name, self.input, self.output, self.symbols.borrow())
169 }
170 }
171}
172
173#[cfg(feature = "pretty_print")]
174impl PrettyPrint for FunctionDefinition {
175 fn pretty_print(&self) -> String {
176 let input_str = format!("{:#?}", self.input);
177 let output_str = format!("{:#?}", self.output);
178 let symbols_str = format!("{:#?}", self.symbols);
179 let mut plan_str = "".to_string();
180 for step in self.plan.borrow().iter() {
181 plan_str = format!("{} - {}\n",plan_str,step.to_string());
182 }
183 let data = vec!["📥 Input", &input_str,
184 "📤 Output", &output_str,
185 "🔣 Symbols", &symbols_str,
186 "📋 Plan", &plan_str];
187 let mut table = tabled::Table::new(data);
188 table.with(Style::modern_rounded())
189 .with(Panel::header(format!("📈 UserFxn::{}\n({})", self.name, humanize(&self.id))))
190 .with(Alignment::left());
191 format!("{table}")
192 }
193}
194
195impl FunctionDefinition {
196
197 pub fn new(id: u64, name: String, code: FunctionDefine) -> Self {
198 Self {
199 id,
200 name,
201 code,
202 input: IndexMap::new(),
203 output: IndexMap::new(),
204 out: Ref::new(Value::Empty),
205 symbols: Ref::new(SymbolTable::new()),
206 plan: Plan::new(),
207 }
208 }
209
210 pub fn solve(&self) -> ValRef {
211 let plan_brrw = self.plan.borrow();
212 for step in plan_brrw.iter() {
213 let result = step.solve();
214 }
215 self.out.clone()
216 }
217
218 pub fn out(&self) -> ValRef {
219 self.out.clone()
220 }
221}
222
223pub struct UserFunction {
226 pub fxn: FunctionDefinition,
227}
228
229impl MechFunctionImpl for UserFunction {
230 fn solve(&self) {
231 self.fxn.solve();
232 }
233 fn out(&self) -> Value {
234 self.fxn.out.borrow().clone()
235 }
236 fn to_string(&self) -> String { format!("UserFxn::{:?}", self.fxn.name) }
237}
238#[cfg(feature = "compiler")]
239impl MechFunctionCompiler for UserFunction {
240 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
241 todo!();
242 }
243}
244
245pub struct Plan(pub Ref<Vec<Box<dyn MechFunction>>>);
249
250impl Clone for Plan {
251 fn clone(&self) -> Self { Plan(self.0.clone()) }
252}
253
254impl fmt::Debug for Plan {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 for p in &(*self.0.borrow()) {
257 writeln!(f, "{}", p.to_string())?;
258 }
259 Ok(())
260 }
261}
262
263impl Plan {
264 pub fn new() -> Self { Plan(Ref::new(vec![])) }
265 pub fn borrow(&self) -> std::cell::Ref<'_, Vec<Box<dyn MechFunction>>> { self.0.borrow() }
266 pub fn borrow_mut(&self) -> std::cell::RefMut<'_, Vec<Box<dyn MechFunction>>> { self.0.borrow_mut() }
267 pub fn add_function(&self, func: Box<dyn MechFunction>) { self.0.borrow_mut().push(func); }
268 pub fn get_functions(&self) -> std::cell::Ref<'_, Vec<Box<dyn MechFunction>>> { self.0.borrow() }
269 pub fn len(&self) -> usize { self.0.borrow().len() }
270 pub fn is_empty(&self) -> bool { self.0.borrow().is_empty() }
271}
272
273#[cfg(feature = "pretty_print")]
274impl PrettyPrint for Plan {
275 fn pretty_print(&self) -> String {
276 let mut builder = Builder::default();
277 let plan_brrw = self.0.borrow();
278
279 if self.is_empty() {
280 builder.push_record(vec!["".to_string()]);
281 } else {
282 let total = plan_brrw.len();
283 let mut display_fxns: Vec<String> = Vec::new();
284
285 let indices: Vec<usize> = if total > 30 {
287 (0..10).chain((total - 10)..total).collect()
288 } else {
289 (0..total).collect()
290 };
291
292 for &ix in &indices {
293 let fxn_str = plan_brrw[ix].to_string();
294 let lines: Vec<&str> = fxn_str.lines().collect();
295
296 let truncated = if lines.len() > 20 {
297 let mut t = Vec::new();
298 t.extend_from_slice(&lines[..10]); t.push("…"); t.extend_from_slice(&lines[lines.len()-10..]); t.join("\n")
302 } else {
303 lines.join("\n")
304 };
305
306 display_fxns.push(format!("{}. {}", ix + 1, truncated));
307 }
308
309 if total > 30 {
311 display_fxns.insert(10, "…".to_string());
312 }
313
314 let mut row: Vec<String> = Vec::new();
316 for plan_str in display_fxns {
317 row.push(plan_str);
318 if row.len() == 4 {
319 builder.push_record(row.clone());
320 row.clear();
321 }
322 }
323 if !row.is_empty() {
324 builder.push_record(row);
325 }
326 }
327
328 let mut table = builder.build();
329 table.with(Style::modern_rounded())
330 .with(Panel::header("📋 Plan"));
331
332 format!("{table}")
333 }
334}
335
336
337
338pub struct FunctionRegistry {
348 pub registry: RefCell<HashMap<u64, Box<dyn MechFunctionImpl>>>,
349}
350
351#[derive(Debug, Clone)]
352pub struct UnhandledFunctionArgumentKind1 {
353 pub arg: ValueKind,
354 pub fxn_name: String,
355}
356impl MechErrorKind for UnhandledFunctionArgumentKind1 {
357 fn name(&self) -> &str { "UnhandledFunctionArgumentKind1" }
358 fn message(&self) -> String {
359 format!("Unhandled function argument kind for function '{}': arg = {:?}", self.fxn_name, self.arg)
360 }
361}
362
363#[derive(Debug, Clone)]
364pub struct UnhandledFunctionArgumentKind2 {
365 pub arg: (ValueKind, ValueKind),
366 pub fxn_name: String,
367}
368impl MechErrorKind for UnhandledFunctionArgumentKind2 {
369 fn name(&self) -> &str { "UnhandledFunctionArgumentKind2" }
370 fn message(&self) -> String {
371 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
372 }
373}
374
375#[derive(Debug, Clone)]
376pub struct UnhandledFunctionArgumentKind3 {
377 pub arg: (ValueKind, ValueKind, ValueKind),
378 pub fxn_name: String,
379}
380impl MechErrorKind for UnhandledFunctionArgumentKind3 {
381 fn name(&self) -> &str { "UnhandledFunctionArgumentKind3" }
382 fn message(&self) -> String {
383 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
384 }
385}
386
387#[derive(Debug, Clone)]
388pub struct UnhandledFunctionArgumentKind4 {
389 pub arg: (ValueKind, ValueKind, ValueKind, ValueKind),
390 pub fxn_name: String,
391}
392impl MechErrorKind for UnhandledFunctionArgumentKind4 {
393 fn name(&self) -> &str { "UnhandledFunctionArgumentKind4" }
394 fn message(&self) -> String {
395 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
396 }
397}
398
399#[derive(Debug, Clone)]
400pub struct UnhandledFunctionArgumentKindVarg {
401 pub arg: Vec<ValueKind>,
402 pub fxn_name: String,
403}
404impl MechErrorKind for UnhandledFunctionArgumentKindVarg {
405 fn name(&self) -> &str { "UnhandledFunctionArgumentKindVarg" }
406 fn message(&self) -> String {
407 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
408 }
409}
410
411#[derive(Debug, Clone)]
412pub struct UnhandledFunctionArgumentIxes {
413 pub arg: (ValueKind, Vec<ValueKind>, ValueKind),
414 pub fxn_name: String,
415}
416impl MechErrorKind for UnhandledFunctionArgumentIxes {
417 fn name(&self) -> &str { "UnhandledFunctionArgumentIxes" }
418 fn message(&self) -> String {
419 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
420 }
421}
422
423#[derive(Debug, Clone)]
424pub struct UnhandledFunctionArgumentIxesMono {
425 pub arg: (ValueKind, Vec<ValueKind>),
426 pub fxn_name: String,
427}
428impl MechErrorKind for UnhandledFunctionArgumentIxesMono {
429 fn name(&self) -> &str { "UnhandledFunctionArgumentIxesMono" }
430 fn message(&self) -> String {
431 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
432 }
433}
434
435#[derive(Debug, Clone)]
436pub struct IncorrectNumberOfArguments {
437 pub expected: usize,
438 pub found: usize,
439}
440impl MechErrorKind for IncorrectNumberOfArguments {
441 fn name(&self) -> &str {
442 "IncorrectNumberOfArguments"
443 }
444
445 fn message(&self) -> String {
446 format!("Expected {} arguments, but found {}", self.expected, self.found)
447 }
448}