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_analysed_type_variant, get_metadata_with_enum_and_variant, get_value_and_type,
1426        strip_spaces,
1427    };
1428    use crate::{
1429        compiler, Expr, FunctionTypeRegistry, GlobalVariableTypeSpec, InferredType, InstructionId,
1430        Path, VariableId,
1431    };
1432    use golem_wasm_ast::analysis::analysed_type::{
1433        bool, case, f32, field, list, option, r#enum, record, result, s32, s8, str, tuple, u32,
1434        u64, u8, variant,
1435    };
1436    use golem_wasm_rpc::{parse_value_and_type, IntoValue, IntoValueAndType, Value, ValueAndType};
1437
1438    #[test]
1439    async fn test_interpreter_for_literal() {
1440        let mut interpreter = Interpreter::default();
1441
1442        let instructions = RibByteCode {
1443            instructions: vec![RibIR::PushLit(1i32.into_value_and_type())],
1444        };
1445
1446        let result = interpreter.run(instructions).await.unwrap();
1447        assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1448    }
1449
1450    #[test]
1451    async fn test_interpreter_for_equal_to() {
1452        let mut interpreter = Interpreter::default();
1453
1454        let instructions = RibByteCode {
1455            instructions: vec![
1456                RibIR::PushLit(1i32.into_value_and_type()),
1457                RibIR::PushLit(1u32.into_value_and_type()),
1458                RibIR::EqualTo,
1459            ],
1460        };
1461
1462        let result = interpreter.run(instructions).await.unwrap();
1463        assert!(result.get_bool().unwrap());
1464    }
1465
1466    #[test]
1467    async fn test_interpreter_for_greater_than() {
1468        let mut interpreter = Interpreter::default();
1469
1470        let instructions = RibByteCode {
1471            instructions: vec![
1472                RibIR::PushLit(1i32.into_value_and_type()),
1473                RibIR::PushLit(2u32.into_value_and_type()),
1474                RibIR::GreaterThan,
1475            ],
1476        };
1477
1478        let result = interpreter.run(instructions).await.unwrap();
1479        assert!(result.get_bool().unwrap());
1480    }
1481
1482    #[test]
1483    async fn test_interpreter_for_less_than() {
1484        let mut interpreter = Interpreter::default();
1485
1486        let instructions = RibByteCode {
1487            instructions: vec![
1488                RibIR::PushLit(2i32.into_value_and_type()),
1489                RibIR::PushLit(1u32.into_value_and_type()),
1490                RibIR::LessThan,
1491            ],
1492        };
1493
1494        let result = interpreter.run(instructions).await.unwrap();
1495        assert!(result.get_bool().unwrap());
1496    }
1497
1498    #[test]
1499    async fn test_interpreter_for_greater_than_or_equal_to() {
1500        let mut interpreter = Interpreter::default();
1501
1502        let instructions = RibByteCode {
1503            instructions: vec![
1504                RibIR::PushLit(2i32.into_value_and_type()),
1505                RibIR::PushLit(3u32.into_value_and_type()),
1506                RibIR::GreaterThanOrEqualTo,
1507            ],
1508        };
1509
1510        let result = interpreter.run(instructions).await.unwrap();
1511        assert!(result.get_bool().unwrap());
1512    }
1513
1514    #[test]
1515    async fn test_interpreter_for_less_than_or_equal_to() {
1516        let mut interpreter = Interpreter::default();
1517
1518        let instructions = RibByteCode {
1519            instructions: vec![
1520                RibIR::PushLit(2i32.into_value_and_type()), // rhs
1521                RibIR::PushLit(1i32.into_value_and_type()), // lhs
1522                RibIR::LessThanOrEqualTo,
1523            ],
1524        };
1525
1526        let result = interpreter.run(instructions).await.unwrap();
1527        assert!(result.get_bool().unwrap());
1528    }
1529
1530    #[test]
1531    async fn test_interpreter_for_assign_and_load_var() {
1532        let mut interpreter = Interpreter::default();
1533
1534        let instructions = RibByteCode {
1535            instructions: vec![
1536                RibIR::PushLit(1i32.into_value_and_type()),
1537                RibIR::AssignVar(VariableId::local_with_no_id("x")),
1538                RibIR::LoadVar(VariableId::local_with_no_id("x")),
1539            ],
1540        };
1541
1542        let result = interpreter.run(instructions).await.unwrap();
1543        assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1544    }
1545
1546    #[test]
1547    async fn test_interpreter_for_jump() {
1548        let mut interpreter = Interpreter::default();
1549
1550        let instructions = RibByteCode {
1551            instructions: vec![
1552                RibIR::Jump(InstructionId::init()),
1553                RibIR::PushLit(1i32.into_value_and_type()),
1554                RibIR::Label(InstructionId::init()),
1555            ],
1556        };
1557
1558        let result = interpreter.run(instructions).await;
1559        assert!(result.is_ok());
1560    }
1561
1562    #[test]
1563    async fn test_interpreter_for_jump_if_false() {
1564        let mut interpreter = Interpreter::default();
1565
1566        let id = InstructionId::init().increment_mut();
1567
1568        let instructions = RibByteCode {
1569            instructions: vec![
1570                RibIR::PushLit(false.into_value_and_type()),
1571                RibIR::JumpIfFalse(id.clone()),
1572                RibIR::PushLit(1i32.into_value_and_type()),
1573                RibIR::Label(id),
1574            ],
1575        };
1576
1577        let result = interpreter.run(instructions).await;
1578        assert!(result.is_ok());
1579    }
1580
1581    #[test]
1582    async fn test_interpreter_for_record() {
1583        let mut interpreter = Interpreter::default();
1584
1585        let instructions = RibByteCode {
1586            instructions: vec![
1587                RibIR::PushLit(2i32.into_value_and_type()),
1588                RibIR::PushLit(1i32.into_value_and_type()),
1589                RibIR::CreateAndPushRecord(record(vec![field("x", s32()), field("y", s32())])),
1590                RibIR::UpdateRecord("x".to_string()),
1591                RibIR::UpdateRecord("y".to_string()),
1592            ],
1593        };
1594
1595        let result = interpreter.run(instructions).await.unwrap();
1596        let expected = ValueAndType::new(
1597            Value::Record(vec![1i32.into_value(), 2i32.into_value()]),
1598            record(vec![field("x", s32()), field("y", s32())]),
1599        );
1600
1601        assert_eq!(result.get_val().unwrap(), expected);
1602    }
1603
1604    #[test]
1605    async fn test_interpreter_for_sequence() {
1606        let mut interpreter = Interpreter::default();
1607
1608        let instructions = RibByteCode {
1609            instructions: vec![
1610                RibIR::PushLit(2i32.into_value_and_type()),
1611                RibIR::PushLit(1i32.into_value_and_type()),
1612                RibIR::PushList(list(s32()), 2),
1613            ],
1614        };
1615
1616        let result = interpreter.run(instructions).await.unwrap();
1617        let expected = ValueAndType::new(
1618            Value::List(vec![1i32.into_value(), 2i32.into_value()]),
1619            list(s32()),
1620        );
1621        assert_eq!(result.get_val().unwrap(), expected);
1622    }
1623
1624    #[test]
1625    async fn test_interpreter_for_select_field() {
1626        let mut interpreter = Interpreter::default();
1627
1628        let instructions = RibByteCode {
1629            instructions: vec![
1630                RibIR::PushLit(1i32.into_value_and_type()),
1631                RibIR::PushLit(2i32.into_value_and_type()),
1632                RibIR::CreateAndPushRecord(record(vec![field("x", s32())])),
1633                RibIR::UpdateRecord("x".to_string()),
1634                RibIR::SelectField("x".to_string()),
1635            ],
1636        };
1637
1638        let result = interpreter.run(instructions).await.unwrap();
1639        assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1640    }
1641
1642    #[test]
1643    async fn test_interpreter_for_select_index() {
1644        let mut interpreter = Interpreter::default();
1645
1646        let instructions = RibByteCode {
1647            instructions: vec![
1648                RibIR::PushLit(1i32.into_value_and_type()),
1649                RibIR::PushLit(2i32.into_value_and_type()),
1650                RibIR::PushList(list(s32()), 2),
1651                RibIR::SelectIndex(0),
1652            ],
1653        };
1654
1655        let result = interpreter.run(instructions).await.unwrap();
1656        assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1657    }
1658
1659    #[test]
1660    async fn test_interpreter_variable_scope_0() {
1661        let rib_expr = r#"
1662               let x: u64 = 1;
1663               let y = x + 2u64;
1664               y
1665            "#;
1666
1667        let expr = Expr::from_text(rib_expr).unwrap();
1668
1669        let compiled = compiler::compile(expr, &vec![]).unwrap();
1670
1671        let mut interpreter = Interpreter::default();
1672
1673        let result = interpreter.run(compiled.byte_code).await.unwrap();
1674
1675        assert_eq!(result.get_val().unwrap(), 3u64.into_value_and_type());
1676    }
1677
1678    #[test]
1679    async fn test_interpreter_variable_scope_1() {
1680        let rib_expr = r#"
1681               let x: u64 = 1;
1682               let z = {foo : x};
1683               let x = x + 2u64;
1684               { bar: x, baz: z }
1685            "#;
1686
1687        let expr = Expr::from_text(rib_expr).unwrap();
1688
1689        let compiled = compiler::compile(expr, &vec![]).unwrap();
1690
1691        let mut interpreter = Interpreter::default();
1692
1693        let result = interpreter.run(compiled.byte_code).await.unwrap();
1694
1695        let analysed_type = record(vec![
1696            field("bar", u64()),
1697            field("baz", record(vec![field("foo", u64())])),
1698        ]);
1699
1700        let expected = get_value_and_type(&analysed_type, r#"{ bar: 3, baz: { foo: 1 } }"#);
1701
1702        assert_eq!(result.get_val().unwrap(), expected);
1703    }
1704
1705    #[test]
1706    async fn test_interpreter_variable_scope_2() {
1707        let rib_expr = r#"
1708               let x: u64 = 1;
1709               let x = x;
1710
1711               let result1 = match some(x + 1:u64) {
1712                  some(x) => x,
1713                  none => x
1714               };
1715
1716               let z: option<u64> = none;
1717
1718               let result2 = match z {
1719                  some(x) => x,
1720                  none => x
1721               };
1722
1723               { result1: result1, result2: result2 }
1724            "#;
1725
1726        let expr = Expr::from_text(rib_expr).unwrap();
1727
1728        let compiled = compiler::compile(expr, &vec![]).unwrap();
1729
1730        let mut interpreter = Interpreter::default();
1731
1732        let result = interpreter.run(compiled.byte_code).await.unwrap();
1733
1734        let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1735
1736        let expected = get_value_and_type(&analysed_type, r#"{ result1: 2, result2: 1 }"#);
1737
1738        assert_eq!(result.get_val().unwrap(), expected);
1739    }
1740
1741    #[test]
1742    async fn test_interpreter_variable_scope_3() {
1743        let rib_expr = r#"
1744               let x: u64 = 1;
1745               let x = x;
1746
1747               let result1 = match some(x + 1:u64) {
1748                  some(x) => match some(x + 1:u64) {
1749                     some(x) => x,
1750                     none => x
1751                  },
1752                  none => x
1753               };
1754
1755               let z: option<u64> = none;
1756
1757               let result2 = match z {
1758                  some(x) => x,
1759                  none => match some(x + 1:u64) {
1760                     some(x) => x,
1761                     none => x
1762                  }
1763               };
1764
1765               { result1: result1, result2: result2 }
1766            "#;
1767
1768        let expr = Expr::from_text(rib_expr).unwrap();
1769
1770        let compiled = compiler::compile(expr, &vec![]).unwrap();
1771
1772        let mut interpreter = Interpreter::default();
1773
1774        let result = interpreter.run(compiled.byte_code).await.unwrap();
1775
1776        let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1777
1778        let expected = get_value_and_type(&analysed_type, r#"{ result1: 3, result2: 2 }"#);
1779
1780        assert_eq!(result.get_val().unwrap(), expected);
1781    }
1782
1783    #[test]
1784    async fn test_interpreter_global_variable_with_type_spec() {
1785        // request.path.user-id and request.headers.* should be inferred as string,
1786        // since we configure the compiler with a type-spec (given below)
1787        let rib_expr = r#"
1788               let res1 = request.path.user-id;
1789               let res2 = request.headers.name;
1790               let res3 = request.headers.age;
1791               "${res1}-${res2}-${res3}"
1792            "#;
1793
1794        let type_spec = vec![
1795            GlobalVariableTypeSpec {
1796                variable_id: VariableId::global("request".to_string()),
1797                path: Path::from_elems(vec!["path"]),
1798                inferred_type: InferredType::Str,
1799            },
1800            GlobalVariableTypeSpec {
1801                variable_id: VariableId::global("request".to_string()),
1802                path: Path::from_elems(vec!["headers"]),
1803                inferred_type: InferredType::Str,
1804            },
1805        ];
1806
1807        let mut rib_input = HashMap::new();
1808
1809        // Rib compiler identifies the input requirements to be a string (due to type-spec passed)
1810        // and therefore, we pass input value (value_and_type) to the interpreter with headers and path values as string
1811        let analysed_type_of_input = &record(vec![
1812            field("path", record(vec![field("user-id", str())])),
1813            field(
1814                "headers",
1815                record(vec![field("name", str()), field("age", str())]),
1816            ),
1817        ]);
1818
1819        let value_and_type = get_value_and_type(
1820            analysed_type_of_input,
1821            r#"{path : { user-id: "1" }, headers: { name: "foo", age: "20" }}"#,
1822        );
1823
1824        rib_input.insert("request".to_string(), value_and_type);
1825
1826        let mut interpreter = test_utils::interpreter_static_response(
1827            &ValueAndType::new(Value::S8(1), s8()),
1828            Some(RibInput::new(rib_input)),
1829        );
1830
1831        let expr = Expr::from_text(rib_expr).unwrap();
1832
1833        let compiled =
1834            compiler::compile_with_restricted_global_variables(expr, &vec![], None, &type_spec)
1835                .unwrap();
1836
1837        let result = interpreter
1838            .run(compiled.byte_code)
1839            .await
1840            .unwrap()
1841            .get_val()
1842            .unwrap()
1843            .value;
1844
1845        assert_eq!(result, Value::String("1-foo-20".to_string()))
1846    }
1847
1848    #[test]
1849    async fn test_interpreter_global_variable_override_type_spec() {
1850        let rib_expr = r#"
1851             let res1: u32 = request.path.user-id;
1852             let res2 = request.headers.name;
1853             let res3: u32 = request.headers.age;
1854             let res4 = res1 + res3;
1855             "${res4}-${res2}"
1856            "#;
1857
1858        // We always specify the type of request.path.* and request.headers.* to be a string using type-spec
1859        // however the rib script (above) explicitly specify the type of request.path.user-id
1860        // and request.header.age to be u32. In this case, the Rib compiler infer them as u32 and interpreter works with u32.
1861        let type_spec = vec![
1862            GlobalVariableTypeSpec {
1863                variable_id: VariableId::global("request".to_string()),
1864                path: Path::from_elems(vec!["path"]),
1865                inferred_type: InferredType::Str,
1866            },
1867            GlobalVariableTypeSpec {
1868                variable_id: VariableId::global("request".to_string()),
1869                path: Path::from_elems(vec!["headers"]),
1870                inferred_type: InferredType::Str,
1871            },
1872        ];
1873
1874        let mut rib_input = HashMap::new();
1875
1876        // We pass the input value to rib-interpreter with request.path.user-id
1877        // and request.headers.age as u32, since the compiler inferred these input type requirements to be u32.
1878        let analysed_type_of_input = &record(vec![
1879            field("path", record(vec![field("user-id", u32())])),
1880            field(
1881                "headers",
1882                record(vec![field("name", str()), field("age", u32())]),
1883            ),
1884        ]);
1885
1886        let value_and_type = get_value_and_type(
1887            analysed_type_of_input,
1888            r#"{path : { user-id: 1 }, headers: { name: "foo", age: 20 }}"#,
1889        );
1890
1891        rib_input.insert("request".to_string(), value_and_type);
1892
1893        let mut interpreter = test_utils::interpreter_static_response(
1894            &ValueAndType::new(Value::S8(1), s8()),
1895            Some(RibInput::new(rib_input)),
1896        );
1897
1898        let expr = Expr::from_text(rib_expr).unwrap();
1899
1900        let compiled =
1901            compiler::compile_with_restricted_global_variables(expr, &vec![], None, &type_spec)
1902                .unwrap();
1903
1904        let result = interpreter
1905            .run(compiled.byte_code)
1906            .await
1907            .unwrap()
1908            .get_val()
1909            .unwrap()
1910            .value;
1911
1912        assert_eq!(result, Value::String("21-foo".to_string()))
1913    }
1914
1915    #[test]
1916    async fn test_interpreter_with_variant_and_enum() {
1917        let mut interpreter = test_utils::interpreter_dynamic_response(None);
1918
1919        // This has intentionally got conflicting variable names
1920        // variable `x` is same as the enum name `x`
1921        // similarly, variably `validate` is same as the variant name validate
1922        let expr = r#"
1923          let x = x;
1924          let y = x;
1925          let result1 = add-enum(x, y);
1926          let validate = validate;
1927          let validate2 = validate;
1928          let result2 = add-variant(validate, validate2);
1929          {res1: result1, res2: result2}
1930        "#;
1931
1932        let expr = Expr::from_text(expr).unwrap();
1933        let compiled = compiler::compile(expr, &get_metadata_with_enum_and_variant()).unwrap();
1934        let result = interpreter.run(compiled.byte_code).await.unwrap();
1935        let expected_enum_type = r#enum(&["x", "y", "z"]);
1936        let expected_variant_type = get_analysed_type_variant();
1937
1938        let expected_record_type = record(vec![
1939            field("res1", expected_enum_type),
1940            field("res2", expected_variant_type),
1941        ]);
1942
1943        let expected_record_value = Value::Record(vec![
1944            Value::Enum(0),
1945            Value::Variant {
1946                case_idx: 2,
1947                case_value: None,
1948            },
1949        ]);
1950
1951        assert_eq!(
1952            result,
1953            RibResult::Val(ValueAndType::new(
1954                expected_record_value,
1955                expected_record_type
1956            ))
1957        );
1958    }
1959
1960    #[test]
1961    async fn test_interpreter_with_conflicting_variable_names() {
1962        let mut interpreter = test_utils::interpreter_dynamic_response(None);
1963
1964        // This has intentionally conflicting variable names
1965        // variable `x` is same as the enum name `x`
1966        // similarly, variably `validate` is same as the variant name `validate`
1967        // and `process-user` is same as the variant name `process-user`
1968        let expr = r#"
1969          let x = 1;
1970          let y = 2;
1971          let result1 = add-u32(x, y);
1972          let process-user = 3;
1973          let validate = 4;
1974          let result2 = add-u64(process-user, validate);
1975          {res1: result1, res2: result2}
1976        "#;
1977
1978        let expr = Expr::from_text(expr).unwrap();
1979        let compiled = compiler::compile(expr, &get_metadata_with_enum_and_variant()).unwrap();
1980        let result = interpreter.run(compiled.byte_code).await.unwrap();
1981        let expected_value = Value::Record(vec![3u32.into_value(), 7u64.into_value()]);
1982
1983        let expected_type = record(vec![field("res1", u32()), field("res2", u64())]);
1984        assert_eq!(
1985            result,
1986            RibResult::Val(ValueAndType::new(expected_value, expected_type))
1987        );
1988    }
1989
1990    #[test]
1991    async fn test_interpreter_list_reduce() {
1992        let mut interpreter = Interpreter::default();
1993
1994        let rib_expr = r#"
1995          let x: list<u8> = [1, 2];
1996
1997          reduce z, a in x from 0u8 {
1998            yield z + a;
1999          }
2000
2001          "#;
2002
2003        let expr = Expr::from_text(rib_expr).unwrap();
2004
2005        let compiled = compiler::compile(expr, &vec![]).unwrap();
2006
2007        let result = interpreter
2008            .run(compiled.byte_code)
2009            .await
2010            .unwrap()
2011            .get_val()
2012            .unwrap();
2013
2014        assert_eq!(result, 3u8.into_value_and_type());
2015    }
2016
2017    #[test]
2018    async fn test_interpreter_list_reduce_from_record() {
2019        let mut interpreter = Interpreter::default();
2020
2021        let rib_expr = r#"
2022           let x = [{name: "foo", age: 1u64}, {name: "bar", age: 2u64}];
2023
2024           let names = for i in x {
2025             yield i.name;
2026           };
2027
2028          reduce z, a in names from "" {
2029            let result = if z == "" then a else "${z}, ${a}";
2030
2031            yield result;
2032          }
2033
2034          "#;
2035
2036        let expr = Expr::from_text(rib_expr).unwrap();
2037
2038        let compiled = compiler::compile(expr, &vec![]).unwrap();
2039
2040        let result = interpreter
2041            .run(compiled.byte_code)
2042            .await
2043            .unwrap()
2044            .get_val()
2045            .unwrap();
2046
2047        assert_eq!(result, "foo, bar".into_value_and_type());
2048    }
2049
2050    #[test]
2051    async fn test_interpreter_list_reduce_text() {
2052        let mut interpreter = Interpreter::default();
2053
2054        let rib_expr = r#"
2055           let x = ["foo", "bar"];
2056
2057          reduce z, a in x from "" {
2058            let result = if z == "" then a else "${z}, ${a}";
2059
2060            yield result;
2061          }
2062
2063          "#;
2064
2065        let expr = Expr::from_text(rib_expr).unwrap();
2066
2067        let compiled = compiler::compile(expr, &vec![]).unwrap();
2068
2069        let result = interpreter
2070            .run(compiled.byte_code)
2071            .await
2072            .unwrap()
2073            .get_val()
2074            .unwrap();
2075
2076        assert_eq!(result, "foo, bar".into_value_and_type());
2077    }
2078
2079    #[test]
2080    async fn test_interpreter_list_reduce_empty() {
2081        let mut interpreter = Interpreter::default();
2082
2083        let rib_expr = r#"
2084          let x: list<u8> = [];
2085
2086          reduce z, a in x from 0u8 {
2087            yield z + a;
2088          }
2089
2090          "#;
2091
2092        let expr = Expr::from_text(rib_expr).unwrap();
2093
2094        let compiled = compiler::compile(expr, &vec![]).unwrap();
2095
2096        let result = interpreter
2097            .run(compiled.byte_code)
2098            .await
2099            .unwrap()
2100            .get_val()
2101            .unwrap();
2102
2103        assert_eq!(result, 0u8.into_value_and_type());
2104    }
2105
2106    #[test]
2107    async fn test_interpreter_with_numbers_1() {
2108        let component_metadata =
2109            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2110
2111        let mut interpreter =
2112            test_utils::interpreter_static_response(&ValueAndType::new(Value::U64(2), u64()), None);
2113
2114        // 1 is automatically inferred to be u32
2115        let rib = r#"
2116          let worker = instance("my-worker");
2117          worker.foo(1)
2118        "#;
2119
2120        let expr = Expr::from_text(rib).unwrap();
2121        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2122        let result = interpreter.run(compiled.byte_code).await.unwrap();
2123
2124        assert_eq!(
2125            result.get_val().unwrap(),
2126            ValueAndType::new(Value::U64(2), u64())
2127        );
2128    }
2129
2130    #[test]
2131    async fn test_interpreter_with_numbers_2() {
2132        let component_metadata =
2133            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2134
2135        let mut interpreter =
2136            test_utils::interpreter_static_response(&ValueAndType::new(Value::U64(2), u64()), None);
2137
2138        // 1 and 2 are automatically inferred to be u32
2139        // since the type of z is inferred to be u32 as that being passed to a function
2140        // that expects u32
2141        let rib = r#"
2142          let worker = instance("my-worker");
2143          let z = 1 + 2;
2144          worker.foo(z)
2145        "#;
2146
2147        let expr = Expr::from_text(rib).unwrap();
2148        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2149        let result = interpreter.run(compiled.byte_code).await.unwrap();
2150
2151        assert_eq!(
2152            result.get_val().unwrap(),
2153            ValueAndType::new(Value::U64(2), u64())
2154        );
2155    }
2156
2157    #[test]
2158    async fn test_interpreter_with_numbers_3() {
2159        let component_metadata =
2160            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2161
2162        // This will cause a type inference error
2163        // because the operands of the + operator are not of the same type
2164        let rib = r#"
2165          let worker = instance("my-worker");
2166          let z = 1: u8 + 2;
2167          worker.foo(z)
2168        "#;
2169
2170        let expr = Expr::from_text(rib).unwrap();
2171        let compile_result = compiler::compile(expr, &component_metadata);
2172        assert!(compile_result.is_err());
2173    }
2174
2175    #[test]
2176    async fn test_interpreter_with_numbers_4() {
2177        let component_metadata =
2178            test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2179
2180        // This will cause a type inference error
2181        // because the operands of the + operator are supposed to be u32
2182        // since z is u32
2183        let rib = r#"
2184          let worker = instance("my-worker");
2185          let z = 1: u8 + 2: u8;
2186          worker.foo(z)
2187        "#;
2188
2189        let expr = Expr::from_text(rib).unwrap();
2190        let compile_result = compiler::compile(expr, &component_metadata);
2191        assert!(compile_result.is_err());
2192    }
2193
2194    #[test]
2195    async fn test_interpreter_list_comprehension() {
2196        let mut interpreter = Interpreter::default();
2197
2198        let rib_expr = r#"
2199          let x = ["foo", "bar"];
2200
2201          for i in x {
2202            yield i;
2203          }
2204
2205          "#;
2206
2207        let expr = Expr::from_text(rib_expr).unwrap();
2208
2209        let compiled = compiler::compile(expr, &vec![]).unwrap();
2210
2211        let result = interpreter
2212            .run(compiled.byte_code)
2213            .await
2214            .unwrap()
2215            .get_val()
2216            .unwrap();
2217
2218        let expected = r#"["foo", "bar"]"#;
2219        let expected_value = golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2220
2221        assert_eq!(result, expected_value);
2222    }
2223
2224    #[test]
2225    async fn test_interpreter_list_comprehension_empty() {
2226        let mut interpreter = Interpreter::default();
2227
2228        let rib_expr = r#"
2229          let x: list<string> = [];
2230
2231          for i in x {
2232            yield i;
2233          }
2234
2235          "#;
2236
2237        let expr = Expr::from_text(rib_expr).unwrap();
2238
2239        let compiled = compiler::compile(expr, &vec![]).unwrap();
2240
2241        let result = interpreter
2242            .run(compiled.byte_code)
2243            .await
2244            .unwrap()
2245            .get_val()
2246            .unwrap();
2247
2248        let expected = r#"[]"#;
2249        let expected_value_and_type =
2250            golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2251
2252        assert_eq!(result, expected_value_and_type);
2253    }
2254
2255    #[test]
2256    async fn test_interpreter_pattern_match_on_option_nested() {
2257        let mut interpreter = Interpreter::default();
2258
2259        let expr = r#"
2260           let x: option<option<u64>> = none;
2261
2262           match x {
2263              some(some(t)) => t,
2264              some(none) => 0u64,
2265              none => 0u64
2266
2267           }
2268        "#;
2269
2270        let mut expr = Expr::from_text(expr).unwrap();
2271        expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2272            .unwrap();
2273        let compiled = compiler::compile(expr, &vec![]).unwrap();
2274        let result = interpreter.run(compiled.byte_code).await.unwrap();
2275
2276        assert_eq!(result.get_val().unwrap(), 0u64.into_value_and_type());
2277    }
2278
2279    #[test]
2280    async fn test_interpreter_pattern_match_on_tuple() {
2281        let mut interpreter = Interpreter::default();
2282
2283        let expr = r#"
2284           let x: tuple<u64, string, string> = (1, "foo", "bar");
2285
2286           match x {
2287              (x, y, z) => "${x} ${y} ${z}"
2288           }
2289        "#;
2290
2291        let mut expr = Expr::from_text(expr).unwrap();
2292        expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2293            .unwrap();
2294        let compiled = compiler::compile(expr, &vec![]).unwrap();
2295        let result = interpreter.run(compiled.byte_code).await.unwrap();
2296
2297        assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2298    }
2299
2300    #[test]
2301    async fn test_interpreter_pattern_match_on_tuple_with_option_some() {
2302        let mut interpreter = Interpreter::default();
2303
2304        let expr = r#"
2305           let x: tuple<u64, option<string>, string> = (1, some("foo"), "bar");
2306
2307           match x {
2308              (x, none, z) => "${x} ${z}",
2309              (x, some(y), z) => "${x} ${y} ${z}"
2310           }
2311        "#;
2312
2313        let mut expr = Expr::from_text(expr).unwrap();
2314        expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2315            .unwrap();
2316
2317        let compiled = compiler::compile(expr, &vec![]).unwrap();
2318        let result = interpreter.run(compiled.byte_code).await.unwrap();
2319
2320        assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2321    }
2322
2323    #[test]
2324    async fn test_interpreter_pattern_match_on_tuple_with_option_none() {
2325        let mut interpreter = Interpreter::default();
2326
2327        let expr = r#"
2328           let x: tuple<u64, option<string>, string> = (1, none, "bar");
2329
2330           match x {
2331              (x, none, z) => "${x} ${z}",
2332              (x, some(y), z) => "${x} ${y} ${z}"
2333           }
2334        "#;
2335
2336        let expr = Expr::from_text(expr).unwrap();
2337        let compiled = compiler::compile(expr, &vec![]).unwrap();
2338        let result = interpreter.run(compiled.byte_code).await.unwrap();
2339
2340        assert_eq!(result.get_val().unwrap(), "1 bar".into_value_and_type());
2341    }
2342
2343    #[test]
2344    async fn test_interpreter_pattern_match_dynamic_branch_1() {
2345        let mut interpreter = Interpreter::default();
2346
2347        let expr = r#"
2348           let x: u64 = 1;
2349
2350           match x {
2351                1 => ok(1: u64),
2352                2 => err("none")
2353           }
2354        "#;
2355
2356        let expr = Expr::from_text(expr).unwrap();
2357        let compiled = compiler::compile(expr, &vec![]).unwrap();
2358        let rib_result = interpreter.run(compiled.byte_code).await.unwrap();
2359
2360        let expected = ValueAndType::new(
2361            Value::Result(Ok(Some(Box::new(Value::U64(1))))),
2362            result(u64(), str()),
2363        );
2364
2365        assert_eq!(rib_result.get_val().unwrap(), expected);
2366    }
2367
2368    #[test]
2369    async fn test_interpreter_pattern_match_dynamic_branch_2() {
2370        let mut interpreter = Interpreter::default();
2371
2372        let expr = r#"
2373           let x = some({foo: 1:u64});
2374
2375           match x {
2376               some(x) => ok(x.foo),
2377               none => err("none")
2378           }
2379        "#;
2380
2381        let expr = Expr::from_text(expr).unwrap();
2382        let compiled = compiler::compile(expr, &vec![]).unwrap();
2383        let rib_result = interpreter.run(compiled.byte_code).await.unwrap();
2384
2385        let expected = ValueAndType::new(
2386            Value::Result(Ok(Some(Box::new(Value::U64(1))))),
2387            result(u64(), str()),
2388        );
2389
2390        assert_eq!(rib_result.get_val().unwrap(), expected);
2391    }
2392
2393    #[test]
2394    async fn test_interpreter_pattern_match_on_tuple_with_all_types() {
2395        let mut interpreter = Interpreter::default();
2396
2397        let tuple = test_utils::get_analysed_type_tuple();
2398
2399        let analysed_exports = test_utils::get_component_metadata("foo", vec![tuple], Some(str()));
2400
2401        let expr = r#"
2402
2403           let record = { request : { path : { user : "jak" } }, y : "bar" };
2404           let input = (1, ok(100), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2405           foo(input);
2406           match input {
2407             (n1, err(x1), txt, rec, process-user(x), register-user(n), validate, dev, prod, test) =>  "Invalid",
2408             (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}"
2409           }
2410
2411        "#;
2412
2413        let expr = Expr::from_text(expr).unwrap();
2414        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2415        let result = interpreter.run(compiled.byte_code).await.unwrap();
2416
2417        assert_eq!(
2418            result.get_val().unwrap(),
2419            "foo 100 1 bar jak validate prod dev test".into_value_and_type()
2420        );
2421    }
2422
2423    #[test]
2424    async fn test_interpreter_pattern_match_on_tuple_with_wild_pattern() {
2425        let mut interpreter = Interpreter::default();
2426
2427        let tuple = test_utils::get_analysed_type_tuple();
2428
2429        let analysed_exports =
2430            test_utils::get_component_metadata("my-worker-function", vec![tuple], Some(str()));
2431
2432        let expr = r#"
2433
2434           let record = { request : { path : { user : "jak" } }, y : "baz" };
2435           let input = (1, ok(1), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2436           my-worker-function(input);
2437           match input {
2438             (n1, ok(x), txt, rec, _, _, _, _, prod, _) =>  "prod ${n1} ${txt} ${rec.request.path.user} ${rec.y}",
2439             (n1, ok(x), txt, rec, _, _, _, _, dev, _) =>   "dev ${n1} ${txt} ${rec.request.path.user} ${rec.y}"
2440           }
2441        "#;
2442
2443        let expr = Expr::from_text(expr).unwrap();
2444        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2445        let result = interpreter.run(compiled.byte_code).await.unwrap();
2446
2447        assert_eq!(
2448            result.get_val().unwrap(),
2449            "dev 1 bar jak baz".into_value_and_type()
2450        );
2451    }
2452
2453    #[test]
2454    async fn test_interpreter_record_output_in_pattern_match() {
2455        let input_analysed_type = test_utils::get_analysed_type_record();
2456        let output_analysed_type = test_utils::get_analysed_type_result();
2457
2458        let result_value = get_value_and_type(&output_analysed_type, r#"ok(1)"#);
2459
2460        let mut interpreter = test_utils::interpreter_static_response(&result_value, None);
2461
2462        let analysed_exports = test_utils::get_component_metadata(
2463            "my-worker-function",
2464            vec![input_analysed_type],
2465            Some(output_analysed_type),
2466        );
2467
2468        let expr = r#"
2469
2470           let input = { request : { path : { user : "jak" } }, y : "baz" };
2471           let result = my-worker-function(input);
2472           match result {
2473             ok(result) => { body: result, status: 200 },
2474             err(result) => { status: 400, body: 400 }
2475           }
2476        "#;
2477
2478        let expr = Expr::from_text(expr).unwrap();
2479        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2480        let result = interpreter.run(compiled.byte_code).await.unwrap();
2481
2482        let expected = test_utils::get_value_and_type(
2483            &record(vec![field("body", u64()), field("status", u64())]),
2484            r#"{body: 1, status: 200}"#,
2485        );
2486
2487        assert_eq!(result.get_val().unwrap(), expected);
2488    }
2489
2490    #[test]
2491    async fn test_interpreter_tuple_output_in_pattern_match() {
2492        let input_analysed_type = test_utils::get_analysed_type_record();
2493        let output_analysed_type = test_utils::get_analysed_type_result();
2494
2495        let result_value = get_value_and_type(&output_analysed_type, r#"err("failed")"#);
2496
2497        let mut interpreter = test_utils::interpreter_static_response(&result_value, None);
2498
2499        let analysed_exports = test_utils::get_component_metadata(
2500            "my-worker-function",
2501            vec![input_analysed_type],
2502            Some(output_analysed_type),
2503        );
2504
2505        let expr = r#"
2506
2507           let input = { request : { path : { user : "jak" } }, y : "baz" };
2508           let result = my-worker-function(input);
2509           match result {
2510             ok(res) => ("${res}", "foo"),
2511             err(msg) => (msg, "bar")
2512           }
2513        "#;
2514
2515        let expr = Expr::from_text(expr).unwrap();
2516        let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2517        let result = interpreter.run(compiled.byte_code).await.unwrap();
2518
2519        let expected = get_value_and_type(&tuple(vec![str(), str()]), r#"("failed", "bar")"#);
2520
2521        assert_eq!(result.get_val().unwrap(), expected);
2522    }
2523
2524    #[test]
2525    async fn test_interpreter_with_indexed_resource_drop() {
2526        let expr = r#"
2527           let user_id = "user";
2528           golem:it/api.{cart(user_id).drop}();
2529           "success"
2530        "#;
2531        let expr = Expr::from_text(expr).unwrap();
2532        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2533
2534        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2535
2536        let mut rib_interpreter = Interpreter::default();
2537        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2538
2539        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2540    }
2541
2542    #[test]
2543    async fn test_interpreter_with_indexed_resource_checkout() {
2544        let expr = r#"
2545           let user_id = "foo";
2546           let result = golem:it/api.{cart(user_id).checkout}();
2547           result
2548        "#;
2549
2550        let expr = Expr::from_text(expr).unwrap();
2551
2552        let result_type = variant(vec![
2553            case("error", str()),
2554            case("success", record(vec![field("order-id", str())])),
2555        ]);
2556
2557        let result_value = test_utils::get_value_and_type(
2558            &result_type,
2559            r#"
2560          success({order-id: "foo"})
2561        "#,
2562        );
2563
2564        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2565        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2566
2567        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2568        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2569
2570        assert_eq!(result.get_val().unwrap(), result_value);
2571    }
2572
2573    #[test]
2574    async fn test_interpreter_with_indexed_resource_get_cart_contents() {
2575        let expr = r#"
2576           let user_id = "bar";
2577           let result = golem:it/api.{cart(user_id).get-cart-contents}();
2578           result[0].product-id
2579        "#;
2580
2581        let expr = Expr::from_text(expr).unwrap();
2582
2583        let result_type = list(record(vec![
2584            field("product-id", str()),
2585            field("name", str()),
2586            field("price", f32()),
2587            field("quantity", u32()),
2588        ]));
2589
2590        let result_value = test_utils::get_value_and_type(
2591            &result_type,
2592            r#"
2593            [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}]
2594        "#,
2595        );
2596
2597        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2598        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2599
2600        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2601        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2602
2603        assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2604    }
2605
2606    #[test]
2607    async fn test_interpreter_with_indexed_resource_update_item_quantity() {
2608        let expr = r#"
2609           let user_id = "jon";
2610           let product_id = "mac";
2611           let quantity = 1032;
2612           golem:it/api.{cart(user_id).update-item-quantity}(product_id, quantity);
2613           "successfully updated"
2614        "#;
2615        let expr = Expr::from_text(expr).unwrap();
2616
2617        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2618
2619        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2620
2621        let mut rib_executor = Interpreter::default();
2622
2623        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2624
2625        assert_eq!(
2626            result.get_val().unwrap(),
2627            "successfully updated".into_value_and_type()
2628        );
2629    }
2630
2631    #[test]
2632    async fn test_interpreter_with_indexed_resource_add_item() {
2633        let expr = r#"
2634           let user_id = "foo";
2635           let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2636           golem:it/api.{cart(user_id).add-item}(product);
2637
2638           "successfully added"
2639        "#;
2640
2641        let expr = Expr::from_text(expr).unwrap();
2642
2643        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2644
2645        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2646
2647        let mut rib_executor = Interpreter::default();
2648
2649        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2650
2651        assert_eq!(
2652            result.get_val().unwrap(),
2653            "successfully added".into_value_and_type()
2654        );
2655    }
2656
2657    #[test]
2658    async fn test_interpreter_with_resource_add_item() {
2659        let expr = r#"
2660           let user_id = "foo";
2661           let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2662           golem:it/api.{cart.add-item}(product);
2663
2664           "successfully added"
2665        "#;
2666
2667        let expr = Expr::from_text(expr).unwrap();
2668
2669        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2670
2671        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2672
2673        let mut rib_executor = Interpreter::default();
2674
2675        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2676
2677        assert_eq!(
2678            result.get_val().unwrap(),
2679            "successfully added".into_value_and_type()
2680        );
2681    }
2682
2683    #[test]
2684    async fn test_interpreter_with_resource_get_cart_contents() {
2685        let expr = r#"
2686           let result = golem:it/api.{cart.get-cart-contents}();
2687           result[0].product-id
2688        "#;
2689
2690        let expr = Expr::from_text(expr).unwrap();
2691
2692        let result_type = list(record(vec![
2693            field("product-id", str()),
2694            field("name", str()),
2695            field("price", f32()),
2696            field("quantity", u32()),
2697        ]));
2698
2699        let result_value = test_utils::get_value_and_type(
2700            &result_type,
2701            r#"
2702            [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}]
2703        "#,
2704        );
2705
2706        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2707        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2708
2709        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2710        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2711
2712        assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2713    }
2714
2715    #[test]
2716    async fn test_interpreter_with_resource_update_item() {
2717        let expr = r#"
2718           let product_id = "mac";
2719           let quantity = 1032;
2720           golem:it/api.{cart.update-item-quantity}(product_id, quantity);
2721           "successfully updated"
2722        "#;
2723        let expr = Expr::from_text(expr).unwrap();
2724
2725        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2726
2727        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2728
2729        let mut rib_executor = Interpreter::default();
2730
2731        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2732
2733        assert_eq!(
2734            result.get_val().unwrap(),
2735            "successfully updated".into_value_and_type()
2736        );
2737    }
2738
2739    #[test]
2740    async fn test_interpreter_with_resource_checkout() {
2741        let expr = r#"
2742           let result = golem:it/api.{cart.checkout}();
2743           result
2744        "#;
2745
2746        let expr = Expr::from_text(expr).unwrap();
2747
2748        let result_type = variant(vec![
2749            case("error", str()),
2750            case("success", record(vec![field("order-id", str())])),
2751        ]);
2752
2753        let result_value = test_utils::get_value_and_type(
2754            &result_type,
2755            r#"
2756          success({order-id: "foo"})
2757        "#,
2758        );
2759
2760        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2761        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2762
2763        let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2764        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2765
2766        assert_eq!(result.get_val().unwrap(), result_value);
2767    }
2768
2769    #[test]
2770    async fn test_interpreter_with_resource_drop() {
2771        let expr = r#"
2772           golem:it/api.{cart.drop}();
2773           "success"
2774        "#;
2775        let expr = Expr::from_text(expr).unwrap();
2776        let component_metadata = test_utils::get_metadata_with_resource_without_params();
2777
2778        let compiled = compiler::compile(expr, &component_metadata).unwrap();
2779
2780        let mut rib_interpreter = Interpreter::default();
2781        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2782
2783        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2784    }
2785
2786    #[test]
2787    async fn test_interpreter_for_select_index_expr_1() {
2788        // infinite computation will respond with an error - than a stack overflow
2789        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
2790        let expr = r#"
2791              let list: list<u8> = [1, 2, 3, 4, 5];
2792              let index: u8 = 4;
2793              list[index]
2794              "#;
2795
2796        let expr = Expr::from_text(expr).unwrap();
2797
2798        let compiled = compiler::compile(expr, &vec![]).unwrap();
2799
2800        let mut interpreter = Interpreter::default();
2801        let result = interpreter.run(compiled.byte_code).await.unwrap();
2802
2803        let expected = ValueAndType::new(Value::U8(5), u8());
2804
2805        assert_eq!(result.get_val().unwrap(), expected);
2806    }
2807
2808    #[test]
2809    async fn test_interpreter_for_select_index_expr_out_of_bound() {
2810        let expr = r#"
2811              let list: list<u8> = [1, 2, 3, 4, 5];
2812              let index: u8 = 10;
2813              list[index]
2814              "#;
2815
2816        let expr = Expr::from_text(expr).unwrap();
2817
2818        let compiled = compiler::compile(expr, &vec![]).unwrap();
2819
2820        let mut interpreter = Interpreter::default();
2821        let result = interpreter.run(compiled.byte_code).await.unwrap_err();
2822
2823        assert_eq!(
2824            result,
2825            "index 10 is out of bound in the list of length 5".to_string()
2826        );
2827    }
2828
2829    #[test]
2830    async fn test_interpreter_for_select_index_expr_2() {
2831        let expr = r#"
2832              let list: list<u8> = [1, 2, 3, 4, 5];
2833              let indices: list<u8> = [0, 1, 2, 3];
2834
2835              for i in indices {
2836                 yield list[i];
2837              }
2838              "#;
2839
2840        let expr = Expr::from_text(expr).unwrap();
2841
2842        let compiled = compiler::compile(expr, &vec![]).unwrap();
2843
2844        let mut interpreter = Interpreter::default();
2845        let result = interpreter.run(compiled.byte_code).await.unwrap();
2846
2847        let expected = ValueAndType::new(
2848            Value::List(vec![Value::U8(1), Value::U8(2), Value::U8(3), Value::U8(4)]),
2849            list(u8()),
2850        );
2851
2852        assert_eq!(result.get_val().unwrap(), expected);
2853    }
2854
2855    #[test]
2856    async fn test_interpreter_for_select_index_expr_3() {
2857        let expr = r#"
2858              let list: list<u8> = [2, 5, 4];
2859              let indices: list<u8> = [0, 1];
2860
2861               reduce z, index in indices from 0u8 {
2862                  yield list[index] + z;
2863                }
2864              "#;
2865
2866        let expr = Expr::from_text(expr).unwrap();
2867
2868        let compiled = compiler::compile(expr, &vec![]).unwrap();
2869
2870        let mut interpreter = Interpreter::default();
2871        let result = interpreter.run(compiled.byte_code).await.unwrap();
2872
2873        let expected = ValueAndType::new(Value::U8(7), u8());
2874
2875        assert_eq!(result.get_val().unwrap(), expected);
2876    }
2877
2878    #[test]
2879    async fn test_interpreter_for_select_index_expr_4() {
2880        let expr = r#"
2881              let list: list<u8> = [2, 5, 4];
2882              let x: u8 = 0;
2883              let y: u8 = 2;
2884              list[x..=y]
2885              "#;
2886
2887        let expr = Expr::from_text(expr).unwrap();
2888
2889        let compiled = compiler::compile(expr, &vec![]).unwrap();
2890
2891        let mut interpreter = Interpreter::default();
2892        let result = interpreter.run(compiled.byte_code).await.unwrap();
2893
2894        let expected = ValueAndType::new(
2895            Value::List(vec![Value::U8(2), Value::U8(5), Value::U8(4)]),
2896            list(u8()),
2897        );
2898
2899        assert_eq!(result.get_val().unwrap(), expected);
2900    }
2901
2902    #[test]
2903    async fn test_interpreter_for_select_index_expr_5() {
2904        let expr = r#"
2905              let list: list<u8> = [2, 5, 4];
2906              let x: u8 = 0;
2907              let y: u8 = 2;
2908              let x1: u8 = 1;
2909              let result = list[x..=y];
2910              for i in result[x1..=y] {
2911                yield i;
2912              }
2913              "#;
2914
2915        let expr = Expr::from_text(expr).unwrap();
2916
2917        let compiled = compiler::compile(expr, &vec![]).unwrap();
2918
2919        let mut interpreter = Interpreter::default();
2920        let result = interpreter.run(compiled.byte_code).await.unwrap();
2921
2922        let expected = ValueAndType::new(Value::List(vec![Value::U8(5), Value::U8(4)]), list(u8()));
2923
2924        assert_eq!(result.get_val().unwrap(), expected);
2925    }
2926
2927    #[test]
2928    async fn test_interpreter_for_select_index_expr_6() {
2929        let expr = r#"
2930              let list: list<u8> = [2, 5, 4, 6];
2931              let x: u8 = 0;
2932              let y: u8 = 2;
2933              let result = list[x..y];
2934              for i in result[x..y] {
2935                yield i;
2936              }
2937              "#;
2938
2939        let expr = Expr::from_text(expr).unwrap();
2940
2941        let compiled = compiler::compile(expr, &vec![]).unwrap();
2942
2943        let mut interpreter = Interpreter::default();
2944        let result = interpreter.run(compiled.byte_code).await.unwrap();
2945
2946        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2947
2948        assert_eq!(result.get_val().unwrap(), expected);
2949    }
2950
2951    #[test]
2952    async fn test_interpreter_for_select_index_expr_7() {
2953        let expr = r#"
2954              let list: list<u8> = [2, 5, 4, 6];
2955              let x: u8 = 0;
2956              let result = list[x..];
2957              for i in result[x..] {
2958                yield i;
2959              }
2960              "#;
2961
2962        let expr = Expr::from_text(expr).unwrap();
2963
2964        let compiled = compiler::compile(expr, &vec![]).unwrap();
2965
2966        let mut interpreter = Interpreter::default();
2967        let result = interpreter.run(compiled.byte_code).await.unwrap();
2968
2969        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2970
2971        assert_eq!(result.get_val().unwrap(), expected);
2972    }
2973
2974    #[test]
2975    async fn test_interpreter_for_select_index_expr_8() {
2976        let expr = r#"
2977              let list: list<u8> = [2, 5, 4, 6];
2978              let result = list[0..2];
2979              for i in result[0..2] {
2980                yield i;
2981              }
2982              "#;
2983
2984        let expr = Expr::from_text(expr).unwrap();
2985
2986        let compiled = compiler::compile(expr, &vec![]).unwrap();
2987
2988        let mut interpreter = Interpreter::default();
2989        let result = interpreter.run(compiled.byte_code).await.unwrap();
2990
2991        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2992
2993        assert_eq!(result.get_val().unwrap(), expected);
2994    }
2995
2996    // Simulating the behaviour in languages like rust
2997    // Emitting the description of the range than the evaluated range
2998    // Description given out as ValueAndType::Record
2999    #[test]
3000    async fn test_interpreter_range_returns_1() {
3001        let expr = r#"
3002              let x = 1..;
3003              x
3004              "#;
3005
3006        let expr = Expr::from_text(expr).unwrap();
3007
3008        let compiled = compiler::compile(expr, &vec![]).unwrap();
3009
3010        let mut interpreter = Interpreter::default();
3011        let result = interpreter.run(compiled.byte_code).await.unwrap();
3012
3013        let expected = ValueAndType::new(
3014            Value::Record(vec![
3015                Value::U64(1),
3016                Value::Bool(false), // non inclusive
3017            ]),
3018            record(vec![
3019                field("from", option(u64())),
3020                field("inclusive", bool()),
3021            ]),
3022        );
3023
3024        assert_eq!(result.get_val().unwrap(), expected);
3025    }
3026
3027    #[test]
3028    async fn test_interpreter_range_returns_2() {
3029        let expr = r#"
3030              let x = 1..2;
3031              x
3032              "#;
3033
3034        let expr = Expr::from_text(expr).unwrap();
3035
3036        let compiled = compiler::compile(expr, &vec![]).unwrap();
3037
3038        let mut interpreter = Interpreter::default();
3039        let result = interpreter.run(compiled.byte_code).await.unwrap();
3040
3041        let expected = ValueAndType::new(
3042            Value::Record(vec![
3043                Value::U64(1),
3044                Value::U64(2),
3045                Value::Bool(false), // non inclusive
3046            ]),
3047            record(vec![
3048                field("from", option(u64())),
3049                field("to", option(u64())),
3050                field("inclusive", bool()),
3051            ]),
3052        );
3053
3054        assert_eq!(result.get_val().unwrap(), expected);
3055    }
3056
3057    #[test]
3058    async fn test_interpreter_range_returns_3() {
3059        let expr = r#"
3060              let x = 1..=10;
3061              x
3062              "#;
3063
3064        let expr = Expr::from_text(expr).unwrap();
3065
3066        let compiled = compiler::compile(expr, &vec![]).unwrap();
3067
3068        let mut interpreter = Interpreter::default();
3069        let result = interpreter.run(compiled.byte_code).await.unwrap();
3070
3071        let expected = ValueAndType::new(
3072            Value::Record(vec![
3073                Value::U64(1),
3074                Value::U64(10),
3075                Value::Bool(true), // inclusive
3076            ]),
3077            record(vec![
3078                field("from", option(u64())),
3079                field("to", option(u64())),
3080                field("inclusive", bool()),
3081            ]),
3082        );
3083
3084        assert_eq!(result.get_val().unwrap(), expected);
3085    }
3086
3087    #[test]
3088    async fn test_interpreter_range_returns_4() {
3089        let expr = r#"
3090              let x = 1:u64;
3091              let y = x;
3092              let range = x..=y;
3093              let range2 = x..;
3094              let range3 = x..y;
3095              range;
3096              range2;
3097              range3
3098              "#;
3099
3100        let expr = Expr::from_text(expr).unwrap();
3101
3102        let compiled = compiler::compile(expr, &vec![]).unwrap();
3103
3104        let mut interpreter = Interpreter::default();
3105        let result = interpreter.run(compiled.byte_code).await.unwrap();
3106
3107        let expected = ValueAndType::new(
3108            Value::Record(vec![Value::U64(1), Value::U64(1), Value::Bool(false)]),
3109            record(vec![
3110                field("from", option(u64())),
3111                field("to", option(u64())),
3112                field("inclusive", bool()),
3113            ]),
3114        );
3115
3116        assert_eq!(result.get_val().unwrap(), expected);
3117    }
3118
3119    #[test]
3120    async fn test_interpreter_range_returns_5() {
3121        let expr = r#"
3122              let y = 1:u64 + 10: u64;
3123              1..y
3124              "#;
3125
3126        let expr = Expr::from_text(expr).unwrap();
3127
3128        let compiled = compiler::compile(expr, &vec![]).unwrap();
3129
3130        let mut interpreter = Interpreter::default();
3131        let result = interpreter.run(compiled.byte_code).await.unwrap();
3132
3133        let expected = ValueAndType::new(
3134            Value::Record(vec![Value::U64(1), Value::U64(11), Value::Bool(false)]),
3135            record(vec![
3136                field("from", option(u64())),
3137                field("to", option(u64())),
3138                field("inclusive", bool()),
3139            ]),
3140        );
3141
3142        assert_eq!(result.get_val().unwrap(), expected);
3143    }
3144
3145    #[test]
3146    async fn test_interpreter_range_with_comprehension_1() {
3147        let expr = r#"
3148              let range = 1..=5;
3149              for i in range {
3150                yield i;
3151              }
3152
3153              "#;
3154
3155        let expr = Expr::from_text(expr).unwrap();
3156
3157        let compiled = compiler::compile(expr, &vec![]).unwrap();
3158
3159        let mut interpreter = Interpreter::default();
3160        let result = interpreter.run(compiled.byte_code).await.unwrap();
3161
3162        let expected = ValueAndType::new(
3163            Value::List(vec![
3164                Value::U64(1),
3165                Value::U64(2),
3166                Value::U64(3),
3167                Value::U64(4),
3168                Value::U64(5),
3169            ]),
3170            list(u64()),
3171        );
3172
3173        assert_eq!(result.get_val().unwrap(), expected);
3174    }
3175
3176    #[test]
3177    async fn test_interpreter_range_with_comprehension_2() {
3178        let expr = r#"
3179              let range = 1..5;
3180              for i in range {
3181                yield i;
3182              }
3183
3184              "#;
3185
3186        let expr = Expr::from_text(expr).unwrap();
3187
3188        let compiled = compiler::compile(expr, &vec![]).unwrap();
3189
3190        let mut interpreter = Interpreter::default();
3191        let result = interpreter.run(compiled.byte_code).await.unwrap();
3192
3193        let expected = ValueAndType::new(
3194            Value::List(vec![
3195                Value::U64(1),
3196                Value::U64(2),
3197                Value::U64(3),
3198                Value::U64(4),
3199            ]),
3200            list(u64()),
3201        );
3202
3203        assert_eq!(result.get_val().unwrap(), expected);
3204    }
3205
3206    #[test]
3207    async fn test_interpreter_range_with_comprehension_3() {
3208        // infinite computation will respond with an error - than a stack overflow
3209        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3210        let expr = r#"
3211              let range = 1:u64..;
3212              for i in range {
3213                yield i;
3214              }
3215
3216              "#;
3217
3218        let expr = Expr::from_text(expr).unwrap();
3219
3220        let compiled = compiler::compile(expr, &vec![]).unwrap();
3221
3222        let mut interpreter = Interpreter::default();
3223        let result = interpreter.run(compiled.byte_code).await;
3224        assert!(result.is_err());
3225    }
3226
3227    #[test]
3228    async fn test_interpreter_range_with_list_reduce_1() {
3229        // infinite computation will respond with an error - than a stack overflow
3230        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3231        let expr = r#"
3232                let initial: u8 = 1;
3233                let final: u8 = 5;
3234                let x = initial..final;
3235
3236                reduce z, a in x from 0u8 {
3237                  yield z + a;
3238                }
3239
3240              "#;
3241
3242        let expr = Expr::from_text(expr).unwrap();
3243
3244        let compiled = compiler::compile(expr, &vec![]).unwrap();
3245
3246        let mut interpreter = Interpreter::default();
3247        let result = interpreter.run(compiled.byte_code).await.unwrap();
3248
3249        let expected = ValueAndType::new(Value::U8(10), u8());
3250
3251        assert_eq!(result.get_val().unwrap(), expected);
3252    }
3253
3254    #[test]
3255    async fn test_interpreter_ephemeral_worker_0() {
3256        let expr = r#"
3257              let x = instance();
3258              let result = x.foo("bar");
3259              result
3260            "#;
3261        let expr = Expr::from_text(expr).unwrap();
3262
3263        let component_metadata = test_utils::get_metadata();
3264
3265        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3266
3267        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3268
3269        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3270
3271        let expected_val = test_utils::parse_function_details(
3272            r#"
3273              {
3274                 worker-name: none,
3275                 function-name: "amazon:shopping-cart/api1.{foo}",
3276                 args0: "bar"
3277              }
3278            "#,
3279        );
3280
3281        assert_eq!(result.get_val().unwrap(), expected_val);
3282    }
3283
3284    #[test]
3285    async fn test_interpreter_ephemeral_worker_1() {
3286        let expr = r#"
3287              let x = instance();
3288              x
3289            "#;
3290        let expr = Expr::from_text(expr).unwrap();
3291
3292        let component_metadata = test_utils::get_metadata();
3293
3294        let compiled = compiler::compile(expr, &component_metadata);
3295
3296        assert!(compiled.is_err());
3297    }
3298
3299    #[test]
3300    async fn test_interpreter_ephemeral_worker_2() {
3301        let expr = r#"
3302             instance
3303            "#;
3304        let expr = Expr::from_text(expr).unwrap();
3305
3306        let component_metadata = test_utils::get_metadata();
3307
3308        let compiled = compiler::compile(expr, &component_metadata);
3309
3310        assert!(compiled.is_err());
3311    }
3312
3313    #[test]
3314    async fn test_interpreter_ephemeral_worker_3() {
3315        let expr = r#"
3316              instance()
3317            "#;
3318        let expr = Expr::from_text(expr).unwrap();
3319
3320        let component_metadata = test_utils::get_metadata();
3321
3322        let compiled = compiler::compile(expr, &component_metadata);
3323
3324        assert!(compiled.is_err());
3325    }
3326
3327    #[test]
3328    async fn test_interpreter_ephemeral_worker_4() {
3329        let expr = r#"
3330              instance().foo("bar")
3331            "#;
3332        let expr = Expr::from_text(expr).unwrap();
3333
3334        let component_metadata = test_utils::get_metadata();
3335
3336        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3337
3338        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3339
3340        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3341
3342        let expected_val = test_utils::parse_function_details(
3343            r#"
3344              {
3345                 worker-name: none,
3346                 function-name: "amazon:shopping-cart/api1.{foo}",
3347                 args0: "bar"
3348              }
3349            "#,
3350        );
3351
3352        assert_eq!(result.get_val().unwrap(), expected_val);
3353    }
3354
3355    #[test]
3356    async fn test_interpreter_ephemeral_worker_5() {
3357        let expr = r#"
3358              let result = instance.foo("bar");
3359              result
3360            "#;
3361        let expr = Expr::from_text(expr).unwrap();
3362        let component_metadata = test_utils::get_metadata();
3363
3364        let compiled = compiler::compile(expr, &component_metadata)
3365            .unwrap_err()
3366            .to_string();
3367
3368        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());
3369    }
3370
3371    #[test]
3372    async fn test_interpreter_ephemeral_worker_6() {
3373        let expr = r#"
3374                let x = instance();
3375                let result = x.bar("bar");
3376                result
3377            "#;
3378        let expr = Expr::from_text(expr).unwrap();
3379        let component_metadata = test_utils::get_metadata();
3380
3381        let compilation_error = compiler::compile(expr, &component_metadata)
3382            .unwrap_err()
3383            .to_string();
3384
3385        assert_eq!(
3386            compilation_error,
3387            "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()
3388        );
3389    }
3390
3391    #[test]
3392    async fn test_interpreter_ephemeral_worker_7() {
3393        let expr = r#"
3394                let worker = instance();
3395                let invokes: list<u8> = [1, 2, 3, 4];
3396
3397                for i in invokes {
3398                    yield worker.qux[wasi:clocks]("bar");
3399                };
3400
3401                "success"
3402            "#;
3403        let expr = Expr::from_text(expr).unwrap();
3404        let component_metadata = test_utils::get_metadata();
3405
3406        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3407
3408        let mut rib_interpreter =
3409            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3410
3411        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3412
3413        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3414    }
3415
3416    /// Durable worker
3417    #[test]
3418    async fn test_interpreter_durable_worker_0() {
3419        let expr = r#"
3420                let worker = instance("my-worker");
3421                let result = worker.foo("bar");
3422                result
3423            "#;
3424        let expr = Expr::from_text(expr).unwrap();
3425        let component_metadata = test_utils::get_metadata();
3426
3427        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3428
3429        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3430
3431        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3432
3433        let expected_val = test_utils::parse_function_details(
3434            r#"
3435              {
3436                 worker-name: some("my-worker"),
3437                 function-name: "amazon:shopping-cart/api1.{foo}",
3438                 args0: "bar"
3439              }
3440            "#,
3441        );
3442
3443        assert_eq!(result.get_val().unwrap(), expected_val);
3444    }
3445
3446    #[test]
3447    async fn test_interpreter_durable_worker_1() {
3448        let expr = r#"
3449                instance("my-worker").foo("bar")
3450            "#;
3451        let expr = Expr::from_text(expr).unwrap();
3452        let component_metadata = test_utils::get_metadata();
3453
3454        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3455
3456        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3457
3458        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3459
3460        let expected_val = test_utils::parse_function_details(
3461            r#"
3462              {
3463                 worker-name: some("my-worker"),
3464                 function-name: "amazon:shopping-cart/api1.{foo}",
3465                 args0: "bar"
3466              }
3467            "#,
3468        );
3469
3470        assert_eq!(result.get_val().unwrap(), expected_val);
3471    }
3472
3473    #[test]
3474    async fn test_interpreter_durable_worker_2() {
3475        let expr = r#"
3476                let result = instance("my-worker").foo("bar");
3477                result
3478            "#;
3479        let expr = Expr::from_text(expr).unwrap();
3480        let component_metadata = test_utils::get_metadata();
3481
3482        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3483
3484        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3485
3486        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3487
3488        let expected_val = test_utils::parse_function_details(
3489            r#"
3490              {
3491                 worker-name: some("my-worker"),
3492                 function-name: "amazon:shopping-cart/api1.{foo}",
3493                 args0: "bar"
3494              }
3495            "#,
3496        );
3497
3498        assert_eq!(result.get_val().unwrap(), expected_val);
3499    }
3500
3501    #[test]
3502    async fn test_interpreter_durable_worker_3() {
3503        let expr = r#"
3504                let my_worker = instance("my-worker");
3505                let result = my_worker.foo[api1]("bar");
3506                result
3507            "#;
3508        let expr = Expr::from_text(expr).unwrap();
3509        let component_metadata = test_utils::get_metadata();
3510
3511        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3512
3513        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3514
3515        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3516
3517        let expected_val = test_utils::parse_function_details(
3518            r#"
3519              {
3520                 worker-name: some("my-worker"),
3521                 function-name: "amazon:shopping-cart/api1.{foo}",
3522                 args0: "bar"
3523              }
3524            "#,
3525        );
3526
3527        assert_eq!(result.get_val().unwrap(), expected_val);
3528    }
3529
3530    #[test]
3531    async fn test_interpreter_durable_worker_4() {
3532        let expr = r#"
3533                let worker = instance("my-worker");
3534                let result = worker.bar("bar");
3535                result
3536            "#;
3537        let expr = Expr::from_text(expr).unwrap();
3538        let component_metadata = test_utils::get_metadata();
3539
3540        let compilation_error = compiler::compile(expr, &component_metadata)
3541            .unwrap_err()
3542            .to_string();
3543
3544        assert_eq!(
3545            compilation_error,
3546            "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()
3547        );
3548    }
3549
3550    #[test]
3551    async fn test_interpreter_durable_worker_5() {
3552        let expr = r#"
3553                let worker = instance("my-worker");
3554                let result = worker.bar[api1]("bar");
3555                result
3556            "#;
3557        let expr = Expr::from_text(expr).unwrap();
3558        let component_metadata = test_utils::get_metadata();
3559
3560        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3561
3562        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3563
3564        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3565
3566        let expected_val = test_utils::parse_function_details(
3567            r#"
3568              {
3569                 worker-name: some("my-worker"),
3570                 function-name: "amazon:shopping-cart/api1.{bar}",
3571                 args0: "bar"
3572              }
3573            "#,
3574        );
3575
3576        assert_eq!(result.get_val().unwrap(), expected_val);
3577    }
3578
3579    #[test]
3580    async fn test_interpreter_durable_worker_6() {
3581        let expr = r#"
3582                let worker = instance("my-worker");
3583                let result = worker.bar[api2]("bar");
3584                result
3585            "#;
3586        let expr = Expr::from_text(expr).unwrap();
3587        let component_metadata = test_utils::get_metadata();
3588
3589        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3590
3591        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3592
3593        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3594
3595        let expected_val = test_utils::parse_function_details(
3596            r#"
3597              {
3598                 worker-name: some("my-worker"),
3599                 function-name: "amazon:shopping-cart/api2.{bar}",
3600                 args0: "bar"
3601              }
3602            "#,
3603        );
3604
3605        assert_eq!(result.get_val().unwrap(), expected_val);
3606    }
3607
3608    #[test]
3609    async fn test_interpreter_durable_worker_7() {
3610        let expr = r#"
3611                let worker = instance("my-worker");
3612                let result = worker.baz("bar");
3613                result
3614            "#;
3615        let expr = Expr::from_text(expr).unwrap();
3616        let component_metadata = test_utils::get_metadata();
3617
3618        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3619
3620        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3621
3622        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3623
3624        let expected_val = test_utils::parse_function_details(
3625            r#"
3626              {
3627                 worker-name: some("my-worker"),
3628                 function-name: "wasi:clocks/monotonic-clock.{baz}",
3629                 args0: "bar"
3630              }
3631            "#,
3632        );
3633
3634        assert_eq!(result.get_val().unwrap(), expected_val);
3635    }
3636
3637    #[test]
3638    async fn test_interpreter_durable_worker_8() {
3639        let expr = r#"
3640                let worker = instance("my-worker");
3641                let result = worker.qux("bar");
3642                result
3643            "#;
3644        let expr = Expr::from_text(expr).unwrap();
3645        let component_metadata = test_utils::get_metadata();
3646
3647        let compiled = compiler::compile(expr, &component_metadata)
3648            .unwrap_err()
3649            .to_string();
3650
3651        assert_eq!(
3652            compiled,
3653            "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()
3654        );
3655    }
3656
3657    #[test]
3658    async fn test_interpreter_durable_worker_9() {
3659        let expr = r#"
3660                let worker = instance("my-worker");
3661                let result = worker.qux[amazon:shopping-cart]("bar");
3662                result
3663            "#;
3664        let expr = Expr::from_text(expr).unwrap();
3665        let component_metadata = test_utils::get_metadata();
3666
3667        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3668
3669        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3670
3671        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3672
3673        let expected_val = test_utils::parse_function_details(
3674            r#"
3675              {
3676                 worker-name: some("my-worker"),
3677                 function-name: "amazon:shopping-cart/api1.{qux}",
3678                 args0: "bar"
3679              }
3680            "#,
3681        );
3682
3683        assert_eq!(result.get_val().unwrap(), expected_val);
3684    }
3685
3686    #[test]
3687    async fn test_interpreter_durable_worker_10() {
3688        let expr = r#"
3689                let worker = instance("my-worker");
3690                let result = worker.qux[wasi:clocks]("bar");
3691                result
3692            "#;
3693        let expr = Expr::from_text(expr).unwrap();
3694        let component_metadata = test_utils::get_metadata();
3695
3696        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3697
3698        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3699
3700        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3701
3702        let expected_val = test_utils::parse_function_details(
3703            r#"
3704              {
3705                 worker-name: some("my-worker"),
3706                 function-name: "wasi:clocks/monotonic-clock.{qux}",
3707                 args0: "bar"
3708              }
3709            "#,
3710        );
3711
3712        assert_eq!(result.get_val().unwrap(), expected_val);
3713    }
3714
3715    #[test]
3716    async fn test_interpreter_durable_worker_11() {
3717        let expr = r#"
3718                let worker = instance("my-worker");
3719                let invokes: list<u8> = [1, 2, 3, 4];
3720
3721                for i in invokes {
3722                    yield worker.qux[wasi:clocks]("bar");
3723                };
3724
3725                "success"
3726            "#;
3727        let expr = Expr::from_text(expr).unwrap();
3728        let component_metadata = test_utils::get_metadata();
3729
3730        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3731
3732        let mut rib_interpreter =
3733            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3734
3735        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3736
3737        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3738    }
3739
3740    #[test]
3741    async fn test_interpreter_durable_worker_with_resource_0() {
3742        let expr = r#"
3743                let worker = instance("my-worker");
3744                worker.cart[golem:it]("bar")
3745            "#;
3746        let expr = Expr::from_text(expr).unwrap();
3747        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3748
3749        let compiled = compiler::compile(expr, &component_metadata)
3750            .unwrap_err()
3751            .to_string();
3752
3753        let expected = r#"
3754            error in the following rib found at line 3, column 17
3755            `cart("bar")`
3756            cause: program is invalid as it returns a resource constructor
3757            "#;
3758
3759        assert_eq!(compiled, strip_spaces(expected));
3760    }
3761
3762    // This resource construction is a Noop, and compiler can give warnings
3763    // once we support warnings in the compiler
3764    #[test]
3765    async fn test_interpreter_durable_worker_with_resource_1() {
3766        let expr = r#"
3767                let worker = instance("my-worker");
3768                worker.cart[golem:it]("bar");
3769                "success"
3770            "#;
3771        let expr = Expr::from_text(expr).unwrap();
3772        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3773
3774        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3775
3776        let mut rib_interpreter =
3777            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3778
3779        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3780
3781        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3782    }
3783
3784    #[test]
3785    async fn test_interpreter_durable_worker_with_resource_2() {
3786        let expr = r#"
3787                let worker = instance("my-worker");
3788                let cart = worker.cart[golem:it]("bar");
3789                let result = cart.add-item({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3790                result
3791            "#;
3792        let expr = Expr::from_text(expr).unwrap();
3793        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3794
3795        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3796
3797        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3798
3799        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3800
3801        let analysed_type = record(vec![
3802            field("worker-name", option(str())),
3803            field("function-name", str()),
3804            field(
3805                "args0",
3806                record(vec![
3807                    field("product-id", str()),
3808                    field("name", str()),
3809                    field("price", f32()),
3810                    field("quantity", u32()),
3811                ]),
3812            ),
3813        ]);
3814
3815        let expected_val = get_value_and_type(
3816            &analysed_type,
3817            r#"
3818              {
3819                 worker-name: some("my-worker"),
3820                 function-name: "golem:it/api.{cart(\"bar\").add-item}",
3821                 args0: {product-id: "mac", name: "macbook", price: 1.0, quantity: 1}
3822              }
3823            "#,
3824        );
3825
3826        assert_eq!(result.get_val().unwrap(), expected_val);
3827    }
3828
3829    #[test]
3830    async fn test_interpreter_durable_worker_with_resource_3() {
3831        let expr = r#"
3832                let worker = instance("my-worker");
3833                let cart = worker.cart[golem:it]("bar");
3834                cart.add-items({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3835                "success"
3836            "#;
3837        let expr = Expr::from_text(expr).unwrap();
3838        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3839
3840        let compiled = compiler::compile(expr, &component_metadata)
3841            .unwrap_err()
3842            .to_string();
3843
3844        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());
3845    }
3846
3847    #[test]
3848    async fn test_interpreter_durable_worker_with_resource_4() {
3849        let expr = r#"
3850                let worker = instance("my-worker");
3851                let cart = worker.carts[golem:it]("bar");
3852                cart.add-item({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3853                "success"
3854            "#;
3855        let expr = Expr::from_text(expr).unwrap();
3856        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3857
3858        let compiled = compiler::compile(expr, &component_metadata)
3859            .unwrap_err()
3860            .to_string();
3861
3862        assert_eq!(
3863            compiled,
3864            "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()
3865        );
3866    }
3867
3868    #[test]
3869    async fn test_interpreter_durable_worker_with_resource_5() {
3870        // Ephemeral
3871        let expr = r#"
3872                let worker = instance();
3873                let cart = worker.cart[golem:it]("bar");
3874                cart.add-item({product-id: "mac", name: "macbook", quantity: 1, price: 1});
3875                "success"
3876            "#;
3877        let expr = Expr::from_text(expr).unwrap();
3878        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3879
3880        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3881
3882        let mut rib_interpreter =
3883            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3884
3885        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3886
3887        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3888    }
3889
3890    #[test]
3891    async fn test_interpreter_durable_worker_with_resource_6() {
3892        // Ephemeral
3893        let expr = r#"
3894                let worker = instance();
3895                let cart = worker.cart[golem:it]("bar");
3896                cart.add-item({product-id: "mac", name: 1, quantity: 1, price: 1});
3897                "success"
3898            "#;
3899        let expr = Expr::from_text(expr).unwrap();
3900        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3901
3902        let error_message = compiler::compile(expr, &component_metadata)
3903            .unwrap_err()
3904            .to_string();
3905
3906        let expected = r#"
3907            error in the following rib found at line 4, column 31
3908            `{product-id: "mac", name: 1, quantity: 1, price: 1}`
3909            found within:
3910            `golem:it/api.{cart("bar").add-item}({product-id: "mac", name: 1, quantity: 1, price: 1})`
3911            cause: type mismatch at path: `name`. expected string
3912            invalid argument to the function `golem:it/api.{cart("bar").add-item}`
3913            "#;
3914
3915        assert_eq!(error_message, strip_spaces(expected));
3916    }
3917
3918    #[test]
3919    async fn test_interpreter_durable_worker_with_resource_7() {
3920        let expr = r#"
3921                let worker = instance("my-worker");
3922                let cart = worker.cart("bar");
3923                cart.add-item({product-id: "mac", name: "apple", price: 1, quantity: 1});
3924                "success"
3925            "#;
3926        let expr = Expr::from_text(expr).unwrap();
3927        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3928
3929        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3930
3931        let mut rib_interpreter =
3932            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3933
3934        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3935
3936        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3937    }
3938
3939    #[test]
3940    async fn test_interpreter_durable_worker_with_resource_8() {
3941        let expr = r#"
3942                let worker = instance("my-worker");
3943                let a = "mac";
3944                let b = "apple";
3945                let c = 1;
3946                let d = 1;
3947                let cart = worker.cart("bar");
3948                cart.add-item({product-id: a, name: b, quantity: c, price: d});
3949                "success"
3950            "#;
3951        let expr = Expr::from_text(expr).unwrap();
3952        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3953
3954        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3955
3956        let mut rib_interpreter =
3957            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3958
3959        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3960
3961        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3962    }
3963
3964    #[test]
3965    async fn test_interpreter_durable_worker_with_resource_9() {
3966        let expr = r#"
3967                let worker = instance("my-worker");
3968                let a = "mac";
3969                let b = "apple";
3970                let c = 1;
3971                let d = 1;
3972                let cart = worker.cart("bar");
3973                cart.add-item({product-id: a, name: b, quantity: c, price: d});
3974                cart.remove-item(a);
3975                cart.update-item-quantity(a, 2);
3976                let result = cart.get-cart-contents();
3977                cart.drop();
3978                result
3979            "#;
3980        let expr = Expr::from_text(expr).unwrap();
3981        let component_metadata = test_utils::get_metadata_with_resource_with_params();
3982
3983        let compiled = compiler::compile(expr, &component_metadata).unwrap();
3984
3985        let mut rib_interpreter =
3986            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3987
3988        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3989
3990        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3991    }
3992
3993    #[test]
3994    async fn test_interpreter_durable_worker_with_resource_10() {
3995        let expr = r#"
3996                let my_worker = "my-worker";
3997                let worker = instance(my_worker);
3998                let a = "mac";
3999                let b = "apple";
4000                let c = 1;
4001                let d = 1;
4002                let cart = worker.cart("bar");
4003                cart.add-item({product-id: a, name: b, price: d, quantity: c});
4004                cart.remove-item(a);
4005                cart.update-item-quantity(a, 2);
4006                let result = cart.get-cart-contents();
4007                cart.drop();
4008                result
4009            "#;
4010        let expr = Expr::from_text(expr).unwrap();
4011        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4012
4013        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4014
4015        let mut rib_interpreter =
4016            test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
4017
4018        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4019
4020        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4021    }
4022
4023    #[test]
4024    async fn test_interpreter_durable_worker_with_resource_11() {
4025        let expr = r#"
4026                let worker = instance(request.path.user-id: string);
4027                let result = worker.qux[amazon:shopping-cart]("bar");
4028                result
4029            "#;
4030        let expr = Expr::from_text(expr).unwrap();
4031        let component_metadata = test_utils::get_metadata();
4032
4033        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4034
4035        let mut input = HashMap::new();
4036
4037        // Passing request data as input to interpreter
4038        let rib_input_key = "request";
4039        let rib_input_value = ValueAndType::new(
4040            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4041            record(vec![field("path", record(vec![field("user-id", str())]))]),
4042        );
4043
4044        input.insert(rib_input_key.to_string(), rib_input_value);
4045
4046        let rib_input = RibInput::new(input);
4047
4048        let mut rib_interpreter = test_utils::interpreter_static_response(
4049            &"success".into_value_and_type(),
4050            Some(rib_input),
4051        );
4052
4053        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4054
4055        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4056    }
4057
4058    #[test]
4059    async fn test_interpreter_durable_worker_with_resource_12() {
4060        let expr = r#"
4061                let user_id1: string = request.path.user-id;
4062                let user_id2: string = request.path.user-id;
4063                let worker1 = instance(user_id1);
4064                let result1 = worker1.qux[amazon:shopping-cart]("bar");
4065                let worker2 = instance(user_id2);
4066                let result2 = worker2.qux[amazon:shopping-cart]("bar");
4067                user_id2
4068            "#;
4069        let expr = Expr::from_text(expr).unwrap();
4070        let component_metadata = test_utils::get_metadata();
4071
4072        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4073
4074        let mut input = HashMap::new();
4075
4076        let rib_input_key = "request";
4077        let rib_input_value = ValueAndType::new(
4078            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4079            record(vec![field("path", record(vec![field("user-id", str())]))]),
4080        );
4081
4082        input.insert(rib_input_key.to_string(), rib_input_value);
4083
4084        let rib_input = RibInput::new(input);
4085
4086        let mut rib_interpreter = test_utils::interpreter_static_response(
4087            &"success".into_value_and_type(),
4088            Some(rib_input),
4089        );
4090
4091        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4092
4093        assert_eq!(result.get_val().unwrap(), "user".into_value_and_type());
4094    }
4095
4096    #[test]
4097    async fn test_interpreter_durable_worker_with_resource_13() {
4098        let expr = r#"
4099                let worker1 = instance("foo");
4100                let result = worker.qux[amazon:shopping-cart]("bar");
4101                "success"
4102            "#;
4103        let expr = Expr::from_text(expr).unwrap();
4104        let component_metadata = test_utils::get_metadata();
4105
4106        let error = compiler::compile(expr, &component_metadata)
4107            .unwrap_err()
4108            .to_string();
4109
4110        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");
4111    }
4112
4113    #[test]
4114    async fn test_interpreter_durable_worker_with_resource_14() {
4115        let expr = r#"
4116                let worker = instance(1: u32);
4117                let result = worker.qux[amazon:shopping-cart]("bar");
4118                "success"
4119            "#;
4120        let expr = Expr::from_text(expr).unwrap();
4121        let component_metadata = test_utils::get_metadata();
4122
4123        let error = compiler::compile(expr, &component_metadata)
4124            .unwrap_err()
4125            .to_string();
4126
4127        let expected = r#"
4128            error in the following rib found at line 2, column 39
4129            `1: u32`
4130            cause: expected string, found u32
4131            "#;
4132
4133        assert_eq!(error, strip_spaces(expected));
4134    }
4135
4136    #[test]
4137    async fn test_interpreter_durable_worker_with_resource_15() {
4138        let expr = r#"
4139                let worker = instance("my-worker-name");
4140                let result = worker.qux[amazon:shopping-cart]("param1");
4141                result
4142            "#;
4143        let expr = Expr::from_text(expr).unwrap();
4144        let component_metadata = test_utils::get_metadata();
4145
4146        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4147
4148        let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
4149
4150        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4151
4152        let result_val = result.get_val().unwrap();
4153
4154        let expected_val = test_utils::parse_function_details(
4155            r#"
4156              {
4157                 worker-name: some("my-worker-name"),
4158                 function-name: "amazon:shopping-cart/api1.{qux}",
4159                 args0: "param1"
4160              }
4161            "#,
4162        );
4163
4164        assert_eq!(result_val, expected_val);
4165    }
4166
4167    #[test]
4168    async fn test_interpreter_durable_worker_with_resource_16() {
4169        let expr = r#"
4170                let x = request.path.user-id;
4171                let worker = instance(x);
4172                let cart = worker.cart("bar");
4173                let result = cart.get-cart-contents();
4174                result
4175            "#;
4176        let expr = Expr::from_text(expr).unwrap();
4177        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4178
4179        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4180
4181        let mut input = HashMap::new();
4182
4183        let rib_input_key = "request";
4184        let rib_input_value = ValueAndType::new(
4185            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4186            record(vec![field("path", record(vec![field("user-id", str())]))]),
4187        );
4188
4189        input.insert(rib_input_key.to_string(), rib_input_value);
4190
4191        let rib_input = RibInput::new(input);
4192
4193        let mut rib_interpreter = test_utils::interpreter_worker_details_response(Some(rib_input));
4194
4195        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4196
4197        let result_val = result.get_val().unwrap();
4198
4199        let expected_analysed_type = record(vec![
4200            field("worker-name", option(str())),
4201            field("function-name", str()),
4202        ]);
4203
4204        let expected_val = parse_value_and_type(
4205            &expected_analysed_type,
4206            r#"
4207              {
4208                 worker-name: some("user"),
4209                 function-name: "golem:it/api.{cart(\"bar\").get-cart-contents}",
4210              }
4211            "#,
4212        )
4213        .unwrap();
4214
4215        assert_eq!(result_val, expected_val)
4216    }
4217
4218    #[test]
4219    async fn test_interpreter_durable_worker_with_resource_17() {
4220        let expr = r#"
4221                let x: string = request.path.user-id;
4222                let min: u8 = 1;
4223                let max: u8 = 3;
4224                let result = for i in min..=max {
4225                   let worker = instance("my-worker");
4226                   let cart = worker.cart("bar");
4227                   yield cart.get-cart-contents();
4228                };
4229                result
4230            "#;
4231        let expr = Expr::from_text(expr).unwrap();
4232        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4233
4234        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4235
4236        let mut input = HashMap::new();
4237
4238        let rib_input_key = "request";
4239        let rib_input_value = ValueAndType::new(
4240            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4241            record(vec![field("path", record(vec![field("user-id", str())]))]),
4242        );
4243
4244        input.insert(rib_input_key.to_string(), rib_input_value);
4245
4246        let rib_input = RibInput::new(input);
4247
4248        let mut rib_interpreter = test_utils::interpreter_worker_details_response(Some(rib_input));
4249
4250        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4251
4252        let result_val = result.get_val().unwrap().value;
4253
4254        let worker_name = Some("my-worker".to_string()).into_value();
4255        let function_name = "golem:it/api.{cart(\"bar\").get-cart-contents}"
4256            .to_string()
4257            .into_value();
4258
4259        let expected = Value::List(vec![
4260            Value::Record(vec![worker_name.clone(), function_name.clone()]),
4261            Value::Record(vec![worker_name.clone(), function_name.clone()]),
4262            Value::Record(vec![worker_name.clone(), function_name.clone()]),
4263        ]);
4264
4265        assert_eq!(result_val, expected);
4266    }
4267
4268    #[test]
4269    async fn test_interpreter_durable_worker_with_resource_18() {
4270        let expr = r#"
4271
4272            let initial = 1: u64;
4273            let final = 5: u64;
4274            let range = initial..final;
4275            let worker = instance("my-worker");
4276            let cart = worker.cart[golem:it]("bar");
4277
4278            for i in range {
4279                yield cart.add-item(request.body);
4280            };
4281
4282            "success"
4283        "#;
4284        let expr = Expr::from_text(expr).unwrap();
4285        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4286
4287        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4288
4289        let mut input = HashMap::new();
4290
4291        let rib_input_key = "request";
4292        let rib_input_value = ValueAndType::new(
4293            Value::Record(vec![Value::Record(vec![
4294                Value::String("mac-book".to_string()),
4295                Value::String("mac".to_string()),
4296                Value::U32(1),
4297                Value::F32(1.0),
4298            ])]),
4299            record(vec![field(
4300                "body",
4301                record(vec![
4302                    field("name", str()),
4303                    field("product-id", str()),
4304                    field("quantity", u32()),
4305                    field("price", f32()),
4306                ]),
4307            )]),
4308        );
4309
4310        input.insert(rib_input_key.to_string(), rib_input_value);
4311
4312        let rib_input = RibInput::new(input);
4313
4314        let mut rib_interpreter = test_utils::interpreter_static_response(
4315            &"success".into_value_and_type(),
4316            Some(rib_input),
4317        );
4318
4319        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4320
4321        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4322    }
4323
4324    #[test]
4325    async fn test_interpreter_durable_worker_with_resource_19() {
4326        let expr = r#"
4327
4328            let initial = 1: u64;
4329            let final = 5: u64;
4330            let range = initial..final;
4331
4332            for i in range {
4333                let worker = instance("my-worker");
4334                let cart = worker.cart[golem:it]("bar");
4335                yield cart.add-item(request.body);
4336            };
4337
4338            "success"
4339        "#;
4340        let expr = Expr::from_text(expr).unwrap();
4341        let component_metadata = test_utils::get_metadata_with_resource_with_params();
4342
4343        let compiled = compiler::compile(expr, &component_metadata).unwrap();
4344
4345        let mut input = HashMap::new();
4346
4347        let rib_input_key = "request";
4348        let rib_input_value = ValueAndType::new(
4349            Value::Record(vec![Value::Record(vec![
4350                Value::String("mac-book".to_string()),
4351                Value::String("mac".to_string()),
4352                Value::U32(1),
4353                Value::F32(1.0),
4354            ])]),
4355            record(vec![field(
4356                "body",
4357                record(vec![
4358                    field("name", str()),
4359                    field("product-id", str()),
4360                    field("quantity", u32()),
4361                    field("price", f32()),
4362                ]),
4363            )]),
4364        );
4365
4366        input.insert(rib_input_key.to_string(), rib_input_value);
4367
4368        let rib_input = RibInput::new(input);
4369
4370        let mut rib_interpreter = test_utils::interpreter_static_response(
4371            &"success".into_value_and_type(),
4372            Some(rib_input),
4373        );
4374
4375        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4376
4377        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4378    }
4379
4380    mod test_utils {
4381        use crate::interpreter::rib_interpreter::Interpreter;
4382        use crate::{
4383            EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, GetLiteralValue,
4384            RibFunctionInvoke, RibInput,
4385        };
4386        use async_trait::async_trait;
4387        use golem_wasm_ast::analysis::analysed_type::{
4388            case, f32, field, handle, list, option, r#enum, record, result, str, tuple, u32, u64,
4389            unit_case, variant,
4390        };
4391        use golem_wasm_ast::analysis::{
4392            AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedFunctionResult,
4393            AnalysedInstance, AnalysedResourceId, AnalysedResourceMode, AnalysedType,
4394        };
4395        use golem_wasm_rpc::{IntoValueAndType, Value, ValueAndType};
4396        use std::sync::Arc;
4397
4398        pub(crate) fn strip_spaces(input: &str) -> String {
4399            let lines = input.lines();
4400
4401            let first_line = lines
4402                .clone()
4403                .find(|line| !line.trim().is_empty())
4404                .unwrap_or("");
4405            let margin_width = first_line.chars().take_while(|c| c.is_whitespace()).count();
4406
4407            let result = lines
4408                .map(|line| {
4409                    if line.trim().is_empty() {
4410                        String::new()
4411                    } else {
4412                        line[margin_width..].to_string()
4413                    }
4414                })
4415                .collect::<Vec<String>>()
4416                .join("\n");
4417
4418            result.strip_prefix("\n").unwrap_or(&result).to_string()
4419        }
4420
4421        pub(crate) fn get_analysed_type_variant() -> AnalysedType {
4422            variant(vec![
4423                case("register-user", u64()),
4424                case("process-user", str()),
4425                unit_case("validate"),
4426            ])
4427        }
4428
4429        pub(crate) fn get_analysed_type_record() -> AnalysedType {
4430            record(vec![
4431                field(
4432                    "request",
4433                    record(vec![field("path", record(vec![field("user", str())]))]),
4434                ),
4435                field("y", str()),
4436            ])
4437        }
4438
4439        pub(crate) fn get_analysed_type_result() -> AnalysedType {
4440            result(u64(), str())
4441        }
4442
4443        pub(crate) fn get_analysed_type_enum() -> AnalysedType {
4444            r#enum(&["prod", "dev", "test"])
4445        }
4446
4447        pub(crate) fn get_analysed_typ_str() -> AnalysedType {
4448            str()
4449        }
4450
4451        pub(crate) fn get_analysed_typ_u64() -> AnalysedType {
4452            u64()
4453        }
4454
4455        pub(crate) fn get_analysed_type_tuple() -> AnalysedType {
4456            tuple(vec![
4457                get_analysed_typ_u64(),
4458                get_analysed_type_result(),
4459                get_analysed_typ_str(),
4460                get_analysed_type_record(),
4461                get_analysed_type_variant(),
4462                get_analysed_type_variant(),
4463                get_analysed_type_variant(),
4464                get_analysed_type_enum(),
4465                get_analysed_type_enum(),
4466                get_analysed_type_enum(),
4467            ])
4468        }
4469
4470        pub(crate) fn get_component_metadata(
4471            function_name: &str,
4472            input_types: Vec<AnalysedType>,
4473            output: Option<AnalysedType>,
4474        ) -> Vec<AnalysedExport> {
4475            let analysed_function_parameters = input_types
4476                .into_iter()
4477                .enumerate()
4478                .map(|(index, typ)| AnalysedFunctionParameter {
4479                    name: format!("param{}", index),
4480                    typ,
4481                })
4482                .collect();
4483
4484            let results = if let Some(output) = output {
4485                vec![AnalysedFunctionResult {
4486                    name: None,
4487                    typ: output,
4488                }]
4489            } else {
4490                // Representing Unit
4491                vec![]
4492            };
4493
4494            vec![AnalysedExport::Function(AnalysedFunction {
4495                name: function_name.to_string(),
4496                parameters: analysed_function_parameters,
4497                results,
4498            })]
4499        }
4500
4501        pub(crate) fn get_metadata_with_resource_with_params() -> Vec<AnalysedExport> {
4502            get_metadata_with_resource(vec![AnalysedFunctionParameter {
4503                name: "user-id".to_string(),
4504                typ: str(),
4505            }])
4506        }
4507
4508        pub(crate) fn get_metadata_with_resource_without_params() -> Vec<AnalysedExport> {
4509            get_metadata_with_resource(vec![])
4510        }
4511
4512        pub(crate) fn get_metadata() -> Vec<AnalysedExport> {
4513            // Exist in only amazon:shopping-cart/api1
4514            let analysed_function_in_api1 = AnalysedFunction {
4515                name: "foo".to_string(),
4516                parameters: vec![AnalysedFunctionParameter {
4517                    name: "arg1".to_string(),
4518                    typ: str(),
4519                }],
4520                results: vec![AnalysedFunctionResult {
4521                    name: None,
4522                    typ: str(),
4523                }],
4524            };
4525
4526            // Exist in both amazon:shopping-cart/api1 and amazon:shopping-cart/api2
4527            let analysed_function_in_api1_and_api2 = AnalysedFunction {
4528                name: "bar".to_string(),
4529                parameters: vec![AnalysedFunctionParameter {
4530                    name: "arg1".to_string(),
4531                    typ: str(),
4532                }],
4533                results: vec![AnalysedFunctionResult {
4534                    name: None,
4535                    typ: str(),
4536                }],
4537            };
4538
4539            // Exist in only wasi:clocks/monotonic-clock
4540            let analysed_function_in_wasi = AnalysedFunction {
4541                name: "baz".to_string(),
4542                parameters: vec![AnalysedFunctionParameter {
4543                    name: "arg1".to_string(),
4544                    typ: str(),
4545                }],
4546                results: vec![AnalysedFunctionResult {
4547                    name: None,
4548                    typ: str(),
4549                }],
4550            };
4551
4552            // Exist in wasi:clocks/monotonic-clock and amazon:shopping-cart/api1
4553            let analysed_function_in_wasi_and_api1 = AnalysedFunction {
4554                name: "qux".to_string(),
4555                parameters: vec![AnalysedFunctionParameter {
4556                    name: "arg1".to_string(),
4557                    typ: str(),
4558                }],
4559                results: vec![AnalysedFunctionResult {
4560                    name: None,
4561                    typ: str(),
4562                }],
4563            };
4564
4565            let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
4566                name: "amazon:shopping-cart/api1".to_string(),
4567                functions: vec![
4568                    analysed_function_in_api1,
4569                    analysed_function_in_api1_and_api2.clone(),
4570                    analysed_function_in_wasi_and_api1.clone(),
4571                ],
4572            });
4573
4574            let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
4575                name: "amazon:shopping-cart/api2".to_string(),
4576                functions: vec![analysed_function_in_api1_and_api2],
4577            });
4578
4579            let analysed_export3 = AnalysedExport::Instance(AnalysedInstance {
4580                name: "wasi:clocks/monotonic-clock".to_string(),
4581                functions: vec![
4582                    analysed_function_in_wasi,
4583                    analysed_function_in_wasi_and_api1,
4584                ],
4585            });
4586
4587            vec![analysed_export1, analysed_export2, analysed_export3]
4588        }
4589
4590        fn get_metadata_with_resource(
4591            resource_constructor_params: Vec<AnalysedFunctionParameter>,
4592        ) -> Vec<AnalysedExport> {
4593            let instance = AnalysedExport::Instance(AnalysedInstance {
4594                name: "golem:it/api".to_string(),
4595                functions: vec![
4596                    AnalysedFunction {
4597                        name: "[constructor]cart".to_string(),
4598                        parameters: resource_constructor_params,
4599                        results: vec![AnalysedFunctionResult {
4600                            name: None,
4601                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
4602                        }],
4603                    },
4604                    AnalysedFunction {
4605                        name: "[method]cart.add-item".to_string(),
4606                        parameters: vec![
4607                            AnalysedFunctionParameter {
4608                                name: "self".to_string(),
4609                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4610                            },
4611                            AnalysedFunctionParameter {
4612                                name: "item".to_string(),
4613                                typ: record(vec![
4614                                    field("product-id", str()),
4615                                    field("name", str()),
4616                                    field("price", f32()),
4617                                    field("quantity", u32()),
4618                                ]),
4619                            },
4620                        ],
4621                        results: vec![],
4622                    },
4623                    AnalysedFunction {
4624                        name: "[method]cart.remove-item".to_string(),
4625                        parameters: vec![
4626                            AnalysedFunctionParameter {
4627                                name: "self".to_string(),
4628                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4629                            },
4630                            AnalysedFunctionParameter {
4631                                name: "product-id".to_string(),
4632                                typ: str(),
4633                            },
4634                        ],
4635                        results: vec![],
4636                    },
4637                    AnalysedFunction {
4638                        name: "[method]cart.update-item-quantity".to_string(),
4639                        parameters: vec![
4640                            AnalysedFunctionParameter {
4641                                name: "self".to_string(),
4642                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4643                            },
4644                            AnalysedFunctionParameter {
4645                                name: "product-id".to_string(),
4646                                typ: str(),
4647                            },
4648                            AnalysedFunctionParameter {
4649                                name: "quantity".to_string(),
4650                                typ: u32(),
4651                            },
4652                        ],
4653                        results: vec![],
4654                    },
4655                    AnalysedFunction {
4656                        name: "[method]cart.checkout".to_string(),
4657                        parameters: vec![AnalysedFunctionParameter {
4658                            name: "self".to_string(),
4659                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4660                        }],
4661                        results: vec![AnalysedFunctionResult {
4662                            name: None,
4663                            typ: variant(vec![
4664                                case("error", str()),
4665                                case("success", record(vec![field("order-id", str())])),
4666                            ]),
4667                        }],
4668                    },
4669                    AnalysedFunction {
4670                        name: "[method]cart.get-cart-contents".to_string(),
4671                        parameters: vec![AnalysedFunctionParameter {
4672                            name: "self".to_string(),
4673                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4674                        }],
4675                        results: vec![AnalysedFunctionResult {
4676                            name: None,
4677                            typ: list(record(vec![
4678                                field("product-id", str()),
4679                                field("name", str()),
4680                                field("price", f32()),
4681                                field("quantity", u32()),
4682                            ])),
4683                        }],
4684                    },
4685                    AnalysedFunction {
4686                        name: "[method]cart.merge-with".to_string(),
4687                        parameters: vec![
4688                            AnalysedFunctionParameter {
4689                                name: "self".to_string(),
4690                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4691                            },
4692                            AnalysedFunctionParameter {
4693                                name: "other-cart".to_string(),
4694                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4695                            },
4696                        ],
4697                        results: vec![],
4698                    },
4699                    AnalysedFunction {
4700                        name: "[drop]cart".to_string(),
4701                        parameters: vec![AnalysedFunctionParameter {
4702                            name: "self".to_string(),
4703                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
4704                        }],
4705                        results: vec![],
4706                    },
4707                ],
4708            });
4709
4710            vec![instance]
4711        }
4712
4713        pub(crate) fn get_value_and_type(
4714            analysed_type: &AnalysedType,
4715            wasm_wave_str: &str,
4716        ) -> ValueAndType {
4717            golem_wasm_rpc::parse_value_and_type(analysed_type, wasm_wave_str).unwrap()
4718        }
4719
4720        // The interpreter that always returns a static value for every function calls in Rib
4721        // regardless of the input arguments
4722        pub(crate) fn interpreter_static_response(
4723            result_value: &ValueAndType,
4724            input: Option<RibInput>,
4725        ) -> Interpreter {
4726            let value = result_value.clone();
4727
4728            let invoke = Arc::new(TestInvoke1 { value });
4729
4730            Interpreter {
4731                input: input.unwrap_or_default(),
4732                invoke,
4733                custom_stack: None,
4734                custom_env: None,
4735            }
4736        }
4737
4738        // The interpreter that always returns a record value consisting of function name, worker name etc
4739        // for every function calls in Rib.
4740        // Example : `my-instance.qux[amazon:shopping-cart]("bar")` will return a record
4741        // that contains the actual worker-name of my-instance, the function name `qux` and arguments
4742        // It helps ensures that interpreter invokes the function at the expected worker.
4743        pub(crate) fn interpreter_worker_details_response(
4744            rib_input: Option<RibInput>,
4745        ) -> Interpreter {
4746            let invoke: Arc<dyn RibFunctionInvoke + Send + Sync> = Arc::new(TestInvoke2);
4747
4748            Interpreter {
4749                input: rib_input.unwrap_or_default(),
4750                invoke,
4751                custom_stack: None,
4752                custom_env: None,
4753            }
4754        }
4755
4756        // A simple interpreter that returns response based on the function
4757        pub(crate) fn interpreter_dynamic_response(input: Option<RibInput>) -> Interpreter {
4758            let invoke = Arc::new(TestInvoke3);
4759
4760            Interpreter {
4761                input: input.unwrap_or_default(),
4762                invoke,
4763                custom_stack: None,
4764                custom_env: None,
4765            }
4766        }
4767
4768        pub(crate) fn parse_function_details(input: &str) -> ValueAndType {
4769            let analysed_type = record(vec![
4770                field("worker-name", option(str())),
4771                field("function-name", str()),
4772                field("args0", str()),
4773            ]);
4774
4775            get_value_and_type(&analysed_type, input)
4776        }
4777
4778        struct TestInvoke1 {
4779            value: ValueAndType,
4780        }
4781
4782        #[async_trait]
4783        impl RibFunctionInvoke for TestInvoke1 {
4784            async fn invoke(
4785                &self,
4786                _worker_name: Option<EvaluatedWorkerName>,
4787                _fqn: EvaluatedFqFn,
4788                _args: EvaluatedFnArgs,
4789            ) -> Result<ValueAndType, String> {
4790                let value = self.value.clone();
4791                Ok(ValueAndType::new(
4792                    Value::Tuple(vec![value.value]),
4793                    tuple(vec![value.typ]),
4794                ))
4795            }
4796        }
4797
4798        struct TestInvoke2;
4799
4800        #[async_trait]
4801        impl RibFunctionInvoke for TestInvoke2 {
4802            async fn invoke(
4803                &self,
4804                worker_name: Option<EvaluatedWorkerName>,
4805                function_name: EvaluatedFqFn,
4806                args: EvaluatedFnArgs,
4807            ) -> Result<ValueAndType, String> {
4808                let worker_name = worker_name.map(|x| x.0);
4809
4810                let function_name = function_name.0.into_value_and_type();
4811
4812                let args = args.0;
4813
4814                let mut arg_types = vec![];
4815
4816                for (index, value_and_type) in args.iter().enumerate() {
4817                    let name = format!("args{}", index);
4818                    let value = value_and_type.typ.clone();
4819                    arg_types.push(field(name.as_str(), value));
4820                }
4821
4822                let mut analysed_type_pairs = vec![];
4823                analysed_type_pairs.push(field("worker-name", option(str())));
4824                analysed_type_pairs.push(field("function-name", str()));
4825                analysed_type_pairs.extend(arg_types);
4826
4827                let mut values = vec![];
4828
4829                values.push(Value::Option(
4830                    worker_name.map(|x| Box::new(Value::String(x))),
4831                ));
4832                values.push(function_name.value);
4833
4834                for arg_value in args {
4835                    values.push(arg_value.value);
4836                }
4837
4838                let value = ValueAndType::new(
4839                    Value::Tuple(vec![Value::Record(values)]),
4840                    tuple(vec![record(analysed_type_pairs)]),
4841                );
4842                Ok(value)
4843            }
4844        }
4845
4846        pub(crate) fn get_metadata_with_enum_and_variant() -> Vec<AnalysedExport> {
4847            vec![
4848                AnalysedExport::Function(AnalysedFunction {
4849                    name: "add-u32".to_string(),
4850                    parameters: vec![
4851                        AnalysedFunctionParameter {
4852                            name: "param1".to_string(),
4853                            typ: u32(),
4854                        },
4855                        AnalysedFunctionParameter {
4856                            name: "param2".to_string(),
4857                            typ: u32(),
4858                        },
4859                    ],
4860                    results: vec![AnalysedFunctionResult {
4861                        name: None,
4862                        typ: u32(),
4863                    }],
4864                }),
4865                AnalysedExport::Function(AnalysedFunction {
4866                    name: "add-u64".to_string(),
4867                    parameters: vec![
4868                        AnalysedFunctionParameter {
4869                            name: "param1".to_string(),
4870                            typ: u64(),
4871                        },
4872                        AnalysedFunctionParameter {
4873                            name: "param2".to_string(),
4874                            typ: u64(),
4875                        },
4876                    ],
4877                    results: vec![AnalysedFunctionResult {
4878                        name: None,
4879                        typ: u64(),
4880                    }],
4881                }),
4882                AnalysedExport::Function(AnalysedFunction {
4883                    name: "add-enum".to_string(),
4884                    parameters: vec![
4885                        AnalysedFunctionParameter {
4886                            name: "param1".to_string(),
4887                            typ: r#enum(&["x", "y", "z"]),
4888                        },
4889                        AnalysedFunctionParameter {
4890                            name: "param2".to_string(),
4891                            typ: r#enum(&["x", "y", "z"]),
4892                        },
4893                    ],
4894                    results: vec![AnalysedFunctionResult {
4895                        name: None,
4896                        typ: r#enum(&["x", "y", "z"]),
4897                    }],
4898                }),
4899                AnalysedExport::Function(AnalysedFunction {
4900                    name: "add-variant".to_string(),
4901                    parameters: vec![
4902                        AnalysedFunctionParameter {
4903                            name: "param1".to_string(),
4904                            typ: get_analysed_type_variant(),
4905                        },
4906                        AnalysedFunctionParameter {
4907                            name: "param2".to_string(),
4908                            typ: get_analysed_type_variant(),
4909                        },
4910                    ],
4911                    results: vec![AnalysedFunctionResult {
4912                        name: None,
4913                        typ: get_analysed_type_variant(),
4914                    }],
4915                }),
4916            ]
4917        }
4918
4919        struct TestInvoke3;
4920
4921        #[async_trait]
4922        impl RibFunctionInvoke for TestInvoke3 {
4923            async fn invoke(
4924                &self,
4925                _worker_name: Option<EvaluatedWorkerName>,
4926                function_name: EvaluatedFqFn,
4927                args: EvaluatedFnArgs,
4928            ) -> Result<ValueAndType, String> {
4929                match function_name.0.as_str() {
4930                    "add-u32" => {
4931                        let args = args.0;
4932                        let arg1 = args[0].get_literal().and_then(|x| x.get_number()).unwrap();
4933                        let arg2 = args[1].get_literal().and_then(|x| x.get_number()).unwrap();
4934                        let result = arg1 + arg2;
4935                        let u32 = result.cast_to(&u32()).unwrap();
4936
4937                        Ok(ValueAndType::new(
4938                            Value::Tuple(vec![u32.value]),
4939                            tuple(vec![u32.typ]),
4940                        ))
4941                    }
4942                    "add-u64" => {
4943                        let args = args.0;
4944                        let arg1 = args[0].get_literal().and_then(|x| x.get_number()).unwrap();
4945                        let arg2 = args[1].get_literal().and_then(|x| x.get_number()).unwrap();
4946                        let result = arg1 + arg2;
4947                        let u64 = result.cast_to(&u64()).unwrap();
4948                        Ok(ValueAndType::new(
4949                            Value::Tuple(vec![u64.value]),
4950                            tuple(vec![u64.typ]),
4951                        ))
4952                    }
4953                    "add-enum" => {
4954                        let args = args.0;
4955                        let arg1 = args[0].clone().value;
4956                        let arg2 = args[1].clone().value;
4957                        match (arg1, arg2) {
4958                            (Value::Enum(x), Value::Enum(y)) => {
4959                                if x == y {
4960                                    let result =
4961                                        ValueAndType::new(Value::Enum(x), r#enum(&["x", "y", "z"]));
4962                                    Ok(ValueAndType::new(
4963                                        Value::Tuple(vec![result.value]),
4964                                        tuple(vec![result.typ]),
4965                                    ))
4966                                } else {
4967                                    Err(format!("Enums are not equal: {} and {}", x, y))
4968                                }
4969                            }
4970                            (v1, v2) => Err(format!(
4971                                "Invalid arguments for add-enum: {:?} and {:?}",
4972                                v1, v2
4973                            )),
4974                        }
4975                    }
4976                    "add-variant" => {
4977                        let args = args.0;
4978                        let arg1 = args[0].clone().value;
4979                        let arg2 = args[1].clone().value;
4980                        match (arg1, arg2) {
4981                            (
4982                                Value::Variant {
4983                                    case_idx: case_idx1,
4984                                    case_value,
4985                                },
4986                                Value::Variant {
4987                                    case_idx: case_idx2,
4988                                    ..
4989                                },
4990                            ) => {
4991                                if case_idx1 == case_idx2 {
4992                                    let result = ValueAndType::new(
4993                                        Value::Variant {
4994                                            case_idx: case_idx1,
4995                                            case_value,
4996                                        },
4997                                        get_analysed_type_variant(),
4998                                    );
4999                                    Ok(ValueAndType::new(
5000                                        Value::Tuple(vec![result.value]),
5001                                        tuple(vec![result.typ]),
5002                                    ))
5003                                } else {
5004                                    Err(format!(
5005                                        "Variants are not equal: {} and {}",
5006                                        case_idx1, case_idx2
5007                                    ))
5008                                }
5009                            }
5010                            (v1, v2) => Err(format!(
5011                                "Invalid arguments for add-variant: {:?} and {:?}",
5012                                v1, v2
5013                            )),
5014                        }
5015                    }
5016                    fun => Err(format!("unknown function {}", fun)),
5017                }
5018            }
5019        }
5020    }
5021}