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