1use crate::types::*;
2use crate::value::*;
3use crate::nodes::*;
4use crate::*;
5
6use hashbrown::{HashMap, HashSet};
7use indexmap::map::IndexMap;
8use std::rc::Rc;
9use std::cell::RefCell;
10use tabled::{
11 builder::Builder,
12 settings::{object::Rows,Panel, Span, Alignment, Modify, Style},
13 Tabled,
14};
15use std::fmt;
16
17pub trait MechFunction {
20 fn solve(&self);
21 fn out(&self) -> Value;
22 fn to_string(&self) -> String;
23}
24
25pub trait NativeFunctionCompiler {
26 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>>;
27}
28
29pub struct Functions {
30 pub functions: HashMap<u64,FunctionDefinition>,
31 pub function_compilers: HashMap<u64, Box<dyn NativeFunctionCompiler>>,
32 pub kinds: HashMap<u64,ValueKind>,
33 pub enums: HashMap<u64,MechEnum>,
34}
35
36impl Functions {
37 pub fn new() -> Self {
38 Self {
39 functions: HashMap::new(),
40 function_compilers: HashMap::new(),
41 kinds: HashMap::new(),
42 enums: HashMap::new(),
43 }
44 }
45}
46
47#[derive(Clone)]
48pub struct FunctionDefinition {
49 pub code: FunctionDefine,
50 pub id: u64,
51 pub name: String,
52 pub input: IndexMap<u64, KindAnnotation>,
53 pub output: IndexMap<u64, KindAnnotation>,
54 pub symbols: SymbolTableRef,
55 pub out: Ref<Value>,
56 pub plan: Plan,
57}
58
59impl fmt::Debug for FunctionDefinition {
60 #[inline]
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 let input_str = format!("{:#?}", self.input);
63 let output_str = format!("{:#?}", self.output);
64 let symbols_str = format!("{:#?}", self.symbols);
65 let mut plan_str = "".to_string();
66 for step in self.plan.borrow().iter() {
67 plan_str = format!("{} - {}\n",plan_str,step.to_string());
68 }
69 let data = vec!["๐ฅ Input", &input_str,
70 "๐ค Output", &output_str,
71 "๐ฃ Symbols", &symbols_str,
72 "๐ Plan", &plan_str];
73 let mut table = tabled::Table::new(data);
74 table.with(Style::modern_rounded())
75 .with(Panel::header(format!("๐ UserFxn::{}\n({})", self.name, humanize(&self.id))))
76 .with(Alignment::left());
77 println!("{table}");
78 Ok(())
79 }
80}
81
82impl FunctionDefinition {
83
84 pub fn new(id: u64, name: String, code: FunctionDefine) -> Self {
85 Self {
86 id,
87 name,
88 code,
89 input: IndexMap::new(),
90 output: IndexMap::new(),
91 out: new_ref(Value::Empty),
92 symbols: new_ref(SymbolTable::new()),
93 plan: new_ref(Vec::new()),
94 }
95 }
96
97 pub fn solve(&self) -> ValRef {
98 let plan_brrw = self.plan.borrow();
99 for step in plan_brrw.iter() {
100 let result = step.solve();
101 }
102 self.out.clone()
103 }
104
105 pub fn out(&self) -> ValRef {
106 self.out.clone()
107 }
108}
109
110#[derive(Debug)]
113pub struct UserFunction {
114 pub fxn: FunctionDefinition,
115}
116
117impl MechFunction for UserFunction {
118 fn solve(&self) {
119 self.fxn.solve();
120 }
121 fn out(&self) -> Value {
122 Value::MutableReference(self.fxn.out.clone())
123 }
124 fn to_string(&self) -> String { format!("UserFxn::{:?}", self.fxn.name)}
125}
126
127pub type Dictionary = IndexMap<u64,String>;
130
131#[derive(Clone, Debug)]
132pub struct SymbolTable {
133 pub symbols: HashMap<u64,ValRef>,
134 pub mutable_variables: HashMap<u64,ValRef>,
135 pub dictionary: Ref<Dictionary>,
136 pub reverse_lookup: HashMap<*const RefCell<Value>, u64>,
137}
138
139impl SymbolTable {
140
141 pub fn new() -> SymbolTable {
142 Self {
143 symbols: HashMap::new(),
144 mutable_variables: HashMap::new(),
145 dictionary: new_ref(IndexMap::new()),
146 reverse_lookup: HashMap::new(),
147 }
148 }
149
150 pub fn get_mutable(&self, key: u64) -> Option<ValRef> {
151 self.mutable_variables.get(&key).cloned()
152 }
153
154 pub fn get(&self, key: u64) -> Option<ValRef> {
155 self.symbols.get(&key).cloned()
156 }
157
158 pub fn contains(&self, key: u64) -> bool {
159 self.symbols.contains_key(&key)
160 }
161
162 pub fn insert(&mut self, key: u64, value: Value, mutable: bool) -> ValRef {
163 let cell = new_ref(value);
164 self.reverse_lookup.insert(Rc::as_ptr(&cell), key);
165 let old = self.symbols.insert(key,cell.clone());
166 if mutable {
167 self.mutable_variables.insert(key,cell.clone());
168 }
169 cell.clone()
170 }
171
172 pub fn pretty_print(&self) -> String {
173 let mut builder = Builder::default();
174 let dict_brrw = self.dictionary.borrow();
175 for (k,v) in &self.symbols {
176 let name = dict_brrw.get(k).unwrap_or(&"??".to_string()).clone();
177 let v_brrw = v.borrow();
178 builder.push_record(vec![format!("\n{} : {:?}\n{}\n",name, v_brrw.kind(), v_brrw.pretty_print())])
179 }
180 if self.symbols.is_empty() {
181 builder.push_record(vec!["".to_string()]);
182 }
183 let mut table = builder.build();
184 let table_style = Style::empty()
185 .top(' ')
186 .left(' ')
187 .right(' ')
188 .bottom(' ')
189 .vertical(' ')
190 .horizontal('ยท')
191 .intersection_bottom(' ')
192 .corner_top_left(' ')
193 .corner_top_right(' ')
194 .corner_bottom_left(' ')
195 .corner_bottom_right(' ');
196 table.with(table_style);
197 format!("{table}")
198 }
199}