1use crate::call_type::{CallType, InstanceCreationType};
16use crate::generic_type_parameter::GenericTypeParameter;
17use crate::parser::block::block;
18use crate::parser::type_name::TypeName;
19use crate::rib_compilation_error::RibCompilationError;
20use crate::rib_source_span::SourceSpan;
21use crate::type_registry::FunctionTypeRegistry;
22use crate::{
23 from_string, text, type_checker, type_inference, DynamicParsedFunctionName,
24 GlobalVariableTypeSpec, InferredType, ParsedFunctionName, VariableId,
25};
26use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
27use combine::parser::char::spaces;
28use combine::stream::position;
29use combine::Parser;
30use combine::{eof, EasyParser};
31use golem_api_grpc::proto::golem::rib::range_expr::RangeExpr;
32use golem_wasm_ast::analysis::AnalysedType;
33use golem_wasm_rpc::{IntoValueAndType, ValueAndType};
34use serde::{Deserialize, Serialize, Serializer};
35use serde_json::Value;
36use std::collections::VecDeque;
37use std::fmt::Display;
38use std::ops::Deref;
39use std::str::FromStr;
40
41#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
42pub enum Expr {
43 Let {
44 variable_id: VariableId,
45 type_annotation: Option<TypeName>,
46 expr: Box<Expr>,
47 inferred_type: InferredType,
48 source_span: SourceSpan,
49 },
50 SelectField {
51 expr: Box<Expr>,
52 field: String,
53 type_annotation: Option<TypeName>,
54 inferred_type: InferredType,
55 source_span: SourceSpan,
56 },
57 SelectIndex {
58 expr: Box<Expr>,
59 index: Box<Expr>,
60 type_annotation: Option<TypeName>,
61 inferred_type: InferredType,
62 source_span: SourceSpan,
63 },
64 Sequence {
65 exprs: Vec<Expr>,
66 type_annotation: Option<TypeName>,
67 inferred_type: InferredType,
68 source_span: SourceSpan,
69 },
70 Range {
71 range: Range,
72 type_annotation: Option<TypeName>,
73 inferred_type: InferredType,
74 source_span: SourceSpan,
75 },
76 Record {
77 exprs: Vec<(String, Box<Expr>)>,
78 type_annotation: Option<TypeName>,
79 inferred_type: InferredType,
80 source_span: SourceSpan,
81 },
82 Tuple {
83 exprs: Vec<Expr>,
84 type_annotation: Option<TypeName>,
85 inferred_type: InferredType,
86 source_span: SourceSpan,
87 },
88 Literal {
89 value: String,
90 type_annotation: Option<TypeName>,
91 inferred_type: InferredType,
92 source_span: SourceSpan,
93 },
94 Number {
95 number: Number,
96 type_annotation: Option<TypeName>,
97 inferred_type: InferredType,
98 source_span: SourceSpan,
99 },
100 Flags {
101 flags: Vec<String>,
102 type_annotation: Option<TypeName>,
103 inferred_type: InferredType,
104 source_span: SourceSpan,
105 },
106 Identifier {
107 variable_id: VariableId,
108 type_annotation: Option<TypeName>,
109 inferred_type: InferredType,
110 source_span: SourceSpan,
111 },
112 Boolean {
113 value: bool,
114 type_annotation: Option<TypeName>,
115 inferred_type: InferredType,
116 source_span: SourceSpan,
117 },
118 Concat {
119 exprs: Vec<Expr>,
120 type_annotation: Option<TypeName>,
121 inferred_type: InferredType,
122 source_span: SourceSpan,
123 },
124 ExprBlock {
125 exprs: Vec<Expr>,
126 type_annotation: Option<TypeName>,
127 inferred_type: InferredType,
128 source_span: SourceSpan,
129 },
130 Not {
131 expr: Box<Expr>,
132 inferred_type: InferredType,
133 type_annotation: Option<TypeName>,
134 source_span: SourceSpan,
135 },
136 GreaterThan {
137 lhs: Box<Expr>,
138 rhs: Box<Expr>,
139 type_annotation: Option<TypeName>,
140 inferred_type: InferredType,
141 source_span: SourceSpan,
142 },
143 And {
144 lhs: Box<Expr>,
145 rhs: Box<Expr>,
146 type_annotation: Option<TypeName>,
147 inferred_type: InferredType,
148 source_span: SourceSpan,
149 },
150 Or {
151 lhs: Box<Expr>,
152 rhs: Box<Expr>,
153 type_annotation: Option<TypeName>,
154 inferred_type: InferredType,
155 source_span: SourceSpan,
156 },
157 GreaterThanOrEqualTo {
158 lhs: Box<Expr>,
159 rhs: Box<Expr>,
160 type_annotation: Option<TypeName>,
161 inferred_type: InferredType,
162 source_span: SourceSpan,
163 },
164 LessThanOrEqualTo {
165 lhs: Box<Expr>,
166 rhs: Box<Expr>,
167 type_annotation: Option<TypeName>,
168 inferred_type: InferredType,
169 source_span: SourceSpan,
170 },
171 Plus {
172 lhs: Box<Expr>,
173 rhs: Box<Expr>,
174 type_annotation: Option<TypeName>,
175 inferred_type: InferredType,
176 source_span: SourceSpan,
177 },
178 Multiply {
179 lhs: Box<Expr>,
180 rhs: Box<Expr>,
181 type_annotation: Option<TypeName>,
182 inferred_type: InferredType,
183 source_span: SourceSpan,
184 },
185 Minus {
186 lhs: Box<Expr>,
187 rhs: Box<Expr>,
188 type_annotation: Option<TypeName>,
189 inferred_type: InferredType,
190 source_span: SourceSpan,
191 },
192 Divide {
193 lhs: Box<Expr>,
194 rhs: Box<Expr>,
195 type_annotation: Option<TypeName>,
196 inferred_type: InferredType,
197 source_span: SourceSpan,
198 },
199 EqualTo {
200 lhs: Box<Expr>,
201 rhs: Box<Expr>,
202 type_annotation: Option<TypeName>,
203 inferred_type: InferredType,
204 source_span: SourceSpan,
205 },
206 LessThan {
207 lhs: Box<Expr>,
208 rhs: Box<Expr>,
209 type_annotation: Option<TypeName>,
210 inferred_type: InferredType,
211 source_span: SourceSpan,
212 },
213 Cond {
214 cond: Box<Expr>,
215 lhs: Box<Expr>,
216 rhs: Box<Expr>,
217 type_annotation: Option<TypeName>,
218 inferred_type: InferredType,
219 source_span: SourceSpan,
220 },
221 PatternMatch {
222 predicate: Box<Expr>,
223 match_arms: Vec<MatchArm>,
224 type_annotation: Option<TypeName>,
225 inferred_type: InferredType,
226 source_span: SourceSpan,
227 },
228 Option {
229 expr: Option<Box<Expr>>,
230 type_annotation: Option<TypeName>,
231 inferred_type: InferredType,
232 source_span: SourceSpan,
233 },
234 Result {
235 expr: Result<Box<Expr>, Box<Expr>>,
236 type_annotation: Option<TypeName>,
237 inferred_type: InferredType,
238 source_span: SourceSpan,
239 },
240 Call {
246 call_type: CallType,
247 generic_type_parameter: Option<GenericTypeParameter>,
248 args: Vec<Expr>,
249 type_annotation: Option<TypeName>,
250 inferred_type: InferredType,
251 source_span: SourceSpan,
252 },
253 InvokeMethodLazy {
259 lhs: Box<Expr>,
260 method: String,
261 generic_type_parameter: Option<GenericTypeParameter>,
262 args: Vec<Expr>,
263 type_annotation: Option<TypeName>,
264 inferred_type: InferredType,
265 source_span: SourceSpan,
266 },
267 Unwrap {
268 expr: Box<Expr>,
269 inferred_type: InferredType,
270 type_annotation: Option<TypeName>,
271 source_span: SourceSpan,
272 },
273 Throw {
274 message: String,
275 inferred_type: InferredType,
276 type_annotation: Option<TypeName>,
277 source_span: SourceSpan,
278 },
279 GetTag {
280 expr: Box<Expr>,
281 inferred_type: InferredType,
282 type_annotation: Option<TypeName>,
283 source_span: SourceSpan,
284 },
285 ListComprehension {
286 iterated_variable: VariableId,
287 iterable_expr: Box<Expr>,
288 yield_expr: Box<Expr>,
289 type_annotation: Option<TypeName>,
290 inferred_type: InferredType,
291 source_span: SourceSpan,
292 },
293 ListReduce {
294 reduce_variable: VariableId,
295 iterated_variable: VariableId,
296 iterable_expr: Box<Expr>,
297 type_annotation: Option<TypeName>,
298 yield_expr: Box<Expr>,
299 init_value_expr: Box<Expr>,
300 inferred_type: InferredType,
301 source_span: SourceSpan,
302 },
303 Length {
304 expr: Box<Expr>,
305 inferred_type: InferredType,
306 type_annotation: Option<TypeName>,
307 source_span: SourceSpan,
308 },
309}
310
311impl Expr {
312 pub fn as_record(&self) -> Option<Vec<(String, Expr)>> {
313 match self {
314 Expr::Record { exprs: fields, .. } => Some(
315 fields
316 .iter()
317 .map(|(k, v)| (k.clone(), v.deref().clone()))
318 .collect::<Vec<_>>(),
319 ),
320 _ => None,
321 }
322 }
323 pub fn from_text(input: &str) -> Result<Expr, String> {
340 if input.trim().ends_with(';') {
341 return Err("unexpected `;` at the end of rib expression. \nnote: `;` is used to separate expressions, but it should not appear after the last expression (which is the return value)".to_string());
342 }
343
344 spaces()
345 .with(block().skip(eof()))
346 .easy_parse(position::Stream::new(input))
347 .map(|t| t.0)
348 .map_err(|err| format!("{}", err))
349 }
350
351 pub fn is_literal(&self) -> bool {
352 matches!(self, Expr::Literal { .. })
353 }
354
355 pub fn is_block(&self) -> bool {
356 matches!(self, Expr::ExprBlock { .. })
357 }
358
359 pub fn is_number(&self) -> bool {
360 matches!(self, Expr::Number { .. })
361 }
362
363 pub fn is_record(&self) -> bool {
364 matches!(self, Expr::Record { .. })
365 }
366
367 pub fn is_result(&self) -> bool {
368 matches!(self, Expr::Result { .. })
369 }
370
371 pub fn is_option(&self) -> bool {
372 matches!(self, Expr::Option { .. })
373 }
374
375 pub fn is_tuple(&self) -> bool {
376 matches!(self, Expr::Tuple { .. })
377 }
378
379 pub fn is_list(&self) -> bool {
380 matches!(self, Expr::Sequence { .. })
381 }
382
383 pub fn is_flags(&self) -> bool {
384 matches!(self, Expr::Flags { .. })
385 }
386
387 pub fn is_identifier(&self) -> bool {
388 matches!(self, Expr::Identifier { .. })
389 }
390
391 pub fn is_select_field(&self) -> bool {
392 matches!(self, Expr::SelectField { .. })
393 }
394
395 pub fn is_if_else(&self) -> bool {
396 matches!(self, Expr::Cond { .. })
397 }
398
399 pub fn is_function_call(&self) -> bool {
400 matches!(self, Expr::Call { .. })
401 }
402
403 pub fn is_match_expr(&self) -> bool {
404 matches!(self, Expr::PatternMatch { .. })
405 }
406
407 pub fn is_boolean(&self) -> bool {
408 matches!(self, Expr::Boolean { .. })
409 }
410
411 pub fn is_comparison(&self) -> bool {
412 matches!(
413 self,
414 Expr::GreaterThan { .. }
415 | Expr::GreaterThanOrEqualTo { .. }
416 | Expr::LessThanOrEqualTo { .. }
417 | Expr::EqualTo { .. }
418 | Expr::LessThan { .. }
419 )
420 }
421
422 pub fn is_concat(&self) -> bool {
423 matches!(self, Expr::Concat { .. })
424 }
425
426 pub fn is_multiple(&self) -> bool {
427 matches!(self, Expr::ExprBlock { .. })
428 }
429
430 pub fn inbuilt_variant(&self) -> Option<(String, Option<Expr>)> {
431 match self {
432 Expr::Option {
433 expr: Some(expr), ..
434 } => Some(("some".to_string(), Some(expr.deref().clone()))),
435 Expr::Option { expr: None, .. } => Some(("some".to_string(), None)),
436 Expr::Result { expr: Ok(expr), .. } => {
437 Some(("ok".to_string(), Some(expr.deref().clone())))
438 }
439 Expr::Result {
440 expr: Err(expr), ..
441 } => Some(("err".to_string(), Some(expr.deref().clone()))),
442 _ => None,
443 }
444 }
445 pub fn unwrap(&self) -> Self {
446 Expr::Unwrap {
447 expr: Box::new(self.clone()),
448 inferred_type: InferredType::Unknown,
449 source_span: SourceSpan::default(),
450 type_annotation: None,
451 }
452 }
453
454 pub fn length(expr: Expr) -> Self {
455 Expr::Length {
456 expr: Box::new(expr),
457 inferred_type: InferredType::U64,
458 source_span: SourceSpan::default(),
459 type_annotation: None,
460 }
461 }
462
463 pub fn boolean(value: bool) -> Self {
464 Expr::Boolean {
465 value,
466 inferred_type: InferredType::Bool,
467 source_span: SourceSpan::default(),
468 type_annotation: None,
469 }
470 }
471
472 pub fn and(left: Expr, right: Expr) -> Self {
473 Expr::And {
474 lhs: Box::new(left),
475 rhs: Box::new(right),
476 inferred_type: InferredType::Bool,
477 source_span: SourceSpan::default(),
478 type_annotation: None,
479 }
480 }
481
482 pub fn throw(message: impl AsRef<str>) -> Self {
483 Expr::Throw {
484 message: message.as_ref().to_string(),
485 inferred_type: InferredType::Unknown,
486 source_span: SourceSpan::default(),
487 type_annotation: None,
488 }
489 }
490
491 pub fn plus(left: Expr, right: Expr) -> Self {
492 Expr::Plus {
493 lhs: Box::new(left),
494 rhs: Box::new(right),
495 inferred_type: InferredType::Unknown,
496 source_span: SourceSpan::default(),
497 type_annotation: None,
498 }
499 }
500
501 pub fn minus(left: Expr, right: Expr) -> Self {
502 Expr::Minus {
503 lhs: Box::new(left),
504 rhs: Box::new(right),
505 inferred_type: InferredType::number(),
506 source_span: SourceSpan::default(),
507 type_annotation: None,
508 }
509 }
510
511 pub fn divide(left: Expr, right: Expr) -> Self {
512 Expr::Divide {
513 lhs: Box::new(left),
514 rhs: Box::new(right),
515 inferred_type: InferredType::number(),
516 source_span: SourceSpan::default(),
517 type_annotation: None,
518 }
519 }
520
521 pub fn multiply(left: Expr, right: Expr) -> Self {
522 Expr::Multiply {
523 lhs: Box::new(left),
524 rhs: Box::new(right),
525 inferred_type: InferredType::number(),
526 source_span: SourceSpan::default(),
527 type_annotation: None,
528 }
529 }
530
531 pub fn and_combine(conditions: Vec<Expr>) -> Option<Expr> {
532 let mut cond: Option<Expr> = None;
533
534 for i in conditions {
535 let left = Box::new(cond.clone().unwrap_or(Expr::boolean(true)));
536 cond = Some(Expr::And {
537 lhs: left,
538 rhs: Box::new(i),
539 inferred_type: InferredType::Bool,
540 source_span: SourceSpan::default(),
541 type_annotation: None,
542 });
543 }
544
545 cond
546 }
547
548 pub fn call_worker_function(
549 dynamic_parsed_fn_name: DynamicParsedFunctionName,
550 generic_type_parameter: Option<GenericTypeParameter>,
551 worker_name: Option<Expr>,
552 args: Vec<Expr>,
553 ) -> Self {
554 Expr::Call {
555 call_type: CallType::Function {
556 function_name: dynamic_parsed_fn_name,
557 worker: worker_name.map(Box::new),
558 },
559 generic_type_parameter,
560 args,
561 inferred_type: InferredType::Unknown,
562 source_span: SourceSpan::default(),
563 type_annotation: None,
564 }
565 }
566
567 pub fn call(
568 call_type: CallType,
569 generic_type_parameter: Option<GenericTypeParameter>,
570 args: Vec<Expr>,
571 ) -> Self {
572 Expr::Call {
573 call_type,
574 generic_type_parameter,
575 args,
576 inferred_type: InferredType::Unknown,
577 source_span: SourceSpan::default(),
578 type_annotation: None,
579 }
580 }
581
582 pub fn invoke_worker_function(
583 lhs: Expr,
584 function_name: String,
585 generic_type_parameter: Option<GenericTypeParameter>,
586 args: Vec<Expr>,
587 ) -> Self {
588 Expr::InvokeMethodLazy {
589 lhs: Box::new(lhs),
590 method: function_name,
591 generic_type_parameter,
592 args,
593 inferred_type: InferredType::Unknown,
594 source_span: SourceSpan::default(),
595 type_annotation: None,
596 }
597 }
598
599 pub fn concat(expressions: Vec<Expr>) -> Self {
600 Expr::Concat {
601 exprs: expressions,
602 inferred_type: InferredType::Str,
603 source_span: SourceSpan::default(),
604 type_annotation: None,
605 }
606 }
607
608 pub fn cond(cond: Expr, lhs: Expr, rhs: Expr) -> Self {
609 Expr::Cond {
610 cond: Box::new(cond),
611 lhs: Box::new(lhs),
612 rhs: Box::new(rhs),
613 inferred_type: InferredType::Unknown,
614 source_span: SourceSpan::default(),
615 type_annotation: None,
616 }
617 }
618
619 pub fn equal_to(left: Expr, right: Expr) -> Self {
620 Expr::EqualTo {
621 lhs: Box::new(left),
622 rhs: Box::new(right),
623 inferred_type: InferredType::Bool,
624 source_span: SourceSpan::default(),
625 type_annotation: None,
626 }
627 }
628
629 pub fn err(expr: Expr, type_annotation: Option<TypeName>) -> Self {
630 let inferred_type = expr.inferred_type();
631 Expr::Result {
632 expr: Err(Box::new(expr)),
633 type_annotation,
634 inferred_type: InferredType::Result {
635 ok: Some(Box::new(InferredType::Unknown)),
636 error: Some(Box::new(inferred_type)),
637 },
638 source_span: SourceSpan::default(),
639 }
640 }
641
642 pub fn flags(flags: Vec<String>) -> Self {
643 Expr::Flags {
644 flags: flags.clone(),
645 inferred_type: InferredType::Flags(flags),
646 source_span: SourceSpan::default(),
647 type_annotation: None,
648 }
649 }
650
651 pub fn greater_than(left: Expr, right: Expr) -> Self {
652 Expr::GreaterThan {
653 lhs: Box::new(left),
654 rhs: Box::new(right),
655 inferred_type: InferredType::Bool,
656 source_span: SourceSpan::default(),
657 type_annotation: None,
658 }
659 }
660
661 pub fn greater_than_or_equal_to(left: Expr, right: Expr) -> Self {
662 Expr::GreaterThanOrEqualTo {
663 lhs: Box::new(left),
664 rhs: Box::new(right),
665 inferred_type: InferredType::Bool,
666 source_span: SourceSpan::default(),
667 type_annotation: None,
668 }
669 }
670
671 pub fn identifier_global(name: impl AsRef<str>, type_annotation: Option<TypeName>) -> Self {
673 Expr::Identifier {
674 variable_id: VariableId::global(name.as_ref().to_string()),
675 type_annotation,
676 inferred_type: InferredType::Unknown,
677 source_span: SourceSpan::default(),
678 }
679 }
680
681 pub fn identifier_local(
682 name: impl AsRef<str>,
683 id: u32,
684 type_annotation: Option<TypeName>,
685 ) -> Self {
686 Expr::Identifier {
687 variable_id: VariableId::local(name.as_ref(), id),
688 type_annotation,
689 inferred_type: InferredType::Unknown,
690 source_span: SourceSpan::default(),
691 }
692 }
693
694 pub fn identifier_with_variable_id(
695 variable_id: VariableId,
696 type_annotation: Option<TypeName>,
697 ) -> Self {
698 Expr::Identifier {
699 variable_id,
700 type_annotation,
701 inferred_type: InferredType::Unknown,
702 source_span: SourceSpan::default(),
703 }
704 }
705
706 pub fn less_than(left: Expr, right: Expr) -> Self {
707 Expr::LessThan {
708 lhs: Box::new(left),
709 rhs: Box::new(right),
710 inferred_type: InferredType::Bool,
711 source_span: SourceSpan::default(),
712 type_annotation: None,
713 }
714 }
715
716 pub fn less_than_or_equal_to(left: Expr, right: Expr) -> Self {
717 Expr::LessThanOrEqualTo {
718 lhs: Box::new(left),
719 rhs: Box::new(right),
720 inferred_type: InferredType::Bool,
721 source_span: SourceSpan::default(),
722 type_annotation: None,
723 }
724 }
725
726 pub fn range(from: Expr, to: Expr) -> Self {
727 Expr::Range {
728 range: Range::Range {
729 from: Box::new(from.clone()),
730 to: Box::new(to.clone()),
731 },
732 inferred_type: InferredType::Range {
733 from: Box::new(from.inferred_type()),
734 to: Some(Box::new(to.inferred_type())),
735 },
736 source_span: SourceSpan::default(),
737 type_annotation: None,
738 }
739 }
740
741 pub fn range_from(from: Expr) -> Self {
742 Expr::Range {
743 range: Range::RangeFrom {
744 from: Box::new(from.clone()),
745 },
746 inferred_type: InferredType::Range {
747 from: Box::new(from.inferred_type()),
748 to: None,
749 },
750 source_span: SourceSpan::default(),
751 type_annotation: None,
752 }
753 }
754
755 pub fn range_inclusive(from: Expr, to: Expr) -> Self {
756 Expr::Range {
757 range: Range::RangeInclusive {
758 from: Box::new(from.clone()),
759 to: Box::new(to.clone()),
760 },
761 inferred_type: InferredType::Range {
762 from: Box::new(from.inferred_type()),
763 to: Some(Box::new(to.inferred_type())),
764 },
765 source_span: SourceSpan::default(),
766 type_annotation: None,
767 }
768 }
769
770 pub fn let_binding(
771 name: impl AsRef<str>,
772 expr: Expr,
773 type_annotation: Option<TypeName>,
774 ) -> Self {
775 Expr::Let {
776 variable_id: VariableId::global(name.as_ref().to_string()),
777 type_annotation,
778 expr: Box::new(expr),
779 source_span: SourceSpan::default(),
780 inferred_type: InferredType::Tuple(vec![]),
781 }
782 }
783
784 pub fn let_binding_with_variable_id(
785 variable_id: VariableId,
786 expr: Expr,
787 type_annotation: Option<TypeName>,
788 ) -> Self {
789 Expr::Let {
790 variable_id,
791 type_annotation,
792 expr: Box::new(expr),
793 source_span: SourceSpan::default(),
794 inferred_type: InferredType::Tuple(vec![]),
795 }
796 }
797
798 pub fn typed_list_reduce(
799 reduce_variable: VariableId,
800 iterated_variable: VariableId,
801 iterable_expr: Expr,
802 init_value_expr: Expr,
803 yield_expr: Expr,
804 inferred_type: InferredType,
805 ) -> Self {
806 Expr::ListReduce {
807 reduce_variable,
808 iterated_variable,
809 iterable_expr: Box::new(iterable_expr),
810 yield_expr: Box::new(yield_expr),
811 init_value_expr: Box::new(init_value_expr),
812 inferred_type,
813 source_span: SourceSpan::default(),
814 type_annotation: None,
815 }
816 }
817
818 pub fn list_reduce(
819 reduce_variable: VariableId,
820 iterated_variable: VariableId,
821 iterable_expr: Expr,
822 init_value_expr: Expr,
823 yield_expr: Expr,
824 ) -> Self {
825 Expr::typed_list_reduce(
826 reduce_variable,
827 iterated_variable,
828 iterable_expr,
829 init_value_expr,
830 yield_expr,
831 InferredType::Unknown,
832 )
833 }
834
835 pub fn list_comprehension_typed(
836 iterated_variable: VariableId,
837 iterable_expr: Expr,
838 yield_expr: Expr,
839 inferred_type: InferredType,
840 ) -> Self {
841 Expr::ListComprehension {
842 iterated_variable,
843 iterable_expr: Box::new(iterable_expr),
844 yield_expr: Box::new(yield_expr),
845 inferred_type,
846 source_span: SourceSpan::default(),
847 type_annotation: None,
848 }
849 }
850
851 pub fn list_comprehension(
852 variable_id: VariableId,
853 iterable_expr: Expr,
854 yield_expr: Expr,
855 ) -> Self {
856 Expr::list_comprehension_typed(
857 variable_id,
858 iterable_expr,
859 yield_expr,
860 InferredType::List(Box::new(InferredType::Unknown)),
861 )
862 }
863
864 pub fn bind_global_variable_types(
865 &self,
866 type_spec: &Vec<GlobalVariableTypeSpec>,
867 ) -> Result<Self, RibCompilationError> {
868 type_inference::bind_global_variable_types(self, type_spec)
869 }
870
871 pub fn bind_instance_types(&mut self) {
872 type_inference::bind_instance_types(self)
873 }
874
875 pub fn literal(value: impl AsRef<str>) -> Self {
876 Expr::Literal {
877 value: value.as_ref().to_string(),
878 inferred_type: InferredType::Str,
879 source_span: SourceSpan::default(),
880 type_annotation: None,
881 }
882 }
883
884 pub fn empty_expr() -> Self {
885 Expr::literal("")
886 }
887
888 pub fn expr_block(expressions: Vec<Expr>) -> Self {
889 let inferred_type = expressions
890 .last()
891 .map_or(InferredType::Unknown, |e| e.inferred_type());
892
893 Expr::ExprBlock {
894 exprs: expressions,
895 inferred_type,
896 source_span: SourceSpan::default(),
897 type_annotation: None,
898 }
899 }
900
901 #[allow(clippy::should_implement_trait)]
902 pub fn not(expr: Expr) -> Self {
903 Expr::Not {
904 expr: Box::new(expr),
905 inferred_type: InferredType::Bool,
906 source_span: SourceSpan::default(),
907 type_annotation: None,
908 }
909 }
910
911 pub fn ok(expr: Expr, type_annotation: Option<TypeName>) -> Self {
912 let inferred_type = expr.inferred_type();
913
914 Expr::Result {
915 expr: Ok(Box::new(expr)),
916 type_annotation,
917 inferred_type: InferredType::Result {
918 ok: Some(Box::new(inferred_type)),
919 error: Some(Box::new(InferredType::Unknown)),
920 },
921 source_span: SourceSpan::default(),
922 }
923 }
924
925 pub fn option(expr: Option<Expr>) -> Self {
926 let inferred_type = match &expr {
927 Some(expr) => expr.inferred_type(),
928 None => InferredType::Unknown,
929 };
930
931 Expr::Option {
932 expr: expr.map(Box::new),
933 type_annotation: None,
934 inferred_type: InferredType::Option(Box::new(inferred_type)),
935 source_span: SourceSpan::default(),
936 }
937 }
938
939 pub fn or(left: Expr, right: Expr) -> Self {
940 Expr::Or {
941 lhs: Box::new(left),
942 rhs: Box::new(right),
943 inferred_type: InferredType::Bool,
944 source_span: SourceSpan::default(),
945 type_annotation: None,
946 }
947 }
948
949 pub fn pattern_match(expr: Expr, match_arms: Vec<MatchArm>) -> Self {
950 Expr::PatternMatch {
951 predicate: Box::new(expr),
952 match_arms,
953 inferred_type: InferredType::Unknown,
954 source_span: SourceSpan::default(),
955 type_annotation: None,
956 }
957 }
958
959 pub fn record(expressions: Vec<(String, Expr)>) -> Self {
960 let inferred_type = InferredType::Record(
961 expressions
962 .iter()
963 .map(|(field_name, expr)| (field_name.to_string(), expr.inferred_type()))
964 .collect(),
965 );
966
967 Expr::Record {
968 exprs: expressions
969 .into_iter()
970 .map(|(field_name, expr)| (field_name, Box::new(expr)))
971 .collect(),
972 inferred_type,
973 source_span: SourceSpan::default(),
974 type_annotation: None,
975 }
976 }
977
978 pub fn select_field(
979 expr: Expr,
980 field: impl AsRef<str>,
981 type_annotation: Option<TypeName>,
982 ) -> Self {
983 Expr::SelectField {
984 expr: Box::new(expr),
985 field: field.as_ref().to_string(),
986 type_annotation,
987 inferred_type: InferredType::Unknown,
988 source_span: SourceSpan::default(),
989 }
990 }
991
992 pub fn select_index(expr: Expr, index: Expr) -> Self {
993 Expr::SelectIndex {
994 expr: Box::new(expr),
995 index: Box::new(index),
996 type_annotation: None,
997 inferred_type: InferredType::Unknown,
998 source_span: SourceSpan::default(),
999 }
1000 }
1001
1002 pub fn get_tag(expr: Expr) -> Self {
1003 Expr::GetTag {
1004 expr: Box::new(expr),
1005 inferred_type: InferredType::Unknown,
1006 source_span: SourceSpan::default(),
1007 type_annotation: None,
1008 }
1009 }
1010
1011 pub fn tuple(expressions: Vec<Expr>) -> Self {
1012 let inferred_type = InferredType::Tuple(
1013 expressions
1014 .iter()
1015 .map(|expr| expr.inferred_type())
1016 .collect(),
1017 );
1018
1019 Expr::Tuple {
1020 exprs: expressions,
1021 inferred_type,
1022 source_span: SourceSpan::default(),
1023 type_annotation: None,
1024 }
1025 }
1026
1027 pub fn sequence(expressions: Vec<Expr>, type_annotation: Option<TypeName>) -> Self {
1028 let inferred_type = InferredType::List(Box::new(
1029 expressions
1030 .first()
1031 .map_or(InferredType::Unknown, |x| x.inferred_type()),
1032 ));
1033
1034 Expr::Sequence {
1035 exprs: expressions,
1036 type_annotation,
1037 inferred_type,
1038 source_span: SourceSpan::default(),
1039 }
1040 }
1041
1042 pub fn inferred_type(&self) -> InferredType {
1043 match self {
1044 Expr::Let { inferred_type, .. }
1045 | Expr::SelectField { inferred_type, .. }
1046 | Expr::SelectIndex { inferred_type, .. }
1047 | Expr::Sequence { inferred_type, .. }
1048 | Expr::Record { inferred_type, .. }
1049 | Expr::Tuple { inferred_type, .. }
1050 | Expr::Literal { inferred_type, .. }
1051 | Expr::Number { inferred_type, .. }
1052 | Expr::Flags { inferred_type, .. }
1053 | Expr::Identifier { inferred_type, .. }
1054 | Expr::Boolean { inferred_type, .. }
1055 | Expr::Concat { inferred_type, .. }
1056 | Expr::ExprBlock { inferred_type, .. }
1057 | Expr::Not { inferred_type, .. }
1058 | Expr::GreaterThan { inferred_type, .. }
1059 | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1060 | Expr::LessThanOrEqualTo { inferred_type, .. }
1061 | Expr::EqualTo { inferred_type, .. }
1062 | Expr::Plus { inferred_type, .. }
1063 | Expr::Minus { inferred_type, .. }
1064 | Expr::Divide { inferred_type, .. }
1065 | Expr::Multiply { inferred_type, .. }
1066 | Expr::LessThan { inferred_type, .. }
1067 | Expr::Cond { inferred_type, .. }
1068 | Expr::PatternMatch { inferred_type, .. }
1069 | Expr::Option { inferred_type, .. }
1070 | Expr::Result { inferred_type, .. }
1071 | Expr::Unwrap { inferred_type, .. }
1072 | Expr::Throw { inferred_type, .. }
1073 | Expr::GetTag { inferred_type, .. }
1074 | Expr::And { inferred_type, .. }
1075 | Expr::Or { inferred_type, .. }
1076 | Expr::ListComprehension { inferred_type, .. }
1077 | Expr::ListReduce { inferred_type, .. }
1078 | Expr::Call { inferred_type, .. }
1079 | Expr::Range { inferred_type, .. }
1080 | Expr::InvokeMethodLazy { inferred_type, .. } => inferred_type.clone(),
1081 Expr::Length { inferred_type, .. } => inferred_type.clone(),
1082 }
1083 }
1084
1085 pub fn infer_types(
1086 &mut self,
1087 function_type_registry: &FunctionTypeRegistry,
1088 type_spec: &Vec<GlobalVariableTypeSpec>,
1089 ) -> Result<(), RibCompilationError> {
1090 self.infer_types_initial_phase(function_type_registry, type_spec)?;
1091 self.bind_instance_types();
1092 type_inference::type_inference_fix_point(Self::resolve_method_calls, self)?;
1097 self.infer_function_call_types(function_type_registry)?;
1098 type_inference::type_inference_fix_point(Self::inference_scan, self)?;
1099 self.infer_orphan_literals()?;
1100 self.check_types(function_type_registry)?;
1101 self.unify_types()?;
1102 Ok(())
1103 }
1104
1105 pub fn infer_types_initial_phase(
1106 &mut self,
1107 function_type_registry: &FunctionTypeRegistry,
1108 type_spec: &Vec<GlobalVariableTypeSpec>,
1109 ) -> Result<(), RibCompilationError> {
1110 self.identify_instance_creation(function_type_registry)?;
1111 *self = self.bind_global_variable_types(type_spec)?;
1112 self.bind_type_annotations();
1113 self.bind_default_types_to_index_expressions();
1114 self.bind_variables_of_list_comprehension();
1115 self.bind_variables_of_list_reduce();
1116 self.bind_variables_of_pattern_match();
1117 self.bind_variables_of_let_assignment();
1118 self.infer_variants(function_type_registry);
1119 self.infer_enums(function_type_registry);
1120 Ok(())
1121 }
1122
1123 pub fn resolve_method_calls(&mut self) -> Result<(), RibCompilationError> {
1124 self.bind_instance_types();
1125 self.infer_worker_function_invokes()?;
1126 Ok(())
1127 }
1128
1129 pub fn inference_scan(&mut self) -> Result<(), RibCompilationError> {
1133 self.infer_all_identifiers();
1134 self.push_types_down()?;
1135 self.infer_all_identifiers();
1136 let expr = self.pull_types_up()?;
1137 *self = expr;
1138 self.infer_global_inputs();
1139 Ok(())
1140 }
1141
1142 pub fn infer_orphan_literals(&mut self) -> Result<(), RibCompilationError> {
1143 type_inference::infer_orphan_literals(self)
1144 }
1145
1146 pub fn infer_worker_function_invokes(&mut self) -> Result<(), RibCompilationError> {
1147 type_inference::infer_worker_function_invokes(self)
1148 }
1149
1150 pub fn bind_default_types_to_index_expressions(&mut self) {
1151 type_inference::bind_default_types_to_index_expressions(self);
1152 }
1153
1154 pub fn bind_variables_of_pattern_match(&mut self) {
1158 type_inference::bind_variables_of_pattern_match(self);
1159 }
1160
1161 pub fn bind_variables_of_let_assignment(&mut self) {
1165 type_inference::bind_variables_of_let_assignment(self);
1166 }
1167
1168 pub fn bind_variables_of_list_comprehension(&mut self) {
1169 type_inference::bind_variables_of_list_comprehension(self);
1170 }
1171
1172 pub fn bind_variables_of_list_reduce(&mut self) {
1173 type_inference::bind_variables_of_list_reduce(self);
1174 }
1175
1176 pub fn identify_instance_creation(
1177 &mut self,
1178 function_type_registry: &FunctionTypeRegistry,
1179 ) -> Result<(), RibCompilationError> {
1180 type_inference::identify_instance_creation(self, function_type_registry)
1181 }
1182
1183 pub fn infer_function_call_types(
1184 &mut self,
1185 function_type_registry: &FunctionTypeRegistry,
1186 ) -> Result<(), RibCompilationError> {
1187 type_inference::infer_function_call_types(self, function_type_registry)?;
1188 Ok(())
1189 }
1190
1191 pub fn push_types_down(&mut self) -> Result<(), RibCompilationError> {
1192 type_inference::push_types_down(self)
1193 }
1194
1195 pub fn infer_all_identifiers(&mut self) {
1196 type_inference::infer_all_identifiers(self)
1197 }
1198
1199 pub fn pull_types_up(&self) -> Result<Expr, RibCompilationError> {
1200 type_inference::type_pull_up(self)
1201 }
1202
1203 pub fn infer_global_inputs(&mut self) {
1204 type_inference::infer_global_inputs(self);
1205 }
1206
1207 pub fn bind_type_annotations(&mut self) {
1208 type_inference::bind_type_annotations(self);
1209 }
1210
1211 pub fn check_types(
1212 &mut self,
1213 function_type_registry: &FunctionTypeRegistry,
1214 ) -> Result<(), RibCompilationError> {
1215 type_checker::type_check(self, function_type_registry)
1216 }
1217
1218 pub fn unify_types(&mut self) -> Result<(), RibCompilationError> {
1219 type_inference::unify_types(self)?;
1220 Ok(())
1221 }
1222
1223 pub fn merge_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1224 let mut expr_copied = self.clone();
1225 expr_copied.add_infer_type_mut(new_inferred_type);
1226 expr_copied
1227 }
1228
1229 pub fn add_infer_type_mut(&mut self, new_inferred_type: InferredType) {
1230 match self {
1231 Expr::Identifier { inferred_type, .. }
1232 | Expr::Let { inferred_type, .. }
1233 | Expr::SelectField { inferred_type, .. }
1234 | Expr::SelectIndex { inferred_type, .. }
1235 | Expr::Sequence { inferred_type, .. }
1236 | Expr::Record { inferred_type, .. }
1237 | Expr::Tuple { inferred_type, .. }
1238 | Expr::Literal { inferred_type, .. }
1239 | Expr::Number { inferred_type, .. }
1240 | Expr::Flags { inferred_type, .. }
1241 | Expr::Boolean { inferred_type, .. }
1242 | Expr::Concat { inferred_type, .. }
1243 | Expr::ExprBlock { inferred_type, .. }
1244 | Expr::Not { inferred_type, .. }
1245 | Expr::GreaterThan { inferred_type, .. }
1246 | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1247 | Expr::LessThanOrEqualTo { inferred_type, .. }
1248 | Expr::EqualTo { inferred_type, .. }
1249 | Expr::Plus { inferred_type, .. }
1250 | Expr::Minus { inferred_type, .. }
1251 | Expr::Divide { inferred_type, .. }
1252 | Expr::Multiply { inferred_type, .. }
1253 | Expr::LessThan { inferred_type, .. }
1254 | Expr::Cond { inferred_type, .. }
1255 | Expr::PatternMatch { inferred_type, .. }
1256 | Expr::Option { inferred_type, .. }
1257 | Expr::Result { inferred_type, .. }
1258 | Expr::Unwrap { inferred_type, .. }
1259 | Expr::Throw { inferred_type, .. }
1260 | Expr::GetTag { inferred_type, .. }
1261 | Expr::And { inferred_type, .. }
1262 | Expr::Or { inferred_type, .. }
1263 | Expr::ListComprehension { inferred_type, .. }
1264 | Expr::ListReduce { inferred_type, .. }
1265 | Expr::InvokeMethodLazy { inferred_type, .. }
1266 | Expr::Range { inferred_type, .. }
1267 | Expr::Length { inferred_type, .. }
1268 | Expr::Call { inferred_type, .. } => {
1269 if new_inferred_type != InferredType::Unknown {
1270 *inferred_type = inferred_type.merge(new_inferred_type);
1271 }
1272 }
1273 }
1274 }
1275
1276 pub fn reset_type(&mut self) {
1277 type_inference::reset_type_info(self);
1278 }
1279
1280 pub fn source_span(&self) -> SourceSpan {
1281 match self {
1282 Expr::Identifier { source_span, .. }
1283 | Expr::Let { source_span, .. }
1284 | Expr::SelectField { source_span, .. }
1285 | Expr::SelectIndex { source_span, .. }
1286 | Expr::Sequence { source_span, .. }
1287 | Expr::Record { source_span, .. }
1288 | Expr::Tuple { source_span, .. }
1289 | Expr::Literal { source_span, .. }
1290 | Expr::Number { source_span, .. }
1291 | Expr::Flags { source_span, .. }
1292 | Expr::Boolean { source_span, .. }
1293 | Expr::Concat { source_span, .. }
1294 | Expr::ExprBlock { source_span, .. }
1295 | Expr::Not { source_span, .. }
1296 | Expr::GreaterThan { source_span, .. }
1297 | Expr::GreaterThanOrEqualTo { source_span, .. }
1298 | Expr::LessThanOrEqualTo { source_span, .. }
1299 | Expr::EqualTo { source_span, .. }
1300 | Expr::LessThan { source_span, .. }
1301 | Expr::Plus { source_span, .. }
1302 | Expr::Minus { source_span, .. }
1303 | Expr::Divide { source_span, .. }
1304 | Expr::Multiply { source_span, .. }
1305 | Expr::Cond { source_span, .. }
1306 | Expr::PatternMatch { source_span, .. }
1307 | Expr::Option { source_span, .. }
1308 | Expr::Result { source_span, .. }
1309 | Expr::Unwrap { source_span, .. }
1310 | Expr::Throw { source_span, .. }
1311 | Expr::And { source_span, .. }
1312 | Expr::Or { source_span, .. }
1313 | Expr::GetTag { source_span, .. }
1314 | Expr::ListComprehension { source_span, .. }
1315 | Expr::ListReduce { source_span, .. }
1316 | Expr::InvokeMethodLazy { source_span, .. }
1317 | Expr::Range { source_span, .. }
1318 | Expr::Length { source_span, .. }
1319 | Expr::Call { source_span, .. } => source_span.clone(),
1320 }
1321 }
1322
1323 pub fn with_type_annotation_opt(&self, type_annotation: Option<TypeName>) -> Expr {
1324 if let Some(type_annotation) = type_annotation {
1325 self.with_type_annotation(type_annotation)
1326 } else {
1327 self.clone()
1328 }
1329 }
1330
1331 pub fn with_type_annotation(&self, type_annotation: TypeName) -> Expr {
1332 let mut expr_copied = self.clone();
1333 expr_copied.with_type_annotation_mut(type_annotation);
1334 expr_copied
1335 }
1336
1337 pub fn with_type_annotation_mut(&mut self, type_annotation: TypeName) {
1338 let new_type_annotation = type_annotation;
1339
1340 match self {
1341 Expr::Identifier {
1342 type_annotation, ..
1343 }
1344 | Expr::Let {
1345 type_annotation, ..
1346 }
1347 | Expr::SelectField {
1348 type_annotation, ..
1349 }
1350 | Expr::SelectIndex {
1351 type_annotation, ..
1352 }
1353 | Expr::Sequence {
1354 type_annotation, ..
1355 }
1356 | Expr::Record {
1357 type_annotation, ..
1358 }
1359 | Expr::Tuple {
1360 type_annotation, ..
1361 }
1362 | Expr::Literal {
1363 type_annotation, ..
1364 }
1365 | Expr::Number {
1366 type_annotation, ..
1367 }
1368 | Expr::Flags {
1369 type_annotation, ..
1370 }
1371 | Expr::Boolean {
1372 type_annotation, ..
1373 }
1374 | Expr::Concat {
1375 type_annotation, ..
1376 }
1377 | Expr::ExprBlock {
1378 type_annotation, ..
1379 }
1380 | Expr::Not {
1381 type_annotation, ..
1382 }
1383 | Expr::GreaterThan {
1384 type_annotation, ..
1385 }
1386 | Expr::GreaterThanOrEqualTo {
1387 type_annotation, ..
1388 }
1389 | Expr::LessThanOrEqualTo {
1390 type_annotation, ..
1391 }
1392 | Expr::EqualTo {
1393 type_annotation, ..
1394 }
1395 | Expr::LessThan {
1396 type_annotation, ..
1397 }
1398 | Expr::Plus {
1399 type_annotation, ..
1400 }
1401 | Expr::Minus {
1402 type_annotation, ..
1403 }
1404 | Expr::Divide {
1405 type_annotation, ..
1406 }
1407 | Expr::Multiply {
1408 type_annotation, ..
1409 }
1410 | Expr::Cond {
1411 type_annotation, ..
1412 }
1413 | Expr::PatternMatch {
1414 type_annotation, ..
1415 }
1416 | Expr::Option {
1417 type_annotation, ..
1418 }
1419 | Expr::Result {
1420 type_annotation, ..
1421 }
1422 | Expr::Unwrap {
1423 type_annotation, ..
1424 }
1425 | Expr::Throw {
1426 type_annotation, ..
1427 }
1428 | Expr::And {
1429 type_annotation, ..
1430 }
1431 | Expr::Or {
1432 type_annotation, ..
1433 }
1434 | Expr::GetTag {
1435 type_annotation, ..
1436 }
1437 | Expr::Range {
1438 type_annotation, ..
1439 }
1440 | Expr::ListComprehension {
1441 type_annotation, ..
1442 }
1443 | Expr::ListReduce {
1444 type_annotation, ..
1445 }
1446 | Expr::InvokeMethodLazy {
1447 type_annotation, ..
1448 }
1449 | Expr::Length {
1450 type_annotation, ..
1451 }
1452 | Expr::Call {
1453 type_annotation, ..
1454 } => {
1455 *type_annotation = Some(new_type_annotation);
1456 }
1457 }
1458 }
1459
1460 pub fn with_source_span(&self, new_source_span: SourceSpan) -> Expr {
1461 let mut expr_copied = self.clone();
1462 expr_copied.with_source_span_mut(new_source_span);
1463 expr_copied
1464 }
1465
1466 pub fn with_source_span_mut(&mut self, new_source_span: SourceSpan) {
1467 match self {
1468 Expr::Identifier { source_span, .. }
1469 | Expr::Let { source_span, .. }
1470 | Expr::SelectField { source_span, .. }
1471 | Expr::SelectIndex { source_span, .. }
1472 | Expr::Sequence { source_span, .. }
1473 | Expr::Record { source_span, .. }
1474 | Expr::Tuple { source_span, .. }
1475 | Expr::Literal { source_span, .. }
1476 | Expr::Number { source_span, .. }
1477 | Expr::Flags { source_span, .. }
1478 | Expr::Boolean { source_span, .. }
1479 | Expr::Concat { source_span, .. }
1480 | Expr::ExprBlock { source_span, .. }
1481 | Expr::Not { source_span, .. }
1482 | Expr::GreaterThan { source_span, .. }
1483 | Expr::GreaterThanOrEqualTo { source_span, .. }
1484 | Expr::LessThanOrEqualTo { source_span, .. }
1485 | Expr::EqualTo { source_span, .. }
1486 | Expr::LessThan { source_span, .. }
1487 | Expr::Plus { source_span, .. }
1488 | Expr::Minus { source_span, .. }
1489 | Expr::Divide { source_span, .. }
1490 | Expr::Multiply { source_span, .. }
1491 | Expr::Cond { source_span, .. }
1492 | Expr::PatternMatch { source_span, .. }
1493 | Expr::Option { source_span, .. }
1494 | Expr::Result { source_span, .. }
1495 | Expr::Unwrap { source_span, .. }
1496 | Expr::Throw { source_span, .. }
1497 | Expr::And { source_span, .. }
1498 | Expr::Or { source_span, .. }
1499 | Expr::GetTag { source_span, .. }
1500 | Expr::Range { source_span, .. }
1501 | Expr::ListComprehension { source_span, .. }
1502 | Expr::ListReduce { source_span, .. }
1503 | Expr::InvokeMethodLazy { source_span, .. }
1504 | Expr::Length { source_span, .. }
1505 | Expr::Call { source_span, .. } => {
1506 *source_span = new_source_span;
1507 }
1508 }
1509 }
1510
1511 pub fn with_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1512 let mut expr_copied = self.clone();
1513 expr_copied.with_inferred_type_mut(new_inferred_type);
1514 expr_copied
1515 }
1516
1517 pub fn with_inferred_type_mut(&mut self, new_inferred_type: InferredType) {
1520 match self {
1521 Expr::Identifier { inferred_type, .. }
1522 | Expr::Let { inferred_type, .. }
1523 | Expr::SelectField { inferred_type, .. }
1524 | Expr::SelectIndex { inferred_type, .. }
1525 | Expr::Sequence { inferred_type, .. }
1526 | Expr::Record { inferred_type, .. }
1527 | Expr::Tuple { inferred_type, .. }
1528 | Expr::Literal { inferred_type, .. }
1529 | Expr::Number { inferred_type, .. }
1530 | Expr::Flags { inferred_type, .. }
1531 | Expr::Boolean { inferred_type, .. }
1532 | Expr::Concat { inferred_type, .. }
1533 | Expr::ExprBlock { inferred_type, .. }
1534 | Expr::Not { inferred_type, .. }
1535 | Expr::GreaterThan { inferred_type, .. }
1536 | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1537 | Expr::LessThanOrEqualTo { inferred_type, .. }
1538 | Expr::EqualTo { inferred_type, .. }
1539 | Expr::LessThan { inferred_type, .. }
1540 | Expr::Plus { inferred_type, .. }
1541 | Expr::Minus { inferred_type, .. }
1542 | Expr::Divide { inferred_type, .. }
1543 | Expr::Multiply { inferred_type, .. }
1544 | Expr::Cond { inferred_type, .. }
1545 | Expr::PatternMatch { inferred_type, .. }
1546 | Expr::Option { inferred_type, .. }
1547 | Expr::Result { inferred_type, .. }
1548 | Expr::Unwrap { inferred_type, .. }
1549 | Expr::Throw { inferred_type, .. }
1550 | Expr::And { inferred_type, .. }
1551 | Expr::Or { inferred_type, .. }
1552 | Expr::GetTag { inferred_type, .. }
1553 | Expr::ListComprehension { inferred_type, .. }
1554 | Expr::ListReduce { inferred_type, .. }
1555 | Expr::InvokeMethodLazy { inferred_type, .. }
1556 | Expr::Range { inferred_type, .. }
1557 | Expr::Length { inferred_type, .. }
1558 | Expr::Call { inferred_type, .. } => {
1559 if new_inferred_type != InferredType::Unknown {
1560 *inferred_type = new_inferred_type;
1561 }
1562 }
1563 }
1564 }
1565
1566 pub fn infer_enums(&mut self, function_type_registry: &FunctionTypeRegistry) {
1567 type_inference::infer_enums(self, function_type_registry);
1568 }
1569
1570 pub fn infer_variants(&mut self, function_type_registry: &FunctionTypeRegistry) {
1571 type_inference::infer_variants(self, function_type_registry);
1572 }
1573
1574 pub fn visit_children_bottom_up<'a>(&'a self, queue: &mut VecDeque<&'a Expr>) {
1575 type_inference::visit_children_bottom_up(self, queue);
1576 }
1577
1578 pub fn visit_children_mut_top_down<'a>(&'a mut self, queue: &mut VecDeque<&'a mut Expr>) {
1579 type_inference::visit_children_mut_top_down(self, queue);
1580 }
1581
1582 pub fn visit_children_mut_bottom_up<'a>(&'a mut self, queue: &mut VecDeque<&'a mut Expr>) {
1583 type_inference::visit_children_bottom_up_mut(self, queue);
1584 }
1585
1586 pub fn number_inferred(
1587 big_decimal: BigDecimal,
1588 type_annotation: Option<TypeName>,
1589 inferred_type: InferredType,
1590 ) -> Expr {
1591 Expr::Number {
1592 number: Number { value: big_decimal },
1593 type_annotation,
1594 inferred_type,
1595 source_span: SourceSpan::default(),
1596 }
1597 }
1598
1599 pub fn number(big_decimal: BigDecimal) -> Expr {
1600 Expr::number_inferred(big_decimal, None, InferredType::number())
1601 }
1602}
1603
1604#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
1605pub enum Range {
1606 Range { from: Box<Expr>, to: Box<Expr> },
1607 RangeInclusive { from: Box<Expr>, to: Box<Expr> },
1608 RangeFrom { from: Box<Expr> },
1609}
1610
1611impl Range {
1612 pub fn from(&self) -> Option<&Expr> {
1613 match self {
1614 Range::Range { from, .. } => Some(from),
1615 Range::RangeInclusive { from, .. } => Some(from),
1616 Range::RangeFrom { from } => Some(from),
1617 }
1618 }
1619
1620 pub fn to(&self) -> Option<&Expr> {
1621 match self {
1622 Range::Range { to, .. } => Some(to),
1623 Range::RangeInclusive { to, .. } => Some(to),
1624 Range::RangeFrom { .. } => None,
1625 }
1626 }
1627
1628 pub fn inclusive(&self) -> bool {
1629 matches!(self, Range::RangeInclusive { .. })
1630 }
1631
1632 pub fn get_exprs_mut(&mut self) -> Vec<&mut Box<Expr>> {
1633 match self {
1634 Range::Range { from, to } => vec![from, to],
1635 Range::RangeInclusive { from, to } => vec![from, to],
1636 Range::RangeFrom { from } => vec![from],
1637 }
1638 }
1639
1640 pub fn get_exprs(&self) -> Vec<&Expr> {
1641 match self {
1642 Range::Range { from, to } => vec![from.as_ref(), to.as_ref()],
1643 Range::RangeInclusive { from, to } => vec![from.as_ref(), to.as_ref()],
1644 Range::RangeFrom { from } => vec![from.as_ref()],
1645 }
1646 }
1647}
1648
1649#[derive(Debug, Hash, Clone, PartialEq, Ord, PartialOrd)]
1650pub struct Number {
1651 pub value: BigDecimal,
1652}
1653
1654impl Eq for Number {}
1655
1656impl Number {
1657 pub fn to_val(&self, analysed_type: &AnalysedType) -> Option<ValueAndType> {
1658 match analysed_type {
1659 AnalysedType::F64(_) => self.value.to_f64().map(|v| v.into_value_and_type()),
1660 AnalysedType::U64(_) => self.value.to_u64().map(|v| v.into_value_and_type()),
1661 AnalysedType::F32(_) => self.value.to_f32().map(|v| v.into_value_and_type()),
1662 AnalysedType::U32(_) => self.value.to_u32().map(|v| v.into_value_and_type()),
1663 AnalysedType::S32(_) => self.value.to_i32().map(|v| v.into_value_and_type()),
1664 AnalysedType::S64(_) => self.value.to_i64().map(|v| v.into_value_and_type()),
1665 AnalysedType::U8(_) => self.value.to_u8().map(|v| v.into_value_and_type()),
1666 AnalysedType::S8(_) => self.value.to_i8().map(|v| v.into_value_and_type()),
1667 AnalysedType::U16(_) => self.value.to_u16().map(|v| v.into_value_and_type()),
1668 AnalysedType::S16(_) => self.value.to_i16().map(|v| v.into_value_and_type()),
1669 _ => None,
1670 }
1671 }
1672}
1673
1674impl Display for Number {
1675 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1676 write!(f, "{}", self.value)
1677 }
1678}
1679
1680#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1681pub struct MatchArm {
1682 pub arm_pattern: ArmPattern,
1683 pub arm_resolution_expr: Box<Expr>,
1684}
1685
1686impl MatchArm {
1687 pub fn new(arm_pattern: ArmPattern, arm_resolution: Expr) -> MatchArm {
1688 MatchArm {
1689 arm_pattern,
1690 arm_resolution_expr: Box::new(arm_resolution),
1691 }
1692 }
1693}
1694#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1695pub enum ArmPattern {
1696 WildCard,
1697 As(String, Box<ArmPattern>),
1698 Constructor(String, Vec<ArmPattern>),
1699 TupleConstructor(Vec<ArmPattern>),
1700 RecordConstructor(Vec<(String, ArmPattern)>),
1701 ListConstructor(Vec<ArmPattern>),
1702 Literal(Box<Expr>),
1703}
1704
1705impl ArmPattern {
1706 pub fn is_wildcard(&self) -> bool {
1707 matches!(self, ArmPattern::WildCard)
1708 }
1709
1710 pub fn is_literal_identifier(&self) -> bool {
1711 matches!(self, ArmPattern::Literal(expr) if expr.is_identifier())
1712 }
1713
1714 pub fn constructor(name: &str, patterns: Vec<ArmPattern>) -> ArmPattern {
1715 ArmPattern::Constructor(name.to_string(), patterns)
1716 }
1717
1718 pub fn literal(expr: Expr) -> ArmPattern {
1719 ArmPattern::Literal(Box::new(expr))
1720 }
1721
1722 pub fn get_expr_literals_mut(&mut self) -> Vec<&mut Box<Expr>> {
1723 match self {
1724 ArmPattern::Literal(expr) => vec![expr],
1725 ArmPattern::As(_, pattern) => pattern.get_expr_literals_mut(),
1726 ArmPattern::Constructor(_, patterns) => {
1727 let mut result = vec![];
1728 for pattern in patterns {
1729 result.extend(pattern.get_expr_literals_mut());
1730 }
1731 result
1732 }
1733 ArmPattern::TupleConstructor(patterns) => {
1734 let mut result = vec![];
1735 for pattern in patterns {
1736 result.extend(pattern.get_expr_literals_mut());
1737 }
1738 result
1739 }
1740 ArmPattern::RecordConstructor(patterns) => {
1741 let mut result = vec![];
1742 for (_, pattern) in patterns {
1743 result.extend(pattern.get_expr_literals_mut());
1744 }
1745 result
1746 }
1747 ArmPattern::ListConstructor(patterns) => {
1748 let mut result = vec![];
1749 for pattern in patterns {
1750 result.extend(pattern.get_expr_literals_mut());
1751 }
1752 result
1753 }
1754 ArmPattern::WildCard => vec![],
1755 }
1756 }
1757
1758 pub fn get_expr_literals(&self) -> Vec<&Expr> {
1759 match self {
1760 ArmPattern::Literal(expr) => vec![expr.as_ref()],
1761 ArmPattern::As(_, pattern) => pattern.get_expr_literals(),
1762 ArmPattern::Constructor(_, patterns) => {
1763 let mut result = vec![];
1764 for pattern in patterns {
1765 result.extend(pattern.get_expr_literals());
1766 }
1767 result
1768 }
1769 ArmPattern::TupleConstructor(patterns) => {
1770 let mut result = vec![];
1771 for pattern in patterns {
1772 result.extend(pattern.get_expr_literals());
1773 }
1774 result
1775 }
1776 ArmPattern::RecordConstructor(patterns) => {
1777 let mut result = vec![];
1778 for (_, pattern) in patterns {
1779 result.extend(pattern.get_expr_literals());
1780 }
1781 result
1782 }
1783 ArmPattern::ListConstructor(patterns) => {
1784 let mut result = vec![];
1785 for pattern in patterns {
1786 result.extend(pattern.get_expr_literals());
1787 }
1788 result
1789 }
1790 ArmPattern::WildCard => vec![],
1791 }
1792 }
1793 pub fn ok(binding_variable: &str) -> ArmPattern {
1795 ArmPattern::Literal(Box::new(Expr::Result {
1796 expr: Ok(Box::new(Expr::Identifier {
1797 variable_id: VariableId::global(binding_variable.to_string()),
1798 type_annotation: None,
1799 inferred_type: InferredType::Unknown,
1800 source_span: SourceSpan::default(),
1801 })),
1802 type_annotation: None,
1803 inferred_type: InferredType::Result {
1804 ok: Some(Box::new(InferredType::Unknown)),
1805 error: Some(Box::new(InferredType::Unknown)),
1806 },
1807 source_span: SourceSpan::default(),
1808 }))
1809 }
1810
1811 pub fn err(binding_variable: &str) -> ArmPattern {
1813 ArmPattern::Literal(Box::new(Expr::Result {
1814 expr: Err(Box::new(Expr::Identifier {
1815 variable_id: VariableId::global(binding_variable.to_string()),
1816 type_annotation: None,
1817 inferred_type: InferredType::Unknown,
1818 source_span: SourceSpan::default(),
1819 })),
1820 type_annotation: None,
1821 inferred_type: InferredType::Result {
1822 ok: Some(Box::new(InferredType::Unknown)),
1823 error: Some(Box::new(InferredType::Unknown)),
1824 },
1825 source_span: SourceSpan::default(),
1826 }))
1827 }
1828
1829 pub fn some(binding_variable: &str) -> ArmPattern {
1831 ArmPattern::Literal(Box::new(Expr::Option {
1832 expr: Some(Box::new(Expr::Identifier {
1833 variable_id: VariableId::local_with_no_id(binding_variable),
1834 type_annotation: None,
1835 inferred_type: InferredType::Unknown,
1836 source_span: SourceSpan::default(),
1837 })),
1838 type_annotation: None,
1839 inferred_type: InferredType::Unknown,
1840 source_span: SourceSpan::default(),
1841 }))
1842 }
1843
1844 pub fn none() -> ArmPattern {
1845 ArmPattern::Literal(Box::new(Expr::Option {
1846 expr: None,
1847 type_annotation: None,
1848 inferred_type: InferredType::Unknown,
1849 source_span: SourceSpan::default(),
1850 }))
1851 }
1852
1853 pub fn identifier(binding_variable: &str) -> ArmPattern {
1854 ArmPattern::Literal(Box::new(Expr::Identifier {
1855 variable_id: VariableId::global(binding_variable.to_string()),
1856 type_annotation: None,
1857 inferred_type: InferredType::Unknown,
1858 source_span: SourceSpan::default(),
1859 }))
1860 }
1861 pub fn custom_constructor(name: &str, args: Vec<ArmPattern>) -> ArmPattern {
1862 ArmPattern::Constructor(name.to_string(), args)
1863 }
1864}
1865
1866#[cfg(feature = "protobuf")]
1867impl TryFrom<golem_api_grpc::proto::golem::rib::Expr> for Expr {
1868 type Error = String;
1869
1870 fn try_from(value: golem_api_grpc::proto::golem::rib::Expr) -> Result<Self, Self::Error> {
1871 let expr = value.expr.ok_or("Missing expr")?;
1872
1873 let expr = match expr {
1874 golem_api_grpc::proto::golem::rib::expr::Expr::Let(expr) => {
1875 let name = expr.name;
1876 let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
1877 let expr_: golem_api_grpc::proto::golem::rib::Expr =
1878 *expr.expr.ok_or("Missing expr")?;
1879 let expr: Expr = expr_.try_into()?;
1880 Expr::let_binding(name, expr, type_annotation)
1881 }
1882
1883 golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(expr) => {
1884 let selection = *expr.expr.ok_or("Missing expr")?;
1885 let field = *expr.index.ok_or("Missing index")?;
1886 let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
1887
1888 Expr::select_index(selection.try_into()?, field.try_into()?)
1889 .with_type_annotation_opt(type_annotation)
1890 }
1891
1892 golem_api_grpc::proto::golem::rib::expr::Expr::Length(expr) => {
1893 let expr = expr.expr.ok_or("Missing expr")?;
1894 Expr::Length {
1895 expr: Box::new((*expr).try_into()?),
1896 type_annotation: None,
1897 inferred_type: InferredType::Unknown,
1898 source_span: SourceSpan::default(),
1899 }
1900 }
1901
1902 golem_api_grpc::proto::golem::rib::expr::Expr::Range(range) => {
1903 let range_expr = range.range_expr.ok_or("Missing range expr")?;
1904
1905 match range_expr {
1906 RangeExpr::RangeFrom(range_from) => {
1907 let from = range_from.from.ok_or("Missing from expr")?;
1908 Expr::range_from((*from).try_into()?)
1909 }
1910 RangeExpr::Range(range) => {
1911 let from = range.from.ok_or("Missing from expr")?;
1912 let to = range.to.ok_or("Missing to expr")?;
1913 Expr::range((*from).try_into()?, (*to).try_into()?)
1914 }
1915 RangeExpr::RangeInclusive(range_inclusive) => {
1916 let from = range_inclusive.from.ok_or("Missing from expr")?;
1917 let to = range_inclusive.to.ok_or("Missing to expr")?;
1918 Expr::range_inclusive((*from).try_into()?, (*to).try_into()?)
1919 }
1920 }
1921 }
1922
1923 golem_api_grpc::proto::golem::rib::expr::Expr::Not(expr) => {
1924 let expr = expr.expr.ok_or("Missing expr")?;
1925 Expr::not((*expr).try_into()?)
1926 }
1927
1928 golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(expr) => {
1929 let left = expr.left.ok_or("Missing left expr")?;
1930 let right = expr.right.ok_or("Missing right expr")?;
1931 Expr::greater_than((*left).try_into()?, (*right).try_into()?)
1932 }
1933
1934 golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(expr) => {
1935 let left = expr.left.ok_or("Missing left expr")?;
1936 let right = expr.right.ok_or("Missing right expr")?;
1937 Expr::greater_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
1938 }
1939
1940 golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(expr) => {
1941 let left = expr.left.ok_or("Missing left expr")?;
1942 let right = expr.right.ok_or("Missing right expr")?;
1943 Expr::less_than((*left).try_into()?, (*right).try_into()?)
1944 }
1945
1946 golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(expr) => {
1947 let left = expr.left.ok_or("Missing left expr")?;
1948 let right = expr.right.ok_or("Missing right expr")?;
1949 Expr::less_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
1950 }
1951
1952 golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(expr) => {
1953 let left = expr.left.ok_or("Missing left expr")?;
1954 let right = expr.right.ok_or("Missing right expr")?;
1955 Expr::equal_to((*left).try_into()?, (*right).try_into()?)
1956 }
1957
1958 golem_api_grpc::proto::golem::rib::expr::Expr::Add(expr) => {
1959 let left = expr.left.ok_or("Missing left expr")?;
1960 let right = expr.right.ok_or("Missing right expr")?;
1961 Expr::plus((*left).try_into()?, (*right).try_into()?)
1962 }
1963
1964 golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(expr) => {
1965 let left = expr.left.ok_or("Missing left expr")?;
1966 let right = expr.right.ok_or("Missing right expr")?;
1967 Expr::plus((*left).try_into()?, (*right).try_into()?)
1968 }
1969
1970 golem_api_grpc::proto::golem::rib::expr::Expr::Divide(expr) => {
1971 let left = expr.left.ok_or("Missing left expr")?;
1972 let right = expr.right.ok_or("Missing right expr")?;
1973 Expr::plus((*left).try_into()?, (*right).try_into()?)
1974 }
1975
1976 golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(expr) => {
1977 let left = expr.left.ok_or("Missing left expr")?;
1978 let right = expr.right.ok_or("Missing right expr")?;
1979 Expr::plus((*left).try_into()?, (*right).try_into()?)
1980 }
1981
1982 golem_api_grpc::proto::golem::rib::expr::Expr::Cond(expr) => {
1983 let left = expr.left.ok_or("Missing left expr")?;
1984 let cond = expr.cond.ok_or("Missing cond expr")?;
1985 let right = expr.right.ok_or("Missing right expr")?;
1986 Expr::cond(
1987 (*left).try_into()?,
1988 (*cond).try_into()?,
1989 (*right).try_into()?,
1990 )
1991 }
1992
1993 golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
1994 golem_api_grpc::proto::golem::rib::ConcatExpr { exprs },
1995 ) => {
1996 let exprs: Vec<Expr> = exprs
1997 .into_iter()
1998 .map(|expr| expr.try_into())
1999 .collect::<Result<Vec<_>, _>>()?;
2000 Expr::concat(exprs)
2001 }
2002
2003 golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2004 golem_api_grpc::proto::golem::rib::MultipleExpr { exprs },
2005 ) => {
2006 let exprs: Vec<Expr> = exprs
2007 .into_iter()
2008 .map(|expr| expr.try_into())
2009 .collect::<Result<Vec<_>, _>>()?;
2010 Expr::expr_block(exprs)
2011 }
2012
2013 golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2014 golem_api_grpc::proto::golem::rib::SequenceExpr { exprs, type_name },
2015 ) => {
2016 let type_annotation = type_name.map(TypeName::try_from).transpose()?;
2017
2018 let exprs: Vec<Expr> = exprs
2019 .into_iter()
2020 .map(|expr| expr.try_into())
2021 .collect::<Result<Vec<_>, _>>()?;
2022 Expr::sequence(exprs, type_annotation)
2023 }
2024
2025 golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2026 golem_api_grpc::proto::golem::rib::TupleExpr { exprs },
2027 ) => {
2028 let exprs: Vec<Expr> = exprs
2029 .into_iter()
2030 .map(|expr| expr.try_into())
2031 .collect::<Result<Vec<_>, _>>()?;
2032 Expr::tuple(exprs)
2033 }
2034
2035 golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2036 golem_api_grpc::proto::golem::rib::RecordExpr { fields },
2037 ) => {
2038 let mut values: Vec<(String, Expr)> = vec![];
2039 for record in fields.into_iter() {
2040 let name = record.name;
2041 let expr = record.expr.ok_or("Missing expr")?;
2042 values.push((name, expr.try_into()?));
2043 }
2044 Expr::record(values)
2045 }
2046
2047 golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2048 golem_api_grpc::proto::golem::rib::FlagsExpr { values },
2049 ) => Expr::flags(values),
2050
2051 golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2052 golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2053 ) => Expr::literal(value),
2054
2055 golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2056 golem_api_grpc::proto::golem::rib::IdentifierExpr { name, type_name },
2057 ) => {
2058 let type_name = type_name.map(TypeName::try_from).transpose()?;
2059
2060 Expr::identifier_global(name.as_str(), type_name)
2061 }
2062
2063 golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2064 golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2065 ) => Expr::boolean(value),
2066
2067 golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2068 golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2069 ) => Expr::throw(message),
2070
2071 golem_api_grpc::proto::golem::rib::expr::Expr::And(expr) => {
2072 let left = expr.left.ok_or("Missing left expr")?;
2073 let right = expr.right.ok_or("Missing right expr")?;
2074 Expr::and((*left).try_into()?, (*right).try_into()?)
2075 }
2076
2077 golem_api_grpc::proto::golem::rib::expr::Expr::Or(expr) => {
2078 let left = expr.left.ok_or("Missing left expr")?;
2079 let right = expr.right.ok_or("Missing right expr")?;
2080 Expr::or((*left).try_into()?, (*right).try_into()?)
2081 }
2082
2083 golem_api_grpc::proto::golem::rib::expr::Expr::Tag(expr) => {
2084 let expr = expr.expr.ok_or("Missing expr in tag")?;
2085 Expr::get_tag((*expr).try_into()?)
2086 }
2087
2088 golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(expr) => {
2089 let expr = expr.expr.ok_or("Missing expr")?;
2090 let expr: Expr = (*expr).try_into()?;
2091 expr.unwrap()
2092 }
2093
2094 golem_api_grpc::proto::golem::rib::expr::Expr::Number(number) => {
2095 let type_name = number.type_name.map(TypeName::try_from).transpose()?;
2097 let big_decimal = if let Some(number) = number.number {
2098 BigDecimal::from_str(&number).map_err(|e| e.to_string())?
2099 } else if let Some(float) = number.float {
2100 BigDecimal::from_f64(float).ok_or("Invalid float")?
2101 } else {
2102 return Err("Missing number".to_string());
2103 };
2104
2105 Expr::number(big_decimal).with_type_annotation_opt(type_name)
2106 }
2107 golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(expr) => {
2108 let expr = *expr;
2109 let field = expr.field;
2110 let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2111 let expr = *expr.expr.ok_or(
2112 "Mi\
2113 ssing expr",
2114 )?;
2115
2116 Expr::select_field(expr.try_into()?, field.as_str(), type_name)
2117 }
2118 golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndex(expr) => {
2119 let expr = *expr;
2120 let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2121 let index = expr.index as usize;
2122 let expr = *expr.expr.ok_or("Missing expr")?;
2123
2124 let index_expr =
2125 Expr::number(BigDecimal::from_usize(index).ok_or("Invalid index")?);
2126
2127 Expr::select_index(expr.try_into()?, index_expr).with_type_annotation_opt(type_name)
2128 }
2129 golem_api_grpc::proto::golem::rib::expr::Expr::Option(expr) => {
2130 let type_name = expr.type_name;
2131 let type_name = type_name.map(TypeName::try_from).transpose()?;
2132
2133 match expr.expr {
2134 Some(expr) => {
2135 Expr::option(Some((*expr).try_into()?)).with_type_annotation_opt(type_name)
2136 }
2137 None => Expr::option(None).with_type_annotation_opt(type_name),
2138 }
2139 }
2140 golem_api_grpc::proto::golem::rib::expr::Expr::Result(expr) => {
2141 let type_name = expr.type_name;
2142 let type_name = type_name.map(TypeName::try_from).transpose()?;
2143 let result = expr.result.ok_or("Missing result")?;
2144 match result {
2145 golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(expr) => {
2146 Expr::ok((*expr).try_into()?, type_name)
2147 }
2148 golem_api_grpc::proto::golem::rib::result_expr::Result::Err(expr) => {
2149 Expr::err((*expr).try_into()?, type_name)
2150 }
2151 }
2152 }
2153 golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(expr) => {
2154 let patterns: Vec<MatchArm> = expr
2155 .patterns
2156 .into_iter()
2157 .map(|expr| expr.try_into())
2158 .collect::<Result<Vec<_>, _>>()?;
2159 let expr = expr.expr.ok_or("Missing expr")?;
2160 Expr::pattern_match((*expr).try_into()?, patterns)
2161 }
2162 golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(
2163 list_comprehension,
2164 ) => {
2165 let iterable_expr = list_comprehension.iterable_expr.ok_or("Missing expr")?;
2166 let iterable_expr = (*iterable_expr).try_into()?;
2167 let yield_expr = list_comprehension.yield_expr.ok_or("Missing list")?;
2168 let yield_expr = (*yield_expr).try_into()?;
2169 let variable_id =
2170 VariableId::list_comprehension_identifier(list_comprehension.iterated_variable);
2171 Expr::list_comprehension(variable_id, iterable_expr, yield_expr)
2172 }
2173 golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(list_reduce) => {
2174 let init_value_expr = list_reduce.init_value_expr.ok_or("Missing initial expr")?;
2175 let init_value_expr = (*init_value_expr).try_into()?;
2176 let iterable_expr = list_reduce.iterable_expr.ok_or("Missing expr")?;
2177 let iterable_expr = (*iterable_expr).try_into()?;
2178 let yield_expr = list_reduce.yield_expr.ok_or("Missing list")?;
2179 let yield_expr = (*yield_expr).try_into()?;
2180 let iterated_variable_id =
2181 VariableId::list_comprehension_identifier(list_reduce.iterated_variable);
2182 let reduce_variable_id =
2183 VariableId::list_reduce_identifier(list_reduce.reduce_variable);
2184 Expr::list_reduce(
2185 reduce_variable_id,
2186 iterated_variable_id,
2187 iterable_expr,
2188 init_value_expr,
2189 yield_expr,
2190 )
2191 }
2192 golem_api_grpc::proto::golem::rib::expr::Expr::Call(expr) => {
2193 let params: Vec<Expr> = expr
2194 .params
2195 .into_iter()
2196 .map(|expr| expr.try_into())
2197 .collect::<Result<Vec<_>, _>>()?;
2198 let legacy_invocation_name = expr.name;
2200 let call_type = expr.call_type;
2201 let generic_type_parameter = expr
2202 .generic_type_parameter
2203 .map(|tp| GenericTypeParameter { value: tp });
2204
2205 match (legacy_invocation_name, call_type) {
2206 (Some(legacy), None) => {
2207 let name = legacy.name.ok_or("Missing function call name")?;
2208 match name {
2209 golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => {
2210 Expr::call_worker_function(DynamicParsedFunctionName::parse(
2212 ParsedFunctionName::try_from(name)?.to_string()
2213 )?, generic_type_parameter, None, params)
2214 }
2215 golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(
2216 name,
2217 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2218 golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(
2219 name,
2220 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2221 }
2222 }
2223 (_, Some(call_type)) => {
2224 let name = call_type.name.ok_or("Missing function call name")?;
2225 match name {
2226 golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => {
2227 Expr::call_worker_function(name.try_into()?, generic_type_parameter, None, params)
2228 }
2229 golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(
2230 name,
2231 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2232 golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(
2233 name,
2234 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2235 golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(instance_creation) => {
2236 let instance_creation_type = InstanceCreationType::try_from(*instance_creation)?;
2237 let call_type = CallType::InstanceCreation(instance_creation_type);
2238 Expr::Call {
2239 call_type,
2240 generic_type_parameter,
2241 args: vec![],
2242 inferred_type: InferredType::Unknown,
2243 source_span: SourceSpan::default(),
2244 type_annotation: None, }
2246 }
2247 }
2248 }
2249 (_, _) => Err("Missing both call type (and legacy invocation type)")?,
2250 }
2251 }
2252 golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(lazy_invoke) => {
2253 let lhs_proto = lazy_invoke.lhs.ok_or("Missing lhs")?;
2254 let lhs = Box::new((*lhs_proto).try_into()?);
2255 let method = lazy_invoke.method;
2256 let generic_type_parameter = lazy_invoke.generic_type_parameter;
2257 let args: Vec<Expr> = lazy_invoke
2258 .args
2259 .into_iter()
2260 .map(Expr::try_from)
2261 .collect::<Result<Vec<_>, _>>()?;
2262
2263 Expr::InvokeMethodLazy {
2264 lhs,
2265 method,
2266 generic_type_parameter: generic_type_parameter
2267 .map(|value| GenericTypeParameter { value }),
2268 args,
2269 inferred_type: InferredType::Unknown,
2270 source_span: SourceSpan::default(),
2271 type_annotation: None, }
2273 }
2274 };
2275 Ok(expr)
2276 }
2277}
2278
2279impl Display for Expr {
2280 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2281 write!(f, "{}", text::to_string(self).unwrap())
2282 }
2283}
2284
2285impl Display for ArmPattern {
2286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2287 write!(f, "{}", text::to_string_arm_pattern(self).unwrap())
2288 }
2289}
2290
2291impl<'de> Deserialize<'de> for Expr {
2292 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2293 where
2294 D: serde::Deserializer<'de>,
2295 {
2296 let value = serde_json::Value::deserialize(deserializer)?;
2297 match value {
2298 Value::String(expr_string) => match from_string(expr_string.as_str()) {
2299 Ok(expr) => Ok(expr),
2300 Err(message) => Err(serde::de::Error::custom(message.to_string())),
2301 },
2302
2303 e => Err(serde::de::Error::custom(format!(
2304 "Failed to deserialize expression {}",
2305 e
2306 ))),
2307 }
2308 }
2309}
2310
2311impl Serialize for Expr {
2312 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2313 where
2314 S: Serializer,
2315 {
2316 match text::to_string(self) {
2317 Ok(value) => serde_json::Value::serialize(&Value::String(value), serializer),
2318 Err(error) => Err(serde::ser::Error::custom(error.to_string())),
2319 }
2320 }
2321}
2322
2323#[cfg(feature = "protobuf")]
2324mod protobuf {
2325 use crate::{ArmPattern, Expr, MatchArm, Range};
2326 use golem_api_grpc::proto::golem::rib::range_expr::RangeExpr;
2327
2328 impl From<Expr> for golem_api_grpc::proto::golem::rib::Expr {
2329 fn from(value: Expr) -> Self {
2330 let expr = match value {
2331 Expr::Let {
2332 variable_id,
2333 type_annotation,
2334 expr,
2335 ..
2336 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Let(
2337 Box::new(golem_api_grpc::proto::golem::rib::LetExpr {
2338 name: variable_id.name().to_string(),
2339 expr: Some(Box::new((*expr).into())),
2340 type_name: type_annotation.map(|t| t.into()),
2341 }),
2342 )),
2343
2344 Expr::Length { expr, .. } => {
2345 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Length(
2346 Box::new(golem_api_grpc::proto::golem::rib::LengthExpr {
2347 expr: Some(Box::new((*expr).into())),
2348 }),
2349 ))
2350 }
2351
2352 Expr::SelectField {
2353 expr,
2354 field,
2355 type_annotation,
2356 ..
2357 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(
2358 Box::new(golem_api_grpc::proto::golem::rib::SelectFieldExpr {
2359 expr: Some(Box::new((*expr).into())),
2360 field,
2361 type_name: type_annotation.map(|t| t.into()),
2362 }),
2363 )),
2364
2365 Expr::Range { range, .. } => match range {
2366 Range::RangeFrom { from } => {
2367 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2368 Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2369 range_expr: Some(RangeExpr::RangeFrom(Box::new(
2370 golem_api_grpc::proto::golem::rib::RangeFrom {
2371 from: Some(Box::new((*from).into())),
2372 },
2373 ))),
2374 }),
2375 ))
2376 }
2377 Range::Range { from, to } => {
2378 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2379 Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2380 range_expr: Some(RangeExpr::Range(Box::new(
2381 golem_api_grpc::proto::golem::rib::Range {
2382 from: Some(Box::new((*from).into())),
2383 to: Some(Box::new((*to).into())),
2384 },
2385 ))),
2386 }),
2387 ))
2388 }
2389 Range::RangeInclusive { from, to } => {
2390 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2391 Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2392 range_expr: Some(RangeExpr::RangeInclusive(Box::new(
2393 golem_api_grpc::proto::golem::rib::RangeInclusive {
2394 from: Some(Box::new((*from).into())),
2395 to: Some(Box::new((*to).into())),
2396 },
2397 ))),
2398 }),
2399 ))
2400 }
2401 },
2402
2403 Expr::SelectIndex {
2404 expr,
2405 index,
2406 type_annotation,
2407 ..
2408 } => Some(
2409 golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(Box::new(
2410 golem_api_grpc::proto::golem::rib::SelectIndexExprV1 {
2411 expr: Some(Box::new((*expr).into())),
2412 index: Some(Box::new((*index).into())),
2413 type_name: type_annotation.map(|t| t.into()),
2414 },
2415 )),
2416 ),
2417
2418 Expr::Sequence {
2419 exprs: expressions,
2420 type_annotation,
2421 ..
2422 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2423 golem_api_grpc::proto::golem::rib::SequenceExpr {
2424 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2425 type_name: type_annotation.map(|t| t.into()),
2426 },
2427 )),
2428 Expr::Record { exprs: fields, .. } => {
2429 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2430 golem_api_grpc::proto::golem::rib::RecordExpr {
2431 fields: fields
2432 .into_iter()
2433 .map(|(name, expr)| {
2434 golem_api_grpc::proto::golem::rib::RecordFieldExpr {
2435 name,
2436 expr: Some((*expr).into()),
2437 }
2438 })
2439 .collect(),
2440 },
2441 ))
2442 }
2443 Expr::Tuple {
2444 exprs: expressions, ..
2445 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2446 golem_api_grpc::proto::golem::rib::TupleExpr {
2447 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2448 },
2449 )),
2450 Expr::Literal { value, .. } => {
2451 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2452 golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2453 ))
2454 }
2455 Expr::Number {
2456 number,
2457 type_annotation,
2458 ..
2459 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Number(
2460 golem_api_grpc::proto::golem::rib::NumberExpr {
2461 number: Some(number.value.to_string()),
2462 float: None,
2463 type_name: type_annotation.map(|t| t.into()),
2464 },
2465 )),
2466 Expr::Flags { flags, .. } => {
2467 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2468 golem_api_grpc::proto::golem::rib::FlagsExpr { values: flags },
2469 ))
2470 }
2471 Expr::Identifier {
2472 variable_id,
2473 type_annotation,
2474 ..
2475 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2476 golem_api_grpc::proto::golem::rib::IdentifierExpr {
2477 name: variable_id.name(),
2478 type_name: type_annotation.map(|t| t.into()),
2479 },
2480 )),
2481 Expr::Boolean { value, .. } => {
2482 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2483 golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2484 ))
2485 }
2486 Expr::Concat {
2487 exprs: expressions, ..
2488 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
2489 golem_api_grpc::proto::golem::rib::ConcatExpr {
2490 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2491 },
2492 )),
2493 Expr::ExprBlock {
2494 exprs: expressions, ..
2495 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2496 golem_api_grpc::proto::golem::rib::MultipleExpr {
2497 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2498 },
2499 )),
2500 Expr::Not { expr, .. } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Not(
2501 Box::new(golem_api_grpc::proto::golem::rib::NotExpr {
2502 expr: Some(Box::new((*expr).into())),
2503 }),
2504 )),
2505 Expr::GreaterThan {
2506 lhs: left,
2507 rhs: right,
2508 ..
2509 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(
2510 Box::new(golem_api_grpc::proto::golem::rib::GreaterThanExpr {
2511 left: Some(Box::new((*left).into())),
2512 right: Some(Box::new((*right).into())),
2513 }),
2514 )),
2515 Expr::GreaterThanOrEqualTo { lhs, rhs, .. } => Some(
2516 golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(Box::new(
2517 golem_api_grpc::proto::golem::rib::GreaterThanOrEqualToExpr {
2518 left: Some(Box::new((*lhs).into())),
2519 right: Some(Box::new((*rhs).into())),
2520 },
2521 )),
2522 ),
2523 Expr::LessThan {
2524 lhs: left,
2525 rhs: right,
2526 ..
2527 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(
2528 Box::new(golem_api_grpc::proto::golem::rib::LessThanExpr {
2529 left: Some(Box::new((*left).into())),
2530 right: Some(Box::new((*right).into())),
2531 }),
2532 )),
2533 Expr::Plus {
2534 lhs: left,
2535 rhs: right,
2536 ..
2537 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Add(
2538 Box::new(golem_api_grpc::proto::golem::rib::AddExpr {
2539 left: Some(Box::new((*left).into())),
2540 right: Some(Box::new((*right).into())),
2541 }),
2542 )),
2543 Expr::Minus {
2544 lhs: left,
2545 rhs: right,
2546 ..
2547 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(
2548 Box::new(golem_api_grpc::proto::golem::rib::SubtractExpr {
2549 left: Some(Box::new((*left).into())),
2550 right: Some(Box::new((*right).into())),
2551 }),
2552 )),
2553 Expr::Divide { lhs, rhs, .. } => {
2554 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Divide(
2555 Box::new(golem_api_grpc::proto::golem::rib::DivideExpr {
2556 left: Some(Box::new((*lhs).into())),
2557 right: Some(Box::new((*rhs).into())),
2558 }),
2559 ))
2560 }
2561 Expr::Multiply { lhs, rhs, .. } => {
2562 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(
2563 Box::new(golem_api_grpc::proto::golem::rib::MultiplyExpr {
2564 left: Some(Box::new((*lhs).into())),
2565 right: Some(Box::new((*rhs).into())),
2566 }),
2567 ))
2568 }
2569 Expr::LessThanOrEqualTo { lhs, rhs, .. } => Some(
2570 golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(Box::new(
2571 golem_api_grpc::proto::golem::rib::LessThanOrEqualToExpr {
2572 left: Some(Box::new((*lhs).into())),
2573 right: Some(Box::new((*rhs).into())),
2574 },
2575 )),
2576 ),
2577 Expr::EqualTo { lhs, rhs, .. } => {
2578 Some(golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(
2579 Box::new(golem_api_grpc::proto::golem::rib::EqualToExpr {
2580 left: Some(Box::new((*lhs).into())),
2581 right: Some(Box::new((*rhs).into())),
2582 }),
2583 ))
2584 }
2585 Expr::Cond {
2591 cond: lhs,
2592 lhs: cond,
2593 rhs,
2594 ..
2595 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Cond(
2596 Box::new(golem_api_grpc::proto::golem::rib::CondExpr {
2597 left: Some(Box::new((*lhs).into())),
2598 cond: Some(Box::new((*cond).into())),
2599 right: Some(Box::new((*rhs).into())),
2600 }),
2601 )),
2602 Expr::PatternMatch {
2603 predicate,
2604 match_arms,
2605 ..
2606 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(
2607 Box::new(golem_api_grpc::proto::golem::rib::PatternMatchExpr {
2608 expr: Some(Box::new((*predicate).into())),
2609 patterns: match_arms.into_iter().map(|a| a.into()).collect(),
2610 }),
2611 )),
2612 Expr::Option {
2613 expr,
2614 type_annotation,
2615 ..
2616 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Option(
2617 Box::new(golem_api_grpc::proto::golem::rib::OptionExpr {
2618 expr: expr.map(|expr| Box::new((*expr).into())),
2619 type_name: type_annotation.map(|t| t.into()),
2620 }),
2621 )),
2622 Expr::Result {
2623 expr,
2624 type_annotation,
2625 ..
2626 } => {
2627 let type_name = type_annotation.map(|t| t.into());
2628
2629 let result = match expr {
2630 Ok(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(
2631 Box::new((*expr).into()),
2632 ),
2633 Err(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Err(
2634 Box::new((*expr).into()),
2635 ),
2636 };
2637
2638 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Result(
2639 Box::new(golem_api_grpc::proto::golem::rib::ResultExpr {
2640 result: Some(result),
2641 type_name,
2642 }),
2643 ))
2644 }
2645 Expr::Call {
2646 call_type,
2647 generic_type_parameter,
2648 args,
2649 ..
2650 } => {
2651 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Call(
2652 Box::new(golem_api_grpc::proto::golem::rib::CallExpr {
2653 name: None, params: args.into_iter().map(|expr| expr.into()).collect(),
2655 generic_type_parameter: generic_type_parameter.map(|t| t.value),
2656 call_type: Some(Box::new(
2657 golem_api_grpc::proto::golem::rib::CallType::from(call_type),
2658 )),
2659 }),
2660 ))
2661 }
2662 Expr::Unwrap { expr, .. } => {
2663 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(
2664 Box::new(golem_api_grpc::proto::golem::rib::UnwrapExpr {
2665 expr: Some(Box::new((*expr).into())),
2666 }),
2667 ))
2668 }
2669 Expr::Throw { message, .. } => {
2670 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2671 golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2672 ))
2673 }
2674 Expr::GetTag { expr, .. } => {
2675 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tag(
2676 Box::new(golem_api_grpc::proto::golem::rib::GetTagExpr {
2677 expr: Some(Box::new((*expr).into())),
2678 }),
2679 ))
2680 }
2681 Expr::And { lhs, rhs, .. } => {
2682 Some(golem_api_grpc::proto::golem::rib::expr::Expr::And(
2683 Box::new(golem_api_grpc::proto::golem::rib::AndExpr {
2684 left: Some(Box::new((*lhs).into())),
2685 right: Some(Box::new((*rhs).into())),
2686 }),
2687 ))
2688 }
2689
2690 Expr::Or { lhs, rhs, .. } => {
2691 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Or(Box::new(
2692 golem_api_grpc::proto::golem::rib::OrExpr {
2693 left: Some(Box::new((*lhs).into())),
2694 right: Some(Box::new((*rhs).into())),
2695 },
2696 )))
2697 }
2698 Expr::ListComprehension {
2699 iterated_variable,
2700 iterable_expr,
2701 yield_expr,
2702 ..
2703 } => Some(
2704 golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(Box::new(
2705 golem_api_grpc::proto::golem::rib::ListComprehensionExpr {
2706 iterated_variable: iterated_variable.name(),
2707 iterable_expr: Some(Box::new((*iterable_expr).into())),
2708 yield_expr: Some(Box::new((*yield_expr).into())),
2709 },
2710 )),
2711 ),
2712
2713 Expr::ListReduce {
2714 reduce_variable,
2715 iterated_variable,
2716 iterable_expr,
2717 yield_expr,
2718 init_value_expr,
2719 ..
2720 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(
2721 Box::new(golem_api_grpc::proto::golem::rib::ListReduceExpr {
2722 reduce_variable: reduce_variable.name(),
2723 iterated_variable: iterated_variable.name(),
2724 iterable_expr: Some(Box::new((*iterable_expr).into())),
2725 init_value_expr: Some(Box::new((*init_value_expr).into())),
2726 yield_expr: Some(Box::new((*yield_expr).into())),
2727 }),
2728 )),
2729 Expr::InvokeMethodLazy {
2730 lhs,
2731 method,
2732 generic_type_parameter,
2733 args,
2734 ..
2735 } => Some(
2736 golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(Box::new(
2737 golem_api_grpc::proto::golem::rib::LazyInvokeMethodExpr {
2738 lhs: Some(Box::new((*lhs).into())),
2739 method,
2740 generic_type_parameter: generic_type_parameter.map(|t| t.value),
2741 args: args.into_iter().map(|expr| expr.into()).collect(),
2742 },
2743 )),
2744 ),
2745 };
2746
2747 golem_api_grpc::proto::golem::rib::Expr { expr }
2748 }
2749 }
2750
2751 impl TryFrom<golem_api_grpc::proto::golem::rib::ArmPattern> for ArmPattern {
2752 type Error = String;
2753
2754 fn try_from(
2755 value: golem_api_grpc::proto::golem::rib::ArmPattern,
2756 ) -> Result<Self, Self::Error> {
2757 let pattern = value.pattern.ok_or("Missing pattern")?;
2758 match pattern {
2759 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(_) => {
2760 Ok(ArmPattern::WildCard)
2761 }
2762 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(asp) => {
2763 let name = asp.name;
2764 let pattern = asp.pattern.ok_or("Missing pattern")?;
2765 Ok(ArmPattern::As(name, Box::new((*pattern).try_into()?)))
2766 }
2767 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
2768 golem_api_grpc::proto::golem::rib::ConstructorArmPattern { name, patterns },
2769 ) => {
2770 let patterns = patterns
2771 .into_iter()
2772 .map(ArmPattern::try_from)
2773 .collect::<Result<Vec<_>, _>>()?;
2774 Ok(ArmPattern::Constructor(name, patterns))
2775 }
2776 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
2777 golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern { patterns },
2778 ) => {
2779 let patterns = patterns
2780 .into_iter()
2781 .map(ArmPattern::try_from)
2782 .collect::<Result<Vec<_>, _>>()?;
2783 Ok(ArmPattern::TupleConstructor(patterns))
2784 }
2785 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
2786 golem_api_grpc::proto::golem::rib::LiteralArmPattern { expr },
2787 ) => {
2788 let inner = expr.ok_or("Missing expr")?;
2789 Ok(ArmPattern::Literal(Box::new(inner.try_into()?)))
2790 }
2791 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
2792 golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern { fields },
2793 ) => {
2794 let fields = fields
2795 .into_iter()
2796 .map(|field| {
2797 let name = field.name;
2798 let proto_pattern = field.pattern.ok_or("Missing pattern")?;
2799 let arm_pattern = ArmPattern::try_from(proto_pattern)?;
2800 Ok((name, arm_pattern))
2801 })
2802 .collect::<Result<Vec<_>, String>>()?;
2803 Ok(ArmPattern::RecordConstructor(fields))
2804 }
2805 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
2806 golem_api_grpc::proto::golem::rib::ListConstructorArmPattern { patterns },
2807 ) => {
2808 let patterns = patterns
2809 .into_iter()
2810 .map(ArmPattern::try_from)
2811 .collect::<Result<Vec<_>, _>>()?;
2812 Ok(ArmPattern::ListConstructor(patterns))
2813 }
2814 }
2815 }
2816 }
2817
2818 impl From<ArmPattern> for golem_api_grpc::proto::golem::rib::ArmPattern {
2819 fn from(value: ArmPattern) -> Self {
2820 match value {
2821 ArmPattern::WildCard => golem_api_grpc::proto::golem::rib::ArmPattern {
2822 pattern: Some(
2823 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(
2824 golem_api_grpc::proto::golem::rib::WildCardArmPattern {},
2825 ),
2826 ),
2827 },
2828 ArmPattern::As(name, pattern) => golem_api_grpc::proto::golem::rib::ArmPattern {
2829 pattern: Some(golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(
2830 Box::new(golem_api_grpc::proto::golem::rib::AsArmPattern {
2831 name,
2832 pattern: Some(Box::new((*pattern).into())),
2833 }),
2834 )),
2835 },
2836 ArmPattern::Constructor(name, patterns) => {
2837 golem_api_grpc::proto::golem::rib::ArmPattern {
2838 pattern: Some(
2839 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
2840 golem_api_grpc::proto::golem::rib::ConstructorArmPattern {
2841 name,
2842 patterns: patterns
2843 .into_iter()
2844 .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
2845 .collect(),
2846 },
2847 ),
2848 ),
2849 }
2850 }
2851 ArmPattern::Literal(expr) => golem_api_grpc::proto::golem::rib::ArmPattern {
2852 pattern: Some(
2853 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
2854 golem_api_grpc::proto::golem::rib::LiteralArmPattern {
2855 expr: Some((*expr).into()),
2856 },
2857 ),
2858 ),
2859 },
2860
2861 ArmPattern::TupleConstructor(patterns) => {
2862 golem_api_grpc::proto::golem::rib::ArmPattern {
2863 pattern: Some(
2864 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
2865 golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern {
2866 patterns: patterns
2867 .into_iter()
2868 .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
2869 .collect(),
2870 },
2871 ),
2872 ),
2873 }
2874 }
2875
2876 ArmPattern::RecordConstructor(fields) => {
2877 golem_api_grpc::proto::golem::rib::ArmPattern {
2878 pattern: Some(
2879 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
2880 golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern {
2881 fields: fields
2882 .into_iter()
2883 .map(|(name, pattern)| {
2884 golem_api_grpc::proto::golem::rib::RecordFieldArmPattern {
2885 name,
2886 pattern: Some(pattern.into()),
2887 }
2888 })
2889 .collect(),
2890 },
2891 ),
2892 ),
2893 }
2894 }
2895
2896 ArmPattern::ListConstructor(patterns) => {
2897 golem_api_grpc::proto::golem::rib::ArmPattern {
2898 pattern: Some(
2899 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
2900 golem_api_grpc::proto::golem::rib::ListConstructorArmPattern {
2901 patterns: patterns
2902 .into_iter()
2903 .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
2904 .collect(),
2905 },
2906 ),
2907 ),
2908 }
2909 }
2910 }
2911 }
2912 }
2913
2914 impl TryFrom<golem_api_grpc::proto::golem::rib::MatchArm> for MatchArm {
2915 type Error = String;
2916
2917 fn try_from(
2918 value: golem_api_grpc::proto::golem::rib::MatchArm,
2919 ) -> Result<Self, Self::Error> {
2920 let pattern = value.pattern.ok_or("Missing pattern")?;
2921 let expr = value.expr.ok_or("Missing expr")?;
2922 Ok(MatchArm::new(pattern.try_into()?, expr.try_into()?))
2923 }
2924 }
2925
2926 impl From<MatchArm> for golem_api_grpc::proto::golem::rib::MatchArm {
2927 fn from(value: MatchArm) -> Self {
2928 let MatchArm {
2929 arm_pattern,
2930 arm_resolution_expr,
2931 } = value;
2932 golem_api_grpc::proto::golem::rib::MatchArm {
2933 pattern: Some(arm_pattern.into()),
2934 expr: Some((*arm_resolution_expr).into()),
2935 }
2936 }
2937 }
2938}
2939
2940#[cfg(test)]
2941mod tests {
2942 use bigdecimal::BigDecimal;
2943 use test_r::test;
2944
2945 use crate::ParsedFunctionSite::PackagedInterface;
2946 use crate::{
2947 ArmPattern, DynamicParsedFunctionName, DynamicParsedFunctionReference, Expr, MatchArm,
2948 };
2949
2950 #[test]
2951 fn test_single_expr_in_interpolation_wrapped_in_quotes() {
2952 let input = r#""${foo}""#;
2953 let result = Expr::from_text(input);
2954 assert_eq!(
2955 result,
2956 Ok(Expr::concat(vec![Expr::identifier_global("foo", None)]))
2957 );
2958
2959 let input = r#""${{foo}}""#;
2960 let result = Expr::from_text(input);
2961 assert_eq!(
2962 result,
2963 Ok(Expr::concat(vec![Expr::flags(vec!["foo".to_string()])]))
2964 );
2965
2966 let input = r#""${{foo: "bar"}}""#;
2967 let result = Expr::from_text(input);
2968 assert_eq!(
2969 result,
2970 Ok(Expr::concat(vec![Expr::record(vec![(
2971 "foo".to_string(),
2972 Expr::literal("bar")
2973 )])]))
2974 );
2975 }
2976
2977 fn expected() -> Expr {
2978 Expr::expr_block(vec![
2979 Expr::let_binding("x", Expr::number(BigDecimal::from(1)), None),
2980 Expr::let_binding("y", Expr::number(BigDecimal::from(2)), None),
2981 Expr::let_binding(
2982 "result",
2983 Expr::greater_than(
2984 Expr::identifier_global("x", None),
2985 Expr::identifier_global("y", None),
2986 ),
2987 None,
2988 ),
2989 Expr::let_binding(
2990 "foo",
2991 Expr::option(Some(Expr::identifier_global("result", None))),
2992 None,
2993 ),
2994 Expr::let_binding(
2995 "bar",
2996 Expr::ok(Expr::identifier_global("result", None), None),
2997 None,
2998 ),
2999 Expr::let_binding(
3000 "baz",
3001 Expr::pattern_match(
3002 Expr::identifier_global("foo", None),
3003 vec![
3004 MatchArm::new(
3005 ArmPattern::constructor(
3006 "some",
3007 vec![ArmPattern::Literal(Box::new(Expr::identifier_global(
3008 "x", None,
3009 )))],
3010 ),
3011 Expr::identifier_global("x", None),
3012 ),
3013 MatchArm::new(
3014 ArmPattern::constructor("none", vec![]),
3015 Expr::boolean(false),
3016 ),
3017 ],
3018 ),
3019 None,
3020 ),
3021 Expr::let_binding(
3022 "qux",
3023 Expr::pattern_match(
3024 Expr::identifier_global("bar", None),
3025 vec![
3026 MatchArm::new(
3027 ArmPattern::constructor(
3028 "ok",
3029 vec![ArmPattern::Literal(Box::new(Expr::identifier_global(
3030 "x", None,
3031 )))],
3032 ),
3033 Expr::identifier_global("x", None),
3034 ),
3035 MatchArm::new(
3036 ArmPattern::constructor(
3037 "err",
3038 vec![ArmPattern::Literal(Box::new(Expr::identifier_global(
3039 "msg", None,
3040 )))],
3041 ),
3042 Expr::boolean(false),
3043 ),
3044 ],
3045 ),
3046 None,
3047 ),
3048 Expr::let_binding(
3049 "result",
3050 Expr::call_worker_function(
3051 DynamicParsedFunctionName {
3052 site: PackagedInterface {
3053 namespace: "ns".to_string(),
3054 package: "name".to_string(),
3055 interface: "interface".to_string(),
3056 version: None,
3057 },
3058 function: DynamicParsedFunctionReference::RawResourceStaticMethod {
3059 resource: "resource1".to_string(),
3060 method: "do-something-static".to_string(),
3061 },
3062 },
3063 None,
3064 None,
3065 vec![
3066 Expr::identifier_global("baz", None),
3067 Expr::identifier_global("qux", None),
3068 ],
3069 ),
3070 None,
3071 ),
3072 Expr::identifier_global("result", None),
3073 ])
3074 }
3075
3076 #[test]
3077 fn test_rib() {
3078 let sample_rib = r#"
3079 let x = 1;
3080 let y = 2;
3081 let result = x > y;
3082 let foo = some(result);
3083 let bar = ok(result);
3084
3085 let baz = match foo {
3086 some(x) => x,
3087 none => false
3088 };
3089
3090 let qux = match bar {
3091 ok(x) => x,
3092 err(msg) => false
3093 };
3094
3095 let result = ns:name/interface.{[static]resource1.do-something-static}(baz, qux);
3096
3097 result
3098 "#;
3099
3100 let result = Expr::from_text(sample_rib);
3101 assert_eq!(result, Ok(expected()));
3102 }
3103}