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 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 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 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}