rib/interpreter/
rib_interpreter.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.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://license.golem.cloud/LICENSE
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 super::interpreter_stack_value::RibInterpreterStackValue;
16use crate::interpreter::env::InterpreterEnv;
17use crate::interpreter::instruction_cursor::RibByteCodeCursor;
18use crate::interpreter::rib_runtime_error::{
19    arithmetic_error, no_result, throw_error, RibRuntimeError,
20};
21use crate::interpreter::stack::InterpreterStack;
22use crate::{
23    internal_corrupted_state, DefaultWorkerNameGenerator, GenerateWorkerName, RibByteCode,
24    RibComponentFunctionInvoke, RibIR, RibInput, RibResult,
25};
26use std::sync::Arc;
27
28pub struct Interpreter {
29    pub input: RibInput,
30    pub invoke: Arc<dyn RibComponentFunctionInvoke + Sync + Send>,
31    pub generate_worker_name: Arc<dyn GenerateWorkerName + Sync + Send>,
32}
33
34impl Default for Interpreter {
35    fn default() -> Self {
36        Interpreter {
37            input: RibInput::default(),
38            invoke: Arc::new(internal::NoopRibFunctionInvoke),
39            generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
40        }
41    }
42}
43
44pub type RibInterpreterResult<T> = Result<T, RibRuntimeError>;
45
46impl Interpreter {
47    pub fn new(
48        input: RibInput,
49        invoke: Arc<dyn RibComponentFunctionInvoke + Sync + Send>,
50        generate_worker_name: Arc<dyn GenerateWorkerName + Sync + Send>,
51    ) -> Self {
52        Interpreter {
53            input: input.clone(),
54            invoke,
55            generate_worker_name,
56        }
57    }
58
59    // Interpreter that's not expected to call a side-effecting function call.
60    // All it needs is environment with the required variables to evaluate the Rib script
61    pub fn pure(
62        input: RibInput,
63        generate_worker_name: Arc<dyn GenerateWorkerName + Sync + Send>,
64    ) -> Self {
65        Interpreter {
66            input,
67            invoke: Arc::new(internal::NoopRibFunctionInvoke),
68            generate_worker_name,
69        }
70    }
71
72    pub fn override_rib_input(&mut self, rib_input: RibInput) {
73        self.input = rib_input;
74    }
75
76    pub async fn run(&mut self, instructions0: RibByteCode) -> Result<RibResult, RibRuntimeError> {
77        let mut byte_code_cursor = RibByteCodeCursor::from_rib_byte_code(instructions0);
78        let mut stack = InterpreterStack::default();
79
80        let mut interpreter_env = InterpreterEnv::from(&self.input, &self.invoke);
81
82        while let Some(instruction) = byte_code_cursor.get_instruction() {
83            match instruction {
84                RibIR::GenerateWorkerName(instance_count) => {
85                    internal::run_generate_worker_name(
86                        instance_count,
87                        self,
88                        &mut stack,
89                        &mut interpreter_env,
90                    )?;
91                }
92
93                RibIR::PushLit(val) => {
94                    stack.push_val(val);
95                }
96
97                RibIR::PushFlag(val) => {
98                    stack.push_val(val);
99                }
100
101                RibIR::CreateAndPushRecord(analysed_type) => {
102                    internal::run_create_record_instruction(analysed_type, &mut stack)?;
103                }
104
105                RibIR::UpdateRecord(field_name) => {
106                    internal::run_update_record_instruction(field_name, &mut stack)?;
107                }
108
109                RibIR::PushList(analysed_type, arg_size) => {
110                    internal::run_push_list_instruction(arg_size, analysed_type, &mut stack)?;
111                }
112
113                RibIR::EqualTo => {
114                    internal::run_compare_instruction(&mut stack, |left, right| left == right)?;
115                }
116
117                RibIR::GreaterThan => {
118                    internal::run_compare_instruction(&mut stack, |left, right| left > right)?;
119                }
120
121                RibIR::LessThan => {
122                    internal::run_compare_instruction(&mut stack, |left, right| left < right)?;
123                }
124
125                RibIR::GreaterThanOrEqualTo => {
126                    internal::run_compare_instruction(&mut stack, |left, right| left >= right)?;
127                }
128
129                RibIR::LessThanOrEqualTo => {
130                    internal::run_compare_instruction(&mut stack, |left, right| left <= right)?;
131                }
132                RibIR::Plus(analysed_type) => {
133                    internal::run_math_instruction(
134                        &mut stack,
135                        |left, right| {
136                            let result = left + right;
137                            result.map_err(|err| arithmetic_error(err.as_str()))
138                        },
139                        &analysed_type,
140                    )?;
141                }
142                RibIR::Minus(analysed_type) => {
143                    internal::run_math_instruction(
144                        &mut stack,
145                        |left, right| {
146                            let result = left - right;
147                            result.map_err(|err| arithmetic_error(err.as_str()))
148                        },
149                        &analysed_type,
150                    )?;
151                }
152                RibIR::Divide(analysed_type) => {
153                    internal::run_math_instruction(
154                        &mut stack,
155                        |left, right| {
156                            if right.is_zero() {
157                                Err(arithmetic_error(
158                                    format!("division by zero. left: {left}, right: {right}")
159                                        .as_str(),
160                                ))
161                            } else {
162                                (left / right).map_err(|err| arithmetic_error(err.as_str()))
163                            }
164                        },
165                        &analysed_type,
166                    )?;
167                }
168                RibIR::Multiply(analysed_type) => {
169                    internal::run_math_instruction(
170                        &mut stack,
171                        |left, right| {
172                            let result = left * right;
173                            result.map_err(|err| arithmetic_error(err.as_str()))
174                        },
175                        &analysed_type,
176                    )?;
177                }
178
179                RibIR::AssignVar(variable_id) => {
180                    internal::run_assign_var_instruction(
181                        variable_id,
182                        &mut stack,
183                        &mut interpreter_env,
184                    )?;
185                }
186
187                RibIR::LoadVar(variable_id) => {
188                    internal::run_load_var_instruction(
189                        variable_id,
190                        &mut stack,
191                        &mut interpreter_env,
192                    )?;
193                }
194
195                RibIR::IsEmpty => {
196                    internal::run_is_empty_instruction(&mut stack)?;
197                }
198
199                RibIR::JumpIfFalse(instruction_id) => {
200                    internal::run_jump_if_false_instruction(
201                        instruction_id,
202                        &mut byte_code_cursor,
203                        &mut stack,
204                    )?;
205                }
206
207                RibIR::SelectField(field_name) => {
208                    internal::run_select_field_instruction(field_name, &mut stack)?;
209                }
210
211                RibIR::SelectIndex(index) => {
212                    internal::run_select_index_instruction(&mut stack, index)?;
213                }
214
215                RibIR::SelectIndexV1 => {
216                    internal::run_select_index_v1_instruction(&mut stack)?;
217                }
218
219                RibIR::CreateFunctionName(site, function_type) => {
220                    internal::run_create_function_name_instruction(
221                        site,
222                        function_type,
223                        &mut stack,
224                    )?;
225                }
226
227                RibIR::InvokeFunction(
228                    component_info,
229                    instance_variable,
230                    arg_size,
231                    expected_result_type,
232                ) => {
233                    internal::run_invoke_function_instruction(
234                        component_info,
235                        &byte_code_cursor.position(),
236                        arg_size,
237                        instance_variable,
238                        &mut stack,
239                        &mut interpreter_env,
240                        expected_result_type,
241                    )
242                    .await?;
243                }
244
245                RibIR::PushVariant(variant_name, analysed_type) => {
246                    internal::run_variant_construction_instruction(
247                        variant_name,
248                        analysed_type,
249                        &mut stack,
250                    )
251                    .await?;
252                }
253
254                RibIR::PushEnum(enum_name, analysed_type) => {
255                    internal::run_push_enum_instruction(&mut stack, enum_name, analysed_type)?;
256                }
257
258                RibIR::Throw(message) => {
259                    return Err(throw_error(message.as_str()));
260                }
261
262                RibIR::GetTag => {
263                    internal::run_get_tag_instruction(&mut stack)?;
264                }
265
266                RibIR::Deconstruct => {
267                    internal::run_deconstruct_instruction(&mut stack)?;
268                }
269
270                RibIR::Jump(instruction_id) => {
271                    byte_code_cursor.move_to(&instruction_id).ok_or_else(|| {
272                        internal_corrupted_state!(
273                            "internal error. Failed to move to label {}",
274                            instruction_id.index
275                        )
276                    })?;
277                }
278
279                RibIR::PushSome(analysed_type) => {
280                    internal::run_create_some_instruction(&mut stack, analysed_type)?;
281                }
282                RibIR::PushNone(analysed_type) => {
283                    internal::run_create_none_instruction(&mut stack, analysed_type)?;
284                }
285                RibIR::PushOkResult(analysed_type) => {
286                    internal::run_create_ok_instruction(&mut stack, analysed_type)?;
287                }
288                RibIR::PushErrResult(analysed_type) => {
289                    internal::run_create_err_instruction(&mut stack, analysed_type)?;
290                }
291                RibIR::Concat(arg_size) => {
292                    internal::run_concat_instruction(&mut stack, arg_size)?;
293                }
294                RibIR::PushTuple(analysed_type, arg_size) => {
295                    internal::run_push_tuple_instruction(arg_size, analysed_type, &mut stack)?;
296                }
297                RibIR::Negate => {
298                    internal::run_negate_instruction(&mut stack)?;
299                }
300
301                RibIR::Label(_) => {}
302
303                RibIR::And => {
304                    internal::run_and_instruction(&mut stack)?;
305                }
306
307                RibIR::Or => {
308                    internal::run_or_instruction(&mut stack)?;
309                }
310                RibIR::ToIterator => {
311                    internal::run_to_iterator(&mut stack)?;
312                }
313                RibIR::CreateSink(analysed_type) => {
314                    internal::run_create_sink_instruction(&mut stack, analysed_type)?
315                }
316                RibIR::AdvanceIterator => {
317                    internal::run_advance_iterator_instruction(&mut stack)?;
318                }
319                RibIR::PushToSink => {
320                    internal::run_push_to_sink_instruction(&mut stack)?;
321                }
322
323                RibIR::SinkToList => {
324                    internal::run_sink_to_list_instruction(&mut stack)?;
325                }
326
327                RibIR::Length => {
328                    internal::run_length_instruction(&mut stack)?;
329                }
330            }
331        }
332
333        match byte_code_cursor.last() {
334            Some(RibIR::AssignVar(_)) => Ok(RibResult::Unit),
335            _ => {
336                let stack_value = stack
337                    .pop()
338                    .unwrap_or_else(|| RibInterpreterStackValue::Unit);
339
340                let rib_result = RibResult::from_rib_interpreter_stack_value(&stack_value)
341                    .ok_or_else(no_result)?;
342                Ok(rib_result)
343            }
344        }
345    }
346}
347
348mod internal {
349    use crate::interpreter::env::{EnvironmentKey, InterpreterEnv};
350    use crate::interpreter::interpreter_stack_value::RibInterpreterStackValue;
351    use crate::interpreter::literal::LiteralValue;
352    use crate::interpreter::stack::InterpreterStack;
353    use crate::{
354        bail_corrupted_state, internal_corrupted_state, AnalysedTypeWithUnit, CoercedNumericValue,
355        ComponentDependencyKey, EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName,
356        FunctionReferenceType, GetLiteralValue, InstanceVariable, InstructionId, Interpreter,
357        ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite,
358        RibComponentFunctionInvoke, RibFunctionInvokeResult, RibInterpreterResult, TypeHint,
359        VariableId,
360    };
361    use golem_wasm_ast::analysis::AnalysedType;
362    use golem_wasm_ast::analysis::TypeResult;
363    use golem_wasm_rpc::{IntoValueAndType, Value, ValueAndType};
364
365    use crate::interpreter::instruction_cursor::RibByteCodeCursor;
366    use crate::interpreter::rib_runtime_error::{
367        cast_error_custom, empty_stack, exhausted_iterator, field_not_found, function_invoke_fail,
368        index_out_of_bound, infinite_computation, input_not_found, instruction_jump_error,
369        insufficient_stack_items, invalid_type_with_stack_value, type_mismatch_with_type_hint,
370        RibRuntimeError,
371    };
372    use crate::type_inference::GetTypeHint;
373    use async_trait::async_trait;
374    use golem_wasm_ast::analysis::analysed_type::{s16, s32, s64, s8, str, u16, u32, u64, u8};
375    use std::ops::Deref;
376
377    pub(crate) struct NoopRibFunctionInvoke;
378
379    #[async_trait]
380    impl RibComponentFunctionInvoke for NoopRibFunctionInvoke {
381        async fn invoke(
382            &self,
383            _component_dependency_key: ComponentDependencyKey,
384            _instruction_id: &InstructionId,
385            _worker_name: EvaluatedWorkerName,
386            _function_name: EvaluatedFqFn,
387            _args: EvaluatedFnArgs,
388            _return_type: Option<AnalysedType>,
389        ) -> RibFunctionInvokeResult {
390            Ok(None)
391        }
392    }
393
394    pub(crate) fn run_is_empty_instruction(
395        interpreter_stack: &mut InterpreterStack,
396    ) -> RibInterpreterResult<()> {
397        let rib_result = interpreter_stack.pop().ok_or_else(empty_stack)?;
398
399        let bool_opt = match rib_result {
400            RibInterpreterStackValue::Val(ValueAndType {
401                value: Value::List(items),
402                ..
403            }) => Some(items.is_empty()),
404            RibInterpreterStackValue::Iterator(iter) => {
405                let mut peekable_iter = iter.peekable();
406                let result = peekable_iter.peek().is_some();
407                interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(peekable_iter)));
408                Some(result)
409            }
410            RibInterpreterStackValue::Sink(values, analysed_type) => {
411                let possible_iterator = interpreter_stack.pop().ok_or_else(|| {
412                    internal_corrupted_state!(
413                        "internal error: Expecting an iterator to check is empty"
414                    )
415                })?;
416
417                match possible_iterator {
418                    RibInterpreterStackValue::Iterator(iter) => {
419                        let mut peekable_iter = iter.peekable();
420                        let result = peekable_iter.peek().is_some();
421                        interpreter_stack
422                            .push(RibInterpreterStackValue::Iterator(Box::new(peekable_iter)));
423                        interpreter_stack
424                            .push(RibInterpreterStackValue::Sink(values, analysed_type));
425                        Some(result)
426                    }
427
428                    _ => None,
429                }
430            }
431            RibInterpreterStackValue::Val(_) => None,
432            RibInterpreterStackValue::Unit => None,
433        };
434
435        let bool = bool_opt.ok_or(internal_corrupted_state!("failed to execute is_empty"))?;
436        interpreter_stack.push_val(bool.into_value_and_type());
437        Ok(())
438    }
439
440    pub(crate) fn run_jump_if_false_instruction(
441        instruction_id: InstructionId,
442        instruction_stack: &mut RibByteCodeCursor,
443        interpreter_stack: &mut InterpreterStack,
444    ) -> RibInterpreterResult<()> {
445        let predicate = interpreter_stack.try_pop_bool()?;
446
447        // Jump if predicate is false
448        if !predicate {
449            instruction_stack
450                .move_to(&instruction_id)
451                .ok_or_else(|| instruction_jump_error(instruction_id))?;
452        }
453
454        Ok(())
455    }
456
457    macro_rules! match_range_to_value {
458        (
459        $from_val:expr,
460        $to_val:expr,
461        $variant:ident,
462        $type_fn:expr,
463        $inclusive:expr,
464        $stack:expr
465    ) => {
466            match $to_val {
467                Value::$variant(num2) => {
468                    if $inclusive {
469                        let range_iter = (*$from_val..=*num2)
470                            .map(|i| ValueAndType::new(Value::$variant(i), $type_fn));
471                        $stack.push(RibInterpreterStackValue::Iterator(Box::new(range_iter)));
472                    } else {
473                        let range_iter = (*$from_val..*num2)
474                            .map(|i| ValueAndType::new(Value::$variant(i), $type_fn));
475                        $stack.push(RibInterpreterStackValue::Iterator(Box::new(range_iter)));
476                    }
477                }
478
479                _ => bail_corrupted_state!(concat!(
480                    "expected a field named 'to' to be of type ",
481                    stringify!($variant),
482                    ", but it was not"
483                )),
484            }
485        };
486    }
487
488    pub(crate) fn run_to_iterator(
489        interpreter_stack: &mut InterpreterStack,
490    ) -> RibInterpreterResult<()> {
491        let popped_up = interpreter_stack.pop().ok_or_else(empty_stack)?;
492
493        let value_and_type = popped_up.get_val().ok_or_else(empty_stack)?;
494
495        match (value_and_type.value, value_and_type.typ) {
496            (Value::List(items), AnalysedType::List(item_type)) => {
497                let items = items
498                    .into_iter()
499                    .map(|item| ValueAndType::new(item, (*item_type.inner).clone()))
500                    .collect::<Vec<_>>();
501
502                interpreter_stack.push(RibInterpreterStackValue::Iterator(Box::new(
503                    items.into_iter(),
504                )));
505
506                Ok(())
507            }
508            (Value::Record(fields), AnalysedType::Record(_)) => {
509                let from_value = fields.first().ok_or_else(|| {
510                    internal_corrupted_state!(
511                        "expected a field named 'from' to be present in the record"
512                    )
513                })?;
514
515                let to_value = fields.get(1).ok_or_else(|| {
516                    infinite_computation(
517                        "an infinite range is being iterated. make sure range is finite to avoid infinite computation",
518                    )
519                })?;
520
521                let inclusive_value = fields.get(2).ok_or_else(|| {
522                    internal_corrupted_state!(
523                        "expected a field named 'inclusive' to be present in the record"
524                    )
525                })?;
526
527                let inclusive = match inclusive_value {
528                    Value::Bool(b) => *b,
529                    _ => {
530                        bail_corrupted_state!(
531                            "expected a field named 'inclusive' to be of type boolean, but it was not"
532                        )
533                    }
534                };
535
536                match from_value {
537                    Value::S8(num1) => {
538                        match_range_to_value!(num1, to_value, S8, s8(), inclusive, interpreter_stack);
539                    }
540
541                    Value::U8(num1) => {
542                        match_range_to_value!(num1, to_value, U8, u8(), inclusive, interpreter_stack);
543                    }
544
545                    Value::S16(num1) => {
546                        match_range_to_value!(num1, to_value, S16, s16(), inclusive, interpreter_stack);
547                    }
548
549                    Value::U16(num1) => {
550                        match_range_to_value!(num1, to_value, U16, u16(), inclusive, interpreter_stack);
551                    }
552
553                    Value::S32(num1) => {
554                        match_range_to_value!(num1, to_value, S32, s32(), inclusive, interpreter_stack);
555                    }
556
557                    Value::U32(num1) => {
558                        match_range_to_value!(num1, to_value, U32, u32(), inclusive, interpreter_stack);
559                    }
560
561                    Value::S64(num1) => {
562                        match_range_to_value!(num1, to_value, S64, s64(), inclusive, interpreter_stack);
563                    }
564
565                    Value::U64(num1) => {
566                        match_range_to_value!(num1, to_value, U64, u64(), inclusive, interpreter_stack);
567                    }
568
569                    _ => bail_corrupted_state!(
570                        "expected a field named 'from' to be of type S8, U8, S16, U16, S32, U32, S64, U64, but it was not"
571                    ),
572                }
573
574                Ok(())
575            }
576
577            _ => Err(internal_corrupted_state!(
578                "failed to convert to an iterator"
579            )),
580        }
581    }
582
583    pub(crate) fn run_create_sink_instruction(
584        interpreter_stack: &mut InterpreterStack,
585        analysed_type: AnalysedType,
586    ) -> RibInterpreterResult<()> {
587        let analysed_type = match analysed_type {
588            AnalysedType::List(type_list) => *type_list.inner,
589            _ => bail_corrupted_state!("expecting a list type to create sink"),
590        };
591        interpreter_stack.create_sink(analysed_type);
592        Ok(())
593    }
594
595    pub(crate) fn run_advance_iterator_instruction(
596        interpreter_stack: &mut InterpreterStack,
597    ) -> RibInterpreterResult<()> {
598        let mut stack_value = interpreter_stack.pop().ok_or_else(empty_stack)?;
599
600        match &mut stack_value {
601            RibInterpreterStackValue::Sink(_, _) => {
602                let mut existing_iterator = interpreter_stack
603                    .pop()
604                    .ok_or(internal_corrupted_state!("failed to get an iterator"))?;
605
606                match &mut existing_iterator {
607                    RibInterpreterStackValue::Iterator(iter) => {
608                        if let Some(value_and_type) = iter.next() {
609                            interpreter_stack.push(existing_iterator); // push the iterator back
610                            interpreter_stack.push(stack_value); // push the sink back
611                            interpreter_stack.push(RibInterpreterStackValue::Val(value_and_type));
612                            Ok(())
613                        } else {
614                            Err(exhausted_iterator())
615                        }
616                    }
617
618                    _ => Err(internal_corrupted_state!(
619                        "sink cannot exist without a corresponding iterator"
620                    )),
621                }
622            }
623
624            RibInterpreterStackValue::Iterator(iter) => {
625                if let Some(value_and_type) = iter.next() {
626                    interpreter_stack.push(stack_value);
627                    interpreter_stack.push(RibInterpreterStackValue::Val(value_and_type));
628                    Ok(())
629                } else {
630                    Err(exhausted_iterator())
631                }
632            }
633            _ => Err(exhausted_iterator()),
634        }
635    }
636
637    pub(crate) fn run_push_to_sink_instruction(
638        interpreter_stack: &mut InterpreterStack,
639    ) -> RibInterpreterResult<()> {
640        let last_value = interpreter_stack.pop_val();
641        match last_value {
642            Some(val) => {
643                interpreter_stack.push_to_sink(val)?;
644
645                Ok(())
646            }
647            None => Ok(()),
648        }
649    }
650
651    pub(crate) fn run_sink_to_list_instruction(
652        interpreter_stack: &mut InterpreterStack,
653    ) -> RibInterpreterResult<()> {
654        let (result, analysed_type) =
655            interpreter_stack
656                .pop_sink()
657                .ok_or(internal_corrupted_state!(
658                    "failed to retrieve items from sink"
659                ))?;
660
661        interpreter_stack.push_list(
662            result.into_iter().map(|vnt| vnt.value).collect(),
663            &analysed_type,
664        );
665
666        Ok(())
667    }
668
669    pub(crate) fn run_length_instruction(
670        interpreter_stack: &mut InterpreterStack,
671    ) -> RibInterpreterResult<()> {
672        let rib_result = interpreter_stack.pop().ok_or_else(empty_stack)?;
673
674        let length = match rib_result {
675            RibInterpreterStackValue::Val(ValueAndType {
676                value: Value::List(items),
677                ..
678            }) => items.len(),
679            RibInterpreterStackValue::Iterator(iter) => iter.count(),
680            _ => bail_corrupted_state!("failed to get the length of the value"),
681        };
682
683        interpreter_stack.push_val(ValueAndType::new(Value::U64(length as u64), u64()));
684        Ok(())
685    }
686
687    pub(crate) fn run_assign_var_instruction(
688        variable_id: VariableId,
689        interpreter_stack: &mut InterpreterStack,
690        interpreter_env: &mut InterpreterEnv,
691    ) -> RibInterpreterResult<()> {
692        let value = interpreter_stack.pop().ok_or_else(empty_stack)?;
693        let env_key = EnvironmentKey::from(variable_id);
694
695        interpreter_env.insert(env_key, value);
696        Ok(())
697    }
698
699    pub(crate) fn run_load_var_instruction(
700        variable_id: VariableId,
701        interpreter_stack: &mut InterpreterStack,
702        interpreter_env: &mut InterpreterEnv,
703    ) -> RibInterpreterResult<()> {
704        let env_key = EnvironmentKey::from(variable_id.clone());
705        let value = interpreter_env
706            .lookup(&env_key)
707            .ok_or_else(|| input_not_found(variable_id.name().as_str()))?;
708
709        match value {
710            RibInterpreterStackValue::Unit => {
711                interpreter_stack.push(RibInterpreterStackValue::Unit);
712            }
713            RibInterpreterStackValue::Val(val) => interpreter_stack.push_val(val.clone()),
714            RibInterpreterStackValue::Iterator(_) => {
715                bail_corrupted_state!("internal error: unable to assign an iterator to a variable")
716            }
717            RibInterpreterStackValue::Sink(_, _) => {
718                bail_corrupted_state!("internal error: unable to assign a sink to a variable")
719            }
720        }
721
722        Ok(())
723    }
724
725    pub(crate) fn run_generate_worker_name(
726        variable_id: Option<VariableId>,
727        interpreter: &mut Interpreter,
728        interpreter_stack: &mut InterpreterStack,
729        interpreter_env: &mut InterpreterEnv,
730    ) -> RibInterpreterResult<()> {
731        match variable_id {
732            None => {
733                let worker_name = interpreter.generate_worker_name.generate_worker_name();
734
735                interpreter_stack
736                    .push_val(ValueAndType::new(Value::String(worker_name.clone()), str()));
737            }
738
739            Some(variable_id) => {
740                let instance_variable = variable_id.as_instance_variable();
741
742                let env_key = EnvironmentKey::from(instance_variable);
743
744                let worker_id = interpreter_env.lookup(&env_key);
745
746                match worker_id {
747                    Some(worker_id) => {
748                        let value_and_type = worker_id.get_val().ok_or_else(|| {
749                            internal_corrupted_state!(
750                        "expected a worker name to be present in the environment, but it was not found"
751                    )
752                        })?;
753
754                        interpreter_stack.push_val(value_and_type);
755                    }
756
757                    None => {
758                        let worker_name = interpreter.generate_worker_name.generate_worker_name();
759
760                        interpreter_stack
761                            .push_val(ValueAndType::new(Value::String(worker_name.clone()), str()));
762                    }
763                }
764            }
765        }
766
767        Ok(())
768    }
769
770    pub(crate) fn run_create_record_instruction(
771        analysed_type: AnalysedType,
772        interpreter_stack: &mut InterpreterStack,
773    ) -> RibInterpreterResult<()> {
774        let name_type_pair = match analysed_type {
775            AnalysedType::Record(type_record) => type_record.fields,
776            _ => {
777                bail_corrupted_state!(
778                    "expected a record type to create a record, but obtained {}",
779                    analysed_type.get_type_hint()
780                )
781            }
782        };
783
784        interpreter_stack.create_record(name_type_pair);
785        Ok(())
786    }
787
788    pub(crate) fn run_update_record_instruction(
789        field_name: String,
790        interpreter_stack: &mut InterpreterStack,
791    ) -> RibInterpreterResult<()> {
792        let (current_record_fields, record_type) = interpreter_stack.try_pop_record()?;
793
794        let idx = record_type
795            .fields
796            .iter()
797            .position(|pair| pair.name == field_name)
798            .ok_or_else(|| {
799                internal_corrupted_state!(
800                    "Invalid field name {field_name}, should be one of {}",
801                    record_type
802                        .fields
803                        .iter()
804                        .map(|pair| pair.name.clone())
805                        .collect::<Vec<_>>()
806                        .join(", ")
807                )
808            })?;
809        let value = interpreter_stack.try_pop_val()?;
810
811        let mut fields = current_record_fields;
812        fields[idx] = value.value;
813
814        interpreter_stack.push_val(ValueAndType {
815            value: Value::Record(fields),
816            typ: AnalysedType::Record(record_type),
817        });
818        Ok(())
819    }
820
821    pub(crate) fn run_push_list_instruction(
822        list_size: usize,
823        analysed_type: AnalysedType,
824        interpreter_stack: &mut InterpreterStack,
825    ) -> RibInterpreterResult<()> {
826        match analysed_type {
827            AnalysedType::List(inner_type) => {
828                let items = interpreter_stack.try_pop_n_val(list_size)?;
829
830                interpreter_stack.push_list(
831                    items.into_iter().map(|vnt| vnt.value).collect(),
832                    inner_type.inner.deref(),
833                );
834
835                Ok(())
836            }
837
838            _ => Err(internal_corrupted_state!(
839                "failed to create list due to mismatch in types. expected: list, actual: {}",
840                analysed_type.get_type_hint()
841            )),
842        }
843    }
844
845    pub(crate) fn run_push_tuple_instruction(
846        list_size: usize,
847        analysed_type: AnalysedType,
848        interpreter_stack: &mut InterpreterStack,
849    ) -> RibInterpreterResult<()> {
850        match analysed_type {
851            AnalysedType::Tuple(_inner_type) => {
852                let items = interpreter_stack.try_pop_n_val(list_size)?;
853                interpreter_stack.push_tuple(items);
854                Ok(())
855            }
856
857            _ => Err(internal_corrupted_state!(
858                "failed to create tuple due to mismatch in types. expected: tuple, actual: {}",
859                analysed_type.get_type_hint()
860            )),
861        }
862    }
863
864    pub(crate) fn run_negate_instruction(
865        interpreter_stack: &mut InterpreterStack,
866    ) -> RibInterpreterResult<()> {
867        let bool = interpreter_stack.try_pop_bool()?;
868        let negated = !bool;
869
870        interpreter_stack.push_val(negated.into_value_and_type());
871        Ok(())
872    }
873
874    pub(crate) fn run_and_instruction(
875        interpreter_stack: &mut InterpreterStack,
876    ) -> RibInterpreterResult<()> {
877        let left = interpreter_stack.try_pop()?;
878        let right = interpreter_stack.try_pop()?;
879
880        let result = left.compare(&right, |a, b| match (a.get_bool(), b.get_bool()) {
881            (Some(a), Some(b)) => a && b,
882            _ => false,
883        })?;
884
885        interpreter_stack.push(result);
886
887        Ok(())
888    }
889
890    pub(crate) fn run_or_instruction(
891        interpreter_stack: &mut InterpreterStack,
892    ) -> RibInterpreterResult<()> {
893        let left = interpreter_stack.try_pop()?;
894        let right = interpreter_stack.try_pop()?;
895
896        let result = left.compare(&right, |a, b| match (a.get_bool(), b.get_bool()) {
897            (Some(a), Some(b)) => a || b,
898            _ => false,
899        })?;
900
901        interpreter_stack.push(result);
902
903        Ok(())
904    }
905
906    pub(crate) fn run_math_instruction(
907        interpreter_stack: &mut InterpreterStack,
908        compare_fn: fn(
909            CoercedNumericValue,
910            CoercedNumericValue,
911        ) -> Result<CoercedNumericValue, RibRuntimeError>,
912        target_numerical_type: &AnalysedType,
913    ) -> RibInterpreterResult<()> {
914        let left = interpreter_stack.try_pop()?;
915        let right = interpreter_stack.try_pop()?;
916
917        let result = left.evaluate_math_op(&right, compare_fn)?;
918        let numerical_type = result
919            .cast_to(target_numerical_type)
920            .ok_or_else(|| cast_error_custom(result, target_numerical_type.get_type_hint()))?;
921
922        interpreter_stack.push_val(numerical_type);
923
924        Ok(())
925    }
926
927    pub(crate) fn run_compare_instruction(
928        interpreter_stack: &mut InterpreterStack,
929        compare_fn: fn(LiteralValue, LiteralValue) -> bool,
930    ) -> RibInterpreterResult<()> {
931        let left = interpreter_stack.try_pop()?;
932        let right = interpreter_stack.try_pop()?;
933
934        let result = left.compare(&right, compare_fn)?;
935
936        interpreter_stack.push(result);
937
938        Ok(())
939    }
940
941    // Kept for backward compatibility with byte code
942    pub(crate) fn run_select_field_instruction(
943        field_name: String,
944        interpreter_stack: &mut InterpreterStack,
945    ) -> RibInterpreterResult<()> {
946        let record = interpreter_stack.try_pop()?;
947
948        match record {
949            RibInterpreterStackValue::Val(ValueAndType {
950                value: Value::Record(field_values),
951                typ: AnalysedType::Record(typ),
952            }) => {
953                let field = field_values
954                    .into_iter()
955                    .zip(typ.fields)
956                    .find(|(_value, field)| field.name == field_name)
957                    .ok_or_else(|| field_not_found(field_name.as_str()))?;
958
959                let value = field.0;
960                interpreter_stack.push_val(ValueAndType::new(value, field.1.typ));
961                Ok(())
962            }
963            _ => Err(field_not_found(field_name.as_str())),
964        }
965    }
966
967    pub(crate) fn run_select_index_v1_instruction(
968        interpreter_stack: &mut InterpreterStack,
969    ) -> RibInterpreterResult<()> {
970        let stack_list_value = interpreter_stack.pop().ok_or_else(empty_stack)?;
971
972        let index_value = interpreter_stack.pop().ok_or(empty_stack())?;
973
974        match stack_list_value {
975            RibInterpreterStackValue::Val(ValueAndType {
976                value: Value::List(items),
977                typ: AnalysedType::List(typ),
978            }) => match index_value.get_literal().and_then(|v| v.get_number()) {
979                Some(CoercedNumericValue::PosInt(index)) => {
980                    let value = items
981                        .get(index as usize)
982                        .ok_or_else(|| index_out_of_bound(index as usize, items.len()))?
983                        .clone();
984
985                    interpreter_stack.push_val(ValueAndType::new(value, (*typ.inner).clone()));
986                    Ok(())
987                }
988                Some(CoercedNumericValue::NegInt(index)) => {
989                    if index >= 0 {
990                        let value = items
991                            .get(index as usize)
992                            .ok_or_else(|| index_out_of_bound(index as usize, items.len()))?
993                            .clone();
994
995                        interpreter_stack.push_val(ValueAndType::new(value, (*typ.inner).clone()));
996                    } else {
997                        return Err(index_out_of_bound(index as usize, items.len()));
998                    }
999                    Ok(())
1000                }
1001
1002                _ => Err(internal_corrupted_state!("failed range selection")),
1003            },
1004            RibInterpreterStackValue::Val(ValueAndType {
1005                value: Value::Tuple(items),
1006                typ: AnalysedType::Tuple(typ),
1007            }) => match index_value.get_literal().and_then(|v| v.get_number()) {
1008                Some(CoercedNumericValue::PosInt(index)) => {
1009                    let value = items
1010                        .get(index as usize)
1011                        .ok_or_else(|| index_out_of_bound(index as usize, items.len()))?
1012                        .clone();
1013
1014                    let item_type = typ
1015                        .items
1016                        .get(index as usize)
1017                        .ok_or_else(|| {
1018                            internal_corrupted_state!(
1019                                "type not found in the tuple at index {}",
1020                                index
1021                            )
1022                        })?
1023                        .clone();
1024
1025                    interpreter_stack.push_val(ValueAndType::new(value, item_type));
1026                    Ok(())
1027                }
1028                _ => Err(invalid_type_with_stack_value(
1029                    vec![TypeHint::Number],
1030                    index_value,
1031                )),
1032            },
1033            result => Err(invalid_type_with_stack_value(
1034                vec![TypeHint::List(None), TypeHint::Tuple(None)],
1035                result,
1036            )),
1037        }
1038    }
1039
1040    pub(crate) fn run_select_index_instruction(
1041        interpreter_stack: &mut InterpreterStack,
1042        index: usize,
1043    ) -> RibInterpreterResult<()> {
1044        let stack_value = interpreter_stack.pop().ok_or_else(empty_stack)?;
1045
1046        match stack_value {
1047            RibInterpreterStackValue::Val(ValueAndType {
1048                value: Value::List(items),
1049                typ: AnalysedType::List(typ),
1050            }) => {
1051                let value = items
1052                    .get(index)
1053                    .ok_or_else(|| index_out_of_bound(index, items.len()))?
1054                    .clone();
1055
1056                interpreter_stack.push_val(ValueAndType::new(value, (*typ.inner).clone()));
1057                Ok(())
1058            }
1059            RibInterpreterStackValue::Val(ValueAndType {
1060                value: Value::Tuple(items),
1061                typ: AnalysedType::Tuple(typ),
1062            }) => {
1063                let value = items
1064                    .get(index)
1065                    .ok_or_else(|| index_out_of_bound(index, items.len()))?
1066                    .clone();
1067
1068                let item_type = typ
1069                    .items
1070                    .get(index)
1071                    .ok_or_else(|| index_out_of_bound(index, items.len()))?
1072                    .clone();
1073
1074                interpreter_stack.push_val(ValueAndType::new(value, item_type));
1075                Ok(())
1076            }
1077            result => Err(invalid_type_with_stack_value(
1078                vec![TypeHint::List(None), TypeHint::Tuple(None)],
1079                result,
1080            )),
1081        }
1082    }
1083
1084    pub(crate) fn run_push_enum_instruction(
1085        interpreter_stack: &mut InterpreterStack,
1086        enum_name: String,
1087        analysed_type: AnalysedType,
1088    ) -> RibInterpreterResult<()> {
1089        match analysed_type {
1090            AnalysedType::Enum(typed_enum) => {
1091                interpreter_stack.push_enum(enum_name, typed_enum.cases)?;
1092                Ok(())
1093            }
1094            _ => Err(type_mismatch_with_type_hint(
1095                vec![TypeHint::Enum(None)],
1096                analysed_type.get_type_hint(),
1097            )),
1098        }
1099    }
1100
1101    pub(crate) async fn run_variant_construction_instruction(
1102        variant_name: String,
1103        analysed_type: AnalysedType,
1104        interpreter_stack: &mut InterpreterStack,
1105    ) -> RibInterpreterResult<()> {
1106        match analysed_type {
1107            AnalysedType::Variant(variants) => {
1108                let variant = variants
1109                    .cases
1110                    .iter()
1111                    .find(|name| name.name == variant_name)
1112                    .ok_or_else(|| {
1113                        internal_corrupted_state!("variant {} not found", variant_name)
1114                    })?;
1115
1116                let variant_arg_typ = variant.typ.clone();
1117
1118                let arg_value = match variant_arg_typ {
1119                    Some(_) => Some(interpreter_stack.try_pop_val()?),
1120                    None => None,
1121                };
1122
1123                interpreter_stack.push_variant(
1124                    variant_name.clone(),
1125                    arg_value.map(|vnt| vnt.value),
1126                    variants.cases.clone(),
1127                )
1128            }
1129
1130            _ => Err(type_mismatch_with_type_hint(
1131                vec![TypeHint::Variant(None)],
1132                analysed_type.get_type_hint(),
1133            )),
1134        }
1135    }
1136
1137    pub(crate) fn run_create_function_name_instruction(
1138        site: ParsedFunctionSite,
1139        function_type: FunctionReferenceType,
1140        interpreter_stack: &mut InterpreterStack,
1141    ) -> RibInterpreterResult<()> {
1142        match function_type {
1143            FunctionReferenceType::Function { function } => {
1144                let parsed_function_name = ParsedFunctionName {
1145                    site,
1146                    function: ParsedFunctionReference::Function { function },
1147                };
1148
1149                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1150            }
1151
1152            FunctionReferenceType::RawResourceConstructor { resource } => {
1153                let parsed_function_name = ParsedFunctionName {
1154                    site,
1155                    function: ParsedFunctionReference::RawResourceConstructor { resource },
1156                };
1157
1158                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1159            }
1160            FunctionReferenceType::RawResourceDrop { resource } => {
1161                let parsed_function_name = ParsedFunctionName {
1162                    site,
1163                    function: ParsedFunctionReference::RawResourceDrop { resource },
1164                };
1165
1166                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1167            }
1168            FunctionReferenceType::RawResourceMethod { resource, method } => {
1169                let parsed_function_name = ParsedFunctionName {
1170                    site,
1171                    function: ParsedFunctionReference::RawResourceMethod { resource, method },
1172                };
1173
1174                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1175            }
1176            FunctionReferenceType::RawResourceStaticMethod { resource, method } => {
1177                let parsed_function_name = ParsedFunctionName {
1178                    site,
1179                    function: ParsedFunctionReference::RawResourceStaticMethod { resource, method },
1180                };
1181
1182                interpreter_stack.push_val(parsed_function_name.to_string().into_value_and_type());
1183            }
1184        }
1185
1186        Ok(())
1187    }
1188
1189    pub(crate) async fn run_invoke_function_instruction(
1190        component_info: ComponentDependencyKey,
1191        instruction_id: &InstructionId,
1192        arg_size: usize,
1193        instance_variable_type: InstanceVariable,
1194        interpreter_stack: &mut InterpreterStack,
1195        interpreter_env: &mut InterpreterEnv,
1196        expected_result_type: AnalysedTypeWithUnit,
1197    ) -> RibInterpreterResult<()> {
1198        let function_name = interpreter_stack
1199            .pop_str()
1200            .ok_or_else(|| internal_corrupted_state!("failed to get a function name"))?;
1201
1202        let function_name_cloned = function_name.clone();
1203
1204        let last_n_elements = interpreter_stack
1205            .pop_n(arg_size)
1206            .ok_or_else(|| insufficient_stack_items(arg_size))?;
1207
1208        let expected_result_type = match expected_result_type {
1209            AnalysedTypeWithUnit::Type(analysed_type) => Some(analysed_type),
1210            AnalysedTypeWithUnit::Unit => None,
1211        };
1212
1213        let parameter_values = last_n_elements
1214            .iter()
1215            .map(|interpreter_result| {
1216                interpreter_result.get_val().ok_or_else(|| {
1217                    internal_corrupted_state!("failed to call function {}", function_name)
1218                })
1219            })
1220            .collect::<RibInterpreterResult<Vec<ValueAndType>>>()?;
1221
1222        match instance_variable_type {
1223            InstanceVariable::WitWorker(variable_id) => {
1224                let worker_id = interpreter_env
1225                    .lookup(&EnvironmentKey::from(variable_id.clone()))
1226                    .map(|x| {
1227                        x.get_val().ok_or_else(|| {
1228                            internal_corrupted_state!(
1229                                "failed to get a worker variable id for function {}",
1230                                function_name
1231                            )
1232                        })
1233                    })
1234                    .transpose()?
1235                    .ok_or_else(|| {
1236                        internal_corrupted_state!(
1237                            "failed to find a worker with id {}",
1238                            variable_id.name()
1239                        )
1240                    })?;
1241
1242                let worker_id_string =
1243                    worker_id
1244                        .get_literal()
1245                        .map(|v| v.as_string())
1246                        .ok_or_else(|| {
1247                            internal_corrupted_state!("failed to get a worker name for variable")
1248                        })?;
1249
1250                let result = interpreter_env
1251                    .invoke_worker_function_async(
1252                        component_info,
1253                        instruction_id,
1254                        worker_id_string,
1255                        function_name_cloned,
1256                        parameter_values,
1257                        expected_result_type.clone(),
1258                    )
1259                    .await
1260                    .map_err(|err| function_invoke_fail(function_name.as_str(), err))?;
1261
1262                match result {
1263                    None => {
1264                        interpreter_stack.push(RibInterpreterStackValue::Unit);
1265                    }
1266                    Some(result) => {
1267                        interpreter_stack.push(RibInterpreterStackValue::Val(result));
1268                    }
1269                }
1270            }
1271
1272            InstanceVariable::WitResource(variable_id)
1273                if variable_id == VariableId::global("___STATIC_WIT_RESOURCE".to_string()) =>
1274            {
1275                let result = interpreter_env
1276                    .invoke_worker_function_async(
1277                        component_info,
1278                        instruction_id,
1279                        "___STATIC_WIT_RESOURCE".to_string(),
1280                        function_name_cloned,
1281                        parameter_values,
1282                        expected_result_type.clone(),
1283                    )
1284                    .await
1285                    .map_err(|err| function_invoke_fail(function_name.as_str(), err))?;
1286
1287                match result {
1288                    None => {
1289                        interpreter_stack.push(RibInterpreterStackValue::Unit);
1290                    }
1291                    Some(result) => {
1292                        interpreter_stack.push(RibInterpreterStackValue::Val(result));
1293                    }
1294                }
1295            }
1296
1297            InstanceVariable::WitResource(variable_id) => {
1298                let mut final_args = vec![];
1299
1300                let handle = interpreter_env
1301                    .lookup(&EnvironmentKey::from(variable_id.clone()))
1302                    .map(|x| {
1303                        x.get_val().ok_or_else(|| {
1304                            internal_corrupted_state!(
1305                                "failed to get a resource with id {}",
1306                                variable_id.name()
1307                            )
1308                        })
1309                    })
1310                    .transpose()?
1311                    .ok_or_else(|| {
1312                        internal_corrupted_state!(
1313                            "failed to find a resource with id {}",
1314                            variable_id.name()
1315                        )
1316                    })?;
1317
1318                match &handle.value {
1319                    Value::Handle { uri, .. } => {
1320                        let worker_name = uri.rsplit_once('/').map(|(_, last)| last).unwrap_or(uri);
1321
1322                        final_args.push(handle.clone());
1323                        final_args.extend(parameter_values);
1324
1325                        let result = interpreter_env
1326                            .invoke_worker_function_async(
1327                                component_info,
1328                                instruction_id,
1329                                worker_name.to_string(),
1330                                function_name_cloned.clone(),
1331                                final_args,
1332                                expected_result_type.clone(),
1333                            )
1334                            .await
1335                            .map_err(|err| function_invoke_fail(function_name.as_str(), err))?;
1336
1337                        match result {
1338                            None => {
1339                                interpreter_stack.push(RibInterpreterStackValue::Unit);
1340                            }
1341                            Some(result) => {
1342                                interpreter_stack.push(RibInterpreterStackValue::Val(result));
1343                            }
1344                        }
1345                    }
1346
1347                    _ => {
1348                        return Err(function_invoke_fail(
1349                            function_name.as_str(),
1350                            "expected the result of a resource construction to be of type `handle`"
1351                                .into(),
1352                        ))
1353                    }
1354                };
1355            }
1356        };
1357
1358        Ok(())
1359    }
1360
1361    pub(crate) fn run_deconstruct_instruction(
1362        interpreter_stack: &mut InterpreterStack,
1363    ) -> RibInterpreterResult<()> {
1364        let value = interpreter_stack
1365            .pop()
1366            .ok_or_else(|| internal_corrupted_state!("no value to unwrap"))?;
1367
1368        let unwrapped_value = value
1369            .unwrap()
1370            .ok_or_else(|| internal_corrupted_state!("failed to unwrap the value {}", value))?;
1371
1372        interpreter_stack.push_val(unwrapped_value);
1373        Ok(())
1374    }
1375
1376    pub(crate) fn run_get_tag_instruction(
1377        interpreter_stack: &mut InterpreterStack,
1378    ) -> RibInterpreterResult<()> {
1379        let value = interpreter_stack
1380            .pop_val()
1381            .ok_or_else(|| internal_corrupted_state!("failed to get a tag value"))?;
1382
1383        let tag = match value {
1384            ValueAndType {
1385                value: Value::Variant { case_idx, .. },
1386                typ: AnalysedType::Variant(typ),
1387            } => typ.cases[case_idx as usize].name.clone(),
1388            ValueAndType {
1389                value: Value::Option(option),
1390                ..
1391            } => match option {
1392                Some(_) => "some".to_string(),
1393                None => "none".to_string(),
1394            },
1395            ValueAndType {
1396                value: Value::Result(result_value),
1397                ..
1398            } => match result_value {
1399                Ok(_) => "ok".to_string(),
1400                Err(_) => "err".to_string(),
1401            },
1402            ValueAndType {
1403                value: Value::Enum(idx),
1404                typ: AnalysedType::Enum(typ),
1405            } => typ.cases[idx as usize].clone(),
1406            _ => "untagged".to_string(),
1407        };
1408
1409        interpreter_stack.push_val(tag.into_value_and_type());
1410        Ok(())
1411    }
1412
1413    pub(crate) fn run_create_some_instruction(
1414        interpreter_stack: &mut InterpreterStack,
1415        analysed_type: AnalysedType,
1416    ) -> RibInterpreterResult<()> {
1417        let value = interpreter_stack.try_pop_val()?;
1418
1419        match analysed_type {
1420            AnalysedType::Option(analysed_type) => {
1421                interpreter_stack.push_some(value.value, analysed_type.inner.deref());
1422                Ok(())
1423            }
1424            _ => Err(type_mismatch_with_type_hint(
1425                vec![TypeHint::Option(None)],
1426                analysed_type.get_type_hint(),
1427            )),
1428        }
1429    }
1430
1431    pub(crate) fn run_create_none_instruction(
1432        interpreter_stack: &mut InterpreterStack,
1433        analysed_type: Option<AnalysedType>,
1434    ) -> RibInterpreterResult<()> {
1435        match analysed_type {
1436            Some(AnalysedType::Option(_)) | None => {
1437                interpreter_stack.push_none(analysed_type);
1438                Ok(())
1439            }
1440            _ => Err(type_mismatch_with_type_hint(
1441                vec![TypeHint::Option(None)],
1442                analysed_type
1443                    .as_ref()
1444                    .map(|t| t.get_type_hint())
1445                    .unwrap_or_else(|| TypeHint::Unknown),
1446            )),
1447        }
1448    }
1449
1450    pub(crate) fn run_create_ok_instruction(
1451        interpreter_stack: &mut InterpreterStack,
1452        analysed_type: AnalysedType,
1453    ) -> RibInterpreterResult<()> {
1454        let value = interpreter_stack.try_pop_val()?;
1455
1456        match analysed_type {
1457            AnalysedType::Result(TypeResult { ok, err, .. }) => {
1458                interpreter_stack.push_ok(value.value, ok.as_deref(), err.as_deref());
1459                Ok(())
1460            }
1461            _ => Err(type_mismatch_with_type_hint(
1462                vec![TypeHint::Result {
1463                    ok: None,
1464                    err: None,
1465                }],
1466                analysed_type.get_type_hint(),
1467            )),
1468        }
1469    }
1470
1471    pub(crate) fn run_create_err_instruction(
1472        interpreter_stack: &mut InterpreterStack,
1473        analysed_type: AnalysedType,
1474    ) -> RibInterpreterResult<()> {
1475        let value = interpreter_stack.try_pop_val()?;
1476
1477        match analysed_type {
1478            AnalysedType::Result(TypeResult { ok, err, .. }) => {
1479                interpreter_stack.push_err(value.value, ok.as_deref(), err.as_deref());
1480                Ok(())
1481            }
1482            _ => Err(type_mismatch_with_type_hint(
1483                vec![TypeHint::Result {
1484                    ok: None,
1485                    err: None,
1486                }],
1487                analysed_type.get_type_hint(),
1488            )),
1489        }
1490    }
1491
1492    pub(crate) fn run_concat_instruction(
1493        interpreter_stack: &mut InterpreterStack,
1494        arg_size: usize,
1495    ) -> RibInterpreterResult<()> {
1496        let value_and_types = interpreter_stack.try_pop_n_val(arg_size)?;
1497
1498        let mut result = String::new();
1499
1500        for val in value_and_types {
1501            match &val.value {
1502                Value::String(s) => {
1503                    // Avoid extra quotes when concatenating strings
1504                    result.push_str(s);
1505                }
1506                Value::Char(char) => {
1507                    // Avoid extra single quotes when concatenating chars
1508                    result.push(*char);
1509                }
1510                _ => {
1511                    result.push_str(&val.to_string());
1512                }
1513            }
1514        }
1515
1516        interpreter_stack.push_val(result.into_value_and_type());
1517
1518        Ok(())
1519    }
1520}
1521
1522#[cfg(test)]
1523mod tests {
1524    use std::collections::HashMap;
1525    use test_r::test;
1526
1527    use super::*;
1528    use crate::interpreter::rib_interpreter::tests::test_utils::{
1529        get_analysed_type_variant, get_value_and_type, strip_spaces, RibTestDeps,
1530    };
1531    use crate::{
1532        CustomInstanceSpec, Expr, GlobalVariableTypeSpec, InferredType, InstructionId,
1533        InterfaceName, Path, RibCompiler, RibCompilerConfig, VariableId,
1534    };
1535    use golem_wasm_ast::analysis::analysed_type::{
1536        bool, case, f32, field, list, option, r#enum, record, result, result_err, result_ok, s32,
1537        str, tuple, u32, u64, u8, unit_case, variant,
1538    };
1539    use golem_wasm_ast::analysis::AnalysedType;
1540    use golem_wasm_rpc::{IntoValue, IntoValueAndType, Value, ValueAndType};
1541
1542    #[test]
1543    async fn test_interpreter_for_literal() {
1544        let mut interpreter = Interpreter::default();
1545
1546        let instructions = RibByteCode {
1547            instructions: vec![RibIR::PushLit(1i32.into_value_and_type())],
1548        };
1549
1550        let result = interpreter.run(instructions).await.unwrap();
1551        assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1552    }
1553
1554    #[test]
1555    async fn test_interpreter_for_equal_to() {
1556        let mut interpreter = Interpreter::default();
1557
1558        let instructions = RibByteCode {
1559            instructions: vec![
1560                RibIR::PushLit(1i32.into_value_and_type()),
1561                RibIR::PushLit(1u32.into_value_and_type()),
1562                RibIR::EqualTo,
1563            ],
1564        };
1565
1566        let result = interpreter.run(instructions).await.unwrap();
1567        assert!(result.get_bool().unwrap());
1568    }
1569
1570    #[test]
1571    async fn test_interpreter_for_greater_than() {
1572        let mut interpreter = Interpreter::default();
1573
1574        let instructions = RibByteCode {
1575            instructions: vec![
1576                RibIR::PushLit(1i32.into_value_and_type()),
1577                RibIR::PushLit(2u32.into_value_and_type()),
1578                RibIR::GreaterThan,
1579            ],
1580        };
1581
1582        let result = interpreter.run(instructions).await.unwrap();
1583        assert!(result.get_bool().unwrap());
1584    }
1585
1586    #[test]
1587    async fn test_interpreter_for_less_than() {
1588        let mut interpreter = Interpreter::default();
1589
1590        let instructions = RibByteCode {
1591            instructions: vec![
1592                RibIR::PushLit(2i32.into_value_and_type()),
1593                RibIR::PushLit(1u32.into_value_and_type()),
1594                RibIR::LessThan,
1595            ],
1596        };
1597
1598        let result = interpreter.run(instructions).await.unwrap();
1599        assert!(result.get_bool().unwrap());
1600    }
1601
1602    #[test]
1603    async fn test_interpreter_for_greater_than_or_equal_to() {
1604        let mut interpreter = Interpreter::default();
1605
1606        let instructions = RibByteCode {
1607            instructions: vec![
1608                RibIR::PushLit(2i32.into_value_and_type()),
1609                RibIR::PushLit(3u32.into_value_and_type()),
1610                RibIR::GreaterThanOrEqualTo,
1611            ],
1612        };
1613
1614        let result = interpreter.run(instructions).await.unwrap();
1615        assert!(result.get_bool().unwrap());
1616    }
1617
1618    #[test]
1619    async fn test_interpreter_for_less_than_or_equal_to() {
1620        let mut interpreter = Interpreter::default();
1621
1622        let instructions = RibByteCode {
1623            instructions: vec![
1624                RibIR::PushLit(2i32.into_value_and_type()), // rhs
1625                RibIR::PushLit(1i32.into_value_and_type()), // lhs
1626                RibIR::LessThanOrEqualTo,
1627            ],
1628        };
1629
1630        let result = interpreter.run(instructions).await.unwrap();
1631        assert!(result.get_bool().unwrap());
1632    }
1633
1634    #[test]
1635    async fn test_interpreter_for_assign_and_load_var() {
1636        let mut interpreter = Interpreter::default();
1637
1638        let instructions = RibByteCode {
1639            instructions: vec![
1640                RibIR::PushLit(1i32.into_value_and_type()),
1641                RibIR::AssignVar(VariableId::local_with_no_id("x")),
1642                RibIR::LoadVar(VariableId::local_with_no_id("x")),
1643            ],
1644        };
1645
1646        let result = interpreter.run(instructions).await.unwrap();
1647        assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1648    }
1649
1650    #[test]
1651    async fn test_interpreter_for_jump() {
1652        let mut interpreter = Interpreter::default();
1653
1654        let instructions = RibByteCode {
1655            instructions: vec![
1656                RibIR::Jump(InstructionId::init()),
1657                RibIR::PushLit(1i32.into_value_and_type()),
1658                RibIR::Label(InstructionId::init()),
1659            ],
1660        };
1661
1662        let result = interpreter.run(instructions).await;
1663        assert!(result.is_ok());
1664    }
1665
1666    #[test]
1667    async fn test_interpreter_for_jump_if_false() {
1668        let mut interpreter = Interpreter::default();
1669
1670        let id = InstructionId::init().increment_mut();
1671
1672        let instructions = RibByteCode {
1673            instructions: vec![
1674                RibIR::PushLit(false.into_value_and_type()),
1675                RibIR::JumpIfFalse(id.clone()),
1676                RibIR::PushLit(1i32.into_value_and_type()),
1677                RibIR::Label(id),
1678            ],
1679        };
1680
1681        let result = interpreter.run(instructions).await;
1682        assert!(result.is_ok());
1683    }
1684
1685    #[test]
1686    async fn test_interpreter_for_record() {
1687        let mut interpreter = Interpreter::default();
1688
1689        let instructions = RibByteCode {
1690            instructions: vec![
1691                RibIR::PushLit(2i32.into_value_and_type()),
1692                RibIR::PushLit(1i32.into_value_and_type()),
1693                RibIR::CreateAndPushRecord(record(vec![field("x", s32()), field("y", s32())])),
1694                RibIR::UpdateRecord("x".to_string()),
1695                RibIR::UpdateRecord("y".to_string()),
1696            ],
1697        };
1698
1699        let result = interpreter.run(instructions).await.unwrap();
1700        let expected = ValueAndType::new(
1701            Value::Record(vec![1i32.into_value(), 2i32.into_value()]),
1702            record(vec![field("x", s32()), field("y", s32())]),
1703        );
1704
1705        assert_eq!(result.get_val().unwrap(), expected);
1706    }
1707
1708    #[test]
1709    async fn test_interpreter_for_sequence() {
1710        let mut interpreter = Interpreter::default();
1711
1712        let instructions = RibByteCode {
1713            instructions: vec![
1714                RibIR::PushLit(2i32.into_value_and_type()),
1715                RibIR::PushLit(1i32.into_value_and_type()),
1716                RibIR::PushList(list(s32()), 2),
1717            ],
1718        };
1719
1720        let result = interpreter.run(instructions).await.unwrap();
1721        let expected = ValueAndType::new(
1722            Value::List(vec![1i32.into_value(), 2i32.into_value()]),
1723            list(s32()),
1724        );
1725        assert_eq!(result.get_val().unwrap(), expected);
1726    }
1727
1728    #[test]
1729    async fn test_interpreter_for_select_field() {
1730        let mut interpreter = Interpreter::default();
1731
1732        let instructions = RibByteCode {
1733            instructions: vec![
1734                RibIR::PushLit(1i32.into_value_and_type()),
1735                RibIR::PushLit(2i32.into_value_and_type()),
1736                RibIR::CreateAndPushRecord(record(vec![field("x", s32())])),
1737                RibIR::UpdateRecord("x".to_string()),
1738                RibIR::SelectField("x".to_string()),
1739            ],
1740        };
1741
1742        let result = interpreter.run(instructions).await.unwrap();
1743        assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1744    }
1745
1746    #[test]
1747    async fn test_interpreter_for_select_index() {
1748        let mut interpreter = Interpreter::default();
1749
1750        let instructions = RibByteCode {
1751            instructions: vec![
1752                RibIR::PushLit(1i32.into_value_and_type()),
1753                RibIR::PushLit(2i32.into_value_and_type()),
1754                RibIR::PushList(list(s32()), 2),
1755                RibIR::SelectIndex(0),
1756            ],
1757        };
1758
1759        let result = interpreter.run(instructions).await.unwrap();
1760        assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1761    }
1762
1763    #[test]
1764    async fn test_interpreter_variable_scope_0() {
1765        let rib_expr = r#"
1766               let x = 1;
1767               let y = x + 2;
1768               y
1769            "#;
1770
1771        let expr = Expr::from_text(rib_expr).unwrap();
1772
1773        let mut interpreter = Interpreter::default();
1774
1775        let compiler = RibCompiler::default();
1776
1777        let compiled = compiler.compile(expr).unwrap();
1778
1779        let result = interpreter.run(compiled.byte_code).await.unwrap();
1780
1781        assert_eq!(result.get_val().unwrap(), 3i32.into_value_and_type());
1782    }
1783
1784    #[test]
1785    async fn test_interpreter_variable_scope_1() {
1786        let rib_expr = r#"
1787               let x = 1;
1788               let z = {foo : x};
1789               let x = x + 2u64;
1790               { bar: x, baz: z }
1791            "#;
1792
1793        let expr = Expr::from_text(rib_expr).unwrap();
1794
1795        let mut interpreter = Interpreter::default();
1796
1797        let compiler = RibCompiler::default();
1798        let compiled = compiler.compile(expr).unwrap();
1799
1800        let result = interpreter.run(compiled.byte_code).await.unwrap();
1801
1802        let analysed_type = record(vec![
1803            field("bar", u64()),
1804            field("baz", record(vec![field("foo", u64())])),
1805        ]);
1806
1807        let expected = get_value_and_type(&analysed_type, r#"{ bar: 3, baz: { foo: 1 } }"#);
1808
1809        assert_eq!(result.get_val().unwrap(), expected);
1810    }
1811
1812    #[test]
1813    async fn test_interpreter_variable_scope_2() {
1814        let rib_expr = r#"
1815               let x = 1;
1816               let x = x;
1817
1818               let result1 = match some(x + 1) {
1819                  some(x) => x,
1820                  none => x
1821               };
1822
1823               let z: option<u64> = none;
1824
1825               let result2 = match z {
1826                  some(x) => x,
1827                  none => x
1828               };
1829
1830               { result1: result1, result2: result2 }
1831            "#;
1832
1833        let expr = Expr::from_text(rib_expr).unwrap();
1834
1835        let mut interpreter = Interpreter::default();
1836
1837        let compiler = RibCompiler::default();
1838
1839        let compiled = compiler.compile(expr).unwrap();
1840
1841        let result = interpreter.run(compiled.byte_code).await.unwrap();
1842
1843        let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1844
1845        let expected = get_value_and_type(&analysed_type, r#"{ result1: 2, result2: 1 }"#);
1846
1847        assert_eq!(result.get_val().unwrap(), expected);
1848    }
1849
1850    #[test]
1851    async fn test_interpreter_variable_scope_3() {
1852        let rib_expr = r#"
1853               let x = 1;
1854               let x = x;
1855
1856               let result1 = match some(x + 1) {
1857                  some(x) => match some(x + 1) {
1858                     some(x) => x,
1859                     none => x
1860                  },
1861                  none => x
1862               };
1863
1864               let z: option<u64> = none;
1865
1866               let result2 = match z {
1867                  some(x) => x,
1868                  none => match some(x + 1) {
1869                     some(x) => x,
1870                     none => x
1871                  }
1872               };
1873
1874               { result1: result1, result2: result2 }
1875            "#;
1876
1877        let expr = Expr::from_text(rib_expr).unwrap();
1878
1879        let mut interpreter = Interpreter::default();
1880
1881        let compiler = RibCompiler::default();
1882
1883        let compiled = compiler.compile(expr).unwrap();
1884
1885        let result = interpreter.run(compiled.byte_code).await.unwrap();
1886
1887        let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1888
1889        let expected = get_value_and_type(&analysed_type, r#"{ result1: 3, result2: 2 }"#);
1890
1891        assert_eq!(result.get_val().unwrap(), expected);
1892    }
1893
1894    #[test]
1895    async fn test_interpreter_global_variable_with_type_spec() {
1896        // request.path.user-id and request.headers.* should be inferred as string,
1897        // since we configure the compiler with a type-spec (given below)
1898        let rib_expr = r#"
1899               let res1 = request.path.user-id;
1900               let res2 = request.headers.name;
1901               let res3 = request.headers.age;
1902               "${res1}-${res2}-${res3}"
1903            "#;
1904
1905        let type_spec = vec![
1906            GlobalVariableTypeSpec::new(
1907                "request",
1908                Path::from_elems(vec!["path"]),
1909                InferredType::string(),
1910            ),
1911            GlobalVariableTypeSpec::new(
1912                "request",
1913                Path::from_elems(vec!["headers"]),
1914                InferredType::string(),
1915            ),
1916        ];
1917
1918        let mut rib_input = HashMap::new();
1919
1920        // Rib compiler identifies the input requirements to be a string (due to type-spec passed)
1921        // and therefore, we pass input value (value_and_type) to the interpreter with headers and path values as string
1922        let analysed_type_of_input = &record(vec![
1923            field("path", record(vec![field("user-id", str())])),
1924            field(
1925                "headers",
1926                record(vec![field("name", str()), field("age", str())]),
1927            ),
1928        ]);
1929
1930        let value_and_type = get_value_and_type(
1931            analysed_type_of_input,
1932            r#"{path : { user-id: "1" }, headers: { name: "foo", age: "20" }}"#,
1933        );
1934
1935        rib_input.insert("request".to_string(), value_and_type);
1936
1937        let mut interpreter =
1938            test_utils::interpreter_with_noop_function_invoke(Some(RibInput::new(rib_input)));
1939
1940        let expr = Expr::from_text(rib_expr).unwrap();
1941
1942        let compiler = RibCompiler::new(RibCompilerConfig::new(vec![], type_spec, vec![]));
1943        let compiled = compiler.compile(expr).unwrap();
1944
1945        let result = interpreter
1946            .run(compiled.byte_code)
1947            .await
1948            .unwrap()
1949            .get_val()
1950            .unwrap()
1951            .value;
1952
1953        assert_eq!(result, Value::String("1-foo-20".to_string()))
1954    }
1955
1956    #[test]
1957    async fn test_interpreter_global_variable_override_type_spec() {
1958        let rib_expr = r#"
1959             let res1: u32 = request.path.user-id;
1960             let res2 = request.headers.name;
1961             let res3: u32 = request.headers.age;
1962             let res4 = res1 + res3;
1963             "${res4}-${res2}"
1964            "#;
1965
1966        // We always specify the type of request.path.* and request.headers.* to be a string using type-spec
1967        // however the rib script (above) explicitly specify the type of request.path.user-id
1968        // and request.header.age to be u32. In this case, the Rib compiler infer them as u32 and interpreter works with u32.
1969        let type_spec = vec![
1970            GlobalVariableTypeSpec::new(
1971                "request",
1972                Path::from_elems(vec!["path"]),
1973                InferredType::string(),
1974            ),
1975            GlobalVariableTypeSpec::new(
1976                "request",
1977                Path::from_elems(vec!["headers"]),
1978                InferredType::string(),
1979            ),
1980        ];
1981
1982        let mut rib_input = HashMap::new();
1983
1984        // We pass the input value to rib-interpreter with request.path.user-id
1985        // and request.headers.age as u32, since the compiler inferred these input type requirements to be u32.
1986        let analysed_type_of_input = &record(vec![
1987            field("path", record(vec![field("user-id", u32())])),
1988            field(
1989                "headers",
1990                record(vec![field("name", str()), field("age", u32())]),
1991            ),
1992        ]);
1993
1994        let value_and_type = get_value_and_type(
1995            analysed_type_of_input,
1996            r#"{path : { user-id: 1 }, headers: { name: "foo", age: 20 }}"#,
1997        );
1998
1999        rib_input.insert("request".to_string(), value_and_type);
2000
2001        let mut interpreter =
2002            test_utils::interpreter_with_noop_function_invoke(Some(RibInput::new(rib_input)));
2003
2004        let expr = Expr::from_text(rib_expr).unwrap();
2005
2006        let compiler = RibCompiler::new(RibCompilerConfig::new(vec![], type_spec, vec![]));
2007
2008        let compiled = compiler.compile(expr).unwrap();
2009
2010        let result = interpreter
2011            .run(compiled.byte_code)
2012            .await
2013            .unwrap()
2014            .get_val()
2015            .unwrap()
2016            .value;
2017
2018        assert_eq!(result, Value::String("21-foo".to_string()))
2019    }
2020
2021    #[test]
2022    async fn test_interpreter_concatenation() {
2023        let mut interpreter = Interpreter::default();
2024
2025        let rib_expr = r#"
2026            let x = "foo";
2027            let y = "bar";
2028            let z = {foo: "baz"};
2029            let n: u32 = 42;
2030            let result = "${x}-${y}-${z}-${n}";
2031            result
2032        "#;
2033
2034        let expr = Expr::from_text(rib_expr).unwrap();
2035
2036        let compiler = RibCompiler::default();
2037
2038        let compiled = compiler.compile(expr).unwrap();
2039
2040        let result = interpreter.run(compiled.byte_code).await.unwrap();
2041
2042        assert_eq!(
2043            result.get_val().unwrap().value,
2044            Value::String("foo-bar-{foo: \"baz\"}-42".to_string())
2045        );
2046    }
2047
2048    #[test]
2049    async fn test_interpreter_with_variant_and_enum() {
2050        let test_deps = RibTestDeps::test_deps_with_global_functions();
2051
2052        let compiler = RibCompiler::new(RibCompilerConfig::new(
2053            test_deps.component_dependencies.clone(),
2054            vec![],
2055            vec![],
2056        ));
2057
2058        let mut interpreter = test_deps.interpreter;
2059
2060        // This has intentionally got conflicting variable names
2061        // variable `x` is same as the enum name `x`
2062        // similarly, variably `validate` is same as the variant name validate
2063        let expr = r#"
2064          let x = x;
2065          let y = x;
2066          let a = instance();
2067          let result1 = a.add-enum(x, y);
2068          let validate = validate;
2069          let validate2 = validate;
2070          let result2 = a.add-variant(validate, validate2);
2071          {res1: result1, res2: result2}
2072        "#;
2073
2074        let expr = Expr::from_text(expr).unwrap();
2075
2076        let compiled = compiler.compile(expr);
2077
2078        let result = interpreter.run(compiled.unwrap().byte_code).await.unwrap();
2079        let expected_enum_type = r#enum(&["x", "y", "z"]);
2080        let expected_variant_type = get_analysed_type_variant();
2081
2082        let expected_record_type = record(vec![
2083            field("res1", expected_enum_type),
2084            field("res2", expected_variant_type),
2085        ]);
2086
2087        let expected_record_value = Value::Record(vec![
2088            Value::Enum(0),
2089            Value::Variant {
2090                case_idx: 2,
2091                case_value: None,
2092            },
2093        ]);
2094
2095        assert_eq!(
2096            result,
2097            RibResult::Val(ValueAndType::new(
2098                expected_record_value,
2099                expected_record_type
2100            ))
2101        );
2102    }
2103
2104    #[test]
2105    async fn test_interpreter_with_conflicting_variable_names() {
2106        let test_deps = RibTestDeps::test_deps_with_global_functions();
2107
2108        let compiler = RibCompiler::new(RibCompilerConfig::new(
2109            test_deps.component_dependencies.clone(),
2110            vec![],
2111            vec![],
2112        ));
2113
2114        let mut interpreter = test_deps.interpreter;
2115
2116        // This has intentionally conflicting variable names
2117        // variable `x` is same as the enum name `x`
2118        // similarly, variably `validate` is same as the variant name `validate`
2119        // and `process-user` is same as the variant name `process-user`
2120        let expr = r#"
2121          let x = 1;
2122          let y = 2;
2123          let a = instance();
2124          let result1 = a.add-u32(x, y);
2125          let process-user = 3;
2126          let validate = 4;
2127          let result2 = a.add-u64(process-user, validate);
2128          {res1: result1, res2: result2}
2129        "#;
2130
2131        let expr = Expr::from_text(expr).unwrap();
2132
2133        let compiled = compiler.compile(expr).unwrap();
2134        let result = interpreter.run(compiled.byte_code).await.unwrap();
2135        let expected_value = Value::Record(vec![3u32.into_value(), 7u64.into_value()]);
2136
2137        let expected_type = record(vec![field("res1", u32()), field("res2", u64())]);
2138        assert_eq!(
2139            result,
2140            RibResult::Val(ValueAndType::new(expected_value, expected_type))
2141        );
2142    }
2143
2144    #[test]
2145    async fn test_interpreter_list_reduce() {
2146        let mut interpreter = Interpreter::default();
2147
2148        let rib_expr = r#"
2149          let x: list<u8> = [1, 2];
2150
2151          reduce z, a in x from 0u8 {
2152            yield z + a;
2153          }
2154
2155          "#;
2156
2157        let expr = Expr::from_text(rib_expr).unwrap();
2158        let compiler = RibCompiler::default();
2159        let compiled = compiler.compile(expr).unwrap();
2160        let result = interpreter
2161            .run(compiled.byte_code)
2162            .await
2163            .unwrap()
2164            .get_val()
2165            .unwrap();
2166
2167        assert_eq!(result, 3u8.into_value_and_type());
2168    }
2169
2170    #[test]
2171    async fn test_interpreter_list_reduce_from_record() {
2172        let mut interpreter = Interpreter::default();
2173
2174        let rib_expr = r#"
2175           let x = [{name: "foo", age: 1u64}, {name: "bar", age: 2u64}];
2176
2177           let names = for i in x {
2178             yield i.name;
2179           };
2180
2181          reduce z, a in names from "" {
2182            let result = if z == "" then a else "${z}, ${a}";
2183
2184            yield result;
2185          }
2186
2187          "#;
2188
2189        let expr = Expr::from_text(rib_expr).unwrap();
2190
2191        let compiler = RibCompiler::default();
2192        let compiled = compiler.compile(expr).unwrap();
2193
2194        let result = interpreter
2195            .run(compiled.byte_code)
2196            .await
2197            .unwrap()
2198            .get_val()
2199            .unwrap();
2200
2201        assert_eq!(result, "foo, bar".into_value_and_type());
2202    }
2203
2204    #[test]
2205    async fn test_interpreter_list_reduce_text() {
2206        let mut interpreter = Interpreter::default();
2207
2208        let rib_expr = r#"
2209           let x = ["foo", "bar"];
2210
2211          reduce z, a in x from "" {
2212            let result = if z == "" then a else "${z}, ${a}";
2213
2214            yield result;
2215          }
2216
2217          "#;
2218
2219        let expr = Expr::from_text(rib_expr).unwrap();
2220
2221        let compiler = RibCompiler::default();
2222
2223        let compiled = compiler.compile(expr).unwrap();
2224
2225        let result = interpreter
2226            .run(compiled.byte_code)
2227            .await
2228            .unwrap()
2229            .get_val()
2230            .unwrap();
2231
2232        assert_eq!(result, "foo, bar".into_value_and_type());
2233    }
2234
2235    #[test]
2236    async fn test_interpreter_list_reduce_empty() {
2237        let mut interpreter = Interpreter::default();
2238
2239        let rib_expr = r#"
2240          let x: list<u8> = [];
2241
2242          reduce z, a in x from 0u8 {
2243            yield z + a;
2244          }
2245
2246          "#;
2247
2248        let expr = Expr::from_text(rib_expr).unwrap();
2249
2250        let compiler = RibCompiler::default();
2251
2252        let compiled = compiler.compile(expr).unwrap();
2253
2254        let result = interpreter
2255            .run(compiled.byte_code)
2256            .await
2257            .unwrap()
2258            .get_val()
2259            .unwrap();
2260
2261        assert_eq!(result, 0u8.into_value_and_type());
2262    }
2263
2264    #[test]
2265    async fn test_interpreter_with_numbers_1() {
2266        let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2267
2268        let mut interpreter = test_utils::interpreter_with_static_function_response(
2269            &ValueAndType::new(Value::U64(2), u64()),
2270            None,
2271        );
2272
2273        // 1 is automatically inferred to be u32
2274        let rib = r#"
2275          let worker = instance("my-worker");
2276          worker.foo(1)
2277        "#;
2278
2279        let expr = Expr::from_text(rib).unwrap();
2280
2281        let compiler_config = RibCompilerConfig::new(component_metadata, vec![], vec![]);
2282        let compiler = RibCompiler::new(compiler_config);
2283
2284        let compiled = compiler.compile(expr).unwrap();
2285        let result = interpreter.run(compiled.byte_code).await.unwrap();
2286
2287        assert_eq!(
2288            result.get_val().unwrap(),
2289            ValueAndType::new(Value::U64(2), u64())
2290        );
2291    }
2292
2293    #[test]
2294    async fn test_interpreter_with_numbers_2() {
2295        let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2296
2297        let mut interpreter = test_utils::interpreter_with_static_function_response(
2298            &ValueAndType::new(Value::U64(2), u64()),
2299            None,
2300        );
2301
2302        // 1 and 2 are automatically inferred to be u32
2303        // since the type of z is inferred to be u32 as that being passed to a function
2304        // that expects u32
2305        let rib = r#"
2306          let worker = instance("my-worker");
2307          let z = 1 + 2;
2308          worker.foo(z)
2309        "#;
2310
2311        let expr = Expr::from_text(rib).unwrap();
2312
2313        let compiler_config = RibCompilerConfig::new(component_metadata, vec![], vec![]);
2314        let compiler = RibCompiler::new(compiler_config);
2315
2316        let compiled = compiler.compile(expr).unwrap();
2317        let result = interpreter.run(compiled.byte_code).await.unwrap();
2318
2319        assert_eq!(
2320            result.get_val().unwrap(),
2321            ValueAndType::new(Value::U64(2), u64())
2322        );
2323    }
2324
2325    #[test]
2326    async fn test_interpreter_with_numbers_3() {
2327        let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2328
2329        // This will cause a type inference error
2330        // because the operands of the + operator are not of the same type
2331        let rib = r#"
2332          let worker = instance("my-worker");
2333          let z = 1: u8 + 2;
2334          worker.foo(z)
2335        "#;
2336
2337        let expr = Expr::from_text(rib).unwrap();
2338        let compiler = RibCompiler::new(RibCompilerConfig::new(component_metadata, vec![], vec![]));
2339        let compile_result = compiler.compile(expr);
2340        assert!(compile_result.is_err());
2341    }
2342
2343    #[test]
2344    async fn test_interpreter_with_numbers_4() {
2345        let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2346
2347        // This will cause a type inference error
2348        // because the operands of the + operator are supposed to be u32
2349        // since z is u32
2350        let rib = r#"
2351          let worker = instance("my-worker");
2352          let z = 1: u8 + 2: u8;
2353          worker.foo(z)
2354        "#;
2355
2356        let expr = Expr::from_text(rib).unwrap();
2357        let compiler = RibCompiler::new(RibCompilerConfig::new(component_metadata, vec![], vec![]));
2358        let compile_result = compiler.compile(expr);
2359        assert!(compile_result.is_err());
2360    }
2361
2362    #[test]
2363    async fn test_interpreter_list_comprehension() {
2364        let mut interpreter = Interpreter::default();
2365
2366        let rib_expr = r#"
2367          let x = ["foo", "bar"];
2368
2369          for i in x {
2370            yield i;
2371          }
2372
2373          "#;
2374
2375        let expr = Expr::from_text(rib_expr).unwrap();
2376
2377        let compiler = RibCompiler::default();
2378        let compiled = compiler.compile(expr).unwrap();
2379
2380        let result = interpreter
2381            .run(compiled.byte_code)
2382            .await
2383            .unwrap()
2384            .get_val()
2385            .unwrap();
2386
2387        let expected = r#"["foo", "bar"]"#;
2388        let expected_value = golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2389
2390        assert_eq!(result, expected_value);
2391    }
2392
2393    #[test]
2394    async fn test_interpreter_list_comprehension_empty() {
2395        let mut interpreter = Interpreter::default();
2396
2397        let rib_expr = r#"
2398          let x: list<string> = [];
2399
2400          for i in x {
2401            yield i;
2402          }
2403
2404          "#;
2405
2406        let expr = Expr::from_text(rib_expr).unwrap();
2407
2408        let compiler = RibCompiler::default();
2409        let compiled = compiler.compile(expr).unwrap();
2410
2411        let result = interpreter
2412            .run(compiled.byte_code)
2413            .await
2414            .unwrap()
2415            .get_val()
2416            .unwrap();
2417
2418        let expected = r#"[]"#;
2419        let expected_value_and_type =
2420            golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2421
2422        assert_eq!(result, expected_value_and_type);
2423    }
2424
2425    #[test]
2426    async fn test_interpreter_pattern_match_on_option_nested() {
2427        let mut interpreter = Interpreter::default();
2428
2429        let expr = r#"
2430           let x: option<option<u64>> = none;
2431
2432           match x {
2433              some(some(t)) => t,
2434              some(none) => 0u64,
2435              none => 0u64
2436
2437           }
2438        "#;
2439
2440        let expr = Expr::from_text(expr).unwrap();
2441        let compiler = RibCompiler::default();
2442        let compiled = compiler.compile(expr).unwrap();
2443        let result = interpreter.run(compiled.byte_code).await.unwrap();
2444
2445        assert_eq!(result.get_val().unwrap(), 0u64.into_value_and_type());
2446    }
2447
2448    #[test]
2449    async fn test_interpreter_pattern_match_on_tuple() {
2450        let mut interpreter = Interpreter::default();
2451
2452        let expr = r#"
2453           let x: tuple<u64, string, string> = (1, "foo", "bar");
2454
2455           match x {
2456              (x, y, z) => "${x} ${y} ${z}"
2457           }
2458        "#;
2459
2460        let expr = Expr::from_text(expr).unwrap();
2461        let compiler = RibCompiler::default();
2462        let compiled = compiler.compile(expr).unwrap();
2463        let result = interpreter.run(compiled.byte_code).await.unwrap();
2464
2465        assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2466    }
2467
2468    #[test]
2469    async fn test_interpreter_pattern_match_on_tuple_with_option_some() {
2470        let mut interpreter = Interpreter::default();
2471
2472        let expr = r#"
2473           let x: tuple<u64, option<string>, string> = (1, some("foo"), "bar");
2474
2475           match x {
2476              (x, none, z) => "${x} ${z}",
2477              (x, some(y), z) => "${x} ${y} ${z}"
2478           }
2479        "#;
2480
2481        let expr = Expr::from_text(expr).unwrap();
2482        let compiler = RibCompiler::default();
2483        let compiled = compiler.compile(expr).unwrap();
2484        let result = interpreter.run(compiled.byte_code).await.unwrap();
2485
2486        assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2487    }
2488
2489    #[test]
2490    async fn test_interpreter_pattern_match_on_tuple_with_option_none() {
2491        let mut interpreter = Interpreter::default();
2492
2493        let expr = r#"
2494           let x: tuple<u64, option<string>, string> = (1, none, "bar");
2495
2496           match x {
2497              (x, none, z) => "${x} ${z}",
2498              (x, some(y), z) => "${x} ${y} ${z}"
2499           }
2500        "#;
2501
2502        let expr = Expr::from_text(expr).unwrap();
2503        let compiler = RibCompiler::default();
2504        let compiled = compiler.compile(expr).unwrap();
2505        let result = interpreter.run(compiled.byte_code).await.unwrap();
2506
2507        assert_eq!(result.get_val().unwrap(), "1 bar".into_value_and_type());
2508    }
2509
2510    #[test]
2511    async fn test_interpreter_pattern_match_dynamic_branch_1() {
2512        let mut interpreter = Interpreter::default();
2513
2514        let expr = r#"
2515           let x = 1;
2516
2517           match x {
2518                1 => ok(1),
2519                2 => err("none")
2520           }
2521        "#;
2522
2523        let expr = Expr::from_text(expr).unwrap();
2524        let compiler = RibCompiler::default();
2525        let compiled = compiler.compile(expr).unwrap();
2526        let rib_result = interpreter.run(compiled.byte_code).await.unwrap();
2527
2528        let expected = ValueAndType::new(
2529            Value::Result(Ok(Some(Box::new(Value::S32(1))))),
2530            result(s32(), str()),
2531        );
2532
2533        assert_eq!(rib_result.get_val().unwrap(), expected);
2534    }
2535
2536    #[test]
2537    async fn test_interpreter_pattern_match_dynamic_branch_2() {
2538        let mut interpreter = Interpreter::default();
2539
2540        let expr = r#"
2541           let x = some({foo: 1});
2542
2543           match x {
2544               some(x) => ok(x.foo),
2545               none => err("none")
2546           }
2547        "#;
2548
2549        let expr = Expr::from_text(expr).unwrap();
2550        let compiler = RibCompiler::default();
2551        let compiled = compiler.compile(expr).unwrap();
2552        let rib_result = interpreter.run(compiled.byte_code).await.unwrap();
2553
2554        let expected = ValueAndType::new(
2555            Value::Result(Ok(Some(Box::new(Value::S32(1))))),
2556            result(s32(), str()),
2557        );
2558
2559        assert_eq!(rib_result.get_val().unwrap(), expected);
2560    }
2561
2562    #[test]
2563    async fn test_interpreter_pattern_match_on_tuple_with_all_types() {
2564        let mut interpreter = Interpreter::default();
2565
2566        let tuple = test_utils::get_analysed_type_tuple();
2567
2568        let analysed_exports = test_utils::configurable_metadata("foo", vec![tuple], Some(str()));
2569
2570        let expr = r#"
2571           let worker = instance();
2572           let record = { request : { path : { user : "jak" } }, y : "bar" };
2573           let input = (1, ok(100), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2574           worker.foo(input);
2575           match input {
2576             (n1, err(x1), txt, rec, process-user(x), register-user(n), validate, dev, prod, test) =>  "Invalid",
2577             (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}"
2578           }
2579
2580        "#;
2581
2582        let expr = Expr::from_text(expr).unwrap();
2583        let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2584        let compiled = compiler.compile(expr).unwrap();
2585        let result = interpreter.run(compiled.byte_code).await.unwrap();
2586
2587        assert_eq!(
2588            result.get_val().unwrap(),
2589            "foo 100 1 bar jak validate prod dev test".into_value_and_type()
2590        );
2591    }
2592
2593    #[test]
2594    async fn test_interpreter_pattern_match_on_tuple_with_wild_pattern() {
2595        let mut interpreter = Interpreter::default();
2596
2597        let tuple = test_utils::get_analysed_type_tuple();
2598
2599        let analysed_exports =
2600            test_utils::configurable_metadata("my-worker-function", vec![tuple], Some(str()));
2601
2602        let expr = r#"
2603           let worker = instance();
2604           let record = { request : { path : { user : "jak" } }, y : "baz" };
2605           let input = (1, ok(1), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2606           worker.my-worker-function(input);
2607           match input {
2608             (n1, ok(x), txt, rec, _, _, _, _, prod, _) =>  "prod ${n1} ${txt} ${rec.request.path.user} ${rec.y}",
2609             (n1, ok(x), txt, rec, _, _, _, _, dev, _) =>   "dev ${n1} ${txt} ${rec.request.path.user} ${rec.y}"
2610           }
2611        "#;
2612
2613        let expr = Expr::from_text(expr).unwrap();
2614        let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2615        let compiled = compiler.compile(expr).unwrap();
2616        let result = interpreter.run(compiled.byte_code).await.unwrap();
2617
2618        assert_eq!(
2619            result.get_val().unwrap(),
2620            "dev 1 bar jak baz".into_value_and_type()
2621        );
2622    }
2623
2624    #[test]
2625    async fn test_interpreter_record_output_in_pattern_match() {
2626        let input_analysed_type = test_utils::get_analysed_type_record();
2627        let output_analysed_type = test_utils::get_analysed_type_result();
2628
2629        let result_value = get_value_and_type(&output_analysed_type, r#"ok(1)"#);
2630
2631        let mut interpreter =
2632            test_utils::interpreter_with_static_function_response(&result_value, None);
2633
2634        let analysed_exports = test_utils::configurable_metadata(
2635            "my-worker-function",
2636            vec![input_analysed_type],
2637            Some(output_analysed_type),
2638        );
2639
2640        let expr = r#"
2641           let worker = instance();
2642           let input = { request : { path : { user : "jak" } }, y : "baz" };
2643           let result = worker.my-worker-function(input);
2644           match result {
2645             ok(result) => { body: result, status: 200 },
2646             err(result) => { status: 400, body: 400 }
2647           }
2648        "#;
2649
2650        let expr = Expr::from_text(expr).unwrap();
2651        let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2652        let compiled = compiler.compile(expr).unwrap();
2653        let result = interpreter.run(compiled.byte_code).await.unwrap();
2654
2655        let expected = test_utils::get_value_and_type(
2656            &record(vec![field("body", u64()), field("status", s32())]),
2657            r#"{body: 1, status: 200}"#,
2658        );
2659
2660        assert_eq!(result.get_val().unwrap(), expected);
2661    }
2662
2663    #[test]
2664    async fn test_interpreter_tuple_output_in_pattern_match() {
2665        let input_analysed_type = test_utils::get_analysed_type_record();
2666        let output_analysed_type = test_utils::get_analysed_type_result();
2667
2668        let result_value = get_value_and_type(&output_analysed_type, r#"err("failed")"#);
2669
2670        let mut interpreter =
2671            test_utils::interpreter_with_static_function_response(&result_value, None);
2672
2673        let analysed_exports = test_utils::configurable_metadata(
2674            "my-worker-function",
2675            vec![input_analysed_type],
2676            Some(output_analysed_type),
2677        );
2678
2679        let expr = r#"
2680           let input = { request : { path : { user : "jak" } }, y : "baz" };
2681           let worker = instance();
2682           let result = worker.my-worker-function(input);
2683           match result {
2684             ok(res) => ("${res}", "foo"),
2685             err(msg) => (msg, "bar")
2686           }
2687        "#;
2688
2689        let expr = Expr::from_text(expr).unwrap();
2690        let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2691        let compiled = compiler.compile(expr).unwrap();
2692        let result = interpreter.run(compiled.byte_code).await.unwrap();
2693
2694        let expected = get_value_and_type(&tuple(vec![str(), str()]), r#"("failed", "bar")"#);
2695
2696        assert_eq!(result.get_val().unwrap(), expected);
2697    }
2698
2699    #[test]
2700    async fn test_interpreter_with_indexed_resource_drop() {
2701        let expr = r#"
2702           let user_id = "user";
2703           let worker = instance();
2704           let cart = worker.cart(user_id);
2705           cart.drop();
2706           "success"
2707        "#;
2708        let expr = Expr::from_text(expr).unwrap();
2709        let component_metadata = test_utils::get_metadata_with_resource_with_params();
2710
2711        let compiler_config = RibCompilerConfig::new(component_metadata, vec![], vec![]);
2712        let compiler = RibCompiler::new(compiler_config);
2713        let compiled = compiler.compile(expr).unwrap();
2714
2715        let mut rib_interpreter = test_utils::interpreter_with_resource_function_invoke_impl(None);
2716        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2717
2718        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2719    }
2720
2721    #[test]
2722    async fn test_interpreter_with_indexed_resource_checkout() {
2723        let expr = r#"
2724           let user_id = "foo";
2725           let worker = instance();
2726           let cart = worker.cart(user_id);
2727           let result = cart.checkout();
2728           result
2729        "#;
2730
2731        let expr = Expr::from_text(expr).unwrap();
2732
2733        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2734
2735        let compiler_config =
2736            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2737        let compiler = RibCompiler::new(compiler_config);
2738
2739        let compiled = compiler.compile(expr).unwrap();
2740
2741        let mut rib_executor = test_deps.interpreter;
2742        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2743
2744        let expected_value = Value::Variant {
2745            case_idx: 1,
2746            case_value: Some(Box::new(Value::Record(vec![Value::String(
2747                "foo".to_string(),
2748            )]))),
2749        };
2750
2751        assert_eq!(result.get_val().unwrap().value, expected_value);
2752    }
2753
2754    #[test]
2755    async fn test_interpreter_with_indexed_resources_static_functions_1() {
2756        let expr = r#"
2757           let worker = instance();
2758           let result = worker.cart.create("afsal");
2759           result.checkout()
2760        "#;
2761
2762        let expr = Expr::from_text(expr).unwrap();
2763
2764        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2765
2766        let compiler_config =
2767            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2768        let compiler = RibCompiler::new(compiler_config);
2769
2770        let compiled = compiler.compile(expr).unwrap();
2771
2772        let mut rib_executor = test_deps.interpreter;
2773        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2774
2775        let expected_value = Value::Variant {
2776            case_idx: 1,
2777            case_value: Some(Box::new(Value::Record(vec![Value::String(
2778                "foo".to_string(),
2779            )]))),
2780        };
2781
2782        assert_eq!(result.get_val().unwrap().value, expected_value);
2783    }
2784
2785    #[test]
2786    async fn test_interpreter_with_indexed_resources_static_functions_2() {
2787        let expr = r#"
2788           let worker = instance();
2789           let default-cart = worker.cart("default");
2790           let alternate-cart = worker.cart.create-safe("afsal");
2791           match alternate-cart {
2792             ok(alt) => alt.checkout(),
2793             err(_) => default-cart.checkout()
2794           }
2795        "#;
2796
2797        let expr = Expr::from_text(expr).unwrap();
2798
2799        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2800
2801        let compiler_config =
2802            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2803        let compiler = RibCompiler::new(compiler_config);
2804
2805        let compiled = compiler.compile(expr).unwrap();
2806
2807        let mut rib_executor = test_deps.interpreter;
2808        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2809
2810        let expected_value = Value::Variant {
2811            case_idx: 1,
2812            case_value: Some(Box::new(Value::Record(vec![Value::String(
2813                "foo".to_string(),
2814            )]))),
2815        };
2816
2817        assert_eq!(result.get_val().unwrap().value, expected_value);
2818    }
2819
2820    #[test]
2821    async fn test_interpreter_with_indexed_resource_get_cart_contents() {
2822        let expr = r#"
2823           let user_id = "bar";
2824           let worker = instance();
2825           let cart = worker.cart(user_id);
2826           let result = cart.get-cart-contents();
2827           result[0].product-id
2828        "#;
2829
2830        let expr = Expr::from_text(expr).unwrap();
2831
2832        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2833
2834        let compiler_config =
2835            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2836        let compiler = RibCompiler::new(compiler_config);
2837
2838        let compiled = compiler.compile(expr).unwrap();
2839
2840        let mut rib_executor = test_deps.interpreter;
2841
2842        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2843
2844        assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2845    }
2846
2847    #[test]
2848    async fn test_interpreter_with_indexed_resource_update_item_quantity() {
2849        let expr = r#"
2850           let user_id = "jon";
2851           let product_id = "mac";
2852           let quantity = 1032;
2853           let worker = instance();
2854           let cart = worker.cart(user_id);
2855           cart.update-item-quantity(product_id, quantity);
2856           "successfully updated"
2857        "#;
2858        let expr = Expr::from_text(expr).unwrap();
2859
2860        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2861
2862        let compiler_config =
2863            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2864        let compiler = RibCompiler::new(compiler_config);
2865
2866        let compiled = compiler.compile(expr).unwrap();
2867
2868        let mut rib_executor = test_deps.interpreter;
2869
2870        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2871
2872        assert_eq!(
2873            result.get_val().unwrap(),
2874            "successfully updated".into_value_and_type()
2875        );
2876    }
2877
2878    #[test]
2879    async fn test_interpreter_with_indexed_resource_add_item() {
2880        let expr = r#"
2881           let user_id = "foo";
2882           let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2883           let worker = instance();
2884           let cart = worker.cart(user_id);
2885           cart.add-item(product);
2886
2887           "successfully added"
2888        "#;
2889
2890        let expr = Expr::from_text(expr).unwrap();
2891
2892        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2893
2894        let compiler_config =
2895            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2896        let compiler = RibCompiler::new(compiler_config);
2897
2898        let compiled = compiler.compile(expr).unwrap();
2899
2900        let mut rib_executor = test_deps.interpreter;
2901
2902        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2903
2904        assert_eq!(
2905            result.get_val().unwrap(),
2906            "successfully added".into_value_and_type()
2907        );
2908    }
2909
2910    #[test]
2911    async fn test_interpreter_with_resource_add_item() {
2912        let expr = r#"
2913           let worker = instance();
2914           let cart = worker.cart();
2915           let user_id = "foo";
2916           let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2917           cart.add-item(product);
2918
2919           "successfully added"
2920        "#;
2921
2922        let expr = Expr::from_text(expr).unwrap();
2923
2924        let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
2925
2926        let compiler_config =
2927            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2928        let compiler = RibCompiler::new(compiler_config);
2929
2930        let compiled = compiler.compile(expr).unwrap();
2931
2932        let mut rib_executor = test_deps.interpreter;
2933
2934        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2935
2936        assert_eq!(
2937            result.get_val().unwrap(),
2938            "successfully added".into_value_and_type()
2939        );
2940    }
2941
2942    #[test]
2943    async fn test_interpreter_with_resource_get_cart_contents() {
2944        let expr = r#"
2945           let worker = instance();
2946           let cart = worker.cart();
2947           let result = cart.get-cart-contents();
2948           result[0].product-id
2949        "#;
2950
2951        let expr = Expr::from_text(expr).unwrap();
2952
2953        let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
2954
2955        let compiler_config =
2956            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2957        let compiler = RibCompiler::new(compiler_config);
2958
2959        let compiled = compiler.compile(expr).unwrap();
2960
2961        let mut rib_executor = test_deps.interpreter;
2962        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2963
2964        assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2965    }
2966
2967    #[test]
2968    async fn test_interpreter_with_resource_update_item() {
2969        let expr = r#"
2970           let worker = instance();
2971           let product_id = "mac";
2972           let quantity = 1032;
2973           let cart = worker.cart();
2974           cart.update-item-quantity(product_id, quantity);
2975           "successfully updated"
2976        "#;
2977        let expr = Expr::from_text(expr).unwrap();
2978
2979        let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
2980
2981        let compiler_config =
2982            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2983        let compiler = RibCompiler::new(compiler_config);
2984
2985        let compiled = compiler.compile(expr).unwrap();
2986
2987        let mut rib_executor = test_deps.interpreter;
2988
2989        let result = rib_executor.run(compiled.byte_code).await.unwrap();
2990
2991        assert_eq!(
2992            result.get_val().unwrap(),
2993            "successfully updated".into_value_and_type()
2994        );
2995    }
2996
2997    #[test]
2998    async fn test_interpreter_with_resource_checkout() {
2999        let expr = r#"
3000           let worker = instance();
3001           let cart = worker.cart();
3002           let result = cart.checkout();
3003           result
3004        "#;
3005
3006        let expr = Expr::from_text(expr).unwrap();
3007
3008        let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
3009
3010        let compiler_config =
3011            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3012
3013        let compiler = RibCompiler::new(compiler_config);
3014
3015        let compiled = compiler.compile(expr).unwrap();
3016
3017        let mut interpreter = test_deps.interpreter;
3018
3019        let result = interpreter.run(compiled.byte_code).await.unwrap();
3020
3021        let expected_result = Value::Variant {
3022            case_idx: 1,
3023            case_value: Some(Box::new(Value::Record(vec![Value::String(
3024                "foo".to_string(),
3025            )]))),
3026        };
3027
3028        assert_eq!(result.get_val().unwrap().value, expected_result);
3029    }
3030
3031    #[test]
3032    async fn test_interpreter_with_resource_drop() {
3033        let expr = r#"
3034           let worker = instance();
3035           let cart = worker.cart();
3036           cart.drop();
3037           "success"
3038        "#;
3039        let expr = Expr::from_text(expr).unwrap();
3040        let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
3041
3042        let compiler_config =
3043            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3044        let compiler = RibCompiler::new(compiler_config);
3045        let compiled = compiler.compile(expr).unwrap();
3046
3047        let mut rib_interpreter = test_deps.interpreter;
3048        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3049
3050        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3051    }
3052
3053    #[test]
3054    async fn test_interpreter_for_select_index_expr_1() {
3055        // infinite computation will respond with an error - than a stack overflow
3056        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3057        let expr = r#"
3058              let list: list<u8> = [1, 2, 3, 4, 5];
3059              let index: u8 = 4;
3060              list[index]
3061              "#;
3062
3063        let expr = Expr::from_text(expr).unwrap();
3064
3065        let compiler = RibCompiler::default();
3066        let compiled = compiler.compile(expr).unwrap();
3067
3068        let mut interpreter = Interpreter::default();
3069        let result = interpreter.run(compiled.byte_code).await.unwrap();
3070
3071        let expected = ValueAndType::new(Value::U8(5), u8());
3072
3073        assert_eq!(result.get_val().unwrap(), expected);
3074    }
3075
3076    #[test]
3077    async fn test_interpreter_for_select_index_expr_out_of_bound() {
3078        let expr = r#"
3079              let list: list<u8> = [1, 2, 3, 4, 5];
3080              let index: u8 = 10;
3081              list[index]
3082              "#;
3083
3084        let expr = Expr::from_text(expr).unwrap();
3085
3086        let compiler = RibCompiler::default();
3087        let compiled = compiler.compile(expr).unwrap();
3088
3089        let mut interpreter = Interpreter::default();
3090        let result = interpreter
3091            .run(compiled.byte_code)
3092            .await
3093            .unwrap_err()
3094            .to_string();
3095
3096        assert_eq!(result, "index out of bound: 10 (size: 5)".to_string());
3097    }
3098
3099    #[test]
3100    async fn test_interpreter_for_select_index_expr_2() {
3101        let expr = r#"
3102              let list: list<u8> = [1, 2, 3, 4, 5];
3103              let indices: list<u8> = [0, 1, 2, 3];
3104
3105              for i in indices {
3106                 yield list[i];
3107              }
3108              "#;
3109
3110        let expr = Expr::from_text(expr).unwrap();
3111
3112        let compiler = RibCompiler::default();
3113        let compiled = compiler.compile(expr).unwrap();
3114
3115        let mut interpreter = Interpreter::default();
3116        let result = interpreter.run(compiled.byte_code).await.unwrap();
3117
3118        let expected = ValueAndType::new(
3119            Value::List(vec![Value::U8(1), Value::U8(2), Value::U8(3), Value::U8(4)]),
3120            list(u8()),
3121        );
3122
3123        assert_eq!(result.get_val().unwrap(), expected);
3124    }
3125
3126    #[test]
3127    async fn test_interpreter_for_select_index_expr_3() {
3128        let expr = r#"
3129              let list: list<u8> = [2, 5, 4];
3130              let indices: list<u8> = [0, 1];
3131
3132               reduce z, index in indices from 0u8 {
3133                  yield list[index] + z;
3134                }
3135              "#;
3136
3137        let expr = Expr::from_text(expr).unwrap();
3138
3139        let compiler = RibCompiler::default();
3140        let compiled = compiler.compile(expr).unwrap();
3141
3142        let mut interpreter = Interpreter::default();
3143        let result = interpreter.run(compiled.byte_code).await.unwrap();
3144
3145        let expected = ValueAndType::new(Value::U8(7), u8());
3146
3147        assert_eq!(result.get_val().unwrap(), expected);
3148    }
3149
3150    #[test]
3151    async fn test_interpreter_for_select_index_expr_4() {
3152        let expr = r#"
3153              let list: list<u8> = [2, 5, 4];
3154              let x: u8 = 0;
3155              let y: u8 = 2;
3156              list[x..=y]
3157              "#;
3158
3159        let expr = Expr::from_text(expr).unwrap();
3160
3161        let compiler = RibCompiler::default();
3162        let compiled = compiler.compile(expr).unwrap();
3163
3164        let mut interpreter = Interpreter::default();
3165        let result = interpreter.run(compiled.byte_code).await.unwrap();
3166
3167        let expected = ValueAndType::new(
3168            Value::List(vec![Value::U8(2), Value::U8(5), Value::U8(4)]),
3169            list(u8()),
3170        );
3171
3172        assert_eq!(result.get_val().unwrap(), expected);
3173    }
3174
3175    #[test]
3176    async fn test_interpreter_for_select_index_expr_5() {
3177        let expr = r#"
3178              let list: list<u8> = [2, 5, 4];
3179              let x: u8 = 0;
3180              let y: u8 = 2;
3181              let x1: u8 = 1;
3182              let result = list[x..=y];
3183              for i in result[x1..=y] {
3184                yield i;
3185              }
3186              "#;
3187
3188        let expr = Expr::from_text(expr).unwrap();
3189
3190        let compiler = RibCompiler::default();
3191        let compiled = compiler.compile(expr).unwrap();
3192
3193        let mut interpreter = Interpreter::default();
3194        let result = interpreter.run(compiled.byte_code).await.unwrap();
3195
3196        let expected = ValueAndType::new(Value::List(vec![Value::U8(5), Value::U8(4)]), list(u8()));
3197
3198        assert_eq!(result.get_val().unwrap(), expected);
3199    }
3200
3201    #[test]
3202    async fn test_interpreter_for_select_index_expr_6() {
3203        let expr = r#"
3204              let list: list<u8> = [2, 5, 4, 6];
3205              let x: u8 = 0;
3206              let y: u8 = 2;
3207              let result = list[x..y];
3208              for i in result[x..y] {
3209                yield i;
3210              }
3211              "#;
3212
3213        let expr = Expr::from_text(expr).unwrap();
3214
3215        let compiler = RibCompiler::default();
3216        let compiled = compiler.compile(expr).unwrap();
3217
3218        let mut interpreter = Interpreter::default();
3219        let result = interpreter.run(compiled.byte_code).await.unwrap();
3220
3221        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
3222
3223        assert_eq!(result.get_val().unwrap(), expected);
3224    }
3225
3226    #[test]
3227    async fn test_interpreter_for_select_index_expr_7() {
3228        let expr = r#"
3229              let list: list<u8> = [2, 5, 4, 6];
3230              let x: u8 = 0;
3231              let result = list[x..];
3232              for i in result[x..] {
3233                yield i;
3234              }
3235              "#;
3236
3237        let expr = Expr::from_text(expr).unwrap();
3238
3239        let compiler = RibCompiler::default();
3240        let compiled = compiler.compile(expr).unwrap();
3241
3242        let mut interpreter = Interpreter::default();
3243        let result = interpreter.run(compiled.byte_code).await.unwrap();
3244
3245        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
3246
3247        assert_eq!(result.get_val().unwrap(), expected);
3248    }
3249
3250    #[test]
3251    async fn test_interpreter_for_select_index_expr_8() {
3252        let expr = r#"
3253              let list: list<u8> = [2, 5, 4, 6];
3254              let result = list[0..2];
3255              for i in result[0..2] {
3256                yield i;
3257              }
3258              "#;
3259
3260        let expr = Expr::from_text(expr).unwrap();
3261
3262        let compiler = RibCompiler::default();
3263        let compiled = compiler.compile(expr).unwrap();
3264
3265        let mut interpreter = Interpreter::default();
3266        let result = interpreter.run(compiled.byte_code).await.unwrap();
3267
3268        let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
3269
3270        assert_eq!(result.get_val().unwrap(), expected);
3271    }
3272
3273    // Simulating the behaviour in languages like rust
3274    // Emitting the description of the range than the evaluated range
3275    // Description given out as ValueAndType::Record
3276    #[test]
3277    async fn test_interpreter_range_returns_1() {
3278        let expr = r#"
3279              let x = 1..;
3280              x
3281              "#;
3282
3283        let expr = Expr::from_text(expr).unwrap();
3284
3285        let compiler = RibCompiler::default();
3286        let compiled = compiler.compile(expr).unwrap();
3287
3288        let mut interpreter = Interpreter::default();
3289        let result = interpreter.run(compiled.byte_code).await.unwrap();
3290
3291        let expected = ValueAndType::new(
3292            Value::Record(vec![
3293                Value::S32(1),
3294                Value::Bool(false), // non inclusive
3295            ]),
3296            record(vec![field("from", s32()), field("inclusive", bool())]),
3297        );
3298
3299        assert_eq!(result.get_val().unwrap(), expected);
3300    }
3301
3302    #[test]
3303    async fn test_interpreter_range_returns_2() {
3304        let expr = r#"
3305              let x = 1..2;
3306              x
3307              "#;
3308
3309        let expr = Expr::from_text(expr).unwrap();
3310
3311        let compiler = RibCompiler::default();
3312        let compiled = compiler.compile(expr).unwrap();
3313
3314        let mut interpreter = Interpreter::default();
3315        let result = interpreter.run(compiled.byte_code).await.unwrap();
3316
3317        let expected = ValueAndType::new(
3318            Value::Record(vec![
3319                Value::S32(1),
3320                Value::S32(2),
3321                Value::Bool(false), // non inclusive
3322            ]),
3323            record(vec![
3324                field("from", s32()),
3325                field("to", s32()),
3326                field("inclusive", bool()),
3327            ]),
3328        );
3329
3330        assert_eq!(result.get_val().unwrap(), expected);
3331    }
3332
3333    #[test]
3334    async fn test_interpreter_range_returns_3() {
3335        let expr = r#"
3336              let x = 1..=10;
3337              x
3338              "#;
3339
3340        let expr = Expr::from_text(expr).unwrap();
3341
3342        let compiler = RibCompiler::default();
3343        let compiled = compiler.compile(expr).unwrap();
3344
3345        let mut interpreter = Interpreter::default();
3346        let result = interpreter.run(compiled.byte_code).await.unwrap();
3347
3348        let expected = ValueAndType::new(
3349            Value::Record(vec![
3350                Value::S32(1),
3351                Value::S32(10),
3352                Value::Bool(true), // inclusive
3353            ]),
3354            record(vec![
3355                field("from", s32()),
3356                field("to", s32()),
3357                field("inclusive", bool()),
3358            ]),
3359        );
3360
3361        assert_eq!(result.get_val().unwrap(), expected);
3362    }
3363
3364    #[test]
3365    async fn test_interpreter_range_returns_4() {
3366        let expr = r#"
3367              let x = 1:u64;
3368              let y = x;
3369              let range = x..=y;
3370              let range2 = x..;
3371              let range3 = x..y;
3372              range;
3373              range2;
3374              range3
3375              "#;
3376
3377        let expr = Expr::from_text(expr).unwrap();
3378
3379        let compiler = RibCompiler::default();
3380        let compiled = compiler.compile(expr).unwrap();
3381
3382        let mut interpreter = Interpreter::default();
3383        let result = interpreter.run(compiled.byte_code).await.unwrap();
3384
3385        let expected = ValueAndType::new(
3386            Value::Record(vec![Value::U64(1), Value::U64(1), Value::Bool(false)]),
3387            record(vec![
3388                field("from", u64()),
3389                field("to", u64()),
3390                field("inclusive", bool()),
3391            ]),
3392        );
3393
3394        assert_eq!(result.get_val().unwrap(), expected);
3395    }
3396
3397    #[test]
3398    async fn test_interpreter_range_returns_5() {
3399        let expr = r#"
3400              let y = 1 + 10;
3401              1..y
3402              "#;
3403
3404        let expr = Expr::from_text(expr).unwrap();
3405
3406        let compiler = RibCompiler::default();
3407        let compiled = compiler.compile(expr).unwrap();
3408
3409        let mut interpreter = Interpreter::default();
3410        let result = interpreter.run(compiled.byte_code).await.unwrap();
3411
3412        let expected = ValueAndType::new(
3413            Value::Record(vec![Value::S32(1), Value::S32(11), Value::Bool(false)]),
3414            record(vec![
3415                field("from", s32()),
3416                field("to", s32()),
3417                field("inclusive", bool()),
3418            ]),
3419        );
3420
3421        assert_eq!(result.get_val().unwrap(), expected);
3422    }
3423
3424    #[test]
3425    async fn test_interpreter_range_with_comprehension_1() {
3426        let expr = r#"
3427              let range = 1..=5;
3428              for i in range {
3429                yield i;
3430              }
3431
3432              "#;
3433
3434        let expr = Expr::from_text(expr).unwrap();
3435
3436        let compiler = RibCompiler::default();
3437        let compiled = compiler.compile(expr).unwrap();
3438
3439        let mut interpreter = Interpreter::default();
3440        let result = interpreter.run(compiled.byte_code).await.unwrap();
3441
3442        let expected = ValueAndType::new(
3443            Value::List(vec![
3444                Value::S32(1),
3445                Value::S32(2),
3446                Value::S32(3),
3447                Value::S32(4),
3448                Value::S32(5),
3449            ]),
3450            list(s32()),
3451        );
3452
3453        assert_eq!(result.get_val().unwrap(), expected);
3454    }
3455
3456    #[test]
3457    async fn test_interpreter_range_with_comprehension_2() {
3458        let expr = r#"
3459              let range = 1..5;
3460              for i in range {
3461                yield i;
3462              }
3463
3464              "#;
3465
3466        let expr = Expr::from_text(expr).unwrap();
3467
3468        let compiler = RibCompiler::default();
3469        let compiled = compiler.compile(expr).unwrap();
3470
3471        let mut interpreter = Interpreter::default();
3472        let result = interpreter.run(compiled.byte_code).await.unwrap();
3473
3474        let expected = ValueAndType::new(
3475            Value::List(vec![
3476                Value::S32(1),
3477                Value::S32(2),
3478                Value::S32(3),
3479                Value::S32(4),
3480            ]),
3481            list(s32()),
3482        );
3483
3484        assert_eq!(result.get_val().unwrap(), expected);
3485    }
3486
3487    #[test]
3488    async fn test_interpreter_range_with_comprehension_3() {
3489        // infinite computation will respond with an error - than a stack overflow
3490        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3491        let expr = r#"
3492              let range = 1..;
3493              for i in range {
3494                yield i;
3495              }
3496
3497              "#;
3498
3499        let expr = Expr::from_text(expr).unwrap();
3500
3501        let compiler = RibCompiler::default();
3502        let compiled = compiler.compile(expr).unwrap();
3503
3504        let mut interpreter = Interpreter::default();
3505        let result = interpreter.run(compiled.byte_code).await;
3506        assert!(result.is_err());
3507    }
3508
3509    #[test]
3510    async fn test_interpreter_range_with_list_reduce_1() {
3511        // infinite computation will respond with an error - than a stack overflow
3512        // Note that, `list[1..]` is allowed while `for i in 1.. { yield i; }` is not
3513        let expr = r#"
3514                let initial = 1;
3515                let final = 5;
3516                let x = initial..final;
3517
3518                reduce z, a in x from 0u8 {
3519                  yield z + a;
3520                }
3521
3522              "#;
3523
3524        let expr = Expr::from_text(expr).unwrap();
3525
3526        let compiler = RibCompiler::default();
3527        let compiled = compiler.compile(expr).unwrap();
3528
3529        let mut interpreter = Interpreter::default();
3530        let result = interpreter.run(compiled.byte_code).await.unwrap();
3531
3532        let expected = ValueAndType::new(Value::U8(10), u8());
3533
3534        assert_eq!(result.get_val().unwrap(), expected);
3535    }
3536
3537    #[test]
3538    async fn test_interpreter_ephemeral_worker_0() {
3539        let expr = r#"
3540              let x = instance();
3541              let result = x.pass-through(1, 2);
3542              result
3543            "#;
3544        let expr = Expr::from_text(expr).unwrap();
3545
3546        let test_deps = RibTestDeps::test_deps_for_pass_through_function();
3547
3548        let compiler_config =
3549            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3550        let compiler = RibCompiler::new(compiler_config);
3551        let compiled = compiler.compile(expr).unwrap();
3552
3553        let mut rib_interpreter = test_deps.interpreter;
3554
3555        let result = rib_interpreter
3556            .run(compiled.byte_code)
3557            .await
3558            .unwrap()
3559            .get_val()
3560            .unwrap()
3561            .value;
3562
3563        let expected_value = Value::Record(vec![
3564            Value::String("test-worker".to_string()),
3565            Value::String("pass-through".to_string()),
3566            Value::U64(1),
3567            Value::U32(2),
3568        ]);
3569
3570        assert_eq!(result, expected_value)
3571    }
3572
3573    #[test]
3574    async fn test_interpreter_ephemeral_worker_1() {
3575        let expr = r#"
3576              let x = instance();
3577              x
3578            "#;
3579        let expr = Expr::from_text(expr).unwrap();
3580
3581        let test_deps = RibTestDeps::test_deps_with_global_functions();
3582
3583        let compiler = RibCompiler::new(RibCompilerConfig::new(
3584            test_deps.component_dependencies.clone(),
3585            vec![],
3586            vec![],
3587        ));
3588
3589        let compiled = compiler.compile(expr);
3590
3591        assert!(compiled.is_ok());
3592    }
3593
3594    #[test]
3595    async fn test_interpreter_ephemeral_worker_2() {
3596        let expr = r#"
3597             instance
3598            "#;
3599        let expr = Expr::from_text(expr).unwrap();
3600
3601        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3602
3603        let compiler = RibCompiler::new(RibCompilerConfig::new(
3604            test_deps.component_dependencies.clone(),
3605            vec![],
3606            vec![],
3607        ));
3608
3609        let compiled = compiler.compile(expr);
3610
3611        assert!(compiled.is_err());
3612    }
3613
3614    #[test]
3615    async fn test_interpreter_ephemeral_worker_3() {
3616        let expr = r#"
3617              instance()
3618            "#;
3619        let expr = Expr::from_text(expr).unwrap();
3620
3621        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3622
3623        let compiler = RibCompiler::new(RibCompilerConfig::new(
3624            test_deps.component_dependencies.clone(),
3625            vec![],
3626            vec![],
3627        ));
3628
3629        let compiled = compiler.compile(expr);
3630
3631        assert!(compiled.is_ok());
3632    }
3633
3634    #[test]
3635    async fn test_interpreter_ephemeral_worker_4() {
3636        let expr = r#"
3637              let worker = instance().foo("bar")
3638            "#;
3639        let expr = Expr::from_text(expr).unwrap();
3640
3641        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3642
3643        let compiler_config =
3644            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3645        let compiler = RibCompiler::new(compiler_config);
3646        let error = compiler.compile(expr).unwrap_err();
3647
3648        assert_eq!(
3649            error.to_string(),
3650            "inline invocation of functions on a worker instance is currently not supported"
3651        );
3652    }
3653
3654    #[test]
3655    async fn test_interpreter_ephemeral_worker_5() {
3656        let expr = r#"
3657              let result = instance.foo("bar");
3658              result
3659            "#;
3660        let expr = Expr::from_text(expr).unwrap();
3661        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3662
3663        let compiler = RibCompiler::new(RibCompilerConfig::new(
3664            test_deps.component_dependencies.clone(),
3665            vec![],
3666            vec![],
3667        ));
3668
3669        let compiled = compiler.compile(expr).unwrap_err().to_string();
3670
3671        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());
3672    }
3673
3674    #[test]
3675    async fn test_interpreter_ephemeral_worker_6() {
3676        let expr = r#"
3677                let x = instance();
3678                let result = x.bar("bar");
3679                result
3680            "#;
3681        let expr = Expr::from_text(expr).unwrap();
3682        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3683
3684        let compiler = RibCompiler::new(RibCompilerConfig::new(
3685            test_deps.component_dependencies.clone(),
3686            vec![],
3687            vec![],
3688        ));
3689
3690        let compilation_error = compiler.compile(expr).unwrap_err().to_string();
3691
3692        assert_eq!(
3693            compilation_error,
3694            "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()
3695        );
3696    }
3697
3698    #[test]
3699    async fn test_interpreter_ephemeral_worker_7() {
3700        let expr = r#"
3701                let worker = instance();
3702                let invokes: list<u8> = [1, 2, 3, 4];
3703
3704                for i in invokes {
3705                    yield worker.qux[wasi:clocks]("bar");
3706                };
3707
3708                "success"
3709            "#;
3710        let expr = Expr::from_text(expr).unwrap();
3711        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3712
3713        let compiler_config =
3714            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3715        let compiler = RibCompiler::new(compiler_config);
3716        let compiled = compiler.compile(expr).unwrap();
3717
3718        let mut rib_interpreter = test_deps.interpreter;
3719
3720        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3721
3722        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3723    }
3724
3725    /// Durable worker
3726    #[test]
3727    async fn test_interpreter_durable_worker_0() {
3728        let expr = r#"
3729                let worker = instance("my-worker");
3730                let result = worker.pass-through(42, 43);
3731                result
3732            "#;
3733        let expr = Expr::from_text(expr).unwrap();
3734        let test_deps = RibTestDeps::test_deps_for_pass_through_function();
3735
3736        let compiler_config =
3737            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3738        let compiler = RibCompiler::new(compiler_config);
3739        let compiled = compiler.compile(expr).unwrap();
3740
3741        let mut rib_interpreter = test_deps.interpreter;
3742
3743        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3744
3745        let expected_val = Value::Record(vec![
3746            Value::String("my-worker".to_string()),
3747            Value::String("pass-through".to_string()),
3748            Value::U64(42),
3749            Value::U32(43),
3750        ]);
3751
3752        assert_eq!(result.get_val().unwrap().value, expected_val);
3753    }
3754
3755    #[test]
3756    async fn test_interpreter_durable_worker_1_1() {
3757        let expr = r#"
3758                let x = 1;
3759                let y = 2;
3760                let inst = instance("my-worker");
3761                inst.foo-number(x, y)
3762            "#;
3763        let expr = Expr::from_text(expr).unwrap();
3764        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3765
3766        let compiler_config =
3767            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3768        let compiler = RibCompiler::new(compiler_config);
3769        let compiled = compiler.compile(expr).unwrap();
3770
3771        let mut rib_interpreter = test_deps.interpreter;
3772
3773        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3774
3775        assert_eq!(result.get_val().unwrap().value, Value::S32(1));
3776    }
3777
3778    #[test]
3779    async fn test_interpreter_durable_worker_2() {
3780        let expr = r#"
3781                let inst = instance("my-worker");
3782                let result = inst.foo("bar");
3783                result
3784            "#;
3785        let expr = Expr::from_text(expr).unwrap();
3786        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3787
3788        let compiler_config =
3789            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3790        let compiler = RibCompiler::new(compiler_config);
3791        let compiled = compiler.compile(expr).unwrap();
3792
3793        let mut rib_interpreter = test_deps.interpreter;
3794
3795        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3796
3797        assert_eq!(
3798            result.get_val().unwrap().value,
3799            Value::String("foo".to_string())
3800        );
3801    }
3802
3803    #[test]
3804    async fn test_interpreter_durable_worker_3() {
3805        let expr = r#"
3806                let my_worker = instance("my-worker");
3807                let result = my_worker.foo[api1]("bar");
3808                result
3809            "#;
3810        let expr = Expr::from_text(expr).unwrap();
3811        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3812
3813        let compiler_config =
3814            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3815        let compiler = RibCompiler::new(compiler_config);
3816        let compiled = compiler.compile(expr).unwrap();
3817
3818        let mut rib_interpreter = test_deps.interpreter;
3819
3820        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3821
3822        assert_eq!(
3823            result.get_val().unwrap().value,
3824            Value::String("foo".to_string())
3825        );
3826    }
3827
3828    #[test]
3829    async fn test_interpreter_durable_worker_4() {
3830        let expr = r#"
3831                let worker = instance("my-worker");
3832                let result = worker.bar("bar");
3833                result
3834            "#;
3835        let expr = Expr::from_text(expr).unwrap();
3836
3837        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3838
3839        let compiler = RibCompiler::new(RibCompilerConfig::new(
3840            test_deps.component_dependencies,
3841            vec![],
3842            vec![],
3843        ));
3844
3845        let compilation_error = compiler.compile(expr).unwrap_err().to_string();
3846
3847        assert_eq!(
3848            compilation_error,
3849            "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()
3850        );
3851    }
3852
3853    #[test]
3854    async fn test_interpreter_durable_worker_5() {
3855        let expr = r#"
3856                let worker = instance("my-worker");
3857                let result = worker.bar[api1]("bar");
3858                result
3859            "#;
3860        let expr = Expr::from_text(expr).unwrap();
3861        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3862
3863        let compiler_config =
3864            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3865        let compiler = RibCompiler::new(compiler_config);
3866        let compiled = compiler.compile(expr).unwrap();
3867
3868        let mut rib_interpreter = test_deps.interpreter;
3869
3870        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3871
3872        assert_eq!(
3873            result.get_val().unwrap().value,
3874            Value::String("api1-bar".to_string())
3875        );
3876    }
3877
3878    #[test]
3879    async fn test_interpreter_durable_worker_6() {
3880        let expr = r#"
3881                let worker = instance("my-worker");
3882                let result = worker.bar[api2]("bar");
3883                result
3884            "#;
3885        let expr = Expr::from_text(expr).unwrap();
3886        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3887
3888        let compiler_config =
3889            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3890        let compiler = RibCompiler::new(compiler_config);
3891        let compiled = compiler.compile(expr).unwrap();
3892
3893        let mut rib_interpreter = test_deps.interpreter;
3894
3895        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3896
3897        assert_eq!(
3898            result.get_val().unwrap().value,
3899            Value::String("api2-bar".to_string())
3900        );
3901    }
3902
3903    #[test]
3904    async fn test_interpreter_durable_worker_7() {
3905        let expr = r#"
3906                let worker = instance("my-worker");
3907                let result = worker.baz("bar");
3908                result
3909            "#;
3910        let expr = Expr::from_text(expr).unwrap();
3911        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3912
3913        let compiler_config =
3914            RibCompilerConfig::new(test_deps.component_dependencies, vec![], vec![]);
3915        let compiler = RibCompiler::new(compiler_config);
3916        let compiled = compiler.compile(expr).unwrap();
3917
3918        let mut rib_interpreter = test_deps.interpreter;
3919
3920        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3921
3922        assert_eq!(
3923            result.get_val().unwrap().value,
3924            Value::String("clock-baz".to_string())
3925        );
3926    }
3927
3928    #[test]
3929    async fn test_interpreter_durable_worker_8() {
3930        let expr = r#"
3931                let worker = instance("my-worker");
3932                let result = worker.qux("bar");
3933                result
3934            "#;
3935        let expr = Expr::from_text(expr).unwrap();
3936        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3937
3938        let compiler = RibCompiler::new(RibCompilerConfig::new(
3939            test_deps.component_dependencies.clone(),
3940            vec![],
3941            vec![],
3942        ));
3943
3944        let compiled = compiler.compile(expr).unwrap_err().to_string();
3945
3946        assert_eq!(
3947            compiled,
3948            "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()
3949        );
3950    }
3951
3952    #[test]
3953    async fn test_interpreter_durable_worker_9() {
3954        let expr = r#"
3955                let worker = instance("my-worker");
3956                let result = worker.qux[amazon:shopping-cart]("bar");
3957                result
3958            "#;
3959        let expr = Expr::from_text(expr).unwrap();
3960        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3961
3962        let compiler_config =
3963            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3964        let compiler = RibCompiler::new(compiler_config);
3965        let compiled = compiler.compile(expr).unwrap();
3966
3967        let mut rib_interpreter = test_deps.interpreter;
3968
3969        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3970
3971        assert_eq!(
3972            result.get_val().unwrap().value,
3973            Value::String("qux".to_string())
3974        );
3975    }
3976
3977    #[test]
3978    async fn test_interpreter_durable_worker_10() {
3979        let expr = r#"
3980                let worker = instance("my-worker");
3981                let result = worker.qux[wasi:clocks]("bar");
3982                result
3983            "#;
3984        let expr = Expr::from_text(expr).unwrap();
3985        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3986
3987        let compiler_config =
3988            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3989        let compiler = RibCompiler::new(compiler_config);
3990        let compiled = compiler.compile(expr).unwrap();
3991
3992        let mut rib_interpreter = test_deps.interpreter;
3993
3994        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3995
3996        assert_eq!(
3997            result.get_val().unwrap().value,
3998            Value::String("clock-qux".to_string())
3999        );
4000    }
4001
4002    #[test]
4003    async fn test_interpreter_durable_worker_11() {
4004        let expr = r#"
4005                let worker = instance("my-worker");
4006                let invokes: list<u8> = [1, 2, 3, 4];
4007
4008                for i in invokes {
4009                    yield worker.qux[wasi:clocks]("bar");
4010                };
4011
4012                "success"
4013            "#;
4014        let expr = Expr::from_text(expr).unwrap();
4015        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4016
4017        let compiler_config =
4018            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4019        let compiler = RibCompiler::new(compiler_config);
4020        let compiled = compiler.compile(expr).unwrap();
4021
4022        let mut rib_interpreter = test_deps.interpreter;
4023
4024        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4025
4026        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4027    }
4028
4029    #[test]
4030    async fn test_interpreter_durable_worker_12() {
4031        let expr = r#"
4032                let worker = instance("my-worker");
4033                for i in [1, 2, 3] {
4034                   worker.foo("${i}");
4035                   yield i;
4036                }
4037            "#;
4038        let expr = Expr::from_text(expr).unwrap();
4039        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4040
4041        let compiler_config =
4042            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4043        let compiler = RibCompiler::new(compiler_config);
4044        let compiled = compiler.compile(expr).unwrap();
4045
4046        let mut rib_interpreter = test_deps.interpreter;
4047
4048        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4049
4050        assert_eq!(
4051            result.get_val().unwrap().value,
4052            Value::List(vec![Value::S32(1), Value::S32(2), Value::S32(3)])
4053        );
4054    }
4055
4056    #[test]
4057    async fn test_interpreter_durable_worker_with_resource_0() {
4058        let expr = r#"
4059                let worker = instance("my-worker");
4060                worker.cart[golem:it]("bar")
4061            "#;
4062        let expr = Expr::from_text(expr).unwrap();
4063        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4064
4065        let compiler = RibCompiler::new(RibCompilerConfig::new(
4066            test_deps.component_dependencies.clone(),
4067            vec![],
4068            vec![],
4069        ));
4070
4071        let compiled = compiler.compile(expr);
4072
4073        assert!(compiled.is_ok());
4074    }
4075
4076    // This resource construction is a Noop, and compiler can give warnings
4077    // once we support warnings in the compiler
4078    #[test]
4079    async fn test_interpreter_durable_worker_with_resource_1() {
4080        let expr = r#"
4081                let worker = instance("my-worker");
4082                worker.cart[golem:it]("bar");
4083                "success"
4084            "#;
4085        let expr = Expr::from_text(expr).unwrap();
4086        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4087
4088        let compiler_config =
4089            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4090        let compiler = RibCompiler::new(compiler_config);
4091        let compiled = compiler.compile(expr).unwrap();
4092
4093        let mut rib_interpreter = test_deps.interpreter;
4094
4095        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4096
4097        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4098    }
4099
4100    #[test]
4101    async fn test_interpreter_durable_worker_with_resource_2() {
4102        let expr = r#"
4103                let worker = instance("my-worker");
4104                let cart = worker.cart[golem:it]("bar");
4105                let result = cart.add-item({product-id: "mac", name: "macbook", price: 1:f32, quantity: 1:u32});
4106                result
4107            "#;
4108        let expr = Expr::from_text(expr).unwrap();
4109        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4110
4111        let compiler_config =
4112            RibCompilerConfig::new(test_deps.component_dependencies, vec![], vec![]);
4113        let compiler = RibCompiler::new(compiler_config);
4114        let compiled = compiler.compile(expr).unwrap();
4115
4116        let mut rib_interpreter = test_deps.interpreter;
4117
4118        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4119
4120        assert_eq!(result, RibResult::Unit);
4121    }
4122
4123    #[test]
4124    async fn test_interpreter_durable_worker_with_resource_3() {
4125        let expr = r#"
4126                let worker = instance("my-worker");
4127                let cart = worker.cart[golem:it]("bar");
4128                cart.add-items({product-id: "mac", name: "macbook", price: 1:f32, quantity: 1:u32});
4129                "success"
4130            "#;
4131        let expr = Expr::from_text(expr).unwrap();
4132        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4133
4134        let compiler = RibCompiler::new(RibCompilerConfig::new(
4135            test_deps.component_dependencies.clone(),
4136            vec![],
4137            vec![],
4138        ));
4139
4140        let compiled = compiler.compile(expr).unwrap_err().to_string();
4141
4142        assert_eq!(compiled, "error in the following rib found at line 4, column 17\n`cart.add-items({product-id: \"mac\", name: \"macbook\", price: 1: f32, quantity: 1: u32})`\ncause: invalid function call `add-items`\nfunction 'add-items' not found\n".to_string());
4143    }
4144
4145    #[test]
4146    async fn test_interpreter_durable_worker_with_resource_4() {
4147        let expr = r#"
4148                let worker = instance("my-worker");
4149                let cart = worker.carts[golem:it]("bar");
4150                cart.add-item({product-id: "mac", name: "macbook", price: 1:f32, quantity: 1:u32});
4151                "success"
4152            "#;
4153        let expr = Expr::from_text(expr).unwrap();
4154        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4155
4156        let compiler = RibCompiler::new(RibCompilerConfig::new(
4157            test_deps.component_dependencies.clone(),
4158            vec![],
4159            vec![],
4160        ));
4161
4162        let compiled = compiler.compile(expr).unwrap_err().to_string();
4163
4164        assert_eq!(
4165            compiled,
4166            "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()
4167        );
4168    }
4169
4170    #[test]
4171    async fn test_interpreter_durable_worker_with_resource_5() {
4172        // Ephemeral
4173        let expr = r#"
4174                let worker = instance();
4175                let cart = worker.cart[golem:it]("bar");
4176                cart.add-item({product-id: "mac", name: "macbook", price: 1, quantity: 1});
4177                "success"
4178            "#;
4179        let expr = Expr::from_text(expr).unwrap();
4180        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4181
4182        let compiler_config =
4183            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4184        let compiler = RibCompiler::new(compiler_config);
4185        let compiled = compiler.compile(expr).unwrap();
4186
4187        let mut rib_interpreter = test_deps.interpreter;
4188
4189        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4190
4191        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4192    }
4193
4194    #[test]
4195    async fn test_interpreter_durable_worker_with_resource_6() {
4196        // Ephemeral
4197        let expr = r#"
4198                let worker = instance();
4199                let cart = worker.cart[golem:it]("bar");
4200                cart.add-item({product-id: "mac", name: 1, quantity: 1, price: 1});
4201                "success"
4202            "#;
4203        let expr = Expr::from_text(expr).unwrap();
4204
4205        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4206
4207        let compiler = RibCompiler::new(RibCompilerConfig::new(
4208            test_deps.component_dependencies.clone(),
4209            vec![],
4210            vec![],
4211        ));
4212
4213        let error_message = compiler.compile(expr).unwrap_err().to_string();
4214
4215        let expected = r#"
4216            error in the following rib found at line 4, column 57
4217            `1`
4218            cause: type mismatch. expected string, found s32
4219            the expression `1` is inferred as `s32` by default
4220            "#;
4221
4222        assert_eq!(error_message, strip_spaces(expected));
4223    }
4224
4225    #[test]
4226    async fn test_interpreter_durable_worker_with_resource_7() {
4227        let expr = r#"
4228                let worker = instance("my-worker");
4229                let cart = worker.cart("bar");
4230                cart.add-item({product-id: "mac", name: "apple", price: 1, quantity: 1});
4231                "success"
4232            "#;
4233        let expr = Expr::from_text(expr).unwrap();
4234        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4235
4236        let compiler_config =
4237            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4238        let compiler = RibCompiler::new(compiler_config);
4239        let compiled = compiler.compile(expr).unwrap();
4240
4241        let mut rib_interpreter = test_deps.interpreter;
4242
4243        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4244
4245        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4246    }
4247
4248    #[test]
4249    async fn test_interpreter_durable_worker_with_resource_8() {
4250        let expr = r#"
4251                let worker = instance("my-worker");
4252                let a = "mac";
4253                let b = "apple";
4254                let c = 1;
4255                let d = 1;
4256                let cart = worker.cart("bar");
4257                cart.add-item({product-id: a, name: b, quantity: c, price: d});
4258                "success"
4259            "#;
4260        let expr = Expr::from_text(expr).unwrap();
4261        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4262        let compiler_config =
4263            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4264        let compiler = RibCompiler::new(compiler_config);
4265        let compiled = compiler.compile(expr).unwrap();
4266
4267        let mut rib_interpreter = test_deps.interpreter;
4268
4269        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4270
4271        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4272    }
4273
4274    #[test]
4275    async fn test_interpreter_durable_worker_with_resource_9() {
4276        let expr = r#"
4277                let worker = instance("my-worker");
4278                let a = "mac";
4279                let b = "apple";
4280                let c = 1;
4281                let d = 1;
4282                let cart = worker.cart("bar");
4283                cart.add-item({product-id: a, name: b, quantity: c, price: d});
4284                cart.remove-item(a);
4285                cart.update-item-quantity(a, 2);
4286                let result = cart.get-cart-contents();
4287                cart.drop();
4288                result
4289            "#;
4290        let expr = Expr::from_text(expr).unwrap();
4291        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4292        let compiler_config =
4293            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4294        let compiler = RibCompiler::new(compiler_config);
4295        let compiled = compiler.compile(expr).unwrap();
4296
4297        let mut rib_interpreter = test_deps.interpreter;
4298
4299        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4300
4301        let expected_value = Value::List(vec![Value::Record(vec![
4302            Value::String("foo".to_string()),
4303            Value::String("bar".to_string()),
4304            Value::F32(10.0),
4305            Value::U32(2),
4306        ])]);
4307
4308        assert_eq!(result.get_val().unwrap().value, expected_value);
4309    }
4310
4311    #[test]
4312    async fn test_interpreter_durable_worker_with_resource_10() {
4313        let expr = r#"
4314                let my_worker = "my-worker";
4315                let worker = instance(my_worker);
4316                let a = "mac";
4317                let b = "apple";
4318                let c = 1;
4319                let d = 1;
4320                let cart = worker.cart("bar");
4321                cart.add-item({product-id: a, name: b, price: d, quantity: c});
4322                cart.remove-item(a);
4323                cart.update-item-quantity(a, 2);
4324                let result = cart.get-cart-contents();
4325                cart.drop();
4326                result
4327            "#;
4328        let expr = Expr::from_text(expr).unwrap();
4329        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4330
4331        let compiler_config =
4332            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4333        let compiler = RibCompiler::new(compiler_config);
4334        let compiled = compiler.compile(expr).unwrap();
4335
4336        let mut rib_interpreter = test_deps.interpreter;
4337
4338        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4339
4340        let expected_value = Value::List(vec![Value::Record(vec![
4341            Value::String("foo".to_string()),
4342            Value::String("bar".to_string()),
4343            Value::F32(10.0),
4344            Value::U32(2),
4345        ])]);
4346
4347        assert_eq!(result.get_val().unwrap().value, expected_value);
4348    }
4349
4350    #[test]
4351    async fn test_interpreter_durable_worker_with_resource_11() {
4352        let expr = r#"
4353                let worker = instance(request.path.user-id: string);
4354                let result = worker.qux[amazon:shopping-cart]("bar");
4355                result
4356            "#;
4357        let expr = Expr::from_text(expr).unwrap();
4358
4359        let mut input = HashMap::new();
4360
4361        // Passing request data as input to interpreter
4362        let rib_input_key = "request";
4363        let rib_input_value = ValueAndType::new(
4364            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4365            record(vec![field("path", record(vec![field("user-id", str())]))]),
4366        );
4367
4368        input.insert(rib_input_key.to_string(), rib_input_value);
4369
4370        let rib_input = RibInput::new(input);
4371
4372        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(Some(rib_input));
4373
4374        let compiler_config =
4375            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4376        let compiler = RibCompiler::new(compiler_config);
4377        let compiled = compiler.compile(expr).unwrap();
4378
4379        let mut rib_interpreter = test_deps.interpreter;
4380
4381        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4382
4383        assert_eq!(
4384            result.get_val().unwrap().value,
4385            Value::String("qux".to_string())
4386        )
4387    }
4388
4389    #[test]
4390    async fn test_interpreter_durable_worker_with_resource_12() {
4391        let expr = r#"
4392                let user_id1: string = request.path.user-id;
4393                let user_id2: string = request.path.user-id;
4394                let worker1 = instance(user_id1);
4395                let result1 = worker1.qux[amazon:shopping-cart]("bar");
4396                let worker2 = instance(user_id2);
4397                let result2 = worker2.qux[amazon:shopping-cart]("bar");
4398                user_id2
4399            "#;
4400        let expr = Expr::from_text(expr).unwrap();
4401
4402        let mut input = HashMap::new();
4403
4404        let rib_input_key = "request";
4405
4406        let rib_input_value = ValueAndType::new(
4407            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4408            record(vec![field("path", record(vec![field("user-id", str())]))]),
4409        );
4410
4411        input.insert(rib_input_key.to_string(), rib_input_value);
4412
4413        let rib_input = RibInput::new(input);
4414
4415        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(Some(rib_input));
4416
4417        let compiler_config =
4418            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4419
4420        let compiler = RibCompiler::new(compiler_config);
4421
4422        let compiled = compiler.compile(expr).unwrap();
4423
4424        let mut rib_interpreter = test_deps.interpreter;
4425
4426        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4427
4428        assert_eq!(result.get_val().unwrap(), "user".into_value_and_type());
4429    }
4430
4431    #[test]
4432    async fn test_interpreter_durable_worker_with_resource_13() {
4433        let expr = r#"
4434                let worker1 = instance("foo");
4435                let result = worker.qux[amazon:shopping-cart]("bar");
4436                "success"
4437            "#;
4438        let expr = Expr::from_text(expr).unwrap();
4439
4440        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4441
4442        let compiler = RibCompiler::new(RibCompilerConfig::new(
4443            test_deps.component_dependencies.clone(),
4444            vec![],
4445            vec![],
4446        ));
4447
4448        let error = compiler.compile(expr).unwrap_err().to_string();
4449
4450        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");
4451    }
4452
4453    #[test]
4454    async fn test_interpreter_durable_worker_with_resource_14() {
4455        let expr = r#"
4456                let worker = instance(1: u32);
4457                let result = worker.qux[amazon:shopping-cart]("bar");
4458                "success"
4459            "#;
4460        let expr = Expr::from_text(expr).unwrap();
4461
4462        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4463
4464        let compiler = RibCompiler::new(RibCompilerConfig::new(
4465            test_deps.component_dependencies.clone(),
4466            vec![],
4467            vec![],
4468        ));
4469
4470        let error = compiler.compile(expr).unwrap_err().to_string();
4471
4472        let expected = r#"
4473            error in the following rib found at line 2, column 39
4474            `1: u32`
4475            cause: expected string, found u32
4476            "#;
4477
4478        assert_eq!(error, strip_spaces(expected));
4479    }
4480
4481    #[test]
4482    async fn test_interpreter_durable_worker_with_resource_15() {
4483        let expr = r#"
4484                let worker = instance("my-worker-name");
4485                let result = worker.qux[amazon:shopping-cart]("param1");
4486                result
4487            "#;
4488        let expr = Expr::from_text(expr).unwrap();
4489
4490        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4491
4492        let compiler_config =
4493            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4494
4495        let compiler = RibCompiler::new(compiler_config);
4496
4497        let compiled = compiler.compile(expr).unwrap();
4498
4499        let mut rib_interpreter = test_deps.interpreter;
4500
4501        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4502
4503        let result_val = result.get_val().unwrap();
4504
4505        assert_eq!(result_val.value, Value::String("qux".to_string()));
4506    }
4507
4508    #[test]
4509    async fn test_interpreter_durable_worker_with_resource_16() {
4510        let expr = r#"
4511                let x: string = request.path.user-id;
4512                let worker = instance(x);
4513                let cart = worker.cart("bar");
4514                let result = cart.get-cart-contents();
4515                result
4516            "#;
4517
4518        let expr = Expr::from_text(expr).unwrap();
4519
4520        let mut input = HashMap::new();
4521
4522        let rib_input_key = "request";
4523
4524        let rib_input_value = ValueAndType::new(
4525            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4526            record(vec![field("path", record(vec![field("user-id", str())]))]),
4527        );
4528
4529        input.insert(rib_input_key.to_string(), rib_input_value);
4530
4531        let rib_input = RibInput::new(input);
4532
4533        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4534
4535        let compiler_config =
4536            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4537
4538        let compiler = RibCompiler::new(compiler_config);
4539
4540        let compiled = compiler.compile(expr).unwrap();
4541
4542        let mut rib_interpreter = test_deps.interpreter;
4543
4544        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4545
4546        let result_val = result.get_val().unwrap();
4547
4548        let expected_val = Value::List(vec![Value::Record(vec![
4549            Value::String("foo".to_string()),
4550            Value::String("bar".to_string()),
4551            Value::F32(10.0),
4552            Value::U32(2),
4553        ])]);
4554
4555        assert_eq!(result_val.value, expected_val)
4556    }
4557
4558    #[test]
4559    async fn test_interpreter_durable_worker_with_resource_17() {
4560        let expr = r#"
4561                let x: string = request.path.user-id;
4562                let min: u8 = 1;
4563                let max: u8 = 3;
4564                let result = for i in min..=max {
4565                   let worker = instance("my-worker");
4566                   let cart = worker.cart("bar");
4567                   yield cart.get-cart-contents();
4568                };
4569                result
4570            "#;
4571        let expr = Expr::from_text(expr).unwrap();
4572
4573        let mut input = HashMap::new();
4574
4575        let rib_input_key = "request";
4576
4577        let rib_input_value = ValueAndType::new(
4578            Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4579            record(vec![field("path", record(vec![field("user-id", str())]))]),
4580        );
4581
4582        input.insert(rib_input_key.to_string(), rib_input_value);
4583
4584        let rib_input = RibInput::new(input);
4585
4586        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4587
4588        let compiler_config =
4589            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4590
4591        let compiler = RibCompiler::new(compiler_config);
4592
4593        let compiled = compiler.compile(expr).unwrap();
4594
4595        let mut rib_interpreter = test_deps.interpreter;
4596
4597        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4598
4599        let result_val = result.get_val().unwrap().value;
4600
4601        let cart_contents = Value::List(vec![Value::Record(vec![
4602            Value::String("foo".to_string()),
4603            Value::String("bar".to_string()),
4604            Value::F32(10.0),
4605            Value::U32(2),
4606        ])]);
4607
4608        let expected_val = Value::List(vec![
4609            cart_contents.clone(),
4610            cart_contents.clone(),
4611            cart_contents,
4612        ]);
4613
4614        assert_eq!(result_val, expected_val);
4615    }
4616
4617    #[test]
4618    async fn test_interpreter_durable_worker_with_resource_18() {
4619        let expr = r#"
4620
4621            let initial = 1;
4622            let final = 5;
4623            let range = initial..final;
4624            let worker = instance("my-worker");
4625            let cart = worker.cart[golem:it]("bar");
4626
4627            for i in range {
4628                yield cart.add-item(request.body);
4629            };
4630
4631            "success"
4632        "#;
4633        let expr = Expr::from_text(expr).unwrap();
4634
4635        let mut input = HashMap::new();
4636
4637        let rib_input_key = "request";
4638
4639        let rib_input_value = ValueAndType::new(
4640            Value::Record(vec![Value::Record(vec![
4641                Value::String("mac-book".to_string()),
4642                Value::String("mac".to_string()),
4643                Value::U32(1),
4644                Value::F32(1.0),
4645            ])]),
4646            record(vec![field(
4647                "body",
4648                record(vec![
4649                    field("name", str()),
4650                    field("product-id", str()),
4651                    field("quantity", u32()),
4652                    field("price", f32()),
4653                ]),
4654            )]),
4655        );
4656
4657        input.insert(rib_input_key.to_string(), rib_input_value);
4658
4659        let rib_input = RibInput::new(input);
4660
4661        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4662
4663        let compiler_config =
4664            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4665
4666        let compiler = RibCompiler::new(compiler_config);
4667
4668        let compiled = compiler.compile(expr).unwrap();
4669
4670        let mut rib_interpreter = test_deps.interpreter;
4671
4672        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4673
4674        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4675    }
4676
4677    #[test]
4678    async fn test_interpreter_durable_worker_with_resource_19() {
4679        let expr = r#"
4680
4681            let initial = 1;
4682            let final = 5;
4683            let range = initial..final;
4684
4685            for i in range {
4686                let worker = instance("my-worker");
4687                let cart = worker.cart[golem:it]("bar");
4688                yield cart.add-item(request.body);
4689            };
4690
4691            "success"
4692        "#;
4693        let expr = Expr::from_text(expr).unwrap();
4694
4695        let mut input = HashMap::new();
4696
4697        let rib_input_key = "request";
4698
4699        let rib_input_value = ValueAndType::new(
4700            Value::Record(vec![Value::Record(vec![
4701                Value::String("mac-book".to_string()),
4702                Value::String("mac".to_string()),
4703                Value::U32(1),
4704                Value::F32(1.0),
4705            ])]),
4706            record(vec![field(
4707                "body",
4708                record(vec![
4709                    field("name", str()),
4710                    field("product-id", str()),
4711                    field("quantity", u32()),
4712                    field("price", f32()),
4713                ]),
4714            )]),
4715        );
4716
4717        input.insert(rib_input_key.to_string(), rib_input_value);
4718
4719        let rib_input = RibInput::new(input);
4720
4721        let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4722
4723        let compiler_config =
4724            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4725
4726        let compiler = RibCompiler::new(compiler_config);
4727
4728        let compiled = compiler.compile(expr).unwrap();
4729
4730        let mut rib_interpreter = test_deps.interpreter;
4731
4732        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4733
4734        assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4735    }
4736
4737    #[test]
4738    async fn test_interpreter_custom_instance() {
4739        let expr = r#"
4740                let text = "nyc";
4741                let number = "usa";
4742                let boolean = true;
4743                let optional-str = some("optional");
4744                let optional-number = some(2);
4745                let list-of-str = ["a", "b", "c"];
4746                let tuple = (text, 1, boolean, optional-str);
4747                let record = {city: text, country: number};
4748                let result = ok(text);
4749                let result-ok = ok(text);
4750                let result-err = err(1);
4751                let variant = foo("bar");
4752                let weather-agent = weather-agent("text", 1, true, optional-str, optional-number, none, none, list-of-str, tuple, record, result, result-ok, result-err, variant);
4753                let first-result = weather-agent.get-weather("bar");
4754                let assistant-agent = assistant-agent("my assistant");
4755                let second-result = assistant-agent.ask("foo", "bar");
4756                {weather: first-result, assistant: second-result}
4757            "#;
4758
4759        let weather_agent_constructor_param_types: Vec<AnalysedType> = vec![
4760            str(),
4761            s32(),
4762            bool(),
4763            option(str()),
4764            option(u64()),
4765            option(str()),
4766            option(u64()),
4767            list(str()),
4768            tuple(vec![str(), s32(), bool(), option(str())]),
4769            record(vec![field("city", str()), field("country", str())]),
4770            result(str(), s32()),
4771            result_ok(str()),
4772            result_err(s32()),
4773            variant(vec![
4774                case("foo", str()),
4775                case("bar", s32()),
4776                unit_case("baz"),
4777            ]),
4778        ];
4779
4780        let custom_spec1 = CustomInstanceSpec {
4781            instance_name: "weather-agent".to_string(),
4782            parameter_types: weather_agent_constructor_param_types,
4783            interface_name: Some(InterfaceName {
4784                name: "weather-agent".to_string(),
4785                version: None,
4786            }),
4787        };
4788
4789        let custom_spec2 = CustomInstanceSpec {
4790            instance_name: "assistant-agent".to_string(),
4791            parameter_types: vec![str()],
4792            interface_name: Some(InterfaceName {
4793                name: "assistant-agent".to_string(),
4794                version: None,
4795            }),
4796        };
4797
4798        let expr = Expr::from_text(expr).unwrap();
4799        let test_deps = RibTestDeps::test_deps_with_multiple_interfaces_simple(None);
4800
4801        let compiler_config = RibCompilerConfig::new(
4802            test_deps.component_dependencies.clone(),
4803            vec![],
4804            vec![custom_spec1, custom_spec2],
4805        );
4806        let compiler = RibCompiler::new(compiler_config);
4807        let compiled = compiler
4808            .compile(expr)
4809            .map_err(|err| err.to_string())
4810            .unwrap();
4811
4812        let mut rib_interpreter = test_deps.interpreter;
4813
4814        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4815
4816        let expected = Value::Record(vec![
4817            Value::Record(vec![
4818                // worker-name
4819                Value::String(
4820                    "weather-agent(\"text\",1,true,some(\"optional\"),some(2),none,none,[\"a\", \"b\", \"c\"],(\"nyc\", 1, true, some(\"optional\")),{city: \"nyc\", country: \"usa\"},ok(\"nyc\"),ok(\"nyc\"),err(1),foo(\"bar\"))".to_string(),
4821                ),
4822                // function-name
4823                Value::String("my:agent/weather-agent.{get-weather}".to_string()),
4824                // args concatenated
4825                Value::String("\"bar\"".to_string()),
4826            ]),
4827            Value::Record(vec![
4828                // worker-name
4829                Value::String("assistant-agent(\"my assistant\")".to_string()),
4830                // function-name
4831                Value::String("my:agent/assistant-agent.{ask}".to_string()),
4832                // args concatenated
4833                Value::String("\"foo\"\"bar\"".to_string()),
4834            ]),
4835        ]);
4836
4837        assert_eq!(result.get_val().unwrap().value, expected);
4838    }
4839
4840    #[test]
4841    async fn test_interpreter_custom_instance_conflicting_variants() {
4842        let expr = r#"
4843                let x = instance("abc");
4844                let r1 = x.func1(foo("bar"));
4845                let r2 = x.func2(foo(["baz", "qux"]));
4846                {result1: r1, result2: r2}
4847            "#;
4848
4849        let expr = Expr::from_text(expr).unwrap();
4850        let test_deps = RibTestDeps::test_deps_with_variant_conflicts(None);
4851
4852        let compiler_config =
4853            RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4854        let compiler = RibCompiler::new(compiler_config);
4855        let compiled = compiler
4856            .compile(expr)
4857            .map_err(|err| err.to_string())
4858            .unwrap();
4859
4860        let mut rib_interpreter = test_deps.interpreter;
4861
4862        let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4863
4864        let expected = Value::Record(vec![
4865            Value::Variant {
4866                case_idx: 0,
4867                case_value: Some(Box::new(Value::String("bar".to_string()))),
4868            },
4869            Value::Variant {
4870                case_idx: 0,
4871                case_value: Some(Box::new(Value::List(vec![
4872                    Value::String("baz".to_string()),
4873                    Value::String("qux".to_string()),
4874                ]))),
4875            },
4876        ]);
4877        assert_eq!(result.get_val().unwrap().value, expected);
4878    }
4879
4880    mod test_utils {
4881        use crate::interpreter::rib_interpreter::internal::NoopRibFunctionInvoke;
4882        use crate::interpreter::rib_interpreter::Interpreter;
4883        use crate::{
4884            ComponentDependency, ComponentDependencyKey, DefaultWorkerNameGenerator,
4885            EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, GenerateWorkerName,
4886            GetLiteralValue, InstructionId, RibComponentFunctionInvoke, RibFunctionInvokeResult,
4887            RibInput,
4888        };
4889        use async_trait::async_trait;
4890        use golem_wasm_ast::analysis::analysed_type::{
4891            case, f32, field, handle, list, option, r#enum, record, result, s32, str, tuple, u32,
4892            u64, unit_case, variant,
4893        };
4894        use golem_wasm_ast::analysis::{
4895            AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedFunctionResult,
4896            AnalysedInstance, AnalysedResourceId, AnalysedResourceMode, AnalysedType, TypeHandle,
4897        };
4898        use golem_wasm_rpc::{print_value_and_type, IntoValueAndType, Value, ValueAndType};
4899        use std::sync::Arc;
4900        use uuid::Uuid;
4901
4902        pub(crate) fn strip_spaces(input: &str) -> String {
4903            let lines = input.lines();
4904
4905            let first_line = lines
4906                .clone()
4907                .find(|line| !line.trim().is_empty())
4908                .unwrap_or("");
4909            let margin_width = first_line.chars().take_while(|c| c.is_whitespace()).count();
4910
4911            let result = lines
4912                .map(|line| {
4913                    if line.trim().is_empty() {
4914                        String::new()
4915                    } else {
4916                        line[margin_width..].to_string()
4917                    }
4918                })
4919                .collect::<Vec<String>>()
4920                .join("\n");
4921
4922            result.strip_prefix("\n").unwrap_or(&result).to_string()
4923        }
4924
4925        pub(crate) fn get_analysed_type_variant() -> AnalysedType {
4926            variant(vec![
4927                case("register-user", u64()),
4928                case("process-user", str()),
4929                unit_case("validate"),
4930            ])
4931        }
4932
4933        pub(crate) fn get_analysed_type_record() -> AnalysedType {
4934            record(vec![
4935                field(
4936                    "request",
4937                    record(vec![field("path", record(vec![field("user", str())]))]),
4938                ),
4939                field("y", str()),
4940            ])
4941        }
4942
4943        pub(crate) fn get_analysed_type_result() -> AnalysedType {
4944            result(u64(), str())
4945        }
4946
4947        pub(crate) fn get_analysed_type_enum() -> AnalysedType {
4948            r#enum(&["prod", "dev", "test"])
4949        }
4950
4951        pub(crate) fn get_analysed_typ_str() -> AnalysedType {
4952            str()
4953        }
4954
4955        pub(crate) fn get_analysed_typ_u64() -> AnalysedType {
4956            u64()
4957        }
4958
4959        pub(crate) fn get_analysed_type_tuple() -> AnalysedType {
4960            tuple(vec![
4961                get_analysed_typ_u64(),
4962                get_analysed_type_result(),
4963                get_analysed_typ_str(),
4964                get_analysed_type_record(),
4965                get_analysed_type_variant(),
4966                get_analysed_type_variant(),
4967                get_analysed_type_variant(),
4968                get_analysed_type_enum(),
4969                get_analysed_type_enum(),
4970                get_analysed_type_enum(),
4971            ])
4972        }
4973
4974        pub(crate) fn configurable_metadata(
4975            function_name: &str,
4976            input_types: Vec<AnalysedType>,
4977            output: Option<AnalysedType>,
4978        ) -> Vec<ComponentDependency> {
4979            let analysed_function_parameters = input_types
4980                .into_iter()
4981                .enumerate()
4982                .map(|(index, typ)| AnalysedFunctionParameter {
4983                    name: format!("param{index}"),
4984                    typ,
4985                })
4986                .collect();
4987
4988            let result = output.map(|typ| AnalysedFunctionResult { typ });
4989
4990            let component_info = ComponentDependencyKey {
4991                component_name: "foo".to_string(),
4992                component_id: Uuid::new_v4(),
4993                component_version: 0,
4994                root_package_name: None,
4995                root_package_version: None,
4996            };
4997
4998            vec![ComponentDependency::new(
4999                component_info,
5000                vec![AnalysedExport::Function(AnalysedFunction {
5001                    name: function_name.to_string(),
5002                    parameters: analysed_function_parameters,
5003                    result,
5004                })],
5005            )]
5006        }
5007
5008        pub(crate) fn get_metadata_with_resource_with_params() -> Vec<ComponentDependency> {
5009            get_metadata_with_resource(vec![AnalysedFunctionParameter {
5010                name: "user-id".to_string(),
5011                typ: str(),
5012            }])
5013        }
5014
5015        pub(crate) fn get_metadata_with_resource_without_params() -> Vec<ComponentDependency> {
5016            get_metadata_with_resource(vec![])
5017        }
5018
5019        pub(crate) fn get_metadata_simple_with_variant_conflicts() -> Vec<ComponentDependency> {
5020            let func1 = AnalysedFunction {
5021                name: "func1".to_string(),
5022                parameters: vec![AnalysedFunctionParameter {
5023                    name: "arg1".to_string(),
5024                    typ: variant(vec![case("foo", str())]),
5025                }],
5026                result: Some(AnalysedFunctionResult { typ: str() }),
5027            };
5028
5029            let func2 = AnalysedFunction {
5030                name: "func2".to_string(),
5031                parameters: vec![AnalysedFunctionParameter {
5032                    name: "arg1".to_string(),
5033                    typ: variant(vec![
5034                        case("foo", list(str())), // just different types to that of the foo and bar
5035                    ]),
5036                }],
5037                result: Some(AnalysedFunctionResult { typ: str() }),
5038            };
5039
5040            let component_info = ComponentDependencyKey {
5041                component_name: "foo".to_string(),
5042                component_id: Uuid::new_v4(),
5043                component_version: 0,
5044                root_package_name: None,
5045                root_package_version: None,
5046            };
5047
5048            vec![ComponentDependency::new(
5049                component_info,
5050                vec![
5051                    AnalysedExport::Function(func1),
5052                    AnalysedExport::Function(func2),
5053                ],
5054            )]
5055        }
5056
5057        pub(crate) fn get_metadata_with_multiple_interfaces_simple() -> Vec<ComponentDependency> {
5058            // Exist in only amazon:shopping-cart/api1
5059            let get_weather = AnalysedFunction {
5060                name: "get-weather".to_string(),
5061                parameters: vec![AnalysedFunctionParameter {
5062                    name: "arg1".to_string(),
5063                    typ: str(),
5064                }],
5065                result: Some(AnalysedFunctionResult { typ: str() }),
5066            };
5067
5068            let ask = AnalysedFunction {
5069                name: "ask".to_string(),
5070                parameters: vec![
5071                    AnalysedFunctionParameter {
5072                        name: "arg1".to_string(),
5073                        typ: str(),
5074                    },
5075                    AnalysedFunctionParameter {
5076                        name: "arg2".to_string(),
5077                        typ: str(),
5078                    },
5079                ],
5080                result: Some(AnalysedFunctionResult { typ: s32() }),
5081            };
5082
5083            let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
5084                name: "my:agent/weather-agent".to_string(),
5085                functions: vec![get_weather],
5086            });
5087
5088            let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
5089                name: "my:agent/assistant-agent".to_string(),
5090                functions: vec![ask],
5091            });
5092
5093            let analysed_export3 = AnalysedExport::Function(AnalysedFunction {
5094                name: "variant-param".to_string(),
5095                parameters: vec![AnalysedFunctionParameter {
5096                    name: "arg1".to_string(),
5097                    typ: variant(vec![case("foo", str()), case("bar", s32())]),
5098                }],
5099                result: Some(AnalysedFunctionResult { typ: str() }),
5100            });
5101
5102            let component_info = ComponentDependencyKey {
5103                component_name: "foo".to_string(),
5104                component_id: Uuid::new_v4(),
5105                component_version: 0,
5106                root_package_name: None,
5107                root_package_version: None,
5108            };
5109
5110            vec![ComponentDependency::new(
5111                component_info,
5112                vec![analysed_export1, analysed_export2, analysed_export3],
5113            )]
5114        }
5115
5116        pub(crate) fn get_metadata_with_multiple_interfaces() -> Vec<ComponentDependency> {
5117            // Exist in only amazon:shopping-cart/api1
5118            let analysed_function_in_api1 = AnalysedFunction {
5119                name: "foo".to_string(),
5120                parameters: vec![AnalysedFunctionParameter {
5121                    name: "arg1".to_string(),
5122                    typ: str(),
5123                }],
5124                result: Some(AnalysedFunctionResult { typ: str() }),
5125            };
5126
5127            let analysed_function_in_api1_number = AnalysedFunction {
5128                name: "foo-number".to_string(),
5129                parameters: vec![
5130                    AnalysedFunctionParameter {
5131                        name: "arg1".to_string(),
5132                        typ: u64(),
5133                    },
5134                    AnalysedFunctionParameter {
5135                        name: "arg2".to_string(),
5136                        typ: s32(),
5137                    },
5138                ],
5139                result: Some(AnalysedFunctionResult { typ: s32() }),
5140            };
5141
5142            // Exist in both amazon:shopping-cart/api1 and amazon:shopping-cart/api2
5143            let analysed_function_in_api1_and_api2 = AnalysedFunction {
5144                name: "bar".to_string(),
5145                parameters: vec![AnalysedFunctionParameter {
5146                    name: "arg1".to_string(),
5147                    typ: str(),
5148                }],
5149                result: Some(AnalysedFunctionResult { typ: str() }),
5150            };
5151
5152            // Exist in only wasi:clocks/monotonic-clock
5153            let analysed_function_in_wasi = AnalysedFunction {
5154                name: "baz".to_string(),
5155                parameters: vec![AnalysedFunctionParameter {
5156                    name: "arg1".to_string(),
5157                    typ: str(),
5158                }],
5159                result: Some(AnalysedFunctionResult { typ: str() }),
5160            };
5161
5162            // Exist in wasi:clocks/monotonic-clock and amazon:shopping-cart/api1
5163            let analysed_function_in_wasi_and_api1 = AnalysedFunction {
5164                name: "qux".to_string(),
5165                parameters: vec![AnalysedFunctionParameter {
5166                    name: "arg1".to_string(),
5167                    typ: str(),
5168                }],
5169                result: Some(AnalysedFunctionResult { typ: str() }),
5170            };
5171
5172            let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
5173                name: "amazon:shopping-cart/api1".to_string(),
5174                functions: vec![
5175                    analysed_function_in_api1,
5176                    analysed_function_in_api1_number,
5177                    analysed_function_in_api1_and_api2.clone(),
5178                    analysed_function_in_wasi_and_api1.clone(),
5179                ],
5180            });
5181
5182            let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
5183                name: "amazon:shopping-cart/api2".to_string(),
5184                functions: vec![analysed_function_in_api1_and_api2],
5185            });
5186
5187            let analysed_export3 = AnalysedExport::Instance(AnalysedInstance {
5188                name: "wasi:clocks/monotonic-clock".to_string(),
5189                functions: vec![
5190                    analysed_function_in_wasi,
5191                    analysed_function_in_wasi_and_api1,
5192                ],
5193            });
5194
5195            let component_info = ComponentDependencyKey {
5196                component_name: "foo".to_string(),
5197                component_id: Uuid::new_v4(),
5198                component_version: 0,
5199                root_package_name: None,
5200                root_package_version: None,
5201            };
5202
5203            vec![ComponentDependency::new(
5204                component_info,
5205                vec![analysed_export1, analysed_export2, analysed_export3],
5206            )]
5207        }
5208
5209        fn get_metadata_with_resource(
5210            resource_constructor_params: Vec<AnalysedFunctionParameter>,
5211        ) -> Vec<ComponentDependency> {
5212            let instance = AnalysedExport::Instance(AnalysedInstance {
5213                name: "golem:it/api".to_string(),
5214                functions: vec![
5215                    AnalysedFunction {
5216                        name: "[constructor]cart".to_string(),
5217                        parameters: resource_constructor_params,
5218                        result: Some(AnalysedFunctionResult {
5219                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5220                        }),
5221                    },
5222                    AnalysedFunction {
5223                        name: "[static]cart.create".to_string(),
5224                        parameters: vec![AnalysedFunctionParameter {
5225                            name: "item-name".to_string(),
5226                            typ: str(),
5227                        }],
5228                        result: Some(AnalysedFunctionResult {
5229                            typ: AnalysedType::Handle(TypeHandle {
5230                                name: Some("cart".to_string()),
5231                                owner: Some("golem:it/api".to_string()),
5232                                resource_id: AnalysedResourceId(0),
5233                                mode: AnalysedResourceMode::Owned,
5234                            }),
5235                        }),
5236                    },
5237                    AnalysedFunction {
5238                        name: "[static]cart.create-safe".to_string(),
5239                        parameters: vec![AnalysedFunctionParameter {
5240                            name: "item-name".to_string(),
5241                            typ: str(),
5242                        }],
5243                        result: Some(AnalysedFunctionResult {
5244                            typ: result(
5245                                AnalysedType::Handle(TypeHandle {
5246                                    name: Some("cart".to_string()),
5247                                    owner: Some("golem:it/api".to_string()),
5248                                    resource_id: AnalysedResourceId(0),
5249                                    mode: AnalysedResourceMode::Owned,
5250                                }),
5251                                str(),
5252                            ),
5253                        }),
5254                    },
5255                    AnalysedFunction {
5256                        name: "[method]cart.add-item".to_string(),
5257                        parameters: vec![
5258                            AnalysedFunctionParameter {
5259                                name: "self".to_string(),
5260                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5261                            },
5262                            AnalysedFunctionParameter {
5263                                name: "item".to_string(),
5264                                typ: record(vec![
5265                                    field("product-id", str()),
5266                                    field("name", str()),
5267                                    field("price", f32()),
5268                                    field("quantity", u32()),
5269                                ]),
5270                            },
5271                        ],
5272                        result: None,
5273                    },
5274                    AnalysedFunction {
5275                        name: "[method]cart.remove-item".to_string(),
5276                        parameters: vec![
5277                            AnalysedFunctionParameter {
5278                                name: "self".to_string(),
5279                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5280                            },
5281                            AnalysedFunctionParameter {
5282                                name: "product-id".to_string(),
5283                                typ: str(),
5284                            },
5285                        ],
5286                        result: None,
5287                    },
5288                    AnalysedFunction {
5289                        name: "[method]cart.update-item-quantity".to_string(),
5290                        parameters: vec![
5291                            AnalysedFunctionParameter {
5292                                name: "self".to_string(),
5293                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5294                            },
5295                            AnalysedFunctionParameter {
5296                                name: "product-id".to_string(),
5297                                typ: str(),
5298                            },
5299                            AnalysedFunctionParameter {
5300                                name: "quantity".to_string(),
5301                                typ: u32(),
5302                            },
5303                        ],
5304                        result: None,
5305                    },
5306                    AnalysedFunction {
5307                        name: "[method]cart.checkout".to_string(),
5308                        parameters: vec![AnalysedFunctionParameter {
5309                            name: "self".to_string(),
5310                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5311                        }],
5312                        result: Some(AnalysedFunctionResult {
5313                            typ: variant(vec![
5314                                case("error", str()),
5315                                case("success", record(vec![field("order-id", str())])),
5316                            ]),
5317                        }),
5318                    },
5319                    AnalysedFunction {
5320                        name: "[method]cart.get-cart-contents".to_string(),
5321                        parameters: vec![AnalysedFunctionParameter {
5322                            name: "self".to_string(),
5323                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5324                        }],
5325                        result: Some(AnalysedFunctionResult {
5326                            typ: list(record(vec![
5327                                field("product-id", str()),
5328                                field("name", str()),
5329                                field("price", f32()),
5330                                field("quantity", u32()),
5331                            ])),
5332                        }),
5333                    },
5334                    AnalysedFunction {
5335                        name: "[method]cart.merge-with".to_string(),
5336                        parameters: vec![
5337                            AnalysedFunctionParameter {
5338                                name: "self".to_string(),
5339                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5340                            },
5341                            AnalysedFunctionParameter {
5342                                name: "other-cart".to_string(),
5343                                typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5344                            },
5345                        ],
5346                        result: None,
5347                    },
5348                    AnalysedFunction {
5349                        name: "[drop]cart".to_string(),
5350                        parameters: vec![AnalysedFunctionParameter {
5351                            name: "self".to_string(),
5352                            typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5353                        }],
5354                        result: None,
5355                    },
5356                ],
5357            });
5358
5359            let component_info = ComponentDependencyKey {
5360                component_name: "foo".to_string(),
5361                component_id: Uuid::new_v4(),
5362                component_version: 0,
5363                root_package_name: None,
5364                root_package_version: None,
5365            };
5366
5367            vec![ComponentDependency::new(component_info, vec![instance])]
5368        }
5369
5370        pub(crate) fn get_value_and_type(
5371            analysed_type: &AnalysedType,
5372            wasm_wave_str: &str,
5373        ) -> ValueAndType {
5374            golem_wasm_rpc::parse_value_and_type(analysed_type, wasm_wave_str).unwrap()
5375        }
5376
5377        pub(crate) fn interpreter_with_noop_function_invoke(
5378            input: Option<RibInput>,
5379        ) -> Interpreter {
5380            let invoke: Arc<dyn RibComponentFunctionInvoke + Send + Sync> =
5381                Arc::new(NoopRibFunctionInvoke);
5382
5383            Interpreter {
5384                input: input.unwrap_or_default(),
5385                invoke,
5386                generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5387            }
5388        }
5389
5390        // Interpreter which always returns a specific response
5391        pub(crate) fn interpreter_with_static_function_response(
5392            result_value: &ValueAndType,
5393            input: Option<RibInput>,
5394        ) -> Interpreter {
5395            let value = result_value.clone();
5396
5397            let invoke = Arc::new(TestInvoke1 { value });
5398
5399            Interpreter {
5400                input: input.unwrap_or_default(),
5401                invoke,
5402                generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5403            }
5404        }
5405
5406        // The interpreter that always returns a record value consisting of function name, worker name etc
5407        // for every function calls in Rib.
5408        // Example : `my-instance.qux[amazon:shopping-cart]("bar")` will return a record
5409        // that contains the actual worker-name of my-instance, the function name `qux` and arguments
5410        // It helps ensures that interpreter invokes the function at the expected worker.
5411        pub(crate) fn interpreter_with_resource_function_invoke_impl(
5412            rib_input: Option<RibInput>,
5413        ) -> Interpreter {
5414            let invoke: Arc<dyn RibComponentFunctionInvoke + Send + Sync> =
5415                Arc::new(ResourceFunctionsInvoke);
5416
5417            Interpreter {
5418                input: rib_input.unwrap_or_default(),
5419                invoke,
5420                generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5421            }
5422        }
5423
5424        // A simple interpreter that returns response based on the function
5425        pub(crate) fn interpreter_for_global_functions(input: Option<RibInput>) -> Interpreter {
5426            let invoke = Arc::new(TestInvoke3);
5427
5428            Interpreter {
5429                input: input.unwrap_or_default(),
5430                invoke,
5431                generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5432            }
5433        }
5434
5435        struct TestInvoke1 {
5436            value: ValueAndType,
5437        }
5438
5439        #[async_trait]
5440        impl RibComponentFunctionInvoke for TestInvoke1 {
5441            async fn invoke(
5442                &self,
5443                _component_dependency_key: ComponentDependencyKey,
5444                _instruction_id: &InstructionId,
5445                _worker_name: EvaluatedWorkerName,
5446                _fqn: EvaluatedFqFn,
5447                _args: EvaluatedFnArgs,
5448                _return_type: Option<AnalysedType>,
5449            ) -> RibFunctionInvokeResult {
5450                let value = self.value.clone();
5451                Ok(Some(value))
5452            }
5453        }
5454
5455        struct PassThroughFunctionInvoke;
5456
5457        #[async_trait]
5458        impl RibComponentFunctionInvoke for PassThroughFunctionInvoke {
5459            async fn invoke(
5460                &self,
5461                _component_dependency_key: ComponentDependencyKey,
5462                _instruction_id: &InstructionId,
5463                worker_name: EvaluatedWorkerName,
5464                function_name: EvaluatedFqFn,
5465                args: EvaluatedFnArgs,
5466                _return_type: Option<AnalysedType>,
5467            ) -> RibFunctionInvokeResult {
5468                let analysed_type = record(vec![
5469                    field("worker-name", str()),
5470                    field("function-name", str()),
5471                    field("args0", u64()),
5472                    field("args1", u32()),
5473                ]);
5474
5475                let worker_name = Value::String(worker_name.0);
5476                let function_name = Value::String(function_name.0);
5477                let args0 = args.0[0].value.clone();
5478                let args1 = args.0[1].value.clone();
5479
5480                let value = Value::Record(vec![worker_name, function_name, args0, args1]);
5481
5482                Ok(Some(ValueAndType::new(value, analysed_type)))
5483            }
5484        }
5485
5486        struct ResourceFunctionsInvoke;
5487
5488        #[async_trait]
5489        impl RibComponentFunctionInvoke for ResourceFunctionsInvoke {
5490            async fn invoke(
5491                &self,
5492                _component_dependency_key: ComponentDependencyKey,
5493                _instruction_id: &InstructionId,
5494                worker_name: EvaluatedWorkerName,
5495                function_name: EvaluatedFqFn,
5496                args: EvaluatedFnArgs,
5497                _return_type: Option<AnalysedType>,
5498            ) -> RibFunctionInvokeResult {
5499                match function_name.0.as_str() {
5500                    "golem:it/api.{cart.new}" => {
5501                        let worker_name = worker_name.0;
5502
5503                        let uri = format!(
5504                            "urn:worker:99738bab-a3bf-4a12-8830-b6fd783d1ef2/{worker_name}"
5505                        );
5506                        Ok(ValueAndType::new(
5507                            Value::Handle {
5508                                uri,
5509                                resource_id: 0,
5510                            },
5511                            handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5512                        )
5513                        .into())
5514                    }
5515
5516                    "golem:it/api.{cart.checkout}" => {
5517                        let result_type = variant(vec![
5518                            case("error", str()),
5519                            case("success", record(vec![field("order-id", str())])),
5520                        ]);
5521
5522                        let result_value = get_value_and_type(
5523                            &result_type,
5524                            r#"
5525                            success({order-id: "foo"})
5526                            "#,
5527                        );
5528
5529                        Ok(Some(result_value))
5530                    }
5531
5532                    "golem:it/api.{cart.add-item}" => Ok(None),
5533
5534                    "golem:it/api.{cart.update-item-quantity}" => Ok(None),
5535
5536                    "golem:it/api.{cart.remove-item}" => Ok(None),
5537
5538                    "golem:it/api.{cart.drop}" => Ok(None),
5539
5540                    "golem:it/api.{cart.get-cart-contents}" => {
5541                        let typ = list(record(vec![
5542                            field("product-id", str()),
5543                            field("name", str()),
5544                            field("price", f32()),
5545                            field("quantity", u32()),
5546                        ]));
5547
5548                        let value = Value::Record(vec![
5549                            Value::String("foo".to_string()),
5550                            Value::String("bar".to_string()),
5551                            Value::F32(10.0),
5552                            Value::U32(2),
5553                        ]);
5554
5555                        Ok(Some(ValueAndType::new(Value::List(vec![value]), typ)))
5556                    }
5557
5558                    "golem:it/api.{[static]cart.create}" => {
5559                        let uri = format!(
5560                            "urn:worker:99738bab-a3bf-4a12-8830-b6fd783d1ef2/{}",
5561                            worker_name.0
5562                        );
5563
5564                        let value = Value::Handle {
5565                            uri,
5566                            resource_id: 0,
5567                        };
5568
5569                        Ok(Some(ValueAndType::new(
5570                            value,
5571                            handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5572                        )))
5573                    }
5574
5575                    "golem:it/api.{[static]cart.create-safe}" => {
5576                        let uri = format!(
5577                            "urn:worker:99738bab-a3bf-4a12-8830-b6fd783d1ef2/{}",
5578                            worker_name.0
5579                        );
5580
5581                        let resource = Value::Handle {
5582                            uri,
5583                            resource_id: 0,
5584                        };
5585
5586                        let value = Value::Result(Ok(Some(Box::new(resource))));
5587
5588                        Ok(Some(ValueAndType::new(
5589                            value,
5590                            result(
5591                                handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5592                                str(),
5593                            ),
5594                        )))
5595                    }
5596
5597                    "golem:it/api.{cart.pass-through}" => {
5598                        let worker_name = worker_name.0;
5599                        let function_args = args.0[1..].to_vec();
5600
5601                        let mut arg_types = vec![];
5602
5603                        for (index, value_and_type) in function_args.iter().enumerate() {
5604                            let name = format!("args{index}");
5605                            let value = value_and_type.typ.clone();
5606                            arg_types.push(field(name.as_str(), value));
5607                        }
5608
5609                        let function_name = function_name.0.into_value_and_type();
5610
5611                        let mut analysed_type_pairs = vec![];
5612                        analysed_type_pairs.push(field("worker-name", str()));
5613                        analysed_type_pairs.push(field("function-name", str()));
5614                        analysed_type_pairs.extend(arg_types);
5615
5616                        let mut values = vec![];
5617
5618                        values.push(Value::String(worker_name));
5619                        values.push(function_name.value);
5620
5621                        for arg_value in function_args {
5622                            values.push(arg_value.value);
5623                        }
5624
5625                        let value_and_type =
5626                            ValueAndType::new(Value::Record(values), record(analysed_type_pairs));
5627
5628                        Ok(Some(value_and_type))
5629                    }
5630
5631                    _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5632                }
5633            }
5634        }
5635
5636        struct SimpleVariantConflictInvoke;
5637
5638        #[async_trait]
5639        impl RibComponentFunctionInvoke for SimpleVariantConflictInvoke {
5640            async fn invoke(
5641                &self,
5642                _component_dependency_key: ComponentDependencyKey,
5643                _instruction_id: &InstructionId,
5644                _worker_name: EvaluatedWorkerName,
5645                function_name: EvaluatedFqFn,
5646                args: EvaluatedFnArgs,
5647                _return_type: Option<AnalysedType>,
5648            ) -> RibFunctionInvokeResult {
5649                let arg = args.0.first().unwrap();
5650
5651                match function_name.0.as_str() {
5652                    "func1" | "func2" => Ok(Some(arg.clone())),
5653                    _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5654                }
5655            }
5656        }
5657
5658        struct CustomInstanceFunctionInvoke;
5659        #[async_trait]
5660        impl RibComponentFunctionInvoke for CustomInstanceFunctionInvoke {
5661            async fn invoke(
5662                &self,
5663                _component_dependency_key: ComponentDependencyKey,
5664                _instruction_id: &InstructionId,
5665                worker_name: EvaluatedWorkerName,
5666                function_name: EvaluatedFqFn,
5667                args: EvaluatedFnArgs,
5668                _return_type: Option<AnalysedType>,
5669            ) -> RibFunctionInvokeResult {
5670                let mut arguments_concatenated = String::new();
5671
5672                for arg in args.0 {
5673                    let arg_str = print_value_and_type(&arg)?;
5674                    arguments_concatenated.push_str(arg_str.as_str());
5675                }
5676
5677                let result_value = ValueAndType::new(
5678                    Value::Record(vec![
5679                        Value::String(worker_name.0),
5680                        Value::String(function_name.0.clone()),
5681                        Value::String(arguments_concatenated),
5682                    ]),
5683                    record(vec![
5684                        field("worker-name", str()),
5685                        field("function-name", str()),
5686                        field("args", str()),
5687                    ]),
5688                );
5689
5690                match function_name.0.as_str() {
5691                    "my:agent/weather-agent.{get-weather}" => Ok(Some(result_value)),
5692
5693                    "my:agent/assistant-agent.{ask}" => Ok(Some(result_value)),
5694
5695                    _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5696                }
5697            }
5698        }
5699
5700        struct MultiplePackageFunctionInvoke;
5701
5702        #[async_trait]
5703        impl RibComponentFunctionInvoke for MultiplePackageFunctionInvoke {
5704            async fn invoke(
5705                &self,
5706                _component_dependency_key: ComponentDependencyKey,
5707                _instruction_id: &InstructionId,
5708                _worker_name: EvaluatedWorkerName,
5709                function_name: EvaluatedFqFn,
5710                _args: EvaluatedFnArgs,
5711                _return_type: Option<AnalysedType>,
5712            ) -> RibFunctionInvokeResult {
5713                match function_name.0.as_str() {
5714                    "amazon:shopping-cart/api1.{foo}" => {
5715                        let result_value =
5716                            ValueAndType::new(Value::String("foo".to_string()), str());
5717
5718                        Ok(Some(result_value))
5719                    }
5720
5721                    "amazon:shopping-cart/api1.{foo-number}" => {
5722                        let result_value = ValueAndType::new(Value::S32(1), s32());
5723
5724                        Ok(Some(result_value))
5725                    }
5726
5727                    "amazon:shopping-cart/api1.{bar}" => {
5728                        let result_value =
5729                            ValueAndType::new(Value::String("api1-bar".to_string()), str());
5730
5731                        Ok(Some(result_value))
5732                    }
5733
5734                    "amazon:shopping-cart/api1.{qux}" => {
5735                        let result_value =
5736                            ValueAndType::new(Value::String("qux".to_string()), str());
5737
5738                        Ok(Some(result_value))
5739                    }
5740
5741                    "amazon:shopping-cart/api2.{bar}" => {
5742                        let result_value =
5743                            ValueAndType::new(Value::String("api2-bar".to_string()), str());
5744
5745                        Ok(Some(result_value))
5746                    }
5747
5748                    "wasi:clocks/monotonic-clock.{baz}" => {
5749                        let result_value =
5750                            ValueAndType::new(Value::String("clock-baz".to_string()), str());
5751
5752                        Ok(Some(result_value))
5753                    }
5754
5755                    "wasi:clocks/monotonic-clock.{qux}" => {
5756                        let result_value =
5757                            ValueAndType::new(Value::String("clock-qux".to_string()), str());
5758
5759                        Ok(Some(result_value))
5760                    }
5761
5762                    _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5763                }
5764            }
5765        }
5766
5767        pub(crate) struct StaticWorkerNameGenerator;
5768
5769        impl GenerateWorkerName for StaticWorkerNameGenerator {
5770            fn generate_worker_name(&self) -> String {
5771                "test-worker".to_string()
5772            }
5773        }
5774
5775        pub(crate) struct RibTestDeps {
5776            pub(crate) component_dependencies: Vec<ComponentDependency>,
5777            pub(crate) interpreter: Interpreter,
5778        }
5779
5780        impl RibTestDeps {
5781            pub(crate) fn test_deps_with_global_functions() -> RibTestDeps {
5782                let component_dependencies = get_component_dependency_with_global_functions();
5783                let interpreter = interpreter_for_global_functions(None);
5784
5785                RibTestDeps {
5786                    component_dependencies,
5787                    interpreter,
5788                }
5789            }
5790
5791            pub(crate) fn test_deps_with_resource_functions(
5792                rib_input: Option<RibInput>,
5793            ) -> RibTestDeps {
5794                let component_dependencies = get_metadata_with_resource_without_params();
5795                let interpreter = interpreter_with_resource_function_invoke_impl(rib_input);
5796
5797                RibTestDeps {
5798                    component_dependencies,
5799                    interpreter,
5800                }
5801            }
5802
5803            pub(crate) fn test_deps_with_indexed_resource_functions(
5804                rib_input: Option<RibInput>,
5805            ) -> RibTestDeps {
5806                let component_dependencies = get_metadata_with_resource_with_params();
5807                let interpreter = interpreter_with_resource_function_invoke_impl(rib_input);
5808
5809                RibTestDeps {
5810                    component_dependencies,
5811                    interpreter,
5812                }
5813            }
5814
5815            // A pass through function simply pass through the information embedded in a function call
5816            // such as function name, the worker name and the arguments used to invoke the call
5817            // allowing us to cross verify if the invoke is correct
5818            pub(crate) fn test_deps_for_pass_through_function() -> RibTestDeps {
5819                let exports = vec![AnalysedExport::Function(AnalysedFunction {
5820                    name: "pass-through".to_string(),
5821                    parameters: vec![
5822                        AnalysedFunctionParameter {
5823                            name: "item".to_string(),
5824                            typ: u64(),
5825                        },
5826                        AnalysedFunctionParameter {
5827                            name: "item".to_string(),
5828                            typ: u32(),
5829                        },
5830                    ],
5831                    result: Some(AnalysedFunctionResult {
5832                        typ: record(vec![
5833                            field("worker-name", option(str())),
5834                            field("function-name", str()),
5835                            field("args0", u64()),
5836                            field("args1", u32()),
5837                        ]),
5838                    }),
5839                })];
5840
5841                let component_info = ComponentDependencyKey {
5842                    component_name: "foo".to_string(),
5843                    component_id: Uuid::new_v4(),
5844                    component_version: 0,
5845                    root_package_name: None,
5846                    root_package_version: None,
5847                };
5848
5849                let exports = vec![ComponentDependency::new(component_info, exports)];
5850
5851                let interpreter = Interpreter::new(
5852                    RibInput::default(),
5853                    Arc::new(PassThroughFunctionInvoke),
5854                    Arc::new(StaticWorkerNameGenerator),
5855                );
5856
5857                RibTestDeps {
5858                    component_dependencies: exports,
5859                    interpreter,
5860                }
5861            }
5862
5863            pub(crate) fn test_deps_with_multiple_interfaces_simple(
5864                rib_input: Option<RibInput>,
5865            ) -> RibTestDeps {
5866                let component_dependencies = get_metadata_with_multiple_interfaces_simple();
5867                let interpreter = Interpreter::new(
5868                    rib_input.unwrap_or_default(),
5869                    Arc::new(CustomInstanceFunctionInvoke),
5870                    Arc::new(StaticWorkerNameGenerator),
5871                );
5872
5873                RibTestDeps {
5874                    component_dependencies,
5875                    interpreter,
5876                }
5877            }
5878
5879            pub(crate) fn test_deps_with_variant_conflicts(
5880                rib_input: Option<RibInput>,
5881            ) -> RibTestDeps {
5882                let component_dependencies = get_metadata_simple_with_variant_conflicts();
5883                let interpreter = Interpreter::new(
5884                    rib_input.unwrap_or_default(),
5885                    Arc::new(SimpleVariantConflictInvoke),
5886                    Arc::new(StaticWorkerNameGenerator),
5887                );
5888
5889                RibTestDeps {
5890                    component_dependencies,
5891                    interpreter,
5892                }
5893            }
5894
5895            pub(crate) fn test_deps_with_multiple_interfaces(
5896                rib_input: Option<RibInput>,
5897            ) -> RibTestDeps {
5898                let component_dependencies = get_metadata_with_multiple_interfaces();
5899                let interpreter = Interpreter::new(
5900                    rib_input.unwrap_or_default(),
5901                    Arc::new(MultiplePackageFunctionInvoke),
5902                    Arc::new(StaticWorkerNameGenerator),
5903                );
5904
5905                RibTestDeps {
5906                    component_dependencies,
5907                    interpreter,
5908                }
5909            }
5910        }
5911
5912        fn get_component_dependency_with_global_functions() -> Vec<ComponentDependency> {
5913            let exports = vec![
5914                AnalysedExport::Function(AnalysedFunction {
5915                    name: "add-u32".to_string(),
5916                    parameters: vec![
5917                        AnalysedFunctionParameter {
5918                            name: "param1".to_string(),
5919                            typ: u32(),
5920                        },
5921                        AnalysedFunctionParameter {
5922                            name: "param2".to_string(),
5923                            typ: u32(),
5924                        },
5925                    ],
5926                    result: Some(AnalysedFunctionResult { typ: u32() }),
5927                }),
5928                AnalysedExport::Function(AnalysedFunction {
5929                    name: "add-u64".to_string(),
5930                    parameters: vec![
5931                        AnalysedFunctionParameter {
5932                            name: "param1".to_string(),
5933                            typ: u64(),
5934                        },
5935                        AnalysedFunctionParameter {
5936                            name: "param2".to_string(),
5937                            typ: u64(),
5938                        },
5939                    ],
5940                    result: Some(AnalysedFunctionResult { typ: u64() }),
5941                }),
5942                AnalysedExport::Function(AnalysedFunction {
5943                    name: "add-enum".to_string(),
5944                    parameters: vec![
5945                        AnalysedFunctionParameter {
5946                            name: "param1".to_string(),
5947                            typ: r#enum(&["x", "y", "z"]),
5948                        },
5949                        AnalysedFunctionParameter {
5950                            name: "param2".to_string(),
5951                            typ: r#enum(&["x", "y", "z"]),
5952                        },
5953                    ],
5954                    result: Some(AnalysedFunctionResult {
5955                        typ: r#enum(&["x", "y", "z"]),
5956                    }),
5957                }),
5958                AnalysedExport::Function(AnalysedFunction {
5959                    name: "add-variant".to_string(),
5960                    parameters: vec![
5961                        AnalysedFunctionParameter {
5962                            name: "param1".to_string(),
5963                            typ: get_analysed_type_variant(),
5964                        },
5965                        AnalysedFunctionParameter {
5966                            name: "param2".to_string(),
5967                            typ: get_analysed_type_variant(),
5968                        },
5969                    ],
5970                    result: Some(AnalysedFunctionResult {
5971                        typ: get_analysed_type_variant(),
5972                    }),
5973                }),
5974            ];
5975
5976            let component_info = ComponentDependencyKey {
5977                component_name: "foo".to_string(),
5978                component_id: Uuid::new_v4(),
5979                component_version: 0,
5980                root_package_name: None,
5981                root_package_version: None,
5982            };
5983
5984            vec![ComponentDependency::new(component_info, exports)]
5985        }
5986
5987        struct TestInvoke3;
5988
5989        #[async_trait]
5990        impl RibComponentFunctionInvoke for TestInvoke3 {
5991            async fn invoke(
5992                &self,
5993                _component_dependency: ComponentDependencyKey,
5994                _instruction_id: &InstructionId,
5995                _worker_name: EvaluatedWorkerName,
5996                function_name: EvaluatedFqFn,
5997                args: EvaluatedFnArgs,
5998                _return_type: Option<AnalysedType>,
5999            ) -> RibFunctionInvokeResult {
6000                match function_name.0.as_str() {
6001                    "add-u32" => {
6002                        let args = args.0;
6003                        let arg1 = args[0].get_literal().and_then(|x| x.get_number()).unwrap();
6004                        let arg2 = args[1].get_literal().and_then(|x| x.get_number()).unwrap();
6005                        let result = (arg1 + arg2).unwrap();
6006                        let u32 = result.cast_to(&u32()).unwrap();
6007
6008                        Ok(Some(u32))
6009                    }
6010                    "add-u64" => {
6011                        let args = args.0;
6012                        let arg1 = args[0].get_literal().and_then(|x| x.get_number()).unwrap();
6013                        let arg2 = args[1].get_literal().and_then(|x| x.get_number()).unwrap();
6014                        let result = (arg1 + arg2).unwrap();
6015                        let u64 = result.cast_to(&u64()).unwrap();
6016                        Ok(Some(u64))
6017                    }
6018                    "add-enum" => {
6019                        let args = args.0;
6020                        let arg1 = args[0].clone().value;
6021                        let arg2 = args[1].clone().value;
6022                        match (arg1, arg2) {
6023                            (Value::Enum(x), Value::Enum(y)) => {
6024                                if x == y {
6025                                    let result =
6026                                        ValueAndType::new(Value::Enum(x), r#enum(&["x", "y", "z"]));
6027                                    Ok(Some(result))
6028                                } else {
6029                                    Err(format!("Enums are not equal: {x} and {y}").into())
6030                                }
6031                            }
6032                            (v1, v2) => {
6033                                Err(format!("Invalid arguments for add-enum: {v1:?} and {v2:?}")
6034                                    .into())
6035                            }
6036                        }
6037                    }
6038                    "add-variant" => {
6039                        let args = args.0;
6040                        let arg1 = args[0].clone().value;
6041                        let arg2 = args[1].clone().value;
6042                        match (arg1, arg2) {
6043                            (
6044                                Value::Variant {
6045                                    case_idx: case_idx1,
6046                                    case_value,
6047                                },
6048                                Value::Variant {
6049                                    case_idx: case_idx2,
6050                                    ..
6051                                },
6052                            ) => {
6053                                if case_idx1 == case_idx2 {
6054                                    let result = ValueAndType::new(
6055                                        Value::Variant {
6056                                            case_idx: case_idx1,
6057                                            case_value,
6058                                        },
6059                                        get_analysed_type_variant(),
6060                                    );
6061                                    Ok(Some(result))
6062                                } else {
6063                                    Err(format!(
6064                                        "Variants are not equal: {case_idx1} and {case_idx2}"
6065                                    )
6066                                    .into())
6067                                }
6068                            }
6069                            (v1, v2) => Err(format!(
6070                                "Invalid arguments for add-variant: {v1:?} and {v2:?}"
6071                            )
6072                            .into()),
6073                        }
6074                    }
6075                    fun => Err(format!("unknown function {fun}").into()),
6076                }
6077            }
6078        }
6079    }
6080}