Skip to main content

rib/interpreter/
rib_interpreter.rs

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