interpreter/runtime/
_root_syntax.rs

1use tokio::task::yield_now;
2
3use crate::{
4  error,
5  parallel_ipreter::{check_state, interpret, tok_run, Args, AsyncHeapHelper, Wrapped},
6  types::{
7    set_into_extends, set_runtime_val, BufValue, Heap, Options, RawRTValue, SafePtr, SafePtrMut,
8  },
9  Application, ExtendsInternal, LeadCode, RespPackage, StaticLeadModule,
10};
11use std::{
12  borrow::Cow,
13  collections::HashMap,
14  future::Future,
15  mem::transmute,
16  pin::Pin,
17  sync::Arc,
18  task::{Context, Poll},
19};
20
21#[derive(Debug)]
22pub(crate) struct RTCreatedModule {
23  pub(crate) heap: Heap,
24  pub(crate) methods: StaticLeadModule,
25}
26
27impl RTCreatedModule {
28  pub(crate) async fn run_method<T: FnOnce(&mut Heap, &mut Heap, &[&str]) -> ()>(
29    &mut self,
30    app: *mut Application<'static>,
31    method: &str,
32    file: &str,
33    into_heap: T,
34    heap: &mut Heap,
35    opt: &mut Options,
36  ) {
37    let opt = SafePtrMut(opt);
38    let app = Wrapped(app);
39    let mut temp_heap = Heap::new_with_this(&mut self.heap, app.pkg.extends.clone());
40
41    let (args, method_code) = self
42      .methods
43      .get(&method)
44      .unwrap_or_else(|| error("Unable to find :method", file));
45    into_heap(&mut temp_heap, heap, args);
46
47    // run
48    let file_name = ":fn";
49
50    let file = method_code;
51
52    let mut line = 0usize;
53
54    let mut markers: HashMap<Cow<'static, str>, usize> = HashMap::new();
55
56    let len = file.len();
57
58    let mut total: i8 = 8;
59
60    let mut heap = AsyncHeapHelper::from(temp_heap);
61
62    while line < len {
63      let args = file[line];
64
65      let t = SafePtrMut(&mut total);
66
67      if let Args::Args(x, to_set, val_type) =
68        check_state(unsafe { &mut *t.0 }, args, file_name, &mut heap, &mut line)
69      {
70        tokio::spawn(Sendify(tok_run(
71          unsafe { &mut *t.0 },
72          unsafe { transmute(x) },
73          to_set,
74          val_type,
75          ":fn",
76          SafePtrMut(app.0),
77          unsafe { transmute(&mut heap) },
78          unsafe { transmute(&mut line) },
79          unsafe { transmute(&mut markers) },
80          Some(unsafe { &mut *opt.0 }),
81        )))
82        .await
83        .expect("Expected no errors");
84      }
85
86      line += 1;
87
88      if total <= 0 {
89        total = 8;
90        // Did a heavy task. Yielding...
91        yield_now().await;
92      }
93    }
94  }
95}
96
97pub struct Sendify<Fut>(pub(crate) Fut);
98
99unsafe impl<Fut> Send for Sendify<Fut> {}
100unsafe impl<Fut> Sync for Sendify<Fut> {}
101
102impl<Fut: Future> Future for Sendify<Fut> {
103  type Output = Fut::Output;
104
105  fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
106    unsafe { self.map_unchecked_mut(|s| &mut s.0) }.poll(cx)
107  }
108}
109
110#[allow(unused)]
111pub(crate) async fn insert_into_application(
112  app: SafePtrMut<Application<'static>>,
113  args: SafePtr<[&'static str]>,
114  line: SafePtrMut<usize>,
115  to_set: Cow<'static, str>,
116  heap: SafePtrMut<Heap>,
117  markers: SafePtrMut<HashMap<Cow<'static, str>, usize>>,
118) {
119  let app = unsafe { &mut *app.0 };
120  let heap = unsafe { &mut *heap.0 };
121  let markers = unsafe { &mut *markers.0 };
122  let args = unsafe { &*args.0 };
123  let line = unsafe { &mut *line.0 };
124
125  if args.len() == 3 {
126    let [a, v, v2] = &args[..] else {
127      panic!("Invalid syntax");
128    };
129
130    unsafe {
131      let a = &**a;
132
133      match a {
134        "*listen" => {
135          let function = &**v2;
136          let module = &**v;
137
138          let module = heap
139            .remove(module)
140            .expect("Invalid Format")
141            .expect("Unable to capture Runtime");
142
143          let BufValue::RuntimeRaw(module) = module else {
144            panic!("Expected, Lead Module");
145          };
146
147          let RawRTValue::RTCM(mut module) = module.0 else {
148            panic!("Expected, Lead Module only");
149          };
150
151          let BufValue::Listener(mut listen) = heap
152            .remove(function)
153            .expect("Unable to capture heaplistener")
154            .expect("Unable to capture heaplistener")
155          else {
156            panic!("Invalid! Not HeapListener")
157          };
158
159          let app_ptr: &'static mut Application = unsafe { transmute(&mut *app) };
160
161          tokio::spawn(Sendify(async move {
162            let mut dummy_heap = Heap::new(app_ptr.pkg.extends.clone());
163            let app = app_ptr as *mut _;
164
165            let mut opt = Options::new();
166
167            while let Some(event) = listen.recv().await {
168              let app = unsafe {
169                transmute::<&mut Application, &'static mut Application<'static>>(&mut *app)
170              };
171              let opt: &'static mut Options = unsafe { transmute(&mut opt) };
172              let dummy_heap: &'static mut Heap = unsafe { transmute(&mut dummy_heap) };
173              let module: &'static mut RTCreatedModule = unsafe { transmute(&mut module) };
174
175              module.run_method(
176                app as _,
177                "on",
178                "",
179                move |fn_heap, _, c| {
180                  if c.len() == 1 {
181                    let arg0: &'static str = unsafe { transmute(&*c[0]) };
182
183                    fn_heap.set(Cow::Borrowed(&arg0[2..]), event);
184                  } else {
185                    panic!("Expected, exactly 1 argument");
186                  }
187                },
188                dummy_heap,
189                opt,
190              );
191            }
192          }));
193        }
194        _ => panic!("Invalid syntax"),
195      }
196    }
197
198    return;
199  }
200
201  let [a, v] = &args[..] else {
202    panic!("Invalid syntax");
203  };
204
205  unsafe {
206    let v = &&**v;
207    match &**a {
208      "*run" => {
209        let v = SafePtr(*v);
210        let app = SafePtrMut(app);
211        tokio::spawn(Sendify(async move {
212          let app = app;
213          let app = Wrapped(app.0);
214          interpret(&v, app).await;
215        }))
216        .await;
217      }
218      "*mark" => {
219        markers.insert(Cow::Borrowed(*v as &str), *line);
220      }
221      "*goto" => {
222        *line = *markers.get(*v as &str).expect("No marker was found!");
223      }
224      "*prototype" => {
225        let packages = app.pkg_resolver.call_mut((v, true));
226
227        for pkg in packages {
228          // SAFETY: Infaillable
229          set_into_extends(pkg.extends.unwrap(), &mut heap.extends);
230        }
231      }
232      "*import" => {
233        let packages = app.pkg_resolver.call_mut((v, false));
234
235        let mut pkg = HashMap::new();
236
237        for package in packages {
238          let RespPackage { methods, .. } = package;
239
240          for (sig, call) in methods {
241            pkg.insert(sig.to_string(), *call);
242          }
243        }
244
245        let val = RawRTValue::PKG(pkg);
246
247        set_runtime_val(heap, to_set, val);
248      }
249      "*mod" => {
250        let LeadCode::LeadModule(code) = app.code.get(v).unwrap_or_else(|| {
251          panic!("Unable to read {v}, did you mean {v}.mod.pb?");
252        }) else {
253          panic!("Expected LeadModule, found Lead Code");
254        };
255
256        let m = parse_into_modules(app.pkg.extends.clone(), code);
257
258        set_runtime_val(heap, to_set, RawRTValue::RTCM(m));
259      }
260      a => panic!("Unknown {}", a),
261    };
262  }
263}
264
265pub(crate) fn parse_into_modules(
266  entry: Arc<ExtendsInternal>,
267  methods: &StaticLeadModule,
268) -> RTCreatedModule {
269  return RTCreatedModule {
270    heap: Heap::new(entry),
271    methods: methods.clone(),
272  };
273}