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