1use txtx_addon_kit::types::AuthorizationContext;
2use txtx_addon_kit::{
3 define_function, indoc,
4 types::{
5 diagnostics::Diagnostic,
6 functions::{FunctionImplementation, FunctionSpecification},
7 types::{Type, Value},
8 },
9};
10
11use super::arg_checker;
12
13lazy_static! {
14 pub static ref OPERATORS_FUNCTIONS: Vec<FunctionSpecification> = vec![
15 define_function! {
16 BinaryAndBool => {
17 name: "and_bool",
18 documentation: "`and_bool` returns the binary AND of the left- and right-hand-side arguments.",
19 example: indoc!{r#"
20 output "my_bool" {
21 value = false && true
22 }
23 // > my_bool: false
24 "#},
25 inputs: [
26 lhs: {
27 documentation: "A `boolean` value.",
28 typing: vec![Type::bool()]
29 },
30 rhs: {
31 documentation: "A `boolean` value.",
32 typing: vec![Type::bool()]
33 }
34 ],
35 output: {
36 documentation: "The result of a binary AND between the two arguments.",
37 typing: Type::bool()
38 },
39 }
40 },
41 define_function! {
42 BinaryOrBool => {
43 name: "or_bool",
44 documentation: "`or_bool` returns the binary OR of the left- and right-hand-side arguments.",
45 example: indoc!{r#"
46 output "my_bool" {
47 value = false || true
48 }
49 // > my_bool: true
50 "#},
51 inputs: [
52 lhs: {
53 documentation: "A `boolean` value.",
54 typing: vec![Type::bool()]
55 },
56 rhs: {
57 documentation: "A `boolean` value.",
58 typing: vec![Type::bool()]
59 }
60 ],
61 output: {
62 documentation: "The result of a binary OR between the two arguments.",
63 typing: Type::bool()
64 },
65 }
66 },
67 define_function! {
68 BinaryDivSignedInteger => {
69 name: "div",
70 documentation: "`div` returns the integer division of the left-hand-side argument by the right-hand-side argument, rounding any remainder down to the nearest integer.",
71 example: indoc!{r#"
72 output "my_int" {
73 value = 11 / -3
74 }
75 // > my_int: -3
76 "#},
77 inputs: [
78 lhs: {
79 documentation: "The `int` dividend.",
80 typing: vec![Type::integer()]
81 },
82 rhs: {
83 documentation: "The `int` divisor.",
84 typing: vec![Type::integer()]
85 }
86 ],
87 output: {
88 documentation: "The result of dividing the dividend by the divisor.",
89 typing: Type::integer()
90 },
91 }
92 },
93 define_function! {
94 BinaryEq => {
95 name: "eq",
96 documentation: "`eq` returns `true` if the left- and right-hand-side arguments are equal and `false` if they are not.",
97 example: indoc!{r#"
98 output "is_eq" {
99 value = "arg" == "arg"
100 }
101 // > is_eq: true
102 "#},
103 inputs: [
104 lhs: {
105 documentation: "Any value.",
106 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool(), Type::addon(""), Type::array(Type::null()), Type::arbitrary_object()]
107 },
108 rhs: {
109 documentation: "Any value.",
110 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool(), Type::addon(""), Type::array(Type::null()), Type::arbitrary_object()]
111 }
112 ],
113 output: {
114 documentation: "The result of an equality check between the two inputs.",
115 typing: Type::bool()
116 },
117 }
118 },
119 define_function! {
120 BinaryGreater => {
121 name: "gt",
122 documentation: "`gt` returns `true` if the left-hand-side argument is greater than the right-hand-side argument and `false` if it is not.",
123 example: indoc!{r#"
124 output "is_gt" {
125 value = 2 > 1
126 }
127 // > is_gt: true
128 "#},
129 inputs: [
130 lhs: {
131 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
132 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
133 },
134 rhs: {
135 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
136 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
137 }
138 ],
139 output: {
140 documentation: "The result of checking if the left-hand-side argument is greater than the right-hand-side argument",
141 typing: Type::bool()
142 },
143 }
144 },
145 define_function! {
146 BinaryGreaterEq => {
147 name: "gte",
148 documentation: "`gte` returns `true` if the left-hand-side argument is greater than or equal to the right-hand-side argument and `false` if it is not.",
149 example: indoc!{r#"
150 output "is_gte" {
151 value = 2 >= 2
152 }
153 // > is_gte: true
154 "#},
155 inputs: [
156 lhs: {
157 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
158 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
159 },
160 rhs: {
161 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
162 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
163 }
164 ],
165 output: {
166 documentation: "The result of checking if the left-hand-side argument is greater than or equal to the right-hand-side argument",
167 typing: Type::bool()
168 },
169 }
170 },
171 define_function! {
172 BinaryLess => {
173 name: "lt",
174 documentation: "`lt` returns `true` if the left-hand-side argument is less than the right-hand-side argument and `false` if it is not.",
175 example: indoc!{r#"
176 output "is_lt" {
177 value = 2 < 1
178 }
179 // > is_lt: false
180 "#},
181 inputs: [
182 lhs: {
183 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
184 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
185 },
186 rhs: {
187 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
188 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
189 }
190 ],
191 output: {
192 documentation: "The result of checking if the left-hand-side argument is less than the right-hand-side argument",
193 typing: Type::bool()
194 },
195 }
196 },
197 define_function! {
198 BinaryLessEq => {
199 name: "lte",
200 documentation: "`lte` returns `true` if the left-hand-side argument is less than or equal to the right-hand-side argument and `false` if it is not.",
201 example: indoc!{r#"
202 output "is_lte" {
203 value = 2 <= 2
204 }
205 // > is_lte: true
206 "#},
207 inputs: [
208 lhs: {
209 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
210 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
211 },
212 rhs: {
213 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
214 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
215 }
216 ],
217 output: {
218 documentation: "The result of checking if the left-hand-side argument is less than or equal to the right-hand-side argument",
219 typing: Type::bool()
220 },
221 }
222 },
223 define_function! {
224 BinaryNotEq => {
225 name: "neq",
226 documentation: "`enq` returns `true` if the left- and right-hand-side arguments are not equal and `false` otherwise.",
227 example: indoc!{r#"
228 output "is_neq" {
229 value = "arg" != "arg"
230 }
231 // > is_neq: false
232 "#},
233 inputs: [
234 lhs: {
235 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
236 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
237 },
238 rhs: {
239 documentation: "An `integer`, `float`, `string`, `boolean` or `null` value.",
240 typing: vec![Type::null(), Type::integer(), Type::float(), Type::integer(), Type::string(), Type::bool()]
241 }
242 ],
243 output: {
244 documentation: "The result of a negated equality check between the two inputs.",
245 typing: Type::bool()
246 },
247 }
248 },
249 define_function! {
250 BinaryMinus => {
251 name: "minus",
252 documentation: "`minus` returns the result of subtracting the right-hand-side `integer` argument from the left-hand-side `integer` argument.",
253 example: indoc!{r#"
254 output "my_integer" {
255 value = 10 - 6
256 }
257 // > my_integer: 4
258 "#},
259 inputs: [
260 lhs: {
261 documentation: "The `integer` minuend.",
262 typing: vec![Type::integer()]
263 },
264 rhs: {
265 documentation: "The `integer` subtrahend.",
266 typing: vec![Type::integer()]
267 }
268 ],
269 output: {
270 documentation: "The result of the subtraction operation.",
271 typing: Type::integer()
272 },
273 }
274 },
275 define_function! {
276 BinaryModulo => {
277 name: "modulo",
278 documentation: "`modulo` returns the remainder of dividing the left-hand-side `integer` argument by the right-hand-side `integer` argument.",
279 example: indoc!{r#"
280 output "my_mod" {
281 value = 10 % 3
282 }
283 // > my_mod: 1
284 "#},
285 inputs: [
286 lhs: {
287 documentation: "The `integer` dividend.",
288 typing: vec![Type::integer()]
289 },
290 rhs: {
291 documentation: "The `integer` divisor.",
292 typing: vec![Type::integer()]
293 }
294 ],
295 output: {
296 documentation: "The remainder of the division operation.",
297 typing: Type::integer()
298 },
299 }
300 },
301 define_function! {
302 BinaryMul => {
303 name: "multiply",
304 documentation: "`multiply` returns the product of the left-hand-side `integer` argument and the right-hand-side `integer` argument.",
305 example: indoc!{r#"
306 output "my_product" {
307 value = 10 * 5
308 }
309 // > my_product: 50
310 "#},
311 inputs: [
312 lhs: {
313 documentation: "The first `integer` operand.",
314 typing: vec![Type::integer()],
315 optional: false
316 },
317 rhs: {
318 documentation: "The second `integer` operand.",
319 typing: vec![Type::integer()],
320 optional: false
321 }
322 ],
323 output: {
324 documentation: "The result of the multiplication operation.",
325 typing: Type::integer()
326 },
327 }
328 },
329 define_function! {
330 BinaryPlus => {
331 name: "add",
332 documentation: "`add` returns the sum of the left-hand-side `integer` argument and the right-hand-side `integer` argument.",
333 example: indoc!{r#"
334 output "my_sum" {
335 value = 10 + 5
336 }
337 // > my_sum: 15
338 "#},
339 inputs: [
340 lhs: {
341 documentation: "The first `integer` operand.",
342 typing: vec![Type::integer()]
343 },
344 rhs: {
345 documentation: "The second `integer` operand.",
346 typing: vec![Type::integer()]
347 }
348 ],
349 output: {
350 documentation: "The result of the addition operation.",
351 typing: Type::integer()
352 },
353 }
354 },
355 define_function! {
356 UnaryNegInteger => {
357 name: "neg_integer",
358 documentation: "Returns the negation of the given integer.",
359 example: "// Coming soon",
360 inputs: [
361 value: {
362 documentation: "An integer value.",
363 typing: vec![Type::integer()]
364 }
365 ],
366 output: {
367 documentation: "The negated integer value.",
368 typing: Type::integer()
369 },
370 }
371 },
372 define_function! {
373 UnaryNotBool => {
374 name: "not_bool",
375 documentation: "Returns the logical negation of the given boolean value.",
376 example: "// Coming soon",
377 inputs: [
378 value: {
379 documentation: "A boolean value.",
380 typing: vec![Type::bool()]
381 }
382 ],
383 output: {
384 documentation: "The logical negation of the input boolean value.",
385 typing: Type::bool()
386 },
387 }
388 },
389 ];
390}
391
392pub struct UnaryNegInteger;
393impl FunctionImplementation for UnaryNegInteger {
394 fn check_instantiability(
395 _fn_spec: &FunctionSpecification,
396 _auth_ctx: &AuthorizationContext,
397 _args: &Vec<Type>,
398 ) -> Result<Type, Diagnostic> {
399 unimplemented!()
400 }
401
402 fn run(
403 _fn_spec: &FunctionSpecification,
404 _auth_ctx: &AuthorizationContext,
405 _args: &Vec<Value>,
406 ) -> Result<Value, Diagnostic> {
407 unimplemented!()
408 }
409}
410
411pub struct UnaryNotBool;
412impl FunctionImplementation for UnaryNotBool {
413 fn check_instantiability(
414 _fn_spec: &FunctionSpecification,
415 _auth_ctx: &AuthorizationContext,
416 _args: &Vec<Type>,
417 ) -> Result<Type, Diagnostic> {
418 unimplemented!()
419 }
420
421 fn run(
422 _fn_spec: &FunctionSpecification,
423 _auth_ctx: &AuthorizationContext,
424 _args: &Vec<Value>,
425 ) -> Result<Value, Diagnostic> {
426 unimplemented!()
427 }
428}
429
430pub struct BinaryAndBool;
431impl FunctionImplementation for BinaryAndBool {
432 fn check_instantiability(
433 _fn_spec: &FunctionSpecification,
434 _auth_ctx: &AuthorizationContext,
435 _args: &Vec<Type>,
436 ) -> Result<Type, Diagnostic> {
437 unimplemented!()
438 }
439
440 fn run(
441 _fn_spec: &FunctionSpecification,
442 _auth_ctx: &AuthorizationContext,
443 args: &Vec<Value>,
444 ) -> Result<Value, Diagnostic> {
445 let Some(Value::Bool(lhs)) = args.get(0) else { unreachable!() };
446 let Some(Value::Bool(rhs)) = args.get(1) else { unreachable!() };
447 Ok(Value::bool(*lhs && *rhs))
448 }
449}
450
451pub struct BinaryOrBool;
452impl FunctionImplementation for BinaryOrBool {
453 fn check_instantiability(
454 _fn_spec: &FunctionSpecification,
455 _auth_ctx: &AuthorizationContext,
456 _args: &Vec<Type>,
457 ) -> Result<Type, Diagnostic> {
458 unimplemented!()
459 }
460
461 fn run(
462 _fn_spec: &FunctionSpecification,
463 _auth_ctx: &AuthorizationContext,
464 args: &Vec<Value>,
465 ) -> Result<Value, Diagnostic> {
466 let Some(Value::Bool(lhs)) = args.get(0) else { unreachable!() };
467 let Some(Value::Bool(rhs)) = args.get(1) else { unreachable!() };
468 Ok(Value::bool(*lhs || *rhs))
469 }
470}
471
472pub struct BinaryDivSignedInteger;
473impl FunctionImplementation for BinaryDivSignedInteger {
474 fn check_instantiability(
475 _fn_spec: &FunctionSpecification,
476 _auth_ctx: &AuthorizationContext,
477 _args: &Vec<Type>,
478 ) -> Result<Type, Diagnostic> {
479 unimplemented!()
480 }
481
482 fn run(
483 _fn_spec: &FunctionSpecification,
484 _auth_ctx: &AuthorizationContext,
485 args: &Vec<Value>,
486 ) -> Result<Value, Diagnostic> {
487 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
488 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
489 if rhs.eq(&0) {
490 Err(Diagnostic::error_from_string("cannot divide by zero".to_string()))
491 } else {
492 Ok(Value::integer(lhs.saturating_div(*rhs)))
493 }
494 }
495}
496
497pub struct BinaryEq;
498impl FunctionImplementation for BinaryEq {
499 fn check_instantiability(
500 _fn_spec: &FunctionSpecification,
501 _auth_ctx: &AuthorizationContext,
502 _args: &Vec<Type>,
503 ) -> Result<Type, Diagnostic> {
504 unimplemented!()
505 }
506
507 fn run(
508 fn_spec: &FunctionSpecification,
509 _auth_ctx: &AuthorizationContext,
510 args: &Vec<Value>,
511 ) -> Result<Value, Diagnostic> {
512 arg_checker(fn_spec, args)?;
513 let lhs = args.get(0).unwrap();
514 let rhs = args.get(1).unwrap();
515 Ok(Value::bool(lhs.eq(rhs)))
516 }
517}
518
519pub struct BinaryGreater;
520impl FunctionImplementation for BinaryGreater {
521 fn check_instantiability(
522 _fn_spec: &FunctionSpecification,
523 _auth_ctx: &AuthorizationContext,
524 _args: &Vec<Type>,
525 ) -> Result<Type, Diagnostic> {
526 unimplemented!()
527 }
528
529 fn run(
530 _fn_spec: &FunctionSpecification,
531 _auth_ctx: &AuthorizationContext,
532 args: &Vec<Value>,
533 ) -> Result<Value, Diagnostic> {
534 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
535 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
536 Ok(Value::bool(lhs.gt(&rhs)))
537 }
538}
539
540pub struct BinaryGreaterEq;
541impl FunctionImplementation for BinaryGreaterEq {
542 fn check_instantiability(
543 _fn_spec: &FunctionSpecification,
544 _auth_ctx: &AuthorizationContext,
545 _args: &Vec<Type>,
546 ) -> Result<Type, Diagnostic> {
547 unimplemented!()
548 }
549
550 fn run(
551 _fn_spec: &FunctionSpecification,
552 _auth_ctx: &AuthorizationContext,
553 args: &Vec<Value>,
554 ) -> Result<Value, Diagnostic> {
555 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
556 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
557 Ok(Value::bool(lhs.ge(&rhs)))
558 }
559}
560
561pub struct BinaryLess;
562impl FunctionImplementation for BinaryLess {
563 fn check_instantiability(
564 _fn_spec: &FunctionSpecification,
565 _auth_ctx: &AuthorizationContext,
566 _args: &Vec<Type>,
567 ) -> Result<Type, Diagnostic> {
568 unimplemented!()
569 }
570
571 fn run(
572 _fn_spec: &FunctionSpecification,
573 _auth_ctx: &AuthorizationContext,
574 args: &Vec<Value>,
575 ) -> Result<Value, Diagnostic> {
576 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
577 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
578 Ok(Value::bool(lhs.lt(&rhs)))
579 }
580}
581
582pub struct BinaryLessEq;
583impl FunctionImplementation for BinaryLessEq {
584 fn check_instantiability(
585 _fn_spec: &FunctionSpecification,
586 _auth_ctx: &AuthorizationContext,
587 _args: &Vec<Type>,
588 ) -> Result<Type, Diagnostic> {
589 unimplemented!()
590 }
591
592 fn run(
593 _fn_spec: &FunctionSpecification,
594 _auth_ctx: &AuthorizationContext,
595 args: &Vec<Value>,
596 ) -> Result<Value, Diagnostic> {
597 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
598 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
599 Ok(Value::bool(lhs.le(&rhs)))
600 }
601}
602
603pub struct BinaryNotEq;
604impl FunctionImplementation for BinaryNotEq {
605 fn check_instantiability(
606 _fn_spec: &FunctionSpecification,
607 _auth_ctx: &AuthorizationContext,
608 _args: &Vec<Type>,
609 ) -> Result<Type, Diagnostic> {
610 unimplemented!()
611 }
612
613 fn run(
614 _fn_spec: &FunctionSpecification,
615 _auth_ctx: &AuthorizationContext,
616 args: &Vec<Value>,
617 ) -> Result<Value, Diagnostic> {
618 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
619 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
620 Ok(Value::bool(!lhs.eq(&rhs)))
621 }
622}
623
624pub struct BinaryMinus;
625impl FunctionImplementation for BinaryMinus {
626 fn check_instantiability(
627 _fn_spec: &FunctionSpecification,
628 _auth_ctx: &AuthorizationContext,
629 _args: &Vec<Type>,
630 ) -> Result<Type, Diagnostic> {
631 unimplemented!()
632 }
633
634 fn run(
635 _fn_spec: &FunctionSpecification,
636 _auth_ctx: &AuthorizationContext,
637 args: &Vec<Value>,
638 ) -> Result<Value, Diagnostic> {
639 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
640 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
641 Ok(Value::integer(lhs - rhs))
642 }
643}
644
645pub struct BinaryModulo;
646impl FunctionImplementation for BinaryModulo {
647 fn check_instantiability(
648 _fn_spec: &FunctionSpecification,
649 _auth_ctx: &AuthorizationContext,
650 _args: &Vec<Type>,
651 ) -> Result<Type, Diagnostic> {
652 unimplemented!()
653 }
654
655 fn run(
656 _fn_spec: &FunctionSpecification,
657 _auth_ctx: &AuthorizationContext,
658 args: &Vec<Value>,
659 ) -> Result<Value, Diagnostic> {
660 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
661 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
662 Ok(Value::integer(lhs.rem_euclid(*rhs)))
663 }
664}
665
666pub struct BinaryMul;
667impl FunctionImplementation for BinaryMul {
668 fn check_instantiability(
669 _fn_spec: &FunctionSpecification,
670 _auth_ctx: &AuthorizationContext,
671 _args: &Vec<Type>,
672 ) -> Result<Type, Diagnostic> {
673 unimplemented!()
674 }
675
676 fn run(
677 fn_spec: &FunctionSpecification,
678 _auth_ctx: &AuthorizationContext,
679 args: &Vec<Value>,
680 ) -> Result<Value, Diagnostic> {
681 arg_checker(fn_spec, args)?;
682 let lhs = args.get(0).unwrap().as_integer().unwrap();
683 let rhs = args.get(1).unwrap().as_integer().unwrap();
684 Ok(Value::integer(lhs.saturating_mul(rhs)))
685 }
686}
687
688pub struct BinaryPlus;
689impl FunctionImplementation for BinaryPlus {
690 fn check_instantiability(
691 _fn_spec: &FunctionSpecification,
692 _auth_ctx: &AuthorizationContext,
693 _args: &Vec<Type>,
694 ) -> Result<Type, Diagnostic> {
695 unimplemented!()
696 }
697
698 fn run(
699 _fn_spec: &FunctionSpecification,
700 _auth_ctx: &AuthorizationContext,
701 args: &Vec<Value>,
702 ) -> Result<Value, Diagnostic> {
703 let Some(Value::Integer(lhs)) = args.get(0) else { unreachable!() };
704 let Some(Value::Integer(rhs)) = args.get(1) else { unreachable!() };
705 Ok(Value::integer(lhs + rhs))
706 }
707}