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: 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 }
1185
1186 Ok(())
1187 }
1188
1189 pub(crate) async fn run_invoke_function_instruction(
1190 component_info: ComponentDependencyKey,
1191 instruction_id: &InstructionId,
1192 arg_size: usize,
1193 instance_variable_type: InstanceVariable,
1194 interpreter_stack: &mut InterpreterStack,
1195 interpreter_env: &mut InterpreterEnv,
1196 expected_result_type: AnalysedTypeWithUnit,
1197 ) -> RibInterpreterResult<()> {
1198 let function_name = interpreter_stack
1199 .pop_str()
1200 .ok_or_else(|| internal_corrupted_state!("failed to get a function name"))?;
1201
1202 let function_name_cloned = function_name.clone();
1203
1204 let last_n_elements = interpreter_stack
1205 .pop_n(arg_size)
1206 .ok_or_else(|| insufficient_stack_items(arg_size))?;
1207
1208 let expected_result_type = match expected_result_type {
1209 AnalysedTypeWithUnit::Type(analysed_type) => Some(analysed_type),
1210 AnalysedTypeWithUnit::Unit => None,
1211 };
1212
1213 let parameter_values = last_n_elements
1214 .iter()
1215 .map(|interpreter_result| {
1216 interpreter_result.get_val().ok_or_else(|| {
1217 internal_corrupted_state!("failed to call function {}", function_name)
1218 })
1219 })
1220 .collect::<RibInterpreterResult<Vec<ValueAndType>>>()?;
1221
1222 match instance_variable_type {
1223 InstanceVariable::WitWorker(variable_id) => {
1224 let worker_id = interpreter_env
1225 .lookup(&EnvironmentKey::from(variable_id.clone()))
1226 .map(|x| {
1227 x.get_val().ok_or_else(|| {
1228 internal_corrupted_state!(
1229 "failed to get a worker variable id for function {}",
1230 function_name
1231 )
1232 })
1233 })
1234 .transpose()?
1235 .ok_or_else(|| {
1236 internal_corrupted_state!(
1237 "failed to find a worker with id {}",
1238 variable_id.name()
1239 )
1240 })?;
1241
1242 let worker_id_string =
1243 worker_id
1244 .get_literal()
1245 .map(|v| v.as_string())
1246 .ok_or_else(|| {
1247 internal_corrupted_state!("failed to get a worker name for variable")
1248 })?;
1249
1250 let result = interpreter_env
1251 .invoke_worker_function_async(
1252 component_info,
1253 instruction_id,
1254 worker_id_string,
1255 function_name_cloned,
1256 parameter_values,
1257 expected_result_type.clone(),
1258 )
1259 .await
1260 .map_err(|err| function_invoke_fail(function_name.as_str(), err))?;
1261
1262 match result {
1263 None => {
1264 interpreter_stack.push(RibInterpreterStackValue::Unit);
1265 }
1266 Some(result) => {
1267 interpreter_stack.push(RibInterpreterStackValue::Val(result));
1268 }
1269 }
1270 }
1271
1272 InstanceVariable::WitResource(variable_id)
1273 if variable_id == VariableId::global("___STATIC_WIT_RESOURCE".to_string()) =>
1274 {
1275 let result = interpreter_env
1276 .invoke_worker_function_async(
1277 component_info,
1278 instruction_id,
1279 "___STATIC_WIT_RESOURCE".to_string(),
1280 function_name_cloned,
1281 parameter_values,
1282 expected_result_type.clone(),
1283 )
1284 .await
1285 .map_err(|err| function_invoke_fail(function_name.as_str(), err))?;
1286
1287 match result {
1288 None => {
1289 interpreter_stack.push(RibInterpreterStackValue::Unit);
1290 }
1291 Some(result) => {
1292 interpreter_stack.push(RibInterpreterStackValue::Val(result));
1293 }
1294 }
1295 }
1296
1297 InstanceVariable::WitResource(variable_id) => {
1298 let mut final_args = vec![];
1299
1300 let handle = interpreter_env
1301 .lookup(&EnvironmentKey::from(variable_id.clone()))
1302 .map(|x| {
1303 x.get_val().ok_or_else(|| {
1304 internal_corrupted_state!(
1305 "failed to get a resource with id {}",
1306 variable_id.name()
1307 )
1308 })
1309 })
1310 .transpose()?
1311 .ok_or_else(|| {
1312 internal_corrupted_state!(
1313 "failed to find a resource with id {}",
1314 variable_id.name()
1315 )
1316 })?;
1317
1318 match &handle.value {
1319 Value::Handle { uri, .. } => {
1320 let worker_name = uri.rsplit_once('/').map(|(_, last)| last).unwrap_or(uri);
1321
1322 final_args.push(handle.clone());
1323 final_args.extend(parameter_values);
1324
1325 let result = interpreter_env
1326 .invoke_worker_function_async(
1327 component_info,
1328 instruction_id,
1329 worker_name.to_string(),
1330 function_name_cloned.clone(),
1331 final_args,
1332 expected_result_type.clone(),
1333 )
1334 .await
1335 .map_err(|err| function_invoke_fail(function_name.as_str(), err))?;
1336
1337 match result {
1338 None => {
1339 interpreter_stack.push(RibInterpreterStackValue::Unit);
1340 }
1341 Some(result) => {
1342 interpreter_stack.push(RibInterpreterStackValue::Val(result));
1343 }
1344 }
1345 }
1346
1347 _ => {
1348 return Err(function_invoke_fail(
1349 function_name.as_str(),
1350 "expected the result of a resource construction to be of type `handle`"
1351 .into(),
1352 ))
1353 }
1354 };
1355 }
1356 };
1357
1358 Ok(())
1359 }
1360
1361 pub(crate) fn run_deconstruct_instruction(
1362 interpreter_stack: &mut InterpreterStack,
1363 ) -> RibInterpreterResult<()> {
1364 let value = interpreter_stack
1365 .pop()
1366 .ok_or_else(|| internal_corrupted_state!("no value to unwrap"))?;
1367
1368 let unwrapped_value = value
1369 .unwrap()
1370 .ok_or_else(|| internal_corrupted_state!("failed to unwrap the value {}", value))?;
1371
1372 interpreter_stack.push_val(unwrapped_value);
1373 Ok(())
1374 }
1375
1376 pub(crate) fn run_get_tag_instruction(
1377 interpreter_stack: &mut InterpreterStack,
1378 ) -> RibInterpreterResult<()> {
1379 let value = interpreter_stack
1380 .pop_val()
1381 .ok_or_else(|| internal_corrupted_state!("failed to get a tag value"))?;
1382
1383 let tag = match value {
1384 ValueAndType {
1385 value: Value::Variant { case_idx, .. },
1386 typ: AnalysedType::Variant(typ),
1387 } => typ.cases[case_idx as usize].name.clone(),
1388 ValueAndType {
1389 value: Value::Option(option),
1390 ..
1391 } => match option {
1392 Some(_) => "some".to_string(),
1393 None => "none".to_string(),
1394 },
1395 ValueAndType {
1396 value: Value::Result(result_value),
1397 ..
1398 } => match result_value {
1399 Ok(_) => "ok".to_string(),
1400 Err(_) => "err".to_string(),
1401 },
1402 ValueAndType {
1403 value: Value::Enum(idx),
1404 typ: AnalysedType::Enum(typ),
1405 } => typ.cases[idx as usize].clone(),
1406 _ => "untagged".to_string(),
1407 };
1408
1409 interpreter_stack.push_val(tag.into_value_and_type());
1410 Ok(())
1411 }
1412
1413 pub(crate) fn run_create_some_instruction(
1414 interpreter_stack: &mut InterpreterStack,
1415 analysed_type: AnalysedType,
1416 ) -> RibInterpreterResult<()> {
1417 let value = interpreter_stack.try_pop_val()?;
1418
1419 match analysed_type {
1420 AnalysedType::Option(analysed_type) => {
1421 interpreter_stack.push_some(value.value, analysed_type.inner.deref());
1422 Ok(())
1423 }
1424 _ => Err(type_mismatch_with_type_hint(
1425 vec![TypeHint::Option(None)],
1426 analysed_type.get_type_hint(),
1427 )),
1428 }
1429 }
1430
1431 pub(crate) fn run_create_none_instruction(
1432 interpreter_stack: &mut InterpreterStack,
1433 analysed_type: Option<AnalysedType>,
1434 ) -> RibInterpreterResult<()> {
1435 match analysed_type {
1436 Some(AnalysedType::Option(_)) | None => {
1437 interpreter_stack.push_none(analysed_type);
1438 Ok(())
1439 }
1440 _ => Err(type_mismatch_with_type_hint(
1441 vec![TypeHint::Option(None)],
1442 analysed_type
1443 .as_ref()
1444 .map(|t| t.get_type_hint())
1445 .unwrap_or_else(|| TypeHint::Unknown),
1446 )),
1447 }
1448 }
1449
1450 pub(crate) fn run_create_ok_instruction(
1451 interpreter_stack: &mut InterpreterStack,
1452 analysed_type: AnalysedType,
1453 ) -> RibInterpreterResult<()> {
1454 let value = interpreter_stack.try_pop_val()?;
1455
1456 match analysed_type {
1457 AnalysedType::Result(TypeResult { ok, err, .. }) => {
1458 interpreter_stack.push_ok(value.value, ok.as_deref(), err.as_deref());
1459 Ok(())
1460 }
1461 _ => Err(type_mismatch_with_type_hint(
1462 vec![TypeHint::Result {
1463 ok: None,
1464 err: None,
1465 }],
1466 analysed_type.get_type_hint(),
1467 )),
1468 }
1469 }
1470
1471 pub(crate) fn run_create_err_instruction(
1472 interpreter_stack: &mut InterpreterStack,
1473 analysed_type: AnalysedType,
1474 ) -> RibInterpreterResult<()> {
1475 let value = interpreter_stack.try_pop_val()?;
1476
1477 match analysed_type {
1478 AnalysedType::Result(TypeResult { ok, err, .. }) => {
1479 interpreter_stack.push_err(value.value, ok.as_deref(), err.as_deref());
1480 Ok(())
1481 }
1482 _ => Err(type_mismatch_with_type_hint(
1483 vec![TypeHint::Result {
1484 ok: None,
1485 err: None,
1486 }],
1487 analysed_type.get_type_hint(),
1488 )),
1489 }
1490 }
1491
1492 pub(crate) fn run_concat_instruction(
1493 interpreter_stack: &mut InterpreterStack,
1494 arg_size: usize,
1495 ) -> RibInterpreterResult<()> {
1496 let value_and_types = interpreter_stack.try_pop_n_val(arg_size)?;
1497
1498 let mut result = String::new();
1499
1500 for val in value_and_types {
1501 match &val.value {
1502 Value::String(s) => {
1503 result.push_str(s);
1505 }
1506 Value::Char(char) => {
1507 result.push(*char);
1509 }
1510 _ => {
1511 result.push_str(&val.to_string());
1512 }
1513 }
1514 }
1515
1516 interpreter_stack.push_val(result.into_value_and_type());
1517
1518 Ok(())
1519 }
1520}
1521
1522#[cfg(test)]
1523mod tests {
1524 use std::collections::HashMap;
1525 use test_r::test;
1526
1527 use super::*;
1528 use crate::interpreter::rib_interpreter::tests::test_utils::{
1529 get_analysed_type_variant, get_value_and_type, strip_spaces, RibTestDeps,
1530 };
1531 use crate::{
1532 CustomInstanceSpec, Expr, GlobalVariableTypeSpec, InferredType, InstructionId,
1533 InterfaceName, Path, RibCompiler, RibCompilerConfig, VariableId,
1534 };
1535 use golem_wasm_ast::analysis::analysed_type::{
1536 bool, case, f32, field, list, option, r#enum, record, result, result_err, result_ok, s32,
1537 str, tuple, u32, u64, u8, unit_case, variant,
1538 };
1539 use golem_wasm_ast::analysis::AnalysedType;
1540 use golem_wasm_rpc::{IntoValue, IntoValueAndType, Value, ValueAndType};
1541
1542 #[test]
1543 async fn test_interpreter_for_literal() {
1544 let mut interpreter = Interpreter::default();
1545
1546 let instructions = RibByteCode {
1547 instructions: vec![RibIR::PushLit(1i32.into_value_and_type())],
1548 };
1549
1550 let result = interpreter.run(instructions).await.unwrap();
1551 assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1552 }
1553
1554 #[test]
1555 async fn test_interpreter_for_equal_to() {
1556 let mut interpreter = Interpreter::default();
1557
1558 let instructions = RibByteCode {
1559 instructions: vec![
1560 RibIR::PushLit(1i32.into_value_and_type()),
1561 RibIR::PushLit(1u32.into_value_and_type()),
1562 RibIR::EqualTo,
1563 ],
1564 };
1565
1566 let result = interpreter.run(instructions).await.unwrap();
1567 assert!(result.get_bool().unwrap());
1568 }
1569
1570 #[test]
1571 async fn test_interpreter_for_greater_than() {
1572 let mut interpreter = Interpreter::default();
1573
1574 let instructions = RibByteCode {
1575 instructions: vec![
1576 RibIR::PushLit(1i32.into_value_and_type()),
1577 RibIR::PushLit(2u32.into_value_and_type()),
1578 RibIR::GreaterThan,
1579 ],
1580 };
1581
1582 let result = interpreter.run(instructions).await.unwrap();
1583 assert!(result.get_bool().unwrap());
1584 }
1585
1586 #[test]
1587 async fn test_interpreter_for_less_than() {
1588 let mut interpreter = Interpreter::default();
1589
1590 let instructions = RibByteCode {
1591 instructions: vec![
1592 RibIR::PushLit(2i32.into_value_and_type()),
1593 RibIR::PushLit(1u32.into_value_and_type()),
1594 RibIR::LessThan,
1595 ],
1596 };
1597
1598 let result = interpreter.run(instructions).await.unwrap();
1599 assert!(result.get_bool().unwrap());
1600 }
1601
1602 #[test]
1603 async fn test_interpreter_for_greater_than_or_equal_to() {
1604 let mut interpreter = Interpreter::default();
1605
1606 let instructions = RibByteCode {
1607 instructions: vec![
1608 RibIR::PushLit(2i32.into_value_and_type()),
1609 RibIR::PushLit(3u32.into_value_and_type()),
1610 RibIR::GreaterThanOrEqualTo,
1611 ],
1612 };
1613
1614 let result = interpreter.run(instructions).await.unwrap();
1615 assert!(result.get_bool().unwrap());
1616 }
1617
1618 #[test]
1619 async fn test_interpreter_for_less_than_or_equal_to() {
1620 let mut interpreter = Interpreter::default();
1621
1622 let instructions = RibByteCode {
1623 instructions: vec![
1624 RibIR::PushLit(2i32.into_value_and_type()), RibIR::PushLit(1i32.into_value_and_type()), RibIR::LessThanOrEqualTo,
1627 ],
1628 };
1629
1630 let result = interpreter.run(instructions).await.unwrap();
1631 assert!(result.get_bool().unwrap());
1632 }
1633
1634 #[test]
1635 async fn test_interpreter_for_assign_and_load_var() {
1636 let mut interpreter = Interpreter::default();
1637
1638 let instructions = RibByteCode {
1639 instructions: vec![
1640 RibIR::PushLit(1i32.into_value_and_type()),
1641 RibIR::AssignVar(VariableId::local_with_no_id("x")),
1642 RibIR::LoadVar(VariableId::local_with_no_id("x")),
1643 ],
1644 };
1645
1646 let result = interpreter.run(instructions).await.unwrap();
1647 assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1648 }
1649
1650 #[test]
1651 async fn test_interpreter_for_jump() {
1652 let mut interpreter = Interpreter::default();
1653
1654 let instructions = RibByteCode {
1655 instructions: vec![
1656 RibIR::Jump(InstructionId::init()),
1657 RibIR::PushLit(1i32.into_value_and_type()),
1658 RibIR::Label(InstructionId::init()),
1659 ],
1660 };
1661
1662 let result = interpreter.run(instructions).await;
1663 assert!(result.is_ok());
1664 }
1665
1666 #[test]
1667 async fn test_interpreter_for_jump_if_false() {
1668 let mut interpreter = Interpreter::default();
1669
1670 let id = InstructionId::init().increment_mut();
1671
1672 let instructions = RibByteCode {
1673 instructions: vec![
1674 RibIR::PushLit(false.into_value_and_type()),
1675 RibIR::JumpIfFalse(id.clone()),
1676 RibIR::PushLit(1i32.into_value_and_type()),
1677 RibIR::Label(id),
1678 ],
1679 };
1680
1681 let result = interpreter.run(instructions).await;
1682 assert!(result.is_ok());
1683 }
1684
1685 #[test]
1686 async fn test_interpreter_for_record() {
1687 let mut interpreter = Interpreter::default();
1688
1689 let instructions = RibByteCode {
1690 instructions: vec![
1691 RibIR::PushLit(2i32.into_value_and_type()),
1692 RibIR::PushLit(1i32.into_value_and_type()),
1693 RibIR::CreateAndPushRecord(record(vec![field("x", s32()), field("y", s32())])),
1694 RibIR::UpdateRecord("x".to_string()),
1695 RibIR::UpdateRecord("y".to_string()),
1696 ],
1697 };
1698
1699 let result = interpreter.run(instructions).await.unwrap();
1700 let expected = ValueAndType::new(
1701 Value::Record(vec![1i32.into_value(), 2i32.into_value()]),
1702 record(vec![field("x", s32()), field("y", s32())]),
1703 );
1704
1705 assert_eq!(result.get_val().unwrap(), expected);
1706 }
1707
1708 #[test]
1709 async fn test_interpreter_for_sequence() {
1710 let mut interpreter = Interpreter::default();
1711
1712 let instructions = RibByteCode {
1713 instructions: vec![
1714 RibIR::PushLit(2i32.into_value_and_type()),
1715 RibIR::PushLit(1i32.into_value_and_type()),
1716 RibIR::PushList(list(s32()), 2),
1717 ],
1718 };
1719
1720 let result = interpreter.run(instructions).await.unwrap();
1721 let expected = ValueAndType::new(
1722 Value::List(vec![1i32.into_value(), 2i32.into_value()]),
1723 list(s32()),
1724 );
1725 assert_eq!(result.get_val().unwrap(), expected);
1726 }
1727
1728 #[test]
1729 async fn test_interpreter_for_select_field() {
1730 let mut interpreter = Interpreter::default();
1731
1732 let instructions = RibByteCode {
1733 instructions: vec![
1734 RibIR::PushLit(1i32.into_value_and_type()),
1735 RibIR::PushLit(2i32.into_value_and_type()),
1736 RibIR::CreateAndPushRecord(record(vec![field("x", s32())])),
1737 RibIR::UpdateRecord("x".to_string()),
1738 RibIR::SelectField("x".to_string()),
1739 ],
1740 };
1741
1742 let result = interpreter.run(instructions).await.unwrap();
1743 assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1744 }
1745
1746 #[test]
1747 async fn test_interpreter_for_select_index() {
1748 let mut interpreter = Interpreter::default();
1749
1750 let instructions = RibByteCode {
1751 instructions: vec![
1752 RibIR::PushLit(1i32.into_value_and_type()),
1753 RibIR::PushLit(2i32.into_value_and_type()),
1754 RibIR::PushList(list(s32()), 2),
1755 RibIR::SelectIndex(0),
1756 ],
1757 };
1758
1759 let result = interpreter.run(instructions).await.unwrap();
1760 assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1761 }
1762
1763 #[test]
1764 async fn test_interpreter_variable_scope_0() {
1765 let rib_expr = r#"
1766 let x = 1;
1767 let y = x + 2;
1768 y
1769 "#;
1770
1771 let expr = Expr::from_text(rib_expr).unwrap();
1772
1773 let mut interpreter = Interpreter::default();
1774
1775 let compiler = RibCompiler::default();
1776
1777 let compiled = compiler.compile(expr).unwrap();
1778
1779 let result = interpreter.run(compiled.byte_code).await.unwrap();
1780
1781 assert_eq!(result.get_val().unwrap(), 3i32.into_value_and_type());
1782 }
1783
1784 #[test]
1785 async fn test_interpreter_variable_scope_1() {
1786 let rib_expr = r#"
1787 let x = 1;
1788 let z = {foo : x};
1789 let x = x + 2u64;
1790 { bar: x, baz: z }
1791 "#;
1792
1793 let expr = Expr::from_text(rib_expr).unwrap();
1794
1795 let mut interpreter = Interpreter::default();
1796
1797 let compiler = RibCompiler::default();
1798 let compiled = compiler.compile(expr).unwrap();
1799
1800 let result = interpreter.run(compiled.byte_code).await.unwrap();
1801
1802 let analysed_type = record(vec![
1803 field("bar", u64()),
1804 field("baz", record(vec![field("foo", u64())])),
1805 ]);
1806
1807 let expected = get_value_and_type(&analysed_type, r#"{ bar: 3, baz: { foo: 1 } }"#);
1808
1809 assert_eq!(result.get_val().unwrap(), expected);
1810 }
1811
1812 #[test]
1813 async fn test_interpreter_variable_scope_2() {
1814 let rib_expr = r#"
1815 let x = 1;
1816 let x = x;
1817
1818 let result1 = match some(x + 1) {
1819 some(x) => x,
1820 none => x
1821 };
1822
1823 let z: option<u64> = none;
1824
1825 let result2 = match z {
1826 some(x) => x,
1827 none => x
1828 };
1829
1830 { result1: result1, result2: result2 }
1831 "#;
1832
1833 let expr = Expr::from_text(rib_expr).unwrap();
1834
1835 let mut interpreter = Interpreter::default();
1836
1837 let compiler = RibCompiler::default();
1838
1839 let compiled = compiler.compile(expr).unwrap();
1840
1841 let result = interpreter.run(compiled.byte_code).await.unwrap();
1842
1843 let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1844
1845 let expected = get_value_and_type(&analysed_type, r#"{ result1: 2, result2: 1 }"#);
1846
1847 assert_eq!(result.get_val().unwrap(), expected);
1848 }
1849
1850 #[test]
1851 async fn test_interpreter_variable_scope_3() {
1852 let rib_expr = r#"
1853 let x = 1;
1854 let x = x;
1855
1856 let result1 = match some(x + 1) {
1857 some(x) => match some(x + 1) {
1858 some(x) => x,
1859 none => x
1860 },
1861 none => x
1862 };
1863
1864 let z: option<u64> = none;
1865
1866 let result2 = match z {
1867 some(x) => x,
1868 none => match some(x + 1) {
1869 some(x) => x,
1870 none => x
1871 }
1872 };
1873
1874 { result1: result1, result2: result2 }
1875 "#;
1876
1877 let expr = Expr::from_text(rib_expr).unwrap();
1878
1879 let mut interpreter = Interpreter::default();
1880
1881 let compiler = RibCompiler::default();
1882
1883 let compiled = compiler.compile(expr).unwrap();
1884
1885 let result = interpreter.run(compiled.byte_code).await.unwrap();
1886
1887 let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1888
1889 let expected = get_value_and_type(&analysed_type, r#"{ result1: 3, result2: 2 }"#);
1890
1891 assert_eq!(result.get_val().unwrap(), expected);
1892 }
1893
1894 #[test]
1895 async fn test_interpreter_global_variable_with_type_spec() {
1896 let rib_expr = r#"
1899 let res1 = request.path.user-id;
1900 let res2 = request.headers.name;
1901 let res3 = request.headers.age;
1902 "${res1}-${res2}-${res3}"
1903 "#;
1904
1905 let type_spec = vec![
1906 GlobalVariableTypeSpec::new(
1907 "request",
1908 Path::from_elems(vec!["path"]),
1909 InferredType::string(),
1910 ),
1911 GlobalVariableTypeSpec::new(
1912 "request",
1913 Path::from_elems(vec!["headers"]),
1914 InferredType::string(),
1915 ),
1916 ];
1917
1918 let mut rib_input = HashMap::new();
1919
1920 let analysed_type_of_input = &record(vec![
1923 field("path", record(vec![field("user-id", str())])),
1924 field(
1925 "headers",
1926 record(vec![field("name", str()), field("age", str())]),
1927 ),
1928 ]);
1929
1930 let value_and_type = get_value_and_type(
1931 analysed_type_of_input,
1932 r#"{path : { user-id: "1" }, headers: { name: "foo", age: "20" }}"#,
1933 );
1934
1935 rib_input.insert("request".to_string(), value_and_type);
1936
1937 let mut interpreter =
1938 test_utils::interpreter_with_noop_function_invoke(Some(RibInput::new(rib_input)));
1939
1940 let expr = Expr::from_text(rib_expr).unwrap();
1941
1942 let compiler = RibCompiler::new(RibCompilerConfig::new(vec![], type_spec, vec![]));
1943 let compiled = compiler.compile(expr).unwrap();
1944
1945 let result = interpreter
1946 .run(compiled.byte_code)
1947 .await
1948 .unwrap()
1949 .get_val()
1950 .unwrap()
1951 .value;
1952
1953 assert_eq!(result, Value::String("1-foo-20".to_string()))
1954 }
1955
1956 #[test]
1957 async fn test_interpreter_global_variable_override_type_spec() {
1958 let rib_expr = r#"
1959 let res1: u32 = request.path.user-id;
1960 let res2 = request.headers.name;
1961 let res3: u32 = request.headers.age;
1962 let res4 = res1 + res3;
1963 "${res4}-${res2}"
1964 "#;
1965
1966 let type_spec = vec![
1970 GlobalVariableTypeSpec::new(
1971 "request",
1972 Path::from_elems(vec!["path"]),
1973 InferredType::string(),
1974 ),
1975 GlobalVariableTypeSpec::new(
1976 "request",
1977 Path::from_elems(vec!["headers"]),
1978 InferredType::string(),
1979 ),
1980 ];
1981
1982 let mut rib_input = HashMap::new();
1983
1984 let analysed_type_of_input = &record(vec![
1987 field("path", record(vec![field("user-id", u32())])),
1988 field(
1989 "headers",
1990 record(vec![field("name", str()), field("age", u32())]),
1991 ),
1992 ]);
1993
1994 let value_and_type = get_value_and_type(
1995 analysed_type_of_input,
1996 r#"{path : { user-id: 1 }, headers: { name: "foo", age: 20 }}"#,
1997 );
1998
1999 rib_input.insert("request".to_string(), value_and_type);
2000
2001 let mut interpreter =
2002 test_utils::interpreter_with_noop_function_invoke(Some(RibInput::new(rib_input)));
2003
2004 let expr = Expr::from_text(rib_expr).unwrap();
2005
2006 let compiler = RibCompiler::new(RibCompilerConfig::new(vec![], type_spec, vec![]));
2007
2008 let compiled = compiler.compile(expr).unwrap();
2009
2010 let result = interpreter
2011 .run(compiled.byte_code)
2012 .await
2013 .unwrap()
2014 .get_val()
2015 .unwrap()
2016 .value;
2017
2018 assert_eq!(result, Value::String("21-foo".to_string()))
2019 }
2020
2021 #[test]
2022 async fn test_interpreter_concatenation() {
2023 let mut interpreter = Interpreter::default();
2024
2025 let rib_expr = r#"
2026 let x = "foo";
2027 let y = "bar";
2028 let z = {foo: "baz"};
2029 let n: u32 = 42;
2030 let result = "${x}-${y}-${z}-${n}";
2031 result
2032 "#;
2033
2034 let expr = Expr::from_text(rib_expr).unwrap();
2035
2036 let compiler = RibCompiler::default();
2037
2038 let compiled = compiler.compile(expr).unwrap();
2039
2040 let result = interpreter.run(compiled.byte_code).await.unwrap();
2041
2042 assert_eq!(
2043 result.get_val().unwrap().value,
2044 Value::String("foo-bar-{foo: \"baz\"}-42".to_string())
2045 );
2046 }
2047
2048 #[test]
2049 async fn test_interpreter_with_variant_and_enum() {
2050 let test_deps = RibTestDeps::test_deps_with_global_functions();
2051
2052 let compiler = RibCompiler::new(RibCompilerConfig::new(
2053 test_deps.component_dependencies.clone(),
2054 vec![],
2055 vec![],
2056 ));
2057
2058 let mut interpreter = test_deps.interpreter;
2059
2060 let expr = r#"
2064 let x = x;
2065 let y = x;
2066 let a = instance();
2067 let result1 = a.add-enum(x, y);
2068 let validate = validate;
2069 let validate2 = validate;
2070 let result2 = a.add-variant(validate, validate2);
2071 {res1: result1, res2: result2}
2072 "#;
2073
2074 let expr = Expr::from_text(expr).unwrap();
2075
2076 let compiled = compiler.compile(expr);
2077
2078 let result = interpreter.run(compiled.unwrap().byte_code).await.unwrap();
2079 let expected_enum_type = r#enum(&["x", "y", "z"]);
2080 let expected_variant_type = get_analysed_type_variant();
2081
2082 let expected_record_type = record(vec![
2083 field("res1", expected_enum_type),
2084 field("res2", expected_variant_type),
2085 ]);
2086
2087 let expected_record_value = Value::Record(vec![
2088 Value::Enum(0),
2089 Value::Variant {
2090 case_idx: 2,
2091 case_value: None,
2092 },
2093 ]);
2094
2095 assert_eq!(
2096 result,
2097 RibResult::Val(ValueAndType::new(
2098 expected_record_value,
2099 expected_record_type
2100 ))
2101 );
2102 }
2103
2104 #[test]
2105 async fn test_interpreter_with_conflicting_variable_names() {
2106 let test_deps = RibTestDeps::test_deps_with_global_functions();
2107
2108 let compiler = RibCompiler::new(RibCompilerConfig::new(
2109 test_deps.component_dependencies.clone(),
2110 vec![],
2111 vec![],
2112 ));
2113
2114 let mut interpreter = test_deps.interpreter;
2115
2116 let expr = r#"
2121 let x = 1;
2122 let y = 2;
2123 let a = instance();
2124 let result1 = a.add-u32(x, y);
2125 let process-user = 3;
2126 let validate = 4;
2127 let result2 = a.add-u64(process-user, validate);
2128 {res1: result1, res2: result2}
2129 "#;
2130
2131 let expr = Expr::from_text(expr).unwrap();
2132
2133 let compiled = compiler.compile(expr).unwrap();
2134 let result = interpreter.run(compiled.byte_code).await.unwrap();
2135 let expected_value = Value::Record(vec![3u32.into_value(), 7u64.into_value()]);
2136
2137 let expected_type = record(vec![field("res1", u32()), field("res2", u64())]);
2138 assert_eq!(
2139 result,
2140 RibResult::Val(ValueAndType::new(expected_value, expected_type))
2141 );
2142 }
2143
2144 #[test]
2145 async fn test_interpreter_list_reduce() {
2146 let mut interpreter = Interpreter::default();
2147
2148 let rib_expr = r#"
2149 let x: list<u8> = [1, 2];
2150
2151 reduce z, a in x from 0u8 {
2152 yield z + a;
2153 }
2154
2155 "#;
2156
2157 let expr = Expr::from_text(rib_expr).unwrap();
2158 let compiler = RibCompiler::default();
2159 let compiled = compiler.compile(expr).unwrap();
2160 let result = interpreter
2161 .run(compiled.byte_code)
2162 .await
2163 .unwrap()
2164 .get_val()
2165 .unwrap();
2166
2167 assert_eq!(result, 3u8.into_value_and_type());
2168 }
2169
2170 #[test]
2171 async fn test_interpreter_list_reduce_from_record() {
2172 let mut interpreter = Interpreter::default();
2173
2174 let rib_expr = r#"
2175 let x = [{name: "foo", age: 1u64}, {name: "bar", age: 2u64}];
2176
2177 let names = for i in x {
2178 yield i.name;
2179 };
2180
2181 reduce z, a in names from "" {
2182 let result = if z == "" then a else "${z}, ${a}";
2183
2184 yield result;
2185 }
2186
2187 "#;
2188
2189 let expr = Expr::from_text(rib_expr).unwrap();
2190
2191 let compiler = RibCompiler::default();
2192 let compiled = compiler.compile(expr).unwrap();
2193
2194 let result = interpreter
2195 .run(compiled.byte_code)
2196 .await
2197 .unwrap()
2198 .get_val()
2199 .unwrap();
2200
2201 assert_eq!(result, "foo, bar".into_value_and_type());
2202 }
2203
2204 #[test]
2205 async fn test_interpreter_list_reduce_text() {
2206 let mut interpreter = Interpreter::default();
2207
2208 let rib_expr = r#"
2209 let x = ["foo", "bar"];
2210
2211 reduce z, a in x from "" {
2212 let result = if z == "" then a else "${z}, ${a}";
2213
2214 yield result;
2215 }
2216
2217 "#;
2218
2219 let expr = Expr::from_text(rib_expr).unwrap();
2220
2221 let compiler = RibCompiler::default();
2222
2223 let compiled = compiler.compile(expr).unwrap();
2224
2225 let result = interpreter
2226 .run(compiled.byte_code)
2227 .await
2228 .unwrap()
2229 .get_val()
2230 .unwrap();
2231
2232 assert_eq!(result, "foo, bar".into_value_and_type());
2233 }
2234
2235 #[test]
2236 async fn test_interpreter_list_reduce_empty() {
2237 let mut interpreter = Interpreter::default();
2238
2239 let rib_expr = r#"
2240 let x: list<u8> = [];
2241
2242 reduce z, a in x from 0u8 {
2243 yield z + a;
2244 }
2245
2246 "#;
2247
2248 let expr = Expr::from_text(rib_expr).unwrap();
2249
2250 let compiler = RibCompiler::default();
2251
2252 let compiled = compiler.compile(expr).unwrap();
2253
2254 let result = interpreter
2255 .run(compiled.byte_code)
2256 .await
2257 .unwrap()
2258 .get_val()
2259 .unwrap();
2260
2261 assert_eq!(result, 0u8.into_value_and_type());
2262 }
2263
2264 #[test]
2265 async fn test_interpreter_with_numbers_1() {
2266 let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2267
2268 let mut interpreter = test_utils::interpreter_with_static_function_response(
2269 &ValueAndType::new(Value::U64(2), u64()),
2270 None,
2271 );
2272
2273 let rib = r#"
2275 let worker = instance("my-worker");
2276 worker.foo(1)
2277 "#;
2278
2279 let expr = Expr::from_text(rib).unwrap();
2280
2281 let compiler_config = RibCompilerConfig::new(component_metadata, vec![], vec![]);
2282 let compiler = RibCompiler::new(compiler_config);
2283
2284 let compiled = compiler.compile(expr).unwrap();
2285 let result = interpreter.run(compiled.byte_code).await.unwrap();
2286
2287 assert_eq!(
2288 result.get_val().unwrap(),
2289 ValueAndType::new(Value::U64(2), u64())
2290 );
2291 }
2292
2293 #[test]
2294 async fn test_interpreter_with_numbers_2() {
2295 let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2296
2297 let mut interpreter = test_utils::interpreter_with_static_function_response(
2298 &ValueAndType::new(Value::U64(2), u64()),
2299 None,
2300 );
2301
2302 let rib = r#"
2306 let worker = instance("my-worker");
2307 let z = 1 + 2;
2308 worker.foo(z)
2309 "#;
2310
2311 let expr = Expr::from_text(rib).unwrap();
2312
2313 let compiler_config = RibCompilerConfig::new(component_metadata, vec![], vec![]);
2314 let compiler = RibCompiler::new(compiler_config);
2315
2316 let compiled = compiler.compile(expr).unwrap();
2317 let result = interpreter.run(compiled.byte_code).await.unwrap();
2318
2319 assert_eq!(
2320 result.get_val().unwrap(),
2321 ValueAndType::new(Value::U64(2), u64())
2322 );
2323 }
2324
2325 #[test]
2326 async fn test_interpreter_with_numbers_3() {
2327 let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2328
2329 let rib = r#"
2332 let worker = instance("my-worker");
2333 let z = 1: u8 + 2;
2334 worker.foo(z)
2335 "#;
2336
2337 let expr = Expr::from_text(rib).unwrap();
2338 let compiler = RibCompiler::new(RibCompilerConfig::new(component_metadata, vec![], vec![]));
2339 let compile_result = compiler.compile(expr);
2340 assert!(compile_result.is_err());
2341 }
2342
2343 #[test]
2344 async fn test_interpreter_with_numbers_4() {
2345 let component_metadata = test_utils::configurable_metadata("foo", vec![u32()], Some(u64()));
2346
2347 let rib = r#"
2351 let worker = instance("my-worker");
2352 let z = 1: u8 + 2: u8;
2353 worker.foo(z)
2354 "#;
2355
2356 let expr = Expr::from_text(rib).unwrap();
2357 let compiler = RibCompiler::new(RibCompilerConfig::new(component_metadata, vec![], vec![]));
2358 let compile_result = compiler.compile(expr);
2359 assert!(compile_result.is_err());
2360 }
2361
2362 #[test]
2363 async fn test_interpreter_list_comprehension() {
2364 let mut interpreter = Interpreter::default();
2365
2366 let rib_expr = r#"
2367 let x = ["foo", "bar"];
2368
2369 for i in x {
2370 yield i;
2371 }
2372
2373 "#;
2374
2375 let expr = Expr::from_text(rib_expr).unwrap();
2376
2377 let compiler = RibCompiler::default();
2378 let compiled = compiler.compile(expr).unwrap();
2379
2380 let result = interpreter
2381 .run(compiled.byte_code)
2382 .await
2383 .unwrap()
2384 .get_val()
2385 .unwrap();
2386
2387 let expected = r#"["foo", "bar"]"#;
2388 let expected_value = golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2389
2390 assert_eq!(result, expected_value);
2391 }
2392
2393 #[test]
2394 async fn test_interpreter_list_comprehension_empty() {
2395 let mut interpreter = Interpreter::default();
2396
2397 let rib_expr = r#"
2398 let x: list<string> = [];
2399
2400 for i in x {
2401 yield i;
2402 }
2403
2404 "#;
2405
2406 let expr = Expr::from_text(rib_expr).unwrap();
2407
2408 let compiler = RibCompiler::default();
2409 let compiled = compiler.compile(expr).unwrap();
2410
2411 let result = interpreter
2412 .run(compiled.byte_code)
2413 .await
2414 .unwrap()
2415 .get_val()
2416 .unwrap();
2417
2418 let expected = r#"[]"#;
2419 let expected_value_and_type =
2420 golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2421
2422 assert_eq!(result, expected_value_and_type);
2423 }
2424
2425 #[test]
2426 async fn test_interpreter_pattern_match_on_option_nested() {
2427 let mut interpreter = Interpreter::default();
2428
2429 let expr = r#"
2430 let x: option<option<u64>> = none;
2431
2432 match x {
2433 some(some(t)) => t,
2434 some(none) => 0u64,
2435 none => 0u64
2436
2437 }
2438 "#;
2439
2440 let expr = Expr::from_text(expr).unwrap();
2441 let compiler = RibCompiler::default();
2442 let compiled = compiler.compile(expr).unwrap();
2443 let result = interpreter.run(compiled.byte_code).await.unwrap();
2444
2445 assert_eq!(result.get_val().unwrap(), 0u64.into_value_and_type());
2446 }
2447
2448 #[test]
2449 async fn test_interpreter_pattern_match_on_tuple() {
2450 let mut interpreter = Interpreter::default();
2451
2452 let expr = r#"
2453 let x: tuple<u64, string, string> = (1, "foo", "bar");
2454
2455 match x {
2456 (x, y, z) => "${x} ${y} ${z}"
2457 }
2458 "#;
2459
2460 let expr = Expr::from_text(expr).unwrap();
2461 let compiler = RibCompiler::default();
2462 let compiled = compiler.compile(expr).unwrap();
2463 let result = interpreter.run(compiled.byte_code).await.unwrap();
2464
2465 assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2466 }
2467
2468 #[test]
2469 async fn test_interpreter_pattern_match_on_tuple_with_option_some() {
2470 let mut interpreter = Interpreter::default();
2471
2472 let expr = r#"
2473 let x: tuple<u64, option<string>, string> = (1, some("foo"), "bar");
2474
2475 match x {
2476 (x, none, z) => "${x} ${z}",
2477 (x, some(y), z) => "${x} ${y} ${z}"
2478 }
2479 "#;
2480
2481 let expr = Expr::from_text(expr).unwrap();
2482 let compiler = RibCompiler::default();
2483 let compiled = compiler.compile(expr).unwrap();
2484 let result = interpreter.run(compiled.byte_code).await.unwrap();
2485
2486 assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2487 }
2488
2489 #[test]
2490 async fn test_interpreter_pattern_match_on_tuple_with_option_none() {
2491 let mut interpreter = Interpreter::default();
2492
2493 let expr = r#"
2494 let x: tuple<u64, option<string>, string> = (1, none, "bar");
2495
2496 match x {
2497 (x, none, z) => "${x} ${z}",
2498 (x, some(y), z) => "${x} ${y} ${z}"
2499 }
2500 "#;
2501
2502 let expr = Expr::from_text(expr).unwrap();
2503 let compiler = RibCompiler::default();
2504 let compiled = compiler.compile(expr).unwrap();
2505 let result = interpreter.run(compiled.byte_code).await.unwrap();
2506
2507 assert_eq!(result.get_val().unwrap(), "1 bar".into_value_and_type());
2508 }
2509
2510 #[test]
2511 async fn test_interpreter_pattern_match_dynamic_branch_1() {
2512 let mut interpreter = Interpreter::default();
2513
2514 let expr = r#"
2515 let x = 1;
2516
2517 match x {
2518 1 => ok(1),
2519 2 => err("none")
2520 }
2521 "#;
2522
2523 let expr = Expr::from_text(expr).unwrap();
2524 let compiler = RibCompiler::default();
2525 let compiled = compiler.compile(expr).unwrap();
2526 let rib_result = interpreter.run(compiled.byte_code).await.unwrap();
2527
2528 let expected = ValueAndType::new(
2529 Value::Result(Ok(Some(Box::new(Value::S32(1))))),
2530 result(s32(), str()),
2531 );
2532
2533 assert_eq!(rib_result.get_val().unwrap(), expected);
2534 }
2535
2536 #[test]
2537 async fn test_interpreter_pattern_match_dynamic_branch_2() {
2538 let mut interpreter = Interpreter::default();
2539
2540 let expr = r#"
2541 let x = some({foo: 1});
2542
2543 match x {
2544 some(x) => ok(x.foo),
2545 none => err("none")
2546 }
2547 "#;
2548
2549 let expr = Expr::from_text(expr).unwrap();
2550 let compiler = RibCompiler::default();
2551 let compiled = compiler.compile(expr).unwrap();
2552 let rib_result = interpreter.run(compiled.byte_code).await.unwrap();
2553
2554 let expected = ValueAndType::new(
2555 Value::Result(Ok(Some(Box::new(Value::S32(1))))),
2556 result(s32(), str()),
2557 );
2558
2559 assert_eq!(rib_result.get_val().unwrap(), expected);
2560 }
2561
2562 #[test]
2563 async fn test_interpreter_pattern_match_on_tuple_with_all_types() {
2564 let mut interpreter = Interpreter::default();
2565
2566 let tuple = test_utils::get_analysed_type_tuple();
2567
2568 let analysed_exports = test_utils::configurable_metadata("foo", vec![tuple], Some(str()));
2569
2570 let expr = r#"
2571 let worker = instance();
2572 let record = { request : { path : { user : "jak" } }, y : "bar" };
2573 let input = (1, ok(100), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2574 worker.foo(input);
2575 match input {
2576 (n1, err(x1), txt, rec, process-user(x), register-user(n), validate, dev, prod, test) => "Invalid",
2577 (n1, ok(x2), txt, rec, process-user(x), register-user(n), validate, prod, dev, test) => "foo ${x2} ${n1} ${txt} ${rec.request.path.user} ${validate} ${prod} ${dev} ${test}"
2578 }
2579
2580 "#;
2581
2582 let expr = Expr::from_text(expr).unwrap();
2583 let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2584 let compiled = compiler.compile(expr).unwrap();
2585 let result = interpreter.run(compiled.byte_code).await.unwrap();
2586
2587 assert_eq!(
2588 result.get_val().unwrap(),
2589 "foo 100 1 bar jak validate prod dev test".into_value_and_type()
2590 );
2591 }
2592
2593 #[test]
2594 async fn test_interpreter_pattern_match_on_tuple_with_wild_pattern() {
2595 let mut interpreter = Interpreter::default();
2596
2597 let tuple = test_utils::get_analysed_type_tuple();
2598
2599 let analysed_exports =
2600 test_utils::configurable_metadata("my-worker-function", vec![tuple], Some(str()));
2601
2602 let expr = r#"
2603 let worker = instance();
2604 let record = { request : { path : { user : "jak" } }, y : "baz" };
2605 let input = (1, ok(1), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2606 worker.my-worker-function(input);
2607 match input {
2608 (n1, ok(x), txt, rec, _, _, _, _, prod, _) => "prod ${n1} ${txt} ${rec.request.path.user} ${rec.y}",
2609 (n1, ok(x), txt, rec, _, _, _, _, dev, _) => "dev ${n1} ${txt} ${rec.request.path.user} ${rec.y}"
2610 }
2611 "#;
2612
2613 let expr = Expr::from_text(expr).unwrap();
2614 let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2615 let compiled = compiler.compile(expr).unwrap();
2616 let result = interpreter.run(compiled.byte_code).await.unwrap();
2617
2618 assert_eq!(
2619 result.get_val().unwrap(),
2620 "dev 1 bar jak baz".into_value_and_type()
2621 );
2622 }
2623
2624 #[test]
2625 async fn test_interpreter_record_output_in_pattern_match() {
2626 let input_analysed_type = test_utils::get_analysed_type_record();
2627 let output_analysed_type = test_utils::get_analysed_type_result();
2628
2629 let result_value = get_value_and_type(&output_analysed_type, r#"ok(1)"#);
2630
2631 let mut interpreter =
2632 test_utils::interpreter_with_static_function_response(&result_value, None);
2633
2634 let analysed_exports = test_utils::configurable_metadata(
2635 "my-worker-function",
2636 vec![input_analysed_type],
2637 Some(output_analysed_type),
2638 );
2639
2640 let expr = r#"
2641 let worker = instance();
2642 let input = { request : { path : { user : "jak" } }, y : "baz" };
2643 let result = worker.my-worker-function(input);
2644 match result {
2645 ok(result) => { body: result, status: 200 },
2646 err(result) => { status: 400, body: 400 }
2647 }
2648 "#;
2649
2650 let expr = Expr::from_text(expr).unwrap();
2651 let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2652 let compiled = compiler.compile(expr).unwrap();
2653 let result = interpreter.run(compiled.byte_code).await.unwrap();
2654
2655 let expected = test_utils::get_value_and_type(
2656 &record(vec![field("body", u64()), field("status", s32())]),
2657 r#"{body: 1, status: 200}"#,
2658 );
2659
2660 assert_eq!(result.get_val().unwrap(), expected);
2661 }
2662
2663 #[test]
2664 async fn test_interpreter_tuple_output_in_pattern_match() {
2665 let input_analysed_type = test_utils::get_analysed_type_record();
2666 let output_analysed_type = test_utils::get_analysed_type_result();
2667
2668 let result_value = get_value_and_type(&output_analysed_type, r#"err("failed")"#);
2669
2670 let mut interpreter =
2671 test_utils::interpreter_with_static_function_response(&result_value, None);
2672
2673 let analysed_exports = test_utils::configurable_metadata(
2674 "my-worker-function",
2675 vec![input_analysed_type],
2676 Some(output_analysed_type),
2677 );
2678
2679 let expr = r#"
2680 let input = { request : { path : { user : "jak" } }, y : "baz" };
2681 let worker = instance();
2682 let result = worker.my-worker-function(input);
2683 match result {
2684 ok(res) => ("${res}", "foo"),
2685 err(msg) => (msg, "bar")
2686 }
2687 "#;
2688
2689 let expr = Expr::from_text(expr).unwrap();
2690 let compiler = RibCompiler::new(RibCompilerConfig::new(analysed_exports, vec![], vec![]));
2691 let compiled = compiler.compile(expr).unwrap();
2692 let result = interpreter.run(compiled.byte_code).await.unwrap();
2693
2694 let expected = get_value_and_type(&tuple(vec![str(), str()]), r#"("failed", "bar")"#);
2695
2696 assert_eq!(result.get_val().unwrap(), expected);
2697 }
2698
2699 #[test]
2700 async fn test_interpreter_with_indexed_resource_drop() {
2701 let expr = r#"
2702 let user_id = "user";
2703 let worker = instance();
2704 let cart = worker.cart(user_id);
2705 cart.drop();
2706 "success"
2707 "#;
2708 let expr = Expr::from_text(expr).unwrap();
2709 let component_metadata = test_utils::get_metadata_with_resource_with_params();
2710
2711 let compiler_config = RibCompilerConfig::new(component_metadata, vec![], vec![]);
2712 let compiler = RibCompiler::new(compiler_config);
2713 let compiled = compiler.compile(expr).unwrap();
2714
2715 let mut rib_interpreter = test_utils::interpreter_with_resource_function_invoke_impl(None);
2716 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2717
2718 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2719 }
2720
2721 #[test]
2722 async fn test_interpreter_with_indexed_resource_checkout() {
2723 let expr = r#"
2724 let user_id = "foo";
2725 let worker = instance();
2726 let cart = worker.cart(user_id);
2727 let result = cart.checkout();
2728 result
2729 "#;
2730
2731 let expr = Expr::from_text(expr).unwrap();
2732
2733 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2734
2735 let compiler_config =
2736 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2737 let compiler = RibCompiler::new(compiler_config);
2738
2739 let compiled = compiler.compile(expr).unwrap();
2740
2741 let mut rib_executor = test_deps.interpreter;
2742 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2743
2744 let expected_value = Value::Variant {
2745 case_idx: 1,
2746 case_value: Some(Box::new(Value::Record(vec![Value::String(
2747 "foo".to_string(),
2748 )]))),
2749 };
2750
2751 assert_eq!(result.get_val().unwrap().value, expected_value);
2752 }
2753
2754 #[test]
2755 async fn test_interpreter_with_indexed_resources_static_functions_1() {
2756 let expr = r#"
2757 let worker = instance();
2758 let result = worker.cart.create("afsal");
2759 result.checkout()
2760 "#;
2761
2762 let expr = Expr::from_text(expr).unwrap();
2763
2764 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2765
2766 let compiler_config =
2767 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2768 let compiler = RibCompiler::new(compiler_config);
2769
2770 let compiled = compiler.compile(expr).unwrap();
2771
2772 let mut rib_executor = test_deps.interpreter;
2773 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2774
2775 let expected_value = Value::Variant {
2776 case_idx: 1,
2777 case_value: Some(Box::new(Value::Record(vec![Value::String(
2778 "foo".to_string(),
2779 )]))),
2780 };
2781
2782 assert_eq!(result.get_val().unwrap().value, expected_value);
2783 }
2784
2785 #[test]
2786 async fn test_interpreter_with_indexed_resources_static_functions_2() {
2787 let expr = r#"
2788 let worker = instance();
2789 let default-cart = worker.cart("default");
2790 let alternate-cart = worker.cart.create-safe("afsal");
2791 match alternate-cart {
2792 ok(alt) => alt.checkout(),
2793 err(_) => default-cart.checkout()
2794 }
2795 "#;
2796
2797 let expr = Expr::from_text(expr).unwrap();
2798
2799 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2800
2801 let compiler_config =
2802 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2803 let compiler = RibCompiler::new(compiler_config);
2804
2805 let compiled = compiler.compile(expr).unwrap();
2806
2807 let mut rib_executor = test_deps.interpreter;
2808 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2809
2810 let expected_value = Value::Variant {
2811 case_idx: 1,
2812 case_value: Some(Box::new(Value::Record(vec![Value::String(
2813 "foo".to_string(),
2814 )]))),
2815 };
2816
2817 assert_eq!(result.get_val().unwrap().value, expected_value);
2818 }
2819
2820 #[test]
2821 async fn test_interpreter_with_indexed_resource_get_cart_contents() {
2822 let expr = r#"
2823 let user_id = "bar";
2824 let worker = instance();
2825 let cart = worker.cart(user_id);
2826 let result = cart.get-cart-contents();
2827 result[0].product-id
2828 "#;
2829
2830 let expr = Expr::from_text(expr).unwrap();
2831
2832 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2833
2834 let compiler_config =
2835 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2836 let compiler = RibCompiler::new(compiler_config);
2837
2838 let compiled = compiler.compile(expr).unwrap();
2839
2840 let mut rib_executor = test_deps.interpreter;
2841
2842 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2843
2844 assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2845 }
2846
2847 #[test]
2848 async fn test_interpreter_with_indexed_resource_update_item_quantity() {
2849 let expr = r#"
2850 let user_id = "jon";
2851 let product_id = "mac";
2852 let quantity = 1032;
2853 let worker = instance();
2854 let cart = worker.cart(user_id);
2855 cart.update-item-quantity(product_id, quantity);
2856 "successfully updated"
2857 "#;
2858 let expr = Expr::from_text(expr).unwrap();
2859
2860 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2861
2862 let compiler_config =
2863 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2864 let compiler = RibCompiler::new(compiler_config);
2865
2866 let compiled = compiler.compile(expr).unwrap();
2867
2868 let mut rib_executor = test_deps.interpreter;
2869
2870 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2871
2872 assert_eq!(
2873 result.get_val().unwrap(),
2874 "successfully updated".into_value_and_type()
2875 );
2876 }
2877
2878 #[test]
2879 async fn test_interpreter_with_indexed_resource_add_item() {
2880 let expr = r#"
2881 let user_id = "foo";
2882 let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2883 let worker = instance();
2884 let cart = worker.cart(user_id);
2885 cart.add-item(product);
2886
2887 "successfully added"
2888 "#;
2889
2890 let expr = Expr::from_text(expr).unwrap();
2891
2892 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
2893
2894 let compiler_config =
2895 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2896 let compiler = RibCompiler::new(compiler_config);
2897
2898 let compiled = compiler.compile(expr).unwrap();
2899
2900 let mut rib_executor = test_deps.interpreter;
2901
2902 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2903
2904 assert_eq!(
2905 result.get_val().unwrap(),
2906 "successfully added".into_value_and_type()
2907 );
2908 }
2909
2910 #[test]
2911 async fn test_interpreter_with_resource_add_item() {
2912 let expr = r#"
2913 let worker = instance();
2914 let cart = worker.cart();
2915 let user_id = "foo";
2916 let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2917 cart.add-item(product);
2918
2919 "successfully added"
2920 "#;
2921
2922 let expr = Expr::from_text(expr).unwrap();
2923
2924 let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
2925
2926 let compiler_config =
2927 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2928 let compiler = RibCompiler::new(compiler_config);
2929
2930 let compiled = compiler.compile(expr).unwrap();
2931
2932 let mut rib_executor = test_deps.interpreter;
2933
2934 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2935
2936 assert_eq!(
2937 result.get_val().unwrap(),
2938 "successfully added".into_value_and_type()
2939 );
2940 }
2941
2942 #[test]
2943 async fn test_interpreter_with_resource_get_cart_contents() {
2944 let expr = r#"
2945 let worker = instance();
2946 let cart = worker.cart();
2947 let result = cart.get-cart-contents();
2948 result[0].product-id
2949 "#;
2950
2951 let expr = Expr::from_text(expr).unwrap();
2952
2953 let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
2954
2955 let compiler_config =
2956 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2957 let compiler = RibCompiler::new(compiler_config);
2958
2959 let compiled = compiler.compile(expr).unwrap();
2960
2961 let mut rib_executor = test_deps.interpreter;
2962 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2963
2964 assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2965 }
2966
2967 #[test]
2968 async fn test_interpreter_with_resource_update_item() {
2969 let expr = r#"
2970 let worker = instance();
2971 let product_id = "mac";
2972 let quantity = 1032;
2973 let cart = worker.cart();
2974 cart.update-item-quantity(product_id, quantity);
2975 "successfully updated"
2976 "#;
2977 let expr = Expr::from_text(expr).unwrap();
2978
2979 let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
2980
2981 let compiler_config =
2982 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
2983 let compiler = RibCompiler::new(compiler_config);
2984
2985 let compiled = compiler.compile(expr).unwrap();
2986
2987 let mut rib_executor = test_deps.interpreter;
2988
2989 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2990
2991 assert_eq!(
2992 result.get_val().unwrap(),
2993 "successfully updated".into_value_and_type()
2994 );
2995 }
2996
2997 #[test]
2998 async fn test_interpreter_with_resource_checkout() {
2999 let expr = r#"
3000 let worker = instance();
3001 let cart = worker.cart();
3002 let result = cart.checkout();
3003 result
3004 "#;
3005
3006 let expr = Expr::from_text(expr).unwrap();
3007
3008 let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
3009
3010 let compiler_config =
3011 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3012
3013 let compiler = RibCompiler::new(compiler_config);
3014
3015 let compiled = compiler.compile(expr).unwrap();
3016
3017 let mut interpreter = test_deps.interpreter;
3018
3019 let result = interpreter.run(compiled.byte_code).await.unwrap();
3020
3021 let expected_result = Value::Variant {
3022 case_idx: 1,
3023 case_value: Some(Box::new(Value::Record(vec![Value::String(
3024 "foo".to_string(),
3025 )]))),
3026 };
3027
3028 assert_eq!(result.get_val().unwrap().value, expected_result);
3029 }
3030
3031 #[test]
3032 async fn test_interpreter_with_resource_drop() {
3033 let expr = r#"
3034 let worker = instance();
3035 let cart = worker.cart();
3036 cart.drop();
3037 "success"
3038 "#;
3039 let expr = Expr::from_text(expr).unwrap();
3040 let test_deps = RibTestDeps::test_deps_with_resource_functions(None);
3041
3042 let compiler_config =
3043 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3044 let compiler = RibCompiler::new(compiler_config);
3045 let compiled = compiler.compile(expr).unwrap();
3046
3047 let mut rib_interpreter = test_deps.interpreter;
3048 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3049
3050 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3051 }
3052
3053 #[test]
3054 async fn test_interpreter_for_select_index_expr_1() {
3055 let expr = r#"
3058 let list: list<u8> = [1, 2, 3, 4, 5];
3059 let index: u8 = 4;
3060 list[index]
3061 "#;
3062
3063 let expr = Expr::from_text(expr).unwrap();
3064
3065 let compiler = RibCompiler::default();
3066 let compiled = compiler.compile(expr).unwrap();
3067
3068 let mut interpreter = Interpreter::default();
3069 let result = interpreter.run(compiled.byte_code).await.unwrap();
3070
3071 let expected = ValueAndType::new(Value::U8(5), u8());
3072
3073 assert_eq!(result.get_val().unwrap(), expected);
3074 }
3075
3076 #[test]
3077 async fn test_interpreter_for_select_index_expr_out_of_bound() {
3078 let expr = r#"
3079 let list: list<u8> = [1, 2, 3, 4, 5];
3080 let index: u8 = 10;
3081 list[index]
3082 "#;
3083
3084 let expr = Expr::from_text(expr).unwrap();
3085
3086 let compiler = RibCompiler::default();
3087 let compiled = compiler.compile(expr).unwrap();
3088
3089 let mut interpreter = Interpreter::default();
3090 let result = interpreter
3091 .run(compiled.byte_code)
3092 .await
3093 .unwrap_err()
3094 .to_string();
3095
3096 assert_eq!(result, "index out of bound: 10 (size: 5)".to_string());
3097 }
3098
3099 #[test]
3100 async fn test_interpreter_for_select_index_expr_2() {
3101 let expr = r#"
3102 let list: list<u8> = [1, 2, 3, 4, 5];
3103 let indices: list<u8> = [0, 1, 2, 3];
3104
3105 for i in indices {
3106 yield list[i];
3107 }
3108 "#;
3109
3110 let expr = Expr::from_text(expr).unwrap();
3111
3112 let compiler = RibCompiler::default();
3113 let compiled = compiler.compile(expr).unwrap();
3114
3115 let mut interpreter = Interpreter::default();
3116 let result = interpreter.run(compiled.byte_code).await.unwrap();
3117
3118 let expected = ValueAndType::new(
3119 Value::List(vec![Value::U8(1), Value::U8(2), Value::U8(3), Value::U8(4)]),
3120 list(u8()),
3121 );
3122
3123 assert_eq!(result.get_val().unwrap(), expected);
3124 }
3125
3126 #[test]
3127 async fn test_interpreter_for_select_index_expr_3() {
3128 let expr = r#"
3129 let list: list<u8> = [2, 5, 4];
3130 let indices: list<u8> = [0, 1];
3131
3132 reduce z, index in indices from 0u8 {
3133 yield list[index] + z;
3134 }
3135 "#;
3136
3137 let expr = Expr::from_text(expr).unwrap();
3138
3139 let compiler = RibCompiler::default();
3140 let compiled = compiler.compile(expr).unwrap();
3141
3142 let mut interpreter = Interpreter::default();
3143 let result = interpreter.run(compiled.byte_code).await.unwrap();
3144
3145 let expected = ValueAndType::new(Value::U8(7), u8());
3146
3147 assert_eq!(result.get_val().unwrap(), expected);
3148 }
3149
3150 #[test]
3151 async fn test_interpreter_for_select_index_expr_4() {
3152 let expr = r#"
3153 let list: list<u8> = [2, 5, 4];
3154 let x: u8 = 0;
3155 let y: u8 = 2;
3156 list[x..=y]
3157 "#;
3158
3159 let expr = Expr::from_text(expr).unwrap();
3160
3161 let compiler = RibCompiler::default();
3162 let compiled = compiler.compile(expr).unwrap();
3163
3164 let mut interpreter = Interpreter::default();
3165 let result = interpreter.run(compiled.byte_code).await.unwrap();
3166
3167 let expected = ValueAndType::new(
3168 Value::List(vec![Value::U8(2), Value::U8(5), Value::U8(4)]),
3169 list(u8()),
3170 );
3171
3172 assert_eq!(result.get_val().unwrap(), expected);
3173 }
3174
3175 #[test]
3176 async fn test_interpreter_for_select_index_expr_5() {
3177 let expr = r#"
3178 let list: list<u8> = [2, 5, 4];
3179 let x: u8 = 0;
3180 let y: u8 = 2;
3181 let x1: u8 = 1;
3182 let result = list[x..=y];
3183 for i in result[x1..=y] {
3184 yield i;
3185 }
3186 "#;
3187
3188 let expr = Expr::from_text(expr).unwrap();
3189
3190 let compiler = RibCompiler::default();
3191 let compiled = compiler.compile(expr).unwrap();
3192
3193 let mut interpreter = Interpreter::default();
3194 let result = interpreter.run(compiled.byte_code).await.unwrap();
3195
3196 let expected = ValueAndType::new(Value::List(vec![Value::U8(5), Value::U8(4)]), list(u8()));
3197
3198 assert_eq!(result.get_val().unwrap(), expected);
3199 }
3200
3201 #[test]
3202 async fn test_interpreter_for_select_index_expr_6() {
3203 let expr = r#"
3204 let list: list<u8> = [2, 5, 4, 6];
3205 let x: u8 = 0;
3206 let y: u8 = 2;
3207 let result = list[x..y];
3208 for i in result[x..y] {
3209 yield i;
3210 }
3211 "#;
3212
3213 let expr = Expr::from_text(expr).unwrap();
3214
3215 let compiler = RibCompiler::default();
3216 let compiled = compiler.compile(expr).unwrap();
3217
3218 let mut interpreter = Interpreter::default();
3219 let result = interpreter.run(compiled.byte_code).await.unwrap();
3220
3221 let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
3222
3223 assert_eq!(result.get_val().unwrap(), expected);
3224 }
3225
3226 #[test]
3227 async fn test_interpreter_for_select_index_expr_7() {
3228 let expr = r#"
3229 let list: list<u8> = [2, 5, 4, 6];
3230 let x: u8 = 0;
3231 let result = list[x..];
3232 for i in result[x..] {
3233 yield i;
3234 }
3235 "#;
3236
3237 let expr = Expr::from_text(expr).unwrap();
3238
3239 let compiler = RibCompiler::default();
3240 let compiled = compiler.compile(expr).unwrap();
3241
3242 let mut interpreter = Interpreter::default();
3243 let result = interpreter.run(compiled.byte_code).await.unwrap();
3244
3245 let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
3246
3247 assert_eq!(result.get_val().unwrap(), expected);
3248 }
3249
3250 #[test]
3251 async fn test_interpreter_for_select_index_expr_8() {
3252 let expr = r#"
3253 let list: list<u8> = [2, 5, 4, 6];
3254 let result = list[0..2];
3255 for i in result[0..2] {
3256 yield i;
3257 }
3258 "#;
3259
3260 let expr = Expr::from_text(expr).unwrap();
3261
3262 let compiler = RibCompiler::default();
3263 let compiled = compiler.compile(expr).unwrap();
3264
3265 let mut interpreter = Interpreter::default();
3266 let result = interpreter.run(compiled.byte_code).await.unwrap();
3267
3268 let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
3269
3270 assert_eq!(result.get_val().unwrap(), expected);
3271 }
3272
3273 #[test]
3277 async fn test_interpreter_range_returns_1() {
3278 let expr = r#"
3279 let x = 1..;
3280 x
3281 "#;
3282
3283 let expr = Expr::from_text(expr).unwrap();
3284
3285 let compiler = RibCompiler::default();
3286 let compiled = compiler.compile(expr).unwrap();
3287
3288 let mut interpreter = Interpreter::default();
3289 let result = interpreter.run(compiled.byte_code).await.unwrap();
3290
3291 let expected = ValueAndType::new(
3292 Value::Record(vec![
3293 Value::S32(1),
3294 Value::Bool(false), ]),
3296 record(vec![field("from", s32()), field("inclusive", bool())]),
3297 );
3298
3299 assert_eq!(result.get_val().unwrap(), expected);
3300 }
3301
3302 #[test]
3303 async fn test_interpreter_range_returns_2() {
3304 let expr = r#"
3305 let x = 1..2;
3306 x
3307 "#;
3308
3309 let expr = Expr::from_text(expr).unwrap();
3310
3311 let compiler = RibCompiler::default();
3312 let compiled = compiler.compile(expr).unwrap();
3313
3314 let mut interpreter = Interpreter::default();
3315 let result = interpreter.run(compiled.byte_code).await.unwrap();
3316
3317 let expected = ValueAndType::new(
3318 Value::Record(vec![
3319 Value::S32(1),
3320 Value::S32(2),
3321 Value::Bool(false), ]),
3323 record(vec![
3324 field("from", s32()),
3325 field("to", s32()),
3326 field("inclusive", bool()),
3327 ]),
3328 );
3329
3330 assert_eq!(result.get_val().unwrap(), expected);
3331 }
3332
3333 #[test]
3334 async fn test_interpreter_range_returns_3() {
3335 let expr = r#"
3336 let x = 1..=10;
3337 x
3338 "#;
3339
3340 let expr = Expr::from_text(expr).unwrap();
3341
3342 let compiler = RibCompiler::default();
3343 let compiled = compiler.compile(expr).unwrap();
3344
3345 let mut interpreter = Interpreter::default();
3346 let result = interpreter.run(compiled.byte_code).await.unwrap();
3347
3348 let expected = ValueAndType::new(
3349 Value::Record(vec![
3350 Value::S32(1),
3351 Value::S32(10),
3352 Value::Bool(true), ]),
3354 record(vec![
3355 field("from", s32()),
3356 field("to", s32()),
3357 field("inclusive", bool()),
3358 ]),
3359 );
3360
3361 assert_eq!(result.get_val().unwrap(), expected);
3362 }
3363
3364 #[test]
3365 async fn test_interpreter_range_returns_4() {
3366 let expr = r#"
3367 let x = 1:u64;
3368 let y = x;
3369 let range = x..=y;
3370 let range2 = x..;
3371 let range3 = x..y;
3372 range;
3373 range2;
3374 range3
3375 "#;
3376
3377 let expr = Expr::from_text(expr).unwrap();
3378
3379 let compiler = RibCompiler::default();
3380 let compiled = compiler.compile(expr).unwrap();
3381
3382 let mut interpreter = Interpreter::default();
3383 let result = interpreter.run(compiled.byte_code).await.unwrap();
3384
3385 let expected = ValueAndType::new(
3386 Value::Record(vec![Value::U64(1), Value::U64(1), Value::Bool(false)]),
3387 record(vec![
3388 field("from", u64()),
3389 field("to", u64()),
3390 field("inclusive", bool()),
3391 ]),
3392 );
3393
3394 assert_eq!(result.get_val().unwrap(), expected);
3395 }
3396
3397 #[test]
3398 async fn test_interpreter_range_returns_5() {
3399 let expr = r#"
3400 let y = 1 + 10;
3401 1..y
3402 "#;
3403
3404 let expr = Expr::from_text(expr).unwrap();
3405
3406 let compiler = RibCompiler::default();
3407 let compiled = compiler.compile(expr).unwrap();
3408
3409 let mut interpreter = Interpreter::default();
3410 let result = interpreter.run(compiled.byte_code).await.unwrap();
3411
3412 let expected = ValueAndType::new(
3413 Value::Record(vec![Value::S32(1), Value::S32(11), Value::Bool(false)]),
3414 record(vec![
3415 field("from", s32()),
3416 field("to", s32()),
3417 field("inclusive", bool()),
3418 ]),
3419 );
3420
3421 assert_eq!(result.get_val().unwrap(), expected);
3422 }
3423
3424 #[test]
3425 async fn test_interpreter_range_with_comprehension_1() {
3426 let expr = r#"
3427 let range = 1..=5;
3428 for i in range {
3429 yield i;
3430 }
3431
3432 "#;
3433
3434 let expr = Expr::from_text(expr).unwrap();
3435
3436 let compiler = RibCompiler::default();
3437 let compiled = compiler.compile(expr).unwrap();
3438
3439 let mut interpreter = Interpreter::default();
3440 let result = interpreter.run(compiled.byte_code).await.unwrap();
3441
3442 let expected = ValueAndType::new(
3443 Value::List(vec![
3444 Value::S32(1),
3445 Value::S32(2),
3446 Value::S32(3),
3447 Value::S32(4),
3448 Value::S32(5),
3449 ]),
3450 list(s32()),
3451 );
3452
3453 assert_eq!(result.get_val().unwrap(), expected);
3454 }
3455
3456 #[test]
3457 async fn test_interpreter_range_with_comprehension_2() {
3458 let expr = r#"
3459 let range = 1..5;
3460 for i in range {
3461 yield i;
3462 }
3463
3464 "#;
3465
3466 let expr = Expr::from_text(expr).unwrap();
3467
3468 let compiler = RibCompiler::default();
3469 let compiled = compiler.compile(expr).unwrap();
3470
3471 let mut interpreter = Interpreter::default();
3472 let result = interpreter.run(compiled.byte_code).await.unwrap();
3473
3474 let expected = ValueAndType::new(
3475 Value::List(vec![
3476 Value::S32(1),
3477 Value::S32(2),
3478 Value::S32(3),
3479 Value::S32(4),
3480 ]),
3481 list(s32()),
3482 );
3483
3484 assert_eq!(result.get_val().unwrap(), expected);
3485 }
3486
3487 #[test]
3488 async fn test_interpreter_range_with_comprehension_3() {
3489 let expr = r#"
3492 let range = 1..;
3493 for i in range {
3494 yield i;
3495 }
3496
3497 "#;
3498
3499 let expr = Expr::from_text(expr).unwrap();
3500
3501 let compiler = RibCompiler::default();
3502 let compiled = compiler.compile(expr).unwrap();
3503
3504 let mut interpreter = Interpreter::default();
3505 let result = interpreter.run(compiled.byte_code).await;
3506 assert!(result.is_err());
3507 }
3508
3509 #[test]
3510 async fn test_interpreter_range_with_list_reduce_1() {
3511 let expr = r#"
3514 let initial = 1;
3515 let final = 5;
3516 let x = initial..final;
3517
3518 reduce z, a in x from 0u8 {
3519 yield z + a;
3520 }
3521
3522 "#;
3523
3524 let expr = Expr::from_text(expr).unwrap();
3525
3526 let compiler = RibCompiler::default();
3527 let compiled = compiler.compile(expr).unwrap();
3528
3529 let mut interpreter = Interpreter::default();
3530 let result = interpreter.run(compiled.byte_code).await.unwrap();
3531
3532 let expected = ValueAndType::new(Value::U8(10), u8());
3533
3534 assert_eq!(result.get_val().unwrap(), expected);
3535 }
3536
3537 #[test]
3538 async fn test_interpreter_ephemeral_worker_0() {
3539 let expr = r#"
3540 let x = instance();
3541 let result = x.pass-through(1, 2);
3542 result
3543 "#;
3544 let expr = Expr::from_text(expr).unwrap();
3545
3546 let test_deps = RibTestDeps::test_deps_for_pass_through_function();
3547
3548 let compiler_config =
3549 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3550 let compiler = RibCompiler::new(compiler_config);
3551 let compiled = compiler.compile(expr).unwrap();
3552
3553 let mut rib_interpreter = test_deps.interpreter;
3554
3555 let result = rib_interpreter
3556 .run(compiled.byte_code)
3557 .await
3558 .unwrap()
3559 .get_val()
3560 .unwrap()
3561 .value;
3562
3563 let expected_value = Value::Record(vec![
3564 Value::String("test-worker".to_string()),
3565 Value::String("pass-through".to_string()),
3566 Value::U64(1),
3567 Value::U32(2),
3568 ]);
3569
3570 assert_eq!(result, expected_value)
3571 }
3572
3573 #[test]
3574 async fn test_interpreter_ephemeral_worker_1() {
3575 let expr = r#"
3576 let x = instance();
3577 x
3578 "#;
3579 let expr = Expr::from_text(expr).unwrap();
3580
3581 let test_deps = RibTestDeps::test_deps_with_global_functions();
3582
3583 let compiler = RibCompiler::new(RibCompilerConfig::new(
3584 test_deps.component_dependencies.clone(),
3585 vec![],
3586 vec![],
3587 ));
3588
3589 let compiled = compiler.compile(expr);
3590
3591 assert!(compiled.is_ok());
3592 }
3593
3594 #[test]
3595 async fn test_interpreter_ephemeral_worker_2() {
3596 let expr = r#"
3597 instance
3598 "#;
3599 let expr = Expr::from_text(expr).unwrap();
3600
3601 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3602
3603 let compiler = RibCompiler::new(RibCompilerConfig::new(
3604 test_deps.component_dependencies.clone(),
3605 vec![],
3606 vec![],
3607 ));
3608
3609 let compiled = compiler.compile(expr);
3610
3611 assert!(compiled.is_err());
3612 }
3613
3614 #[test]
3615 async fn test_interpreter_ephemeral_worker_3() {
3616 let expr = r#"
3617 instance()
3618 "#;
3619 let expr = Expr::from_text(expr).unwrap();
3620
3621 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3622
3623 let compiler = RibCompiler::new(RibCompilerConfig::new(
3624 test_deps.component_dependencies.clone(),
3625 vec![],
3626 vec![],
3627 ));
3628
3629 let compiled = compiler.compile(expr);
3630
3631 assert!(compiled.is_ok());
3632 }
3633
3634 #[test]
3635 async fn test_interpreter_ephemeral_worker_4() {
3636 let expr = r#"
3637 let worker = instance().foo("bar")
3638 "#;
3639 let expr = Expr::from_text(expr).unwrap();
3640
3641 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3642
3643 let compiler_config =
3644 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3645 let compiler = RibCompiler::new(compiler_config);
3646 let error = compiler.compile(expr).unwrap_err();
3647
3648 assert_eq!(
3649 error.to_string(),
3650 "inline invocation of functions on a worker instance is currently not supported"
3651 );
3652 }
3653
3654 #[test]
3655 async fn test_interpreter_ephemeral_worker_5() {
3656 let expr = r#"
3657 let result = instance.foo("bar");
3658 result
3659 "#;
3660 let expr = Expr::from_text(expr).unwrap();
3661 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3662
3663 let compiler = RibCompiler::new(RibCompilerConfig::new(
3664 test_deps.component_dependencies.clone(),
3665 vec![],
3666 vec![],
3667 ));
3668
3669 let compiled = compiler.compile(expr).unwrap_err().to_string();
3670
3671 assert_eq!(compiled, "error in the following rib found at line 2, column 28\n`instance`\ncause: `instance` is a reserved keyword\nhelp: use `instance()` instead of `instance` to create an ephemeral worker instance.\nhelp: for a durable worker, use `instance(\"foo\")` where `\"foo\"` is the worker name\n".to_string());
3672 }
3673
3674 #[test]
3675 async fn test_interpreter_ephemeral_worker_6() {
3676 let expr = r#"
3677 let x = instance();
3678 let result = x.bar("bar");
3679 result
3680 "#;
3681 let expr = Expr::from_text(expr).unwrap();
3682 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3683
3684 let compiler = RibCompiler::new(RibCompilerConfig::new(
3685 test_deps.component_dependencies.clone(),
3686 vec![],
3687 vec![],
3688 ));
3689
3690 let compilation_error = compiler.compile(expr).unwrap_err().to_string();
3691
3692 assert_eq!(
3693 compilation_error,
3694 "error in the following rib found at line 3, column 30\n`x.bar(\"bar\")`\ncause: invalid function call `bar`\nmultiple interfaces contain function 'bar'. specify an interface name as type parameter from: api1, api2\n".to_string()
3695 );
3696 }
3697
3698 #[test]
3699 async fn test_interpreter_ephemeral_worker_7() {
3700 let expr = r#"
3701 let worker = instance();
3702 let invokes: list<u8> = [1, 2, 3, 4];
3703
3704 for i in invokes {
3705 yield worker.qux[wasi:clocks]("bar");
3706 };
3707
3708 "success"
3709 "#;
3710 let expr = Expr::from_text(expr).unwrap();
3711 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3712
3713 let compiler_config =
3714 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3715 let compiler = RibCompiler::new(compiler_config);
3716 let compiled = compiler.compile(expr).unwrap();
3717
3718 let mut rib_interpreter = test_deps.interpreter;
3719
3720 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3721
3722 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3723 }
3724
3725 #[test]
3727 async fn test_interpreter_durable_worker_0() {
3728 let expr = r#"
3729 let worker = instance("my-worker");
3730 let result = worker.pass-through(42, 43);
3731 result
3732 "#;
3733 let expr = Expr::from_text(expr).unwrap();
3734 let test_deps = RibTestDeps::test_deps_for_pass_through_function();
3735
3736 let compiler_config =
3737 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3738 let compiler = RibCompiler::new(compiler_config);
3739 let compiled = compiler.compile(expr).unwrap();
3740
3741 let mut rib_interpreter = test_deps.interpreter;
3742
3743 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3744
3745 let expected_val = Value::Record(vec![
3746 Value::String("my-worker".to_string()),
3747 Value::String("pass-through".to_string()),
3748 Value::U64(42),
3749 Value::U32(43),
3750 ]);
3751
3752 assert_eq!(result.get_val().unwrap().value, expected_val);
3753 }
3754
3755 #[test]
3756 async fn test_interpreter_durable_worker_1_1() {
3757 let expr = r#"
3758 let x = 1;
3759 let y = 2;
3760 let inst = instance("my-worker");
3761 inst.foo-number(x, y)
3762 "#;
3763 let expr = Expr::from_text(expr).unwrap();
3764 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3765
3766 let compiler_config =
3767 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3768 let compiler = RibCompiler::new(compiler_config);
3769 let compiled = compiler.compile(expr).unwrap();
3770
3771 let mut rib_interpreter = test_deps.interpreter;
3772
3773 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3774
3775 assert_eq!(result.get_val().unwrap().value, Value::S32(1));
3776 }
3777
3778 #[test]
3779 async fn test_interpreter_durable_worker_2() {
3780 let expr = r#"
3781 let inst = instance("my-worker");
3782 let result = inst.foo("bar");
3783 result
3784 "#;
3785 let expr = Expr::from_text(expr).unwrap();
3786 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3787
3788 let compiler_config =
3789 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3790 let compiler = RibCompiler::new(compiler_config);
3791 let compiled = compiler.compile(expr).unwrap();
3792
3793 let mut rib_interpreter = test_deps.interpreter;
3794
3795 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3796
3797 assert_eq!(
3798 result.get_val().unwrap().value,
3799 Value::String("foo".to_string())
3800 );
3801 }
3802
3803 #[test]
3804 async fn test_interpreter_durable_worker_3() {
3805 let expr = r#"
3806 let my_worker = instance("my-worker");
3807 let result = my_worker.foo[api1]("bar");
3808 result
3809 "#;
3810 let expr = Expr::from_text(expr).unwrap();
3811 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3812
3813 let compiler_config =
3814 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3815 let compiler = RibCompiler::new(compiler_config);
3816 let compiled = compiler.compile(expr).unwrap();
3817
3818 let mut rib_interpreter = test_deps.interpreter;
3819
3820 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3821
3822 assert_eq!(
3823 result.get_val().unwrap().value,
3824 Value::String("foo".to_string())
3825 );
3826 }
3827
3828 #[test]
3829 async fn test_interpreter_durable_worker_4() {
3830 let expr = r#"
3831 let worker = instance("my-worker");
3832 let result = worker.bar("bar");
3833 result
3834 "#;
3835 let expr = Expr::from_text(expr).unwrap();
3836
3837 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3838
3839 let compiler = RibCompiler::new(RibCompilerConfig::new(
3840 test_deps.component_dependencies,
3841 vec![],
3842 vec![],
3843 ));
3844
3845 let compilation_error = compiler.compile(expr).unwrap_err().to_string();
3846
3847 assert_eq!(
3848 compilation_error,
3849 "error in the following rib found at line 3, column 30\n`worker.bar(\"bar\")`\ncause: invalid function call `bar`\nmultiple interfaces contain function 'bar'. specify an interface name as type parameter from: api1, api2\n".to_string()
3850 );
3851 }
3852
3853 #[test]
3854 async fn test_interpreter_durable_worker_5() {
3855 let expr = r#"
3856 let worker = instance("my-worker");
3857 let result = worker.bar[api1]("bar");
3858 result
3859 "#;
3860 let expr = Expr::from_text(expr).unwrap();
3861 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3862
3863 let compiler_config =
3864 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3865 let compiler = RibCompiler::new(compiler_config);
3866 let compiled = compiler.compile(expr).unwrap();
3867
3868 let mut rib_interpreter = test_deps.interpreter;
3869
3870 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3871
3872 assert_eq!(
3873 result.get_val().unwrap().value,
3874 Value::String("api1-bar".to_string())
3875 );
3876 }
3877
3878 #[test]
3879 async fn test_interpreter_durable_worker_6() {
3880 let expr = r#"
3881 let worker = instance("my-worker");
3882 let result = worker.bar[api2]("bar");
3883 result
3884 "#;
3885 let expr = Expr::from_text(expr).unwrap();
3886 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3887
3888 let compiler_config =
3889 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3890 let compiler = RibCompiler::new(compiler_config);
3891 let compiled = compiler.compile(expr).unwrap();
3892
3893 let mut rib_interpreter = test_deps.interpreter;
3894
3895 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3896
3897 assert_eq!(
3898 result.get_val().unwrap().value,
3899 Value::String("api2-bar".to_string())
3900 );
3901 }
3902
3903 #[test]
3904 async fn test_interpreter_durable_worker_7() {
3905 let expr = r#"
3906 let worker = instance("my-worker");
3907 let result = worker.baz("bar");
3908 result
3909 "#;
3910 let expr = Expr::from_text(expr).unwrap();
3911 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3912
3913 let compiler_config =
3914 RibCompilerConfig::new(test_deps.component_dependencies, vec![], vec![]);
3915 let compiler = RibCompiler::new(compiler_config);
3916 let compiled = compiler.compile(expr).unwrap();
3917
3918 let mut rib_interpreter = test_deps.interpreter;
3919
3920 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3921
3922 assert_eq!(
3923 result.get_val().unwrap().value,
3924 Value::String("clock-baz".to_string())
3925 );
3926 }
3927
3928 #[test]
3929 async fn test_interpreter_durable_worker_8() {
3930 let expr = r#"
3931 let worker = instance("my-worker");
3932 let result = worker.qux("bar");
3933 result
3934 "#;
3935 let expr = Expr::from_text(expr).unwrap();
3936 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3937
3938 let compiler = RibCompiler::new(RibCompilerConfig::new(
3939 test_deps.component_dependencies.clone(),
3940 vec![],
3941 vec![],
3942 ));
3943
3944 let compiled = compiler.compile(expr).unwrap_err().to_string();
3945
3946 assert_eq!(
3947 compiled,
3948 "error in the following rib found at line 3, column 30\n`worker.qux(\"bar\")`\ncause: invalid function call `qux`\nfunction 'qux' exists in multiple packages. specify a package name as type parameter from: amazon:shopping-cart (interfaces: api1), wasi:clocks (interfaces: monotonic-clock)\n".to_string()
3949 );
3950 }
3951
3952 #[test]
3953 async fn test_interpreter_durable_worker_9() {
3954 let expr = r#"
3955 let worker = instance("my-worker");
3956 let result = worker.qux[amazon:shopping-cart]("bar");
3957 result
3958 "#;
3959 let expr = Expr::from_text(expr).unwrap();
3960 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3961
3962 let compiler_config =
3963 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3964 let compiler = RibCompiler::new(compiler_config);
3965 let compiled = compiler.compile(expr).unwrap();
3966
3967 let mut rib_interpreter = test_deps.interpreter;
3968
3969 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3970
3971 assert_eq!(
3972 result.get_val().unwrap().value,
3973 Value::String("qux".to_string())
3974 );
3975 }
3976
3977 #[test]
3978 async fn test_interpreter_durable_worker_10() {
3979 let expr = r#"
3980 let worker = instance("my-worker");
3981 let result = worker.qux[wasi:clocks]("bar");
3982 result
3983 "#;
3984 let expr = Expr::from_text(expr).unwrap();
3985 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
3986
3987 let compiler_config =
3988 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
3989 let compiler = RibCompiler::new(compiler_config);
3990 let compiled = compiler.compile(expr).unwrap();
3991
3992 let mut rib_interpreter = test_deps.interpreter;
3993
3994 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3995
3996 assert_eq!(
3997 result.get_val().unwrap().value,
3998 Value::String("clock-qux".to_string())
3999 );
4000 }
4001
4002 #[test]
4003 async fn test_interpreter_durable_worker_11() {
4004 let expr = r#"
4005 let worker = instance("my-worker");
4006 let invokes: list<u8> = [1, 2, 3, 4];
4007
4008 for i in invokes {
4009 yield worker.qux[wasi:clocks]("bar");
4010 };
4011
4012 "success"
4013 "#;
4014 let expr = Expr::from_text(expr).unwrap();
4015 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4016
4017 let compiler_config =
4018 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4019 let compiler = RibCompiler::new(compiler_config);
4020 let compiled = compiler.compile(expr).unwrap();
4021
4022 let mut rib_interpreter = test_deps.interpreter;
4023
4024 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4025
4026 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4027 }
4028
4029 #[test]
4030 async fn test_interpreter_durable_worker_12() {
4031 let expr = r#"
4032 let worker = instance("my-worker");
4033 for i in [1, 2, 3] {
4034 worker.foo("${i}");
4035 yield i;
4036 }
4037 "#;
4038 let expr = Expr::from_text(expr).unwrap();
4039 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4040
4041 let compiler_config =
4042 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4043 let compiler = RibCompiler::new(compiler_config);
4044 let compiled = compiler.compile(expr).unwrap();
4045
4046 let mut rib_interpreter = test_deps.interpreter;
4047
4048 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4049
4050 assert_eq!(
4051 result.get_val().unwrap().value,
4052 Value::List(vec![Value::S32(1), Value::S32(2), Value::S32(3)])
4053 );
4054 }
4055
4056 #[test]
4057 async fn test_interpreter_durable_worker_with_resource_0() {
4058 let expr = r#"
4059 let worker = instance("my-worker");
4060 worker.cart[golem:it]("bar")
4061 "#;
4062 let expr = Expr::from_text(expr).unwrap();
4063 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4064
4065 let compiler = RibCompiler::new(RibCompilerConfig::new(
4066 test_deps.component_dependencies.clone(),
4067 vec![],
4068 vec![],
4069 ));
4070
4071 let compiled = compiler.compile(expr);
4072
4073 assert!(compiled.is_ok());
4074 }
4075
4076 #[test]
4079 async fn test_interpreter_durable_worker_with_resource_1() {
4080 let expr = r#"
4081 let worker = instance("my-worker");
4082 worker.cart[golem:it]("bar");
4083 "success"
4084 "#;
4085 let expr = Expr::from_text(expr).unwrap();
4086 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4087
4088 let compiler_config =
4089 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4090 let compiler = RibCompiler::new(compiler_config);
4091 let compiled = compiler.compile(expr).unwrap();
4092
4093 let mut rib_interpreter = test_deps.interpreter;
4094
4095 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4096
4097 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4098 }
4099
4100 #[test]
4101 async fn test_interpreter_durable_worker_with_resource_2() {
4102 let expr = r#"
4103 let worker = instance("my-worker");
4104 let cart = worker.cart[golem:it]("bar");
4105 let result = cart.add-item({product-id: "mac", name: "macbook", price: 1:f32, quantity: 1:u32});
4106 result
4107 "#;
4108 let expr = Expr::from_text(expr).unwrap();
4109 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4110
4111 let compiler_config =
4112 RibCompilerConfig::new(test_deps.component_dependencies, vec![], vec![]);
4113 let compiler = RibCompiler::new(compiler_config);
4114 let compiled = compiler.compile(expr).unwrap();
4115
4116 let mut rib_interpreter = test_deps.interpreter;
4117
4118 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4119
4120 assert_eq!(result, RibResult::Unit);
4121 }
4122
4123 #[test]
4124 async fn test_interpreter_durable_worker_with_resource_3() {
4125 let expr = r#"
4126 let worker = instance("my-worker");
4127 let cart = worker.cart[golem:it]("bar");
4128 cart.add-items({product-id: "mac", name: "macbook", price: 1:f32, quantity: 1:u32});
4129 "success"
4130 "#;
4131 let expr = Expr::from_text(expr).unwrap();
4132 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4133
4134 let compiler = RibCompiler::new(RibCompilerConfig::new(
4135 test_deps.component_dependencies.clone(),
4136 vec![],
4137 vec![],
4138 ));
4139
4140 let compiled = compiler.compile(expr).unwrap_err().to_string();
4141
4142 assert_eq!(compiled, "error in the following rib found at line 4, column 17\n`cart.add-items({product-id: \"mac\", name: \"macbook\", price: 1: f32, quantity: 1: u32})`\ncause: invalid function call `add-items`\nfunction 'add-items' not found\n".to_string());
4143 }
4144
4145 #[test]
4146 async fn test_interpreter_durable_worker_with_resource_4() {
4147 let expr = r#"
4148 let worker = instance("my-worker");
4149 let cart = worker.carts[golem:it]("bar");
4150 cart.add-item({product-id: "mac", name: "macbook", price: 1:f32, quantity: 1:u32});
4151 "success"
4152 "#;
4153 let expr = Expr::from_text(expr).unwrap();
4154 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4155
4156 let compiler = RibCompiler::new(RibCompilerConfig::new(
4157 test_deps.component_dependencies.clone(),
4158 vec![],
4159 vec![],
4160 ));
4161
4162 let compiled = compiler.compile(expr).unwrap_err().to_string();
4163
4164 assert_eq!(
4165 compiled,
4166 "error in the following rib found at line 3, column 28\n`worker.carts[golem:it](\"bar\")`\ncause: invalid function call `carts`\nfunction 'carts' not found in package 'golem:it'\n".to_string()
4167 );
4168 }
4169
4170 #[test]
4171 async fn test_interpreter_durable_worker_with_resource_5() {
4172 let expr = r#"
4174 let worker = instance();
4175 let cart = worker.cart[golem:it]("bar");
4176 cart.add-item({product-id: "mac", name: "macbook", price: 1, quantity: 1});
4177 "success"
4178 "#;
4179 let expr = Expr::from_text(expr).unwrap();
4180 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4181
4182 let compiler_config =
4183 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4184 let compiler = RibCompiler::new(compiler_config);
4185 let compiled = compiler.compile(expr).unwrap();
4186
4187 let mut rib_interpreter = test_deps.interpreter;
4188
4189 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4190
4191 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4192 }
4193
4194 #[test]
4195 async fn test_interpreter_durable_worker_with_resource_6() {
4196 let expr = r#"
4198 let worker = instance();
4199 let cart = worker.cart[golem:it]("bar");
4200 cart.add-item({product-id: "mac", name: 1, quantity: 1, price: 1});
4201 "success"
4202 "#;
4203 let expr = Expr::from_text(expr).unwrap();
4204
4205 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4206
4207 let compiler = RibCompiler::new(RibCompilerConfig::new(
4208 test_deps.component_dependencies.clone(),
4209 vec![],
4210 vec![],
4211 ));
4212
4213 let error_message = compiler.compile(expr).unwrap_err().to_string();
4214
4215 let expected = r#"
4216 error in the following rib found at line 4, column 57
4217 `1`
4218 cause: type mismatch. expected string, found s32
4219 the expression `1` is inferred as `s32` by default
4220 "#;
4221
4222 assert_eq!(error_message, strip_spaces(expected));
4223 }
4224
4225 #[test]
4226 async fn test_interpreter_durable_worker_with_resource_7() {
4227 let expr = r#"
4228 let worker = instance("my-worker");
4229 let cart = worker.cart("bar");
4230 cart.add-item({product-id: "mac", name: "apple", price: 1, quantity: 1});
4231 "success"
4232 "#;
4233 let expr = Expr::from_text(expr).unwrap();
4234 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4235
4236 let compiler_config =
4237 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4238 let compiler = RibCompiler::new(compiler_config);
4239 let compiled = compiler.compile(expr).unwrap();
4240
4241 let mut rib_interpreter = test_deps.interpreter;
4242
4243 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4244
4245 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4246 }
4247
4248 #[test]
4249 async fn test_interpreter_durable_worker_with_resource_8() {
4250 let expr = r#"
4251 let worker = instance("my-worker");
4252 let a = "mac";
4253 let b = "apple";
4254 let c = 1;
4255 let d = 1;
4256 let cart = worker.cart("bar");
4257 cart.add-item({product-id: a, name: b, quantity: c, price: d});
4258 "success"
4259 "#;
4260 let expr = Expr::from_text(expr).unwrap();
4261 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4262 let compiler_config =
4263 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4264 let compiler = RibCompiler::new(compiler_config);
4265 let compiled = compiler.compile(expr).unwrap();
4266
4267 let mut rib_interpreter = test_deps.interpreter;
4268
4269 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4270
4271 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4272 }
4273
4274 #[test]
4275 async fn test_interpreter_durable_worker_with_resource_9() {
4276 let expr = r#"
4277 let worker = instance("my-worker");
4278 let a = "mac";
4279 let b = "apple";
4280 let c = 1;
4281 let d = 1;
4282 let cart = worker.cart("bar");
4283 cart.add-item({product-id: a, name: b, quantity: c, price: d});
4284 cart.remove-item(a);
4285 cart.update-item-quantity(a, 2);
4286 let result = cart.get-cart-contents();
4287 cart.drop();
4288 result
4289 "#;
4290 let expr = Expr::from_text(expr).unwrap();
4291 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4292 let compiler_config =
4293 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4294 let compiler = RibCompiler::new(compiler_config);
4295 let compiled = compiler.compile(expr).unwrap();
4296
4297 let mut rib_interpreter = test_deps.interpreter;
4298
4299 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4300
4301 let expected_value = Value::List(vec![Value::Record(vec![
4302 Value::String("foo".to_string()),
4303 Value::String("bar".to_string()),
4304 Value::F32(10.0),
4305 Value::U32(2),
4306 ])]);
4307
4308 assert_eq!(result.get_val().unwrap().value, expected_value);
4309 }
4310
4311 #[test]
4312 async fn test_interpreter_durable_worker_with_resource_10() {
4313 let expr = r#"
4314 let my_worker = "my-worker";
4315 let worker = instance(my_worker);
4316 let a = "mac";
4317 let b = "apple";
4318 let c = 1;
4319 let d = 1;
4320 let cart = worker.cart("bar");
4321 cart.add-item({product-id: a, name: b, price: d, quantity: c});
4322 cart.remove-item(a);
4323 cart.update-item-quantity(a, 2);
4324 let result = cart.get-cart-contents();
4325 cart.drop();
4326 result
4327 "#;
4328 let expr = Expr::from_text(expr).unwrap();
4329 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(None);
4330
4331 let compiler_config =
4332 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4333 let compiler = RibCompiler::new(compiler_config);
4334 let compiled = compiler.compile(expr).unwrap();
4335
4336 let mut rib_interpreter = test_deps.interpreter;
4337
4338 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4339
4340 let expected_value = Value::List(vec![Value::Record(vec![
4341 Value::String("foo".to_string()),
4342 Value::String("bar".to_string()),
4343 Value::F32(10.0),
4344 Value::U32(2),
4345 ])]);
4346
4347 assert_eq!(result.get_val().unwrap().value, expected_value);
4348 }
4349
4350 #[test]
4351 async fn test_interpreter_durable_worker_with_resource_11() {
4352 let expr = r#"
4353 let worker = instance(request.path.user-id: string);
4354 let result = worker.qux[amazon:shopping-cart]("bar");
4355 result
4356 "#;
4357 let expr = Expr::from_text(expr).unwrap();
4358
4359 let mut input = HashMap::new();
4360
4361 let rib_input_key = "request";
4363 let rib_input_value = ValueAndType::new(
4364 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4365 record(vec![field("path", record(vec![field("user-id", str())]))]),
4366 );
4367
4368 input.insert(rib_input_key.to_string(), rib_input_value);
4369
4370 let rib_input = RibInput::new(input);
4371
4372 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(Some(rib_input));
4373
4374 let compiler_config =
4375 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4376 let compiler = RibCompiler::new(compiler_config);
4377 let compiled = compiler.compile(expr).unwrap();
4378
4379 let mut rib_interpreter = test_deps.interpreter;
4380
4381 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4382
4383 assert_eq!(
4384 result.get_val().unwrap().value,
4385 Value::String("qux".to_string())
4386 )
4387 }
4388
4389 #[test]
4390 async fn test_interpreter_durable_worker_with_resource_12() {
4391 let expr = r#"
4392 let user_id1: string = request.path.user-id;
4393 let user_id2: string = request.path.user-id;
4394 let worker1 = instance(user_id1);
4395 let result1 = worker1.qux[amazon:shopping-cart]("bar");
4396 let worker2 = instance(user_id2);
4397 let result2 = worker2.qux[amazon:shopping-cart]("bar");
4398 user_id2
4399 "#;
4400 let expr = Expr::from_text(expr).unwrap();
4401
4402 let mut input = HashMap::new();
4403
4404 let rib_input_key = "request";
4405
4406 let rib_input_value = ValueAndType::new(
4407 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4408 record(vec![field("path", record(vec![field("user-id", str())]))]),
4409 );
4410
4411 input.insert(rib_input_key.to_string(), rib_input_value);
4412
4413 let rib_input = RibInput::new(input);
4414
4415 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(Some(rib_input));
4416
4417 let compiler_config =
4418 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4419
4420 let compiler = RibCompiler::new(compiler_config);
4421
4422 let compiled = compiler.compile(expr).unwrap();
4423
4424 let mut rib_interpreter = test_deps.interpreter;
4425
4426 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4427
4428 assert_eq!(result.get_val().unwrap(), "user".into_value_and_type());
4429 }
4430
4431 #[test]
4432 async fn test_interpreter_durable_worker_with_resource_13() {
4433 let expr = r#"
4434 let worker1 = instance("foo");
4435 let result = worker.qux[amazon:shopping-cart]("bar");
4436 "success"
4437 "#;
4438 let expr = Expr::from_text(expr).unwrap();
4439
4440 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4441
4442 let compiler = RibCompiler::new(RibCompilerConfig::new(
4443 test_deps.component_dependencies.clone(),
4444 vec![],
4445 vec![],
4446 ));
4447
4448 let error = compiler.compile(expr).unwrap_err().to_string();
4449
4450 assert_eq!(error, "error in the following rib found at line 3, column 30\n`worker.qux[amazon:shopping-cart](\"bar\")`\ncause: invalid method invocation `worker.qux`. make sure `worker` is defined and is a valid instance type (i.e, resource or worker)\n");
4451 }
4452
4453 #[test]
4454 async fn test_interpreter_durable_worker_with_resource_14() {
4455 let expr = r#"
4456 let worker = instance(1: u32);
4457 let result = worker.qux[amazon:shopping-cart]("bar");
4458 "success"
4459 "#;
4460 let expr = Expr::from_text(expr).unwrap();
4461
4462 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4463
4464 let compiler = RibCompiler::new(RibCompilerConfig::new(
4465 test_deps.component_dependencies.clone(),
4466 vec![],
4467 vec![],
4468 ));
4469
4470 let error = compiler.compile(expr).unwrap_err().to_string();
4471
4472 let expected = r#"
4473 error in the following rib found at line 2, column 39
4474 `1: u32`
4475 cause: expected string, found u32
4476 "#;
4477
4478 assert_eq!(error, strip_spaces(expected));
4479 }
4480
4481 #[test]
4482 async fn test_interpreter_durable_worker_with_resource_15() {
4483 let expr = r#"
4484 let worker = instance("my-worker-name");
4485 let result = worker.qux[amazon:shopping-cart]("param1");
4486 result
4487 "#;
4488 let expr = Expr::from_text(expr).unwrap();
4489
4490 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces(None);
4491
4492 let compiler_config =
4493 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4494
4495 let compiler = RibCompiler::new(compiler_config);
4496
4497 let compiled = compiler.compile(expr).unwrap();
4498
4499 let mut rib_interpreter = test_deps.interpreter;
4500
4501 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4502
4503 let result_val = result.get_val().unwrap();
4504
4505 assert_eq!(result_val.value, Value::String("qux".to_string()));
4506 }
4507
4508 #[test]
4509 async fn test_interpreter_durable_worker_with_resource_16() {
4510 let expr = r#"
4511 let x: string = request.path.user-id;
4512 let worker = instance(x);
4513 let cart = worker.cart("bar");
4514 let result = cart.get-cart-contents();
4515 result
4516 "#;
4517
4518 let expr = Expr::from_text(expr).unwrap();
4519
4520 let mut input = HashMap::new();
4521
4522 let rib_input_key = "request";
4523
4524 let rib_input_value = ValueAndType::new(
4525 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4526 record(vec![field("path", record(vec![field("user-id", str())]))]),
4527 );
4528
4529 input.insert(rib_input_key.to_string(), rib_input_value);
4530
4531 let rib_input = RibInput::new(input);
4532
4533 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4534
4535 let compiler_config =
4536 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4537
4538 let compiler = RibCompiler::new(compiler_config);
4539
4540 let compiled = compiler.compile(expr).unwrap();
4541
4542 let mut rib_interpreter = test_deps.interpreter;
4543
4544 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4545
4546 let result_val = result.get_val().unwrap();
4547
4548 let expected_val = Value::List(vec![Value::Record(vec![
4549 Value::String("foo".to_string()),
4550 Value::String("bar".to_string()),
4551 Value::F32(10.0),
4552 Value::U32(2),
4553 ])]);
4554
4555 assert_eq!(result_val.value, expected_val)
4556 }
4557
4558 #[test]
4559 async fn test_interpreter_durable_worker_with_resource_17() {
4560 let expr = r#"
4561 let x: string = request.path.user-id;
4562 let min: u8 = 1;
4563 let max: u8 = 3;
4564 let result = for i in min..=max {
4565 let worker = instance("my-worker");
4566 let cart = worker.cart("bar");
4567 yield cart.get-cart-contents();
4568 };
4569 result
4570 "#;
4571 let expr = Expr::from_text(expr).unwrap();
4572
4573 let mut input = HashMap::new();
4574
4575 let rib_input_key = "request";
4576
4577 let rib_input_value = ValueAndType::new(
4578 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4579 record(vec![field("path", record(vec![field("user-id", str())]))]),
4580 );
4581
4582 input.insert(rib_input_key.to_string(), rib_input_value);
4583
4584 let rib_input = RibInput::new(input);
4585
4586 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4587
4588 let compiler_config =
4589 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4590
4591 let compiler = RibCompiler::new(compiler_config);
4592
4593 let compiled = compiler.compile(expr).unwrap();
4594
4595 let mut rib_interpreter = test_deps.interpreter;
4596
4597 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4598
4599 let result_val = result.get_val().unwrap().value;
4600
4601 let cart_contents = Value::List(vec![Value::Record(vec![
4602 Value::String("foo".to_string()),
4603 Value::String("bar".to_string()),
4604 Value::F32(10.0),
4605 Value::U32(2),
4606 ])]);
4607
4608 let expected_val = Value::List(vec![
4609 cart_contents.clone(),
4610 cart_contents.clone(),
4611 cart_contents,
4612 ]);
4613
4614 assert_eq!(result_val, expected_val);
4615 }
4616
4617 #[test]
4618 async fn test_interpreter_durable_worker_with_resource_18() {
4619 let expr = r#"
4620
4621 let initial = 1;
4622 let final = 5;
4623 let range = initial..final;
4624 let worker = instance("my-worker");
4625 let cart = worker.cart[golem:it]("bar");
4626
4627 for i in range {
4628 yield cart.add-item(request.body);
4629 };
4630
4631 "success"
4632 "#;
4633 let expr = Expr::from_text(expr).unwrap();
4634
4635 let mut input = HashMap::new();
4636
4637 let rib_input_key = "request";
4638
4639 let rib_input_value = ValueAndType::new(
4640 Value::Record(vec![Value::Record(vec![
4641 Value::String("mac-book".to_string()),
4642 Value::String("mac".to_string()),
4643 Value::U32(1),
4644 Value::F32(1.0),
4645 ])]),
4646 record(vec![field(
4647 "body",
4648 record(vec![
4649 field("name", str()),
4650 field("product-id", str()),
4651 field("quantity", u32()),
4652 field("price", f32()),
4653 ]),
4654 )]),
4655 );
4656
4657 input.insert(rib_input_key.to_string(), rib_input_value);
4658
4659 let rib_input = RibInput::new(input);
4660
4661 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4662
4663 let compiler_config =
4664 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4665
4666 let compiler = RibCompiler::new(compiler_config);
4667
4668 let compiled = compiler.compile(expr).unwrap();
4669
4670 let mut rib_interpreter = test_deps.interpreter;
4671
4672 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4673
4674 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4675 }
4676
4677 #[test]
4678 async fn test_interpreter_durable_worker_with_resource_19() {
4679 let expr = r#"
4680
4681 let initial = 1;
4682 let final = 5;
4683 let range = initial..final;
4684
4685 for i in range {
4686 let worker = instance("my-worker");
4687 let cart = worker.cart[golem:it]("bar");
4688 yield cart.add-item(request.body);
4689 };
4690
4691 "success"
4692 "#;
4693 let expr = Expr::from_text(expr).unwrap();
4694
4695 let mut input = HashMap::new();
4696
4697 let rib_input_key = "request";
4698
4699 let rib_input_value = ValueAndType::new(
4700 Value::Record(vec![Value::Record(vec![
4701 Value::String("mac-book".to_string()),
4702 Value::String("mac".to_string()),
4703 Value::U32(1),
4704 Value::F32(1.0),
4705 ])]),
4706 record(vec![field(
4707 "body",
4708 record(vec![
4709 field("name", str()),
4710 field("product-id", str()),
4711 field("quantity", u32()),
4712 field("price", f32()),
4713 ]),
4714 )]),
4715 );
4716
4717 input.insert(rib_input_key.to_string(), rib_input_value);
4718
4719 let rib_input = RibInput::new(input);
4720
4721 let test_deps = RibTestDeps::test_deps_with_indexed_resource_functions(Some(rib_input));
4722
4723 let compiler_config =
4724 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4725
4726 let compiler = RibCompiler::new(compiler_config);
4727
4728 let compiled = compiler.compile(expr).unwrap();
4729
4730 let mut rib_interpreter = test_deps.interpreter;
4731
4732 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4733
4734 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4735 }
4736
4737 #[test]
4738 async fn test_interpreter_custom_instance() {
4739 let expr = r#"
4740 let text = "nyc";
4741 let number = "usa";
4742 let boolean = true;
4743 let optional-str = some("optional");
4744 let optional-number = some(2);
4745 let list-of-str = ["a", "b", "c"];
4746 let tuple = (text, 1, boolean, optional-str);
4747 let record = {city: text, country: number};
4748 let result = ok(text);
4749 let result-ok = ok(text);
4750 let result-err = err(1);
4751 let variant = foo("bar");
4752 let weather-agent = weather-agent("text", 1, true, optional-str, optional-number, none, none, list-of-str, tuple, record, result, result-ok, result-err, variant);
4753 let first-result = weather-agent.get-weather("bar");
4754 let assistant-agent = assistant-agent("my assistant");
4755 let second-result = assistant-agent.ask("foo", "bar");
4756 {weather: first-result, assistant: second-result}
4757 "#;
4758
4759 let weather_agent_constructor_param_types: Vec<AnalysedType> = vec![
4760 str(),
4761 s32(),
4762 bool(),
4763 option(str()),
4764 option(u64()),
4765 option(str()),
4766 option(u64()),
4767 list(str()),
4768 tuple(vec![str(), s32(), bool(), option(str())]),
4769 record(vec![field("city", str()), field("country", str())]),
4770 result(str(), s32()),
4771 result_ok(str()),
4772 result_err(s32()),
4773 variant(vec![
4774 case("foo", str()),
4775 case("bar", s32()),
4776 unit_case("baz"),
4777 ]),
4778 ];
4779
4780 let custom_spec1 = CustomInstanceSpec {
4781 instance_name: "weather-agent".to_string(),
4782 parameter_types: weather_agent_constructor_param_types,
4783 interface_name: Some(InterfaceName {
4784 name: "weather-agent".to_string(),
4785 version: None,
4786 }),
4787 };
4788
4789 let custom_spec2 = CustomInstanceSpec {
4790 instance_name: "assistant-agent".to_string(),
4791 parameter_types: vec![str()],
4792 interface_name: Some(InterfaceName {
4793 name: "assistant-agent".to_string(),
4794 version: None,
4795 }),
4796 };
4797
4798 let expr = Expr::from_text(expr).unwrap();
4799 let test_deps = RibTestDeps::test_deps_with_multiple_interfaces_simple(None);
4800
4801 let compiler_config = RibCompilerConfig::new(
4802 test_deps.component_dependencies.clone(),
4803 vec![],
4804 vec![custom_spec1, custom_spec2],
4805 );
4806 let compiler = RibCompiler::new(compiler_config);
4807 let compiled = compiler
4808 .compile(expr)
4809 .map_err(|err| err.to_string())
4810 .unwrap();
4811
4812 let mut rib_interpreter = test_deps.interpreter;
4813
4814 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4815
4816 let expected = Value::Record(vec![
4817 Value::Record(vec![
4818 Value::String(
4820 "weather-agent(\"text\",1,true,some(\"optional\"),some(2),none,none,[\"a\", \"b\", \"c\"],(\"nyc\", 1, true, some(\"optional\")),{city: \"nyc\", country: \"usa\"},ok(\"nyc\"),ok(\"nyc\"),err(1),foo(\"bar\"))".to_string(),
4821 ),
4822 Value::String("my:agent/weather-agent.{get-weather}".to_string()),
4824 Value::String("\"bar\"".to_string()),
4826 ]),
4827 Value::Record(vec![
4828 Value::String("assistant-agent(\"my assistant\")".to_string()),
4830 Value::String("my:agent/assistant-agent.{ask}".to_string()),
4832 Value::String("\"foo\"\"bar\"".to_string()),
4834 ]),
4835 ]);
4836
4837 assert_eq!(result.get_val().unwrap().value, expected);
4838 }
4839
4840 #[test]
4841 async fn test_interpreter_custom_instance_conflicting_variants() {
4842 let expr = r#"
4843 let x = instance("abc");
4844 let r1 = x.func1(foo("bar"));
4845 let r2 = x.func2(foo(["baz", "qux"]));
4846 {result1: r1, result2: r2}
4847 "#;
4848
4849 let expr = Expr::from_text(expr).unwrap();
4850 let test_deps = RibTestDeps::test_deps_with_variant_conflicts(None);
4851
4852 let compiler_config =
4853 RibCompilerConfig::new(test_deps.component_dependencies.clone(), vec![], vec![]);
4854 let compiler = RibCompiler::new(compiler_config);
4855 let compiled = compiler
4856 .compile(expr)
4857 .map_err(|err| err.to_string())
4858 .unwrap();
4859
4860 let mut rib_interpreter = test_deps.interpreter;
4861
4862 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4863
4864 let expected = Value::Record(vec![
4865 Value::Variant {
4866 case_idx: 0,
4867 case_value: Some(Box::new(Value::String("bar".to_string()))),
4868 },
4869 Value::Variant {
4870 case_idx: 0,
4871 case_value: Some(Box::new(Value::List(vec![
4872 Value::String("baz".to_string()),
4873 Value::String("qux".to_string()),
4874 ]))),
4875 },
4876 ]);
4877 assert_eq!(result.get_val().unwrap().value, expected);
4878 }
4879
4880 mod test_utils {
4881 use crate::interpreter::rib_interpreter::internal::NoopRibFunctionInvoke;
4882 use crate::interpreter::rib_interpreter::Interpreter;
4883 use crate::{
4884 ComponentDependency, ComponentDependencyKey, DefaultWorkerNameGenerator,
4885 EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, GenerateWorkerName,
4886 GetLiteralValue, InstructionId, RibComponentFunctionInvoke, RibFunctionInvokeResult,
4887 RibInput,
4888 };
4889 use async_trait::async_trait;
4890 use golem_wasm_ast::analysis::analysed_type::{
4891 case, f32, field, handle, list, option, r#enum, record, result, s32, str, tuple, u32,
4892 u64, unit_case, variant,
4893 };
4894 use golem_wasm_ast::analysis::{
4895 AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedFunctionResult,
4896 AnalysedInstance, AnalysedResourceId, AnalysedResourceMode, AnalysedType, TypeHandle,
4897 };
4898 use golem_wasm_rpc::{print_value_and_type, IntoValueAndType, Value, ValueAndType};
4899 use std::sync::Arc;
4900 use uuid::Uuid;
4901
4902 pub(crate) fn strip_spaces(input: &str) -> String {
4903 let lines = input.lines();
4904
4905 let first_line = lines
4906 .clone()
4907 .find(|line| !line.trim().is_empty())
4908 .unwrap_or("");
4909 let margin_width = first_line.chars().take_while(|c| c.is_whitespace()).count();
4910
4911 let result = lines
4912 .map(|line| {
4913 if line.trim().is_empty() {
4914 String::new()
4915 } else {
4916 line[margin_width..].to_string()
4917 }
4918 })
4919 .collect::<Vec<String>>()
4920 .join("\n");
4921
4922 result.strip_prefix("\n").unwrap_or(&result).to_string()
4923 }
4924
4925 pub(crate) fn get_analysed_type_variant() -> AnalysedType {
4926 variant(vec![
4927 case("register-user", u64()),
4928 case("process-user", str()),
4929 unit_case("validate"),
4930 ])
4931 }
4932
4933 pub(crate) fn get_analysed_type_record() -> AnalysedType {
4934 record(vec![
4935 field(
4936 "request",
4937 record(vec![field("path", record(vec![field("user", str())]))]),
4938 ),
4939 field("y", str()),
4940 ])
4941 }
4942
4943 pub(crate) fn get_analysed_type_result() -> AnalysedType {
4944 result(u64(), str())
4945 }
4946
4947 pub(crate) fn get_analysed_type_enum() -> AnalysedType {
4948 r#enum(&["prod", "dev", "test"])
4949 }
4950
4951 pub(crate) fn get_analysed_typ_str() -> AnalysedType {
4952 str()
4953 }
4954
4955 pub(crate) fn get_analysed_typ_u64() -> AnalysedType {
4956 u64()
4957 }
4958
4959 pub(crate) fn get_analysed_type_tuple() -> AnalysedType {
4960 tuple(vec![
4961 get_analysed_typ_u64(),
4962 get_analysed_type_result(),
4963 get_analysed_typ_str(),
4964 get_analysed_type_record(),
4965 get_analysed_type_variant(),
4966 get_analysed_type_variant(),
4967 get_analysed_type_variant(),
4968 get_analysed_type_enum(),
4969 get_analysed_type_enum(),
4970 get_analysed_type_enum(),
4971 ])
4972 }
4973
4974 pub(crate) fn configurable_metadata(
4975 function_name: &str,
4976 input_types: Vec<AnalysedType>,
4977 output: Option<AnalysedType>,
4978 ) -> Vec<ComponentDependency> {
4979 let analysed_function_parameters = input_types
4980 .into_iter()
4981 .enumerate()
4982 .map(|(index, typ)| AnalysedFunctionParameter {
4983 name: format!("param{index}"),
4984 typ,
4985 })
4986 .collect();
4987
4988 let result = output.map(|typ| AnalysedFunctionResult { typ });
4989
4990 let component_info = ComponentDependencyKey {
4991 component_name: "foo".to_string(),
4992 component_id: Uuid::new_v4(),
4993 component_version: 0,
4994 root_package_name: None,
4995 root_package_version: None,
4996 };
4997
4998 vec![ComponentDependency::new(
4999 component_info,
5000 vec![AnalysedExport::Function(AnalysedFunction {
5001 name: function_name.to_string(),
5002 parameters: analysed_function_parameters,
5003 result,
5004 })],
5005 )]
5006 }
5007
5008 pub(crate) fn get_metadata_with_resource_with_params() -> Vec<ComponentDependency> {
5009 get_metadata_with_resource(vec![AnalysedFunctionParameter {
5010 name: "user-id".to_string(),
5011 typ: str(),
5012 }])
5013 }
5014
5015 pub(crate) fn get_metadata_with_resource_without_params() -> Vec<ComponentDependency> {
5016 get_metadata_with_resource(vec![])
5017 }
5018
5019 pub(crate) fn get_metadata_simple_with_variant_conflicts() -> Vec<ComponentDependency> {
5020 let func1 = AnalysedFunction {
5021 name: "func1".to_string(),
5022 parameters: vec![AnalysedFunctionParameter {
5023 name: "arg1".to_string(),
5024 typ: variant(vec![case("foo", str())]),
5025 }],
5026 result: Some(AnalysedFunctionResult { typ: str() }),
5027 };
5028
5029 let func2 = AnalysedFunction {
5030 name: "func2".to_string(),
5031 parameters: vec![AnalysedFunctionParameter {
5032 name: "arg1".to_string(),
5033 typ: variant(vec![
5034 case("foo", list(str())), ]),
5036 }],
5037 result: Some(AnalysedFunctionResult { typ: str() }),
5038 };
5039
5040 let component_info = ComponentDependencyKey {
5041 component_name: "foo".to_string(),
5042 component_id: Uuid::new_v4(),
5043 component_version: 0,
5044 root_package_name: None,
5045 root_package_version: None,
5046 };
5047
5048 vec![ComponentDependency::new(
5049 component_info,
5050 vec![
5051 AnalysedExport::Function(func1),
5052 AnalysedExport::Function(func2),
5053 ],
5054 )]
5055 }
5056
5057 pub(crate) fn get_metadata_with_multiple_interfaces_simple() -> Vec<ComponentDependency> {
5058 let get_weather = AnalysedFunction {
5060 name: "get-weather".to_string(),
5061 parameters: vec![AnalysedFunctionParameter {
5062 name: "arg1".to_string(),
5063 typ: str(),
5064 }],
5065 result: Some(AnalysedFunctionResult { typ: str() }),
5066 };
5067
5068 let ask = AnalysedFunction {
5069 name: "ask".to_string(),
5070 parameters: vec![
5071 AnalysedFunctionParameter {
5072 name: "arg1".to_string(),
5073 typ: str(),
5074 },
5075 AnalysedFunctionParameter {
5076 name: "arg2".to_string(),
5077 typ: str(),
5078 },
5079 ],
5080 result: Some(AnalysedFunctionResult { typ: s32() }),
5081 };
5082
5083 let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
5084 name: "my:agent/weather-agent".to_string(),
5085 functions: vec![get_weather],
5086 });
5087
5088 let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
5089 name: "my:agent/assistant-agent".to_string(),
5090 functions: vec![ask],
5091 });
5092
5093 let analysed_export3 = AnalysedExport::Function(AnalysedFunction {
5094 name: "variant-param".to_string(),
5095 parameters: vec![AnalysedFunctionParameter {
5096 name: "arg1".to_string(),
5097 typ: variant(vec![case("foo", str()), case("bar", s32())]),
5098 }],
5099 result: Some(AnalysedFunctionResult { typ: str() }),
5100 });
5101
5102 let component_info = ComponentDependencyKey {
5103 component_name: "foo".to_string(),
5104 component_id: Uuid::new_v4(),
5105 component_version: 0,
5106 root_package_name: None,
5107 root_package_version: None,
5108 };
5109
5110 vec![ComponentDependency::new(
5111 component_info,
5112 vec![analysed_export1, analysed_export2, analysed_export3],
5113 )]
5114 }
5115
5116 pub(crate) fn get_metadata_with_multiple_interfaces() -> Vec<ComponentDependency> {
5117 let analysed_function_in_api1 = AnalysedFunction {
5119 name: "foo".to_string(),
5120 parameters: vec![AnalysedFunctionParameter {
5121 name: "arg1".to_string(),
5122 typ: str(),
5123 }],
5124 result: Some(AnalysedFunctionResult { typ: str() }),
5125 };
5126
5127 let analysed_function_in_api1_number = AnalysedFunction {
5128 name: "foo-number".to_string(),
5129 parameters: vec![
5130 AnalysedFunctionParameter {
5131 name: "arg1".to_string(),
5132 typ: u64(),
5133 },
5134 AnalysedFunctionParameter {
5135 name: "arg2".to_string(),
5136 typ: s32(),
5137 },
5138 ],
5139 result: Some(AnalysedFunctionResult { typ: s32() }),
5140 };
5141
5142 let analysed_function_in_api1_and_api2 = AnalysedFunction {
5144 name: "bar".to_string(),
5145 parameters: vec![AnalysedFunctionParameter {
5146 name: "arg1".to_string(),
5147 typ: str(),
5148 }],
5149 result: Some(AnalysedFunctionResult { typ: str() }),
5150 };
5151
5152 let analysed_function_in_wasi = AnalysedFunction {
5154 name: "baz".to_string(),
5155 parameters: vec![AnalysedFunctionParameter {
5156 name: "arg1".to_string(),
5157 typ: str(),
5158 }],
5159 result: Some(AnalysedFunctionResult { typ: str() }),
5160 };
5161
5162 let analysed_function_in_wasi_and_api1 = AnalysedFunction {
5164 name: "qux".to_string(),
5165 parameters: vec![AnalysedFunctionParameter {
5166 name: "arg1".to_string(),
5167 typ: str(),
5168 }],
5169 result: Some(AnalysedFunctionResult { typ: str() }),
5170 };
5171
5172 let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
5173 name: "amazon:shopping-cart/api1".to_string(),
5174 functions: vec![
5175 analysed_function_in_api1,
5176 analysed_function_in_api1_number,
5177 analysed_function_in_api1_and_api2.clone(),
5178 analysed_function_in_wasi_and_api1.clone(),
5179 ],
5180 });
5181
5182 let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
5183 name: "amazon:shopping-cart/api2".to_string(),
5184 functions: vec![analysed_function_in_api1_and_api2],
5185 });
5186
5187 let analysed_export3 = AnalysedExport::Instance(AnalysedInstance {
5188 name: "wasi:clocks/monotonic-clock".to_string(),
5189 functions: vec![
5190 analysed_function_in_wasi,
5191 analysed_function_in_wasi_and_api1,
5192 ],
5193 });
5194
5195 let component_info = ComponentDependencyKey {
5196 component_name: "foo".to_string(),
5197 component_id: Uuid::new_v4(),
5198 component_version: 0,
5199 root_package_name: None,
5200 root_package_version: None,
5201 };
5202
5203 vec![ComponentDependency::new(
5204 component_info,
5205 vec![analysed_export1, analysed_export2, analysed_export3],
5206 )]
5207 }
5208
5209 fn get_metadata_with_resource(
5210 resource_constructor_params: Vec<AnalysedFunctionParameter>,
5211 ) -> Vec<ComponentDependency> {
5212 let instance = AnalysedExport::Instance(AnalysedInstance {
5213 name: "golem:it/api".to_string(),
5214 functions: vec![
5215 AnalysedFunction {
5216 name: "[constructor]cart".to_string(),
5217 parameters: resource_constructor_params,
5218 result: Some(AnalysedFunctionResult {
5219 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5220 }),
5221 },
5222 AnalysedFunction {
5223 name: "[static]cart.create".to_string(),
5224 parameters: vec![AnalysedFunctionParameter {
5225 name: "item-name".to_string(),
5226 typ: str(),
5227 }],
5228 result: Some(AnalysedFunctionResult {
5229 typ: AnalysedType::Handle(TypeHandle {
5230 name: Some("cart".to_string()),
5231 owner: Some("golem:it/api".to_string()),
5232 resource_id: AnalysedResourceId(0),
5233 mode: AnalysedResourceMode::Owned,
5234 }),
5235 }),
5236 },
5237 AnalysedFunction {
5238 name: "[static]cart.create-safe".to_string(),
5239 parameters: vec![AnalysedFunctionParameter {
5240 name: "item-name".to_string(),
5241 typ: str(),
5242 }],
5243 result: Some(AnalysedFunctionResult {
5244 typ: result(
5245 AnalysedType::Handle(TypeHandle {
5246 name: Some("cart".to_string()),
5247 owner: Some("golem:it/api".to_string()),
5248 resource_id: AnalysedResourceId(0),
5249 mode: AnalysedResourceMode::Owned,
5250 }),
5251 str(),
5252 ),
5253 }),
5254 },
5255 AnalysedFunction {
5256 name: "[method]cart.add-item".to_string(),
5257 parameters: vec![
5258 AnalysedFunctionParameter {
5259 name: "self".to_string(),
5260 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5261 },
5262 AnalysedFunctionParameter {
5263 name: "item".to_string(),
5264 typ: record(vec![
5265 field("product-id", str()),
5266 field("name", str()),
5267 field("price", f32()),
5268 field("quantity", u32()),
5269 ]),
5270 },
5271 ],
5272 result: None,
5273 },
5274 AnalysedFunction {
5275 name: "[method]cart.remove-item".to_string(),
5276 parameters: vec![
5277 AnalysedFunctionParameter {
5278 name: "self".to_string(),
5279 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5280 },
5281 AnalysedFunctionParameter {
5282 name: "product-id".to_string(),
5283 typ: str(),
5284 },
5285 ],
5286 result: None,
5287 },
5288 AnalysedFunction {
5289 name: "[method]cart.update-item-quantity".to_string(),
5290 parameters: vec![
5291 AnalysedFunctionParameter {
5292 name: "self".to_string(),
5293 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5294 },
5295 AnalysedFunctionParameter {
5296 name: "product-id".to_string(),
5297 typ: str(),
5298 },
5299 AnalysedFunctionParameter {
5300 name: "quantity".to_string(),
5301 typ: u32(),
5302 },
5303 ],
5304 result: None,
5305 },
5306 AnalysedFunction {
5307 name: "[method]cart.checkout".to_string(),
5308 parameters: vec![AnalysedFunctionParameter {
5309 name: "self".to_string(),
5310 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5311 }],
5312 result: Some(AnalysedFunctionResult {
5313 typ: variant(vec![
5314 case("error", str()),
5315 case("success", record(vec![field("order-id", str())])),
5316 ]),
5317 }),
5318 },
5319 AnalysedFunction {
5320 name: "[method]cart.get-cart-contents".to_string(),
5321 parameters: vec![AnalysedFunctionParameter {
5322 name: "self".to_string(),
5323 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5324 }],
5325 result: Some(AnalysedFunctionResult {
5326 typ: list(record(vec![
5327 field("product-id", str()),
5328 field("name", str()),
5329 field("price", f32()),
5330 field("quantity", u32()),
5331 ])),
5332 }),
5333 },
5334 AnalysedFunction {
5335 name: "[method]cart.merge-with".to_string(),
5336 parameters: vec![
5337 AnalysedFunctionParameter {
5338 name: "self".to_string(),
5339 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5340 },
5341 AnalysedFunctionParameter {
5342 name: "other-cart".to_string(),
5343 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
5344 },
5345 ],
5346 result: None,
5347 },
5348 AnalysedFunction {
5349 name: "[drop]cart".to_string(),
5350 parameters: vec![AnalysedFunctionParameter {
5351 name: "self".to_string(),
5352 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5353 }],
5354 result: None,
5355 },
5356 ],
5357 });
5358
5359 let component_info = ComponentDependencyKey {
5360 component_name: "foo".to_string(),
5361 component_id: Uuid::new_v4(),
5362 component_version: 0,
5363 root_package_name: None,
5364 root_package_version: None,
5365 };
5366
5367 vec![ComponentDependency::new(component_info, vec![instance])]
5368 }
5369
5370 pub(crate) fn get_value_and_type(
5371 analysed_type: &AnalysedType,
5372 wasm_wave_str: &str,
5373 ) -> ValueAndType {
5374 golem_wasm_rpc::parse_value_and_type(analysed_type, wasm_wave_str).unwrap()
5375 }
5376
5377 pub(crate) fn interpreter_with_noop_function_invoke(
5378 input: Option<RibInput>,
5379 ) -> Interpreter {
5380 let invoke: Arc<dyn RibComponentFunctionInvoke + Send + Sync> =
5381 Arc::new(NoopRibFunctionInvoke);
5382
5383 Interpreter {
5384 input: input.unwrap_or_default(),
5385 invoke,
5386 generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5387 }
5388 }
5389
5390 pub(crate) fn interpreter_with_static_function_response(
5392 result_value: &ValueAndType,
5393 input: Option<RibInput>,
5394 ) -> Interpreter {
5395 let value = result_value.clone();
5396
5397 let invoke = Arc::new(TestInvoke1 { value });
5398
5399 Interpreter {
5400 input: input.unwrap_or_default(),
5401 invoke,
5402 generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5403 }
5404 }
5405
5406 pub(crate) fn interpreter_with_resource_function_invoke_impl(
5412 rib_input: Option<RibInput>,
5413 ) -> Interpreter {
5414 let invoke: Arc<dyn RibComponentFunctionInvoke + Send + Sync> =
5415 Arc::new(ResourceFunctionsInvoke);
5416
5417 Interpreter {
5418 input: rib_input.unwrap_or_default(),
5419 invoke,
5420 generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5421 }
5422 }
5423
5424 pub(crate) fn interpreter_for_global_functions(input: Option<RibInput>) -> Interpreter {
5426 let invoke = Arc::new(TestInvoke3);
5427
5428 Interpreter {
5429 input: input.unwrap_or_default(),
5430 invoke,
5431 generate_worker_name: Arc::new(DefaultWorkerNameGenerator),
5432 }
5433 }
5434
5435 struct TestInvoke1 {
5436 value: ValueAndType,
5437 }
5438
5439 #[async_trait]
5440 impl RibComponentFunctionInvoke for TestInvoke1 {
5441 async fn invoke(
5442 &self,
5443 _component_dependency_key: ComponentDependencyKey,
5444 _instruction_id: &InstructionId,
5445 _worker_name: EvaluatedWorkerName,
5446 _fqn: EvaluatedFqFn,
5447 _args: EvaluatedFnArgs,
5448 _return_type: Option<AnalysedType>,
5449 ) -> RibFunctionInvokeResult {
5450 let value = self.value.clone();
5451 Ok(Some(value))
5452 }
5453 }
5454
5455 struct PassThroughFunctionInvoke;
5456
5457 #[async_trait]
5458 impl RibComponentFunctionInvoke for PassThroughFunctionInvoke {
5459 async fn invoke(
5460 &self,
5461 _component_dependency_key: ComponentDependencyKey,
5462 _instruction_id: &InstructionId,
5463 worker_name: EvaluatedWorkerName,
5464 function_name: EvaluatedFqFn,
5465 args: EvaluatedFnArgs,
5466 _return_type: Option<AnalysedType>,
5467 ) -> RibFunctionInvokeResult {
5468 let analysed_type = record(vec![
5469 field("worker-name", str()),
5470 field("function-name", str()),
5471 field("args0", u64()),
5472 field("args1", u32()),
5473 ]);
5474
5475 let worker_name = Value::String(worker_name.0);
5476 let function_name = Value::String(function_name.0);
5477 let args0 = args.0[0].value.clone();
5478 let args1 = args.0[1].value.clone();
5479
5480 let value = Value::Record(vec![worker_name, function_name, args0, args1]);
5481
5482 Ok(Some(ValueAndType::new(value, analysed_type)))
5483 }
5484 }
5485
5486 struct ResourceFunctionsInvoke;
5487
5488 #[async_trait]
5489 impl RibComponentFunctionInvoke for ResourceFunctionsInvoke {
5490 async fn invoke(
5491 &self,
5492 _component_dependency_key: ComponentDependencyKey,
5493 _instruction_id: &InstructionId,
5494 worker_name: EvaluatedWorkerName,
5495 function_name: EvaluatedFqFn,
5496 args: EvaluatedFnArgs,
5497 _return_type: Option<AnalysedType>,
5498 ) -> RibFunctionInvokeResult {
5499 match function_name.0.as_str() {
5500 "golem:it/api.{cart.new}" => {
5501 let worker_name = worker_name.0;
5502
5503 let uri = format!(
5504 "urn:worker:99738bab-a3bf-4a12-8830-b6fd783d1ef2/{worker_name}"
5505 );
5506 Ok(ValueAndType::new(
5507 Value::Handle {
5508 uri,
5509 resource_id: 0,
5510 },
5511 handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5512 )
5513 .into())
5514 }
5515
5516 "golem:it/api.{cart.checkout}" => {
5517 let result_type = variant(vec![
5518 case("error", str()),
5519 case("success", record(vec![field("order-id", str())])),
5520 ]);
5521
5522 let result_value = get_value_and_type(
5523 &result_type,
5524 r#"
5525 success({order-id: "foo"})
5526 "#,
5527 );
5528
5529 Ok(Some(result_value))
5530 }
5531
5532 "golem:it/api.{cart.add-item}" => Ok(None),
5533
5534 "golem:it/api.{cart.update-item-quantity}" => Ok(None),
5535
5536 "golem:it/api.{cart.remove-item}" => Ok(None),
5537
5538 "golem:it/api.{cart.drop}" => Ok(None),
5539
5540 "golem:it/api.{cart.get-cart-contents}" => {
5541 let typ = list(record(vec![
5542 field("product-id", str()),
5543 field("name", str()),
5544 field("price", f32()),
5545 field("quantity", u32()),
5546 ]));
5547
5548 let value = Value::Record(vec![
5549 Value::String("foo".to_string()),
5550 Value::String("bar".to_string()),
5551 Value::F32(10.0),
5552 Value::U32(2),
5553 ]);
5554
5555 Ok(Some(ValueAndType::new(Value::List(vec![value]), typ)))
5556 }
5557
5558 "golem:it/api.{[static]cart.create}" => {
5559 let uri = format!(
5560 "urn:worker:99738bab-a3bf-4a12-8830-b6fd783d1ef2/{}",
5561 worker_name.0
5562 );
5563
5564 let value = Value::Handle {
5565 uri,
5566 resource_id: 0,
5567 };
5568
5569 Ok(Some(ValueAndType::new(
5570 value,
5571 handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5572 )))
5573 }
5574
5575 "golem:it/api.{[static]cart.create-safe}" => {
5576 let uri = format!(
5577 "urn:worker:99738bab-a3bf-4a12-8830-b6fd783d1ef2/{}",
5578 worker_name.0
5579 );
5580
5581 let resource = Value::Handle {
5582 uri,
5583 resource_id: 0,
5584 };
5585
5586 let value = Value::Result(Ok(Some(Box::new(resource))));
5587
5588 Ok(Some(ValueAndType::new(
5589 value,
5590 result(
5591 handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
5592 str(),
5593 ),
5594 )))
5595 }
5596
5597 "golem:it/api.{cart.pass-through}" => {
5598 let worker_name = worker_name.0;
5599 let function_args = args.0[1..].to_vec();
5600
5601 let mut arg_types = vec![];
5602
5603 for (index, value_and_type) in function_args.iter().enumerate() {
5604 let name = format!("args{index}");
5605 let value = value_and_type.typ.clone();
5606 arg_types.push(field(name.as_str(), value));
5607 }
5608
5609 let function_name = function_name.0.into_value_and_type();
5610
5611 let mut analysed_type_pairs = vec![];
5612 analysed_type_pairs.push(field("worker-name", str()));
5613 analysed_type_pairs.push(field("function-name", str()));
5614 analysed_type_pairs.extend(arg_types);
5615
5616 let mut values = vec![];
5617
5618 values.push(Value::String(worker_name));
5619 values.push(function_name.value);
5620
5621 for arg_value in function_args {
5622 values.push(arg_value.value);
5623 }
5624
5625 let value_and_type =
5626 ValueAndType::new(Value::Record(values), record(analysed_type_pairs));
5627
5628 Ok(Some(value_and_type))
5629 }
5630
5631 _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5632 }
5633 }
5634 }
5635
5636 struct SimpleVariantConflictInvoke;
5637
5638 #[async_trait]
5639 impl RibComponentFunctionInvoke for SimpleVariantConflictInvoke {
5640 async fn invoke(
5641 &self,
5642 _component_dependency_key: ComponentDependencyKey,
5643 _instruction_id: &InstructionId,
5644 _worker_name: EvaluatedWorkerName,
5645 function_name: EvaluatedFqFn,
5646 args: EvaluatedFnArgs,
5647 _return_type: Option<AnalysedType>,
5648 ) -> RibFunctionInvokeResult {
5649 let arg = args.0.first().unwrap();
5650
5651 match function_name.0.as_str() {
5652 "func1" | "func2" => Ok(Some(arg.clone())),
5653 _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5654 }
5655 }
5656 }
5657
5658 struct CustomInstanceFunctionInvoke;
5659 #[async_trait]
5660 impl RibComponentFunctionInvoke for CustomInstanceFunctionInvoke {
5661 async fn invoke(
5662 &self,
5663 _component_dependency_key: ComponentDependencyKey,
5664 _instruction_id: &InstructionId,
5665 worker_name: EvaluatedWorkerName,
5666 function_name: EvaluatedFqFn,
5667 args: EvaluatedFnArgs,
5668 _return_type: Option<AnalysedType>,
5669 ) -> RibFunctionInvokeResult {
5670 let mut arguments_concatenated = String::new();
5671
5672 for arg in args.0 {
5673 let arg_str = print_value_and_type(&arg)?;
5674 arguments_concatenated.push_str(arg_str.as_str());
5675 }
5676
5677 let result_value = ValueAndType::new(
5678 Value::Record(vec![
5679 Value::String(worker_name.0),
5680 Value::String(function_name.0.clone()),
5681 Value::String(arguments_concatenated),
5682 ]),
5683 record(vec![
5684 field("worker-name", str()),
5685 field("function-name", str()),
5686 field("args", str()),
5687 ]),
5688 );
5689
5690 match function_name.0.as_str() {
5691 "my:agent/weather-agent.{get-weather}" => Ok(Some(result_value)),
5692
5693 "my:agent/assistant-agent.{ask}" => Ok(Some(result_value)),
5694
5695 _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5696 }
5697 }
5698 }
5699
5700 struct MultiplePackageFunctionInvoke;
5701
5702 #[async_trait]
5703 impl RibComponentFunctionInvoke for MultiplePackageFunctionInvoke {
5704 async fn invoke(
5705 &self,
5706 _component_dependency_key: ComponentDependencyKey,
5707 _instruction_id: &InstructionId,
5708 _worker_name: EvaluatedWorkerName,
5709 function_name: EvaluatedFqFn,
5710 _args: EvaluatedFnArgs,
5711 _return_type: Option<AnalysedType>,
5712 ) -> RibFunctionInvokeResult {
5713 match function_name.0.as_str() {
5714 "amazon:shopping-cart/api1.{foo}" => {
5715 let result_value =
5716 ValueAndType::new(Value::String("foo".to_string()), str());
5717
5718 Ok(Some(result_value))
5719 }
5720
5721 "amazon:shopping-cart/api1.{foo-number}" => {
5722 let result_value = ValueAndType::new(Value::S32(1), s32());
5723
5724 Ok(Some(result_value))
5725 }
5726
5727 "amazon:shopping-cart/api1.{bar}" => {
5728 let result_value =
5729 ValueAndType::new(Value::String("api1-bar".to_string()), str());
5730
5731 Ok(Some(result_value))
5732 }
5733
5734 "amazon:shopping-cart/api1.{qux}" => {
5735 let result_value =
5736 ValueAndType::new(Value::String("qux".to_string()), str());
5737
5738 Ok(Some(result_value))
5739 }
5740
5741 "amazon:shopping-cart/api2.{bar}" => {
5742 let result_value =
5743 ValueAndType::new(Value::String("api2-bar".to_string()), str());
5744
5745 Ok(Some(result_value))
5746 }
5747
5748 "wasi:clocks/monotonic-clock.{baz}" => {
5749 let result_value =
5750 ValueAndType::new(Value::String("clock-baz".to_string()), str());
5751
5752 Ok(Some(result_value))
5753 }
5754
5755 "wasi:clocks/monotonic-clock.{qux}" => {
5756 let result_value =
5757 ValueAndType::new(Value::String("clock-qux".to_string()), str());
5758
5759 Ok(Some(result_value))
5760 }
5761
5762 _ => Err(format!("unexpected function name: {}", function_name.0).into()),
5763 }
5764 }
5765 }
5766
5767 pub(crate) struct StaticWorkerNameGenerator;
5768
5769 impl GenerateWorkerName for StaticWorkerNameGenerator {
5770 fn generate_worker_name(&self) -> String {
5771 "test-worker".to_string()
5772 }
5773 }
5774
5775 pub(crate) struct RibTestDeps {
5776 pub(crate) component_dependencies: Vec<ComponentDependency>,
5777 pub(crate) interpreter: Interpreter,
5778 }
5779
5780 impl RibTestDeps {
5781 pub(crate) fn test_deps_with_global_functions() -> RibTestDeps {
5782 let component_dependencies = get_component_dependency_with_global_functions();
5783 let interpreter = interpreter_for_global_functions(None);
5784
5785 RibTestDeps {
5786 component_dependencies,
5787 interpreter,
5788 }
5789 }
5790
5791 pub(crate) fn test_deps_with_resource_functions(
5792 rib_input: Option<RibInput>,
5793 ) -> RibTestDeps {
5794 let component_dependencies = get_metadata_with_resource_without_params();
5795 let interpreter = interpreter_with_resource_function_invoke_impl(rib_input);
5796
5797 RibTestDeps {
5798 component_dependencies,
5799 interpreter,
5800 }
5801 }
5802
5803 pub(crate) fn test_deps_with_indexed_resource_functions(
5804 rib_input: Option<RibInput>,
5805 ) -> RibTestDeps {
5806 let component_dependencies = get_metadata_with_resource_with_params();
5807 let interpreter = interpreter_with_resource_function_invoke_impl(rib_input);
5808
5809 RibTestDeps {
5810 component_dependencies,
5811 interpreter,
5812 }
5813 }
5814
5815 pub(crate) fn test_deps_for_pass_through_function() -> RibTestDeps {
5819 let exports = vec![AnalysedExport::Function(AnalysedFunction {
5820 name: "pass-through".to_string(),
5821 parameters: vec![
5822 AnalysedFunctionParameter {
5823 name: "item".to_string(),
5824 typ: u64(),
5825 },
5826 AnalysedFunctionParameter {
5827 name: "item".to_string(),
5828 typ: u32(),
5829 },
5830 ],
5831 result: Some(AnalysedFunctionResult {
5832 typ: record(vec![
5833 field("worker-name", option(str())),
5834 field("function-name", str()),
5835 field("args0", u64()),
5836 field("args1", u32()),
5837 ]),
5838 }),
5839 })];
5840
5841 let component_info = ComponentDependencyKey {
5842 component_name: "foo".to_string(),
5843 component_id: Uuid::new_v4(),
5844 component_version: 0,
5845 root_package_name: None,
5846 root_package_version: None,
5847 };
5848
5849 let exports = vec![ComponentDependency::new(component_info, exports)];
5850
5851 let interpreter = Interpreter::new(
5852 RibInput::default(),
5853 Arc::new(PassThroughFunctionInvoke),
5854 Arc::new(StaticWorkerNameGenerator),
5855 );
5856
5857 RibTestDeps {
5858 component_dependencies: exports,
5859 interpreter,
5860 }
5861 }
5862
5863 pub(crate) fn test_deps_with_multiple_interfaces_simple(
5864 rib_input: Option<RibInput>,
5865 ) -> RibTestDeps {
5866 let component_dependencies = get_metadata_with_multiple_interfaces_simple();
5867 let interpreter = Interpreter::new(
5868 rib_input.unwrap_or_default(),
5869 Arc::new(CustomInstanceFunctionInvoke),
5870 Arc::new(StaticWorkerNameGenerator),
5871 );
5872
5873 RibTestDeps {
5874 component_dependencies,
5875 interpreter,
5876 }
5877 }
5878
5879 pub(crate) fn test_deps_with_variant_conflicts(
5880 rib_input: Option<RibInput>,
5881 ) -> RibTestDeps {
5882 let component_dependencies = get_metadata_simple_with_variant_conflicts();
5883 let interpreter = Interpreter::new(
5884 rib_input.unwrap_or_default(),
5885 Arc::new(SimpleVariantConflictInvoke),
5886 Arc::new(StaticWorkerNameGenerator),
5887 );
5888
5889 RibTestDeps {
5890 component_dependencies,
5891 interpreter,
5892 }
5893 }
5894
5895 pub(crate) fn test_deps_with_multiple_interfaces(
5896 rib_input: Option<RibInput>,
5897 ) -> RibTestDeps {
5898 let component_dependencies = get_metadata_with_multiple_interfaces();
5899 let interpreter = Interpreter::new(
5900 rib_input.unwrap_or_default(),
5901 Arc::new(MultiplePackageFunctionInvoke),
5902 Arc::new(StaticWorkerNameGenerator),
5903 );
5904
5905 RibTestDeps {
5906 component_dependencies,
5907 interpreter,
5908 }
5909 }
5910 }
5911
5912 fn get_component_dependency_with_global_functions() -> Vec<ComponentDependency> {
5913 let exports = vec![
5914 AnalysedExport::Function(AnalysedFunction {
5915 name: "add-u32".to_string(),
5916 parameters: vec![
5917 AnalysedFunctionParameter {
5918 name: "param1".to_string(),
5919 typ: u32(),
5920 },
5921 AnalysedFunctionParameter {
5922 name: "param2".to_string(),
5923 typ: u32(),
5924 },
5925 ],
5926 result: Some(AnalysedFunctionResult { typ: u32() }),
5927 }),
5928 AnalysedExport::Function(AnalysedFunction {
5929 name: "add-u64".to_string(),
5930 parameters: vec![
5931 AnalysedFunctionParameter {
5932 name: "param1".to_string(),
5933 typ: u64(),
5934 },
5935 AnalysedFunctionParameter {
5936 name: "param2".to_string(),
5937 typ: u64(),
5938 },
5939 ],
5940 result: Some(AnalysedFunctionResult { typ: u64() }),
5941 }),
5942 AnalysedExport::Function(AnalysedFunction {
5943 name: "add-enum".to_string(),
5944 parameters: vec![
5945 AnalysedFunctionParameter {
5946 name: "param1".to_string(),
5947 typ: r#enum(&["x", "y", "z"]),
5948 },
5949 AnalysedFunctionParameter {
5950 name: "param2".to_string(),
5951 typ: r#enum(&["x", "y", "z"]),
5952 },
5953 ],
5954 result: Some(AnalysedFunctionResult {
5955 typ: r#enum(&["x", "y", "z"]),
5956 }),
5957 }),
5958 AnalysedExport::Function(AnalysedFunction {
5959 name: "add-variant".to_string(),
5960 parameters: vec![
5961 AnalysedFunctionParameter {
5962 name: "param1".to_string(),
5963 typ: get_analysed_type_variant(),
5964 },
5965 AnalysedFunctionParameter {
5966 name: "param2".to_string(),
5967 typ: get_analysed_type_variant(),
5968 },
5969 ],
5970 result: Some(AnalysedFunctionResult {
5971 typ: get_analysed_type_variant(),
5972 }),
5973 }),
5974 ];
5975
5976 let component_info = ComponentDependencyKey {
5977 component_name: "foo".to_string(),
5978 component_id: Uuid::new_v4(),
5979 component_version: 0,
5980 root_package_name: None,
5981 root_package_version: None,
5982 };
5983
5984 vec![ComponentDependency::new(component_info, exports)]
5985 }
5986
5987 struct TestInvoke3;
5988
5989 #[async_trait]
5990 impl RibComponentFunctionInvoke for TestInvoke3 {
5991 async fn invoke(
5992 &self,
5993 _component_dependency: ComponentDependencyKey,
5994 _instruction_id: &InstructionId,
5995 _worker_name: EvaluatedWorkerName,
5996 function_name: EvaluatedFqFn,
5997 args: EvaluatedFnArgs,
5998 _return_type: Option<AnalysedType>,
5999 ) -> RibFunctionInvokeResult {
6000 match function_name.0.as_str() {
6001 "add-u32" => {
6002 let args = args.0;
6003 let arg1 = args[0].get_literal().and_then(|x| x.get_number()).unwrap();
6004 let arg2 = args[1].get_literal().and_then(|x| x.get_number()).unwrap();
6005 let result = (arg1 + arg2).unwrap();
6006 let u32 = result.cast_to(&u32()).unwrap();
6007
6008 Ok(Some(u32))
6009 }
6010 "add-u64" => {
6011 let args = args.0;
6012 let arg1 = args[0].get_literal().and_then(|x| x.get_number()).unwrap();
6013 let arg2 = args[1].get_literal().and_then(|x| x.get_number()).unwrap();
6014 let result = (arg1 + arg2).unwrap();
6015 let u64 = result.cast_to(&u64()).unwrap();
6016 Ok(Some(u64))
6017 }
6018 "add-enum" => {
6019 let args = args.0;
6020 let arg1 = args[0].clone().value;
6021 let arg2 = args[1].clone().value;
6022 match (arg1, arg2) {
6023 (Value::Enum(x), Value::Enum(y)) => {
6024 if x == y {
6025 let result =
6026 ValueAndType::new(Value::Enum(x), r#enum(&["x", "y", "z"]));
6027 Ok(Some(result))
6028 } else {
6029 Err(format!("Enums are not equal: {x} and {y}").into())
6030 }
6031 }
6032 (v1, v2) => {
6033 Err(format!("Invalid arguments for add-enum: {v1:?} and {v2:?}")
6034 .into())
6035 }
6036 }
6037 }
6038 "add-variant" => {
6039 let args = args.0;
6040 let arg1 = args[0].clone().value;
6041 let arg2 = args[1].clone().value;
6042 match (arg1, arg2) {
6043 (
6044 Value::Variant {
6045 case_idx: case_idx1,
6046 case_value,
6047 },
6048 Value::Variant {
6049 case_idx: case_idx2,
6050 ..
6051 },
6052 ) => {
6053 if case_idx1 == case_idx2 {
6054 let result = ValueAndType::new(
6055 Value::Variant {
6056 case_idx: case_idx1,
6057 case_value,
6058 },
6059 get_analysed_type_variant(),
6060 );
6061 Ok(Some(result))
6062 } else {
6063 Err(format!(
6064 "Variants are not equal: {case_idx1} and {case_idx2}"
6065 )
6066 .into())
6067 }
6068 }
6069 (v1, v2) => Err(format!(
6070 "Invalid arguments for add-variant: {v1:?} and {v2:?}"
6071 )
6072 .into()),
6073 }
6074 }
6075 fun => Err(format!("unknown function {fun}").into()),
6076 }
6077 }
6078 }
6079 }
6080}