ad_astra/runtime/ops.rs
1////////////////////////////////////////////////////////////////////////////////
2// This file is part of "Ad Astra", an embeddable scripting programming //
3// language platform. //
4// //
5// This work is proprietary software with source-available code. //
6// //
7// To copy, use, distribute, or contribute to this work, you must agree to //
8// the terms of the General License Agreement: //
9// //
10// https://github.com/Eliah-Lakhin/ad-astra/blob/master/EULA.md //
11// //
12// The agreement grants a Basic Commercial License, allowing you to use //
13// this work in non-commercial and limited commercial products with a total //
14// gross revenue cap. To remove this commercial limit for one of your //
15// products, you must acquire a Full Commercial License. //
16// //
17// If you contribute to the source code, documentation, or related materials, //
18// you must grant me an exclusive license to these contributions. //
19// Contributions are governed by the "Contributions" section of the General //
20// License Agreement. //
21// //
22// Copying the work in parts is strictly forbidden, except as permitted //
23// under the General License Agreement. //
24// //
25// If you do not or cannot agree to the terms of this Agreement, //
26// do not use this work. //
27// //
28// This work is provided "as is", without any warranties, express or implied, //
29// except where such disclaimers are legally invalid. //
30// //
31// Copyright (c) 2024 Ilya Lakhin (Илья Александрович Лахин). //
32// All rights reserved. //
33////////////////////////////////////////////////////////////////////////////////
34
35use std::{
36 cmp::Ordering,
37 fmt::{Debug, Display, Formatter},
38 hash::Hash,
39};
40
41pub(crate) use crate::runtime::ops::functions::{
42 Fn0Repr,
43 Fn1Repr,
44 Fn2Repr,
45 Fn3Repr,
46 Fn4Repr,
47 Fn5Repr,
48 Fn6Repr,
49 Fn7Repr,
50};
51pub use crate::runtime::ops::{
52 functions::{Fn0, Fn1, Fn2, Fn3, Fn4, Fn5, Fn6, Fn7},
53 types::{DynamicArgument, DynamicReturn, DynamicType},
54};
55use crate::runtime::{Arg, Cell, Ident, InvocationMeta, Origin, RuntimeResult};
56
57/// A script assignment operator: `lhs = rhs`.
58///
59/// Implementing this trait enables the
60/// [Object::assign](crate::runtime::Object::assign) operation.
61///
62/// The trait must be implemented for the
63/// [registered type](crate::runtime::ScriptType), and the implementation must
64/// be exported using the [export](crate::export) macro. For more details,
65/// see the [module documentation](crate::runtime::ops).
66pub trait ScriptAssign {
67 /// A rough estimation of the type of the right-hand side of the operation.
68 ///
69 /// This type must implement [ScriptType](crate::runtime::ScriptType).
70 type RHS: ?Sized;
71
72 /// Operation implementation.
73 ///
74 /// The parameters and return type of this function correspond to those of
75 /// the [Object::assign](crate::runtime::Object::assign) function.
76 fn script_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
77}
78
79/// A script concatenation operator: `[a, b, c]`.
80///
81/// Implementing this trait enables the
82/// [TypeMeta::concat](crate::runtime::TypeMeta::concat) operation.
83///
84/// The trait must be implemented for the
85/// [registered type](crate::runtime::ScriptType), and the implementation must
86/// be exported using the [export](crate::export) macro. For more details, see
87/// the [module documentation](crate::runtime::ops).
88pub trait ScriptConcat {
89 /// A rough estimation of the result type of this operation.
90 ///
91 /// This type must implement [ScriptType](crate::runtime::ScriptType).
92 type Result: ?Sized;
93
94 /// Operation implementation.
95 ///
96 /// The parameters and return type of this function correspond to those of
97 /// the [TypeMeta::concat](crate::runtime::TypeMeta::concat) function.
98 fn script_concat(origin: Origin, items: &mut [Arg]) -> RuntimeResult<Cell>;
99}
100
101/// A dynamic resolver of the object fields: `foo.bar`.
102///
103/// Implementing this trait enables the
104/// [Object::field](crate::runtime::Object::field) operation.
105///
106/// The trait must be implemented for the
107/// [registered type](crate::runtime::ScriptType), and the implementation must
108/// be exported using the [export](crate::export) macro. For more details, see
109/// the [module documentation](crate::runtime::ops).
110pub trait ScriptField {
111 /// A rough estimation of the result type of this operation.
112 ///
113 /// This type must implement [ScriptType](crate::runtime::ScriptType).
114 ///
115 /// If the type is fully dynamic, consider using the [DynamicType] type as
116 /// a `Result` specification.
117 type Result: ?Sized;
118
119 /// Operation implementation.
120 ///
121 /// The parameters and return type of this function correspond to those of
122 /// the [Object::field](crate::runtime::Object::field) function.
123 fn script_field(origin: Origin, lhs: Arg, rhs: Ident) -> RuntimeResult<Cell>;
124}
125
126/// A script [cloning](Clone) operator: `*foo`.
127///
128/// Implementing this trait enables the
129/// [Object::clone](crate::runtime::Object::clone) operation.
130///
131/// The underlying type on which this trait is implemented must also implement
132/// the [Clone] trait, which provides the actual implementation of the script
133/// cloning operation.
134///
135/// The trait must be implemented for the
136/// [registered type](crate::runtime::ScriptType), and the implementation must
137/// be exported using the [export](crate::export) macro. For more details, see
138/// the [module documentation](crate::runtime::ops).
139pub trait ScriptClone: Clone {}
140
141/// A script [debugging](Debug) formatting operator.
142///
143/// Implementing this trait enables the
144/// [Object::debug](crate::runtime::Object::debug) operation.
145///
146/// The underlying type on which this trait is implemented must also implement
147/// the [Debug] trait, which provides the actual implementation of the script
148/// debugging operation.
149///
150/// The trait must be implemented for the
151/// [registered type](crate::runtime::ScriptType), and the implementation must
152/// be exported using the [export](crate::export) macro. For more details, see
153/// the [module documentation](crate::runtime::ops).
154pub trait ScriptDebug: Debug {}
155
156/// A script [displaying](Display) formatting operator.
157///
158/// Implementing this trait enables the
159/// [Object::display](crate::runtime::Object::display) operation.
160///
161/// The underlying type on which this trait is implemented must also implement
162/// the [Display] trait, which provides the actual implementation of the script
163/// debugging operation.
164///
165/// The trait must be implemented for the
166/// [registered type](crate::runtime::ScriptType), and the implementation must
167/// be exported using the [export](crate::export) macro. For more details, see
168/// the [module documentation](crate::runtime::ops).
169pub trait ScriptDisplay: Display {}
170
171/// A script equality operator: `lhs == rhs`.
172///
173/// Implementing this trait enables the
174/// [Object::partial_eq](crate::runtime::Object::partial_eq) operation.
175///
176/// Note that the implementation of [ScriptPartialEq::script_eq] serves both
177/// partial and [full equality](Eq) purposes.
178///
179/// The trait must be implemented for the
180/// [registered type](crate::runtime::ScriptType), and the implementation must
181/// be exported using the [export](crate::export) macro. For more details, see
182/// the [module documentation](crate::runtime::ops).
183pub trait ScriptPartialEq {
184 /// A rough estimation of the type of the right-hand side of the operation.
185 ///
186 /// This type must implement [ScriptType](crate::runtime::ScriptType).
187 type RHS: ?Sized;
188
189 /// Operation implementation.
190 ///
191 /// The parameters and return type of this function correspond to those of
192 /// the [Object::partial_eq](crate::runtime::Object::partial_eq) function.
193 fn script_eq(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<bool>;
194}
195
196/// A default constructor for a script object.
197///
198/// Implementing this trait enables the
199/// [TypeMeta::instantiate](crate::runtime::TypeMeta::instantiate) operation.
200///
201/// The trait must be implemented for the
202/// [registered type](crate::runtime::ScriptType), and the implementation must
203/// be exported using the [export](crate::export) macro. For more details, see
204/// the [module documentation](crate::runtime::ops).
205pub trait ScriptDefault {
206 /// Operation implementation.
207 ///
208 /// The parameter and return type of this function correspond to those of
209 /// the [TypeMeta::instantiate](crate::runtime::TypeMeta::instantiate)
210 /// function.
211 fn script_default(origin: Origin) -> RuntimeResult<Cell>;
212}
213
214/// A script partial ordering operator: `lhs >= rhs`, `lhs < rhs`, etc.
215///
216/// Implementing this trait enables the
217/// [Object::partial_ord](crate::runtime::Object::partial_ord) operation.
218///
219/// The trait must be implemented for the
220/// [registered type](crate::runtime::ScriptType), and the implementation must
221/// be exported using the [export](crate::export) macro. For more details, see
222/// the [module documentation](crate::runtime::ops).
223pub trait ScriptPartialOrd {
224 /// A rough estimation of the type of the right-hand side of the operation.
225 ///
226 /// This type must implement [ScriptType](crate::runtime::ScriptType).
227 type RHS: ?Sized;
228
229 /// Operation implementation.
230 ///
231 /// The parameters and return type of this function correspond to those of
232 /// the [Object::partial_ord](crate::runtime::Object::partial_ord) function.
233 fn script_partial_cmp(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Option<Ordering>>;
234}
235
236/// A script full ordering operator: `lhs >= rhs`, `lhs < rhs`, etc.
237///
238/// Implementing this trait enables the
239/// [Object::ord](crate::runtime::Object::ord) operation.
240///
241/// The trait must be implemented for the
242/// [registered type](crate::runtime::ScriptType), and the implementation must
243/// be exported using the [export](crate::export) macro. For more details, see
244/// the [module documentation](crate::runtime::ops).
245pub trait ScriptOrd {
246 /// Operation implementation.
247 ///
248 /// The parameters and return type of this function correspond to those of
249 /// the [Object::ord](crate::runtime::Object::ord) function.
250 fn script_cmp(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Ordering>;
251}
252
253/// A script data [hashing](Hash) operator.
254///
255/// Implementing this trait enables the
256/// [Object::hash](crate::runtime::Object::hash) operation.
257///
258/// The underlying type on which this trait is implemented must also implement
259/// the [Hash] trait, which provides the actual implementation of the script
260/// data hashing operation.
261///
262/// The trait must be implemented for the
263/// [registered type](crate::runtime::ScriptType), and the implementation must
264/// be exported using the [export](crate::export) macro. For more details, see
265/// the [module documentation](crate::runtime::ops).
266pub trait ScriptHash: Hash {}
267
268/// A script invocation operator: `foo(arg1, arg2, arg3)`.
269///
270/// Implementing this trait enables the
271/// [Object::invoke](crate::runtime::Object::invoke) operation.
272///
273/// The trait must be implemented for the
274/// [registered type](crate::runtime::ScriptType), and the implementation must
275/// be exported using the [export](crate::export) macro. For more details, see
276/// the [module documentation](crate::runtime::ops).
277pub trait ScriptInvocation {
278 /// Operation implementation.
279 ///
280 /// The parameters and return type of this function correspond to those of
281 /// the [Object::invoke](crate::runtime::Object::invoke) function.
282 fn invoke(origin: Origin, lhs: Arg, arguments: &mut [Arg]) -> RuntimeResult<Cell>;
283
284 /// Returns the invocation signature description.
285 ///
286 /// The function returns None if the signature is fully dynamic.
287 fn hint() -> Option<&'static InvocationMeta>;
288}
289
290/// A script context binding operator.
291///
292/// Implementing this trait enables the
293/// [Object::bind](crate::runtime::Object::bind) operation.
294///
295/// The trait must be implemented for the
296/// [registered type](crate::runtime::ScriptType), and the implementation must
297/// be exported using the [export](crate::export) macro. For more details, see
298/// the [module documentation](crate::runtime::ops).
299pub trait ScriptBinding {
300 /// A rough estimation of the type of the right-hand side of the operation.
301 ///
302 /// This type must implement [ScriptType](crate::runtime::ScriptType).
303 type RHS: ?Sized;
304
305 /// Operation implementation.
306 ///
307 /// The parameters and return type of this function correspond to those of
308 /// the [Object::bind](crate::runtime::Object::bind) function.
309 fn script_binding(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
310}
311
312/// A script addition operator: `lhs + rhs`.
313///
314/// Implementing this trait enables the
315/// [Object::add](crate::runtime::Object::add) operation.
316///
317/// The trait must be implemented for the
318/// [registered type](crate::runtime::ScriptType), and the implementation must
319/// be exported using the [export](crate::export) macro. For more details, see
320/// the [module documentation](crate::runtime::ops).
321pub trait ScriptAdd {
322 /// A rough estimation of the type of the right-hand side of the operation.
323 ///
324 /// This type must implement [ScriptType](crate::runtime::ScriptType).
325 type RHS: ?Sized;
326
327 /// A rough estimation of the result type of this operation.
328 ///
329 /// This type must implement [ScriptType](crate::runtime::ScriptType).
330 type Result: ?Sized;
331
332 /// Operation implementation.
333 ///
334 /// The parameters and return type of this function correspond to those of
335 /// the [Object::add](crate::runtime::Object::add) function.
336 fn script_add(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
337}
338
339/// A script addition and assignment operator: `lhs += rhs`.
340///
341/// Implementing this trait enables the
342/// [Object::add_assign](crate::runtime::Object::add_assign) operation.
343///
344/// The trait must be implemented for the
345/// [registered type](crate::runtime::ScriptType), and the implementation must
346/// be exported using the [export](crate::export) macro. For more details, see
347/// the [module documentation](crate::runtime::ops).
348pub trait ScriptAddAssign {
349 /// A rough estimation of the type of the right-hand side of the operation.
350 ///
351 /// This type must implement [ScriptType](crate::runtime::ScriptType).
352 type RHS: ?Sized;
353
354 /// Operation implementation.
355 ///
356 /// The parameters and return type of this function correspond to those of
357 /// the [Object::add_assign](crate::runtime::Object::add_assign) function.
358 fn script_add_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
359}
360
361/// A script subtraction operator: `lhs - rhs`.
362///
363/// Implementing this trait enables the
364/// [Object::sub](crate::runtime::Object::sub) operation.
365///
366/// The trait must be implemented for the
367/// [registered type](crate::runtime::ScriptType), and the implementation must
368/// be exported using the [export](crate::export) macro. For more details, see
369/// the [module documentation](crate::runtime::ops).
370pub trait ScriptSub {
371 /// A rough estimation of the type of the right-hand side of the operation.
372 ///
373 /// This type must implement [ScriptType](crate::runtime::ScriptType).
374 type RHS: ?Sized;
375
376 /// A rough estimation of the result type of this operation.
377 ///
378 /// This type must implement [ScriptType](crate::runtime::ScriptType).
379 type Result: ?Sized;
380
381 /// Operation implementation.
382 ///
383 /// The parameters and return type of this function correspond to those of
384 /// the [Object::sub](crate::runtime::Object::sub) function.
385 fn script_sub(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
386}
387
388/// A script subtraction and assignment operator: `lhs -= rhs`.
389///
390/// Implementing this trait enables the
391/// [Object::sub_assign](crate::runtime::Object::sub_assign) operation.
392///
393/// The trait must be implemented for the
394/// [registered type](crate::runtime::ScriptType), and the implementation must
395/// be exported using the [export](crate::export) macro. For more details, see
396/// the [module documentation](crate::runtime::ops).
397pub trait ScriptSubAssign {
398 /// A rough estimation of the type of the right-hand side of the operation.
399 ///
400 /// This type must implement [ScriptType](crate::runtime::ScriptType).
401 type RHS: ?Sized;
402
403 /// Operation implementation.
404 ///
405 /// The parameters and return type of this function correspond to those of
406 /// the [Object::sub_assign](crate::runtime::Object::sub_assign) function.
407 fn script_sub_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
408}
409
410/// A script multiplication operator: `lhs * rhs`.
411///
412/// Implementing this trait enables the
413/// [Object::mul](crate::runtime::Object::mul) operation.
414///
415/// The trait must be implemented for the
416/// [registered type](crate::runtime::ScriptType), and the implementation must
417/// be exported using the [export](crate::export) macro. For more details, see
418/// the [module documentation](crate::runtime::ops).
419pub trait ScriptMul {
420 /// A rough estimation of the type of the right-hand side of the operation.
421 ///
422 /// This type must implement [ScriptType](crate::runtime::ScriptType).
423 type RHS: ?Sized;
424
425 /// A rough estimation of the result type of this operation.
426 ///
427 /// This type must implement [ScriptType](crate::runtime::ScriptType).
428 type Result: ?Sized;
429
430 /// Operation implementation.
431 ///
432 /// The parameters and return type of this function correspond to those of
433 /// the [Object::mul](crate::runtime::Object::mul) function.
434 fn script_mul(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
435}
436
437/// A script multiplication and assignment operator: `lhs *= rhs`.
438///
439/// Implementing this trait enables the
440/// [Object::mul_assign](crate::runtime::Object::mul_assign) operation.
441///
442/// The trait must be implemented for the
443/// [registered type](crate::runtime::ScriptType), and the implementation must
444/// be exported using the [export](crate::export) macro. For more details, see
445/// the [module documentation](crate::runtime::ops).
446pub trait ScriptMulAssign {
447 /// A rough estimation of the type of the right-hand side of the operation.
448 ///
449 /// This type must implement [ScriptType](crate::runtime::ScriptType).
450 type RHS: ?Sized;
451
452 /// Operation implementation.
453 ///
454 /// The parameters and return type of this function correspond to those of
455 /// the [Object::mul_assign](crate::runtime::Object::mul_assign) function.
456 fn script_mul_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
457}
458
459/// A script division operator: `lhs / rhs`.
460///
461/// Implementing this trait enables the
462/// [Object::div](crate::runtime::Object::div) operation.
463///
464/// The trait must be implemented for the
465/// [registered type](crate::runtime::ScriptType), and the implementation must
466/// be exported using the [export](crate::export) macro. For more details, see
467/// the [module documentation](crate::runtime::ops).
468pub trait ScriptDiv {
469 /// A rough estimation of the type of the right-hand side of the operation.
470 ///
471 /// This type must implement [ScriptType](crate::runtime::ScriptType).
472 type RHS: ?Sized;
473
474 /// A rough estimation of the result type of this operation.
475 ///
476 /// This type must implement [ScriptType](crate::runtime::ScriptType).
477 type Result: ?Sized;
478
479 /// Operation implementation.
480 ///
481 /// The parameters and return type of this function correspond to those of
482 /// the [Object::div](crate::runtime::Object::div) function.
483 fn script_div(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
484}
485
486/// A script division and assignment operator: `lhs /= rhs`.
487///
488/// Implementing this trait enables the
489/// [Object::div_assign](crate::runtime::Object::div_assign) operation.
490///
491/// The trait must be implemented for the
492/// [registered type](crate::runtime::ScriptType), and the implementation must
493/// be exported using the [export](crate::export) macro. For more details, see
494/// the [module documentation](crate::runtime::ops).
495pub trait ScriptDivAssign {
496 /// A rough estimation of the type of the right-hand side of the operation.
497 ///
498 /// This type must implement [ScriptType](crate::runtime::ScriptType).
499 type RHS: ?Sized;
500
501 /// Operation implementation.
502 ///
503 /// The parameters and return type of this function correspond to those of
504 /// the [Object::div_assign](crate::runtime::Object::div_assign) function.
505 fn script_div_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
506}
507
508/// A script logical conjunction operator: `lhs && rhs`.
509///
510/// Implementing this trait enables the
511/// [Object::and](crate::runtime::Object::and) operation.
512///
513/// The trait must be implemented for the
514/// [registered type](crate::runtime::ScriptType), and the implementation must
515/// be exported using the [export](crate::export) macro. For more details, see
516/// the [module documentation](crate::runtime::ops).
517pub trait ScriptAnd {
518 /// A rough estimation of the type of the right-hand side of the operation.
519 ///
520 /// This type must implement [ScriptType](crate::runtime::ScriptType).
521 type RHS: ?Sized;
522
523 /// A rough estimation of the result type of this operation.
524 ///
525 /// This type must implement [ScriptType](crate::runtime::ScriptType).
526 type Result: ?Sized;
527
528 /// Operation implementation.
529 ///
530 /// The parameters and return type of this function correspond to those of
531 /// the [Object::and](crate::runtime::Object::and) function.
532 fn script_and(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
533}
534
535/// A script logical disjunction operator: `lhs || rhs`.
536///
537/// Implementing this trait enables the
538/// [Object::or](crate::runtime::Object::or) operation.
539///
540/// The trait must be implemented for the
541/// [registered type](crate::runtime::ScriptType), and the implementation must
542/// be exported using the [export](crate::export) macro. For more details, see
543/// the [module documentation](crate::runtime::ops).
544pub trait ScriptOr {
545 /// A rough estimation of the type of the right-hand side of the operation.
546 ///
547 /// This type must implement [ScriptType](crate::runtime::ScriptType).
548 type RHS: ?Sized;
549
550 /// A rough estimation of the result type of this operation.
551 ///
552 /// This type must implement [ScriptType](crate::runtime::ScriptType).
553 type Result: ?Sized;
554
555 /// Operation implementation.
556 ///
557 /// The parameters and return type of this function correspond to those of
558 /// the [Object::or](crate::runtime::Object::or) function.
559 fn script_or(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
560}
561
562/// A script logical negation operator: `!foo`.
563///
564/// Implementing this trait enables the
565/// [Object::not](crate::runtime::Object::not) operation.
566///
567/// The trait must be implemented for the
568/// [registered type](crate::runtime::ScriptType), and the implementation must
569/// be exported using the [export](crate::export) macro. For more details, see
570/// the [module documentation](crate::runtime::ops).
571pub trait ScriptNot {
572 /// A rough estimation of the result type of this operation.
573 ///
574 /// This type must implement [ScriptType](crate::runtime::ScriptType).
575 type Result: ?Sized;
576
577 /// Operation implementation.
578 ///
579 /// The parameters and return type of this function correspond to those of
580 /// the [Object::not](crate::runtime::Object::not) function.
581 fn script_not(origin: Origin, lhs: Arg) -> RuntimeResult<Cell>;
582}
583
584/// A script numeric negation operator: `-foo`.
585///
586/// Implementing this trait enables the
587/// [Object::neg](crate::runtime::Object::neg) operation.
588///
589/// The trait must be implemented for the
590/// [registered type](crate::runtime::ScriptType), and the implementation must
591/// be exported using the [export](crate::export) macro. For more details, see
592/// the [module documentation](crate::runtime::ops).
593pub trait ScriptNeg {
594 /// A rough estimation of the result type of this operation.
595 ///
596 /// This type must implement [ScriptType](crate::runtime::ScriptType).
597 type Result: ?Sized;
598
599 /// Operation implementation.
600 ///
601 /// The parameters and return type of this function correspond to those of
602 /// the [Object::neg](crate::runtime::Object::neg) function.
603 fn script_neg(origin: Origin, lhs: Arg) -> RuntimeResult<Cell>;
604}
605
606/// A script bitwise conjunction operator: `lhs & rhs`.
607///
608/// Implementing this trait enables the
609/// [Object::bit_and](crate::runtime::Object::bit_and) operation.
610///
611/// The trait must be implemented for the
612/// [registered type](crate::runtime::ScriptType), and the implementation must
613/// be exported using the [export](crate::export) macro. For more details, see
614/// the [module documentation](crate::runtime::ops).
615pub trait ScriptBitAnd {
616 /// A rough estimation of the type of the right-hand side of the operation.
617 ///
618 /// This type must implement [ScriptType](crate::runtime::ScriptType).
619 type RHS: ?Sized;
620
621 /// A rough estimation of the result type of this operation.
622 ///
623 /// This type must implement [ScriptType](crate::runtime::ScriptType).
624 type Result: ?Sized;
625
626 /// Operation implementation.
627 ///
628 /// The parameters and return type of this function correspond to those of
629 /// the [Object::bit_and](crate::runtime::Object::bit_and) function.
630 fn script_bit_and(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
631}
632
633/// A script bitwise conjunction and assignment operator: `lhs &= rhs`.
634///
635/// Implementing this trait enables the
636/// [Object::bit_and_assign](crate::runtime::Object::bit_and_assign) operation.
637///
638/// The trait must be implemented for the
639/// [registered type](crate::runtime::ScriptType), and the implementation must
640/// be exported using the [export](crate::export) macro. For more details, see
641/// the [module documentation](crate::runtime::ops).
642pub trait ScriptBitAndAssign {
643 /// A rough estimation of the type of the right-hand side of the operation.
644 ///
645 /// This type must implement [ScriptType](crate::runtime::ScriptType).
646 type RHS: ?Sized;
647
648 /// Operation implementation.
649 ///
650 /// The parameters and return type of this function correspond to those of
651 /// the [Object::bit_and_assign](crate::runtime::Object::bit_and_assign)
652 /// function.
653 fn script_bit_and_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
654}
655
656/// A script bitwise disjunction operator: `lhs | rhs`.
657///
658/// Implementing this trait enables the
659/// [Object::bit_or](crate::runtime::Object::bit_or) operation.
660///
661/// The trait must be implemented for the
662/// [registered type](crate::runtime::ScriptType), and the implementation must
663/// be exported using the [export](crate::export) macro. For more details, see
664/// the [module documentation](crate::runtime::ops).
665pub trait ScriptBitOr {
666 /// A rough estimation of the type of the right-hand side of the operation.
667 ///
668 /// This type must implement [ScriptType](crate::runtime::ScriptType).
669 type RHS: ?Sized;
670
671 /// A rough estimation of the result type of this operation.
672 ///
673 /// This type must implement [ScriptType](crate::runtime::ScriptType).
674 type Result: ?Sized;
675
676 /// Operation implementation.
677 ///
678 /// The parameters and return type of this function correspond to those of
679 /// the [Object::bit_or](crate::runtime::Object::bit_or) function.
680 fn script_bit_or(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
681}
682
683/// A script bitwise disjunction and assignment operator: `lhs |= rhs`.
684///
685/// Implementing this trait enables the
686/// [Object::bit_or_assign](crate::runtime::Object::bit_or_assign) operation.
687///
688/// The trait must be implemented for the
689/// [registered type](crate::runtime::ScriptType), and the implementation must
690/// be exported using the [export](crate::export) macro. For more details, see
691/// the [module documentation](crate::runtime::ops).
692pub trait ScriptBitOrAssign {
693 /// A rough estimation of the type of the right-hand side of the operation.
694 ///
695 /// This type must implement [ScriptType](crate::runtime::ScriptType).
696 type RHS: ?Sized;
697
698 /// Operation implementation.
699 ///
700 /// The parameters and return type of this function correspond to those of
701 /// the [Object::bit_or_assign](crate::runtime::Object::bit_or_assign)
702 /// function.
703 fn script_bit_or_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
704}
705
706/// A script bitwise exclusive disjunction operator: `lhs ^ rhs`.
707///
708/// Implementing this trait enables the
709/// [Object::bit_xor](crate::runtime::Object::bit_xor) operation.
710///
711/// The trait must be implemented for the
712/// [registered type](crate::runtime::ScriptType), and the implementation must
713/// be exported using the [export](crate::export) macro. For more details, see
714/// the [module documentation](crate::runtime::ops).
715pub trait ScriptBitXor {
716 /// A rough estimation of the type of the right-hand side of the operation.
717 ///
718 /// This type must implement [ScriptType](crate::runtime::ScriptType).
719 type RHS: ?Sized;
720
721 /// A rough estimation of the result type of this operation.
722 ///
723 /// This type must implement [ScriptType](crate::runtime::ScriptType).
724 type Result: ?Sized;
725
726 /// Operation implementation.
727 ///
728 /// The parameters and return type of this function correspond to those of
729 /// the [Object::bit_xor](crate::runtime::Object::bit_xor) function.
730 fn script_bit_xor(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
731}
732
733/// A script bitwise exclusive disjunction and assignment operator:
734/// `lhs ^= rhs`.
735///
736/// Implementing this trait enables the
737/// [Object::bit_xor_assign](crate::runtime::Object::bit_xor_assign) operation.
738///
739/// The trait must be implemented for the
740/// [registered type](crate::runtime::ScriptType), and the implementation must
741/// be exported using the [export](crate::export) macro. For more details, see
742/// the [module documentation](crate::runtime::ops).
743pub trait ScriptBitXorAssign {
744 /// A rough estimation of the type of the right-hand side of the operation.
745 ///
746 /// This type must implement [ScriptType](crate::runtime::ScriptType).
747 type RHS: ?Sized;
748
749 /// Operation implementation.
750 ///
751 /// The parameters and return type of this function correspond to those of
752 /// the [Object::bit_xor_assign](crate::runtime::Object::bit_xor_assign)
753 /// function.
754 fn script_bit_xor_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
755}
756
757/// A script bitwise left shift operator: `lhs << rhs`.
758///
759/// Implementing this trait enables the
760/// [Object::shl](crate::runtime::Object::shl) operation.
761///
762/// The trait must be implemented for the
763/// [registered type](crate::runtime::ScriptType), and the implementation must
764/// be exported using the [export](crate::export) macro. For more details, see
765/// the [module documentation](crate::runtime::ops).
766pub trait ScriptShl {
767 /// A rough estimation of the type of the right-hand side of the operation.
768 ///
769 /// This type must implement [ScriptType](crate::runtime::ScriptType).
770 type RHS: ?Sized;
771
772 /// A rough estimation of the result type of this operation.
773 ///
774 /// This type must implement [ScriptType](crate::runtime::ScriptType).
775 type Result: ?Sized;
776
777 /// Operation implementation.
778 ///
779 /// The parameters and return type of this function correspond to those of
780 /// the [Object::shl](crate::runtime::Object::shl) function.
781 fn script_shl(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
782}
783
784/// A script bitwise left shift and assignment operator: `lhs <<= rhs`.
785///
786/// Implementing this trait enables the
787/// [Object::shl_assign](crate::runtime::Object::shl_assign) operation.
788///
789/// The trait must be implemented for the
790/// [registered type](crate::runtime::ScriptType), and the implementation must
791/// be exported using the [export](crate::export) macro. For more details, see
792/// the [module documentation](crate::runtime::ops).
793pub trait ScriptShlAssign {
794 /// A rough estimation of the type of the right-hand side of the operation.
795 ///
796 /// This type must implement [ScriptType](crate::runtime::ScriptType).
797 type RHS: ?Sized;
798
799 /// Operation implementation.
800 ///
801 /// The parameters and return type of this function correspond to those of
802 /// the [Object::shl_assign](crate::runtime::Object::shl_assign) function.
803 fn script_shl_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
804}
805
806/// A script bitwise right shift operator: `lhs >> rhs`.
807///
808/// Implementing this trait enables the
809/// [Object::shr](crate::runtime::Object::shr) operation.
810///
811/// The trait must be implemented for the
812/// [registered type](crate::runtime::ScriptType), and the implementation must
813/// be exported using the [export](crate::export) macro. For more details, see
814/// the [module documentation](crate::runtime::ops).
815pub trait ScriptShr {
816 /// A rough estimation of the type of the right-hand side of the operation.
817 ///
818 /// This type must implement [ScriptType](crate::runtime::ScriptType).
819 type RHS: ?Sized;
820
821 /// A rough estimation of the result type of this operation.
822 ///
823 /// This type must implement [ScriptType](crate::runtime::ScriptType).
824 type Result: ?Sized;
825
826 /// Operation implementation.
827 ///
828 /// The parameters and return type of this function correspond to those of
829 /// the [Object::shr](crate::runtime::Object::shr) function.
830 fn script_shr(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
831}
832
833/// A script bitwise right shift and assignment operator: `lhs >>= rhs`.
834///
835/// Implementing this trait enables the
836/// [Object::shr_assign](crate::runtime::Object::shr_assign) operation.
837///
838/// The trait must be implemented for the
839/// [registered type](crate::runtime::ScriptType), and the implementation must
840/// be exported using the [export](crate::export) macro. For more details, see
841/// the [module documentation](crate::runtime::ops).
842pub trait ScriptShrAssign {
843 /// A rough estimation of the type of the right-hand side of the operation.
844 ///
845 /// This type must implement [ScriptType](crate::runtime::ScriptType).
846 type RHS: ?Sized;
847
848 /// Operation implementation.
849 ///
850 /// The parameters and return type of this function correspond to those of
851 /// the [Object::shr_assign](crate::runtime::Object::shr_assign) function.
852 fn script_shr_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
853}
854
855/// A script reminder of division operator: `lhs % rhs`.
856///
857/// Implementing this trait enables the
858/// [Object::rem](crate::runtime::Object::rem) operation.
859///
860/// The trait must be implemented for the
861/// [registered type](crate::runtime::ScriptType), and the implementation must
862/// be exported using the [export](crate::export) macro. For more details, see
863/// the [module documentation](crate::runtime::ops).
864pub trait ScriptRem {
865 /// A rough estimation of the type of the right-hand side of the operation.
866 ///
867 /// This type must implement [ScriptType](crate::runtime::ScriptType).
868 type RHS: ?Sized;
869
870 /// A rough estimation of the result type of this operation.
871 ///
872 /// This type must implement [ScriptType](crate::runtime::ScriptType).
873 type Result: ?Sized;
874
875 /// Operation implementation.
876 ///
877 /// The parameters and return type of this function correspond to those of
878 /// the [Object::rem](crate::runtime::Object::rem) function.
879 fn script_rem(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<Cell>;
880}
881
882/// A script reminder of division and assignment operator: `lhs %= rhs`.
883///
884/// Implementing this trait enables the
885/// [Object::rem_assign](crate::runtime::Object::rem_assign) operation.
886///
887/// The trait must be implemented for the
888/// [registered type](crate::runtime::ScriptType), and the implementation must
889/// be exported using the [export](crate::export) macro. For more details, see
890/// the [module documentation](crate::runtime::ops).
891pub trait ScriptRemAssign {
892 /// A rough estimation of the type of the right-hand side of the operation.
893 ///
894 /// This type must implement [ScriptType](crate::runtime::ScriptType).
895 type RHS: ?Sized;
896
897 /// Operation implementation.
898 ///
899 /// The parameters and return type of this function correspond to those of
900 /// the [Object::rem_assign](crate::runtime::Object::rem_assign) function.
901 fn script_rem_assign(origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()>;
902}
903
904/// A marker trait indicating that the underlying type represents void data.
905///
906/// When this trait is implemented for a script type, the
907/// [Prototype::implements_none](crate::runtime::Prototype::implements_none)
908/// function will return `true`.
909///
910/// The trait must be implemented for the
911/// [registered type](crate::runtime::ScriptType), and the implementation must
912/// be exported using the [export](crate::export) macro. For more details, see
913/// the [module documentation](crate::runtime::ops).
914pub trait ScriptNone {}
915
916/// A type of the script operator.
917#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
918#[non_exhaustive]
919pub enum OperatorKind {
920 /// An assignment operator: `lhs = rhs`.
921 Assign,
922
923 /// An array constructor: `[a, b, c]`.
924 Concat,
925
926 /// A field access operator: `foo.bar`.
927 Field,
928
929 /// A cloning operator: `*foo`.
930 Clone,
931
932 /// A [Debug] formatting operator.
933 Debug,
934
935 /// A [Display] formatting operator.
936 Display,
937
938 /// An equality operator: `lhs == rhs`.
939 PartialEq,
940
941 /// An object's default constructor.
942 Default,
943
944 /// A partial ordering operator: `lhs >= rhs`, `lhs < rhs`, etc.
945 PartialOrd,
946
947 /// A full ordering operator: `lhs >= rhs`, `lhs < rhs`, etc.
948 Ord,
949
950 /// A data [Hash] operator.
951 Hash,
952
953 /// An invocation operator: `foo(arg1, arg2, arg3)`.
954 Invocation,
955
956 /// A context binding operator.
957 Binding,
958
959 /// An addition operator: `lhs + rhs`.
960 Add,
961
962 /// An addition and assignment operator: `lhs += rhs`.
963 AddAssign,
964
965 /// An subtraction operator: `lhs - rhs`.
966 Sub,
967
968 /// An subtraction and assignment operator: `lhs -= rhs`.
969 SubAssign,
970
971 /// A multiplication operator: `lhs * rhs`.
972 Mul,
973
974 /// A multiplication and assignment operator: `lhs *= rhs`.
975 MulAssign,
976
977 /// A division operator: `lhs / rhs`.
978 Div,
979
980 /// A division and assignment operator: `lhs /= rhs`.
981 DivAssign,
982
983 /// A logical conjunction operator: `lhs && rhs`.
984 And,
985
986 /// A logical disjunction operator: `lhs || rhs`.
987 Or,
988
989 /// A logical negation operator: `!foo`.
990 Not,
991
992 /// A numeric negation operator: `-foo`.
993 Neg,
994
995 /// A bitwise conjunction operator: `lhs & rhs`.
996 BitAnd,
997
998 /// A bitwise conjunction and assignment operator: `lhs &= rhs`.
999 BitAndAssign,
1000
1001 /// A bitwise disjunction operator: `lhs | rhs`.
1002 BitOr,
1003
1004 /// A bitwise disjunction and assignment operator: `lhs |= rhs`.
1005 BitOrAssign,
1006
1007 /// A bitwise exclusive disjunction operator: `lhs ^ rhs`.
1008 BitXor,
1009
1010 /// A bitwise exclusive disjunction and assignment operator: `lhs ^= rhs`.
1011 BitXorAssign,
1012
1013 /// A bitwise left shift operator: `lhs << rhs`.
1014 Shl,
1015
1016 /// A bitwise left shift and assignment operator: `lhs <<= rhs`.
1017 ShlAssign,
1018
1019 /// A bitwise right shift operator: `lhs >> rhs`.
1020 Shr,
1021
1022 /// A bitwise right shift and assignment operator: `lhs >>= rhs`.
1023 ShrAssign,
1024
1025 /// A reminder of division operator: `lhs % rhs`.
1026 Rem,
1027
1028 /// A reminder of division and assignment operator: `lhs %= rhs`.
1029 RemAssign,
1030}
1031
1032impl Display for OperatorKind {
1033 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
1034 match self {
1035 Self::Assign => formatter.write_str("= operator"),
1036 Self::Concat => formatter.write_str("[] operator"),
1037 Self::Field => formatter.write_str("field access operator"),
1038 Self::Clone => formatter.write_str("clone operator"),
1039 Self::Debug => formatter.write_str("debug operator"),
1040 Self::Display => formatter.write_str("display operator"),
1041 Self::PartialEq => formatter.write_str("== operator"),
1042 Self::Default => formatter.write_str("default constructor"),
1043 Self::PartialOrd => formatter.write_str("ordering"),
1044 Self::Ord => formatter.write_str("ordering"),
1045 Self::Hash => formatter.write_str("hash interface"),
1046 Self::Invocation => formatter.write_str("invocation"),
1047 Self::Binding => formatter.write_str("binding"),
1048 Self::Add => formatter.write_str("+ operator"),
1049 Self::AddAssign => formatter.write_str("+= operator"),
1050 Self::Sub => formatter.write_str("- operator"),
1051 Self::SubAssign => formatter.write_str("-= operator"),
1052 Self::Mul => formatter.write_str("* operator"),
1053 Self::MulAssign => formatter.write_str("*= operator"),
1054 Self::Div => formatter.write_str("/ operator"),
1055 Self::DivAssign => formatter.write_str("/= operator"),
1056 Self::And => formatter.write_str("&& operator"),
1057 Self::Or => formatter.write_str("|| operator"),
1058 Self::Not => formatter.write_str("! operator"),
1059 Self::Neg => formatter.write_str("negative - operator"),
1060 Self::BitAnd => formatter.write_str("& operator"),
1061 Self::BitAndAssign => formatter.write_str("&= operator"),
1062 Self::BitOr => formatter.write_str("| operator"),
1063 Self::BitOrAssign => formatter.write_str("|= operator"),
1064 Self::BitXor => formatter.write_str("^ operator"),
1065 Self::BitXorAssign => formatter.write_str("^= operator"),
1066 Self::Shl => formatter.write_str("<< operator"),
1067 Self::ShlAssign => formatter.write_str("<<= operator"),
1068 Self::Shr => formatter.write_str(">> operator"),
1069 Self::ShrAssign => formatter.write_str(">>= operator"),
1070 Self::Rem => formatter.write_str("% operator"),
1071 Self::RemAssign => formatter.write_str("%= operator"),
1072 }
1073 }
1074}
1075
1076mod types {
1077 use std::marker::PhantomData;
1078
1079 use crate::{
1080 export,
1081 runtime::{
1082 Arg,
1083 Cell,
1084 Downcast,
1085 Origin,
1086 Provider,
1087 RuntimeResult,
1088 ScriptType,
1089 TypeHint,
1090 Upcast,
1091 },
1092 };
1093
1094 /// A type that cannot be inferred during static semantic analysis.
1095 ///
1096 /// Normally, you should not instantiate or use this object in
1097 /// implementations, but you can use this type as a hint for the analyzer
1098 /// when the implementation nature is fully dynamic.
1099 ///
1100 /// ```
1101 /// # use ad_astra::{
1102 /// # export,
1103 /// # runtime::{
1104 /// # ops::{DynamicType, ScriptAssign},
1105 /// # Arg,
1106 /// # Origin,
1107 /// # RuntimeResult,
1108 /// # },
1109 /// # };
1110 /// #
1111 /// struct Foo;
1112 ///
1113 /// #[export]
1114 /// type FooAlias = Foo;
1115 ///
1116 /// #[export]
1117 /// impl ScriptAssign for Foo {
1118 /// // `type RHS = Foo;` would be more preferable in this case.
1119 /// type RHS = DynamicType;
1120 ///
1121 /// fn script_assign(_origin: Origin, lhs: Arg, rhs: Arg) -> RuntimeResult<()> {
1122 /// let rhs = rhs.data.take::<Foo>(rhs.origin)?;
1123 ///
1124 /// let (lhs_origin, mut lhs_cell) = lhs.split();
1125 ///
1126 /// let lhs = lhs_cell.borrow_mut::<Foo>(lhs_origin)?;
1127 ///
1128 /// *lhs = rhs;
1129 ///
1130 /// Ok(())
1131 /// }
1132 /// }
1133 /// ```
1134 ///
1135 /// Generally, it is recommended to use this type as sparingly as possible,
1136 /// preferring more specific types even if they provide an imprecise
1137 /// description.
1138 ///
1139 /// If you need more control over the exported function's arguments and
1140 /// result type casting, consider using [DynamicArgument] and
1141 /// [DynamicReturn] wrappers instead.
1142 pub struct DynamicType;
1143
1144 /// Unknown type.
1145 ///
1146 /// This type cannot be inferred statically.
1147 #[export(include)]
1148 #[export(name "?")]
1149 type DynamicTypeExport = DynamicType;
1150
1151 /// A type of a function's parameter that may have a more dynamic casting
1152 /// nature than usual.
1153 ///
1154 /// The analyzer will assume that the argument's type belongs to the
1155 /// [type family](crate::runtime::TypeFamily) of the `T` type, but the
1156 /// Script Engine will not automatically [downcast](Downcast) the script's
1157 /// argument, allowing the implementation to manually cast the argument's
1158 /// [Cell].
1159 ///
1160 /// ```
1161 /// # use ad_astra::{
1162 /// # export,
1163 /// # runtime::{ops::DynamicArgument, Downcast, Provider, RuntimeResult},
1164 /// # };
1165 /// #
1166 /// #[export]
1167 /// fn plus_10(mut arg: DynamicArgument<usize>) -> RuntimeResult<usize> {
1168 /// let mut arg_ty = arg.data.type_match();
1169 ///
1170 /// if arg_ty.belongs_to::<usize>() {
1171 /// let arg = <usize>::downcast(arg.origin, Provider::Borrowed(&mut arg.data))?;
1172 ///
1173 /// return Ok(arg + 10);
1174 /// }
1175 ///
1176 /// if arg_ty.is::<str>() {
1177 /// let arg = arg.data.borrow_str(arg.origin)?;
1178 ///
1179 /// return Ok(arg.len() + 10);
1180 /// }
1181 ///
1182 /// Err(arg_ty.mismatch(arg.origin))
1183 /// }
1184 /// ```
1185 pub struct DynamicArgument<T> {
1186 /// A Rust or Script source code range where the argument has been
1187 /// provided.
1188 pub origin: Origin,
1189
1190 /// The actual data of the argument.
1191 pub data: Cell,
1192
1193 phantom: PhantomData<T>,
1194 }
1195
1196 impl<T> DynamicArgument<T> {
1197 /// A helper function that converts this instance into an operator's
1198 /// [argument](Arg).
1199 #[inline(always)]
1200 pub fn into_argument(self) -> Arg {
1201 Arg {
1202 origin: self.origin,
1203 data: self.data,
1204 }
1205 }
1206 }
1207
1208 impl<'a, T: ScriptType> Downcast<'a> for DynamicArgument<T> {
1209 #[inline(always)]
1210 fn downcast(origin: Origin, provider: Provider<'a>) -> RuntimeResult<Self> {
1211 Ok(DynamicArgument {
1212 origin,
1213 data: provider.to_owned(),
1214 phantom: PhantomData,
1215 })
1216 }
1217
1218 #[inline(always)]
1219 fn hint() -> TypeHint {
1220 TypeHint::Type(T::type_meta())
1221 }
1222 }
1223
1224 /// A type for a function's return value that may have a more dynamic
1225 /// casting nature than usual.
1226 ///
1227 /// The analyzer will assume that the return type belongs to the
1228 /// [type family](crate::runtime::TypeFamily) of the `T` type, but the
1229 /// Script Engine will not automatically [upcast](Upcast) the Rust value,
1230 /// allowing the implementation to manually cast the result into a [Cell].
1231 ///
1232 /// ```
1233 /// # use ad_astra::{
1234 /// # export,
1235 /// # runtime::{ops::DynamicReturn, Cell, Origin, RuntimeResult},
1236 /// # };
1237 /// #
1238 /// #[export]
1239 /// fn string_or_number(is_string: bool) -> RuntimeResult<DynamicReturn<usize>> {
1240 /// match is_string {
1241 /// true => Ok(DynamicReturn::new(Cell::give(Origin::nil(), "string")?)),
1242 /// false => Ok(DynamicReturn::new(Cell::give(Origin::nil(), 100usize)?)),
1243 /// }
1244 /// }
1245 /// ```
1246 #[repr(transparent)]
1247 pub struct DynamicReturn<T> {
1248 /// The underlying return object.
1249 pub data: Cell,
1250 phantom: PhantomData<T>,
1251 }
1252
1253 impl<T> DynamicReturn<T> {
1254 /// A constructor that wraps the provided `data` [Cell] into a
1255 /// DynamicReturn.
1256 #[inline(always)]
1257 pub fn new(data: Cell) -> Self {
1258 DynamicReturn {
1259 data,
1260 phantom: PhantomData,
1261 }
1262 }
1263 }
1264
1265 impl<'a, T: ScriptType> Upcast<'a> for DynamicReturn<T> {
1266 type Output = Cell;
1267
1268 #[inline(always)]
1269 fn upcast(_origin: Origin, this: Self) -> RuntimeResult<Self::Output> {
1270 Ok(this.data)
1271 }
1272
1273 #[inline(always)]
1274 fn hint() -> TypeHint {
1275 TypeHint::Type(T::type_meta())
1276 }
1277 }
1278}
1279
1280mod functions {
1281 use lady_deirdre::sync::Lazy;
1282
1283 use crate::{
1284 export,
1285 report::system_panic,
1286 runtime::{
1287 ops::{OperatorKind, ScriptConcat, ScriptInvocation},
1288 ty::ScriptType,
1289 Arg,
1290 Cell,
1291 Downcast,
1292 InvocationMeta,
1293 Origin,
1294 Param,
1295 Provider,
1296 RuntimeError,
1297 RuntimeResult,
1298 TypeHint,
1299 Upcast,
1300 },
1301 };
1302
1303 #[repr(transparent)]
1304 pub struct FnRepr<const ARGS: usize, F: ?Sized> {
1305 callable: Box<F>,
1306 }
1307
1308 macro_rules! impl_fn {
1309 (
1310 $(#[doc = $fn_doc:expr])*
1311 $fn_ty:ident;
1312 $fn_repr_ty:ident [$arity:expr] as $name:expr => $($arg:ident: $index:expr),*;
1313 ) => {
1314 $(#[doc = $fn_doc])*
1315 pub type $fn_ty<$($arg, )* R> = Box<dyn Fn($($arg),*) -> RuntimeResult<R> + Send + Sync + 'static>;
1316
1317 $(#[doc = $fn_doc])*
1318 #[export(include)]
1319 #[export(name $name)]
1320 #[export(family &crate::runtime::__intrinsics::FUNCTION_FAMILY)]
1321 pub(crate) type $fn_repr_ty = FnRepr<
1322 0,
1323 dyn Fn(Origin, &mut [Arg; $arity]) -> RuntimeResult<Cell> + Send + Sync + 'static,
1324 >;
1325
1326 impl<'a $(, $arg)*, R> Downcast<'a> for $fn_ty<$($arg, )* R>
1327 where
1328 $(
1329 $arg: Upcast<'static>,
1330 )*
1331 R: Downcast<'static>,
1332 {
1333 #[inline]
1334 fn downcast(downcast_origin: Origin, provider: Provider<'a>) -> RuntimeResult<Self> {
1335 let cell = provider.to_owned();
1336 let ty = cell.ty();
1337
1338 if !ty.prototype().implements_invocation() {
1339 return Err(RuntimeError::UndefinedOperator {
1340 access_origin: downcast_origin,
1341 receiver_origin: Some(cell.origin()),
1342 receiver_type: ty,
1343 operator: OperatorKind::Invocation,
1344 });
1345 }
1346
1347 Ok(Box::new(move |$(#[allow(non_snake_case)] $arg: $arg),*| {
1348 let object = cell.clone().into_object();
1349
1350 let mut arguments: [Arg; $arity] = [
1351 $(Arg {
1352 origin: downcast_origin,
1353 data: Cell::give(downcast_origin, $arg)?
1354 }),*
1355 ];
1356
1357 let result = object.invoke(
1358 downcast_origin,
1359 downcast_origin,
1360 &mut arguments,
1361 )?;
1362
1363 <R as Downcast<'static>>::downcast(
1364 downcast_origin,
1365 Provider::Owned(result),
1366 )
1367 }))
1368 }
1369
1370 #[inline(always)]
1371 fn hint() -> TypeHint {
1372 TypeHint::Type(<$fn_repr_ty>::type_meta())
1373 }
1374 }
1375
1376 impl<'a $(, $arg)*, R> Upcast<'a> for $fn_ty<$($arg, )* R>
1377 where
1378 $($arg: Downcast<'static>,)*
1379 R: Upcast<'static>,
1380 {
1381 type Output = Box<$fn_repr_ty>;
1382
1383 #[inline]
1384 fn upcast(_origin: Origin, this: Self) -> RuntimeResult<Self::Output> {
1385 Ok(Box::new($fn_repr_ty {
1386 callable: Box::new(
1387 move |
1388 origin: Origin,
1389 #[allow(unused)] arguments: &mut [Arg; $arity],
1390 | {
1391 $(
1392 // Safety: Index is lesser than array length.
1393 #[allow(non_snake_case)]
1394 let $arg = unsafe {
1395 Arg::take_unchecked(arguments, $index)
1396 };
1397 #[allow(non_snake_case)]
1398 let $arg = <$arg as Downcast<'static>>::downcast(
1399 $arg.origin,
1400 $arg.into_provider(),
1401 )?;
1402 )*
1403
1404 let result = this($($arg),*)?;
1405
1406 Cell::give(origin, result)
1407 },
1408 ),
1409 }))
1410 }
1411
1412 #[inline(always)]
1413 fn hint() -> TypeHint {
1414 TypeHint::Type(<$fn_repr_ty>::type_meta())
1415 }
1416 }
1417
1418 #[export(include)]
1419 impl ScriptConcat for $fn_repr_ty {
1420 type Result = Self;
1421
1422 fn script_concat(origin: Origin, items: &mut [Arg]) -> RuntimeResult<Cell> {
1423 $crate::runtime::__intrinsics::canonicals::script_concat::<Self>(origin, items)
1424 }
1425 }
1426
1427 #[export(include)]
1428 impl ScriptInvocation for $fn_repr_ty {
1429 fn invoke(origin: Origin, lhs: Arg, arguments: &mut [Arg]) -> RuntimeResult<Cell> {
1430 let function = lhs.data.take::<Self>(origin)?;
1431
1432 let arguments_count = arguments.len();
1433
1434 if arguments_count != $arity {
1435 return Err(RuntimeError::ArityMismatch {
1436 invocation_origin: origin,
1437 function_origin: Origin::default(),
1438 parameters: $arity,
1439 arguments: arguments_count,
1440 });
1441 }
1442
1443 let arguments = match arguments.try_into() {
1444 Ok(array) => array,
1445
1446 Err(_) => {
1447 system_panic!("Argument slice to array casting failure.")
1448 }
1449 };
1450
1451 (function.callable)(origin, arguments)
1452 }
1453
1454 fn hint() -> Option<&'static InvocationMeta> {
1455 static META: Lazy<InvocationMeta> = Lazy::new(|| {
1456 InvocationMeta {
1457 origin: Origin::default(),
1458 name: None,
1459 doc: Some(concat!($($fn_doc),*)),
1460 receiver: None,
1461 inputs: Some(vec![
1462 $(
1463 Param {
1464 name: {
1465 #[allow(unused)]
1466 #[allow(non_snake_case)]
1467 let $arg = ();
1468 None
1469 },
1470 hint: TypeHint::dynamic(),
1471 },
1472 )*
1473 ]),
1474 output: TypeHint::dynamic(),
1475 }
1476 });
1477
1478 Some(&META)
1479 }
1480 }
1481 };
1482 }
1483
1484 impl_fn!(
1485 /// A function with 0 arguments.
1486 Fn0;
1487 Fn0Repr[0] as "fn(0)" =>;
1488 );
1489
1490 impl_fn!(
1491 /// A function with 1 argument.
1492 Fn1;
1493 Fn1Repr[1] as "fn(1)" => A: 0;
1494 );
1495
1496 impl_fn!(
1497 /// A function with 2 arguments.
1498 Fn2;
1499 Fn2Repr[2] as "fn(2)" => A: 0, B: 1;
1500 );
1501
1502 impl_fn!(
1503 /// A function with 3 arguments.
1504 Fn3;
1505 Fn3Repr[3] as "fn(3)" => A: 0, B: 1, C: 2;
1506 );
1507
1508 impl_fn!(
1509 /// A function with 4 arguments.
1510 Fn4;
1511 Fn4Repr[4] as "fn(4)" => A: 0, B: 1, C: 2, D: 3;
1512 );
1513
1514 impl_fn!(
1515 /// A function with 5 arguments.
1516 Fn5;
1517 Fn5Repr[5] as "fn(5)" => A: 0, B: 1, C: 2, D: 3, E: 4;
1518 );
1519
1520 impl_fn!(
1521 /// A function with 6 arguments.
1522 Fn6;
1523 Fn6Repr[6] as "fn(6)" => A: 0, B: 1, C: 2, D: 3, E: 4, F: 5;
1524 );
1525
1526 impl_fn!(
1527 /// A function with 7 arguments.
1528 Fn7;
1529 Fn7Repr[7] as "fn(7)" => A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6;
1530 );
1531}