rib/interpreter/
rib_interpreter.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::interpreter::env::InterpreterEnv;
16use crate::interpreter::instruction_cursor::RibByteCodeCursor;
17use crate::interpreter::stack::InterpreterStack;
18use crate::{RibByteCode, RibFunctionInvoke, RibIR, RibInput, RibResult};
19use std::sync::Arc;
20
21use super::interpreter_stack_value::RibInterpreterStackValue;
22
23pub struct Interpreter {
24    pub input: RibInput,
25    pub invoke: Arc<dyn RibFunctionInvoke + Sync + Send>,
26    pub custom_stack: Option<InterpreterStack>,
27    pub custom_env: Option<InterpreterEnv>,
28}
29
30impl Default for Interpreter {
31    fn default() -> Self {
32        Interpreter {
33            input: RibInput::default(),
34            invoke: Arc::new(internal::NoopRibFunctionInvoke),
35            custom_stack: None,
36            custom_env: None,
37        }
38    }
39}
40
41impl Interpreter {
42    pub fn new(
43        input: &RibInput,
44        invoke: Arc<dyn RibFunctionInvoke + Sync + Send>,
45        custom_stack: Option<InterpreterStack>,
46        custom_env: Option<InterpreterEnv>,
47    ) -> Self {
48        Interpreter {
49            input: input.clone(),
50            invoke,
51            custom_stack,
52            custom_env,
53        }
54    }
55
56    // Interpreter that's not expected to call a side-effecting function call.
57    // All it needs is environment with the required variables to evaluate the Rib script
58    pub fn pure(
59        input: &RibInput,
60        custom_stack: Option<InterpreterStack>,
61        custom_env: Option<InterpreterEnv>,
62    ) -> Self {
63        Interpreter {
64            input: input.clone(),
65            invoke: Arc::new(internal::NoopRibFunctionInvoke),
66            custom_stack,
67            custom_env,
68        }
69    }
70
71    // Override rib input helps with incremental interpretation
72    // where a rib script is now trying to access a specific input
73    // such that the compiler already knows the required global variable and its types,
74    // to later override the interpreter with this input. The previous inputs will be completely
75    // discard as they are either loaded in as variables, or if they are accessed again, the inputs
76    // will be or can be overriden back
77    pub fn override_rib_input(&mut self, rib_input: RibInput) {
78        self.input = rib_input;
79    }
80
81    pub async fn run(&mut self, instructions0: RibByteCode) -> Result<RibResult, String> {
82        let mut byte_code_cursor = RibByteCodeCursor::from_rib_byte_code(instructions0);
83        let stack = match &mut self.custom_stack {
84            Some(custom) => custom,
85            None => &mut InterpreterStack::default(),
86        };
87
88        let interpreter_env = match &mut self.custom_env {
89            Some(custom) => custom,
90            None => &mut InterpreterEnv::from(&self.input, &self.invoke),
91        };
92
93        while let Some(instruction) = byte_code_cursor.get_instruction() {
94            match instruction {
95                RibIR::PushLit(val) => {
96                    stack.push_val(val);
97                }
98
99                RibIR::PushFlag(val) => {
100                    stack.push_val(val);
101                }
102
103                RibIR::CreateAndPushRecord(analysed_type) => {
104                    internal::run_create_record_instruction(analysed_type, stack)?;
105                }
106
107                RibIR::UpdateRecord(field_name) => {
108                    internal::run_update_record_instruction(field_name, stack)?;
109                }
110
111                RibIR::PushList(analysed_type, arg_size) => {
112                    internal::run_push_list_instruction(arg_size, analysed_type, stack)?;
113                }
114
115                RibIR::EqualTo => {
116                    internal::run_compare_instruction(stack, |left, right| left == right)?;
117                }
118
119                RibIR::GreaterThan => {
120                    internal::run_compare_instruction(stack, |left, right| left > right)?;
121                }
122
123                RibIR::LessThan => {
124                    internal::run_compare_instruction(stack, |left, right| left < right)?;
125                }
126
127                RibIR::GreaterThanOrEqualTo => {
128                    internal::run_compare_instruction(stack, |left, right| left >= right)?;
129                }
130
131                RibIR::LessThanOrEqualTo => {
132                    internal::run_compare_instruction(stack, |left, right| left <= right)?;
133                }
134                RibIR::Plus(analysed_type) => {
135                    internal::run_math_instruction(
136                        stack,
137                        |left, right| left + right,
138                        &analysed_type,
139                    )?;
140                }
141                RibIR::Minus(analysed_type) => {
142                    internal::run_math_instruction(
143                        stack,
144                        |left, right| left - right,
145                        &analysed_type,
146                    )?;
147                }
148                RibIR::Divide(analysed_type) => {
149                    internal::run_math_instruction(
150                        stack,
151                        |left, right| left / right,
152                        &analysed_type,
153                    )?;
154                }
155                RibIR::Multiply(analysed_type) => {
156                    internal::run_math_instruction(
157                        stack,
158                        |left, right| left * right,
159                        &analysed_type,
160                    )?;
161                }
162
163                RibIR::AssignVar(variable_id) => {
164                    internal::run_assign_var_instruction(variable_id, stack, interpreter_env)?;
165                }
166
167                RibIR::LoadVar(variable_id) => {
168                    internal::run_load_var_instruction(variable_id, stack, interpreter_env)?;
169                }
170
171                RibIR::IsEmpty => {
172                    internal::run_is_empty_instruction(stack)?;
173                }
174
175                RibIR::JumpIfFalse(instruction_id) => {
176                    internal::run_jump_if_false_instruction(
177                        instruction_id,
178                        &mut byte_code_cursor,
179                        stack,
180                    )?;
181                }
182
183                RibIR::SelectField(field_name) => {
184                    internal::run_select_field_instruction(field_name, stack)?;
185                }
186
187                RibIR::SelectIndex(index) => {
188                    internal::run_select_index_instruction(stack, index)?;
189                }
190
191                RibIR::SelectIndexV1 => {
192                    internal::run_select_index_v1_instruction(stack)?;
193                }
194
195                RibIR::CreateFunctionName(site, function_type) => {
196                    internal::run_create_function_name_instruction(site, function_type, stack)?;
197                }
198
199                RibIR::InvokeFunction(worker_type, arg_size, _) => {
200                    internal::run_call_instruction(arg_size, worker_type, stack, interpreter_env)
201                        .await?;
202                }
203
204                RibIR::PushVariant(variant_name, analysed_type) => {
205                    internal::run_variant_construction_instruction(
206                        variant_name,
207                        analysed_type,
208                        stack,
209                    )
210                    .await?;
211                }
212
213                RibIR::PushEnum(enum_name, analysed_type) => {
214                    internal::run_push_enum_instruction(stack, enum_name, analysed_type)?;
215                }
216
217                RibIR::Throw(message) => {
218                    return Err(message);
219                }
220
221                RibIR::GetTag => {
222                    internal::run_get_tag_instruction(stack)?;
223                }
224
225                RibIR::Deconstruct => {
226                    internal::run_deconstruct_instruction(stack)?;
227                }
228
229                RibIR::Jump(instruction_id) => {
230                    byte_code_cursor.move_to(&instruction_id).ok_or_else(|| {
231                        format!(
232                            "internal error. Failed to move to label {}",
233                            instruction_id.index
234                        )
235                    })?;
236                }
237
238                RibIR::PushSome(analysed_type) => {
239                    internal::run_create_some_instruction(stack, analysed_type)?;
240                }
241                RibIR::PushNone(analysed_type) => {
242                    internal::run_create_none_instruction(stack, analysed_type)?;
243                }
244                RibIR::PushOkResult(analysed_type) => {
245                    internal::run_create_ok_instruction(stack, analysed_type)?;
246                }
247                RibIR::PushErrResult(analysed_type) => {
248                    internal::run_create_err_instruction(stack, analysed_type)?;
249                }
250                RibIR::Concat(arg_size) => {
251                    internal::run_concat_instruction(stack, arg_size)?;
252                }
253                RibIR::PushTuple(analysed_type, arg_size) => {
254                    internal::run_push_tuple_instruction(arg_size, analysed_type, stack)?;
255                }
256                RibIR::Negate => {
257                    internal::run_negate_instruction(stack)?;
258                }
259
260                RibIR::Label(_) => {}
261
262                RibIR::And => {
263                    internal::run_and_instruction(stack)?;
264                }
265
266                RibIR::Or => {
267                    internal::run_or_instruction(stack)?;
268                }
269                RibIR::ToIterator => {
270                    internal::run_to_iterator(stack)?;
271                }
272                RibIR::CreateSink(analysed_type) => {
273                    internal::run_create_sink_instruction(stack, &analysed_type)?
274                }
275                RibIR::AdvanceIterator => {
276                    internal::run_advance_iterator_instruction(stack)?;
277                }
278                RibIR::PushToSink => {
279                    internal::run_push_to_sink_instruction(stack)?;
280                }
281
282                RibIR::SinkToList => {
283                    internal::run_sink_to_list_instruction(stack)?;
284                }
285
286                RibIR::Length => {
287                    internal::run_length_instruction(stack)?;
288                }
289            }
290        }
291
292        let stack_value = stack
293            .pop()
294            .unwrap_or_else(|| RibInterpreterStackValue::Unit);
295
296        let rib_result = RibResult::from_rib_interpreter_stack_value(&stack_value)
297            .ok_or_else(|| "Failed to obtain a valid result from rib execution".to_string())?;
298
299        Ok(rib_result)
300    }
301}
302
303mod internal {
304    use crate::interpreter::env::{EnvironmentKey, InterpreterEnv};
305    use crate::interpreter::interpreter_stack_value::RibInterpreterStackValue;
306    use crate::interpreter::literal::LiteralValue;
307    use crate::interpreter::stack::InterpreterStack;
308    use crate::{
309        CoercedNumericValue, EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName,
310        FunctionReferenceType, InstructionId, ParsedFunctionName, ParsedFunctionReference,
311        ParsedFunctionSite, RibFunctionInvoke, VariableId, WorkerNamePresence,
312    };
313    use golem_wasm_ast::analysis::AnalysedType;
314    use golem_wasm_ast::analysis::TypeResult;
315    use golem_wasm_rpc::{print_value_and_type, IntoValueAndType, Value, ValueAndType};
316
317    use crate::interpreter::instruction_cursor::RibByteCodeCursor;
318    use async_trait::async_trait;
319    use golem_wasm_ast::analysis::analysed_type::{tuple, u64};
320    use std::ops::Deref;
321
322    pub(crate) struct NoopRibFunctionInvoke;
323
324    #[async_trait]
325    impl RibFunctionInvoke for NoopRibFunctionInvoke {
326        async fn invoke(
327            &self,
328            _worker_name: Option<EvaluatedWorkerName>,
329            _function_name: EvaluatedFqFn,
330            _args: EvaluatedFnArgs,
331        ) -> Result<ValueAndType, String> {
332            Ok(ValueAndType {
333                value: Value::Tuple(vec![]),
334                typ: tuple(vec![]),
335            })
336        }
337    }
338
339    pub(crate) fn run_is_empty_instruction(
340        interpreter_stack: &mut InterpreterStack,
341    ) -> Result<(), String> {
342        let rib_result = interpreter_stack.pop().ok_or_else(|| {
343            "internal Error: Failed to get a value from the stack to do check is_empty".to_string()
344        })?;
345
346        let bool_opt = match rib_result {
347            RibInterpreterStackValue::Val(ValueAndType {
348                value: Value::List(items),
349                ..
350            }) => Some(items.is_empty()),
351            RibInterpreterStackValue::Iterator(iter) => {
352                let mut peekable_iter = iter.peekable();
353                let result = peekable_iter.peek().is_some();
354                interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(peekable_iter)));
355                Some(result)
356            }
357            RibInterpreterStackValue::Sink(values, analysed_type) => {
358                let possible_iterator = interpreter_stack.pop().ok_or_else(|| {
359                    "internal error: Expecting an iterator to check is empty".to_string()
360                })?;
361
362                match possible_iterator {
363                    RibInterpreterStackValue::Iterator(iter) => {
364                        let mut peekable_iter = iter.peekable();
365                        let result = peekable_iter.peek().is_some();
366                        interpreter_stack
367                            .push(RibInterpreterStackValue::Iterator(Box::new(peekable_iter)));
368                        interpreter_stack
369                            .push(RibInterpreterStackValue::Sink(values, analysed_type));
370                        Some(result)
371                    }
372
373                    _ => None,
374                }
375            }
376            RibInterpreterStackValue::Val(_) => None,
377            RibInterpreterStackValue::Unit => None,
378        };
379
380        let bool = bool_opt.ok_or("internal error: Failed to run instruction is_empty")?;
381        interpreter_stack.push_val(bool.into_value_and_type());
382        Ok(())
383    }
384
385    pub(crate) fn run_jump_if_false_instruction(
386        instruction_id: InstructionId,
387        instruction_stack: &mut RibByteCodeCursor,
388        interpreter_stack: &mut InterpreterStack,
389    ) -> Result<(), String> {
390        let predicate = interpreter_stack.try_pop_bool()?;
391
392        // Jump if predicate is false
393        if !predicate {
394            instruction_stack.move_to(&instruction_id).ok_or_else(|| {
395                format!(
396                    "internal error: Failed to move to the instruction at {}",
397                    instruction_id.index
398                )
399            })?;
400        }
401
402        Ok(())
403    }
404
405    pub(crate) fn run_to_iterator(interpreter_stack: &mut InterpreterStack) -> Result<(), String> {
406        let popped_up = interpreter_stack
407            .pop()
408            .ok_or_else(|| "internal error: failed to get a value from the stack".to_string())?;
409
410        let value_and_type = popped_up
411            .get_val()
412            .ok_or_else(|| "internal error: failed to get a value from the stack".to_string())?;
413
414        match (value_and_type.value, value_and_type.typ) {
415            (Value::List(items), AnalysedType::List(item_type)) => {
416                let items = items
417                    .into_iter()
418                    .map(|item| ValueAndType::new(item, (*item_type.inner).clone()))
419                    .collect::<Vec<_>>();
420
421                interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(
422                    items.into_iter(),
423                )));
424
425                Ok(())
426            }
427            (Value::Record(fields), AnalysedType::Record(record_type)) => {
428                let mut from: Option<usize> = None;
429                let mut to: Option<usize> = None;
430                let mut inclusive = false;
431
432                let value_and_names = fields.into_iter().zip(record_type.fields);
433
434                for (value, name_and_type) in value_and_names {
435                    match name_and_type.name.as_str() {
436                        "from" => {
437                            from =
438                                Some(to_num(&value).ok_or_else(|| {
439                                    format!("cannot cast {:?} to a number", value)
440                                })?)
441                        }
442                        "to" => {
443                            to =
444                                Some(to_num(&value).ok_or_else(|| {
445                                    format!("cannot cast {:?} to a number", value)
446                                })?)
447                        }
448                        "inclusive" => {
449                            inclusive = match value {
450                                Value::Bool(b) => b,
451                                _ => return Err("inclusive field should be a boolean".to_string()),
452                            }
453                        }
454                        _ => return Err(format!("Invalid field name {}", name_and_type.name)),
455                    }
456                }
457
458                match (from, to) {
459                    (Some(from), Some(to)) => {
460                        if inclusive {
461                            interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(
462                                (from..=to)
463                                    .map(|i| ValueAndType::new(Value::U64(i as u64), u64())),
464                            )));
465                        } else {
466                            interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(
467                                (from..to)
468                                    .map(|i| ValueAndType::new(Value::U64(i as u64), u64())),
469                            )));
470                        }
471                    }
472
473                    (None, Some(to)) => {
474                        if inclusive {
475                            interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(
476                                (0..=to)
477                                    .map(|i| ValueAndType::new(Value::U64(i as u64), u64())),
478                            )));
479                        } else {
480                            interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(
481                                (0..to)
482                                    .map(|i| ValueAndType::new(Value::U64(i as u64), u64())),
483                            )));
484                        }
485                    }
486
487                    // avoiding panicking with stack overflow for rib like the following
488                    // for i in 0.. {
489                    //   yield i
490                    // }
491                    (Some(_), None) => {
492                        return Err("an infinite range is being iterated. make sure range is finite to avoid infinite computation".to_string())
493                    }
494
495                    (None, None) => {
496                        interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new({
497                            let range = 0..;
498                            range
499                                .into_iter()
500                                .map(|i| ValueAndType::new(Value::U64(i as u64), u64()))
501                        })));
502                    }
503                };
504
505                Ok(())
506            }
507
508            _ => Err("internal error: failed to convert to an iterator".to_string()),
509        }
510    }
511
512    fn to_num(value: &Value) -> Option<usize> {
513        match value {
514            Value::U64(u64) => Some(*u64 as usize),
515            Value::Bool(_) => None,
516            Value::U8(u8) => Some(*u8 as usize),
517            Value::U16(u16) => Some(*u16 as usize),
518            Value::U32(u32) => Some(*u32 as usize),
519            Value::S8(s8) => Some(*s8 as usize),
520            Value::S16(s16) => Some(*s16 as usize),
521            Value::S32(s32) => Some(*s32 as usize),
522            Value::S64(s64) => Some(*s64 as usize),
523            Value::F32(f32) => Some(*f32 as usize),
524            Value::F64(f64) => Some(*f64 as usize),
525            _ => None,
526        }
527    }
528
529    pub(crate) fn run_create_sink_instruction(
530        interpreter_stack: &mut InterpreterStack,
531        analysed_type: &AnalysedType,
532    ) -> Result<(), String> {
533        let analysed_type = match analysed_type {
534            AnalysedType::List(type_list) => type_list.clone().inner,
535            _ => return Err("Expecting a list type to create sink".to_string()),
536        };
537        interpreter_stack.create_sink(analysed_type.deref());
538        Ok(())
539    }
540
541    pub(crate) fn run_advance_iterator_instruction(
542        interpreter_stack: &mut InterpreterStack,
543    ) -> Result<(), String> {
544        let mut rib_result = interpreter_stack
545            .pop()
546            .ok_or_else(|| "internal error: failed to advance the iterator".to_string())?;
547
548        match &mut rib_result {
549            RibInterpreterStackValue::Sink(_, _) => {
550                let mut existing_iterator = interpreter_stack
551                    .pop()
552                    .ok_or("internal error: failed to get an iterator")?;
553
554                match &mut existing_iterator {
555                    RibInterpreterStackValue::Iterator(iter) => {
556                        if let Some(value_and_type) = iter.next() {
557                            interpreter_stack.push(existing_iterator);
558                            interpreter_stack.push(rib_result);
559                            interpreter_stack.push(RibInterpreterStackValue::Val(value_and_type));
560                            Ok(())
561                        } else {
562                            Err("no more items found in the iterator".to_string())
563                        }
564                    }
565
566                    _ => Err(
567                        "internal error: A sink cannot exist without a corresponding iterator"
568                            .to_string(),
569                    ),
570                }
571            }
572
573            RibInterpreterStackValue::Iterator(iter) => {
574                if let Some(value_and_type) = iter.next() {
575                    interpreter_stack.push(rib_result);
576                    interpreter_stack.push(RibInterpreterStackValue::Val(value_and_type));
577                    Ok(())
578                } else {
579                    Err("no more items found in the iterator".to_string())
580                }
581            }
582            _ => Err("internal Error: expected an iterator".to_string()),
583        }
584    }
585
586    pub(crate) fn run_push_to_sink_instruction(
587        interpreter_stack: &mut InterpreterStack,
588    ) -> Result<(), String> {
589        let last_value = interpreter_stack.pop_val();
590        match last_value {
591            Some(val) => {
592                interpreter_stack.push_to_sink(val)?;
593
594                Ok(())
595            }
596            _ => Err("Failed to push values to sink".to_string()),
597        }
598    }
599
600    pub(crate) fn run_sink_to_list_instruction(
601        interpreter_stack: &mut InterpreterStack,
602    ) -> Result<(), String> {
603        let (result, analysed_type) = interpreter_stack
604            .pop_sink()
605            .ok_or("Failed to retrieve items from sink")?;
606
607        interpreter_stack.push_list(
608            result.into_iter().map(|vnt| vnt.value).collect(),
609            &analysed_type,
610        );
611
612        Ok(())
613    }
614
615    pub(crate) fn run_length_instruction(
616        interpreter_stack: &mut InterpreterStack,
617    ) -> Result<(), String> {
618        let rib_result = interpreter_stack
619            .pop()
620            .ok_or("internal error: failed to get a value from the stack")?;
621
622        let length = match rib_result {
623            RibInterpreterStackValue::Val(ValueAndType {
624                value: Value::List(items),
625                ..
626            }) => items.len(),
627            RibInterpreterStackValue::Iterator(iter) => iter.count(),
628            _ => return Err("internal error: failed to get the length of the value".to_string()),
629        };
630
631        interpreter_stack.push_val(ValueAndType::new(Value::U64(length as u64), u64()));
632        Ok(())
633    }
634
635    pub(crate) fn run_assign_var_instruction(
636        variable_id: VariableId,
637        interpreter_stack: &mut InterpreterStack,
638        interpreter_env: &mut InterpreterEnv,
639    ) -> Result<(), String> {
640        let value = interpreter_stack.pop().ok_or_else(|| {
641            "Expected a value on the stack before assigning a variable".to_string()
642        })?;
643        let env_key = EnvironmentKey::from(variable_id);
644
645        interpreter_env.insert(env_key, value);
646        Ok(())
647    }
648
649    pub(crate) fn run_load_var_instruction(
650        variable_id: VariableId,
651        interpreter_stack: &mut InterpreterStack,
652        interpreter_env: &mut InterpreterEnv,
653    ) -> Result<(), String> {
654        let env_key = EnvironmentKey::from(variable_id.clone());
655        let value = interpreter_env.lookup(&env_key).ok_or_else(|| {
656            format!(
657                "`{}` not found. If this is a global input, pass it to the rib interpreter",
658                variable_id
659            )
660        })?;
661
662        match value {
663            RibInterpreterStackValue::Unit => {
664                interpreter_stack.push(RibInterpreterStackValue::Unit);
665            }
666            RibInterpreterStackValue::Val(val) => interpreter_stack.push_val(val.clone()),
667            RibInterpreterStackValue::Iterator(_) => {
668                return Err("Unable to assign an iterator to a variable".to_string())
669            }
670            RibInterpreterStackValue::Sink(_, _) => {
671                return Err("Unable to assign a sink to a variable".to_string())
672            }
673        }
674
675        Ok(())
676    }
677
678    pub(crate) fn run_create_record_instruction(
679        analysed_type: AnalysedType,
680        interpreter_stack: &mut InterpreterStack,
681    ) -> Result<(), String> {
682        let name_type_pair = match analysed_type {
683            AnalysedType::Record(type_record) => type_record.fields,
684            _ => {
685                return Err(format!(
686                    "internal error: expected a record type to create a record, but obtained {:?}",
687                    analysed_type
688                ))
689            }
690        };
691
692        interpreter_stack.create_record(name_type_pair);
693        Ok(())
694    }
695
696    pub(crate) fn run_update_record_instruction(
697        field_name: String,
698        interpreter_stack: &mut InterpreterStack,
699    ) -> Result<(), String> {
700        let (current_record_fields, record_type) = interpreter_stack.try_pop_record()?;
701
702        let idx = record_type
703            .fields
704            .iter()
705            .position(|pair| pair.name == field_name)
706            .ok_or_else(|| {
707                format!(
708                    "Invalid field name {field_name}, should be one of {}",
709                    record_type
710                        .fields
711                        .iter()
712                        .map(|pair| pair.name.clone())
713                        .collect::<Vec<_>>()
714                        .join(", ")
715                )
716            })?;
717        let value = interpreter_stack.try_pop_val()?;
718
719        let mut fields = current_record_fields;
720        fields[idx] = value.value;
721
722        interpreter_stack.push_val(ValueAndType {
723            value: Value::Record(fields),
724            typ: AnalysedType::Record(record_type),
725        });
726        Ok(())
727    }
728
729    pub(crate) fn run_push_list_instruction(
730        list_size: usize,
731        analysed_type: AnalysedType,
732        interpreter_stack: &mut InterpreterStack,
733    ) -> Result<(), String> {
734        match analysed_type {
735            AnalysedType::List(inner_type) => {
736                let items =
737                    interpreter_stack.try_pop_n_val(list_size)?;
738
739
740                interpreter_stack.push_list(items.into_iter().map(|vnt| vnt.value).collect(), inner_type.inner.deref());
741
742                Ok(())
743            }
744
745            _ => Err(format!("internal error: failed to create tuple due to mismatch in types. expected: list, actual: {:?}", analysed_type)),
746        }
747    }
748
749    pub(crate) fn run_push_tuple_instruction(
750        list_size: usize,
751        analysed_type: AnalysedType,
752        interpreter_stack: &mut InterpreterStack,
753    ) -> Result<(), String> {
754        match analysed_type {
755            AnalysedType::Tuple(_inner_type) => {
756                let items =
757                    interpreter_stack.try_pop_n_val(list_size)?;
758                interpreter_stack.push_tuple(items);
759                Ok(())
760            }
761
762            _ => Err(format!("internal error: failed to create tuple due to mismatch in types. expected: tuple, actual: {:?}", analysed_type)),
763        }
764    }
765
766    pub(crate) fn run_negate_instruction(
767        interpreter_stack: &mut InterpreterStack,
768    ) -> Result<(), String> {
769        let bool = interpreter_stack.try_pop_bool()?;
770        let negated = !bool;
771
772        interpreter_stack.push_val(negated.into_value_and_type());
773        Ok(())
774    }
775
776    pub(crate) fn run_and_instruction(
777        interpreter_stack: &mut InterpreterStack,
778    ) -> Result<(), String> {
779        let left = interpreter_stack.try_pop()?;
780        let right = interpreter_stack.try_pop()?;
781
782        let result = left.compare(&right, |a, b| match (a.get_bool(), b.get_bool()) {
783            (Some(a), Some(b)) => a && b,
784            _ => false,
785        })?;
786
787        interpreter_stack.push(result);
788
789        Ok(())
790    }
791
792    pub(crate) fn run_or_instruction(
793        interpreter_stack: &mut InterpreterStack,
794    ) -> Result<(), String> {
795        let left = interpreter_stack.try_pop()?;
796        let right = interpreter_stack.try_pop()?;
797
798        let result = left.compare(&right, |a, b| match (a.get_bool(), b.get_bool()) {
799            (Some(a), Some(b)) => a || b,
800            _ => false,
801        })?;
802
803        interpreter_stack.push(result);
804
805        Ok(())
806    }
807
808    pub(crate) fn run_math_instruction(
809        interpreter_stack: &mut InterpreterStack,
810        compare_fn: fn(CoercedNumericValue, CoercedNumericValue) -> CoercedNumericValue,
811        target_numerical_type: &AnalysedType,
812    ) -> Result<(), String> {
813        let left = interpreter_stack.try_pop()?;
814        let right = interpreter_stack.try_pop()?;
815
816        let result = left.evaluate_math_op(&right, compare_fn)?;
817        let numerical_type = result.cast_to(target_numerical_type).ok_or_else(|| {
818            format!(
819                "failed to cast number {} to {:?}",
820                result, target_numerical_type
821            )
822        })?;
823
824        interpreter_stack.push_val(numerical_type);
825
826        Ok(())
827    }
828
829    pub(crate) fn run_compare_instruction(
830        interpreter_stack: &mut InterpreterStack,
831        compare_fn: fn(LiteralValue, LiteralValue) -> bool,
832    ) -> Result<(), String> {
833        let left = interpreter_stack.try_pop()?;
834        let right = interpreter_stack.try_pop()?;
835
836        let result = left.compare(&right, compare_fn)?;
837
838        interpreter_stack.push(result);
839
840        Ok(())
841    }
842
843    // Kept for backward compatibility with byte code
844    pub(crate) fn run_select_field_instruction(
845        field_name: String,
846        interpreter_stack: &mut InterpreterStack,
847    ) -> Result<(), String> {
848        let record = interpreter_stack.try_pop()?;
849
850        match record {
851            RibInterpreterStackValue::Val(ValueAndType {
852                value: Value::Record(field_values),
853                typ: AnalysedType::Record(typ),
854            }) => {
855                let field = field_values
856                    .into_iter()
857                    .zip(typ.fields)
858                    .find(|(_value, field)| field.name == field_name)
859                    .ok_or_else(|| format!("Field {} not found in the record", field_name))?;
860
861                let value = field.0;
862                interpreter_stack.push_val(ValueAndType::new(value, field.1.typ));
863                Ok(())
864            }
865            result => {
866                let stack_value_as_string = String::try_from(result)?;
867
868                Err(format!(
869                    "Unable to select field `{}` as the input `{}` is not a `record` type",
870                    field_name, stack_value_as_string
871                ))
872            }
873        }
874    }
875
876    pub(crate) fn run_select_index_v1_instruction(
877        interpreter_stack: &mut InterpreterStack,
878    ) -> Result<(), String> {
879        let stack_list_value = interpreter_stack
880            .pop()
881            .ok_or_else(|| "internal error: failed to get value from the stack".to_string())?;
882
883        let index_value = interpreter_stack
884            .pop()
885            .ok_or("internal error: failed to get the index expression from the stack")?;
886
887        match stack_list_value {
888            RibInterpreterStackValue::Val(ValueAndType {
889                value: Value::List(items),
890                typ: AnalysedType::List(typ),
891            }) => match index_value.get_literal().and_then(|v| v.get_number()) {
892                Some(CoercedNumericValue::PosInt(index)) => {
893                    let value = items
894                        .get(index as usize)
895                        .ok_or_else(|| format!(
896                            "index {} is out of bound in the list of length {}",
897                            index,
898                            items.len()
899                        ))?
900                        .clone();
901
902                    interpreter_stack.push_val(ValueAndType::new(value, (*typ.inner).clone()));
903                    Ok(())
904                }
905                _ => Err("internal error: range selection not supported at byte code level. missing desugar phase".to_string()),
906            },
907            RibInterpreterStackValue::Val(ValueAndType {
908                value: Value::Tuple(items),
909                typ: AnalysedType::Tuple(typ),
910            }) => match index_value.get_literal().and_then(|v| v.get_number()) {
911                Some(CoercedNumericValue::PosInt(index)) => {
912                    let value = items
913                        .get(index as usize)
914                        .ok_or_else(|| format!(
915                            "index {} is out of bound in a tuple of length {}",
916                            index,
917                            items.len()
918                        ))?
919                        .clone();
920
921                    let item_type = typ
922                        .items
923                        .get(index as usize)
924                        .ok_or_else(|| format!(
925                            "internal error: type not found in the tuple at index {}",
926                            index
927                        ))?
928                        .clone();
929
930                    interpreter_stack.push_val(ValueAndType::new(value, item_type));
931                    Ok(())
932                }
933                _ => Err("expected a number to select an index from tuple".to_string()),
934            },
935            result => Err(format!(
936                "expected a sequence value or tuple to select an index. But obtained {:?}",
937                result
938            )),
939        }
940    }
941
942    pub(crate) fn run_select_index_instruction(
943        interpreter_stack: &mut InterpreterStack,
944        index: usize,
945    ) -> Result<(), String> {
946        let stack_value = interpreter_stack
947            .pop()
948            .ok_or_else(|| "internal error: failed to get value from the stack".to_string())?;
949
950        match stack_value {
951            RibInterpreterStackValue::Val(ValueAndType {
952                value: Value::List(items),
953                typ: AnalysedType::List(typ),
954            }) => {
955                let value = items
956                    .get(index)
957                    .ok_or_else(|| {
958                        format!(
959                            "index {} is out of bound. list size: {}",
960                            index,
961                            items.len()
962                        )
963                    })?
964                    .clone();
965
966                interpreter_stack.push_val(ValueAndType::new(value, (*typ.inner).clone()));
967                Ok(())
968            }
969            RibInterpreterStackValue::Val(ValueAndType {
970                value: Value::Tuple(items),
971                typ: AnalysedType::Tuple(typ),
972            }) => {
973                let value = items
974                    .get(index)
975                    .ok_or_else(|| format!("Index {} not found in the tuple", index))?
976                    .clone();
977
978                let item_type = typ
979                    .items
980                    .get(index)
981                    .ok_or_else(|| format!("Index {} not found in the tuple type", index))?
982                    .clone();
983
984                interpreter_stack.push_val(ValueAndType::new(value, item_type));
985                Ok(())
986            }
987            result => Err(format!(
988                "Expected a sequence value or tuple to select an index. But obtained {:?}",
989                result
990            )),
991        }
992    }
993
994    pub(crate) fn run_push_enum_instruction(
995        interpreter_stack: &mut InterpreterStack,
996        enum_name: String,
997        analysed_type: AnalysedType,
998    ) -> Result<(), String> {
999        match analysed_type {
1000            AnalysedType::Enum(typed_enum) => {
1001                interpreter_stack.push_enum(enum_name, typed_enum.cases)?;
1002                Ok(())
1003            }
1004            _ => Err(format!(
1005                "Expected a enum type for {}, but obtained {:?}",
1006                enum_name, analysed_type
1007            )),
1008        }
1009    }
1010
1011    pub(crate) async fn run_variant_construction_instruction(
1012        variant_name: String,
1013        analysed_type: AnalysedType,
1014        interpreter_stack: &mut InterpreterStack,
1015    ) -> Result<(), String> {
1016        match analysed_type {
1017            AnalysedType::Variant(variants) => {
1018                let variant = variants
1019                    .cases
1020                    .iter()
1021                    .find(|name| name.name == variant_name)
1022                    .ok_or_else(|| format!("unknown variant {} not found", variant_name))?;
1023
1024                let variant_arg_typ = variant.typ.clone();
1025
1026                let arg_value = match variant_arg_typ {
1027                    Some(_) => Some(interpreter_stack.try_pop_val()?),
1028                    None => None,
1029                };
1030
1031                interpreter_stack.push_variant(
1032                    variant_name.clone(),
1033                    arg_value.map(|vnt| vnt.value),
1034                    variants.cases.clone(),
1035                )
1036            }
1037
1038            _ => Err(format!(
1039                "internal error: expected a variant type for {}, but obtained {:?}",
1040                variant_name, analysed_type
1041            )),
1042        }
1043    }
1044
1045    pub(crate) fn run_create_function_name_instruction(
1046        site: ParsedFunctionSite,
1047        function_type: FunctionReferenceType,
1048        interpreter_stack: &mut InterpreterStack,
1049    ) -> Result<(), String> {
1050        match function_type {
1051            FunctionReferenceType::Function { function } => {
1052                let parsed_function_name = ParsedFunctionName {
1053                    site,
1054                    function: ParsedFunctionReference::Function { function },
1055                };
1056
1057                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1058            }
1059
1060            FunctionReferenceType::RawResourceConstructor { resource } => {
1061                let parsed_function_name = ParsedFunctionName {
1062                    site,
1063                    function: ParsedFunctionReference::RawResourceConstructor { resource },
1064                };
1065
1066                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1067            }
1068            FunctionReferenceType::RawResourceDrop { resource } => {
1069                let parsed_function_name = ParsedFunctionName {
1070                    site,
1071                    function: ParsedFunctionReference::RawResourceDrop { resource },
1072                };
1073
1074                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1075            }
1076            FunctionReferenceType::RawResourceMethod { resource, method } => {
1077                let parsed_function_name = ParsedFunctionName {
1078                    site,
1079                    function: ParsedFunctionReference::RawResourceMethod { resource, method },
1080                };
1081
1082                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1083            }
1084            FunctionReferenceType::RawResourceStaticMethod { resource, method } => {
1085                let parsed_function_name = ParsedFunctionName {
1086                    site,
1087                    function: ParsedFunctionReference::RawResourceStaticMethod { resource, method },
1088                };
1089
1090                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1091            }
1092            FunctionReferenceType::IndexedResourceConstructor { resource, arg_size } => {
1093                let last_n_elements = interpreter_stack
1094                    .pop_n(arg_size)
1095                    .ok_or_else(|| "Failed to get values from the stack".to_string())?;
1096
1097                let parameter_values = last_n_elements
1098                    .iter()
1099                    .map(|interpreter_result| {
1100                        interpreter_result.get_val().ok_or_else(|| {
1101                            "internal error: failed to construct resource".to_string()
1102                        })
1103                    })
1104                    .collect::<Result<Vec<ValueAndType>, String>>()?;
1105
1106                let parsed_function_name = ParsedFunctionName {
1107                    site,
1108                    function: ParsedFunctionReference::IndexedResourceConstructor {
1109                        resource,
1110                        resource_params: parameter_values
1111                            .iter()
1112                            .map(print_value_and_type)
1113                            .collect::<Result<Vec<String>, String>>()?,
1114                    },
1115                };
1116
1117                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1118            }
1119            FunctionReferenceType::IndexedResourceMethod {
1120                resource,
1121                arg_size,
1122                method,
1123            } => {
1124                let last_n_elements = interpreter_stack
1125                    .pop_n(arg_size)
1126                    .ok_or_else(|| "Failed to get values from the stack".to_string())?;
1127
1128                let param_values = last_n_elements
1129                    .iter()
1130                    .map(|interpreter_result| {
1131                        interpreter_result.get_val().ok_or_else(|| {
1132                            "internal error: failed to call indexed resource method".to_string()
1133                        })
1134                    })
1135                    .collect::<Result<Vec<ValueAndType>, String>>()?;
1136
1137                let parsed_function_name = ParsedFunctionName {
1138                    site,
1139                    function: ParsedFunctionReference::IndexedResourceMethod {
1140                        resource,
1141                        resource_params: param_values
1142                            .iter()
1143                            .map(print_value_and_type)
1144                            .collect::<Result<Vec<String>, String>>()?,
1145                        method,
1146                    },
1147                };
1148
1149                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1150            }
1151            FunctionReferenceType::IndexedResourceStaticMethod {
1152                resource,
1153                arg_size,
1154                method,
1155            } => {
1156                let last_n_elements = interpreter_stack.pop_n(arg_size).ok_or_else(|| {
1157                    "internal error: Failed to get arguments for static resource method".to_string()
1158                })?;
1159
1160                let param_values = last_n_elements
1161                    .iter()
1162                    .map(|interpreter_result| {
1163                        interpreter_result.get_val().ok_or_else(|| {
1164                            "internal error: Failed to call static resource method".to_string()
1165                        })
1166                    })
1167                    .collect::<Result<Vec<ValueAndType>, String>>()?;
1168
1169                let parsed_function_name = ParsedFunctionName {
1170                    site,
1171                    function: ParsedFunctionReference::IndexedResourceStaticMethod {
1172                        resource,
1173                        resource_params: param_values
1174                            .iter()
1175                            .map(print_value_and_type)
1176                            .collect::<Result<Vec<String>, String>>()?,
1177                        method,
1178                    },
1179                };
1180
1181                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1182            }
1183            FunctionReferenceType::IndexedResourceDrop { resource, arg_size } => {
1184                let last_n_elements = interpreter_stack.pop_n(arg_size).ok_or_else(|| {
1185                    "internal error: failed to get resource parameters for indexed resource drop"
1186                        .to_string()
1187                })?;
1188
1189                let param_values = last_n_elements
1190                    .iter()
1191                    .map(|interpreter_result| {
1192                        interpreter_result.get_val().ok_or_else(|| {
1193                            "internal error: failed to call indexed resource drop".to_string()
1194                        })
1195                    })
1196                    .collect::<Result<Vec<ValueAndType>, String>>()?;
1197
1198                let parsed_function_name = ParsedFunctionName {
1199                    site,
1200                    function: ParsedFunctionReference::IndexedResourceDrop {
1201                        resource,
1202                        resource_params: param_values
1203                            .iter()
1204                            .map(print_value_and_type)
1205                            .collect::<Result<Vec<String>, String>>()?,
1206                    },
1207                };
1208
1209                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1210            }
1211        }
1212
1213        Ok(())
1214    }
1215
1216    pub(crate) async fn run_call_instruction(
1217        arg_size: usize,
1218        worker_type: WorkerNamePresence,
1219        interpreter_stack: &mut InterpreterStack,
1220        interpreter_env: &mut InterpreterEnv,
1221    ) -> Result<(), String> {
1222        let function_name = interpreter_stack
1223            .pop_str()
1224            .ok_or_else(|| "internal error: failed to get a function name".to_string())?;
1225
1226        let worker_name = match worker_type {
1227            WorkerNamePresence::Present => {
1228                let worker_name = interpreter_stack
1229                    .pop_str()
1230                    .ok_or_else(|| "internal error: failed to get the worker name".to_string())?;
1231
1232                Some(worker_name.clone())
1233            }
1234            WorkerNamePresence::Absent => None,
1235        };
1236
1237        let last_n_elements = interpreter_stack.pop_n(arg_size).ok_or_else(|| {
1238            "internal error: failed to get arguments for the function call".to_string()
1239        })?;
1240
1241        let parameter_values = last_n_elements
1242            .iter()
1243            .map(|interpreter_result| {
1244                interpreter_result.get_val().ok_or_else(|| {
1245                    format!("internal error: failed to call function {}", function_name)
1246                })
1247            })
1248            .collect::<Result<Vec<ValueAndType>, String>>()?;
1249
1250        let result = interpreter_env
1251            .invoke_worker_function_async(worker_name, function_name, parameter_values)
1252            .await?;
1253
1254        let interpreter_result = match result {
1255            ValueAndType {
1256                value: Value::Tuple(value),
1257                ..
1258            } if value.is_empty() => Ok(RibInterpreterStackValue::Unit),
1259            ValueAndType {
1260                value: Value::Tuple(value),
1261                typ: AnalysedType::Tuple(typ),
1262            } if value.len() == 1 => {
1263                let inner_value = value[0].clone();
1264                let inner_type = typ.items[0].clone();
1265                Ok(RibInterpreterStackValue::Val(ValueAndType::new(
1266                    inner_value,
1267                    inner_type,
1268                )))
1269            }
1270            _ => Err("Named multiple results are not supported yet".to_string()),
1271        };
1272
1273        interpreter_stack.push(interpreter_result?);
1274
1275        Ok(())
1276    }
1277    pub(crate) fn run_deconstruct_instruction(
1278        interpreter_stack: &mut InterpreterStack,
1279    ) -> Result<(), String> {
1280        let value = interpreter_stack
1281            .pop()
1282            .ok_or_else(|| "Failed to get a value from the stack to unwrap".to_string())?;
1283
1284        let unwrapped_value = value
1285            .unwrap()
1286            .ok_or_else(|| format!("Failed to unwrap the value {:?}", value))?;
1287
1288        interpreter_stack.push_val(unwrapped_value);
1289        Ok(())
1290    }
1291
1292    pub(crate) fn run_get_tag_instruction(
1293        interpreter_stack: &mut InterpreterStack,
1294    ) -> Result<(), String> {
1295        let value = interpreter_stack
1296            .pop_val()
1297            .ok_or_else(|| "Failed to get a tag value from the stack to unwrap".to_string())?;
1298
1299        let tag = match value {
1300            ValueAndType {
1301                value: Value::Variant { case_idx, .. },
1302                typ: AnalysedType::Variant(typ),
1303            } => typ.cases[case_idx as usize].name.clone(),
1304            ValueAndType {
1305                value: Value::Option(option),
1306                ..
1307            } => match option {
1308                Some(_) => "some".to_string(),
1309                None => "none".to_string(),
1310            },
1311            ValueAndType {
1312                value: Value::Result(result_value),
1313                ..
1314            } => match result_value {
1315                Ok(_) => "ok".to_string(),
1316                Err(_) => "err".to_string(),
1317            },
1318            ValueAndType {
1319                value: Value::Enum(idx),
1320                typ: AnalysedType::Enum(typ),
1321            } => typ.cases[idx as usize].clone(),
1322            _ => "untagged".to_string(),
1323        };
1324
1325        interpreter_stack.push_val(tag.into_value_and_type());
1326        Ok(())
1327    }
1328
1329    pub(crate) fn run_create_some_instruction(
1330        interpreter_stack: &mut InterpreterStack,
1331        analysed_type: AnalysedType,
1332    ) -> Result<(), String> {
1333        let value = interpreter_stack.try_pop_val()?;
1334
1335        match analysed_type {
1336            AnalysedType::Option(analysed_type) => {
1337                interpreter_stack.push_some(value.value, analysed_type.inner.deref());
1338                Ok(())
1339            }
1340            _ => Err(format!(
1341                "internal error: expected option type to create `some` value. But obtained {:?}",
1342                analysed_type
1343            )),
1344        }
1345    }
1346
1347    pub(crate) fn run_create_none_instruction(
1348        interpreter_stack: &mut InterpreterStack,
1349        analysed_type: Option<AnalysedType>,
1350    ) -> Result<(), String> {
1351        match analysed_type {
1352            Some(AnalysedType::Option(_)) | None => {
1353                interpreter_stack.push_none(analysed_type);
1354                Ok(())
1355            }
1356            _ => Err(format!(
1357                "internal error: expected option type to create `none` value. But obtained {:?}",
1358                analysed_type
1359            )),
1360        }
1361    }
1362
1363    pub(crate) fn run_create_ok_instruction(
1364        interpreter_stack: &mut InterpreterStack,
1365        analysed_type: AnalysedType,
1366    ) -> Result<(), String> {
1367        let value = interpreter_stack.try_pop_val()?;
1368
1369        match analysed_type {
1370            AnalysedType::Result(TypeResult { ok, err }) => {
1371                interpreter_stack.push_ok(value.value, ok.as_deref(), err.as_deref());
1372                Ok(())
1373            }
1374            _ => Err(format!(
1375                "internal error: expected result type to create `ok` value. But obtained {:?}",
1376                analysed_type
1377            )),
1378        }
1379    }
1380
1381    pub(crate) fn run_create_err_instruction(
1382        interpreter_stack: &mut InterpreterStack,
1383        analysed_type: AnalysedType,
1384    ) -> Result<(), String> {
1385        let value = interpreter_stack.try_pop_val()?;
1386
1387        match analysed_type {
1388            AnalysedType::Result(TypeResult { ok, err }) => {
1389                interpreter_stack.push_err(value.value, ok.as_deref(), err.as_deref());
1390                Ok(())
1391            }
1392            _ => Err(format!(
1393                "internal error: expected result type to create `err` value. But obtained {:?}",
1394                analysed_type
1395            )),
1396        }
1397    }
1398
1399    pub(crate) fn run_concat_instruction(
1400        interpreter_stack: &mut InterpreterStack,
1401        arg_size: usize,
1402    ) -> Result<(), String> {
1403        let literals = interpreter_stack.try_pop_n_literals(arg_size)?;
1404
1405        let str = literals
1406            .into_iter()
1407            .fold(String::new(), |mut acc, literal| {
1408                acc.push_str(&literal.as_string());
1409                acc
1410            });
1411
1412        interpreter_stack.push_val(str.into_value_and_type());
1413
1414        Ok(())
1415    }
1416}
1417
1418#[cfg(test)]
1419mod tests {
1420    use std::collections::HashMap;
1421    use test_r::test;
1422
1423    use super::*;
1424    use crate::interpreter::rib_interpreter::tests::test_utils::{
1425        get_value_and_type, strip_spaces,
1426    };
1427    use crate::{
1428        compiler, Expr, FunctionTypeRegistry, GlobalVariableTypeSpec, InferredType, InstructionId,
1429        Path, VariableId,
1430    };
1431    use golem_wasm_ast::analysis::analysed_type::{
1432        bool, case, f32, field, list, option, record, s32, s8, str, tuple, u32, u64, u8, variant,
1433    };
1434    use golem_wasm_rpc::{parse_value_and_type, IntoValue, IntoValueAndType, Value, ValueAndType};
1435
1436    #[test]
1437    async fn test_interpreter_for_literal() {
1438        let mut interpreter = Interpreter::default();
1439
1440        let instructions = RibByteCode {
1441            instructions: vec![RibIR::PushLit(1i32.into_value_and_type())],
1442        };
1443
1444        let result = interpreter.run(instructions).await.unwrap();
1445        assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1446    }
1447
1448    #[test]
1449    async fn test_interpreter_for_equal_to() {
1450        let mut interpreter = Interpreter::default();
1451
1452        let instructions = RibByteCode {
1453            instructions: vec![
1454                RibIR::PushLit(1i32.into_value_and_type()),
1455                RibIR::PushLit(1u32.into_value_and_type()),
1456                RibIR::EqualTo,
1457            ],
1458        };
1459
1460        let result = interpreter.run(instructions).await.unwrap();
1461        assert!(result.get_bool().unwrap());
1462    }
1463
1464    #[test]
1465    async fn test_interpreter_for_greater_than() {
1466        let mut interpreter = Interpreter::default();
1467
1468        let instructions = RibByteCode {
1469            instructions: vec![
1470                RibIR::PushLit(1i32.into_value_and_type()),
1471                RibIR::PushLit(2u32.into_value_and_type()),
1472                RibIR::GreaterThan,
1473            ],
1474        };
1475
1476        let result = interpreter.run(instructions).await.unwrap();
1477        assert!(result.get_bool().unwrap());
1478    }
1479
1480    #[test]
1481    async fn test_interpreter_for_less_than() {
1482        let mut interpreter = Interpreter::default();
1483
1484        let instructions = RibByteCode {
1485            instructions: vec![
1486                RibIR::PushLit(2i32.into_value_and_type()),
1487                RibIR::PushLit(1u32.into_value_and_type()),
1488                RibIR::LessThan,
1489            ],
1490        };
1491
1492        let result = interpreter.run(instructions).await.unwrap();
1493        assert!(result.get_bool().unwrap());
1494    }
1495
1496    #[test]
1497    async fn test_interpreter_for_greater_than_or_equal_to() {
1498        let mut interpreter = Interpreter::default();
1499
1500        let instructions = RibByteCode {
1501            instructions: vec![
1502                RibIR::PushLit(2i32.into_value_and_type()),
1503                RibIR::PushLit(3u32.into_value_and_type()),
1504                RibIR::GreaterThanOrEqualTo,
1505            ],
1506        };
1507
1508        let result = interpreter.run(instructions).await.unwrap();
1509        assert!(result.get_bool().unwrap());
1510    }
1511
1512    #[test]
1513    async fn test_interpreter_for_less_than_or_equal_to() {
1514        let mut interpreter = Interpreter::default();
1515
1516        let instructions = RibByteCode {
1517            instructions: vec![
1518                RibIR::PushLit(2i32.into_value_and_type()), // rhs
1519                RibIR::PushLit(1i32.into_value_and_type()), // lhs
1520                RibIR::LessThanOrEqualTo,
1521            ],
1522        };
1523
1524        let result = interpreter.run(instructions).await.unwrap();
1525        assert!(result.get_bool().unwrap());
1526    }
1527
1528    #[test]
1529    async fn test_interpreter_for_assign_and_load_var() {
1530        let mut interpreter = Interpreter::default();
1531
1532        let instructions = RibByteCode {
1533            instructions: vec![
1534                RibIR::PushLit(1i32.into_value_and_type()),
1535                RibIR::AssignVar(VariableId::local_with_no_id("x")),
1536                RibIR::LoadVar(VariableId::local_with_no_id("x")),
1537            ],
1538        };
1539
1540        let result = interpreter.run(instructions).await.unwrap();
1541        assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1542    }
1543
1544    #[test]
1545    async fn test_interpreter_for_jump() {
1546        let mut interpreter = Interpreter::default();
1547
1548        let instructions = RibByteCode {
1549            instructions: vec![
1550                RibIR::Jump(InstructionId::init()),
1551                RibIR::PushLit(1i32.into_value_and_type()),
1552                RibIR::Label(InstructionId::init()),
1553            ],
1554        };
1555
1556        let result = interpreter.run(instructions).await;
1557        assert!(result.is_ok());
1558    }
1559
1560    #[test]
1561    async fn test_interpreter_for_jump_if_false() {
1562        let mut interpreter = Interpreter::default();
1563
1564        let id = InstructionId::init().increment_mut();
1565
1566        let instructions = RibByteCode {
1567            instructions: vec![
1568                RibIR::PushLit(false.into_value_and_type()),
1569                RibIR::JumpIfFalse(id.clone()),
1570                RibIR::PushLit(1i32.into_value_and_type()),
1571                RibIR::Label(id),
1572            ],
1573        };
1574
1575        let result = interpreter.run(instructions).await;
1576        assert!(result.is_ok());
1577    }
1578
1579    #[test]
1580    async fn test_interpreter_for_record() {
1581        let mut interpreter = Interpreter::default();
1582
1583        let instructions = RibByteCode {
1584            instructions: vec![
1585                RibIR::PushLit(2i32.into_value_and_type()),
1586                RibIR::PushLit(1i32.into_value_and_type()),
1587                RibIR::CreateAndPushRecord(record(vec![field("x", s32()), field("y", s32())])),
1588                RibIR::UpdateRecord("x".to_string()),
1589                RibIR::UpdateRecord("y".to_string()),
1590            ],
1591        };
1592
1593        let result = interpreter.run(instructions).await.unwrap();
1594        let expected = ValueAndType::new(
1595            Value::Record(vec![1i32.into_value(), 2i32.into_value()]),
1596            record(vec![field("x", s32()), field("y", s32())]),
1597        );
1598
1599        assert_eq!(result.get_val().unwrap(), expected);
1600    }
1601
1602    #[test]
1603    async fn test_interpreter_for_sequence() {
1604        let mut interpreter = Interpreter::default();
1605
1606        let instructions = RibByteCode {
1607            instructions: vec![
1608                RibIR::PushLit(2i32.into_value_and_type()),
1609                RibIR::PushLit(1i32.into_value_and_type()),
1610                RibIR::PushList(list(s32()), 2),
1611            ],
1612        };
1613
1614        let result = interpreter.run(instructions).await.unwrap();
1615        let expected = ValueAndType::new(
1616            Value::List(vec![1i32.into_value(), 2i32.into_value()]),
1617            list(s32()),
1618        );
1619        assert_eq!(result.get_val().unwrap(), expected);
1620    }
1621
1622    #[test]
1623    async fn test_interpreter_for_select_field() {
1624        let mut interpreter = Interpreter::default();
1625
1626        let instructions = RibByteCode {
1627            instructions: vec![
1628                RibIR::PushLit(1i32.into_value_and_type()),
1629                RibIR::PushLit(2i32.into_value_and_type()),
1630                RibIR::CreateAndPushRecord(record(vec![field("x", s32())])),
1631                RibIR::UpdateRecord("x".to_string()),
1632                RibIR::SelectField("x".to_string()),
1633            ],
1634        };
1635
1636        let result = interpreter.run(instructions).await.unwrap();
1637        assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1638    }
1639
1640    #[test]
1641    async fn test_interpreter_for_select_index() {
1642        let mut interpreter = Interpreter::default();
1643
1644        let instructions = RibByteCode {
1645            instructions: vec![
1646                RibIR::PushLit(1i32.into_value_and_type()),
1647                RibIR::PushLit(2i32.into_value_and_type()),
1648                RibIR::PushList(list(s32()), 2),
1649                RibIR::SelectIndex(0),
1650            ],
1651        };
1652
1653        let result = interpreter.run(instructions).await.unwrap();
1654        assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1655    }
1656
1657    #[test]
1658    async fn test_interpreter_variable_scope_0() {
1659        let rib_expr = r#"
1660               let x: u64 = 1;
1661               let y = x + 2u64;
1662               y
1663            "#;
1664
1665        let expr = Expr::from_text(rib_expr).unwrap();
1666
1667        let compiled = compiler::compile(expr, &vec![]).unwrap();
1668
1669        let mut interpreter = Interpreter::default();
1670
1671        let result = interpreter.run(compiled.byte_code).await.unwrap();
1672
1673        assert_eq!(result.get_val().unwrap(), 3u64.into_value_and_type());
1674    }
1675
1676    #[test]
1677    async fn test_interpreter_variable_scope_1() {
1678        let rib_expr = r#"
1679               let x: u64 = 1;
1680               let z = {foo : x};
1681               let x = x + 2u64;
1682               { bar: x, baz: z }
1683            "#;
1684
1685        let expr = Expr::from_text(rib_expr).unwrap();
1686
1687        let compiled = compiler::compile(expr, &vec![]).unwrap();
1688
1689        let mut interpreter = Interpreter::default();
1690
1691        let result = interpreter.run(compiled.byte_code).await.unwrap();
1692
1693        let analysed_type = record(vec![
1694            field("bar", u64()),
1695            field("baz", record(vec![field("foo", u64())])),
1696        ]);
1697
1698        let expected = get_value_and_type(&analysed_type, r#"{ bar: 3, baz: { foo: 1 } }"#);
1699
1700        assert_eq!(result.get_val().unwrap(), expected);
1701    }
1702
1703    #[test]
1704    async fn test_interpreter_variable_scope_2() {
1705        let rib_expr = r#"
1706               let x: u64 = 1;
1707               let x = x;
1708
1709               let result1 = match some(x + 1:u64) {
1710                  some(x) => x,
1711                  none => x
1712               };
1713
1714               let z: option<u64> = none;
1715
1716               let result2 = match z {
1717                  some(x) => x,
1718                  none => x
1719               };
1720
1721               { result1: result1, result2: result2 }
1722            "#;
1723
1724        let expr = Expr::from_text(rib_expr).unwrap();
1725
1726        let compiled = compiler::compile(expr, &vec![]).unwrap();
1727
1728        let mut interpreter = Interpreter::default();
1729
1730        let result = interpreter.run(compiled.byte_code).await.unwrap();
1731
1732        let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1733
1734        let expected = get_value_and_type(&analysed_type, r#"{ result1: 2, result2: 1 }"#);
1735
1736        assert_eq!(result.get_val().unwrap(), expected);
1737    }
1738
1739    #[test]
1740    async fn test_interpreter_variable_scope_3() {
1741        let rib_expr = r#"
1742               let x: u64 = 1;
1743               let x = x;
1744
1745               let result1 = match some(x + 1:u64) {
1746                  some(x) => match some(x + 1:u64) {
1747                     some(x) => x,
1748                     none => x
1749                  },
1750                  none => x
1751               };
1752
1753               let z: option<u64> = none;
1754
1755               let result2 = match z {
1756                  some(x) => x,
1757                  none => match some(x + 1:u64) {
1758                     some(x) => x,
1759                     none => x
1760                  }
1761               };
1762
1763               { result1: result1, result2: result2 }
1764            "#;
1765
1766        let expr = Expr::from_text(rib_expr).unwrap();
1767
1768        let compiled = compiler::compile(expr, &vec![]).unwrap();
1769
1770        let mut interpreter = Interpreter::default();
1771
1772        let result = interpreter.run(compiled.byte_code).await.unwrap();
1773
1774        let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1775
1776        let expected = get_value_and_type(&analysed_type, r#"{ result1: 3, result2: 2 }"#);
1777
1778        assert_eq!(result.get_val().unwrap(), expected);
1779    }
1780
1781    #[test]
1782    async fn test_interpreter_global_variable_with_type_spec() {
1783        // request.path.user-id and request.headers.* should be inferred as string,
1784        // since we configure the compiler with a type-spec (given below)
1785        let rib_expr = r#"
1786               let res1 = request.path.user-id;
1787               let res2 = request.headers.name;
1788               let res3 = request.headers.age;
1789               "${res1}-${res2}-${res3}"
1790            "#;
1791
1792        let type_spec = vec![
1793            GlobalVariableTypeSpec {
1794                variable_id: VariableId::global("request".to_string()),
1795                path: Path::from_elems(vec!["path"]),
1796                inferred_type: InferredType::Str,
1797            },
1798            GlobalVariableTypeSpec {
1799                variable_id: VariableId::global("request".to_string()),
1800                path: Path::from_elems(vec!["headers"]),
1801                inferred_type: InferredType::Str,
1802            },
1803        ];
1804
1805        let mut rib_input = HashMap::new();
1806
1807        // Rib compiler identifies the input requirements to be a string (due to type-spec passed)
1808        // and therefore, we pass input value (value_and_type) to the interpreter with headers and path values as string
1809        let analysed_type_of_input = &record(vec![
1810            field("path", record(vec![field("user-id", str())])),
1811            field(
1812                "headers",
1813                record(vec![field("name", str()), field("age", str())]),
1814            ),
1815        ]);
1816
1817        let value_and_type = get_value_and_type(
1818            analysed_type_of_input,
1819            r#"{path : { user-id: "1" }, headers: { name: "foo", age: "20" }}"#,
1820        );
1821
1822        rib_input.insert("request".to_string(), value_and_type);
1823
1824        let mut interpreter = test_utils::interpreter_static_response(
1825            &ValueAndType::new(Value::S8(1), s8()),
1826            Some(RibInput::new(rib_input)),
1827        );
1828
1829        let expr = Expr::from_text(rib_expr).unwrap();
1830
1831        let compiled =
1832            compiler::compile_with_restricted_global_variables(expr, &vec![], None, &type_spec)
1833                .unwrap();
1834
1835        let result = interpreter
1836            .run(compiled.byte_code)
1837            .await
1838            .unwrap()
1839            .get_val()
1840            .unwrap()
1841            .value;
1842
1843        assert_eq!(result, Value::String("1-foo-20".to_string()))
1844    }
1845
1846    #[test]
1847    async fn test_interpreter_global_variable_override_type_spec() {
1848        let rib_expr = r#"
1849             let res1: u32 = request.path.user-id;
1850             let res2 = request.headers.name;
1851             let res3: u32 = request.headers.age;
1852             let res4 = res1 + res3;
1853             "${res4}-${res2}"
1854            "#;
1855
1856        // We always specify the type of request.path.* and request.headers.* to be a string using type-spec
1857        // however the rib script (above) explicitly specify the type of request.path.user-id
1858        // and request.header.age to be u32. In this case, the Rib compiler infer them as u32 and interpreter works with u32.
1859        let type_spec = vec![
1860            GlobalVariableTypeSpec {
1861                variable_id: VariableId::global("request".to_string()),
1862                path: Path::from_elems(vec!["path"]),
1863                inferred_type: InferredType::Str,
1864            },
1865            GlobalVariableTypeSpec {
1866                variable_id: VariableId::global("request".to_string()),
1867                path: Path::from_elems(vec!["headers"]),
1868                inferred_type: InferredType::Str,
1869            },
1870        ];
1871
1872        let mut rib_input = HashMap::new();
1873
1874        // We pass the input value to rib-interpreter with request.path.user-id
1875        // and request.headers.age as u32, since the compiler inferred these input type requirements to be u32.
1876        let analysed_type_of_input = &record(vec![
1877            field("path", record(vec![field("user-id", u32())])),
1878            field(
1879                "headers",
1880                record(vec![field("name", str()), field("age", u32())]),
1881            ),
1882        ]);
1883
1884        let value_and_type = get_value_and_type(
1885            analysed_type_of_input,
1886            r#"{path : { user-id: 1 }, headers: { name: "foo", age: 20 }}"#,
1887        );
1888
1889        rib_input.insert("request".to_string(), value_and_type);
1890
1891        let mut interpreter = test_utils::interpreter_static_response(
1892            &ValueAndType::new(Value::S8(1), s8()),
1893            Some(RibInput::new(rib_input)),
1894        );
1895
1896        let expr = Expr::from_text(rib_expr).unwrap();
1897
1898        let compiled =
1899            compiler::compile_with_restricted_global_variables(expr, &vec![], None, &type_spec)
1900                .unwrap();
1901
1902        let result = interpreter
1903            .run(compiled.byte_code)
1904            .await
1905            .unwrap()
1906            .get_val()
1907            .unwrap()
1908            .value;
1909
1910        assert_eq!(result, Value::String("21-foo".to_string()))
1911    }
1912
1913    #[test]
1914    async fn test_interpreter_list_reduce() {
1915        let mut interpreter = Interpreter::default();
1916
1917        let rib_expr = r#"
1918          let x: list<u8> = [1, 2];
1919
1920          reduce z, a in x from 0u8 {
1921            yield z + a;
1922          }
1923
1924          "#;
1925
1926        let expr = Expr::from_text(rib_expr).unwrap();
1927
1928        let compiled = compiler::compile(expr, &vec![]).unwrap();
1929
1930        let result = interpreter
1931            .run(compiled.byte_code)
1932            .await
1933            .unwrap()
1934            .get_val()
1935            .unwrap();
1936
1937        assert_eq!(result, 3u8.into_value_and_type());
1938    }
1939
1940    #[test]
1941    async fn test_interpreter_list_reduce_from_record() {
1942        let mut interpreter = Interpreter::default();
1943
1944        let rib_expr = r#"
1945           let x = [{name: "foo", age: 1u64}, {name: "bar", age: 2u64}];
1946
1947           let names = for i in x {
1948             yield i.name;
1949           };
1950
1951          reduce z, a in names from "" {
1952            let result = if z == "" then a else "${z}, ${a}";
1953
1954            yield result;
1955          }
1956
1957          "#;
1958
1959        let expr = Expr::from_text(rib_expr).unwrap();
1960
1961        let compiled = compiler::compile(expr, &vec![]).unwrap();
1962
1963        let result = interpreter
1964            .run(compiled.byte_code)
1965            .await
1966            .unwrap()
1967            .get_val()
1968            .unwrap();
1969
1970        assert_eq!(result, "foo, bar".into_value_and_type());
1971    }
1972
1973    #[test]
1974    async fn test_interpreter_list_reduce_text() {
1975        let mut interpreter = Interpreter::default();
1976
1977        let rib_expr = r#"
1978           let x = ["foo", "bar"];
1979
1980          reduce z, a in x from "" {
1981            let result = if z == "" then a else "${z}, ${a}";
1982
1983            yield result;
1984          }
1985
1986          "#;
1987
1988        let expr = Expr::from_text(rib_expr).unwrap();
1989
1990        let compiled = compiler::compile(expr, &vec![]).unwrap();
1991
1992        let result = interpreter
1993            .run(compiled.byte_code)
1994            .await
1995            .unwrap()
1996            .get_val()
1997            .unwrap();
1998
1999        assert_eq!(result, "foo, bar".into_value_and_type());
2000    }
2001
2002    #[test]
2003    async fn test_interpreter_list_reduce_empty() {
2004        let mut interpreter = Interpreter::default();
2005
2006        let rib_expr = r#"
2007          let x: list<u8> = [];
2008
2009          reduce z, a in x from 0u8 {
2010            yield z + a;
2011          }
2012
2013          "#;
2014
2015        let expr = Expr::from_text(rib_expr).unwrap();
2016
2017        let compiled = compiler::compile(expr, &vec![]).unwrap();
2018
2019        let result = interpreter
2020            .run(compiled.byte_code)
2021            .await
2022            .unwrap()
2023            .get_val()
2024            .unwrap();
2025
2026        assert_eq!(result, 0u8.into_value_and_type());
2027    }
2028
2029    #[test]
2030    async fn test_interpreter_with_numbers_1() {
2031        let component_metadata =
2032            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2033
2034        let mut interpreter =
2035            test_utils::interpreter_static_response(&ValueAndType::new(Value::U64(2), u64()), None);
2036
2037        // 1 is automatically inferred to be u32
2038        let rib = r#"
2039          let worker = instance("my-worker");
2040          worker.foo(1)
2041        "#;
2042
2043        let expr = Expr::from_text(rib).unwrap();
2044        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2045        let result = interpreter.run(compiled.byte_code).await.unwrap();
2046
2047        assert_eq!(
2048            result.get_val().unwrap(),
2049            ValueAndType::new(Value::U64(2), u64())
2050        );
2051    }
2052
2053    #[test]
2054    async fn test_interpreter_with_numbers_2() {
2055        let component_metadata =
2056            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2057
2058        let mut interpreter =
2059            test_utils::interpreter_static_response(&ValueAndType::new(Value::U64(2), u64()), None);
2060
2061        // 1 and 2 are automatically inferred to be u32
2062        // since the type of z is inferred to be u32 as that being passed to a function
2063        // that expects u32
2064        let rib = r#"
2065          let worker = instance("my-worker");
2066          let z = 1 + 2;
2067          worker.foo(z)
2068        "#;
2069
2070        let expr = Expr::from_text(rib).unwrap();
2071        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2072        let result = interpreter.run(compiled.byte_code).await.unwrap();
2073
2074        assert_eq!(
2075            result.get_val().unwrap(),
2076            ValueAndType::new(Value::U64(2), u64())
2077        );
2078    }
2079
2080    #[test]
2081    async fn test_interpreter_with_numbers_3() {
2082        let component_metadata =
2083            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2084
2085        // This will cause a type inference error
2086        // because the operands of the + operator are not of the same type
2087        let rib = r#"
2088          let worker = instance("my-worker");
2089          let z = 1: u8 + 2;
2090          worker.foo(z)
2091        "#;
2092
2093        let expr = Expr::from_text(rib).unwrap();
2094        let compile_result = compiler::compile(expr, &component_metadata);
2095        assert!(compile_result.is_err());
2096    }
2097
2098    #[test]
2099    async fn test_interpreter_with_numbers_4() {
2100        let component_metadata =
2101            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2102
2103        // This will cause a type inference error
2104        // because the operands of the + operator are supposed to be u32
2105        // since z is u32
2106        let rib = r#"
2107          let worker = instance("my-worker");
2108          let z = 1: u8 + 2: u8;
2109          worker.foo(z)
2110        "#;
2111
2112        let expr = Expr::from_text(rib).unwrap();
2113        let compile_result = compiler::compile(expr, &component_metadata);
2114        assert!(compile_result.is_err());
2115    }
2116
2117    #[test]
2118    async fn test_interpreter_list_comprehension() {
2119        let mut interpreter = Interpreter::default();
2120
2121        let rib_expr = r#"
2122          let x = ["foo", "bar"];
2123
2124          for i in x {
2125            yield i;
2126          }
2127
2128          "#;
2129
2130        let expr = Expr::from_text(rib_expr).unwrap();
2131
2132        let compiled = compiler::compile(expr, &vec![]).unwrap();
2133
2134        let result = interpreter
2135            .run(compiled.byte_code)
2136            .await
2137            .unwrap()
2138            .get_val()
2139            .unwrap();
2140
2141        let expected = r#"["foo", "bar"]"#;
2142        let expected_value = golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2143
2144        assert_eq!(result, expected_value);
2145    }
2146
2147    #[test]
2148    async fn test_interpreter_list_comprehension_empty() {
2149        let mut interpreter = Interpreter::default();
2150
2151        let rib_expr = r#"
2152          let x: list<string> = [];
2153
2154          for i in x {
2155            yield i;
2156          }
2157
2158          "#;
2159
2160        let expr = Expr::from_text(rib_expr).unwrap();
2161
2162        let compiled = compiler::compile(expr, &vec![]).unwrap();
2163
2164        let result = interpreter
2165            .run(compiled.byte_code)
2166            .await
2167            .unwrap()
2168            .get_val()
2169            .unwrap();
2170
2171        let expected = r#"[]"#;
2172        let expected_value_and_type =
2173            golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2174
2175        assert_eq!(result, expected_value_and_type);
2176    }
2177
2178    #[test]
2179    async fn test_interpreter_pattern_match_on_option_nested() {
2180        let mut interpreter = Interpreter::default();
2181
2182        let expr = r#"
2183           let x: option<option<u64>> = none;
2184
2185           match x {
2186              some(some(t)) => t,
2187              some(none) => 0u64,
2188              none => 0u64
2189
2190           }
2191        "#;
2192
2193        let mut expr = Expr::from_text(expr).unwrap();
2194        expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2195            .unwrap();
2196        let compiled = compiler::compile(expr, &vec![]).unwrap();
2197        let result = interpreter.run(compiled.byte_code).await.unwrap();
2198
2199        assert_eq!(result.get_val().unwrap(), 0u64.into_value_and_type());
2200    }
2201
2202    #[test]
2203    async fn test_interpreter_pattern_match_on_tuple() {
2204        let mut interpreter = Interpreter::default();
2205
2206        let expr = r#"
2207           let x: tuple<u64, string, string> = (1, "foo", "bar");
2208
2209           match x {
2210              (x, y, z) => "${x} ${y} ${z}"
2211           }
2212        "#;
2213
2214        let mut expr = Expr::from_text(expr).unwrap();
2215        expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2216            .unwrap();
2217        let compiled = compiler::compile(expr, &vec![]).unwrap();
2218        let result = interpreter.run(compiled.byte_code).await.unwrap();
2219
2220        assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2221    }
2222
2223    #[test]
2224    async fn test_interpreter_pattern_match_on_tuple_with_option_some() {
2225        let mut interpreter = Interpreter::default();
2226
2227        let expr = r#"
2228           let x: tuple<u64, option<string>, string> = (1, some("foo"), "bar");
2229
2230           match x {
2231              (x, none, z) => "${x} ${z}",
2232              (x, some(y), z) => "${x} ${y} ${z}"
2233           }
2234        "#;
2235
2236        let mut expr = Expr::from_text(expr).unwrap();
2237        expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2238            .unwrap();
2239
2240        let compiled = compiler::compile(expr, &vec![]).unwrap();
2241        let result = interpreter.run(compiled.byte_code).await.unwrap();
2242
2243        assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2244    }
2245
2246    #[test]
2247    async fn test_interpreter_pattern_match_on_tuple_with_option_none() {
2248        let mut interpreter = Interpreter::default();
2249
2250        let expr = r#"
2251           let x: tuple<u64, option<string>, string> = (1, none, "bar");
2252
2253           match x {
2254              (x, none, z) => "${x} ${z}",
2255              (x, some(y), z) => "${x} ${y} ${z}"
2256           }
2257        "#;
2258
2259        let expr = Expr::from_text(expr).unwrap();
2260        let compiled = compiler::compile(expr, &vec![]).unwrap();
2261        let result = interpreter.run(compiled.byte_code).await.unwrap();
2262
2263        assert_eq!(result.get_val().unwrap(), "1 bar".into_value_and_type());
2264    }
2265
2266    #[test]
2267    async fn test_interpreter_pattern_match_on_tuple_with_all_types() {
2268        let mut interpreter = Interpreter::default();
2269
2270        let tuple = test_utils::get_analysed_type_tuple();
2271
2272        let analysed_exports = test_utils::get_component_metadata("foo", vec![tuple], Some(str()));
2273
2274        let expr = r#"
2275
2276           let record = { request : { path : { user : "jak" } }, y : "bar" };
2277           let input = (1, ok(100), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2278           foo(input);
2279           match input {
2280             (n1, err(x1), txt, rec, process-user(x), register-user(n), validate, dev, prod, test) =>  "Invalid",
2281             (n1, ok(x2), txt, rec, process-user(x), register-user(n), validate, prod, dev, test) =>  "foo ${x2} ${n1} ${txt} ${rec.request.path.user} ${validate} ${prod} ${dev} ${test}"
2282           }
2283
2284        "#;
2285
2286        let expr = Expr::from_text(expr).unwrap();
2287        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2288        let result = interpreter.run(compiled.byte_code).await.unwrap();
2289
2290        assert_eq!(
2291            result.get_val().unwrap(),
2292            "foo 100 1 bar jak validate prod dev test".into_value_and_type()
2293        );
2294    }
2295
2296    #[test]
2297    async fn test_interpreter_pattern_match_on_tuple_with_wild_pattern() {
2298        let mut interpreter = Interpreter::default();
2299
2300        let tuple = test_utils::get_analysed_type_tuple();
2301
2302        let analysed_exports =
2303            test_utils::get_component_metadata("my-worker-function", vec![tuple], Some(str()));
2304
2305        let expr = r#"
2306
2307           let record = { request : { path : { user : "jak" } }, y : "baz" };
2308           let input = (1, ok(1), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2309           my-worker-function(input);
2310           match input {
2311             (n1, ok(x), txt, rec, _, _, _, _, prod, _) =>  "prod ${n1} ${txt} ${rec.request.path.user} ${rec.y}",
2312             (n1, ok(x), txt, rec, _, _, _, _, dev, _) =>   "dev ${n1} ${txt} ${rec.request.path.user} ${rec.y}"
2313           }
2314        "#;
2315
2316        let expr = Expr::from_text(expr).unwrap();
2317        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2318        let result = interpreter.run(compiled.byte_code).await.unwrap();
2319
2320        assert_eq!(
2321            result.get_val().unwrap(),
2322            "dev 1 bar jak baz".into_value_and_type()
2323        );
2324    }
2325
2326    #[test]
2327    async fn test_interpreter_record_output_in_pattern_match() {
2328        let input_analysed_type = test_utils::get_analysed_type_record();
2329        let output_analysed_type = test_utils::get_analysed_type_result();
2330
2331        let result_value = get_value_and_type(&output_analysed_type, r#"ok(1)"#);
2332
2333        let mut interpreter = test_utils::interpreter_static_response(&result_value, None);
2334
2335        let analysed_exports = test_utils::get_component_metadata(
2336            "my-worker-function",
2337            vec![input_analysed_type],
2338            Some(output_analysed_type),
2339        );
2340
2341        let expr = r#"
2342
2343           let input = { request : { path : { user : "jak" } }, y : "baz" };
2344           let result = my-worker-function(input);
2345           match result {
2346             ok(result) => { body: result, status: 200 },
2347             err(result) => { status: 400, body: 400 }
2348           }
2349        "#;
2350
2351        let expr = Expr::from_text(expr).unwrap();
2352        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2353        let result = interpreter.run(compiled.byte_code).await.unwrap();
2354
2355        let expected = test_utils::get_value_and_type(
2356            &record(vec![field("body", u64()), field("status", u64())]),
2357            r#"{body: 1, status: 200}"#,
2358        );
2359
2360        assert_eq!(result.get_val().unwrap(), expected);
2361    }
2362
2363    #[test]
2364    async fn test_interpreter_tuple_output_in_pattern_match() {
2365        let input_analysed_type = test_utils::get_analysed_type_record();
2366        let output_analysed_type = test_utils::get_analysed_type_result();
2367
2368        let result_value = get_value_and_type(&output_analysed_type, r#"err("failed")"#);
2369
2370        let mut interpreter = test_utils::interpreter_static_response(&result_value, None);
2371
2372        let analysed_exports = test_utils::get_component_metadata(
2373            "my-worker-function",
2374            vec![input_analysed_type],
2375            Some(output_analysed_type),
2376        );
2377
2378        let expr = r#"
2379
2380           let input = { request : { path : { user : "jak" } }, y : "baz" };
2381           let result = my-worker-function(input);
2382           match result {
2383             ok(res) => ("${res}", "foo"),
2384             err(msg) => (msg, "bar")
2385           }
2386        "#;
2387
2388        let expr = Expr::from_text(expr).unwrap();
2389        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2390        let result = interpreter.run(compiled.byte_code).await.unwrap();
2391
2392        let expected = get_value_and_type(&tuple(vec![str(), str()]), r#"("failed", "bar")"#);
2393
2394        assert_eq!(result.get_val().unwrap(), expected);
2395    }
2396
2397    #[test]
2398    async fn test_interpreter_with_indexed_resource_drop() {
2399        let expr = r#"
2400           let user_id = "user";
2401           golem:it/api.{cart(user_id).drop}();
2402           "success"
2403        "#;
2404        let expr = Expr::from_text(expr).unwrap();
2405        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2406
2407        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2408
2409        let mut rib_interpreter = Interpreter::default();
2410        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2411
2412        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2413    }
2414
2415    #[test]
2416    async fn test_interpreter_with_indexed_resource_checkout() {
2417        let expr = r#"
2418           let user_id = "foo";
2419           let result = golem:it/api.{cart(user_id).checkout}();
2420           result
2421        "#;
2422
2423        let expr = Expr::from_text(expr).unwrap();
2424
2425        let result_type = variant(vec![
2426            case("error", str()),
2427            case("success", record(vec![field("order-id", str())])),
2428        ]);
2429
2430        let result_value = test_utils::get_value_and_type(
2431            &result_type,
2432            r#"
2433          success({order-id: "foo"})
2434        "#,
2435        );
2436
2437        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2438        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2439
2440        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2441        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2442
2443        assert_eq!(result.get_val().unwrap(), result_value);
2444    }
2445
2446    #[test]
2447    async fn test_interpreter_with_indexed_resource_get_cart_contents() {
2448        let expr = r#"
2449           let user_id = "bar";
2450           let result = golem:it/api.{cart(user_id).get-cart-contents}();
2451           result[0].product-id
2452        "#;
2453
2454        let expr = Expr::from_text(expr).unwrap();
2455
2456        let result_type = list(record(vec![
2457            field("product-id", str()),
2458            field("name", str()),
2459            field("price", f32()),
2460            field("quantity", u32()),
2461        ]));
2462
2463        let result_value = test_utils::get_value_and_type(
2464            &result_type,
2465            r#"
2466            [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}]
2467        "#,
2468        );
2469
2470        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2471        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2472
2473        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2474        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2475
2476        assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2477    }
2478
2479    #[test]
2480    async fn test_interpreter_with_indexed_resource_update_item_quantity() {
2481        let expr = r#"
2482           let user_id = "jon";
2483           let product_id = "mac";
2484           let quantity = 1032;
2485           golem:it/api.{cart(user_id).update-item-quantity}(product_id, quantity);
2486           "successfully updated"
2487        "#;
2488        let expr = Expr::from_text(expr).unwrap();
2489
2490        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2491
2492        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2493
2494        let mut rib_executor = Interpreter::default();
2495
2496        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2497
2498        assert_eq!(
2499            result.get_val().unwrap(),
2500            "successfully updated".into_value_and_type()
2501        );
2502    }
2503
2504    #[test]
2505    async fn test_interpreter_with_indexed_resource_add_item() {
2506        let expr = r#"
2507           let user_id = "foo";
2508           let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2509           golem:it/api.{cart(user_id).add-item}(product);
2510
2511           "successfully added"
2512        "#;
2513
2514        let expr = Expr::from_text(expr).unwrap();
2515
2516        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2517
2518        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2519
2520        let mut rib_executor = Interpreter::default();
2521
2522        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2523
2524        assert_eq!(
2525            result.get_val().unwrap(),
2526            "successfully added".into_value_and_type()
2527        );
2528    }
2529
2530    #[test]
2531    async fn test_interpreter_with_resource_add_item() {
2532        let expr = r#"
2533           let user_id = "foo";
2534           let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2535           golem:it/api.{cart.add-item}(product);
2536
2537           "successfully added"
2538        "#;
2539
2540        let expr = Expr::from_text(expr).unwrap();
2541
2542        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2543
2544        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2545
2546        let mut rib_executor = Interpreter::default();
2547
2548        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2549
2550        assert_eq!(
2551            result.get_val().unwrap(),
2552            "successfully added".into_value_and_type()
2553        );
2554    }
2555
2556    #[test]
2557    async fn test_interpreter_with_resource_get_cart_contents() {
2558        let expr = r#"
2559           let result = golem:it/api.{cart.get-cart-contents}();
2560           result[0].product-id
2561        "#;
2562
2563        let expr = Expr::from_text(expr).unwrap();
2564
2565        let result_type = list(record(vec![
2566            field("product-id", str()),
2567            field("name", str()),
2568            field("price", f32()),
2569            field("quantity", u32()),
2570        ]));
2571
2572        let result_value = test_utils::get_value_and_type(
2573            &result_type,
2574            r#"
2575            [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}]
2576        "#,
2577        );
2578
2579        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2580        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2581
2582        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2583        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2584
2585        assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2586    }
2587
2588    #[test]
2589    async fn test_interpreter_with_resource_update_item() {
2590        let expr = r#"
2591           let product_id = "mac";
2592           let quantity = 1032;
2593           golem:it/api.{cart.update-item-quantity}(product_id, quantity);
2594           "successfully updated"
2595        "#;
2596        let expr = Expr::from_text(expr).unwrap();
2597
2598        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2599
2600        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2601
2602        let mut rib_executor = Interpreter::default();
2603
2604        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2605
2606        assert_eq!(
2607            result.get_val().unwrap(),
2608            "successfully updated".into_value_and_type()
2609        );
2610    }
2611
2612    #[test]
2613    async fn test_interpreter_with_resource_checkout() {
2614        let expr = r#"
2615           let result = golem:it/api.{cart.checkout}();
2616           result
2617        "#;
2618
2619        let expr = Expr::from_text(expr).unwrap();
2620
2621        let result_type = variant(vec![
2622            case("error", str()),
2623            case("success", record(vec![field("order-id", str())])),
2624        ]);
2625
2626        let result_value = test_utils::get_value_and_type(
2627            &result_type,
2628            r#"
2629          success({order-id: "foo"})
2630        "#,
2631        );
2632
2633        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2634        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2635
2636        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2637        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2638
2639        assert_eq!(result.get_val().unwrap(), result_value);
2640    }
2641
2642    #[test]
2643    async fn test_interpreter_with_resource_drop() {
2644        let expr = r#"
2645           golem:it/api.{cart.drop}();
2646           "success"
2647        "#;
2648        let expr = Expr::from_text(expr).unwrap();
2649        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2650
2651        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2652
2653        let mut rib_interpreter = Interpreter::default();
2654        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2655
2656        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2657    }
2658
2659    #[test]
2660    async fn test_interpreter_for_select_index_expr_1() {
2661        // infinite computation will respond with an error - than a stack overflow
2662        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
2663        let expr = r#"
2664              let list: list<u8> = [1, 2, 3, 4, 5];
2665              let index: u8 = 4;
2666              list[index]
2667              "#;
2668
2669        let expr = Expr::from_text(expr).unwrap();
2670
2671        let compiled = compiler::compile(expr, &vec![]).unwrap();
2672
2673        let mut interpreter = Interpreter::default();
2674        let result = interpreter.run(compiled.byte_code).await.unwrap();
2675
2676        let expected = ValueAndType::new(Value::U8(5), u8());
2677
2678        assert_eq!(result.get_val().unwrap(), expected);
2679    }
2680
2681    #[test]
2682    async fn test_interpreter_for_select_index_expr_out_of_bound() {
2683        let expr = r#"
2684              let list: list<u8> = [1, 2, 3, 4, 5];
2685              let index: u8 = 10;
2686              list[index]
2687              "#;
2688
2689        let expr = Expr::from_text(expr).unwrap();
2690
2691        let compiled = compiler::compile(expr, &vec![]).unwrap();
2692
2693        let mut interpreter = Interpreter::default();
2694        let result = interpreter.run(compiled.byte_code).await.unwrap_err();
2695
2696        assert_eq!(
2697            result,
2698            "index 10 is out of bound in the list of length 5".to_string()
2699        );
2700    }
2701
2702    #[test]
2703    async fn test_interpreter_for_select_index_expr_2() {
2704        let expr = r#"
2705              let list: list<u8> = [1, 2, 3, 4, 5];
2706              let indices: list<u8> = [0, 1, 2, 3];
2707
2708              for i in indices {
2709                 yield list[i];
2710              }
2711              "#;
2712
2713        let expr = Expr::from_text(expr).unwrap();
2714
2715        let compiled = compiler::compile(expr, &vec![]).unwrap();
2716
2717        let mut interpreter = Interpreter::default();
2718        let result = interpreter.run(compiled.byte_code).await.unwrap();
2719
2720        let expected = ValueAndType::new(
2721            Value::List(vec![Value::U8(1), Value::U8(2), Value::U8(3), Value::U8(4)]),
2722            list(u8()),
2723        );
2724
2725        assert_eq!(result.get_val().unwrap(), expected);
2726    }
2727
2728    #[test]
2729    async fn test_interpreter_for_select_index_expr_3() {
2730        let expr = r#"
2731              let list: list<u8> = [2, 5, 4];
2732              let indices: list<u8> = [0, 1];
2733
2734               reduce z, index in indices from 0u8 {
2735                  yield list[index] + z;
2736                }
2737              "#;
2738
2739        let expr = Expr::from_text(expr).unwrap();
2740
2741        let compiled = compiler::compile(expr, &vec![]).unwrap();
2742
2743        let mut interpreter = Interpreter::default();
2744        let result = interpreter.run(compiled.byte_code).await.unwrap();
2745
2746        let expected = ValueAndType::new(Value::U8(7), u8());
2747
2748        assert_eq!(result.get_val().unwrap(), expected);
2749    }
2750
2751    #[test]
2752    async fn test_interpreter_for_select_index_expr_4() {
2753        let expr = r#"
2754              let list: list<u8> = [2, 5, 4];
2755              let x: u8 = 0;
2756              let y: u8 = 2;
2757              list[x..=y]
2758              "#;
2759
2760        let expr = Expr::from_text(expr).unwrap();
2761
2762        let compiled = compiler::compile(expr, &vec![]).unwrap();
2763
2764        let mut interpreter = Interpreter::default();
2765        let result = interpreter.run(compiled.byte_code).await.unwrap();
2766
2767        let expected = ValueAndType::new(
2768            Value::List(vec![Value::U8(2), Value::U8(5), Value::U8(4)]),
2769            list(u8()),
2770        );
2771
2772        assert_eq!(result.get_val().unwrap(), expected);
2773    }
2774
2775    #[test]
2776    async fn test_interpreter_for_select_index_expr_5() {
2777        let expr = r#"
2778              let list: list<u8> = [2, 5, 4];
2779              let x: u8 = 0;
2780              let y: u8 = 2;
2781              let x1: u8 = 1;
2782              let result = list[x..=y];
2783              for i in result[x1..=y] {
2784                yield i;
2785              }
2786              "#;
2787
2788        let expr = Expr::from_text(expr).unwrap();
2789
2790        let compiled = compiler::compile(expr, &vec![]).unwrap();
2791
2792        let mut interpreter = Interpreter::default();
2793        let result = interpreter.run(compiled.byte_code).await.unwrap();
2794
2795        let expected = ValueAndType::new(Value::List(vec![Value::U8(5), Value::U8(4)]), list(u8()));
2796
2797        assert_eq!(result.get_val().unwrap(), expected);
2798    }
2799
2800    #[test]
2801    async fn test_interpreter_for_select_index_expr_6() {
2802        let expr = r#"
2803              let list: list<u8> = [2, 5, 4, 6];
2804              let x: u8 = 0;
2805              let y: u8 = 2;
2806              let result = list[x..y];
2807              for i in result[x..y] {
2808                yield i;
2809              }
2810              "#;
2811
2812        let expr = Expr::from_text(expr).unwrap();
2813
2814        let compiled = compiler::compile(expr, &vec![]).unwrap();
2815
2816        let mut interpreter = Interpreter::default();
2817        let result = interpreter.run(compiled.byte_code).await.unwrap();
2818
2819        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2820
2821        assert_eq!(result.get_val().unwrap(), expected);
2822    }
2823
2824    #[test]
2825    async fn test_interpreter_for_select_index_expr_7() {
2826        let expr = r#"
2827              let list: list<u8> = [2, 5, 4, 6];
2828              let x: u8 = 0;
2829              let result = list[x..];
2830              for i in result[x..] {
2831                yield i;
2832              }
2833              "#;
2834
2835        let expr = Expr::from_text(expr).unwrap();
2836
2837        let compiled = compiler::compile(expr, &vec![]).unwrap();
2838
2839        let mut interpreter = Interpreter::default();
2840        let result = interpreter.run(compiled.byte_code).await.unwrap();
2841
2842        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2843
2844        assert_eq!(result.get_val().unwrap(), expected);
2845    }
2846
2847    #[test]
2848    async fn test_interpreter_for_select_index_expr_8() {
2849        let expr = r#"
2850              let list: list<u8> = [2, 5, 4, 6];
2851              let result = list[0..2];
2852              for i in result[0..2] {
2853                yield i;
2854              }
2855              "#;
2856
2857        let expr = Expr::from_text(expr).unwrap();
2858
2859        let compiled = compiler::compile(expr, &vec![]).unwrap();
2860
2861        let mut interpreter = Interpreter::default();
2862        let result = interpreter.run(compiled.byte_code).await.unwrap();
2863
2864        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2865
2866        assert_eq!(result.get_val().unwrap(), expected);
2867    }
2868
2869    // Simulating the behaviour in languages like rust
2870    // Emitting the description of the range than the evaluated range
2871    // Description given out as ValueAndType::Record
2872    #[test]
2873    async fn test_interpreter_range_returns_1() {
2874        let expr = r#"
2875              let x = 1..;
2876              x
2877              "#;
2878
2879        let expr = Expr::from_text(expr).unwrap();
2880
2881        let compiled = compiler::compile(expr, &vec![]).unwrap();
2882
2883        let mut interpreter = Interpreter::default();
2884        let result = interpreter.run(compiled.byte_code).await.unwrap();
2885
2886        let expected = ValueAndType::new(
2887            Value::Record(vec![
2888                Value::U64(1),
2889                Value::Bool(false), // non inclusive
2890            ]),
2891            record(vec![
2892                field("from", option(u64())),
2893                field("inclusive", bool()),
2894            ]),
2895        );
2896
2897        assert_eq!(result.get_val().unwrap(), expected);
2898    }
2899
2900    #[test]
2901    async fn test_interpreter_range_returns_2() {
2902        let expr = r#"
2903              let x = 1..2;
2904              x
2905              "#;
2906
2907        let expr = Expr::from_text(expr).unwrap();
2908
2909        let compiled = compiler::compile(expr, &vec![]).unwrap();
2910
2911        let mut interpreter = Interpreter::default();
2912        let result = interpreter.run(compiled.byte_code).await.unwrap();
2913
2914        let expected = ValueAndType::new(
2915            Value::Record(vec![
2916                Value::U64(1),
2917                Value::U64(2),
2918                Value::Bool(false), // non inclusive
2919            ]),
2920            record(vec![
2921                field("from", option(u64())),
2922                field("to", option(u64())),
2923                field("inclusive", bool()),
2924            ]),
2925        );
2926
2927        assert_eq!(result.get_val().unwrap(), expected);
2928    }
2929
2930    #[test]
2931    async fn test_interpreter_range_returns_3() {
2932        let expr = r#"
2933              let x = 1..=10;
2934              x
2935              "#;
2936
2937        let expr = Expr::from_text(expr).unwrap();
2938
2939        let compiled = compiler::compile(expr, &vec![]).unwrap();
2940
2941        let mut interpreter = Interpreter::default();
2942        let result = interpreter.run(compiled.byte_code).await.unwrap();
2943
2944        let expected = ValueAndType::new(
2945            Value::Record(vec![
2946                Value::U64(1),
2947                Value::U64(10),
2948                Value::Bool(true), // inclusive
2949            ]),
2950            record(vec![
2951                field("from", option(u64())),
2952                field("to", option(u64())),
2953                field("inclusive", bool()),
2954            ]),
2955        );
2956
2957        assert_eq!(result.get_val().unwrap(), expected);
2958    }
2959
2960    #[test]
2961    async fn test_interpreter_range_returns_4() {
2962        let expr = r#"
2963              let x = 1:u64;
2964              let y = x;
2965              let range = x..=y;
2966              let range2 = x..;
2967              let range3 = x..y;
2968              range;
2969              range2;
2970              range3
2971              "#;
2972
2973        let expr = Expr::from_text(expr).unwrap();
2974
2975        let compiled = compiler::compile(expr, &vec![]).unwrap();
2976
2977        let mut interpreter = Interpreter::default();
2978        let result = interpreter.run(compiled.byte_code).await.unwrap();
2979
2980        let expected = ValueAndType::new(
2981            Value::Record(vec![Value::U64(1), Value::U64(1), Value::Bool(false)]),
2982            record(vec![
2983                field("from", option(u64())),
2984                field("to", option(u64())),
2985                field("inclusive", bool()),
2986            ]),
2987        );
2988
2989        assert_eq!(result.get_val().unwrap(), expected);
2990    }
2991
2992    #[test]
2993    async fn test_interpreter_range_returns_5() {
2994        let expr = r#"
2995              let y = 1:u64 + 10: u64;
2996              1..y
2997              "#;
2998
2999        let expr = Expr::from_text(expr).unwrap();
3000
3001        let compiled = compiler::compile(expr, &vec![]).unwrap();
3002
3003        let mut interpreter = Interpreter::default();
3004        let result = interpreter.run(compiled.byte_code).await.unwrap();
3005
3006        let expected = ValueAndType::new(
3007            Value::Record(vec![Value::U64(1), Value::U64(11), Value::Bool(false)]),
3008            record(vec![
3009                field("from", option(u64())),
3010                field("to", option(u64())),
3011                field("inclusive", bool()),
3012            ]),
3013        );
3014
3015        assert_eq!(result.get_val().unwrap(), expected);
3016    }
3017
3018    #[test]
3019    async fn test_interpreter_range_with_comprehension_1() {
3020        let expr = r#"
3021              let range = 1..=5;
3022              for i in range {
3023                yield i;
3024              }
3025
3026              "#;
3027
3028        let expr = Expr::from_text(expr).unwrap();
3029
3030        let compiled = compiler::compile(expr, &vec![]).unwrap();
3031
3032        let mut interpreter = Interpreter::default();
3033        let result = interpreter.run(compiled.byte_code).await.unwrap();
3034
3035        let expected = ValueAndType::new(
3036            Value::List(vec![
3037                Value::U64(1),
3038                Value::U64(2),
3039                Value::U64(3),
3040                Value::U64(4),
3041                Value::U64(5),
3042            ]),
3043            list(u64()),
3044        );
3045
3046        assert_eq!(result.get_val().unwrap(), expected);
3047    }
3048
3049    #[test]
3050    async fn test_interpreter_range_with_comprehension_2() {
3051        let expr = r#"
3052              let range = 1..5;
3053              for i in range {
3054                yield i;
3055              }
3056
3057              "#;
3058
3059        let expr = Expr::from_text(expr).unwrap();
3060
3061        let compiled = compiler::compile(expr, &vec![]).unwrap();
3062
3063        let mut interpreter = Interpreter::default();
3064        let result = interpreter.run(compiled.byte_code).await.unwrap();
3065
3066        let expected = ValueAndType::new(
3067            Value::List(vec![
3068                Value::U64(1),
3069                Value::U64(2),
3070                Value::U64(3),
3071                Value::U64(4),
3072            ]),
3073            list(u64()),
3074        );
3075
3076        assert_eq!(result.get_val().unwrap(), expected);
3077    }
3078
3079    #[test]
3080    async fn test_interpreter_range_with_comprehension_3() {
3081        // infinite computation will respond with an error - than a stack overflow
3082        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3083        let expr = r#"
3084              let range = 1:u64..;
3085              for i in range {
3086                yield i;
3087              }
3088
3089              "#;
3090
3091        let expr = Expr::from_text(expr).unwrap();
3092
3093        let compiled = compiler::compile(expr, &vec![]).unwrap();
3094
3095        let mut interpreter = Interpreter::default();
3096        let result = interpreter.run(compiled.byte_code).await;
3097        assert!(result.is_err());
3098    }
3099
3100    #[test]
3101    async fn test_interpreter_range_with_list_reduce_1() {
3102        // infinite computation will respond with an error - than a stack overflow
3103        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3104        let expr = r#"
3105                let initial: u8 = 1;
3106                let final: u8 = 5;
3107                let x = initial..final;
3108
3109                reduce z, a in x from 0u8 {
3110                  yield z + a;
3111                }
3112
3113              "#;
3114
3115        let expr = Expr::from_text(expr).unwrap();
3116
3117        let compiled = compiler::compile(expr, &vec![]).unwrap();
3118
3119        let mut interpreter = Interpreter::default();
3120        let result = interpreter.run(compiled.byte_code).await.unwrap();
3121
3122        let expected = ValueAndType::new(Value::U8(10), u8());
3123
3124        assert_eq!(result.get_val().unwrap(), expected);
3125    }
3126
3127    #[test]
3128    async fn test_interpreter_ephemeral_worker_0() {
3129        let expr = r#"
3130              let x = instance();
3131              let result = x.foo("bar");
3132              result
3133            "#;
3134        let expr = Expr::from_text(expr).unwrap();
3135
3136        let component_metadata = test_utils::get_metadata();
3137
3138        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3139
3140        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3141
3142        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3143
3144        let expected_val = test_utils::parse_function_details(
3145            r#"
3146              {
3147                 worker-name: none,
3148                 function-name: "amazon:shopping-cart/api1.{foo}",
3149                 args0: "bar"
3150              }
3151            "#,
3152        );
3153
3154        assert_eq!(result.get_val().unwrap(), expected_val);
3155    }
3156
3157    #[test]
3158    async fn test_interpreter_ephemeral_worker_1() {
3159        let expr = r#"
3160              let x = instance();
3161              x
3162            "#;
3163        let expr = Expr::from_text(expr).unwrap();
3164
3165        let component_metadata = test_utils::get_metadata();
3166
3167        let compiled = compiler::compile(expr, &component_metadata);
3168
3169        assert!(compiled.is_err());
3170    }
3171
3172    #[test]
3173    async fn test_interpreter_ephemeral_worker_2() {
3174        let expr = r#"
3175             instance
3176            "#;
3177        let expr = Expr::from_text(expr).unwrap();
3178
3179        let component_metadata = test_utils::get_metadata();
3180
3181        let compiled = compiler::compile(expr, &component_metadata);
3182
3183        assert!(compiled.is_err());
3184    }
3185
3186    #[test]
3187    async fn test_interpreter_ephemeral_worker_3() {
3188        let expr = r#"
3189              instance()
3190            "#;
3191        let expr = Expr::from_text(expr).unwrap();
3192
3193        let component_metadata = test_utils::get_metadata();
3194
3195        let compiled = compiler::compile(expr, &component_metadata);
3196
3197        assert!(compiled.is_err());
3198    }
3199
3200    #[test]
3201    async fn test_interpreter_ephemeral_worker_4() {
3202        let expr = r#"
3203              instance().foo("bar")
3204            "#;
3205        let expr = Expr::from_text(expr).unwrap();
3206
3207        let component_metadata = test_utils::get_metadata();
3208
3209        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3210
3211        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3212
3213        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3214
3215        let expected_val = test_utils::parse_function_details(
3216            r#"
3217              {
3218                 worker-name: none,
3219                 function-name: "amazon:shopping-cart/api1.{foo}",
3220                 args0: "bar"
3221              }
3222            "#,
3223        );
3224
3225        assert_eq!(result.get_val().unwrap(), expected_val);
3226    }
3227
3228    #[test]
3229    async fn test_interpreter_ephemeral_worker_5() {
3230        let expr = r#"
3231              let result = instance.foo("bar");
3232              result
3233            "#;
3234        let expr = Expr::from_text(expr).unwrap();
3235        let component_metadata = test_utils::get_metadata();
3236
3237        let compiled = compiler::compile(expr, &component_metadata)
3238            .unwrap_err()
3239            .to_string();
3240
3241        assert_eq!(compiled, "error in the following rib found at line 2, column 28\n`instance`\ncause: `instance` is a reserved keyword\nhelp: use `instance()` instead of `instance` to create an ephemeral worker instance.\nhelp: for a durable worker, use `instance(\"foo\")` where `\"foo\"` is the worker name\n".to_string());
3242    }
3243
3244    #[test]
3245    async fn test_interpreter_ephemeral_worker_6() {
3246        let expr = r#"
3247                let x = instance();
3248                let result = x.bar("bar");
3249                result
3250            "#;
3251        let expr = Expr::from_text(expr).unwrap();
3252        let component_metadata = test_utils::get_metadata();
3253
3254        let compilation_error = compiler::compile(expr, &component_metadata)
3255            .unwrap_err()
3256            .to_string();
3257
3258        assert_eq!(
3259            compilation_error,
3260            "error in the following rib found at line 3, column 30\n`x.bar(\"bar\")`\ncause: invalid function call `bar`\nmultiple interfaces contain function 'bar'. specify an interface name as type parameter from: api1, api2\n".to_string()
3261        );
3262    }
3263
3264    #[test]
3265    async fn test_interpreter_ephemeral_worker_7() {
3266        let expr = r#"
3267                let worker = instance();
3268                let invokes: list<u8> = [1, 2, 3, 4];
3269
3270                for i in invokes {
3271                    yield worker.qux[wasi:clocks]("bar");
3272                };
3273
3274                "success"
3275            "#;
3276        let expr = Expr::from_text(expr).unwrap();
3277        let component_metadata = test_utils::get_metadata();
3278
3279        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3280
3281        let mut rib_interpreter =
3282            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3283
3284        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3285
3286        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3287    }
3288
3289    /// Durable worker
3290    #[test]
3291    async fn test_interpreter_durable_worker_0() {
3292        let expr = r#"
3293                let worker = instance("my-worker");
3294                let result = worker.foo("bar");
3295                result
3296            "#;
3297        let expr = Expr::from_text(expr).unwrap();
3298        let component_metadata = test_utils::get_metadata();
3299
3300        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3301
3302        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3303
3304        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3305
3306        let expected_val = test_utils::parse_function_details(
3307            r#"
3308              {
3309                 worker-name: some("my-worker"),
3310                 function-name: "amazon:shopping-cart/api1.{foo}",
3311                 args0: "bar"
3312              }
3313            "#,
3314        );
3315
3316        assert_eq!(result.get_val().unwrap(), expected_val);
3317    }
3318
3319    #[test]
3320    async fn test_interpreter_durable_worker_1() {
3321        let expr = r#"
3322                instance("my-worker").foo("bar")
3323            "#;
3324        let expr = Expr::from_text(expr).unwrap();
3325        let component_metadata = test_utils::get_metadata();
3326
3327        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3328
3329        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3330
3331        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3332
3333        let expected_val = test_utils::parse_function_details(
3334            r#"
3335              {
3336                 worker-name: some("my-worker"),
3337                 function-name: "amazon:shopping-cart/api1.{foo}",
3338                 args0: "bar"
3339              }
3340            "#,
3341        );
3342
3343        assert_eq!(result.get_val().unwrap(), expected_val);
3344    }
3345
3346    #[test]
3347    async fn test_interpreter_durable_worker_2() {
3348        let expr = r#"
3349                let result = instance("my-worker").foo("bar");
3350                result
3351            "#;
3352        let expr = Expr::from_text(expr).unwrap();
3353        let component_metadata = test_utils::get_metadata();
3354
3355        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3356
3357        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3358
3359        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3360
3361        let expected_val = test_utils::parse_function_details(
3362            r#"
3363              {
3364                 worker-name: some("my-worker"),
3365                 function-name: "amazon:shopping-cart/api1.{foo}",
3366                 args0: "bar"
3367              }
3368            "#,
3369        );
3370
3371        assert_eq!(result.get_val().unwrap(), expected_val);
3372    }
3373
3374    #[test]
3375    async fn test_interpreter_durable_worker_3() {
3376        let expr = r#"
3377                let my_worker = instance("my-worker");
3378                let result = my_worker.foo[api1]("bar");
3379                result
3380            "#;
3381        let expr = Expr::from_text(expr).unwrap();
3382        let component_metadata = test_utils::get_metadata();
3383
3384        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3385
3386        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3387
3388        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3389
3390        let expected_val = test_utils::parse_function_details(
3391            r#"
3392              {
3393                 worker-name: some("my-worker"),
3394                 function-name: "amazon:shopping-cart/api1.{foo}",
3395                 args0: "bar"
3396              }
3397            "#,
3398        );
3399
3400        assert_eq!(result.get_val().unwrap(), expected_val);
3401    }
3402
3403    #[test]
3404    async fn test_interpreter_durable_worker_4() {
3405        let expr = r#"
3406                let worker = instance("my-worker");
3407                let result = worker.bar("bar");
3408                result
3409            "#;
3410        let expr = Expr::from_text(expr).unwrap();
3411        let component_metadata = test_utils::get_metadata();
3412
3413        let compilation_error = compiler::compile(expr, &component_metadata)
3414            .unwrap_err()
3415            .to_string();
3416
3417        assert_eq!(
3418            compilation_error,
3419            "error in the following rib found at line 3, column 30\n`worker.bar(\"bar\")`\ncause: invalid function call `bar`\nmultiple interfaces contain function 'bar'. specify an interface name as type parameter from: api1, api2\n".to_string()
3420        );
3421    }
3422
3423    #[test]
3424    async fn test_interpreter_durable_worker_5() {
3425        let expr = r#"
3426                let worker = instance("my-worker");
3427                let result = worker.bar[api1]("bar");
3428                result
3429            "#;
3430        let expr = Expr::from_text(expr).unwrap();
3431        let component_metadata = test_utils::get_metadata();
3432
3433        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3434
3435        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3436
3437        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3438
3439        let expected_val = test_utils::parse_function_details(
3440            r#"
3441              {
3442                 worker-name: some("my-worker"),
3443                 function-name: "amazon:shopping-cart/api1.{bar}",
3444                 args0: "bar"
3445              }
3446            "#,
3447        );
3448
3449        assert_eq!(result.get_val().unwrap(), expected_val);
3450    }
3451
3452    #[test]
3453    async fn test_interpreter_durable_worker_6() {
3454        let expr = r#"
3455                let worker = instance("my-worker");
3456                let result = worker.bar[api2]("bar");
3457                result
3458            "#;
3459        let expr = Expr::from_text(expr).unwrap();
3460        let component_metadata = test_utils::get_metadata();
3461
3462        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3463
3464        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3465
3466        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3467
3468        let expected_val = test_utils::parse_function_details(
3469            r#"
3470              {
3471                 worker-name: some("my-worker"),
3472                 function-name: "amazon:shopping-cart/api2.{bar}",
3473                 args0: "bar"
3474              }
3475            "#,
3476        );
3477
3478        assert_eq!(result.get_val().unwrap(), expected_val);
3479    }
3480
3481    #[test]
3482    async fn test_interpreter_durable_worker_7() {
3483        let expr = r#"
3484                let worker = instance("my-worker");
3485                let result = worker.baz("bar");
3486                result
3487            "#;
3488        let expr = Expr::from_text(expr).unwrap();
3489        let component_metadata = test_utils::get_metadata();
3490
3491        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3492
3493        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3494
3495        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3496
3497        let expected_val = test_utils::parse_function_details(
3498            r#"
3499              {
3500                 worker-name: some("my-worker"),
3501                 function-name: "wasi:clocks/monotonic-clock.{baz}",
3502                 args0: "bar"
3503              }
3504            "#,
3505        );
3506
3507        assert_eq!(result.get_val().unwrap(), expected_val);
3508    }
3509
3510    #[test]
3511    async fn test_interpreter_durable_worker_8() {
3512        let expr = r#"
3513                let worker = instance("my-worker");
3514                let result = worker.qux("bar");
3515                result
3516            "#;
3517        let expr = Expr::from_text(expr).unwrap();
3518        let component_metadata = test_utils::get_metadata();
3519
3520        let compiled = compiler::compile(expr, &component_metadata)
3521            .unwrap_err()
3522            .to_string();
3523
3524        assert_eq!(
3525            compiled,
3526            "error in the following rib found at line 3, column 30\n`worker.qux(\"bar\")`\ncause: invalid function call `qux`\nfunction 'qux' exists in multiple packages. specify a package name as type parameter from: amazon:shopping-cart (interfaces: api1), wasi:clocks (interfaces: monotonic-clock)\n".to_string()
3527        );
3528    }
3529
3530    #[test]
3531    async fn test_interpreter_durable_worker_9() {
3532        let expr = r#"
3533                let worker = instance("my-worker");
3534                let result = worker.qux[amazon:shopping-cart]("bar");
3535                result
3536            "#;
3537        let expr = Expr::from_text(expr).unwrap();
3538        let component_metadata = test_utils::get_metadata();
3539
3540        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3541
3542        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3543
3544        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3545
3546        let expected_val = test_utils::parse_function_details(
3547            r#"
3548              {
3549                 worker-name: some("my-worker"),
3550                 function-name: "amazon:shopping-cart/api1.{qux}",
3551                 args0: "bar"
3552              }
3553            "#,
3554        );
3555
3556        assert_eq!(result.get_val().unwrap(), expected_val);
3557    }
3558
3559    #[test]
3560    async fn test_interpreter_durable_worker_10() {
3561        let expr = r#"
3562                let worker = instance("my-worker");
3563                let result = worker.qux[wasi:clocks]("bar");
3564                result
3565            "#;
3566        let expr = Expr::from_text(expr).unwrap();
3567        let component_metadata = test_utils::get_metadata();
3568
3569        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3570
3571        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3572
3573        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3574
3575        let expected_val = test_utils::parse_function_details(
3576            r#"
3577              {
3578                 worker-name: some("my-worker"),
3579                 function-name: "wasi:clocks/monotonic-clock.{qux}",
3580                 args0: "bar"
3581              }
3582            "#,
3583        );
3584
3585        assert_eq!(result.get_val().unwrap(), expected_val);
3586    }
3587
3588    #[test]
3589    async fn test_interpreter_durable_worker_11() {
3590        let expr = r#"
3591                let worker = instance("my-worker");
3592                let invokes: list<u8> = [1, 2, 3, 4];
3593
3594                for i in invokes {
3595                    yield worker.qux[wasi:clocks]("bar");
3596                };
3597
3598                "success"
3599            "#;
3600        let expr = Expr::from_text(expr).unwrap();
3601        let component_metadata = test_utils::get_metadata();
3602
3603        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3604
3605        let mut rib_interpreter =
3606            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3607
3608        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3609
3610        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3611    }
3612
3613    #[test]
3614    async fn test_interpreter_durable_worker_with_resource_0() {
3615        let expr = r#"
3616                let worker = instance("my-worker");
3617                worker.cart[golem:it]("bar")
3618            "#;
3619        let expr = Expr::from_text(expr).unwrap();
3620        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3621
3622        let compiled = compiler::compile(expr, &component_metadata)
3623            .unwrap_err()
3624            .to_string();
3625
3626        let expected = r#"
3627            error in the following rib found at line 3, column 17
3628            `cart("bar")`
3629            cause: program is invalid as it returns a resource constructor
3630            "#;
3631
3632        assert_eq!(compiled, strip_spaces(expected));
3633    }
3634
3635    // This resource construction is a Noop, and compiler can give warnings
3636    // once we support warnings in the compiler
3637    #[test]
3638    async fn test_interpreter_durable_worker_with_resource_1() {
3639        let expr = r#"
3640                let worker = instance("my-worker");
3641                worker.cart[golem:it]("bar");
3642                "success"
3643            "#;
3644        let expr = Expr::from_text(expr).unwrap();
3645        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3646
3647        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3648
3649        let mut rib_interpreter =
3650            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3651
3652        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3653
3654        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3655    }
3656
3657    #[test]
3658    async fn test_interpreter_durable_worker_with_resource_2() {
3659        let expr = r#"
3660                let worker = instance("my-worker");
3661                let cart = worker.cart[golem:it]("bar");
3662                let result = cart.add-item({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3663                result
3664            "#;
3665        let expr = Expr::from_text(expr).unwrap();
3666        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3667
3668        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3669
3670        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3671
3672        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3673
3674        let analysed_type = record(vec![
3675            field("worker-name", option(str())),
3676            field("function-name", str()),
3677            field(
3678                "args0",
3679                record(vec![
3680                    field("product-id", str()),
3681                    field("name", str()),
3682                    field("price", f32()),
3683                    field("quantity", u32()),
3684                ]),
3685            ),
3686        ]);
3687
3688        let expected_val = get_value_and_type(
3689            &analysed_type,
3690            r#"
3691              {
3692                 worker-name: some("my-worker"),
3693                 function-name: "golem:it/api.{cart(\"bar\").add-item}",
3694                 args0: {product-id: "mac", name: "macbook", price: 1.0, quantity: 1}
3695              }
3696            "#,
3697        );
3698
3699        assert_eq!(result.get_val().unwrap(), expected_val);
3700    }
3701
3702    #[test]
3703    async fn test_interpreter_durable_worker_with_resource_3() {
3704        let expr = r#"
3705                let worker = instance("my-worker");
3706                let cart = worker.cart[golem:it]("bar");
3707                cart.add-items({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3708                "success"
3709            "#;
3710        let expr = Expr::from_text(expr).unwrap();
3711        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3712
3713        let compiled = compiler::compile(expr, &component_metadata)
3714            .unwrap_err()
3715            .to_string();
3716
3717        assert_eq!(compiled, "error in the following rib found at line 4, column 17\n`cart.add-items({product-id: \"mac\", name: \"macbook\", quantity: 1: u32, price: 1: f32})`\ncause: invalid function call `add-items`\nfunction 'add-items' not found\n".to_string());
3718    }
3719
3720    #[test]
3721    async fn test_interpreter_durable_worker_with_resource_4() {
3722        let expr = r#"
3723                let worker = instance("my-worker");
3724                let cart = worker.carts[golem:it]("bar");
3725                cart.add-item({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3726                "success"
3727            "#;
3728        let expr = Expr::from_text(expr).unwrap();
3729        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3730
3731        let compiled = compiler::compile(expr, &component_metadata)
3732            .unwrap_err()
3733            .to_string();
3734
3735        assert_eq!(
3736            compiled,
3737            "error in the following rib found at line 3, column 28\n`worker.carts[golem:it](\"bar\")`\ncause: invalid function call `carts`\nfunction 'carts' not found in package 'golem:it'\n".to_string()
3738        );
3739    }
3740
3741    #[test]
3742    async fn test_interpreter_durable_worker_with_resource_5() {
3743        // Ephemeral
3744        let expr = r#"
3745                let worker = instance();
3746                let cart = worker.cart[golem:it]("bar");
3747                cart.add-item({product-id: "mac", name: "macbook", quantity: 1, price: 1});
3748                "success"
3749            "#;
3750        let expr = Expr::from_text(expr).unwrap();
3751        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3752
3753        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3754
3755        let mut rib_interpreter =
3756            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3757
3758        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3759
3760        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3761    }
3762
3763    #[test]
3764    async fn test_interpreter_durable_worker_with_resource_6() {
3765        // Ephemeral
3766        let expr = r#"
3767                let worker = instance();
3768                let cart = worker.cart[golem:it]("bar");
3769                cart.add-item({product-id: "mac", name: 1, quantity: 1, price: 1});
3770                "success"
3771            "#;
3772        let expr = Expr::from_text(expr).unwrap();
3773        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3774
3775        let error_message = compiler::compile(expr, &component_metadata)
3776            .unwrap_err()
3777            .to_string();
3778
3779        let expected = r#"
3780            error in the following rib found at line 4, column 31
3781            `{product-id: "mac", name: 1, quantity: 1, price: 1}`
3782            found within:
3783            `golem:it/api.{cart("bar").add-item}({product-id: "mac", name: 1, quantity: 1, price: 1})`
3784            cause: type mismatch at path: `name`. expected string
3785            invalid argument to the function `golem:it/api.{cart("bar").add-item}`
3786            "#;
3787
3788        assert_eq!(error_message, strip_spaces(expected));
3789    }
3790
3791    #[test]
3792    async fn test_interpreter_durable_worker_with_resource_7() {
3793        let expr = r#"
3794                let worker = instance("my-worker");
3795                let cart = worker.cart("bar");
3796                cart.add-item({product-id: "mac", name: "apple", quantity: 1, price: 1});
3797                "success"
3798            "#;
3799        let expr = Expr::from_text(expr).unwrap();
3800        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3801
3802        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3803
3804        let mut rib_interpreter =
3805            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3806
3807        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3808
3809        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3810    }
3811
3812    #[test]
3813    async fn test_interpreter_durable_worker_with_resource_8() {
3814        let expr = r#"
3815                let worker = instance("my-worker");
3816                let a = "mac";
3817                let b = "apple";
3818                let c = 1;
3819                let d = 1;
3820                let cart = worker.cart("bar");
3821                cart.add-item({product-id: a, name: b, quantity: c, price: d});
3822                "success"
3823            "#;
3824        let expr = Expr::from_text(expr).unwrap();
3825        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3826
3827        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3828
3829        let mut rib_interpreter =
3830            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3831
3832        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3833
3834        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3835    }
3836
3837    #[test]
3838    async fn test_interpreter_durable_worker_with_resource_9() {
3839        let expr = r#"
3840                let worker = instance("my-worker");
3841                let a = "mac";
3842                let b = "apple";
3843                let c = 1;
3844                let d = 1;
3845                let cart = worker.cart("bar");
3846                cart.add-item({product-id: a, name: b, quantity: c, price: d});
3847                cart.remove-item(a);
3848                cart.update-item-quantity(a, 2);
3849                let result = cart.get-cart-contents();
3850                cart.drop();
3851                result
3852            "#;
3853        let expr = Expr::from_text(expr).unwrap();
3854        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3855
3856        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3857
3858        let mut rib_interpreter =
3859            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3860
3861        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3862
3863        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3864    }
3865
3866    #[test]
3867    async fn test_interpreter_durable_worker_with_resource_10() {
3868        let expr = r#"
3869                let my_worker = "my-worker";
3870                let worker = instance(my_worker);
3871                let a = "mac";
3872                let b = "apple";
3873                let c = 1;
3874                let d = 1;
3875                let cart = worker.cart("bar");
3876                cart.add-item({product-id: a, name: b, quantity: c, price: d});
3877                cart.remove-item(a);
3878                cart.update-item-quantity(a, 2);
3879                let result = cart.get-cart-contents();
3880                cart.drop();
3881                result
3882            "#;
3883        let expr = Expr::from_text(expr).unwrap();
3884        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3885
3886        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3887
3888        let mut rib_interpreter =
3889            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3890
3891        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3892
3893        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3894    }
3895
3896    #[test]
3897    async fn test_interpreter_durable_worker_with_resource_11() {
3898        let expr = r#"
3899                let worker = instance(request.path.user-id: string);
3900                let result = worker.qux[amazon:shopping-cart]("bar");
3901                result
3902            "#;
3903        let expr = Expr::from_text(expr).unwrap();
3904        let component_metadata = test_utils::get_metadata();
3905
3906        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3907
3908        let mut input = HashMap::new();
3909
3910        // Passing request data as input to interpreter
3911        let rib_input_key = "request";
3912        let rib_input_value = ValueAndType::new(
3913            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
3914            record(vec![field("path", record(vec![field("user-id", str())]))]),
3915        );
3916
3917        input.insert(rib_input_key.to_string(), rib_input_value);
3918
3919        let rib_input = RibInput::new(input);
3920
3921        let mut rib_interpreter = test_utils::interpreter_static_response(
3922            &"success".into_value_and_type(),
3923            Some(rib_input),
3924        );
3925
3926        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3927
3928        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3929    }
3930
3931    #[test]
3932    async fn test_interpreter_durable_worker_with_resource_12() {
3933        let expr = r#"
3934                let user_id1: string = request.path.user-id;
3935                let user_id2: string = request.path.user-id;
3936                let worker1 = instance(user_id1);
3937                let result1 = worker1.qux[amazon:shopping-cart]("bar");
3938                let worker2 = instance(user_id2);
3939                let result2 = worker2.qux[amazon:shopping-cart]("bar");
3940                user_id2
3941            "#;
3942        let expr = Expr::from_text(expr).unwrap();
3943        let component_metadata = test_utils::get_metadata();
3944
3945        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3946
3947        let mut input = HashMap::new();
3948
3949        let rib_input_key = "request";
3950        let rib_input_value = ValueAndType::new(
3951            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
3952            record(vec![field("path", record(vec![field("user-id", str())]))]),
3953        );
3954
3955        input.insert(rib_input_key.to_string(), rib_input_value);
3956
3957        let rib_input = RibInput::new(input);
3958
3959        let mut rib_interpreter = test_utils::interpreter_static_response(
3960            &"success".into_value_and_type(),
3961            Some(rib_input),
3962        );
3963
3964        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3965
3966        assert_eq!(result.get_val().unwrap(), "user".into_value_and_type());
3967    }
3968
3969    #[test]
3970    async fn test_interpreter_durable_worker_with_resource_13() {
3971        let expr = r#"
3972                let worker1 = instance("foo");
3973                let result = worker.qux[amazon:shopping-cart]("bar");
3974                "success"
3975            "#;
3976        let expr = Expr::from_text(expr).unwrap();
3977        let component_metadata = test_utils::get_metadata();
3978
3979        let error = compiler::compile(expr, &component_metadata)
3980            .unwrap_err()
3981            .to_string();
3982
3983        assert_eq!(error, "error in the following rib found at line 3, column 30\n`worker.qux[amazon:shopping-cart](\"bar\")`\ncause: invalid method invocation `worker.qux`. make sure `worker` is defined and is a valid instance type (i.e, resource or worker)\n");
3984    }
3985
3986    #[test]
3987    async fn test_interpreter_durable_worker_with_resource_14() {
3988        let expr = r#"
3989                let worker = instance(1: u32);
3990                let result = worker.qux[amazon:shopping-cart]("bar");
3991                "success"
3992            "#;
3993        let expr = Expr::from_text(expr).unwrap();
3994        let component_metadata = test_utils::get_metadata();
3995
3996        let error = compiler::compile(expr, &component_metadata)
3997            .unwrap_err()
3998            .to_string();
3999
4000        let expected = r#"
4001            error in the following rib found at line 2, column 39
4002            `1: u32`
4003            cause: expected string, found u32
4004            "#;
4005
4006        assert_eq!(error, strip_spaces(expected));
4007    }
4008
4009    #[test]
4010    async fn test_interpreter_durable_worker_with_resource_15() {
4011        let expr = r#"
4012                let worker = instance("my-worker-name");
4013                let result = worker.qux[amazon:shopping-cart]("param1");
4014                result
4015            "#;
4016        let expr = Expr::from_text(expr).unwrap();
4017        let component_metadata = test_utils::get_metadata();
4018
4019        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4020
4021        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
4022
4023        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4024
4025        let result_val = result.get_val().unwrap();
4026
4027        let expected_val = test_utils::parse_function_details(
4028            r#"
4029              {
4030                 worker-name: some("my-worker-name"),
4031                 function-name: "amazon:shopping-cart/api1.{qux}",
4032                 args0: "param1"
4033              }
4034            "#,
4035        );
4036
4037        assert_eq!(result_val, expected_val);
4038    }
4039
4040    #[test]
4041    async fn test_interpreter_durable_worker_with_resource_16() {
4042        let expr = r#"
4043                let x = request.path.user-id;
4044                let worker = instance(x);
4045                let cart = worker.cart("bar");
4046                let result = cart.get-cart-contents();
4047                result
4048            "#;
4049        let expr = Expr::from_text(expr).unwrap();
4050        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4051
4052        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4053
4054        let mut input = HashMap::new();
4055
4056        let rib_input_key = "request";
4057        let rib_input_value = ValueAndType::new(
4058            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4059            record(vec![field("path", record(vec![field("user-id", str())]))]),
4060        );
4061
4062        input.insert(rib_input_key.to_string(), rib_input_value);
4063
4064        let rib_input = RibInput::new(input);
4065
4066        let mut rib_interpreter = test_utils::interpreter_worker_details_response(Some(rib_input));
4067
4068        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4069
4070        let result_val = result.get_val().unwrap();
4071
4072        let expected_analysed_type = record(vec![
4073            field("worker-name", option(str())),
4074            field("function-name", str()),
4075        ]);
4076
4077        let expected_val = parse_value_and_type(
4078            &expected_analysed_type,
4079            r#"
4080              {
4081                 worker-name: some("user"),
4082                 function-name: "golem:it/api.{cart(\"bar\").get-cart-contents}",
4083              }
4084            "#,
4085        )
4086        .unwrap();
4087
4088        assert_eq!(result_val, expected_val)
4089    }
4090
4091    #[test]
4092    async fn test_interpreter_durable_worker_with_resource_17() {
4093        let expr = r#"
4094                let x: string = request.path.user-id;
4095                let min: u8 = 1;
4096                let max: u8 = 3;
4097                let result = for i in min..=max {
4098                   let worker = instance("my-worker");
4099                   let cart = worker.cart("bar");
4100                   yield cart.get-cart-contents();
4101                };
4102                result
4103            "#;
4104        let expr = Expr::from_text(expr).unwrap();
4105        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4106
4107        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4108
4109        let mut input = HashMap::new();
4110
4111        let rib_input_key = "request";
4112        let rib_input_value = ValueAndType::new(
4113            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4114            record(vec![field("path", record(vec![field("user-id", str())]))]),
4115        );
4116
4117        input.insert(rib_input_key.to_string(), rib_input_value);
4118
4119        let rib_input = RibInput::new(input);
4120
4121        let mut rib_interpreter = test_utils::interpreter_worker_details_response(Some(rib_input));
4122
4123        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4124
4125        let result_val = result.get_val().unwrap().value;
4126
4127        let worker_name = Some("my-worker".to_string()).into_value();
4128        let function_name = "golem:it/api.{cart(\"bar\").get-cart-contents}"
4129            .to_string()
4130            .into_value();
4131
4132        let expected = Value::List(vec![
4133            Value::Record(vec![worker_name.clone(), function_name.clone()]),
4134            Value::Record(vec![worker_name.clone(), function_name.clone()]),
4135            Value::Record(vec![worker_name.clone(), function_name.clone()]),
4136        ]);
4137
4138        assert_eq!(result_val, expected);
4139    }
4140
4141    #[test]
4142    async fn test_interpreter_durable_worker_with_resource_18() {
4143        let expr = r#"
4144
4145            let initial = 1: u64;
4146            let final = 5: u64;
4147            let range = initial..final;
4148            let worker = instance("my-worker");
4149            let cart = worker.cart[golem:it]("bar");
4150
4151            for i in range {
4152                yield cart.add-item(request.body);
4153            };
4154
4155            "success"
4156        "#;
4157        let expr = Expr::from_text(expr).unwrap();
4158        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4159
4160        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4161
4162        let mut input = HashMap::new();
4163
4164        let rib_input_key = "request";
4165        let rib_input_value = ValueAndType::new(
4166            Value::Record(vec![Value::Record(vec![
4167                Value::String("mac-book".to_string()),
4168                Value::String("mac".to_string()),
4169                Value::U32(1),
4170                Value::F32(1.0),
4171            ])]),
4172            record(vec![field(
4173                "body",
4174                record(vec![
4175                    field("name", str()),
4176                    field("product-id", str()),
4177                    field("quantity", u32()),
4178                    field("price", f32()),
4179                ]),
4180            )]),
4181        );
4182
4183        input.insert(rib_input_key.to_string(), rib_input_value);
4184
4185        let rib_input = RibInput::new(input);
4186
4187        let mut rib_interpreter = test_utils::interpreter_static_response(
4188            &"success".into_value_and_type(),
4189            Some(rib_input),
4190        );
4191
4192        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4193
4194        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4195    }
4196
4197    #[test]
4198    async fn test_interpreter_durable_worker_with_resource_19() {
4199        let expr = r#"
4200
4201            let initial = 1: u64;
4202            let final = 5: u64;
4203            let range = initial..final;
4204
4205            for i in range {
4206                let worker = instance("my-worker");
4207                let cart = worker.cart[golem:it]("bar");
4208                yield cart.add-item(request.body);
4209            };
4210
4211            "success"
4212        "#;
4213        let expr = Expr::from_text(expr).unwrap();
4214        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4215
4216        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4217
4218        let mut input = HashMap::new();
4219
4220        let rib_input_key = "request";
4221        let rib_input_value = ValueAndType::new(
4222            Value::Record(vec![Value::Record(vec![
4223                Value::String("mac-book".to_string()),
4224                Value::String("mac".to_string()),
4225                Value::U32(1),
4226                Value::F32(1.0),
4227            ])]),
4228            record(vec![field(
4229                "body",
4230                record(vec![
4231                    field("name", str()),
4232                    field("product-id", str()),
4233                    field("quantity", u32()),
4234                    field("price", f32()),
4235                ]),
4236            )]),
4237        );
4238
4239        input.insert(rib_input_key.to_string(), rib_input_value);
4240
4241        let rib_input = RibInput::new(input);
4242
4243        let mut rib_interpreter = test_utils::interpreter_static_response(
4244            &"success".into_value_and_type(),
4245            Some(rib_input),
4246        );
4247
4248        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4249
4250        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4251    }
4252
4253    mod test_utils {
4254        use crate::interpreter::rib_interpreter::Interpreter;
4255        use crate::{
4256            EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, RibFunctionInvoke, RibInput,
4257        };
4258        use async_trait::async_trait;
4259        use golem_wasm_ast::analysis::analysed_type::{
4260            case, f32, field, handle, list, option, r#enum, record, result, str, tuple, u32, u64,
4261            unit_case, variant,
4262        };
4263        use golem_wasm_ast::analysis::{
4264            AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedFunctionResult,
4265            AnalysedInstance, AnalysedResourceId, AnalysedResourceMode, AnalysedType,
4266        };
4267        use golem_wasm_rpc::{IntoValueAndType, Value, ValueAndType};
4268        use std::sync::Arc;
4269
4270        pub(crate) fn strip_spaces(input: &str) -> String {
4271            let lines = input.lines();
4272
4273            let first_line = lines
4274                .clone()
4275                .find(|line| !line.trim().is_empty())
4276                .unwrap_or("");
4277            let margin_width = first_line.chars().take_while(|c| c.is_whitespace()).count();
4278
4279            let result = lines
4280                .map(|line| {
4281                    if line.trim().is_empty() {
4282                        String::new()
4283                    } else {
4284                        line[margin_width..].to_string()
4285                    }
4286                })
4287                .collect::<Vec<String>>()
4288                .join("\n");
4289
4290            result.strip_prefix("\n").unwrap_or(&result).to_string()
4291        }
4292
4293        pub(crate) fn get_analysed_type_variant() -> AnalysedType {
4294            variant(vec![
4295                case("register-user", u64()),
4296                case("process-user", str()),
4297                unit_case("validate"),
4298            ])
4299        }
4300
4301        pub(crate) fn get_analysed_type_record() -> AnalysedType {
4302            record(vec![
4303                field(
4304                    "request",
4305                    record(vec![field("path", record(vec![field("user", str())]))]),
4306                ),
4307                field("y", str()),
4308            ])
4309        }
4310
4311        pub(crate) fn get_analysed_type_result() -> AnalysedType {
4312            result(u64(), str())
4313        }
4314
4315        pub(crate) fn get_analysed_type_enum() -> AnalysedType {
4316            r#enum(&["prod", "dev", "test"])
4317        }
4318
4319        pub(crate) fn get_analysed_typ_str() -> AnalysedType {
4320            str()
4321        }
4322
4323        pub(crate) fn get_analysed_typ_u64() -> AnalysedType {
4324            u64()
4325        }
4326
4327        pub(crate) fn get_analysed_type_tuple() -> AnalysedType {
4328            tuple(vec![
4329                get_analysed_typ_u64(),
4330                get_analysed_type_result(),
4331                get_analysed_typ_str(),
4332                get_analysed_type_record(),
4333                get_analysed_type_variant(),
4334                get_analysed_type_variant(),
4335                get_analysed_type_variant(),
4336                get_analysed_type_enum(),
4337                get_analysed_type_enum(),
4338                get_analysed_type_enum(),
4339            ])
4340        }
4341
4342        pub(crate) fn get_component_metadata(
4343            function_name: &str,
4344            input_types: Vec<AnalysedType>,
4345            output: Option<AnalysedType>,
4346        ) -> Vec<AnalysedExport> {
4347            let analysed_function_parameters = input_types
4348                .into_iter()
4349                .enumerate()
4350                .map(|(index, typ)| AnalysedFunctionParameter {
4351                    name: format!("param{}", index),
4352                    typ,
4353                })
4354                .collect();
4355
4356            let results = if let Some(output) = output {
4357                vec![AnalysedFunctionResult {
4358                    name: None,
4359                    typ: output,
4360                }]
4361            } else {
4362                // Representing Unit
4363                vec![]
4364            };
4365
4366            vec![AnalysedExport::Function(AnalysedFunction {
4367                name: function_name.to_string(),
4368                parameters: analysed_function_parameters,
4369                results,
4370            })]
4371        }
4372
4373        pub(crate) fn get_metadata_with_resource_with_params() -> Vec<AnalysedExport> {
4374            get_metadata_with_resource(vec![AnalysedFunctionParameter {
4375                name: "user-id".to_string(),
4376                typ: str(),
4377            }])
4378        }
4379
4380        pub(crate) fn get_metadata_with_resource_without_params() -> Vec<AnalysedExport> {
4381            get_metadata_with_resource(vec![])
4382        }
4383
4384        pub(crate) fn get_metadata() -> Vec<AnalysedExport> {
4385            // Exist in only amazon:shopping-cart/api1
4386            let analysed_function_in_api1 = AnalysedFunction {
4387                name: "foo".to_string(),
4388                parameters: vec![AnalysedFunctionParameter {
4389                    name: "arg1".to_string(),
4390                    typ: str(),
4391                }],
4392                results: vec![AnalysedFunctionResult {
4393                    name: None,
4394                    typ: str(),
4395                }],
4396            };
4397
4398            // Exist in both amazon:shopping-cart/api1 and amazon:shopping-cart/api2
4399            let analysed_function_in_api1_and_api2 = AnalysedFunction {
4400                name: "bar".to_string(),
4401                parameters: vec![AnalysedFunctionParameter {
4402                    name: "arg1".to_string(),
4403                    typ: str(),
4404                }],
4405                results: vec![AnalysedFunctionResult {
4406                    name: None,
4407                    typ: str(),
4408                }],
4409            };
4410
4411            // Exist in only wasi:clocks/monotonic-clock
4412            let analysed_function_in_wasi = AnalysedFunction {
4413                name: "baz".to_string(),
4414                parameters: vec![AnalysedFunctionParameter {
4415                    name: "arg1".to_string(),
4416                    typ: str(),
4417                }],
4418                results: vec![AnalysedFunctionResult {
4419                    name: None,
4420                    typ: str(),
4421                }],
4422            };
4423
4424            // Exist in wasi:clocks/monotonic-clock and amazon:shopping-cart/api1
4425            let analysed_function_in_wasi_and_api1 = AnalysedFunction {
4426                name: "qux".to_string(),
4427                parameters: vec![AnalysedFunctionParameter {
4428                    name: "arg1".to_string(),
4429                    typ: str(),
4430                }],
4431                results: vec![AnalysedFunctionResult {
4432                    name: None,
4433                    typ: str(),
4434                }],
4435            };
4436
4437            let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
4438                name: "amazon:shopping-cart/api1".to_string(),
4439                functions: vec![
4440                    analysed_function_in_api1,
4441                    analysed_function_in_api1_and_api2.clone(),
4442                    analysed_function_in_wasi_and_api1.clone(),
4443                ],
4444            });
4445
4446            let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
4447                name: "amazon:shopping-cart/api2".to_string(),
4448                functions: vec![analysed_function_in_api1_and_api2],
4449            });
4450
4451            let analysed_export3 = AnalysedExport::Instance(AnalysedInstance {
4452                name: "wasi:clocks/monotonic-clock".to_string(),
4453                functions: vec![
4454                    analysed_function_in_wasi,
4455                    analysed_function_in_wasi_and_api1,
4456                ],
4457            });
4458
4459            vec![analysed_export1, analysed_export2, analysed_export3]
4460        }
4461
4462        fn get_metadata_with_resource(
4463            resource_constructor_params: Vec<AnalysedFunctionParameter>,
4464        ) -> Vec<AnalysedExport> {
4465            let instance = AnalysedExport::Instance(AnalysedInstance {
4466                name: "golem:it/api".to_string(),
4467                functions: vec![
4468                    AnalysedFunction {
4469                        name: "[constructor]cart".to_string(),
4470                        parameters: resource_constructor_params,
4471                        results: vec![AnalysedFunctionResult {
4472                            name: None,
4473                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
4474                        }],
4475                    },
4476                    AnalysedFunction {
4477                        name: "[method]cart.add-item".to_string(),
4478                        parameters: vec![
4479                            AnalysedFunctionParameter {
4480                                name: "self".to_string(),
4481                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4482                            },
4483                            AnalysedFunctionParameter {
4484                                name: "item".to_string(),
4485                                typ: record(vec![
4486                                    field("product-id", str()),
4487                                    field("name", str()),
4488                                    field("price", f32()),
4489                                    field("quantity", u32()),
4490                                ]),
4491                            },
4492                        ],
4493                        results: vec![],
4494                    },
4495                    AnalysedFunction {
4496                        name: "[method]cart.remove-item".to_string(),
4497                        parameters: vec![
4498                            AnalysedFunctionParameter {
4499                                name: "self".to_string(),
4500                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4501                            },
4502                            AnalysedFunctionParameter {
4503                                name: "product-id".to_string(),
4504                                typ: str(),
4505                            },
4506                        ],
4507                        results: vec![],
4508                    },
4509                    AnalysedFunction {
4510                        name: "[method]cart.update-item-quantity".to_string(),
4511                        parameters: vec![
4512                            AnalysedFunctionParameter {
4513                                name: "self".to_string(),
4514                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4515                            },
4516                            AnalysedFunctionParameter {
4517                                name: "product-id".to_string(),
4518                                typ: str(),
4519                            },
4520                            AnalysedFunctionParameter {
4521                                name: "quantity".to_string(),
4522                                typ: u32(),
4523                            },
4524                        ],
4525                        results: vec![],
4526                    },
4527                    AnalysedFunction {
4528                        name: "[method]cart.checkout".to_string(),
4529                        parameters: vec![AnalysedFunctionParameter {
4530                            name: "self".to_string(),
4531                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4532                        }],
4533                        results: vec![AnalysedFunctionResult {
4534                            name: None,
4535                            typ: variant(vec![
4536                                case("error", str()),
4537                                case("success", record(vec![field("order-id", str())])),
4538                            ]),
4539                        }],
4540                    },
4541                    AnalysedFunction {
4542                        name: "[method]cart.get-cart-contents".to_string(),
4543                        parameters: vec![AnalysedFunctionParameter {
4544                            name: "self".to_string(),
4545                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4546                        }],
4547                        results: vec![AnalysedFunctionResult {
4548                            name: None,
4549                            typ: list(record(vec![
4550                                field("product-id", str()),
4551                                field("name", str()),
4552                                field("price", f32()),
4553                                field("quantity", u32()),
4554                            ])),
4555                        }],
4556                    },
4557                    AnalysedFunction {
4558                        name: "[method]cart.merge-with".to_string(),
4559                        parameters: vec![
4560                            AnalysedFunctionParameter {
4561                                name: "self".to_string(),
4562                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4563                            },
4564                            AnalysedFunctionParameter {
4565                                name: "other-cart".to_string(),
4566                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4567                            },
4568                        ],
4569                        results: vec![],
4570                    },
4571                    AnalysedFunction {
4572                        name: "[drop]cart".to_string(),
4573                        parameters: vec![AnalysedFunctionParameter {
4574                            name: "self".to_string(),
4575                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
4576                        }],
4577                        results: vec![],
4578                    },
4579                ],
4580            });
4581
4582            vec![instance]
4583        }
4584
4585        pub(crate) fn get_value_and_type(
4586            analysed_type: &AnalysedType,
4587            wasm_wave_str: &str,
4588        ) -> ValueAndType {
4589            golem_wasm_rpc::parse_value_and_type(analysed_type, wasm_wave_str).unwrap()
4590        }
4591
4592        // The interpreter that always returns a static value for every function calls in Rib
4593        // regardless of the input arguments
4594        pub(crate) fn interpreter_static_response(
4595            result_value: &ValueAndType,
4596            input: Option<RibInput>,
4597        ) -> Interpreter {
4598            let value = result_value.clone();
4599
4600            let invoke = Arc::new(TestInvoke1 { value });
4601
4602            Interpreter {
4603                input: input.unwrap_or_default(),
4604                invoke,
4605                custom_stack: None,
4606                custom_env: None,
4607            }
4608        }
4609
4610        // The interpreter that always returns a record value consisting of function name, worker name etc
4611        // for every function calls in Rib.
4612        // Example : `my-instance.qux[amazon:shopping-cart]("bar")` will return a record
4613        // that contains the actual worker-name of my-instance, the function name `qux` and arguments
4614        // It helps ensures that interpreter invokes the function at the expected worker.
4615        pub(crate) fn interpreter_worker_details_response(
4616            rib_input: Option<RibInput>,
4617        ) -> Interpreter {
4618            let invoke: Arc<dyn RibFunctionInvoke + Send + Sync> = Arc::new(TestInvoke2);
4619
4620            Interpreter {
4621                input: rib_input.unwrap_or_default(),
4622                invoke,
4623                custom_stack: None,
4624                custom_env: None,
4625            }
4626        }
4627
4628        pub(crate) fn parse_function_details(input: &str) -> ValueAndType {
4629            let analysed_type = record(vec![
4630                field("worker-name", option(str())),
4631                field("function-name", str()),
4632                field("args0", str()),
4633            ]);
4634
4635            get_value_and_type(&analysed_type, input)
4636        }
4637
4638        struct TestInvoke1 {
4639            value: ValueAndType,
4640        }
4641
4642        #[async_trait]
4643        impl RibFunctionInvoke for TestInvoke1 {
4644            async fn invoke(
4645                &self,
4646                _worker_name: Option<EvaluatedWorkerName>,
4647                _fqn: EvaluatedFqFn,
4648                _args: EvaluatedFnArgs,
4649            ) -> Result<ValueAndType, String> {
4650                let value = self.value.clone();
4651                Ok(ValueAndType::new(
4652                    Value::Tuple(vec![value.value]),
4653                    tuple(vec![value.typ]),
4654                ))
4655            }
4656        }
4657
4658        struct TestInvoke2;
4659
4660        #[async_trait]
4661        impl RibFunctionInvoke for TestInvoke2 {
4662            async fn invoke(
4663                &self,
4664                worker_name: Option<EvaluatedWorkerName>,
4665                function_name: EvaluatedFqFn,
4666                args: EvaluatedFnArgs,
4667            ) -> Result<ValueAndType, String> {
4668                let worker_name = worker_name.map(|x| x.0);
4669
4670                let function_name = function_name.0.into_value_and_type();
4671
4672                let args = args.0;
4673
4674                let mut arg_types = vec![];
4675
4676                for (index, value_and_type) in args.iter().enumerate() {
4677                    let name = format!("args{}", index);
4678                    let value = value_and_type.typ.clone();
4679                    arg_types.push(field(name.as_str(), value));
4680                }
4681
4682                let mut analysed_type_pairs = vec![];
4683                analysed_type_pairs.push(field("worker-name", option(str())));
4684                analysed_type_pairs.push(field("function-name", str()));
4685                analysed_type_pairs.extend(arg_types);
4686
4687                let mut values = vec![];
4688
4689                values.push(Value::Option(
4690                    worker_name.map(|x| Box::new(Value::String(x))),
4691                ));
4692                values.push(function_name.value);
4693
4694                for arg_value in args {
4695                    values.push(arg_value.value);
4696                }
4697
4698                let value = ValueAndType::new(
4699                    Value::Tuple(vec![Value::Record(values)]),
4700                    tuple(vec![record(analysed_type_pairs)]),
4701                );
4702                Ok(value)
4703            }
4704        }
4705    }
4706}