1use crate::ParserHandle;
2use intuicio_core::{
3 context::Context,
4 function::{Function, FunctionHandle, FunctionQuery},
5 host::Host,
6 registry::{Registry, RegistryHandle},
7 types::struct_type::NativeStructBuilder,
8};
9use intuicio_data::{
10 lifetime::Lifetime,
11 managed::{
12 DynamicManaged, DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut,
13 gc::DynamicManagedGc,
14 },
15};
16use std::sync::{Arc, RwLock, RwLockWriteGuard};
17
18pub mod shorthand {
19 use super::*;
20 use crate::{
21 pratt::{PrattParserAssociativity, PrattParserRule},
22 shorthand::{inspect, map_err, omap, pratt},
23 };
24
25 pub fn dyn_inspect(parser: ParserHandle, function_name: impl ToString) -> ParserHandle {
26 let function_name = function_name.to_string();
27 dynamic_extension(move |extension| {
28 let function_name = function_name.clone();
29 inspect(parser.clone(), move |value| {
30 extension
31 .call(&function_name)
32 .unwrap()
33 .arg(value.borrow().unwrap())
34 .call_no_return();
35 })
36 })
37 }
38
39 pub fn dyn_map(parser: ParserHandle, function_name: impl ToString) -> ParserHandle {
40 let function_name = function_name.to_string();
41 dynamic_extension(move |extension| {
42 let function_name = function_name.clone();
43 omap(parser.clone(), move |value| {
44 extension
45 .call(&function_name)
46 .unwrap()
47 .arg(value)
48 .call_return()
49 })
50 })
51 }
52
53 pub fn dyn_map_err(parser: ParserHandle, function_name: impl ToString) -> ParserHandle {
54 let function_name = function_name.to_string();
55 dynamic_extension(move |extension| {
56 let function_name = function_name.clone();
57 map_err(parser.clone(), move |error| {
58 extension
59 .call(&function_name)
60 .unwrap()
61 .arg_owned(error)
62 .call_return()
63 .consume()
64 .ok()
65 .unwrap()
66 })
67 })
68 }
69
70 #[derive(Debug, Clone)]
71 pub enum DynamicPrattParserRule {
72 Prefix {
73 operator_function_name: String,
74 transformer_function_name: String,
75 },
76 PrefixOp {
77 operator: String,
78 transformer_function_name: String,
79 },
80 Postfix {
81 operator_function_name: String,
82 transformer_function_name: String,
83 },
84 PostfixOp {
85 operator: String,
86 transformer_function_name: String,
87 },
88 Infix {
89 operator_function_name: String,
90 transformer_function_name: String,
91 associativity: PrattParserAssociativity,
92 },
93 InfixOp {
94 operator: String,
95 transformer_function_name: String,
96 associativity: PrattParserAssociativity,
97 },
98 }
99
100 pub fn dyn_pratt(
101 tokenizer_parser: ParserHandle,
102 rules: Vec<Vec<DynamicPrattParserRule>>,
103 ) -> ParserHandle {
104 dynamic_extension(move |extension| {
105 let rules = rules
106 .clone()
107 .into_iter()
108 .map(move |rules| {
109 rules
110 .into_iter()
111 .map(|rule| match rule {
112 DynamicPrattParserRule::Prefix {
113 operator_function_name,
114 transformer_function_name,
115 } => {
116 let extension_o = extension.clone();
117 let extension_t = extension.clone();
118 PrattParserRule::prefx_raw(
119 move |operator| {
120 extension_o
121 .call(&operator_function_name)
122 .unwrap()
123 .arg(operator.borrow().unwrap())
124 .call_return()
125 .consume()
126 .ok()
127 .unwrap()
128 },
129 move |value| {
130 extension_t
131 .call(&transformer_function_name)
132 .unwrap()
133 .arg(value)
134 .call_return()
135 },
136 )
137 }
138 DynamicPrattParserRule::PrefixOp {
139 operator,
140 transformer_function_name,
141 } => {
142 let extension_t = extension.clone();
143 PrattParserRule::prefx_raw(
144 move |token| {
145 token
146 .read::<String>()
147 .map(|op| *op == operator)
148 .unwrap_or_default()
149 },
150 move |value| {
151 extension_t
152 .call(&transformer_function_name)
153 .unwrap()
154 .arg(value)
155 .call_return()
156 },
157 )
158 }
159 DynamicPrattParserRule::Postfix {
160 operator_function_name,
161 transformer_function_name,
162 } => {
163 let extension_o = extension.clone();
164 let extension_t = extension.clone();
165 PrattParserRule::postfix_raw(
166 move |operator| {
167 extension_o
168 .call(&operator_function_name)
169 .unwrap()
170 .arg(operator.borrow().unwrap())
171 .call_return()
172 .consume()
173 .ok()
174 .unwrap()
175 },
176 move |value| {
177 extension_t
178 .call(&transformer_function_name)
179 .unwrap()
180 .arg(value)
181 .call_return()
182 },
183 )
184 }
185 DynamicPrattParserRule::PostfixOp {
186 operator,
187 transformer_function_name,
188 } => {
189 let extension_t = extension.clone();
190 PrattParserRule::postfix_raw(
191 move |token| {
192 token
193 .read::<String>()
194 .map(|op| *op == operator)
195 .unwrap_or_default()
196 },
197 move |value| {
198 extension_t
199 .call(&transformer_function_name)
200 .unwrap()
201 .arg(value)
202 .call_return()
203 },
204 )
205 }
206 DynamicPrattParserRule::Infix {
207 operator_function_name,
208 transformer_function_name,
209 associativity,
210 } => {
211 let extension_o = extension.clone();
212 let extension_t = extension.clone();
213 PrattParserRule::infix_raw(
214 move |operator| {
215 extension_o
216 .call(&operator_function_name)
217 .unwrap()
218 .arg(operator.borrow().unwrap())
219 .call_return()
220 .consume()
221 .ok()
222 .unwrap()
223 },
224 move |lhs, rhs| {
225 extension_t
226 .call(&transformer_function_name)
227 .unwrap()
228 .arg(lhs)
229 .arg(rhs)
230 .call_return()
231 },
232 associativity,
233 )
234 }
235 DynamicPrattParserRule::InfixOp {
236 operator,
237 transformer_function_name,
238 associativity,
239 } => {
240 let extension_t = extension.clone();
241 PrattParserRule::infix_raw(
242 move |token| {
243 token
244 .read::<String>()
245 .map(|op| *op == operator)
246 .unwrap_or_default()
247 },
248 move |lhs, rhs| {
249 extension_t
250 .call(&transformer_function_name)
251 .unwrap()
252 .arg(lhs)
253 .arg(rhs)
254 .call_return()
255 },
256 associativity,
257 )
258 }
259 })
260 .collect()
261 })
262 .collect();
263 pratt(tokenizer_parser.clone(), rules)
264 })
265 }
266}
267
268pub struct DynamicExtensionBuilder {
269 registry: Registry,
270}
271
272impl Default for DynamicExtensionBuilder {
273 fn default() -> Self {
274 Self {
275 registry: Registry::default()
276 .with_type(
277 NativeStructBuilder::new_named_uninitialized::<DynamicManaged>(
278 "DynamicManaged",
279 )
280 .build(),
281 )
282 .with_type(
283 NativeStructBuilder::new_named_uninitialized::<DynamicManagedRef>(
284 "DynamicManagedRef",
285 )
286 .build(),
287 )
288 .with_type(
289 NativeStructBuilder::new_named_uninitialized::<DynamicManagedRefMut>(
290 "DynamicManagedRefMut",
291 )
292 .build(),
293 )
294 .with_type(
295 NativeStructBuilder::new_named_uninitialized::<DynamicManagedLazy>(
296 "DynamicManagedLazy",
297 )
298 .build(),
299 )
300 .with_type(
301 NativeStructBuilder::new_named_uninitialized::<DynamicManagedGc>(
302 "DynamicManagedGc",
303 )
304 .build(),
305 ),
306 }
307 }
308}
309
310impl DynamicExtensionBuilder {
311 pub fn with(mut self, f: impl FnOnce(&Registry) -> Function) -> Self {
312 self.add(f);
313 self
314 }
315
316 pub fn add(&mut self, f: impl FnOnce(&Registry) -> Function) {
317 self.registry.add_function(f(&self.registry));
318 }
319
320 pub fn build(self) -> DynamicExtension {
321 DynamicExtension {
322 host: Arc::new(RwLock::new(Host::new(
323 Context::new(10240, 10240),
324 RegistryHandle::new(self.registry),
325 ))),
326 }
327 }
328}
329
330pub struct DynamicExtension {
331 host: Arc<RwLock<Host>>,
332}
333
334impl DynamicExtension {
335 pub fn call<'a>(&'a self, name: &str) -> Option<DynamicExtensionCall<'a>> {
336 let host = self.host.write().ok()?;
337 let handle = host.registry().find_function(FunctionQuery {
338 name: Some(name.into()),
339 ..Default::default()
340 })?;
341 Some(DynamicExtensionCall {
342 host,
343 handle,
344 args: vec![],
345 lifetimes: vec![],
346 })
347 }
348}
349
350pub enum Value {
351 Owned(DynamicManaged),
352 Ref(DynamicManagedRef),
353 RefMut(DynamicManagedRefMut),
354 Lazy(DynamicManagedLazy),
355 Gc(DynamicManagedGc),
356}
357
358impl From<DynamicManaged> for Value {
359 fn from(value: DynamicManaged) -> Self {
360 Self::Owned(value)
361 }
362}
363
364impl From<DynamicManagedRef> for Value {
365 fn from(value: DynamicManagedRef) -> Self {
366 Self::Ref(value)
367 }
368}
369
370impl From<DynamicManagedRefMut> for Value {
371 fn from(value: DynamicManagedRefMut) -> Self {
372 Self::RefMut(value)
373 }
374}
375
376impl From<DynamicManagedLazy> for Value {
377 fn from(value: DynamicManagedLazy) -> Self {
378 Self::Lazy(value)
379 }
380}
381
382impl From<DynamicManagedGc> for Value {
383 fn from(value: DynamicManagedGc) -> Self {
384 Self::Gc(value)
385 }
386}
387
388pub struct DynamicExtensionCall<'a> {
389 host: RwLockWriteGuard<'a, Host>,
390 handle: FunctionHandle,
391 args: Vec<Value>,
392 lifetimes: Vec<Lifetime>,
393}
394
395impl DynamicExtensionCall<'_> {
396 pub fn arg(mut self, value: impl Into<Value>) -> Self {
397 self.args.push(value.into());
398 self
399 }
400
401 pub fn arg_owned<T>(mut self, value: T) -> Self {
402 let value = DynamicManaged::new(value).ok().unwrap();
403 self.args.push(Value::Owned(value));
404 self
405 }
406
407 pub fn arg_ref<T>(mut self, value: &T) -> Self {
408 let lifetime = Lifetime::default();
409 let value = DynamicManagedRef::new(value, lifetime.borrow().unwrap());
410 self.args.push(Value::Ref(value));
411 self.lifetimes.push(lifetime);
412 self
413 }
414
415 pub fn arg_ref_mut<T>(mut self, value: &mut T) -> Self {
416 let lifetime = Lifetime::default();
417 let value = DynamicManagedRefMut::new(value, lifetime.borrow_mut().unwrap());
418 self.args.push(Value::RefMut(value));
419 self.lifetimes.push(lifetime);
420 self
421 }
422
423 pub fn arg_lazy<T>(mut self, value: &mut T) -> Self {
424 let lifetime = Lifetime::default();
425 let value = DynamicManagedLazy::new(value, lifetime.lazy());
426 self.args.push(Value::Lazy(value));
427 self.lifetimes.push(lifetime);
428 self
429 }
430
431 pub fn arg_gc<T>(mut self, value: T) -> Self {
432 let value = DynamicManagedGc::new(value);
433 self.args.push(Value::Gc(value));
434 self
435 }
436
437 pub fn call_return(mut self) -> DynamicManaged {
438 let (context, registry) = self.host.context_and_registry();
439 for arg in self.args.into_iter().rev() {
440 match arg {
441 Value::Owned(value) => context.stack().push(value),
442 Value::Ref(value) => context.stack().push(value),
443 Value::RefMut(value) => context.stack().push(value),
444 Value::Lazy(value) => context.stack().push(value),
445 Value::Gc(value) => context.stack().push(value),
446 };
447 }
448 self.handle.invoke(context, registry);
449 context.stack().pop::<DynamicManaged>().unwrap()
450 }
451
452 pub fn call_no_return(mut self) {
453 let (context, registry) = self.host.context_and_registry();
454 for arg in self.args.into_iter().rev() {
455 match arg {
456 Value::Owned(value) => context.stack().push(value),
457 Value::Ref(value) => context.stack().push(value),
458 Value::RefMut(value) => context.stack().push(value),
459 Value::Lazy(value) => context.stack().push(value),
460 Value::Gc(value) => context.stack().push(value),
461 };
462 }
463 self.handle.invoke(context, registry);
464 }
465}
466
467pub fn dynamic_extension(
468 f: impl Fn(Arc<DynamicExtension>) -> ParserHandle + Send + Sync + 'static,
469) -> ParserHandle {
470 crate::shorthand::ext::<DynamicExtension>(f)
471}
472
473#[cfg(test)]
474mod tests {
475 use super::{DynamicExtensionBuilder, dynamic_extension};
476 use crate::{
477 ParserRegistry,
478 shorthand::{map, number_float},
479 };
480 use intuicio_core::transformer::{DynamicManagedValueTransformer, ValueTransformer};
481 use intuicio_derive::intuicio_function;
482
483 #[intuicio_function(transformer = "DynamicManagedValueTransformer")]
484 fn foo(value: String) -> f32 {
485 value.parse().unwrap()
486 }
487
488 #[test]
489 fn test_dynamic_extension() {
490 let extension = DynamicExtensionBuilder::default()
491 .with(foo::define_function)
492 .build();
493 let registry = ParserRegistry::default().with_extension(extension);
494 let parser = dynamic_extension(|extension| {
495 map::<String, f32>(number_float(), move |v| {
496 extension
497 .call("foo")
498 .unwrap()
499 .arg_owned(v)
500 .call_return()
501 .consume()
502 .ok()
503 .unwrap()
504 })
505 });
506 let (rest, result) = parser.parse(®istry, "42.0").unwrap();
507 assert_eq!(rest, "");
508 assert_eq!(result.consume::<f32>().ok().unwrap(), 42.0);
509 }
510}