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
1121 Ok(())
1122 }
1123
1124 pub fn resolve_method_calls(&mut self) -> Result<(), RibCompilationError> {
1125 self.bind_instance_types();
1126 self.infer_worker_function_invokes()?;
1127 Ok(())
1128 }
1129
1130 pub fn inference_scan(&mut self) -> Result<(), RibCompilationError> {
1134 self.infer_all_identifiers();
1135 self.push_types_down()?;
1136 self.infer_all_identifiers();
1137 let expr = self.pull_types_up()?;
1138 *self = expr;
1139 self.infer_global_inputs();
1140 Ok(())
1141 }
1142
1143 pub fn infer_orphan_literals(&mut self) -> Result<(), RibCompilationError> {
1144 type_inference::infer_orphan_literals(self)
1145 }
1146
1147 pub fn infer_worker_function_invokes(&mut self) -> Result<(), RibCompilationError> {
1148 type_inference::infer_worker_function_invokes(self)
1149 }
1150
1151 pub fn bind_default_types_to_index_expressions(&mut self) {
1152 type_inference::bind_default_types_to_index_expressions(self);
1153 }
1154
1155 pub fn bind_variables_of_pattern_match(&mut self) {
1159 type_inference::bind_variables_of_pattern_match(self);
1160 }
1161
1162 pub fn bind_variables_of_let_assignment(&mut self) {
1166 type_inference::bind_variables_of_let_assignment(self);
1167 }
1168
1169 pub fn bind_variables_of_list_comprehension(&mut self) {
1170 type_inference::bind_variables_of_list_comprehension(self);
1171 }
1172
1173 pub fn bind_variables_of_list_reduce(&mut self) {
1174 type_inference::bind_variables_of_list_reduce(self);
1175 }
1176
1177 pub fn identify_instance_creation(
1178 &mut self,
1179 function_type_registry: &FunctionTypeRegistry,
1180 ) -> Result<(), RibCompilationError> {
1181 type_inference::identify_instance_creation(self, function_type_registry)
1182 }
1183
1184 pub fn infer_function_call_types(
1185 &mut self,
1186 function_type_registry: &FunctionTypeRegistry,
1187 ) -> Result<(), RibCompilationError> {
1188 type_inference::infer_function_call_types(self, function_type_registry)?;
1189 Ok(())
1190 }
1191
1192 pub fn push_types_down(&mut self) -> Result<(), RibCompilationError> {
1193 type_inference::push_types_down(self)
1194 }
1195
1196 pub fn infer_all_identifiers(&mut self) {
1197 type_inference::infer_all_identifiers(self)
1198 }
1199
1200 pub fn pull_types_up(&self) -> Result<Expr, RibCompilationError> {
1201 type_inference::type_pull_up(self)
1202 }
1203
1204 pub fn infer_global_inputs(&mut self) {
1205 type_inference::infer_global_inputs(self);
1206 }
1207
1208 pub fn bind_type_annotations(&mut self) {
1209 type_inference::bind_type_annotations(self);
1210 }
1211
1212 pub fn check_types(
1213 &mut self,
1214 function_type_registry: &FunctionTypeRegistry,
1215 ) -> Result<(), RibCompilationError> {
1216 type_checker::type_check(self, function_type_registry)
1217 }
1218
1219 pub fn unify_types(&mut self) -> Result<(), RibCompilationError> {
1220 type_inference::unify_types(self)?;
1221 Ok(())
1222 }
1223
1224 pub fn merge_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1225 let mut expr_copied = self.clone();
1226 expr_copied.add_infer_type_mut(new_inferred_type);
1227 expr_copied
1228 }
1229
1230 pub fn add_infer_type_mut(&mut self, new_inferred_type: InferredType) {
1231 match self {
1232 Expr::Identifier { inferred_type, .. }
1233 | Expr::Let { inferred_type, .. }
1234 | Expr::SelectField { inferred_type, .. }
1235 | Expr::SelectIndex { inferred_type, .. }
1236 | Expr::Sequence { inferred_type, .. }
1237 | Expr::Record { inferred_type, .. }
1238 | Expr::Tuple { inferred_type, .. }
1239 | Expr::Literal { inferred_type, .. }
1240 | Expr::Number { inferred_type, .. }
1241 | Expr::Flags { inferred_type, .. }
1242 | Expr::Boolean { inferred_type, .. }
1243 | Expr::Concat { inferred_type, .. }
1244 | Expr::ExprBlock { inferred_type, .. }
1245 | Expr::Not { inferred_type, .. }
1246 | Expr::GreaterThan { inferred_type, .. }
1247 | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1248 | Expr::LessThanOrEqualTo { inferred_type, .. }
1249 | Expr::EqualTo { inferred_type, .. }
1250 | Expr::Plus { inferred_type, .. }
1251 | Expr::Minus { inferred_type, .. }
1252 | Expr::Divide { inferred_type, .. }
1253 | Expr::Multiply { inferred_type, .. }
1254 | Expr::LessThan { inferred_type, .. }
1255 | Expr::Cond { inferred_type, .. }
1256 | Expr::PatternMatch { inferred_type, .. }
1257 | Expr::Option { inferred_type, .. }
1258 | Expr::Result { inferred_type, .. }
1259 | Expr::Unwrap { inferred_type, .. }
1260 | Expr::Throw { inferred_type, .. }
1261 | Expr::GetTag { inferred_type, .. }
1262 | Expr::And { inferred_type, .. }
1263 | Expr::Or { inferred_type, .. }
1264 | Expr::ListComprehension { inferred_type, .. }
1265 | Expr::ListReduce { inferred_type, .. }
1266 | Expr::InvokeMethodLazy { inferred_type, .. }
1267 | Expr::Range { inferred_type, .. }
1268 | Expr::Length { inferred_type, .. }
1269 | Expr::Call { inferred_type, .. } => {
1270 if new_inferred_type != InferredType::Unknown {
1271 *inferred_type = inferred_type.merge(new_inferred_type);
1272 }
1273 }
1274 }
1275 }
1276
1277 pub fn reset_type(&mut self) {
1278 type_inference::reset_type_info(self);
1279 }
1280
1281 pub fn source_span(&self) -> SourceSpan {
1282 match self {
1283 Expr::Identifier { source_span, .. }
1284 | Expr::Let { source_span, .. }
1285 | Expr::SelectField { source_span, .. }
1286 | Expr::SelectIndex { source_span, .. }
1287 | Expr::Sequence { source_span, .. }
1288 | Expr::Record { source_span, .. }
1289 | Expr::Tuple { source_span, .. }
1290 | Expr::Literal { source_span, .. }
1291 | Expr::Number { source_span, .. }
1292 | Expr::Flags { source_span, .. }
1293 | Expr::Boolean { source_span, .. }
1294 | Expr::Concat { source_span, .. }
1295 | Expr::ExprBlock { source_span, .. }
1296 | Expr::Not { source_span, .. }
1297 | Expr::GreaterThan { source_span, .. }
1298 | Expr::GreaterThanOrEqualTo { source_span, .. }
1299 | Expr::LessThanOrEqualTo { source_span, .. }
1300 | Expr::EqualTo { source_span, .. }
1301 | Expr::LessThan { source_span, .. }
1302 | Expr::Plus { source_span, .. }
1303 | Expr::Minus { source_span, .. }
1304 | Expr::Divide { source_span, .. }
1305 | Expr::Multiply { source_span, .. }
1306 | Expr::Cond { source_span, .. }
1307 | Expr::PatternMatch { source_span, .. }
1308 | Expr::Option { source_span, .. }
1309 | Expr::Result { source_span, .. }
1310 | Expr::Unwrap { source_span, .. }
1311 | Expr::Throw { source_span, .. }
1312 | Expr::And { source_span, .. }
1313 | Expr::Or { source_span, .. }
1314 | Expr::GetTag { source_span, .. }
1315 | Expr::ListComprehension { source_span, .. }
1316 | Expr::ListReduce { source_span, .. }
1317 | Expr::InvokeMethodLazy { source_span, .. }
1318 | Expr::Range { source_span, .. }
1319 | Expr::Length { source_span, .. }
1320 | Expr::Call { source_span, .. } => source_span.clone(),
1321 }
1322 }
1323
1324 pub fn with_type_annotation_opt(&self, type_annotation: Option<TypeName>) -> Expr {
1325 if let Some(type_annotation) = type_annotation {
1326 self.with_type_annotation(type_annotation)
1327 } else {
1328 self.clone()
1329 }
1330 }
1331
1332 pub fn with_type_annotation(&self, type_annotation: TypeName) -> Expr {
1333 let mut expr_copied = self.clone();
1334 expr_copied.with_type_annotation_mut(type_annotation);
1335 expr_copied
1336 }
1337
1338 pub fn with_type_annotation_mut(&mut self, type_annotation: TypeName) {
1339 let new_type_annotation = type_annotation;
1340
1341 match self {
1342 Expr::Identifier {
1343 type_annotation, ..
1344 }
1345 | Expr::Let {
1346 type_annotation, ..
1347 }
1348 | Expr::SelectField {
1349 type_annotation, ..
1350 }
1351 | Expr::SelectIndex {
1352 type_annotation, ..
1353 }
1354 | Expr::Sequence {
1355 type_annotation, ..
1356 }
1357 | Expr::Record {
1358 type_annotation, ..
1359 }
1360 | Expr::Tuple {
1361 type_annotation, ..
1362 }
1363 | Expr::Literal {
1364 type_annotation, ..
1365 }
1366 | Expr::Number {
1367 type_annotation, ..
1368 }
1369 | Expr::Flags {
1370 type_annotation, ..
1371 }
1372 | Expr::Boolean {
1373 type_annotation, ..
1374 }
1375 | Expr::Concat {
1376 type_annotation, ..
1377 }
1378 | Expr::ExprBlock {
1379 type_annotation, ..
1380 }
1381 | Expr::Not {
1382 type_annotation, ..
1383 }
1384 | Expr::GreaterThan {
1385 type_annotation, ..
1386 }
1387 | Expr::GreaterThanOrEqualTo {
1388 type_annotation, ..
1389 }
1390 | Expr::LessThanOrEqualTo {
1391 type_annotation, ..
1392 }
1393 | Expr::EqualTo {
1394 type_annotation, ..
1395 }
1396 | Expr::LessThan {
1397 type_annotation, ..
1398 }
1399 | Expr::Plus {
1400 type_annotation, ..
1401 }
1402 | Expr::Minus {
1403 type_annotation, ..
1404 }
1405 | Expr::Divide {
1406 type_annotation, ..
1407 }
1408 | Expr::Multiply {
1409 type_annotation, ..
1410 }
1411 | Expr::Cond {
1412 type_annotation, ..
1413 }
1414 | Expr::PatternMatch {
1415 type_annotation, ..
1416 }
1417 | Expr::Option {
1418 type_annotation, ..
1419 }
1420 | Expr::Result {
1421 type_annotation, ..
1422 }
1423 | Expr::Unwrap {
1424 type_annotation, ..
1425 }
1426 | Expr::Throw {
1427 type_annotation, ..
1428 }
1429 | Expr::And {
1430 type_annotation, ..
1431 }
1432 | Expr::Or {
1433 type_annotation, ..
1434 }
1435 | Expr::GetTag {
1436 type_annotation, ..
1437 }
1438 | Expr::Range {
1439 type_annotation, ..
1440 }
1441 | Expr::ListComprehension {
1442 type_annotation, ..
1443 }
1444 | Expr::ListReduce {
1445 type_annotation, ..
1446 }
1447 | Expr::InvokeMethodLazy {
1448 type_annotation, ..
1449 }
1450 | Expr::Length {
1451 type_annotation, ..
1452 }
1453 | Expr::Call {
1454 type_annotation, ..
1455 } => {
1456 *type_annotation = Some(new_type_annotation);
1457 }
1458 }
1459 }
1460
1461 pub fn with_source_span(&self, new_source_span: SourceSpan) -> Expr {
1462 let mut expr_copied = self.clone();
1463 expr_copied.with_source_span_mut(new_source_span);
1464 expr_copied
1465 }
1466
1467 pub fn with_source_span_mut(&mut self, new_source_span: SourceSpan) {
1468 match self {
1469 Expr::Identifier { source_span, .. }
1470 | Expr::Let { source_span, .. }
1471 | Expr::SelectField { source_span, .. }
1472 | Expr::SelectIndex { source_span, .. }
1473 | Expr::Sequence { source_span, .. }
1474 | Expr::Record { source_span, .. }
1475 | Expr::Tuple { source_span, .. }
1476 | Expr::Literal { source_span, .. }
1477 | Expr::Number { source_span, .. }
1478 | Expr::Flags { source_span, .. }
1479 | Expr::Boolean { source_span, .. }
1480 | Expr::Concat { source_span, .. }
1481 | Expr::ExprBlock { source_span, .. }
1482 | Expr::Not { source_span, .. }
1483 | Expr::GreaterThan { source_span, .. }
1484 | Expr::GreaterThanOrEqualTo { source_span, .. }
1485 | Expr::LessThanOrEqualTo { source_span, .. }
1486 | Expr::EqualTo { source_span, .. }
1487 | Expr::LessThan { source_span, .. }
1488 | Expr::Plus { source_span, .. }
1489 | Expr::Minus { source_span, .. }
1490 | Expr::Divide { source_span, .. }
1491 | Expr::Multiply { source_span, .. }
1492 | Expr::Cond { source_span, .. }
1493 | Expr::PatternMatch { source_span, .. }
1494 | Expr::Option { source_span, .. }
1495 | Expr::Result { source_span, .. }
1496 | Expr::Unwrap { source_span, .. }
1497 | Expr::Throw { source_span, .. }
1498 | Expr::And { source_span, .. }
1499 | Expr::Or { source_span, .. }
1500 | Expr::GetTag { source_span, .. }
1501 | Expr::Range { source_span, .. }
1502 | Expr::ListComprehension { source_span, .. }
1503 | Expr::ListReduce { source_span, .. }
1504 | Expr::InvokeMethodLazy { source_span, .. }
1505 | Expr::Length { source_span, .. }
1506 | Expr::Call { source_span, .. } => {
1507 *source_span = new_source_span;
1508 }
1509 }
1510 }
1511
1512 pub fn with_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1513 let mut expr_copied = self.clone();
1514 expr_copied.with_inferred_type_mut(new_inferred_type);
1515 expr_copied
1516 }
1517
1518 pub fn with_inferred_type_mut(&mut self, new_inferred_type: InferredType) {
1521 match self {
1522 Expr::Identifier { inferred_type, .. }
1523 | Expr::Let { inferred_type, .. }
1524 | Expr::SelectField { inferred_type, .. }
1525 | Expr::SelectIndex { inferred_type, .. }
1526 | Expr::Sequence { inferred_type, .. }
1527 | Expr::Record { inferred_type, .. }
1528 | Expr::Tuple { inferred_type, .. }
1529 | Expr::Literal { inferred_type, .. }
1530 | Expr::Number { inferred_type, .. }
1531 | Expr::Flags { inferred_type, .. }
1532 | Expr::Boolean { inferred_type, .. }
1533 | Expr::Concat { inferred_type, .. }
1534 | Expr::ExprBlock { inferred_type, .. }
1535 | Expr::Not { inferred_type, .. }
1536 | Expr::GreaterThan { inferred_type, .. }
1537 | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1538 | Expr::LessThanOrEqualTo { inferred_type, .. }
1539 | Expr::EqualTo { inferred_type, .. }
1540 | Expr::LessThan { inferred_type, .. }
1541 | Expr::Plus { inferred_type, .. }
1542 | Expr::Minus { inferred_type, .. }
1543 | Expr::Divide { inferred_type, .. }
1544 | Expr::Multiply { inferred_type, .. }
1545 | Expr::Cond { inferred_type, .. }
1546 | Expr::PatternMatch { inferred_type, .. }
1547 | Expr::Option { inferred_type, .. }
1548 | Expr::Result { inferred_type, .. }
1549 | Expr::Unwrap { inferred_type, .. }
1550 | Expr::Throw { inferred_type, .. }
1551 | Expr::And { inferred_type, .. }
1552 | Expr::Or { inferred_type, .. }
1553 | Expr::GetTag { inferred_type, .. }
1554 | Expr::ListComprehension { inferred_type, .. }
1555 | Expr::ListReduce { inferred_type, .. }
1556 | Expr::InvokeMethodLazy { inferred_type, .. }
1557 | Expr::Range { inferred_type, .. }
1558 | Expr::Length { inferred_type, .. }
1559 | Expr::Call { inferred_type, .. } => {
1560 if new_inferred_type != InferredType::Unknown {
1561 *inferred_type = new_inferred_type;
1562 }
1563 }
1564 }
1565 }
1566
1567 pub fn infer_enums(&mut self, function_type_registry: &FunctionTypeRegistry) {
1568 type_inference::infer_enums(self, function_type_registry);
1569 }
1570
1571 pub fn infer_variants(&mut self, function_type_registry: &FunctionTypeRegistry) {
1572 type_inference::infer_variants(self, function_type_registry);
1573 }
1574
1575 pub fn visit_children_bottom_up<'a>(&'a self, queue: &mut VecDeque<&'a Expr>) {
1576 type_inference::visit_children_bottom_up(self, queue);
1577 }
1578
1579 pub fn visit_children_mut_top_down<'a>(&'a mut self, queue: &mut VecDeque<&'a mut Expr>) {
1580 type_inference::visit_children_mut_top_down(self, queue);
1581 }
1582
1583 pub fn visit_children_mut_bottom_up<'a>(&'a mut self, queue: &mut VecDeque<&'a mut Expr>) {
1584 type_inference::visit_children_bottom_up_mut(self, queue);
1585 }
1586
1587 pub fn number_inferred(
1588 big_decimal: BigDecimal,
1589 type_annotation: Option<TypeName>,
1590 inferred_type: InferredType,
1591 ) -> Expr {
1592 Expr::Number {
1593 number: Number { value: big_decimal },
1594 type_annotation,
1595 inferred_type,
1596 source_span: SourceSpan::default(),
1597 }
1598 }
1599
1600 pub fn number(big_decimal: BigDecimal) -> Expr {
1601 Expr::number_inferred(big_decimal, None, InferredType::number())
1602 }
1603}
1604
1605#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
1606pub enum Range {
1607 Range { from: Box<Expr>, to: Box<Expr> },
1608 RangeInclusive { from: Box<Expr>, to: Box<Expr> },
1609 RangeFrom { from: Box<Expr> },
1610}
1611
1612impl Range {
1613 pub fn from(&self) -> Option<&Expr> {
1614 match self {
1615 Range::Range { from, .. } => Some(from),
1616 Range::RangeInclusive { from, .. } => Some(from),
1617 Range::RangeFrom { from } => Some(from),
1618 }
1619 }
1620
1621 pub fn to(&self) -> Option<&Expr> {
1622 match self {
1623 Range::Range { to, .. } => Some(to),
1624 Range::RangeInclusive { to, .. } => Some(to),
1625 Range::RangeFrom { .. } => None,
1626 }
1627 }
1628
1629 pub fn inclusive(&self) -> bool {
1630 matches!(self, Range::RangeInclusive { .. })
1631 }
1632
1633 pub fn get_exprs_mut(&mut self) -> Vec<&mut Box<Expr>> {
1634 match self {
1635 Range::Range { from, to } => vec![from, to],
1636 Range::RangeInclusive { from, to } => vec![from, to],
1637 Range::RangeFrom { from } => vec![from],
1638 }
1639 }
1640
1641 pub fn get_exprs(&self) -> Vec<&Expr> {
1642 match self {
1643 Range::Range { from, to } => vec![from.as_ref(), to.as_ref()],
1644 Range::RangeInclusive { from, to } => vec![from.as_ref(), to.as_ref()],
1645 Range::RangeFrom { from } => vec![from.as_ref()],
1646 }
1647 }
1648}
1649
1650#[derive(Debug, Hash, Clone, PartialEq, Ord, PartialOrd)]
1651pub struct Number {
1652 pub value: BigDecimal,
1653}
1654
1655impl Eq for Number {}
1656
1657impl Number {
1658 pub fn to_val(&self, analysed_type: &AnalysedType) -> Option<ValueAndType> {
1659 match analysed_type {
1660 AnalysedType::F64(_) => self.value.to_f64().map(|v| v.into_value_and_type()),
1661 AnalysedType::U64(_) => self.value.to_u64().map(|v| v.into_value_and_type()),
1662 AnalysedType::F32(_) => self.value.to_f32().map(|v| v.into_value_and_type()),
1663 AnalysedType::U32(_) => self.value.to_u32().map(|v| v.into_value_and_type()),
1664 AnalysedType::S32(_) => self.value.to_i32().map(|v| v.into_value_and_type()),
1665 AnalysedType::S64(_) => self.value.to_i64().map(|v| v.into_value_and_type()),
1666 AnalysedType::U8(_) => self.value.to_u8().map(|v| v.into_value_and_type()),
1667 AnalysedType::S8(_) => self.value.to_i8().map(|v| v.into_value_and_type()),
1668 AnalysedType::U16(_) => self.value.to_u16().map(|v| v.into_value_and_type()),
1669 AnalysedType::S16(_) => self.value.to_i16().map(|v| v.into_value_and_type()),
1670 _ => None,
1671 }
1672 }
1673}
1674
1675impl Display for Number {
1676 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1677 write!(f, "{}", self.value)
1678 }
1679}
1680
1681#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1682pub struct MatchArm {
1683 pub arm_pattern: ArmPattern,
1684 pub arm_resolution_expr: Box<Expr>,
1685}
1686
1687impl MatchArm {
1688 pub fn new(arm_pattern: ArmPattern, arm_resolution: Expr) -> MatchArm {
1689 MatchArm {
1690 arm_pattern,
1691 arm_resolution_expr: Box::new(arm_resolution),
1692 }
1693 }
1694}
1695#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1696pub enum ArmPattern {
1697 WildCard,
1698 As(String, Box<ArmPattern>),
1699 Constructor(String, Vec<ArmPattern>),
1700 TupleConstructor(Vec<ArmPattern>),
1701 RecordConstructor(Vec<(String, ArmPattern)>),
1702 ListConstructor(Vec<ArmPattern>),
1703 Literal(Box<Expr>),
1704}
1705
1706impl ArmPattern {
1707 pub fn is_wildcard(&self) -> bool {
1708 matches!(self, ArmPattern::WildCard)
1709 }
1710
1711 pub fn is_literal_identifier(&self) -> bool {
1712 matches!(self, ArmPattern::Literal(expr) if expr.is_identifier())
1713 }
1714
1715 pub fn constructor(name: &str, patterns: Vec<ArmPattern>) -> ArmPattern {
1716 ArmPattern::Constructor(name.to_string(), patterns)
1717 }
1718
1719 pub fn literal(expr: Expr) -> ArmPattern {
1720 ArmPattern::Literal(Box::new(expr))
1721 }
1722
1723 pub fn get_expr_literals_mut(&mut self) -> Vec<&mut Box<Expr>> {
1724 match self {
1725 ArmPattern::Literal(expr) => vec![expr],
1726 ArmPattern::As(_, pattern) => pattern.get_expr_literals_mut(),
1727 ArmPattern::Constructor(_, patterns) => {
1728 let mut result = vec![];
1729 for pattern in patterns {
1730 result.extend(pattern.get_expr_literals_mut());
1731 }
1732 result
1733 }
1734 ArmPattern::TupleConstructor(patterns) => {
1735 let mut result = vec![];
1736 for pattern in patterns {
1737 result.extend(pattern.get_expr_literals_mut());
1738 }
1739 result
1740 }
1741 ArmPattern::RecordConstructor(patterns) => {
1742 let mut result = vec![];
1743 for (_, pattern) in patterns {
1744 result.extend(pattern.get_expr_literals_mut());
1745 }
1746 result
1747 }
1748 ArmPattern::ListConstructor(patterns) => {
1749 let mut result = vec![];
1750 for pattern in patterns {
1751 result.extend(pattern.get_expr_literals_mut());
1752 }
1753 result
1754 }
1755 ArmPattern::WildCard => vec![],
1756 }
1757 }
1758
1759 pub fn get_expr_literals(&self) -> Vec<&Expr> {
1760 match self {
1761 ArmPattern::Literal(expr) => vec![expr.as_ref()],
1762 ArmPattern::As(_, pattern) => pattern.get_expr_literals(),
1763 ArmPattern::Constructor(_, patterns) => {
1764 let mut result = vec![];
1765 for pattern in patterns {
1766 result.extend(pattern.get_expr_literals());
1767 }
1768 result
1769 }
1770 ArmPattern::TupleConstructor(patterns) => {
1771 let mut result = vec![];
1772 for pattern in patterns {
1773 result.extend(pattern.get_expr_literals());
1774 }
1775 result
1776 }
1777 ArmPattern::RecordConstructor(patterns) => {
1778 let mut result = vec![];
1779 for (_, pattern) in patterns {
1780 result.extend(pattern.get_expr_literals());
1781 }
1782 result
1783 }
1784 ArmPattern::ListConstructor(patterns) => {
1785 let mut result = vec![];
1786 for pattern in patterns {
1787 result.extend(pattern.get_expr_literals());
1788 }
1789 result
1790 }
1791 ArmPattern::WildCard => vec![],
1792 }
1793 }
1794 pub fn ok(binding_variable: &str) -> ArmPattern {
1796 ArmPattern::Literal(Box::new(Expr::Result {
1797 expr: Ok(Box::new(Expr::Identifier {
1798 variable_id: VariableId::global(binding_variable.to_string()),
1799 type_annotation: None,
1800 inferred_type: InferredType::Unknown,
1801 source_span: SourceSpan::default(),
1802 })),
1803 type_annotation: None,
1804 inferred_type: InferredType::Result {
1805 ok: Some(Box::new(InferredType::Unknown)),
1806 error: Some(Box::new(InferredType::Unknown)),
1807 },
1808 source_span: SourceSpan::default(),
1809 }))
1810 }
1811
1812 pub fn err(binding_variable: &str) -> ArmPattern {
1814 ArmPattern::Literal(Box::new(Expr::Result {
1815 expr: Err(Box::new(Expr::Identifier {
1816 variable_id: VariableId::global(binding_variable.to_string()),
1817 type_annotation: None,
1818 inferred_type: InferredType::Unknown,
1819 source_span: SourceSpan::default(),
1820 })),
1821 type_annotation: None,
1822 inferred_type: InferredType::Result {
1823 ok: Some(Box::new(InferredType::Unknown)),
1824 error: Some(Box::new(InferredType::Unknown)),
1825 },
1826 source_span: SourceSpan::default(),
1827 }))
1828 }
1829
1830 pub fn some(binding_variable: &str) -> ArmPattern {
1832 ArmPattern::Literal(Box::new(Expr::Option {
1833 expr: Some(Box::new(Expr::Identifier {
1834 variable_id: VariableId::local_with_no_id(binding_variable),
1835 type_annotation: None,
1836 inferred_type: InferredType::Unknown,
1837 source_span: SourceSpan::default(),
1838 })),
1839 type_annotation: None,
1840 inferred_type: InferredType::Unknown,
1841 source_span: SourceSpan::default(),
1842 }))
1843 }
1844
1845 pub fn none() -> ArmPattern {
1846 ArmPattern::Literal(Box::new(Expr::Option {
1847 expr: None,
1848 type_annotation: None,
1849 inferred_type: InferredType::Unknown,
1850 source_span: SourceSpan::default(),
1851 }))
1852 }
1853
1854 pub fn identifier(binding_variable: &str) -> ArmPattern {
1855 ArmPattern::Literal(Box::new(Expr::Identifier {
1856 variable_id: VariableId::global(binding_variable.to_string()),
1857 type_annotation: None,
1858 inferred_type: InferredType::Unknown,
1859 source_span: SourceSpan::default(),
1860 }))
1861 }
1862 pub fn custom_constructor(name: &str, args: Vec<ArmPattern>) -> ArmPattern {
1863 ArmPattern::Constructor(name.to_string(), args)
1864 }
1865}
1866
1867#[cfg(feature = "protobuf")]
1868impl TryFrom<golem_api_grpc::proto::golem::rib::Expr> for Expr {
1869 type Error = String;
1870
1871 fn try_from(value: golem_api_grpc::proto::golem::rib::Expr) -> Result<Self, Self::Error> {
1872 let expr = value.expr.ok_or("Missing expr")?;
1873
1874 let expr = match expr {
1875 golem_api_grpc::proto::golem::rib::expr::Expr::Let(expr) => {
1876 let name = expr.name;
1877 let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
1878 let expr_: golem_api_grpc::proto::golem::rib::Expr =
1879 *expr.expr.ok_or("Missing expr")?;
1880 let expr: Expr = expr_.try_into()?;
1881 Expr::let_binding(name, expr, type_annotation)
1882 }
1883
1884 golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(expr) => {
1885 let selection = *expr.expr.ok_or("Missing expr")?;
1886 let field = *expr.index.ok_or("Missing index")?;
1887 let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
1888
1889 Expr::select_index(selection.try_into()?, field.try_into()?)
1890 .with_type_annotation_opt(type_annotation)
1891 }
1892
1893 golem_api_grpc::proto::golem::rib::expr::Expr::Length(expr) => {
1894 let expr = expr.expr.ok_or("Missing expr")?;
1895 Expr::Length {
1896 expr: Box::new((*expr).try_into()?),
1897 type_annotation: None,
1898 inferred_type: InferredType::Unknown,
1899 source_span: SourceSpan::default(),
1900 }
1901 }
1902
1903 golem_api_grpc::proto::golem::rib::expr::Expr::Range(range) => {
1904 let range_expr = range.range_expr.ok_or("Missing range expr")?;
1905
1906 match range_expr {
1907 RangeExpr::RangeFrom(range_from) => {
1908 let from = range_from.from.ok_or("Missing from expr")?;
1909 Expr::range_from((*from).try_into()?)
1910 }
1911 RangeExpr::Range(range) => {
1912 let from = range.from.ok_or("Missing from expr")?;
1913 let to = range.to.ok_or("Missing to expr")?;
1914 Expr::range((*from).try_into()?, (*to).try_into()?)
1915 }
1916 RangeExpr::RangeInclusive(range_inclusive) => {
1917 let from = range_inclusive.from.ok_or("Missing from expr")?;
1918 let to = range_inclusive.to.ok_or("Missing to expr")?;
1919 Expr::range_inclusive((*from).try_into()?, (*to).try_into()?)
1920 }
1921 }
1922 }
1923
1924 golem_api_grpc::proto::golem::rib::expr::Expr::Not(expr) => {
1925 let expr = expr.expr.ok_or("Missing expr")?;
1926 Expr::not((*expr).try_into()?)
1927 }
1928
1929 golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(expr) => {
1930 let left = expr.left.ok_or("Missing left expr")?;
1931 let right = expr.right.ok_or("Missing right expr")?;
1932 Expr::greater_than((*left).try_into()?, (*right).try_into()?)
1933 }
1934
1935 golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(expr) => {
1936 let left = expr.left.ok_or("Missing left expr")?;
1937 let right = expr.right.ok_or("Missing right expr")?;
1938 Expr::greater_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
1939 }
1940
1941 golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(expr) => {
1942 let left = expr.left.ok_or("Missing left expr")?;
1943 let right = expr.right.ok_or("Missing right expr")?;
1944 Expr::less_than((*left).try_into()?, (*right).try_into()?)
1945 }
1946
1947 golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(expr) => {
1948 let left = expr.left.ok_or("Missing left expr")?;
1949 let right = expr.right.ok_or("Missing right expr")?;
1950 Expr::less_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
1951 }
1952
1953 golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(expr) => {
1954 let left = expr.left.ok_or("Missing left expr")?;
1955 let right = expr.right.ok_or("Missing right expr")?;
1956 Expr::equal_to((*left).try_into()?, (*right).try_into()?)
1957 }
1958
1959 golem_api_grpc::proto::golem::rib::expr::Expr::Add(expr) => {
1960 let left = expr.left.ok_or("Missing left expr")?;
1961 let right = expr.right.ok_or("Missing right expr")?;
1962 Expr::plus((*left).try_into()?, (*right).try_into()?)
1963 }
1964
1965 golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(expr) => {
1966 let left = expr.left.ok_or("Missing left expr")?;
1967 let right = expr.right.ok_or("Missing right expr")?;
1968 Expr::plus((*left).try_into()?, (*right).try_into()?)
1969 }
1970
1971 golem_api_grpc::proto::golem::rib::expr::Expr::Divide(expr) => {
1972 let left = expr.left.ok_or("Missing left expr")?;
1973 let right = expr.right.ok_or("Missing right expr")?;
1974 Expr::plus((*left).try_into()?, (*right).try_into()?)
1975 }
1976
1977 golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(expr) => {
1978 let left = expr.left.ok_or("Missing left expr")?;
1979 let right = expr.right.ok_or("Missing right expr")?;
1980 Expr::plus((*left).try_into()?, (*right).try_into()?)
1981 }
1982
1983 golem_api_grpc::proto::golem::rib::expr::Expr::Cond(expr) => {
1984 let left = expr.left.ok_or("Missing left expr")?;
1985 let cond = expr.cond.ok_or("Missing cond expr")?;
1986 let right = expr.right.ok_or("Missing right expr")?;
1987 Expr::cond(
1988 (*left).try_into()?,
1989 (*cond).try_into()?,
1990 (*right).try_into()?,
1991 )
1992 }
1993
1994 golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
1995 golem_api_grpc::proto::golem::rib::ConcatExpr { exprs },
1996 ) => {
1997 let exprs: Vec<Expr> = exprs
1998 .into_iter()
1999 .map(|expr| expr.try_into())
2000 .collect::<Result<Vec<_>, _>>()?;
2001 Expr::concat(exprs)
2002 }
2003
2004 golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2005 golem_api_grpc::proto::golem::rib::MultipleExpr { exprs },
2006 ) => {
2007 let exprs: Vec<Expr> = exprs
2008 .into_iter()
2009 .map(|expr| expr.try_into())
2010 .collect::<Result<Vec<_>, _>>()?;
2011 Expr::expr_block(exprs)
2012 }
2013
2014 golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2015 golem_api_grpc::proto::golem::rib::SequenceExpr { exprs, type_name },
2016 ) => {
2017 let type_annotation = type_name.map(TypeName::try_from).transpose()?;
2018
2019 let exprs: Vec<Expr> = exprs
2020 .into_iter()
2021 .map(|expr| expr.try_into())
2022 .collect::<Result<Vec<_>, _>>()?;
2023 Expr::sequence(exprs, type_annotation)
2024 }
2025
2026 golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2027 golem_api_grpc::proto::golem::rib::TupleExpr { exprs },
2028 ) => {
2029 let exprs: Vec<Expr> = exprs
2030 .into_iter()
2031 .map(|expr| expr.try_into())
2032 .collect::<Result<Vec<_>, _>>()?;
2033 Expr::tuple(exprs)
2034 }
2035
2036 golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2037 golem_api_grpc::proto::golem::rib::RecordExpr { fields },
2038 ) => {
2039 let mut values: Vec<(String, Expr)> = vec![];
2040 for record in fields.into_iter() {
2041 let name = record.name;
2042 let expr = record.expr.ok_or("Missing expr")?;
2043 values.push((name, expr.try_into()?));
2044 }
2045 Expr::record(values)
2046 }
2047
2048 golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2049 golem_api_grpc::proto::golem::rib::FlagsExpr { values },
2050 ) => Expr::flags(values),
2051
2052 golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2053 golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2054 ) => Expr::literal(value),
2055
2056 golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2057 golem_api_grpc::proto::golem::rib::IdentifierExpr { name, type_name },
2058 ) => {
2059 let type_name = type_name.map(TypeName::try_from).transpose()?;
2060
2061 Expr::identifier_global(name.as_str(), type_name)
2062 }
2063
2064 golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2065 golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2066 ) => Expr::boolean(value),
2067
2068 golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2069 golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2070 ) => Expr::throw(message),
2071
2072 golem_api_grpc::proto::golem::rib::expr::Expr::And(expr) => {
2073 let left = expr.left.ok_or("Missing left expr")?;
2074 let right = expr.right.ok_or("Missing right expr")?;
2075 Expr::and((*left).try_into()?, (*right).try_into()?)
2076 }
2077
2078 golem_api_grpc::proto::golem::rib::expr::Expr::Or(expr) => {
2079 let left = expr.left.ok_or("Missing left expr")?;
2080 let right = expr.right.ok_or("Missing right expr")?;
2081 Expr::or((*left).try_into()?, (*right).try_into()?)
2082 }
2083
2084 golem_api_grpc::proto::golem::rib::expr::Expr::Tag(expr) => {
2085 let expr = expr.expr.ok_or("Missing expr in tag")?;
2086 Expr::get_tag((*expr).try_into()?)
2087 }
2088
2089 golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(expr) => {
2090 let expr = expr.expr.ok_or("Missing expr")?;
2091 let expr: Expr = (*expr).try_into()?;
2092 expr.unwrap()
2093 }
2094
2095 golem_api_grpc::proto::golem::rib::expr::Expr::Number(number) => {
2096 let type_name = number.type_name.map(TypeName::try_from).transpose()?;
2098 let big_decimal = if let Some(number) = number.number {
2099 BigDecimal::from_str(&number).map_err(|e| e.to_string())?
2100 } else if let Some(float) = number.float {
2101 BigDecimal::from_f64(float).ok_or("Invalid float")?
2102 } else {
2103 return Err("Missing number".to_string());
2104 };
2105
2106 Expr::number(big_decimal).with_type_annotation_opt(type_name)
2107 }
2108 golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(expr) => {
2109 let expr = *expr;
2110 let field = expr.field;
2111 let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2112 let expr = *expr.expr.ok_or(
2113 "Mi\
2114 ssing expr",
2115 )?;
2116
2117 Expr::select_field(expr.try_into()?, field.as_str(), type_name)
2118 }
2119 golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndex(expr) => {
2120 let expr = *expr;
2121 let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2122 let index = expr.index as usize;
2123 let expr = *expr.expr.ok_or("Missing expr")?;
2124
2125 let index_expr =
2126 Expr::number(BigDecimal::from_usize(index).ok_or("Invalid index")?);
2127
2128 Expr::select_index(expr.try_into()?, index_expr).with_type_annotation_opt(type_name)
2129 }
2130 golem_api_grpc::proto::golem::rib::expr::Expr::Option(expr) => {
2131 let type_name = expr.type_name;
2132 let type_name = type_name.map(TypeName::try_from).transpose()?;
2133
2134 match expr.expr {
2135 Some(expr) => {
2136 Expr::option(Some((*expr).try_into()?)).with_type_annotation_opt(type_name)
2137 }
2138 None => Expr::option(None).with_type_annotation_opt(type_name),
2139 }
2140 }
2141 golem_api_grpc::proto::golem::rib::expr::Expr::Result(expr) => {
2142 let type_name = expr.type_name;
2143 let type_name = type_name.map(TypeName::try_from).transpose()?;
2144 let result = expr.result.ok_or("Missing result")?;
2145 match result {
2146 golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(expr) => {
2147 Expr::ok((*expr).try_into()?, type_name)
2148 }
2149 golem_api_grpc::proto::golem::rib::result_expr::Result::Err(expr) => {
2150 Expr::err((*expr).try_into()?, type_name)
2151 }
2152 }
2153 }
2154 golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(expr) => {
2155 let patterns: Vec<MatchArm> = expr
2156 .patterns
2157 .into_iter()
2158 .map(|expr| expr.try_into())
2159 .collect::<Result<Vec<_>, _>>()?;
2160 let expr = expr.expr.ok_or("Missing expr")?;
2161 Expr::pattern_match((*expr).try_into()?, patterns)
2162 }
2163 golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(
2164 list_comprehension,
2165 ) => {
2166 let iterable_expr = list_comprehension.iterable_expr.ok_or("Missing expr")?;
2167 let iterable_expr = (*iterable_expr).try_into()?;
2168 let yield_expr = list_comprehension.yield_expr.ok_or("Missing list")?;
2169 let yield_expr = (*yield_expr).try_into()?;
2170 let variable_id =
2171 VariableId::list_comprehension_identifier(list_comprehension.iterated_variable);
2172 Expr::list_comprehension(variable_id, iterable_expr, yield_expr)
2173 }
2174 golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(list_reduce) => {
2175 let init_value_expr = list_reduce.init_value_expr.ok_or("Missing initial expr")?;
2176 let init_value_expr = (*init_value_expr).try_into()?;
2177 let iterable_expr = list_reduce.iterable_expr.ok_or("Missing expr")?;
2178 let iterable_expr = (*iterable_expr).try_into()?;
2179 let yield_expr = list_reduce.yield_expr.ok_or("Missing list")?;
2180 let yield_expr = (*yield_expr).try_into()?;
2181 let iterated_variable_id =
2182 VariableId::list_comprehension_identifier(list_reduce.iterated_variable);
2183 let reduce_variable_id =
2184 VariableId::list_reduce_identifier(list_reduce.reduce_variable);
2185 Expr::list_reduce(
2186 reduce_variable_id,
2187 iterated_variable_id,
2188 iterable_expr,
2189 init_value_expr,
2190 yield_expr,
2191 )
2192 }
2193 golem_api_grpc::proto::golem::rib::expr::Expr::Call(expr) => {
2194 let params: Vec<Expr> = expr
2195 .params
2196 .into_iter()
2197 .map(|expr| expr.try_into())
2198 .collect::<Result<Vec<_>, _>>()?;
2199 let legacy_invocation_name = expr.name;
2201 let call_type = expr.call_type;
2202 let generic_type_parameter = expr
2203 .generic_type_parameter
2204 .map(|tp| GenericTypeParameter { value: tp });
2205
2206 match (legacy_invocation_name, call_type) {
2207 (Some(legacy), None) => {
2208 let name = legacy.name.ok_or("Missing function call name")?;
2209 match name {
2210 golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => {
2211 Expr::call_worker_function(DynamicParsedFunctionName::parse(
2213 ParsedFunctionName::try_from(name)?.to_string()
2214 )?, generic_type_parameter, None, params)
2215 }
2216 golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(
2217 name,
2218 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2219 golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(
2220 name,
2221 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2222 }
2223 }
2224 (_, Some(call_type)) => {
2225 let name = call_type.name.ok_or("Missing function call name")?;
2226 match name {
2227 golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => {
2228 Expr::call_worker_function(name.try_into()?, generic_type_parameter, None, params)
2229 }
2230 golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(
2231 name,
2232 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2233 golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(
2234 name,
2235 ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params),
2236 golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(instance_creation) => {
2237 let instance_creation_type = InstanceCreationType::try_from(*instance_creation)?;
2238 let call_type = CallType::InstanceCreation(instance_creation_type);
2239 Expr::Call {
2240 call_type,
2241 generic_type_parameter,
2242 args: vec![],
2243 inferred_type: InferredType::Unknown,
2244 source_span: SourceSpan::default(),
2245 type_annotation: None, }
2247 }
2248 }
2249 }
2250 (_, _) => Err("Missing both call type (and legacy invocation type)")?,
2251 }
2252 }
2253 golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(lazy_invoke) => {
2254 let lhs_proto = lazy_invoke.lhs.ok_or("Missing lhs")?;
2255 let lhs = Box::new((*lhs_proto).try_into()?);
2256 let method = lazy_invoke.method;
2257 let generic_type_parameter = lazy_invoke.generic_type_parameter;
2258 let args: Vec<Expr> = lazy_invoke
2259 .args
2260 .into_iter()
2261 .map(Expr::try_from)
2262 .collect::<Result<Vec<_>, _>>()?;
2263
2264 Expr::InvokeMethodLazy {
2265 lhs,
2266 method,
2267 generic_type_parameter: generic_type_parameter
2268 .map(|value| GenericTypeParameter { value }),
2269 args,
2270 inferred_type: InferredType::Unknown,
2271 source_span: SourceSpan::default(),
2272 type_annotation: None, }
2274 }
2275 };
2276 Ok(expr)
2277 }
2278}
2279
2280impl Display for Expr {
2281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2282 write!(f, "{}", text::to_string(self).unwrap())
2283 }
2284}
2285
2286impl Display for ArmPattern {
2287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2288 write!(f, "{}", text::to_string_arm_pattern(self).unwrap())
2289 }
2290}
2291
2292impl<'de> Deserialize<'de> for Expr {
2293 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2294 where
2295 D: serde::Deserializer<'de>,
2296 {
2297 let value = serde_json::Value::deserialize(deserializer)?;
2298 match value {
2299 Value::String(expr_string) => match from_string(expr_string.as_str()) {
2300 Ok(expr) => Ok(expr),
2301 Err(message) => Err(serde::de::Error::custom(message.to_string())),
2302 },
2303
2304 e => Err(serde::de::Error::custom(format!(
2305 "Failed to deserialize expression {}",
2306 e
2307 ))),
2308 }
2309 }
2310}
2311
2312impl Serialize for Expr {
2313 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2314 where
2315 S: Serializer,
2316 {
2317 match text::to_string(self) {
2318 Ok(value) => serde_json::Value::serialize(&Value::String(value), serializer),
2319 Err(error) => Err(serde::ser::Error::custom(error.to_string())),
2320 }
2321 }
2322}
2323
2324#[cfg(feature = "protobuf")]
2325mod protobuf {
2326 use crate::{ArmPattern, Expr, MatchArm, Range};
2327 use golem_api_grpc::proto::golem::rib::range_expr::RangeExpr;
2328
2329 impl From<Expr> for golem_api_grpc::proto::golem::rib::Expr {
2330 fn from(value: Expr) -> Self {
2331 let expr = match value {
2332 Expr::Let {
2333 variable_id,
2334 type_annotation,
2335 expr,
2336 ..
2337 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Let(
2338 Box::new(golem_api_grpc::proto::golem::rib::LetExpr {
2339 name: variable_id.name().to_string(),
2340 expr: Some(Box::new((*expr).into())),
2341 type_name: type_annotation.map(|t| t.into()),
2342 }),
2343 )),
2344
2345 Expr::Length { expr, .. } => {
2346 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Length(
2347 Box::new(golem_api_grpc::proto::golem::rib::LengthExpr {
2348 expr: Some(Box::new((*expr).into())),
2349 }),
2350 ))
2351 }
2352
2353 Expr::SelectField {
2354 expr,
2355 field,
2356 type_annotation,
2357 ..
2358 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(
2359 Box::new(golem_api_grpc::proto::golem::rib::SelectFieldExpr {
2360 expr: Some(Box::new((*expr).into())),
2361 field,
2362 type_name: type_annotation.map(|t| t.into()),
2363 }),
2364 )),
2365
2366 Expr::Range { range, .. } => match range {
2367 Range::RangeFrom { from } => {
2368 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2369 Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2370 range_expr: Some(RangeExpr::RangeFrom(Box::new(
2371 golem_api_grpc::proto::golem::rib::RangeFrom {
2372 from: Some(Box::new((*from).into())),
2373 },
2374 ))),
2375 }),
2376 ))
2377 }
2378 Range::Range { from, to } => {
2379 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2380 Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2381 range_expr: Some(RangeExpr::Range(Box::new(
2382 golem_api_grpc::proto::golem::rib::Range {
2383 from: Some(Box::new((*from).into())),
2384 to: Some(Box::new((*to).into())),
2385 },
2386 ))),
2387 }),
2388 ))
2389 }
2390 Range::RangeInclusive { from, to } => {
2391 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2392 Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2393 range_expr: Some(RangeExpr::RangeInclusive(Box::new(
2394 golem_api_grpc::proto::golem::rib::RangeInclusive {
2395 from: Some(Box::new((*from).into())),
2396 to: Some(Box::new((*to).into())),
2397 },
2398 ))),
2399 }),
2400 ))
2401 }
2402 },
2403
2404 Expr::SelectIndex {
2405 expr,
2406 index,
2407 type_annotation,
2408 ..
2409 } => Some(
2410 golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(Box::new(
2411 golem_api_grpc::proto::golem::rib::SelectIndexExprV1 {
2412 expr: Some(Box::new((*expr).into())),
2413 index: Some(Box::new((*index).into())),
2414 type_name: type_annotation.map(|t| t.into()),
2415 },
2416 )),
2417 ),
2418
2419 Expr::Sequence {
2420 exprs: expressions,
2421 type_annotation,
2422 ..
2423 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2424 golem_api_grpc::proto::golem::rib::SequenceExpr {
2425 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2426 type_name: type_annotation.map(|t| t.into()),
2427 },
2428 )),
2429 Expr::Record { exprs: fields, .. } => {
2430 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2431 golem_api_grpc::proto::golem::rib::RecordExpr {
2432 fields: fields
2433 .into_iter()
2434 .map(|(name, expr)| {
2435 golem_api_grpc::proto::golem::rib::RecordFieldExpr {
2436 name,
2437 expr: Some((*expr).into()),
2438 }
2439 })
2440 .collect(),
2441 },
2442 ))
2443 }
2444 Expr::Tuple {
2445 exprs: expressions, ..
2446 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2447 golem_api_grpc::proto::golem::rib::TupleExpr {
2448 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2449 },
2450 )),
2451 Expr::Literal { value, .. } => {
2452 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2453 golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2454 ))
2455 }
2456 Expr::Number {
2457 number,
2458 type_annotation,
2459 ..
2460 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Number(
2461 golem_api_grpc::proto::golem::rib::NumberExpr {
2462 number: Some(number.value.to_string()),
2463 float: None,
2464 type_name: type_annotation.map(|t| t.into()),
2465 },
2466 )),
2467 Expr::Flags { flags, .. } => {
2468 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2469 golem_api_grpc::proto::golem::rib::FlagsExpr { values: flags },
2470 ))
2471 }
2472 Expr::Identifier {
2473 variable_id,
2474 type_annotation,
2475 ..
2476 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2477 golem_api_grpc::proto::golem::rib::IdentifierExpr {
2478 name: variable_id.name(),
2479 type_name: type_annotation.map(|t| t.into()),
2480 },
2481 )),
2482 Expr::Boolean { value, .. } => {
2483 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2484 golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2485 ))
2486 }
2487 Expr::Concat {
2488 exprs: expressions, ..
2489 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
2490 golem_api_grpc::proto::golem::rib::ConcatExpr {
2491 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2492 },
2493 )),
2494 Expr::ExprBlock {
2495 exprs: expressions, ..
2496 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2497 golem_api_grpc::proto::golem::rib::MultipleExpr {
2498 exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2499 },
2500 )),
2501 Expr::Not { expr, .. } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Not(
2502 Box::new(golem_api_grpc::proto::golem::rib::NotExpr {
2503 expr: Some(Box::new((*expr).into())),
2504 }),
2505 )),
2506 Expr::GreaterThan {
2507 lhs: left,
2508 rhs: right,
2509 ..
2510 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(
2511 Box::new(golem_api_grpc::proto::golem::rib::GreaterThanExpr {
2512 left: Some(Box::new((*left).into())),
2513 right: Some(Box::new((*right).into())),
2514 }),
2515 )),
2516 Expr::GreaterThanOrEqualTo { lhs, rhs, .. } => Some(
2517 golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(Box::new(
2518 golem_api_grpc::proto::golem::rib::GreaterThanOrEqualToExpr {
2519 left: Some(Box::new((*lhs).into())),
2520 right: Some(Box::new((*rhs).into())),
2521 },
2522 )),
2523 ),
2524 Expr::LessThan {
2525 lhs: left,
2526 rhs: right,
2527 ..
2528 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(
2529 Box::new(golem_api_grpc::proto::golem::rib::LessThanExpr {
2530 left: Some(Box::new((*left).into())),
2531 right: Some(Box::new((*right).into())),
2532 }),
2533 )),
2534 Expr::Plus {
2535 lhs: left,
2536 rhs: right,
2537 ..
2538 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Add(
2539 Box::new(golem_api_grpc::proto::golem::rib::AddExpr {
2540 left: Some(Box::new((*left).into())),
2541 right: Some(Box::new((*right).into())),
2542 }),
2543 )),
2544 Expr::Minus {
2545 lhs: left,
2546 rhs: right,
2547 ..
2548 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(
2549 Box::new(golem_api_grpc::proto::golem::rib::SubtractExpr {
2550 left: Some(Box::new((*left).into())),
2551 right: Some(Box::new((*right).into())),
2552 }),
2553 )),
2554 Expr::Divide { lhs, rhs, .. } => {
2555 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Divide(
2556 Box::new(golem_api_grpc::proto::golem::rib::DivideExpr {
2557 left: Some(Box::new((*lhs).into())),
2558 right: Some(Box::new((*rhs).into())),
2559 }),
2560 ))
2561 }
2562 Expr::Multiply { lhs, rhs, .. } => {
2563 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(
2564 Box::new(golem_api_grpc::proto::golem::rib::MultiplyExpr {
2565 left: Some(Box::new((*lhs).into())),
2566 right: Some(Box::new((*rhs).into())),
2567 }),
2568 ))
2569 }
2570 Expr::LessThanOrEqualTo { lhs, rhs, .. } => Some(
2571 golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(Box::new(
2572 golem_api_grpc::proto::golem::rib::LessThanOrEqualToExpr {
2573 left: Some(Box::new((*lhs).into())),
2574 right: Some(Box::new((*rhs).into())),
2575 },
2576 )),
2577 ),
2578 Expr::EqualTo { lhs, rhs, .. } => {
2579 Some(golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(
2580 Box::new(golem_api_grpc::proto::golem::rib::EqualToExpr {
2581 left: Some(Box::new((*lhs).into())),
2582 right: Some(Box::new((*rhs).into())),
2583 }),
2584 ))
2585 }
2586 Expr::Cond {
2592 cond: lhs,
2593 lhs: cond,
2594 rhs,
2595 ..
2596 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Cond(
2597 Box::new(golem_api_grpc::proto::golem::rib::CondExpr {
2598 left: Some(Box::new((*lhs).into())),
2599 cond: Some(Box::new((*cond).into())),
2600 right: Some(Box::new((*rhs).into())),
2601 }),
2602 )),
2603 Expr::PatternMatch {
2604 predicate,
2605 match_arms,
2606 ..
2607 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(
2608 Box::new(golem_api_grpc::proto::golem::rib::PatternMatchExpr {
2609 expr: Some(Box::new((*predicate).into())),
2610 patterns: match_arms.into_iter().map(|a| a.into()).collect(),
2611 }),
2612 )),
2613 Expr::Option {
2614 expr,
2615 type_annotation,
2616 ..
2617 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Option(
2618 Box::new(golem_api_grpc::proto::golem::rib::OptionExpr {
2619 expr: expr.map(|expr| Box::new((*expr).into())),
2620 type_name: type_annotation.map(|t| t.into()),
2621 }),
2622 )),
2623 Expr::Result {
2624 expr,
2625 type_annotation,
2626 ..
2627 } => {
2628 let type_name = type_annotation.map(|t| t.into());
2629
2630 let result = match expr {
2631 Ok(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(
2632 Box::new((*expr).into()),
2633 ),
2634 Err(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Err(
2635 Box::new((*expr).into()),
2636 ),
2637 };
2638
2639 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Result(
2640 Box::new(golem_api_grpc::proto::golem::rib::ResultExpr {
2641 result: Some(result),
2642 type_name,
2643 }),
2644 ))
2645 }
2646 Expr::Call {
2647 call_type,
2648 generic_type_parameter,
2649 args,
2650 ..
2651 } => {
2652 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Call(
2653 Box::new(golem_api_grpc::proto::golem::rib::CallExpr {
2654 name: None, params: args.into_iter().map(|expr| expr.into()).collect(),
2656 generic_type_parameter: generic_type_parameter.map(|t| t.value),
2657 call_type: Some(Box::new(
2658 golem_api_grpc::proto::golem::rib::CallType::from(call_type),
2659 )),
2660 }),
2661 ))
2662 }
2663 Expr::Unwrap { expr, .. } => {
2664 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(
2665 Box::new(golem_api_grpc::proto::golem::rib::UnwrapExpr {
2666 expr: Some(Box::new((*expr).into())),
2667 }),
2668 ))
2669 }
2670 Expr::Throw { message, .. } => {
2671 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2672 golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2673 ))
2674 }
2675 Expr::GetTag { expr, .. } => {
2676 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tag(
2677 Box::new(golem_api_grpc::proto::golem::rib::GetTagExpr {
2678 expr: Some(Box::new((*expr).into())),
2679 }),
2680 ))
2681 }
2682 Expr::And { lhs, rhs, .. } => {
2683 Some(golem_api_grpc::proto::golem::rib::expr::Expr::And(
2684 Box::new(golem_api_grpc::proto::golem::rib::AndExpr {
2685 left: Some(Box::new((*lhs).into())),
2686 right: Some(Box::new((*rhs).into())),
2687 }),
2688 ))
2689 }
2690
2691 Expr::Or { lhs, rhs, .. } => {
2692 Some(golem_api_grpc::proto::golem::rib::expr::Expr::Or(Box::new(
2693 golem_api_grpc::proto::golem::rib::OrExpr {
2694 left: Some(Box::new((*lhs).into())),
2695 right: Some(Box::new((*rhs).into())),
2696 },
2697 )))
2698 }
2699 Expr::ListComprehension {
2700 iterated_variable,
2701 iterable_expr,
2702 yield_expr,
2703 ..
2704 } => Some(
2705 golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(Box::new(
2706 golem_api_grpc::proto::golem::rib::ListComprehensionExpr {
2707 iterated_variable: iterated_variable.name(),
2708 iterable_expr: Some(Box::new((*iterable_expr).into())),
2709 yield_expr: Some(Box::new((*yield_expr).into())),
2710 },
2711 )),
2712 ),
2713
2714 Expr::ListReduce {
2715 reduce_variable,
2716 iterated_variable,
2717 iterable_expr,
2718 yield_expr,
2719 init_value_expr,
2720 ..
2721 } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(
2722 Box::new(golem_api_grpc::proto::golem::rib::ListReduceExpr {
2723 reduce_variable: reduce_variable.name(),
2724 iterated_variable: iterated_variable.name(),
2725 iterable_expr: Some(Box::new((*iterable_expr).into())),
2726 init_value_expr: Some(Box::new((*init_value_expr).into())),
2727 yield_expr: Some(Box::new((*yield_expr).into())),
2728 }),
2729 )),
2730 Expr::InvokeMethodLazy {
2731 lhs,
2732 method,
2733 generic_type_parameter,
2734 args,
2735 ..
2736 } => Some(
2737 golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(Box::new(
2738 golem_api_grpc::proto::golem::rib::LazyInvokeMethodExpr {
2739 lhs: Some(Box::new((*lhs).into())),
2740 method,
2741 generic_type_parameter: generic_type_parameter.map(|t| t.value),
2742 args: args.into_iter().map(|expr| expr.into()).collect(),
2743 },
2744 )),
2745 ),
2746 };
2747
2748 golem_api_grpc::proto::golem::rib::Expr { expr }
2749 }
2750 }
2751
2752 impl TryFrom<golem_api_grpc::proto::golem::rib::ArmPattern> for ArmPattern {
2753 type Error = String;
2754
2755 fn try_from(
2756 value: golem_api_grpc::proto::golem::rib::ArmPattern,
2757 ) -> Result<Self, Self::Error> {
2758 let pattern = value.pattern.ok_or("Missing pattern")?;
2759 match pattern {
2760 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(_) => {
2761 Ok(ArmPattern::WildCard)
2762 }
2763 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(asp) => {
2764 let name = asp.name;
2765 let pattern = asp.pattern.ok_or("Missing pattern")?;
2766 Ok(ArmPattern::As(name, Box::new((*pattern).try_into()?)))
2767 }
2768 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
2769 golem_api_grpc::proto::golem::rib::ConstructorArmPattern { name, patterns },
2770 ) => {
2771 let patterns = patterns
2772 .into_iter()
2773 .map(ArmPattern::try_from)
2774 .collect::<Result<Vec<_>, _>>()?;
2775 Ok(ArmPattern::Constructor(name, patterns))
2776 }
2777 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
2778 golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern { patterns },
2779 ) => {
2780 let patterns = patterns
2781 .into_iter()
2782 .map(ArmPattern::try_from)
2783 .collect::<Result<Vec<_>, _>>()?;
2784 Ok(ArmPattern::TupleConstructor(patterns))
2785 }
2786 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
2787 golem_api_grpc::proto::golem::rib::LiteralArmPattern { expr },
2788 ) => {
2789 let inner = expr.ok_or("Missing expr")?;
2790 Ok(ArmPattern::Literal(Box::new(inner.try_into()?)))
2791 }
2792 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
2793 golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern { fields },
2794 ) => {
2795 let fields = fields
2796 .into_iter()
2797 .map(|field| {
2798 let name = field.name;
2799 let proto_pattern = field.pattern.ok_or("Missing pattern")?;
2800 let arm_pattern = ArmPattern::try_from(proto_pattern)?;
2801 Ok((name, arm_pattern))
2802 })
2803 .collect::<Result<Vec<_>, String>>()?;
2804 Ok(ArmPattern::RecordConstructor(fields))
2805 }
2806 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
2807 golem_api_grpc::proto::golem::rib::ListConstructorArmPattern { patterns },
2808 ) => {
2809 let patterns = patterns
2810 .into_iter()
2811 .map(ArmPattern::try_from)
2812 .collect::<Result<Vec<_>, _>>()?;
2813 Ok(ArmPattern::ListConstructor(patterns))
2814 }
2815 }
2816 }
2817 }
2818
2819 impl From<ArmPattern> for golem_api_grpc::proto::golem::rib::ArmPattern {
2820 fn from(value: ArmPattern) -> Self {
2821 match value {
2822 ArmPattern::WildCard => golem_api_grpc::proto::golem::rib::ArmPattern {
2823 pattern: Some(
2824 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(
2825 golem_api_grpc::proto::golem::rib::WildCardArmPattern {},
2826 ),
2827 ),
2828 },
2829 ArmPattern::As(name, pattern) => golem_api_grpc::proto::golem::rib::ArmPattern {
2830 pattern: Some(golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(
2831 Box::new(golem_api_grpc::proto::golem::rib::AsArmPattern {
2832 name,
2833 pattern: Some(Box::new((*pattern).into())),
2834 }),
2835 )),
2836 },
2837 ArmPattern::Constructor(name, patterns) => {
2838 golem_api_grpc::proto::golem::rib::ArmPattern {
2839 pattern: Some(
2840 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
2841 golem_api_grpc::proto::golem::rib::ConstructorArmPattern {
2842 name,
2843 patterns: patterns
2844 .into_iter()
2845 .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
2846 .collect(),
2847 },
2848 ),
2849 ),
2850 }
2851 }
2852 ArmPattern::Literal(expr) => golem_api_grpc::proto::golem::rib::ArmPattern {
2853 pattern: Some(
2854 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
2855 golem_api_grpc::proto::golem::rib::LiteralArmPattern {
2856 expr: Some((*expr).into()),
2857 },
2858 ),
2859 ),
2860 },
2861
2862 ArmPattern::TupleConstructor(patterns) => {
2863 golem_api_grpc::proto::golem::rib::ArmPattern {
2864 pattern: Some(
2865 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
2866 golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern {
2867 patterns: patterns
2868 .into_iter()
2869 .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
2870 .collect(),
2871 },
2872 ),
2873 ),
2874 }
2875 }
2876
2877 ArmPattern::RecordConstructor(fields) => {
2878 golem_api_grpc::proto::golem::rib::ArmPattern {
2879 pattern: Some(
2880 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
2881 golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern {
2882 fields: fields
2883 .into_iter()
2884 .map(|(name, pattern)| {
2885 golem_api_grpc::proto::golem::rib::RecordFieldArmPattern {
2886 name,
2887 pattern: Some(pattern.into()),
2888 }
2889 })
2890 .collect(),
2891 },
2892 ),
2893 ),
2894 }
2895 }
2896
2897 ArmPattern::ListConstructor(patterns) => {
2898 golem_api_grpc::proto::golem::rib::ArmPattern {
2899 pattern: Some(
2900 golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
2901 golem_api_grpc::proto::golem::rib::ListConstructorArmPattern {
2902 patterns: patterns
2903 .into_iter()
2904 .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
2905 .collect(),
2906 },
2907 ),
2908 ),
2909 }
2910 }
2911 }
2912 }
2913 }
2914
2915 impl TryFrom<golem_api_grpc::proto::golem::rib::MatchArm> for MatchArm {
2916 type Error = String;
2917
2918 fn try_from(
2919 value: golem_api_grpc::proto::golem::rib::MatchArm,
2920 ) -> Result<Self, Self::Error> {
2921 let pattern = value.pattern.ok_or("Missing pattern")?;
2922 let expr = value.expr.ok_or("Missing expr")?;
2923 Ok(MatchArm::new(pattern.try_into()?, expr.try_into()?))
2924 }
2925 }
2926
2927 impl From<MatchArm> for golem_api_grpc::proto::golem::rib::MatchArm {
2928 fn from(value: MatchArm) -> Self {
2929 let MatchArm {
2930 arm_pattern,
2931 arm_resolution_expr,
2932 } = value;
2933 golem_api_grpc::proto::golem::rib::MatchArm {
2934 pattern: Some(arm_pattern.into()),
2935 expr: Some((*arm_resolution_expr).into()),
2936 }
2937 }
2938 }
2939}
2940
2941#[cfg(test)]
2942mod tests {
2943 use bigdecimal::BigDecimal;
2944 use test_r::test;
2945
2946 use crate::ParsedFunctionSite::PackagedInterface;
2947 use crate::{
2948 ArmPattern, DynamicParsedFunctionName, DynamicParsedFunctionReference, Expr, MatchArm,
2949 };
2950
2951 #[test]
2952 fn test_single_expr_in_interpolation_wrapped_in_quotes() {
2953 let input = r#""${foo}""#;
2954 let result = Expr::from_text(input);
2955 assert_eq!(
2956 result,
2957 Ok(Expr::concat(vec![Expr::identifier_global("foo", None)]))
2958 );
2959
2960 let input = r#""${{foo}}""#;
2961 let result = Expr::from_text(input);
2962 assert_eq!(
2963 result,
2964 Ok(Expr::concat(vec![Expr::flags(vec!["foo".to_string()])]))
2965 );
2966
2967 let input = r#""${{foo: "bar"}}""#;
2968 let result = Expr::from_text(input);
2969 assert_eq!(
2970 result,
2971 Ok(Expr::concat(vec![Expr::record(vec![(
2972 "foo".to_string(),
2973 Expr::literal("bar")
2974 )])]))
2975 );
2976 }
2977
2978 fn expected() -> Expr {
2979 Expr::expr_block(vec![
2980 Expr::let_binding("x", Expr::number(BigDecimal::from(1)), None),
2981 Expr::let_binding("y", Expr::number(BigDecimal::from(2)), None),
2982 Expr::let_binding(
2983 "result",
2984 Expr::greater_than(
2985 Expr::identifier_global("x", None),
2986 Expr::identifier_global("y", None),
2987 ),
2988 None,
2989 ),
2990 Expr::let_binding(
2991 "foo",
2992 Expr::option(Some(Expr::identifier_global("result", None))),
2993 None,
2994 ),
2995 Expr::let_binding(
2996 "bar",
2997 Expr::ok(Expr::identifier_global("result", None), None),
2998 None,
2999 ),
3000 Expr::let_binding(
3001 "baz",
3002 Expr::pattern_match(
3003 Expr::identifier_global("foo", None),
3004 vec![
3005 MatchArm::new(
3006 ArmPattern::constructor(
3007 "some",
3008 vec![ArmPattern::Literal(Box::new(Expr::identifier_global(
3009 "x", None,
3010 )))],
3011 ),
3012 Expr::identifier_global("x", None),
3013 ),
3014 MatchArm::new(
3015 ArmPattern::constructor("none", vec![]),
3016 Expr::boolean(false),
3017 ),
3018 ],
3019 ),
3020 None,
3021 ),
3022 Expr::let_binding(
3023 "qux",
3024 Expr::pattern_match(
3025 Expr::identifier_global("bar", None),
3026 vec![
3027 MatchArm::new(
3028 ArmPattern::constructor(
3029 "ok",
3030 vec![ArmPattern::Literal(Box::new(Expr::identifier_global(
3031 "x", None,
3032 )))],
3033 ),
3034 Expr::identifier_global("x", None),
3035 ),
3036 MatchArm::new(
3037 ArmPattern::constructor(
3038 "err",
3039 vec![ArmPattern::Literal(Box::new(Expr::identifier_global(
3040 "msg", None,
3041 )))],
3042 ),
3043 Expr::boolean(false),
3044 ),
3045 ],
3046 ),
3047 None,
3048 ),
3049 Expr::let_binding(
3050 "result",
3051 Expr::call_worker_function(
3052 DynamicParsedFunctionName {
3053 site: PackagedInterface {
3054 namespace: "ns".to_string(),
3055 package: "name".to_string(),
3056 interface: "interface".to_string(),
3057 version: None,
3058 },
3059 function: DynamicParsedFunctionReference::RawResourceStaticMethod {
3060 resource: "resource1".to_string(),
3061 method: "do-something-static".to_string(),
3062 },
3063 },
3064 None,
3065 None,
3066 vec![
3067 Expr::identifier_global("baz", None),
3068 Expr::identifier_global("qux", None),
3069 ],
3070 ),
3071 None,
3072 ),
3073 Expr::identifier_global("result", None),
3074 ])
3075 }
3076
3077 #[test]
3078 fn test_rib() {
3079 let sample_rib = r#"
3080 let x = 1;
3081 let y = 2;
3082 let result = x > y;
3083 let foo = some(result);
3084 let bar = ok(result);
3085
3086 let baz = match foo {
3087 some(x) => x,
3088 none => false
3089 };
3090
3091 let qux = match bar {
3092 ok(x) => x,
3093 err(msg) => false
3094 };
3095
3096 let result = ns:name/interface.{[static]resource1.do-something-static}(baz, qux);
3097
3098 result
3099 "#;
3100
3101 let result = Expr::from_text(sample_rib);
3102 assert_eq!(result, Ok(expected()));
3103 }
3104}