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