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