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
129}
130
131#[derive(Clone)]
132pub struct FunctionDefinition {
133 pub code: FunctionDefine,
134 pub id: u64,
135 pub name: String,
136 pub input: IndexMap<u64, KindAnnotation>,
137 pub output: IndexMap<u64, KindAnnotation>,
138 pub symbols: SymbolTableRef,
139 pub out: Ref<Value>,
140 pub plan: Plan,
141}
142
143impl fmt::Debug for FunctionDefinition {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 if cfg!(feature = "pretty_print") {
146 #[cfg(feature = "pretty_print")]
147 return fmt::Display::fmt(&self.pretty_print(), f);
148 fmt::Display::fmt(&"".to_string(), f)
149 } else {
150 write!(f, "FunctionDefinition {{ id: {}, name: {}, input: {:?}, output: {:?}, symbols: {:?} }}",
151 self.id, self.name, self.input, self.output, self.symbols.borrow())
152 }
153 }
154}
155
156#[cfg(feature = "pretty_print")]
157impl PrettyPrint for FunctionDefinition {
158 fn pretty_print(&self) -> String {
159 let input_str = format!("{:#?}", self.input);
160 let output_str = format!("{:#?}", self.output);
161 let symbols_str = format!("{:#?}", self.symbols);
162 let mut plan_str = "".to_string();
163 for step in self.plan.borrow().iter() {
164 plan_str = format!("{} - {}\n",plan_str,step.to_string());
165 }
166 let data = vec!["📥 Input", &input_str,
167 "📤 Output", &output_str,
168 "🔣 Symbols", &symbols_str,
169 "📋 Plan", &plan_str];
170 let mut table = tabled::Table::new(data);
171 table.with(Style::modern_rounded())
172 .with(Panel::header(format!("📈 UserFxn::{}\n({})", self.name, humanize(&self.id))))
173 .with(Alignment::left());
174 format!("{table}")
175 }
176}
177
178impl FunctionDefinition {
179
180 pub fn new(id: u64, name: String, code: FunctionDefine) -> Self {
181 Self {
182 id,
183 name,
184 code,
185 input: IndexMap::new(),
186 output: IndexMap::new(),
187 out: Ref::new(Value::Empty),
188 symbols: Ref::new(SymbolTable::new()),
189 plan: Plan::new(),
190 }
191 }
192
193 pub fn solve(&self) -> ValRef {
194 let plan_brrw = self.plan.borrow();
195 for step in plan_brrw.iter() {
196 let result = step.solve();
197 }
198 self.out.clone()
199 }
200
201 pub fn out(&self) -> ValRef {
202 self.out.clone()
203 }
204}
205
206pub struct UserFunction {
209 pub fxn: FunctionDefinition,
210}
211
212impl MechFunctionImpl for UserFunction {
213 fn solve(&self) {
214 self.fxn.solve();
215 }
216 fn out(&self) -> Value {
217 Value::MutableReference(self.fxn.out.clone())
218 }
219 fn to_string(&self) -> String { format!("UserFxn::{:?}", self.fxn.name) }
220}
221#[cfg(feature = "compiler")]
222impl MechFunctionCompiler for UserFunction {
223 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
224 todo!();
225 }
226}
227
228pub struct Plan(pub Ref<Vec<Box<dyn MechFunction>>>);
232
233impl Clone for Plan {
234 fn clone(&self) -> Self { Plan(self.0.clone()) }
235}
236
237impl fmt::Debug for Plan {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 for p in &(*self.0.borrow()) {
240 writeln!(f, "{}", p.to_string())?;
241 }
242 Ok(())
243 }
244}
245
246impl Plan {
247 pub fn new() -> Self { Plan(Ref::new(vec![])) }
248 pub fn borrow(&self) -> std::cell::Ref<'_, Vec<Box<dyn MechFunction>>> { self.0.borrow() }
249 pub fn borrow_mut(&self) -> std::cell::RefMut<'_, Vec<Box<dyn MechFunction>>> { self.0.borrow_mut() }
250 pub fn add_function(&self, func: Box<dyn MechFunction>) { self.0.borrow_mut().push(func); }
251 pub fn get_functions(&self) -> std::cell::Ref<'_, Vec<Box<dyn MechFunction>>> { self.0.borrow() }
252 pub fn len(&self) -> usize { self.0.borrow().len() }
253 pub fn is_empty(&self) -> bool { self.0.borrow().is_empty() }
254}
255
256#[cfg(feature = "pretty_print")]
257impl PrettyPrint for Plan {
258 fn pretty_print(&self) -> String {
259 let mut builder = Builder::default();
260 let plan_brrw = self.0.borrow();
261
262 if self.is_empty() {
263 builder.push_record(vec!["".to_string()]);
264 } else {
265 let total = plan_brrw.len();
266 let mut display_fxns: Vec<String> = Vec::new();
267
268 let indices: Vec<usize> = if total > 30 {
270 (0..10).chain((total - 10)..total).collect()
271 } else {
272 (0..total).collect()
273 };
274
275 for &ix in &indices {
276 let fxn_str = plan_brrw[ix].to_string();
277 let lines: Vec<&str> = fxn_str.lines().collect();
278
279 let truncated = if lines.len() > 20 {
280 let mut t = Vec::new();
281 t.extend_from_slice(&lines[..10]); t.push("…"); t.extend_from_slice(&lines[lines.len()-10..]); t.join("\n")
285 } else {
286 lines.join("\n")
287 };
288
289 display_fxns.push(format!("{}. {}", ix + 1, truncated));
290 }
291
292 if total > 30 {
294 display_fxns.insert(10, "…".to_string());
295 }
296
297 let mut row: Vec<String> = Vec::new();
299 for plan_str in display_fxns {
300 row.push(plan_str);
301 if row.len() == 4 {
302 builder.push_record(row.clone());
303 row.clear();
304 }
305 }
306 if !row.is_empty() {
307 builder.push_record(row);
308 }
309 }
310
311 let mut table = builder.build();
312 table.with(Style::modern_rounded())
313 .with(Panel::header("📋 Plan"));
314
315 format!("{table}")
316 }
317}
318
319
320
321pub struct FunctionRegistry {
331 pub registry: RefCell<HashMap<u64, Box<dyn MechFunctionImpl>>>,
332}
333
334#[derive(Debug, Clone)]
335pub struct UnhandledFunctionArgumentKind1 {
336 pub arg: ValueKind,
337 pub fxn_name: String,
338}
339impl MechErrorKind2 for UnhandledFunctionArgumentKind1 {
340 fn name(&self) -> &str { "UnhandledFunctionArgumentKind1" }
341 fn message(&self) -> String {
342 format!("Unhandled function argument kind for function '{}': arg = {:?}", self.fxn_name, self.arg)
343 }
344}
345
346#[derive(Debug, Clone)]
347pub struct UnhandledFunctionArgumentKind2 {
348 pub arg: (ValueKind, ValueKind),
349 pub fxn_name: String,
350}
351impl MechErrorKind2 for UnhandledFunctionArgumentKind2 {
352 fn name(&self) -> &str { "UnhandledFunctionArgumentKind2" }
353 fn message(&self) -> String {
354 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
355 }
356}
357
358#[derive(Debug, Clone)]
359pub struct UnhandledFunctionArgumentKind3 {
360 pub arg: (ValueKind, ValueKind, ValueKind),
361 pub fxn_name: String,
362}
363impl MechErrorKind2 for UnhandledFunctionArgumentKind3 {
364 fn name(&self) -> &str { "UnhandledFunctionArgumentKind3" }
365 fn message(&self) -> String {
366 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
367 }
368}
369
370#[derive(Debug, Clone)]
371pub struct UnhandledFunctionArgumentKind4 {
372 pub arg: (ValueKind, ValueKind, ValueKind, ValueKind),
373 pub fxn_name: String,
374}
375impl MechErrorKind2 for UnhandledFunctionArgumentKind4 {
376 fn name(&self) -> &str { "UnhandledFunctionArgumentKind4" }
377 fn message(&self) -> String {
378 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
379 }
380}
381
382#[derive(Debug, Clone)]
383pub struct UnhandledFunctionArgumentKindVarg {
384 pub arg: Vec<ValueKind>,
385 pub fxn_name: String,
386}
387impl MechErrorKind2 for UnhandledFunctionArgumentKindVarg {
388 fn name(&self) -> &str { "UnhandledFunctionArgumentKindVarg" }
389 fn message(&self) -> String {
390 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
391 }
392}
393
394#[derive(Debug, Clone)]
395pub struct UnhandledFunctionArgumentIxes {
396 pub arg: (ValueKind, Vec<ValueKind>, ValueKind),
397 pub fxn_name: String,
398}
399impl MechErrorKind2 for UnhandledFunctionArgumentIxes {
400 fn name(&self) -> &str { "UnhandledFunctionArgumentIxes" }
401 fn message(&self) -> String {
402 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
403 }
404}
405
406#[derive(Debug, Clone)]
407pub struct UnhandledFunctionArgumentIxesMono {
408 pub arg: (ValueKind, Vec<ValueKind>),
409 pub fxn_name: String,
410}
411impl MechErrorKind2 for UnhandledFunctionArgumentIxesMono {
412 fn name(&self) -> &str { "UnhandledFunctionArgumentIxesMono" }
413 fn message(&self) -> String {
414 format!("Unhandled function argument kinds for function '{}': arg = {:?}", self.fxn_name, self.arg)
415 }
416}
417
418#[derive(Debug, Clone)]
419pub struct IncorrectNumberOfArguments {
420 pub expected: usize,
421 pub found: usize,
422}
423impl MechErrorKind2 for IncorrectNumberOfArguments {
424 fn name(&self) -> &str {
425 "IncorrectNumberOfArguments"
426 }
427
428 fn message(&self) -> String {
429 format!("Expected {} arguments, but found {}", self.expected, self.found)
430 }
431}