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_value_and_type, strip_spaces,
1426 };
1427 use crate::{
1428 compiler, Expr, FunctionTypeRegistry, GlobalVariableTypeSpec, InferredType, InstructionId,
1429 Path, VariableId,
1430 };
1431 use golem_wasm_ast::analysis::analysed_type::{
1432 bool, case, f32, field, list, option, record, s32, s8, str, tuple, u32, u64, u8, variant,
1433 };
1434 use golem_wasm_rpc::{parse_value_and_type, IntoValue, IntoValueAndType, Value, ValueAndType};
1435
1436 #[test]
1437 async fn test_interpreter_for_literal() {
1438 let mut interpreter = Interpreter::default();
1439
1440 let instructions = RibByteCode {
1441 instructions: vec![RibIR::PushLit(1i32.into_value_and_type())],
1442 };
1443
1444 let result = interpreter.run(instructions).await.unwrap();
1445 assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1446 }
1447
1448 #[test]
1449 async fn test_interpreter_for_equal_to() {
1450 let mut interpreter = Interpreter::default();
1451
1452 let instructions = RibByteCode {
1453 instructions: vec![
1454 RibIR::PushLit(1i32.into_value_and_type()),
1455 RibIR::PushLit(1u32.into_value_and_type()),
1456 RibIR::EqualTo,
1457 ],
1458 };
1459
1460 let result = interpreter.run(instructions).await.unwrap();
1461 assert!(result.get_bool().unwrap());
1462 }
1463
1464 #[test]
1465 async fn test_interpreter_for_greater_than() {
1466 let mut interpreter = Interpreter::default();
1467
1468 let instructions = RibByteCode {
1469 instructions: vec![
1470 RibIR::PushLit(1i32.into_value_and_type()),
1471 RibIR::PushLit(2u32.into_value_and_type()),
1472 RibIR::GreaterThan,
1473 ],
1474 };
1475
1476 let result = interpreter.run(instructions).await.unwrap();
1477 assert!(result.get_bool().unwrap());
1478 }
1479
1480 #[test]
1481 async fn test_interpreter_for_less_than() {
1482 let mut interpreter = Interpreter::default();
1483
1484 let instructions = RibByteCode {
1485 instructions: vec![
1486 RibIR::PushLit(2i32.into_value_and_type()),
1487 RibIR::PushLit(1u32.into_value_and_type()),
1488 RibIR::LessThan,
1489 ],
1490 };
1491
1492 let result = interpreter.run(instructions).await.unwrap();
1493 assert!(result.get_bool().unwrap());
1494 }
1495
1496 #[test]
1497 async fn test_interpreter_for_greater_than_or_equal_to() {
1498 let mut interpreter = Interpreter::default();
1499
1500 let instructions = RibByteCode {
1501 instructions: vec![
1502 RibIR::PushLit(2i32.into_value_and_type()),
1503 RibIR::PushLit(3u32.into_value_and_type()),
1504 RibIR::GreaterThanOrEqualTo,
1505 ],
1506 };
1507
1508 let result = interpreter.run(instructions).await.unwrap();
1509 assert!(result.get_bool().unwrap());
1510 }
1511
1512 #[test]
1513 async fn test_interpreter_for_less_than_or_equal_to() {
1514 let mut interpreter = Interpreter::default();
1515
1516 let instructions = RibByteCode {
1517 instructions: vec![
1518 RibIR::PushLit(2i32.into_value_and_type()), RibIR::PushLit(1i32.into_value_and_type()), RibIR::LessThanOrEqualTo,
1521 ],
1522 };
1523
1524 let result = interpreter.run(instructions).await.unwrap();
1525 assert!(result.get_bool().unwrap());
1526 }
1527
1528 #[test]
1529 async fn test_interpreter_for_assign_and_load_var() {
1530 let mut interpreter = Interpreter::default();
1531
1532 let instructions = RibByteCode {
1533 instructions: vec![
1534 RibIR::PushLit(1i32.into_value_and_type()),
1535 RibIR::AssignVar(VariableId::local_with_no_id("x")),
1536 RibIR::LoadVar(VariableId::local_with_no_id("x")),
1537 ],
1538 };
1539
1540 let result = interpreter.run(instructions).await.unwrap();
1541 assert_eq!(result.get_val().unwrap(), 1i32.into_value_and_type());
1542 }
1543
1544 #[test]
1545 async fn test_interpreter_for_jump() {
1546 let mut interpreter = Interpreter::default();
1547
1548 let instructions = RibByteCode {
1549 instructions: vec![
1550 RibIR::Jump(InstructionId::init()),
1551 RibIR::PushLit(1i32.into_value_and_type()),
1552 RibIR::Label(InstructionId::init()),
1553 ],
1554 };
1555
1556 let result = interpreter.run(instructions).await;
1557 assert!(result.is_ok());
1558 }
1559
1560 #[test]
1561 async fn test_interpreter_for_jump_if_false() {
1562 let mut interpreter = Interpreter::default();
1563
1564 let id = InstructionId::init().increment_mut();
1565
1566 let instructions = RibByteCode {
1567 instructions: vec![
1568 RibIR::PushLit(false.into_value_and_type()),
1569 RibIR::JumpIfFalse(id.clone()),
1570 RibIR::PushLit(1i32.into_value_and_type()),
1571 RibIR::Label(id),
1572 ],
1573 };
1574
1575 let result = interpreter.run(instructions).await;
1576 assert!(result.is_ok());
1577 }
1578
1579 #[test]
1580 async fn test_interpreter_for_record() {
1581 let mut interpreter = Interpreter::default();
1582
1583 let instructions = RibByteCode {
1584 instructions: vec![
1585 RibIR::PushLit(2i32.into_value_and_type()),
1586 RibIR::PushLit(1i32.into_value_and_type()),
1587 RibIR::CreateAndPushRecord(record(vec![field("x", s32()), field("y", s32())])),
1588 RibIR::UpdateRecord("x".to_string()),
1589 RibIR::UpdateRecord("y".to_string()),
1590 ],
1591 };
1592
1593 let result = interpreter.run(instructions).await.unwrap();
1594 let expected = ValueAndType::new(
1595 Value::Record(vec![1i32.into_value(), 2i32.into_value()]),
1596 record(vec![field("x", s32()), field("y", s32())]),
1597 );
1598
1599 assert_eq!(result.get_val().unwrap(), expected);
1600 }
1601
1602 #[test]
1603 async fn test_interpreter_for_sequence() {
1604 let mut interpreter = Interpreter::default();
1605
1606 let instructions = RibByteCode {
1607 instructions: vec![
1608 RibIR::PushLit(2i32.into_value_and_type()),
1609 RibIR::PushLit(1i32.into_value_and_type()),
1610 RibIR::PushList(list(s32()), 2),
1611 ],
1612 };
1613
1614 let result = interpreter.run(instructions).await.unwrap();
1615 let expected = ValueAndType::new(
1616 Value::List(vec![1i32.into_value(), 2i32.into_value()]),
1617 list(s32()),
1618 );
1619 assert_eq!(result.get_val().unwrap(), expected);
1620 }
1621
1622 #[test]
1623 async fn test_interpreter_for_select_field() {
1624 let mut interpreter = Interpreter::default();
1625
1626 let instructions = RibByteCode {
1627 instructions: vec![
1628 RibIR::PushLit(1i32.into_value_and_type()),
1629 RibIR::PushLit(2i32.into_value_and_type()),
1630 RibIR::CreateAndPushRecord(record(vec![field("x", s32())])),
1631 RibIR::UpdateRecord("x".to_string()),
1632 RibIR::SelectField("x".to_string()),
1633 ],
1634 };
1635
1636 let result = interpreter.run(instructions).await.unwrap();
1637 assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1638 }
1639
1640 #[test]
1641 async fn test_interpreter_for_select_index() {
1642 let mut interpreter = Interpreter::default();
1643
1644 let instructions = RibByteCode {
1645 instructions: vec![
1646 RibIR::PushLit(1i32.into_value_and_type()),
1647 RibIR::PushLit(2i32.into_value_and_type()),
1648 RibIR::PushList(list(s32()), 2),
1649 RibIR::SelectIndex(0),
1650 ],
1651 };
1652
1653 let result = interpreter.run(instructions).await.unwrap();
1654 assert_eq!(result.get_val().unwrap(), 2i32.into_value_and_type());
1655 }
1656
1657 #[test]
1658 async fn test_interpreter_variable_scope_0() {
1659 let rib_expr = r#"
1660 let x: u64 = 1;
1661 let y = x + 2u64;
1662 y
1663 "#;
1664
1665 let expr = Expr::from_text(rib_expr).unwrap();
1666
1667 let compiled = compiler::compile(expr, &vec![]).unwrap();
1668
1669 let mut interpreter = Interpreter::default();
1670
1671 let result = interpreter.run(compiled.byte_code).await.unwrap();
1672
1673 assert_eq!(result.get_val().unwrap(), 3u64.into_value_and_type());
1674 }
1675
1676 #[test]
1677 async fn test_interpreter_variable_scope_1() {
1678 let rib_expr = r#"
1679 let x: u64 = 1;
1680 let z = {foo : x};
1681 let x = x + 2u64;
1682 { bar: x, baz: z }
1683 "#;
1684
1685 let expr = Expr::from_text(rib_expr).unwrap();
1686
1687 let compiled = compiler::compile(expr, &vec![]).unwrap();
1688
1689 let mut interpreter = Interpreter::default();
1690
1691 let result = interpreter.run(compiled.byte_code).await.unwrap();
1692
1693 let analysed_type = record(vec![
1694 field("bar", u64()),
1695 field("baz", record(vec![field("foo", u64())])),
1696 ]);
1697
1698 let expected = get_value_and_type(&analysed_type, r#"{ bar: 3, baz: { foo: 1 } }"#);
1699
1700 assert_eq!(result.get_val().unwrap(), expected);
1701 }
1702
1703 #[test]
1704 async fn test_interpreter_variable_scope_2() {
1705 let rib_expr = r#"
1706 let x: u64 = 1;
1707 let x = x;
1708
1709 let result1 = match some(x + 1:u64) {
1710 some(x) => x,
1711 none => x
1712 };
1713
1714 let z: option<u64> = none;
1715
1716 let result2 = match z {
1717 some(x) => x,
1718 none => x
1719 };
1720
1721 { result1: result1, result2: result2 }
1722 "#;
1723
1724 let expr = Expr::from_text(rib_expr).unwrap();
1725
1726 let compiled = compiler::compile(expr, &vec![]).unwrap();
1727
1728 let mut interpreter = Interpreter::default();
1729
1730 let result = interpreter.run(compiled.byte_code).await.unwrap();
1731
1732 let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1733
1734 let expected = get_value_and_type(&analysed_type, r#"{ result1: 2, result2: 1 }"#);
1735
1736 assert_eq!(result.get_val().unwrap(), expected);
1737 }
1738
1739 #[test]
1740 async fn test_interpreter_variable_scope_3() {
1741 let rib_expr = r#"
1742 let x: u64 = 1;
1743 let x = x;
1744
1745 let result1 = match some(x + 1:u64) {
1746 some(x) => match some(x + 1:u64) {
1747 some(x) => x,
1748 none => x
1749 },
1750 none => x
1751 };
1752
1753 let z: option<u64> = none;
1754
1755 let result2 = match z {
1756 some(x) => x,
1757 none => match some(x + 1:u64) {
1758 some(x) => x,
1759 none => x
1760 }
1761 };
1762
1763 { result1: result1, result2: result2 }
1764 "#;
1765
1766 let expr = Expr::from_text(rib_expr).unwrap();
1767
1768 let compiled = compiler::compile(expr, &vec![]).unwrap();
1769
1770 let mut interpreter = Interpreter::default();
1771
1772 let result = interpreter.run(compiled.byte_code).await.unwrap();
1773
1774 let analysed_type = record(vec![field("result1", u64()), field("result2", u64())]);
1775
1776 let expected = get_value_and_type(&analysed_type, r#"{ result1: 3, result2: 2 }"#);
1777
1778 assert_eq!(result.get_val().unwrap(), expected);
1779 }
1780
1781 #[test]
1782 async fn test_interpreter_global_variable_with_type_spec() {
1783 let rib_expr = r#"
1786 let res1 = request.path.user-id;
1787 let res2 = request.headers.name;
1788 let res3 = request.headers.age;
1789 "${res1}-${res2}-${res3}"
1790 "#;
1791
1792 let type_spec = vec![
1793 GlobalVariableTypeSpec {
1794 variable_id: VariableId::global("request".to_string()),
1795 path: Path::from_elems(vec!["path"]),
1796 inferred_type: InferredType::Str,
1797 },
1798 GlobalVariableTypeSpec {
1799 variable_id: VariableId::global("request".to_string()),
1800 path: Path::from_elems(vec!["headers"]),
1801 inferred_type: InferredType::Str,
1802 },
1803 ];
1804
1805 let mut rib_input = HashMap::new();
1806
1807 let analysed_type_of_input = &record(vec![
1810 field("path", record(vec![field("user-id", str())])),
1811 field(
1812 "headers",
1813 record(vec![field("name", str()), field("age", str())]),
1814 ),
1815 ]);
1816
1817 let value_and_type = get_value_and_type(
1818 analysed_type_of_input,
1819 r#"{path : { user-id: "1" }, headers: { name: "foo", age: "20" }}"#,
1820 );
1821
1822 rib_input.insert("request".to_string(), value_and_type);
1823
1824 let mut interpreter = test_utils::interpreter_static_response(
1825 &ValueAndType::new(Value::S8(1), s8()),
1826 Some(RibInput::new(rib_input)),
1827 );
1828
1829 let expr = Expr::from_text(rib_expr).unwrap();
1830
1831 let compiled =
1832 compiler::compile_with_restricted_global_variables(expr, &vec![], None, &type_spec)
1833 .unwrap();
1834
1835 let result = interpreter
1836 .run(compiled.byte_code)
1837 .await
1838 .unwrap()
1839 .get_val()
1840 .unwrap()
1841 .value;
1842
1843 assert_eq!(result, Value::String("1-foo-20".to_string()))
1844 }
1845
1846 #[test]
1847 async fn test_interpreter_global_variable_override_type_spec() {
1848 let rib_expr = r#"
1849 let res1: u32 = request.path.user-id;
1850 let res2 = request.headers.name;
1851 let res3: u32 = request.headers.age;
1852 let res4 = res1 + res3;
1853 "${res4}-${res2}"
1854 "#;
1855
1856 let type_spec = vec![
1860 GlobalVariableTypeSpec {
1861 variable_id: VariableId::global("request".to_string()),
1862 path: Path::from_elems(vec!["path"]),
1863 inferred_type: InferredType::Str,
1864 },
1865 GlobalVariableTypeSpec {
1866 variable_id: VariableId::global("request".to_string()),
1867 path: Path::from_elems(vec!["headers"]),
1868 inferred_type: InferredType::Str,
1869 },
1870 ];
1871
1872 let mut rib_input = HashMap::new();
1873
1874 let analysed_type_of_input = &record(vec![
1877 field("path", record(vec![field("user-id", u32())])),
1878 field(
1879 "headers",
1880 record(vec![field("name", str()), field("age", u32())]),
1881 ),
1882 ]);
1883
1884 let value_and_type = get_value_and_type(
1885 analysed_type_of_input,
1886 r#"{path : { user-id: 1 }, headers: { name: "foo", age: 20 }}"#,
1887 );
1888
1889 rib_input.insert("request".to_string(), value_and_type);
1890
1891 let mut interpreter = test_utils::interpreter_static_response(
1892 &ValueAndType::new(Value::S8(1), s8()),
1893 Some(RibInput::new(rib_input)),
1894 );
1895
1896 let expr = Expr::from_text(rib_expr).unwrap();
1897
1898 let compiled =
1899 compiler::compile_with_restricted_global_variables(expr, &vec![], None, &type_spec)
1900 .unwrap();
1901
1902 let result = interpreter
1903 .run(compiled.byte_code)
1904 .await
1905 .unwrap()
1906 .get_val()
1907 .unwrap()
1908 .value;
1909
1910 assert_eq!(result, Value::String("21-foo".to_string()))
1911 }
1912
1913 #[test]
1914 async fn test_interpreter_list_reduce() {
1915 let mut interpreter = Interpreter::default();
1916
1917 let rib_expr = r#"
1918 let x: list<u8> = [1, 2];
1919
1920 reduce z, a in x from 0u8 {
1921 yield z + a;
1922 }
1923
1924 "#;
1925
1926 let expr = Expr::from_text(rib_expr).unwrap();
1927
1928 let compiled = compiler::compile(expr, &vec![]).unwrap();
1929
1930 let result = interpreter
1931 .run(compiled.byte_code)
1932 .await
1933 .unwrap()
1934 .get_val()
1935 .unwrap();
1936
1937 assert_eq!(result, 3u8.into_value_and_type());
1938 }
1939
1940 #[test]
1941 async fn test_interpreter_list_reduce_from_record() {
1942 let mut interpreter = Interpreter::default();
1943
1944 let rib_expr = r#"
1945 let x = [{name: "foo", age: 1u64}, {name: "bar", age: 2u64}];
1946
1947 let names = for i in x {
1948 yield i.name;
1949 };
1950
1951 reduce z, a in names from "" {
1952 let result = if z == "" then a else "${z}, ${a}";
1953
1954 yield result;
1955 }
1956
1957 "#;
1958
1959 let expr = Expr::from_text(rib_expr).unwrap();
1960
1961 let compiled = compiler::compile(expr, &vec![]).unwrap();
1962
1963 let result = interpreter
1964 .run(compiled.byte_code)
1965 .await
1966 .unwrap()
1967 .get_val()
1968 .unwrap();
1969
1970 assert_eq!(result, "foo, bar".into_value_and_type());
1971 }
1972
1973 #[test]
1974 async fn test_interpreter_list_reduce_text() {
1975 let mut interpreter = Interpreter::default();
1976
1977 let rib_expr = r#"
1978 let x = ["foo", "bar"];
1979
1980 reduce z, a in x from "" {
1981 let result = if z == "" then a else "${z}, ${a}";
1982
1983 yield result;
1984 }
1985
1986 "#;
1987
1988 let expr = Expr::from_text(rib_expr).unwrap();
1989
1990 let compiled = compiler::compile(expr, &vec![]).unwrap();
1991
1992 let result = interpreter
1993 .run(compiled.byte_code)
1994 .await
1995 .unwrap()
1996 .get_val()
1997 .unwrap();
1998
1999 assert_eq!(result, "foo, bar".into_value_and_type());
2000 }
2001
2002 #[test]
2003 async fn test_interpreter_list_reduce_empty() {
2004 let mut interpreter = Interpreter::default();
2005
2006 let rib_expr = r#"
2007 let x: list<u8> = [];
2008
2009 reduce z, a in x from 0u8 {
2010 yield z + a;
2011 }
2012
2013 "#;
2014
2015 let expr = Expr::from_text(rib_expr).unwrap();
2016
2017 let compiled = compiler::compile(expr, &vec![]).unwrap();
2018
2019 let result = interpreter
2020 .run(compiled.byte_code)
2021 .await
2022 .unwrap()
2023 .get_val()
2024 .unwrap();
2025
2026 assert_eq!(result, 0u8.into_value_and_type());
2027 }
2028
2029 #[test]
2030 async fn test_interpreter_with_numbers_1() {
2031 let component_metadata =
2032 test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2033
2034 let mut interpreter =
2035 test_utils::interpreter_static_response(&ValueAndType::new(Value::U64(2), u64()), None);
2036
2037 let rib = r#"
2039 let worker = instance("my-worker");
2040 worker.foo(1)
2041 "#;
2042
2043 let expr = Expr::from_text(rib).unwrap();
2044 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2045 let result = interpreter.run(compiled.byte_code).await.unwrap();
2046
2047 assert_eq!(
2048 result.get_val().unwrap(),
2049 ValueAndType::new(Value::U64(2), u64())
2050 );
2051 }
2052
2053 #[test]
2054 async fn test_interpreter_with_numbers_2() {
2055 let component_metadata =
2056 test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2057
2058 let mut interpreter =
2059 test_utils::interpreter_static_response(&ValueAndType::new(Value::U64(2), u64()), None);
2060
2061 let rib = r#"
2065 let worker = instance("my-worker");
2066 let z = 1 + 2;
2067 worker.foo(z)
2068 "#;
2069
2070 let expr = Expr::from_text(rib).unwrap();
2071 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2072 let result = interpreter.run(compiled.byte_code).await.unwrap();
2073
2074 assert_eq!(
2075 result.get_val().unwrap(),
2076 ValueAndType::new(Value::U64(2), u64())
2077 );
2078 }
2079
2080 #[test]
2081 async fn test_interpreter_with_numbers_3() {
2082 let component_metadata =
2083 test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2084
2085 let rib = r#"
2088 let worker = instance("my-worker");
2089 let z = 1: u8 + 2;
2090 worker.foo(z)
2091 "#;
2092
2093 let expr = Expr::from_text(rib).unwrap();
2094 let compile_result = compiler::compile(expr, &component_metadata);
2095 assert!(compile_result.is_err());
2096 }
2097
2098 #[test]
2099 async fn test_interpreter_with_numbers_4() {
2100 let component_metadata =
2101 test_utils::get_component_metadata("foo", vec![u32()], Some(u64()));
2102
2103 let rib = r#"
2107 let worker = instance("my-worker");
2108 let z = 1: u8 + 2: u8;
2109 worker.foo(z)
2110 "#;
2111
2112 let expr = Expr::from_text(rib).unwrap();
2113 let compile_result = compiler::compile(expr, &component_metadata);
2114 assert!(compile_result.is_err());
2115 }
2116
2117 #[test]
2118 async fn test_interpreter_list_comprehension() {
2119 let mut interpreter = Interpreter::default();
2120
2121 let rib_expr = r#"
2122 let x = ["foo", "bar"];
2123
2124 for i in x {
2125 yield i;
2126 }
2127
2128 "#;
2129
2130 let expr = Expr::from_text(rib_expr).unwrap();
2131
2132 let compiled = compiler::compile(expr, &vec![]).unwrap();
2133
2134 let result = interpreter
2135 .run(compiled.byte_code)
2136 .await
2137 .unwrap()
2138 .get_val()
2139 .unwrap();
2140
2141 let expected = r#"["foo", "bar"]"#;
2142 let expected_value = golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2143
2144 assert_eq!(result, expected_value);
2145 }
2146
2147 #[test]
2148 async fn test_interpreter_list_comprehension_empty() {
2149 let mut interpreter = Interpreter::default();
2150
2151 let rib_expr = r#"
2152 let x: list<string> = [];
2153
2154 for i in x {
2155 yield i;
2156 }
2157
2158 "#;
2159
2160 let expr = Expr::from_text(rib_expr).unwrap();
2161
2162 let compiled = compiler::compile(expr, &vec![]).unwrap();
2163
2164 let result = interpreter
2165 .run(compiled.byte_code)
2166 .await
2167 .unwrap()
2168 .get_val()
2169 .unwrap();
2170
2171 let expected = r#"[]"#;
2172 let expected_value_and_type =
2173 golem_wasm_rpc::parse_value_and_type(&list(str()), expected).unwrap();
2174
2175 assert_eq!(result, expected_value_and_type);
2176 }
2177
2178 #[test]
2179 async fn test_interpreter_pattern_match_on_option_nested() {
2180 let mut interpreter = Interpreter::default();
2181
2182 let expr = r#"
2183 let x: option<option<u64>> = none;
2184
2185 match x {
2186 some(some(t)) => t,
2187 some(none) => 0u64,
2188 none => 0u64
2189
2190 }
2191 "#;
2192
2193 let mut expr = Expr::from_text(expr).unwrap();
2194 expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2195 .unwrap();
2196 let compiled = compiler::compile(expr, &vec![]).unwrap();
2197 let result = interpreter.run(compiled.byte_code).await.unwrap();
2198
2199 assert_eq!(result.get_val().unwrap(), 0u64.into_value_and_type());
2200 }
2201
2202 #[test]
2203 async fn test_interpreter_pattern_match_on_tuple() {
2204 let mut interpreter = Interpreter::default();
2205
2206 let expr = r#"
2207 let x: tuple<u64, string, string> = (1, "foo", "bar");
2208
2209 match x {
2210 (x, y, z) => "${x} ${y} ${z}"
2211 }
2212 "#;
2213
2214 let mut expr = Expr::from_text(expr).unwrap();
2215 expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2216 .unwrap();
2217 let compiled = compiler::compile(expr, &vec![]).unwrap();
2218 let result = interpreter.run(compiled.byte_code).await.unwrap();
2219
2220 assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2221 }
2222
2223 #[test]
2224 async fn test_interpreter_pattern_match_on_tuple_with_option_some() {
2225 let mut interpreter = Interpreter::default();
2226
2227 let expr = r#"
2228 let x: tuple<u64, option<string>, string> = (1, some("foo"), "bar");
2229
2230 match x {
2231 (x, none, z) => "${x} ${z}",
2232 (x, some(y), z) => "${x} ${y} ${z}"
2233 }
2234 "#;
2235
2236 let mut expr = Expr::from_text(expr).unwrap();
2237 expr.infer_types(&FunctionTypeRegistry::empty(), &vec![])
2238 .unwrap();
2239
2240 let compiled = compiler::compile(expr, &vec![]).unwrap();
2241 let result = interpreter.run(compiled.byte_code).await.unwrap();
2242
2243 assert_eq!(result.get_val().unwrap(), "1 foo bar".into_value_and_type());
2244 }
2245
2246 #[test]
2247 async fn test_interpreter_pattern_match_on_tuple_with_option_none() {
2248 let mut interpreter = Interpreter::default();
2249
2250 let expr = r#"
2251 let x: tuple<u64, option<string>, string> = (1, none, "bar");
2252
2253 match x {
2254 (x, none, z) => "${x} ${z}",
2255 (x, some(y), z) => "${x} ${y} ${z}"
2256 }
2257 "#;
2258
2259 let expr = Expr::from_text(expr).unwrap();
2260 let compiled = compiler::compile(expr, &vec![]).unwrap();
2261 let result = interpreter.run(compiled.byte_code).await.unwrap();
2262
2263 assert_eq!(result.get_val().unwrap(), "1 bar".into_value_and_type());
2264 }
2265
2266 #[test]
2267 async fn test_interpreter_pattern_match_on_tuple_with_all_types() {
2268 let mut interpreter = Interpreter::default();
2269
2270 let tuple = test_utils::get_analysed_type_tuple();
2271
2272 let analysed_exports = test_utils::get_component_metadata("foo", vec![tuple], Some(str()));
2273
2274 let expr = r#"
2275
2276 let record = { request : { path : { user : "jak" } }, y : "bar" };
2277 let input = (1, ok(100), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2278 foo(input);
2279 match input {
2280 (n1, err(x1), txt, rec, process-user(x), register-user(n), validate, dev, prod, test) => "Invalid",
2281 (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}"
2282 }
2283
2284 "#;
2285
2286 let expr = Expr::from_text(expr).unwrap();
2287 let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2288 let result = interpreter.run(compiled.byte_code).await.unwrap();
2289
2290 assert_eq!(
2291 result.get_val().unwrap(),
2292 "foo 100 1 bar jak validate prod dev test".into_value_and_type()
2293 );
2294 }
2295
2296 #[test]
2297 async fn test_interpreter_pattern_match_on_tuple_with_wild_pattern() {
2298 let mut interpreter = Interpreter::default();
2299
2300 let tuple = test_utils::get_analysed_type_tuple();
2301
2302 let analysed_exports =
2303 test_utils::get_component_metadata("my-worker-function", vec![tuple], Some(str()));
2304
2305 let expr = r#"
2306
2307 let record = { request : { path : { user : "jak" } }, y : "baz" };
2308 let input = (1, ok(1), "bar", record, process-user("jon"), register-user(1u64), validate, prod, dev, test);
2309 my-worker-function(input);
2310 match input {
2311 (n1, ok(x), txt, rec, _, _, _, _, prod, _) => "prod ${n1} ${txt} ${rec.request.path.user} ${rec.y}",
2312 (n1, ok(x), txt, rec, _, _, _, _, dev, _) => "dev ${n1} ${txt} ${rec.request.path.user} ${rec.y}"
2313 }
2314 "#;
2315
2316 let expr = Expr::from_text(expr).unwrap();
2317 let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2318 let result = interpreter.run(compiled.byte_code).await.unwrap();
2319
2320 assert_eq!(
2321 result.get_val().unwrap(),
2322 "dev 1 bar jak baz".into_value_and_type()
2323 );
2324 }
2325
2326 #[test]
2327 async fn test_interpreter_record_output_in_pattern_match() {
2328 let input_analysed_type = test_utils::get_analysed_type_record();
2329 let output_analysed_type = test_utils::get_analysed_type_result();
2330
2331 let result_value = get_value_and_type(&output_analysed_type, r#"ok(1)"#);
2332
2333 let mut interpreter = test_utils::interpreter_static_response(&result_value, None);
2334
2335 let analysed_exports = test_utils::get_component_metadata(
2336 "my-worker-function",
2337 vec![input_analysed_type],
2338 Some(output_analysed_type),
2339 );
2340
2341 let expr = r#"
2342
2343 let input = { request : { path : { user : "jak" } }, y : "baz" };
2344 let result = my-worker-function(input);
2345 match result {
2346 ok(result) => { body: result, status: 200 },
2347 err(result) => { status: 400, body: 400 }
2348 }
2349 "#;
2350
2351 let expr = Expr::from_text(expr).unwrap();
2352 let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2353 let result = interpreter.run(compiled.byte_code).await.unwrap();
2354
2355 let expected = test_utils::get_value_and_type(
2356 &record(vec![field("body", u64()), field("status", u64())]),
2357 r#"{body: 1, status: 200}"#,
2358 );
2359
2360 assert_eq!(result.get_val().unwrap(), expected);
2361 }
2362
2363 #[test]
2364 async fn test_interpreter_tuple_output_in_pattern_match() {
2365 let input_analysed_type = test_utils::get_analysed_type_record();
2366 let output_analysed_type = test_utils::get_analysed_type_result();
2367
2368 let result_value = get_value_and_type(&output_analysed_type, r#"err("failed")"#);
2369
2370 let mut interpreter = test_utils::interpreter_static_response(&result_value, None);
2371
2372 let analysed_exports = test_utils::get_component_metadata(
2373 "my-worker-function",
2374 vec![input_analysed_type],
2375 Some(output_analysed_type),
2376 );
2377
2378 let expr = r#"
2379
2380 let input = { request : { path : { user : "jak" } }, y : "baz" };
2381 let result = my-worker-function(input);
2382 match result {
2383 ok(res) => ("${res}", "foo"),
2384 err(msg) => (msg, "bar")
2385 }
2386 "#;
2387
2388 let expr = Expr::from_text(expr).unwrap();
2389 let compiled = compiler::compile(expr, &analysed_exports).unwrap();
2390 let result = interpreter.run(compiled.byte_code).await.unwrap();
2391
2392 let expected = get_value_and_type(&tuple(vec![str(), str()]), r#"("failed", "bar")"#);
2393
2394 assert_eq!(result.get_val().unwrap(), expected);
2395 }
2396
2397 #[test]
2398 async fn test_interpreter_with_indexed_resource_drop() {
2399 let expr = r#"
2400 let user_id = "user";
2401 golem:it/api.{cart(user_id).drop}();
2402 "success"
2403 "#;
2404 let expr = Expr::from_text(expr).unwrap();
2405 let component_metadata = test_utils::get_metadata_with_resource_with_params();
2406
2407 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2408
2409 let mut rib_interpreter = Interpreter::default();
2410 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2411
2412 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2413 }
2414
2415 #[test]
2416 async fn test_interpreter_with_indexed_resource_checkout() {
2417 let expr = r#"
2418 let user_id = "foo";
2419 let result = golem:it/api.{cart(user_id).checkout}();
2420 result
2421 "#;
2422
2423 let expr = Expr::from_text(expr).unwrap();
2424
2425 let result_type = variant(vec![
2426 case("error", str()),
2427 case("success", record(vec![field("order-id", str())])),
2428 ]);
2429
2430 let result_value = test_utils::get_value_and_type(
2431 &result_type,
2432 r#"
2433 success({order-id: "foo"})
2434 "#,
2435 );
2436
2437 let component_metadata = test_utils::get_metadata_with_resource_with_params();
2438 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2439
2440 let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2441 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2442
2443 assert_eq!(result.get_val().unwrap(), result_value);
2444 }
2445
2446 #[test]
2447 async fn test_interpreter_with_indexed_resource_get_cart_contents() {
2448 let expr = r#"
2449 let user_id = "bar";
2450 let result = golem:it/api.{cart(user_id).get-cart-contents}();
2451 result[0].product-id
2452 "#;
2453
2454 let expr = Expr::from_text(expr).unwrap();
2455
2456 let result_type = list(record(vec![
2457 field("product-id", str()),
2458 field("name", str()),
2459 field("price", f32()),
2460 field("quantity", u32()),
2461 ]));
2462
2463 let result_value = test_utils::get_value_and_type(
2464 &result_type,
2465 r#"
2466 [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}]
2467 "#,
2468 );
2469
2470 let component_metadata = test_utils::get_metadata_with_resource_with_params();
2471 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2472
2473 let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2474 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2475
2476 assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2477 }
2478
2479 #[test]
2480 async fn test_interpreter_with_indexed_resource_update_item_quantity() {
2481 let expr = r#"
2482 let user_id = "jon";
2483 let product_id = "mac";
2484 let quantity = 1032;
2485 golem:it/api.{cart(user_id).update-item-quantity}(product_id, quantity);
2486 "successfully updated"
2487 "#;
2488 let expr = Expr::from_text(expr).unwrap();
2489
2490 let component_metadata = test_utils::get_metadata_with_resource_with_params();
2491
2492 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2493
2494 let mut rib_executor = Interpreter::default();
2495
2496 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2497
2498 assert_eq!(
2499 result.get_val().unwrap(),
2500 "successfully updated".into_value_and_type()
2501 );
2502 }
2503
2504 #[test]
2505 async fn test_interpreter_with_indexed_resource_add_item() {
2506 let expr = r#"
2507 let user_id = "foo";
2508 let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2509 golem:it/api.{cart(user_id).add-item}(product);
2510
2511 "successfully added"
2512 "#;
2513
2514 let expr = Expr::from_text(expr).unwrap();
2515
2516 let component_metadata = test_utils::get_metadata_with_resource_with_params();
2517
2518 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2519
2520 let mut rib_executor = Interpreter::default();
2521
2522 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2523
2524 assert_eq!(
2525 result.get_val().unwrap(),
2526 "successfully added".into_value_and_type()
2527 );
2528 }
2529
2530 #[test]
2531 async fn test_interpreter_with_resource_add_item() {
2532 let expr = r#"
2533 let user_id = "foo";
2534 let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 };
2535 golem:it/api.{cart.add-item}(product);
2536
2537 "successfully added"
2538 "#;
2539
2540 let expr = Expr::from_text(expr).unwrap();
2541
2542 let component_metadata = test_utils::get_metadata_with_resource_without_params();
2543
2544 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2545
2546 let mut rib_executor = Interpreter::default();
2547
2548 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2549
2550 assert_eq!(
2551 result.get_val().unwrap(),
2552 "successfully added".into_value_and_type()
2553 );
2554 }
2555
2556 #[test]
2557 async fn test_interpreter_with_resource_get_cart_contents() {
2558 let expr = r#"
2559 let result = golem:it/api.{cart.get-cart-contents}();
2560 result[0].product-id
2561 "#;
2562
2563 let expr = Expr::from_text(expr).unwrap();
2564
2565 let result_type = list(record(vec![
2566 field("product-id", str()),
2567 field("name", str()),
2568 field("price", f32()),
2569 field("quantity", u32()),
2570 ]));
2571
2572 let result_value = test_utils::get_value_and_type(
2573 &result_type,
2574 r#"
2575 [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}]
2576 "#,
2577 );
2578
2579 let component_metadata = test_utils::get_metadata_with_resource_without_params();
2580 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2581
2582 let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2583 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2584
2585 assert_eq!(result.get_val().unwrap(), "foo".into_value_and_type());
2586 }
2587
2588 #[test]
2589 async fn test_interpreter_with_resource_update_item() {
2590 let expr = r#"
2591 let product_id = "mac";
2592 let quantity = 1032;
2593 golem:it/api.{cart.update-item-quantity}(product_id, quantity);
2594 "successfully updated"
2595 "#;
2596 let expr = Expr::from_text(expr).unwrap();
2597
2598 let component_metadata = test_utils::get_metadata_with_resource_without_params();
2599
2600 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2601
2602 let mut rib_executor = Interpreter::default();
2603
2604 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2605
2606 assert_eq!(
2607 result.get_val().unwrap(),
2608 "successfully updated".into_value_and_type()
2609 );
2610 }
2611
2612 #[test]
2613 async fn test_interpreter_with_resource_checkout() {
2614 let expr = r#"
2615 let result = golem:it/api.{cart.checkout}();
2616 result
2617 "#;
2618
2619 let expr = Expr::from_text(expr).unwrap();
2620
2621 let result_type = variant(vec![
2622 case("error", str()),
2623 case("success", record(vec![field("order-id", str())])),
2624 ]);
2625
2626 let result_value = test_utils::get_value_and_type(
2627 &result_type,
2628 r#"
2629 success({order-id: "foo"})
2630 "#,
2631 );
2632
2633 let component_metadata = test_utils::get_metadata_with_resource_without_params();
2634 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2635
2636 let mut rib_executor = test_utils::interpreter_static_response(&result_value, None);
2637 let result = rib_executor.run(compiled.byte_code).await.unwrap();
2638
2639 assert_eq!(result.get_val().unwrap(), result_value);
2640 }
2641
2642 #[test]
2643 async fn test_interpreter_with_resource_drop() {
2644 let expr = r#"
2645 golem:it/api.{cart.drop}();
2646 "success"
2647 "#;
2648 let expr = Expr::from_text(expr).unwrap();
2649 let component_metadata = test_utils::get_metadata_with_resource_without_params();
2650
2651 let compiled = compiler::compile(expr, &component_metadata).unwrap();
2652
2653 let mut rib_interpreter = Interpreter::default();
2654 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
2655
2656 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
2657 }
2658
2659 #[test]
2660 async fn test_interpreter_for_select_index_expr_1() {
2661 let expr = r#"
2664 let list: list<u8> = [1, 2, 3, 4, 5];
2665 let index: u8 = 4;
2666 list[index]
2667 "#;
2668
2669 let expr = Expr::from_text(expr).unwrap();
2670
2671 let compiled = compiler::compile(expr, &vec![]).unwrap();
2672
2673 let mut interpreter = Interpreter::default();
2674 let result = interpreter.run(compiled.byte_code).await.unwrap();
2675
2676 let expected = ValueAndType::new(Value::U8(5), u8());
2677
2678 assert_eq!(result.get_val().unwrap(), expected);
2679 }
2680
2681 #[test]
2682 async fn test_interpreter_for_select_index_expr_out_of_bound() {
2683 let expr = r#"
2684 let list: list<u8> = [1, 2, 3, 4, 5];
2685 let index: u8 = 10;
2686 list[index]
2687 "#;
2688
2689 let expr = Expr::from_text(expr).unwrap();
2690
2691 let compiled = compiler::compile(expr, &vec![]).unwrap();
2692
2693 let mut interpreter = Interpreter::default();
2694 let result = interpreter.run(compiled.byte_code).await.unwrap_err();
2695
2696 assert_eq!(
2697 result,
2698 "index 10 is out of bound in the list of length 5".to_string()
2699 );
2700 }
2701
2702 #[test]
2703 async fn test_interpreter_for_select_index_expr_2() {
2704 let expr = r#"
2705 let list: list<u8> = [1, 2, 3, 4, 5];
2706 let indices: list<u8> = [0, 1, 2, 3];
2707
2708 for i in indices {
2709 yield list[i];
2710 }
2711 "#;
2712
2713 let expr = Expr::from_text(expr).unwrap();
2714
2715 let compiled = compiler::compile(expr, &vec![]).unwrap();
2716
2717 let mut interpreter = Interpreter::default();
2718 let result = interpreter.run(compiled.byte_code).await.unwrap();
2719
2720 let expected = ValueAndType::new(
2721 Value::List(vec![Value::U8(1), Value::U8(2), Value::U8(3), Value::U8(4)]),
2722 list(u8()),
2723 );
2724
2725 assert_eq!(result.get_val().unwrap(), expected);
2726 }
2727
2728 #[test]
2729 async fn test_interpreter_for_select_index_expr_3() {
2730 let expr = r#"
2731 let list: list<u8> = [2, 5, 4];
2732 let indices: list<u8> = [0, 1];
2733
2734 reduce z, index in indices from 0u8 {
2735 yield list[index] + z;
2736 }
2737 "#;
2738
2739 let expr = Expr::from_text(expr).unwrap();
2740
2741 let compiled = compiler::compile(expr, &vec![]).unwrap();
2742
2743 let mut interpreter = Interpreter::default();
2744 let result = interpreter.run(compiled.byte_code).await.unwrap();
2745
2746 let expected = ValueAndType::new(Value::U8(7), u8());
2747
2748 assert_eq!(result.get_val().unwrap(), expected);
2749 }
2750
2751 #[test]
2752 async fn test_interpreter_for_select_index_expr_4() {
2753 let expr = r#"
2754 let list: list<u8> = [2, 5, 4];
2755 let x: u8 = 0;
2756 let y: u8 = 2;
2757 list[x..=y]
2758 "#;
2759
2760 let expr = Expr::from_text(expr).unwrap();
2761
2762 let compiled = compiler::compile(expr, &vec![]).unwrap();
2763
2764 let mut interpreter = Interpreter::default();
2765 let result = interpreter.run(compiled.byte_code).await.unwrap();
2766
2767 let expected = ValueAndType::new(
2768 Value::List(vec![Value::U8(2), Value::U8(5), Value::U8(4)]),
2769 list(u8()),
2770 );
2771
2772 assert_eq!(result.get_val().unwrap(), expected);
2773 }
2774
2775 #[test]
2776 async fn test_interpreter_for_select_index_expr_5() {
2777 let expr = r#"
2778 let list: list<u8> = [2, 5, 4];
2779 let x: u8 = 0;
2780 let y: u8 = 2;
2781 let x1: u8 = 1;
2782 let result = list[x..=y];
2783 for i in result[x1..=y] {
2784 yield i;
2785 }
2786 "#;
2787
2788 let expr = Expr::from_text(expr).unwrap();
2789
2790 let compiled = compiler::compile(expr, &vec![]).unwrap();
2791
2792 let mut interpreter = Interpreter::default();
2793 let result = interpreter.run(compiled.byte_code).await.unwrap();
2794
2795 let expected = ValueAndType::new(Value::List(vec![Value::U8(5), Value::U8(4)]), list(u8()));
2796
2797 assert_eq!(result.get_val().unwrap(), expected);
2798 }
2799
2800 #[test]
2801 async fn test_interpreter_for_select_index_expr_6() {
2802 let expr = r#"
2803 let list: list<u8> = [2, 5, 4, 6];
2804 let x: u8 = 0;
2805 let y: u8 = 2;
2806 let result = list[x..y];
2807 for i in result[x..y] {
2808 yield i;
2809 }
2810 "#;
2811
2812 let expr = Expr::from_text(expr).unwrap();
2813
2814 let compiled = compiler::compile(expr, &vec![]).unwrap();
2815
2816 let mut interpreter = Interpreter::default();
2817 let result = interpreter.run(compiled.byte_code).await.unwrap();
2818
2819 let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2820
2821 assert_eq!(result.get_val().unwrap(), expected);
2822 }
2823
2824 #[test]
2825 async fn test_interpreter_for_select_index_expr_7() {
2826 let expr = r#"
2827 let list: list<u8> = [2, 5, 4, 6];
2828 let x: u8 = 0;
2829 let result = list[x..];
2830 for i in result[x..] {
2831 yield i;
2832 }
2833 "#;
2834
2835 let expr = Expr::from_text(expr).unwrap();
2836
2837 let compiled = compiler::compile(expr, &vec![]).unwrap();
2838
2839 let mut interpreter = Interpreter::default();
2840 let result = interpreter.run(compiled.byte_code).await.unwrap();
2841
2842 let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2843
2844 assert_eq!(result.get_val().unwrap(), expected);
2845 }
2846
2847 #[test]
2848 async fn test_interpreter_for_select_index_expr_8() {
2849 let expr = r#"
2850 let list: list<u8> = [2, 5, 4, 6];
2851 let result = list[0..2];
2852 for i in result[0..2] {
2853 yield i;
2854 }
2855 "#;
2856
2857 let expr = Expr::from_text(expr).unwrap();
2858
2859 let compiled = compiler::compile(expr, &vec![]).unwrap();
2860
2861 let mut interpreter = Interpreter::default();
2862 let result = interpreter.run(compiled.byte_code).await.unwrap();
2863
2864 let expected = ValueAndType::new(Value::List(vec![Value::U8(2), Value::U8(5)]), list(u8()));
2865
2866 assert_eq!(result.get_val().unwrap(), expected);
2867 }
2868
2869 #[test]
2873 async fn test_interpreter_range_returns_1() {
2874 let expr = r#"
2875 let x = 1..;
2876 x
2877 "#;
2878
2879 let expr = Expr::from_text(expr).unwrap();
2880
2881 let compiled = compiler::compile(expr, &vec![]).unwrap();
2882
2883 let mut interpreter = Interpreter::default();
2884 let result = interpreter.run(compiled.byte_code).await.unwrap();
2885
2886 let expected = ValueAndType::new(
2887 Value::Record(vec![
2888 Value::U64(1),
2889 Value::Bool(false), ]),
2891 record(vec![
2892 field("from", option(u64())),
2893 field("inclusive", bool()),
2894 ]),
2895 );
2896
2897 assert_eq!(result.get_val().unwrap(), expected);
2898 }
2899
2900 #[test]
2901 async fn test_interpreter_range_returns_2() {
2902 let expr = r#"
2903 let x = 1..2;
2904 x
2905 "#;
2906
2907 let expr = Expr::from_text(expr).unwrap();
2908
2909 let compiled = compiler::compile(expr, &vec![]).unwrap();
2910
2911 let mut interpreter = Interpreter::default();
2912 let result = interpreter.run(compiled.byte_code).await.unwrap();
2913
2914 let expected = ValueAndType::new(
2915 Value::Record(vec![
2916 Value::U64(1),
2917 Value::U64(2),
2918 Value::Bool(false), ]),
2920 record(vec![
2921 field("from", option(u64())),
2922 field("to", option(u64())),
2923 field("inclusive", bool()),
2924 ]),
2925 );
2926
2927 assert_eq!(result.get_val().unwrap(), expected);
2928 }
2929
2930 #[test]
2931 async fn test_interpreter_range_returns_3() {
2932 let expr = r#"
2933 let x = 1..=10;
2934 x
2935 "#;
2936
2937 let expr = Expr::from_text(expr).unwrap();
2938
2939 let compiled = compiler::compile(expr, &vec![]).unwrap();
2940
2941 let mut interpreter = Interpreter::default();
2942 let result = interpreter.run(compiled.byte_code).await.unwrap();
2943
2944 let expected = ValueAndType::new(
2945 Value::Record(vec![
2946 Value::U64(1),
2947 Value::U64(10),
2948 Value::Bool(true), ]),
2950 record(vec![
2951 field("from", option(u64())),
2952 field("to", option(u64())),
2953 field("inclusive", bool()),
2954 ]),
2955 );
2956
2957 assert_eq!(result.get_val().unwrap(), expected);
2958 }
2959
2960 #[test]
2961 async fn test_interpreter_range_returns_4() {
2962 let expr = r#"
2963 let x = 1:u64;
2964 let y = x;
2965 let range = x..=y;
2966 let range2 = x..;
2967 let range3 = x..y;
2968 range;
2969 range2;
2970 range3
2971 "#;
2972
2973 let expr = Expr::from_text(expr).unwrap();
2974
2975 let compiled = compiler::compile(expr, &vec![]).unwrap();
2976
2977 let mut interpreter = Interpreter::default();
2978 let result = interpreter.run(compiled.byte_code).await.unwrap();
2979
2980 let expected = ValueAndType::new(
2981 Value::Record(vec![Value::U64(1), Value::U64(1), Value::Bool(false)]),
2982 record(vec![
2983 field("from", option(u64())),
2984 field("to", option(u64())),
2985 field("inclusive", bool()),
2986 ]),
2987 );
2988
2989 assert_eq!(result.get_val().unwrap(), expected);
2990 }
2991
2992 #[test]
2993 async fn test_interpreter_range_returns_5() {
2994 let expr = r#"
2995 let y = 1:u64 + 10: u64;
2996 1..y
2997 "#;
2998
2999 let expr = Expr::from_text(expr).unwrap();
3000
3001 let compiled = compiler::compile(expr, &vec![]).unwrap();
3002
3003 let mut interpreter = Interpreter::default();
3004 let result = interpreter.run(compiled.byte_code).await.unwrap();
3005
3006 let expected = ValueAndType::new(
3007 Value::Record(vec![Value::U64(1), Value::U64(11), Value::Bool(false)]),
3008 record(vec![
3009 field("from", option(u64())),
3010 field("to", option(u64())),
3011 field("inclusive", bool()),
3012 ]),
3013 );
3014
3015 assert_eq!(result.get_val().unwrap(), expected);
3016 }
3017
3018 #[test]
3019 async fn test_interpreter_range_with_comprehension_1() {
3020 let expr = r#"
3021 let range = 1..=5;
3022 for i in range {
3023 yield i;
3024 }
3025
3026 "#;
3027
3028 let expr = Expr::from_text(expr).unwrap();
3029
3030 let compiled = compiler::compile(expr, &vec![]).unwrap();
3031
3032 let mut interpreter = Interpreter::default();
3033 let result = interpreter.run(compiled.byte_code).await.unwrap();
3034
3035 let expected = ValueAndType::new(
3036 Value::List(vec![
3037 Value::U64(1),
3038 Value::U64(2),
3039 Value::U64(3),
3040 Value::U64(4),
3041 Value::U64(5),
3042 ]),
3043 list(u64()),
3044 );
3045
3046 assert_eq!(result.get_val().unwrap(), expected);
3047 }
3048
3049 #[test]
3050 async fn test_interpreter_range_with_comprehension_2() {
3051 let expr = r#"
3052 let range = 1..5;
3053 for i in range {
3054 yield i;
3055 }
3056
3057 "#;
3058
3059 let expr = Expr::from_text(expr).unwrap();
3060
3061 let compiled = compiler::compile(expr, &vec![]).unwrap();
3062
3063 let mut interpreter = Interpreter::default();
3064 let result = interpreter.run(compiled.byte_code).await.unwrap();
3065
3066 let expected = ValueAndType::new(
3067 Value::List(vec![
3068 Value::U64(1),
3069 Value::U64(2),
3070 Value::U64(3),
3071 Value::U64(4),
3072 ]),
3073 list(u64()),
3074 );
3075
3076 assert_eq!(result.get_val().unwrap(), expected);
3077 }
3078
3079 #[test]
3080 async fn test_interpreter_range_with_comprehension_3() {
3081 let expr = r#"
3084 let range = 1:u64..;
3085 for i in range {
3086 yield i;
3087 }
3088
3089 "#;
3090
3091 let expr = Expr::from_text(expr).unwrap();
3092
3093 let compiled = compiler::compile(expr, &vec![]).unwrap();
3094
3095 let mut interpreter = Interpreter::default();
3096 let result = interpreter.run(compiled.byte_code).await;
3097 assert!(result.is_err());
3098 }
3099
3100 #[test]
3101 async fn test_interpreter_range_with_list_reduce_1() {
3102 let expr = r#"
3105 let initial: u8 = 1;
3106 let final: u8 = 5;
3107 let x = initial..final;
3108
3109 reduce z, a in x from 0u8 {
3110 yield z + a;
3111 }
3112
3113 "#;
3114
3115 let expr = Expr::from_text(expr).unwrap();
3116
3117 let compiled = compiler::compile(expr, &vec![]).unwrap();
3118
3119 let mut interpreter = Interpreter::default();
3120 let result = interpreter.run(compiled.byte_code).await.unwrap();
3121
3122 let expected = ValueAndType::new(Value::U8(10), u8());
3123
3124 assert_eq!(result.get_val().unwrap(), expected);
3125 }
3126
3127 #[test]
3128 async fn test_interpreter_ephemeral_worker_0() {
3129 let expr = r#"
3130 let x = instance();
3131 let result = x.foo("bar");
3132 result
3133 "#;
3134 let expr = Expr::from_text(expr).unwrap();
3135
3136 let component_metadata = test_utils::get_metadata();
3137
3138 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3139
3140 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3141
3142 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3143
3144 let expected_val = test_utils::parse_function_details(
3145 r#"
3146 {
3147 worker-name: none,
3148 function-name: "amazon:shopping-cart/api1.{foo}",
3149 args0: "bar"
3150 }
3151 "#,
3152 );
3153
3154 assert_eq!(result.get_val().unwrap(), expected_val);
3155 }
3156
3157 #[test]
3158 async fn test_interpreter_ephemeral_worker_1() {
3159 let expr = r#"
3160 let x = instance();
3161 x
3162 "#;
3163 let expr = Expr::from_text(expr).unwrap();
3164
3165 let component_metadata = test_utils::get_metadata();
3166
3167 let compiled = compiler::compile(expr, &component_metadata);
3168
3169 assert!(compiled.is_err());
3170 }
3171
3172 #[test]
3173 async fn test_interpreter_ephemeral_worker_2() {
3174 let expr = r#"
3175 instance
3176 "#;
3177 let expr = Expr::from_text(expr).unwrap();
3178
3179 let component_metadata = test_utils::get_metadata();
3180
3181 let compiled = compiler::compile(expr, &component_metadata);
3182
3183 assert!(compiled.is_err());
3184 }
3185
3186 #[test]
3187 async fn test_interpreter_ephemeral_worker_3() {
3188 let expr = r#"
3189 instance()
3190 "#;
3191 let expr = Expr::from_text(expr).unwrap();
3192
3193 let component_metadata = test_utils::get_metadata();
3194
3195 let compiled = compiler::compile(expr, &component_metadata);
3196
3197 assert!(compiled.is_err());
3198 }
3199
3200 #[test]
3201 async fn test_interpreter_ephemeral_worker_4() {
3202 let expr = r#"
3203 instance().foo("bar")
3204 "#;
3205 let expr = Expr::from_text(expr).unwrap();
3206
3207 let component_metadata = test_utils::get_metadata();
3208
3209 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3210
3211 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3212
3213 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3214
3215 let expected_val = test_utils::parse_function_details(
3216 r#"
3217 {
3218 worker-name: none,
3219 function-name: "amazon:shopping-cart/api1.{foo}",
3220 args0: "bar"
3221 }
3222 "#,
3223 );
3224
3225 assert_eq!(result.get_val().unwrap(), expected_val);
3226 }
3227
3228 #[test]
3229 async fn test_interpreter_ephemeral_worker_5() {
3230 let expr = r#"
3231 let result = instance.foo("bar");
3232 result
3233 "#;
3234 let expr = Expr::from_text(expr).unwrap();
3235 let component_metadata = test_utils::get_metadata();
3236
3237 let compiled = compiler::compile(expr, &component_metadata)
3238 .unwrap_err()
3239 .to_string();
3240
3241 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());
3242 }
3243
3244 #[test]
3245 async fn test_interpreter_ephemeral_worker_6() {
3246 let expr = r#"
3247 let x = instance();
3248 let result = x.bar("bar");
3249 result
3250 "#;
3251 let expr = Expr::from_text(expr).unwrap();
3252 let component_metadata = test_utils::get_metadata();
3253
3254 let compilation_error = compiler::compile(expr, &component_metadata)
3255 .unwrap_err()
3256 .to_string();
3257
3258 assert_eq!(
3259 compilation_error,
3260 "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()
3261 );
3262 }
3263
3264 #[test]
3265 async fn test_interpreter_ephemeral_worker_7() {
3266 let expr = r#"
3267 let worker = instance();
3268 let invokes: list<u8> = [1, 2, 3, 4];
3269
3270 for i in invokes {
3271 yield worker.qux[wasi:clocks]("bar");
3272 };
3273
3274 "success"
3275 "#;
3276 let expr = Expr::from_text(expr).unwrap();
3277 let component_metadata = test_utils::get_metadata();
3278
3279 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3280
3281 let mut rib_interpreter =
3282 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3283
3284 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3285
3286 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3287 }
3288
3289 #[test]
3291 async fn test_interpreter_durable_worker_0() {
3292 let expr = r#"
3293 let worker = instance("my-worker");
3294 let result = worker.foo("bar");
3295 result
3296 "#;
3297 let expr = Expr::from_text(expr).unwrap();
3298 let component_metadata = test_utils::get_metadata();
3299
3300 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3301
3302 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3303
3304 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3305
3306 let expected_val = test_utils::parse_function_details(
3307 r#"
3308 {
3309 worker-name: some("my-worker"),
3310 function-name: "amazon:shopping-cart/api1.{foo}",
3311 args0: "bar"
3312 }
3313 "#,
3314 );
3315
3316 assert_eq!(result.get_val().unwrap(), expected_val);
3317 }
3318
3319 #[test]
3320 async fn test_interpreter_durable_worker_1() {
3321 let expr = r#"
3322 instance("my-worker").foo("bar")
3323 "#;
3324 let expr = Expr::from_text(expr).unwrap();
3325 let component_metadata = test_utils::get_metadata();
3326
3327 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3328
3329 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3330
3331 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3332
3333 let expected_val = test_utils::parse_function_details(
3334 r#"
3335 {
3336 worker-name: some("my-worker"),
3337 function-name: "amazon:shopping-cart/api1.{foo}",
3338 args0: "bar"
3339 }
3340 "#,
3341 );
3342
3343 assert_eq!(result.get_val().unwrap(), expected_val);
3344 }
3345
3346 #[test]
3347 async fn test_interpreter_durable_worker_2() {
3348 let expr = r#"
3349 let result = instance("my-worker").foo("bar");
3350 result
3351 "#;
3352 let expr = Expr::from_text(expr).unwrap();
3353 let component_metadata = test_utils::get_metadata();
3354
3355 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3356
3357 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3358
3359 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3360
3361 let expected_val = test_utils::parse_function_details(
3362 r#"
3363 {
3364 worker-name: some("my-worker"),
3365 function-name: "amazon:shopping-cart/api1.{foo}",
3366 args0: "bar"
3367 }
3368 "#,
3369 );
3370
3371 assert_eq!(result.get_val().unwrap(), expected_val);
3372 }
3373
3374 #[test]
3375 async fn test_interpreter_durable_worker_3() {
3376 let expr = r#"
3377 let my_worker = instance("my-worker");
3378 let result = my_worker.foo[api1]("bar");
3379 result
3380 "#;
3381 let expr = Expr::from_text(expr).unwrap();
3382 let component_metadata = test_utils::get_metadata();
3383
3384 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3385
3386 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3387
3388 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3389
3390 let expected_val = test_utils::parse_function_details(
3391 r#"
3392 {
3393 worker-name: some("my-worker"),
3394 function-name: "amazon:shopping-cart/api1.{foo}",
3395 args0: "bar"
3396 }
3397 "#,
3398 );
3399
3400 assert_eq!(result.get_val().unwrap(), expected_val);
3401 }
3402
3403 #[test]
3404 async fn test_interpreter_durable_worker_4() {
3405 let expr = r#"
3406 let worker = instance("my-worker");
3407 let result = worker.bar("bar");
3408 result
3409 "#;
3410 let expr = Expr::from_text(expr).unwrap();
3411 let component_metadata = test_utils::get_metadata();
3412
3413 let compilation_error = compiler::compile(expr, &component_metadata)
3414 .unwrap_err()
3415 .to_string();
3416
3417 assert_eq!(
3418 compilation_error,
3419 "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()
3420 );
3421 }
3422
3423 #[test]
3424 async fn test_interpreter_durable_worker_5() {
3425 let expr = r#"
3426 let worker = instance("my-worker");
3427 let result = worker.bar[api1]("bar");
3428 result
3429 "#;
3430 let expr = Expr::from_text(expr).unwrap();
3431 let component_metadata = test_utils::get_metadata();
3432
3433 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3434
3435 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3436
3437 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3438
3439 let expected_val = test_utils::parse_function_details(
3440 r#"
3441 {
3442 worker-name: some("my-worker"),
3443 function-name: "amazon:shopping-cart/api1.{bar}",
3444 args0: "bar"
3445 }
3446 "#,
3447 );
3448
3449 assert_eq!(result.get_val().unwrap(), expected_val);
3450 }
3451
3452 #[test]
3453 async fn test_interpreter_durable_worker_6() {
3454 let expr = r#"
3455 let worker = instance("my-worker");
3456 let result = worker.bar[api2]("bar");
3457 result
3458 "#;
3459 let expr = Expr::from_text(expr).unwrap();
3460 let component_metadata = test_utils::get_metadata();
3461
3462 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3463
3464 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3465
3466 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3467
3468 let expected_val = test_utils::parse_function_details(
3469 r#"
3470 {
3471 worker-name: some("my-worker"),
3472 function-name: "amazon:shopping-cart/api2.{bar}",
3473 args0: "bar"
3474 }
3475 "#,
3476 );
3477
3478 assert_eq!(result.get_val().unwrap(), expected_val);
3479 }
3480
3481 #[test]
3482 async fn test_interpreter_durable_worker_7() {
3483 let expr = r#"
3484 let worker = instance("my-worker");
3485 let result = worker.baz("bar");
3486 result
3487 "#;
3488 let expr = Expr::from_text(expr).unwrap();
3489 let component_metadata = test_utils::get_metadata();
3490
3491 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3492
3493 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3494
3495 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3496
3497 let expected_val = test_utils::parse_function_details(
3498 r#"
3499 {
3500 worker-name: some("my-worker"),
3501 function-name: "wasi:clocks/monotonic-clock.{baz}",
3502 args0: "bar"
3503 }
3504 "#,
3505 );
3506
3507 assert_eq!(result.get_val().unwrap(), expected_val);
3508 }
3509
3510 #[test]
3511 async fn test_interpreter_durable_worker_8() {
3512 let expr = r#"
3513 let worker = instance("my-worker");
3514 let result = worker.qux("bar");
3515 result
3516 "#;
3517 let expr = Expr::from_text(expr).unwrap();
3518 let component_metadata = test_utils::get_metadata();
3519
3520 let compiled = compiler::compile(expr, &component_metadata)
3521 .unwrap_err()
3522 .to_string();
3523
3524 assert_eq!(
3525 compiled,
3526 "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()
3527 );
3528 }
3529
3530 #[test]
3531 async fn test_interpreter_durable_worker_9() {
3532 let expr = r#"
3533 let worker = instance("my-worker");
3534 let result = worker.qux[amazon:shopping-cart]("bar");
3535 result
3536 "#;
3537 let expr = Expr::from_text(expr).unwrap();
3538 let component_metadata = test_utils::get_metadata();
3539
3540 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3541
3542 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3543
3544 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3545
3546 let expected_val = test_utils::parse_function_details(
3547 r#"
3548 {
3549 worker-name: some("my-worker"),
3550 function-name: "amazon:shopping-cart/api1.{qux}",
3551 args0: "bar"
3552 }
3553 "#,
3554 );
3555
3556 assert_eq!(result.get_val().unwrap(), expected_val);
3557 }
3558
3559 #[test]
3560 async fn test_interpreter_durable_worker_10() {
3561 let expr = r#"
3562 let worker = instance("my-worker");
3563 let result = worker.qux[wasi:clocks]("bar");
3564 result
3565 "#;
3566 let expr = Expr::from_text(expr).unwrap();
3567 let component_metadata = test_utils::get_metadata();
3568
3569 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3570
3571 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3572
3573 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3574
3575 let expected_val = test_utils::parse_function_details(
3576 r#"
3577 {
3578 worker-name: some("my-worker"),
3579 function-name: "wasi:clocks/monotonic-clock.{qux}",
3580 args0: "bar"
3581 }
3582 "#,
3583 );
3584
3585 assert_eq!(result.get_val().unwrap(), expected_val);
3586 }
3587
3588 #[test]
3589 async fn test_interpreter_durable_worker_11() {
3590 let expr = r#"
3591 let worker = instance("my-worker");
3592 let invokes: list<u8> = [1, 2, 3, 4];
3593
3594 for i in invokes {
3595 yield worker.qux[wasi:clocks]("bar");
3596 };
3597
3598 "success"
3599 "#;
3600 let expr = Expr::from_text(expr).unwrap();
3601 let component_metadata = test_utils::get_metadata();
3602
3603 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3604
3605 let mut rib_interpreter =
3606 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3607
3608 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3609
3610 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3611 }
3612
3613 #[test]
3614 async fn test_interpreter_durable_worker_with_resource_0() {
3615 let expr = r#"
3616 let worker = instance("my-worker");
3617 worker.cart[golem:it]("bar")
3618 "#;
3619 let expr = Expr::from_text(expr).unwrap();
3620 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3621
3622 let compiled = compiler::compile(expr, &component_metadata)
3623 .unwrap_err()
3624 .to_string();
3625
3626 let expected = r#"
3627 error in the following rib found at line 3, column 17
3628 `cart("bar")`
3629 cause: program is invalid as it returns a resource constructor
3630 "#;
3631
3632 assert_eq!(compiled, strip_spaces(expected));
3633 }
3634
3635 #[test]
3638 async fn test_interpreter_durable_worker_with_resource_1() {
3639 let expr = r#"
3640 let worker = instance("my-worker");
3641 worker.cart[golem:it]("bar");
3642 "success"
3643 "#;
3644 let expr = Expr::from_text(expr).unwrap();
3645 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3646
3647 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3648
3649 let mut rib_interpreter =
3650 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3651
3652 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3653
3654 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3655 }
3656
3657 #[test]
3658 async fn test_interpreter_durable_worker_with_resource_2() {
3659 let expr = r#"
3660 let worker = instance("my-worker");
3661 let cart = worker.cart[golem:it]("bar");
3662 let result = cart.add-item({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3663 result
3664 "#;
3665 let expr = Expr::from_text(expr).unwrap();
3666 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3667
3668 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3669
3670 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
3671
3672 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3673
3674 let analysed_type = record(vec![
3675 field("worker-name", option(str())),
3676 field("function-name", str()),
3677 field(
3678 "args0",
3679 record(vec![
3680 field("product-id", str()),
3681 field("name", str()),
3682 field("price", f32()),
3683 field("quantity", u32()),
3684 ]),
3685 ),
3686 ]);
3687
3688 let expected_val = get_value_and_type(
3689 &analysed_type,
3690 r#"
3691 {
3692 worker-name: some("my-worker"),
3693 function-name: "golem:it/api.{cart(\"bar\").add-item}",
3694 args0: {product-id: "mac", name: "macbook", price: 1.0, quantity: 1}
3695 }
3696 "#,
3697 );
3698
3699 assert_eq!(result.get_val().unwrap(), expected_val);
3700 }
3701
3702 #[test]
3703 async fn test_interpreter_durable_worker_with_resource_3() {
3704 let expr = r#"
3705 let worker = instance("my-worker");
3706 let cart = worker.cart[golem:it]("bar");
3707 cart.add-items({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3708 "success"
3709 "#;
3710 let expr = Expr::from_text(expr).unwrap();
3711 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3712
3713 let compiled = compiler::compile(expr, &component_metadata)
3714 .unwrap_err()
3715 .to_string();
3716
3717 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());
3718 }
3719
3720 #[test]
3721 async fn test_interpreter_durable_worker_with_resource_4() {
3722 let expr = r#"
3723 let worker = instance("my-worker");
3724 let cart = worker.carts[golem:it]("bar");
3725 cart.add-item({product-id: "mac", name: "macbook", quantity: 1:u32, price: 1:f32});
3726 "success"
3727 "#;
3728 let expr = Expr::from_text(expr).unwrap();
3729 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3730
3731 let compiled = compiler::compile(expr, &component_metadata)
3732 .unwrap_err()
3733 .to_string();
3734
3735 assert_eq!(
3736 compiled,
3737 "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()
3738 );
3739 }
3740
3741 #[test]
3742 async fn test_interpreter_durable_worker_with_resource_5() {
3743 let expr = r#"
3745 let worker = instance();
3746 let cart = worker.cart[golem:it]("bar");
3747 cart.add-item({product-id: "mac", name: "macbook", quantity: 1, price: 1});
3748 "success"
3749 "#;
3750 let expr = Expr::from_text(expr).unwrap();
3751 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3752
3753 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3754
3755 let mut rib_interpreter =
3756 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3757
3758 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3759
3760 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3761 }
3762
3763 #[test]
3764 async fn test_interpreter_durable_worker_with_resource_6() {
3765 let expr = r#"
3767 let worker = instance();
3768 let cart = worker.cart[golem:it]("bar");
3769 cart.add-item({product-id: "mac", name: 1, quantity: 1, price: 1});
3770 "success"
3771 "#;
3772 let expr = Expr::from_text(expr).unwrap();
3773 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3774
3775 let error_message = compiler::compile(expr, &component_metadata)
3776 .unwrap_err()
3777 .to_string();
3778
3779 let expected = r#"
3780 error in the following rib found at line 4, column 31
3781 `{product-id: "mac", name: 1, quantity: 1, price: 1}`
3782 found within:
3783 `golem:it/api.{cart("bar").add-item}({product-id: "mac", name: 1, quantity: 1, price: 1})`
3784 cause: type mismatch at path: `name`. expected string
3785 invalid argument to the function `golem:it/api.{cart("bar").add-item}`
3786 "#;
3787
3788 assert_eq!(error_message, strip_spaces(expected));
3789 }
3790
3791 #[test]
3792 async fn test_interpreter_durable_worker_with_resource_7() {
3793 let expr = r#"
3794 let worker = instance("my-worker");
3795 let cart = worker.cart("bar");
3796 cart.add-item({product-id: "mac", name: "apple", quantity: 1, price: 1});
3797 "success"
3798 "#;
3799 let expr = Expr::from_text(expr).unwrap();
3800 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3801
3802 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3803
3804 let mut rib_interpreter =
3805 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3806
3807 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3808
3809 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3810 }
3811
3812 #[test]
3813 async fn test_interpreter_durable_worker_with_resource_8() {
3814 let expr = r#"
3815 let worker = instance("my-worker");
3816 let a = "mac";
3817 let b = "apple";
3818 let c = 1;
3819 let d = 1;
3820 let cart = worker.cart("bar");
3821 cart.add-item({product-id: a, name: b, quantity: c, price: d});
3822 "success"
3823 "#;
3824 let expr = Expr::from_text(expr).unwrap();
3825 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3826
3827 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3828
3829 let mut rib_interpreter =
3830 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3831
3832 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3833
3834 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3835 }
3836
3837 #[test]
3838 async fn test_interpreter_durable_worker_with_resource_9() {
3839 let expr = r#"
3840 let worker = instance("my-worker");
3841 let a = "mac";
3842 let b = "apple";
3843 let c = 1;
3844 let d = 1;
3845 let cart = worker.cart("bar");
3846 cart.add-item({product-id: a, name: b, quantity: c, price: d});
3847 cart.remove-item(a);
3848 cart.update-item-quantity(a, 2);
3849 let result = cart.get-cart-contents();
3850 cart.drop();
3851 result
3852 "#;
3853 let expr = Expr::from_text(expr).unwrap();
3854 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3855
3856 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3857
3858 let mut rib_interpreter =
3859 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3860
3861 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3862
3863 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3864 }
3865
3866 #[test]
3867 async fn test_interpreter_durable_worker_with_resource_10() {
3868 let expr = r#"
3869 let my_worker = "my-worker";
3870 let worker = instance(my_worker);
3871 let a = "mac";
3872 let b = "apple";
3873 let c = 1;
3874 let d = 1;
3875 let cart = worker.cart("bar");
3876 cart.add-item({product-id: a, name: b, quantity: c, price: d});
3877 cart.remove-item(a);
3878 cart.update-item-quantity(a, 2);
3879 let result = cart.get-cart-contents();
3880 cart.drop();
3881 result
3882 "#;
3883 let expr = Expr::from_text(expr).unwrap();
3884 let component_metadata = test_utils::get_metadata_with_resource_with_params();
3885
3886 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3887
3888 let mut rib_interpreter =
3889 test_utils::interpreter_static_response(&"success".into_value_and_type(), None);
3890
3891 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3892
3893 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3894 }
3895
3896 #[test]
3897 async fn test_interpreter_durable_worker_with_resource_11() {
3898 let expr = r#"
3899 let worker = instance(request.path.user-id: string);
3900 let result = worker.qux[amazon:shopping-cart]("bar");
3901 result
3902 "#;
3903 let expr = Expr::from_text(expr).unwrap();
3904 let component_metadata = test_utils::get_metadata();
3905
3906 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3907
3908 let mut input = HashMap::new();
3909
3910 let rib_input_key = "request";
3912 let rib_input_value = ValueAndType::new(
3913 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
3914 record(vec![field("path", record(vec![field("user-id", str())]))]),
3915 );
3916
3917 input.insert(rib_input_key.to_string(), rib_input_value);
3918
3919 let rib_input = RibInput::new(input);
3920
3921 let mut rib_interpreter = test_utils::interpreter_static_response(
3922 &"success".into_value_and_type(),
3923 Some(rib_input),
3924 );
3925
3926 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3927
3928 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
3929 }
3930
3931 #[test]
3932 async fn test_interpreter_durable_worker_with_resource_12() {
3933 let expr = r#"
3934 let user_id1: string = request.path.user-id;
3935 let user_id2: string = request.path.user-id;
3936 let worker1 = instance(user_id1);
3937 let result1 = worker1.qux[amazon:shopping-cart]("bar");
3938 let worker2 = instance(user_id2);
3939 let result2 = worker2.qux[amazon:shopping-cart]("bar");
3940 user_id2
3941 "#;
3942 let expr = Expr::from_text(expr).unwrap();
3943 let component_metadata = test_utils::get_metadata();
3944
3945 let compiled = compiler::compile(expr, &component_metadata).unwrap();
3946
3947 let mut input = HashMap::new();
3948
3949 let rib_input_key = "request";
3950 let rib_input_value = ValueAndType::new(
3951 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
3952 record(vec![field("path", record(vec![field("user-id", str())]))]),
3953 );
3954
3955 input.insert(rib_input_key.to_string(), rib_input_value);
3956
3957 let rib_input = RibInput::new(input);
3958
3959 let mut rib_interpreter = test_utils::interpreter_static_response(
3960 &"success".into_value_and_type(),
3961 Some(rib_input),
3962 );
3963
3964 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
3965
3966 assert_eq!(result.get_val().unwrap(), "user".into_value_and_type());
3967 }
3968
3969 #[test]
3970 async fn test_interpreter_durable_worker_with_resource_13() {
3971 let expr = r#"
3972 let worker1 = instance("foo");
3973 let result = worker.qux[amazon:shopping-cart]("bar");
3974 "success"
3975 "#;
3976 let expr = Expr::from_text(expr).unwrap();
3977 let component_metadata = test_utils::get_metadata();
3978
3979 let error = compiler::compile(expr, &component_metadata)
3980 .unwrap_err()
3981 .to_string();
3982
3983 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");
3984 }
3985
3986 #[test]
3987 async fn test_interpreter_durable_worker_with_resource_14() {
3988 let expr = r#"
3989 let worker = instance(1: u32);
3990 let result = worker.qux[amazon:shopping-cart]("bar");
3991 "success"
3992 "#;
3993 let expr = Expr::from_text(expr).unwrap();
3994 let component_metadata = test_utils::get_metadata();
3995
3996 let error = compiler::compile(expr, &component_metadata)
3997 .unwrap_err()
3998 .to_string();
3999
4000 let expected = r#"
4001 error in the following rib found at line 2, column 39
4002 `1: u32`
4003 cause: expected string, found u32
4004 "#;
4005
4006 assert_eq!(error, strip_spaces(expected));
4007 }
4008
4009 #[test]
4010 async fn test_interpreter_durable_worker_with_resource_15() {
4011 let expr = r#"
4012 let worker = instance("my-worker-name");
4013 let result = worker.qux[amazon:shopping-cart]("param1");
4014 result
4015 "#;
4016 let expr = Expr::from_text(expr).unwrap();
4017 let component_metadata = test_utils::get_metadata();
4018
4019 let compiled = compiler::compile(expr, &component_metadata).unwrap();
4020
4021 let mut rib_interpreter = test_utils::interpreter_worker_details_response(None);
4022
4023 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4024
4025 let result_val = result.get_val().unwrap();
4026
4027 let expected_val = test_utils::parse_function_details(
4028 r#"
4029 {
4030 worker-name: some("my-worker-name"),
4031 function-name: "amazon:shopping-cart/api1.{qux}",
4032 args0: "param1"
4033 }
4034 "#,
4035 );
4036
4037 assert_eq!(result_val, expected_val);
4038 }
4039
4040 #[test]
4041 async fn test_interpreter_durable_worker_with_resource_16() {
4042 let expr = r#"
4043 let x = request.path.user-id;
4044 let worker = instance(x);
4045 let cart = worker.cart("bar");
4046 let result = cart.get-cart-contents();
4047 result
4048 "#;
4049 let expr = Expr::from_text(expr).unwrap();
4050 let component_metadata = test_utils::get_metadata_with_resource_with_params();
4051
4052 let compiled = compiler::compile(expr, &component_metadata).unwrap();
4053
4054 let mut input = HashMap::new();
4055
4056 let rib_input_key = "request";
4057 let rib_input_value = ValueAndType::new(
4058 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4059 record(vec![field("path", record(vec![field("user-id", str())]))]),
4060 );
4061
4062 input.insert(rib_input_key.to_string(), rib_input_value);
4063
4064 let rib_input = RibInput::new(input);
4065
4066 let mut rib_interpreter = test_utils::interpreter_worker_details_response(Some(rib_input));
4067
4068 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4069
4070 let result_val = result.get_val().unwrap();
4071
4072 let expected_analysed_type = record(vec![
4073 field("worker-name", option(str())),
4074 field("function-name", str()),
4075 ]);
4076
4077 let expected_val = parse_value_and_type(
4078 &expected_analysed_type,
4079 r#"
4080 {
4081 worker-name: some("user"),
4082 function-name: "golem:it/api.{cart(\"bar\").get-cart-contents}",
4083 }
4084 "#,
4085 )
4086 .unwrap();
4087
4088 assert_eq!(result_val, expected_val)
4089 }
4090
4091 #[test]
4092 async fn test_interpreter_durable_worker_with_resource_17() {
4093 let expr = r#"
4094 let x: string = request.path.user-id;
4095 let min: u8 = 1;
4096 let max: u8 = 3;
4097 let result = for i in min..=max {
4098 let worker = instance("my-worker");
4099 let cart = worker.cart("bar");
4100 yield cart.get-cart-contents();
4101 };
4102 result
4103 "#;
4104 let expr = Expr::from_text(expr).unwrap();
4105 let component_metadata = test_utils::get_metadata_with_resource_with_params();
4106
4107 let compiled = compiler::compile(expr, &component_metadata).unwrap();
4108
4109 let mut input = HashMap::new();
4110
4111 let rib_input_key = "request";
4112 let rib_input_value = ValueAndType::new(
4113 Value::Record(vec![Value::Record(vec![Value::String("user".to_string())])]),
4114 record(vec![field("path", record(vec![field("user-id", str())]))]),
4115 );
4116
4117 input.insert(rib_input_key.to_string(), rib_input_value);
4118
4119 let rib_input = RibInput::new(input);
4120
4121 let mut rib_interpreter = test_utils::interpreter_worker_details_response(Some(rib_input));
4122
4123 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4124
4125 let result_val = result.get_val().unwrap().value;
4126
4127 let worker_name = Some("my-worker".to_string()).into_value();
4128 let function_name = "golem:it/api.{cart(\"bar\").get-cart-contents}"
4129 .to_string()
4130 .into_value();
4131
4132 let expected = Value::List(vec![
4133 Value::Record(vec![worker_name.clone(), function_name.clone()]),
4134 Value::Record(vec![worker_name.clone(), function_name.clone()]),
4135 Value::Record(vec![worker_name.clone(), function_name.clone()]),
4136 ]);
4137
4138 assert_eq!(result_val, expected);
4139 }
4140
4141 #[test]
4142 async fn test_interpreter_durable_worker_with_resource_18() {
4143 let expr = r#"
4144
4145 let initial = 1: u64;
4146 let final = 5: u64;
4147 let range = initial..final;
4148 let worker = instance("my-worker");
4149 let cart = worker.cart[golem:it]("bar");
4150
4151 for i in range {
4152 yield cart.add-item(request.body);
4153 };
4154
4155 "success"
4156 "#;
4157 let expr = Expr::from_text(expr).unwrap();
4158 let component_metadata = test_utils::get_metadata_with_resource_with_params();
4159
4160 let compiled = compiler::compile(expr, &component_metadata).unwrap();
4161
4162 let mut input = HashMap::new();
4163
4164 let rib_input_key = "request";
4165 let rib_input_value = ValueAndType::new(
4166 Value::Record(vec![Value::Record(vec![
4167 Value::String("mac-book".to_string()),
4168 Value::String("mac".to_string()),
4169 Value::U32(1),
4170 Value::F32(1.0),
4171 ])]),
4172 record(vec![field(
4173 "body",
4174 record(vec![
4175 field("name", str()),
4176 field("product-id", str()),
4177 field("quantity", u32()),
4178 field("price", f32()),
4179 ]),
4180 )]),
4181 );
4182
4183 input.insert(rib_input_key.to_string(), rib_input_value);
4184
4185 let rib_input = RibInput::new(input);
4186
4187 let mut rib_interpreter = test_utils::interpreter_static_response(
4188 &"success".into_value_and_type(),
4189 Some(rib_input),
4190 );
4191
4192 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4193
4194 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4195 }
4196
4197 #[test]
4198 async fn test_interpreter_durable_worker_with_resource_19() {
4199 let expr = r#"
4200
4201 let initial = 1: u64;
4202 let final = 5: u64;
4203 let range = initial..final;
4204
4205 for i in range {
4206 let worker = instance("my-worker");
4207 let cart = worker.cart[golem:it]("bar");
4208 yield cart.add-item(request.body);
4209 };
4210
4211 "success"
4212 "#;
4213 let expr = Expr::from_text(expr).unwrap();
4214 let component_metadata = test_utils::get_metadata_with_resource_with_params();
4215
4216 let compiled = compiler::compile(expr, &component_metadata).unwrap();
4217
4218 let mut input = HashMap::new();
4219
4220 let rib_input_key = "request";
4221 let rib_input_value = ValueAndType::new(
4222 Value::Record(vec![Value::Record(vec![
4223 Value::String("mac-book".to_string()),
4224 Value::String("mac".to_string()),
4225 Value::U32(1),
4226 Value::F32(1.0),
4227 ])]),
4228 record(vec![field(
4229 "body",
4230 record(vec![
4231 field("name", str()),
4232 field("product-id", str()),
4233 field("quantity", u32()),
4234 field("price", f32()),
4235 ]),
4236 )]),
4237 );
4238
4239 input.insert(rib_input_key.to_string(), rib_input_value);
4240
4241 let rib_input = RibInput::new(input);
4242
4243 let mut rib_interpreter = test_utils::interpreter_static_response(
4244 &"success".into_value_and_type(),
4245 Some(rib_input),
4246 );
4247
4248 let result = rib_interpreter.run(compiled.byte_code).await.unwrap();
4249
4250 assert_eq!(result.get_val().unwrap(), "success".into_value_and_type());
4251 }
4252
4253 mod test_utils {
4254 use crate::interpreter::rib_interpreter::Interpreter;
4255 use crate::{
4256 EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, RibFunctionInvoke, RibInput,
4257 };
4258 use async_trait::async_trait;
4259 use golem_wasm_ast::analysis::analysed_type::{
4260 case, f32, field, handle, list, option, r#enum, record, result, str, tuple, u32, u64,
4261 unit_case, variant,
4262 };
4263 use golem_wasm_ast::analysis::{
4264 AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedFunctionResult,
4265 AnalysedInstance, AnalysedResourceId, AnalysedResourceMode, AnalysedType,
4266 };
4267 use golem_wasm_rpc::{IntoValueAndType, Value, ValueAndType};
4268 use std::sync::Arc;
4269
4270 pub(crate) fn strip_spaces(input: &str) -> String {
4271 let lines = input.lines();
4272
4273 let first_line = lines
4274 .clone()
4275 .find(|line| !line.trim().is_empty())
4276 .unwrap_or("");
4277 let margin_width = first_line.chars().take_while(|c| c.is_whitespace()).count();
4278
4279 let result = lines
4280 .map(|line| {
4281 if line.trim().is_empty() {
4282 String::new()
4283 } else {
4284 line[margin_width..].to_string()
4285 }
4286 })
4287 .collect::<Vec<String>>()
4288 .join("\n");
4289
4290 result.strip_prefix("\n").unwrap_or(&result).to_string()
4291 }
4292
4293 pub(crate) fn get_analysed_type_variant() -> AnalysedType {
4294 variant(vec![
4295 case("register-user", u64()),
4296 case("process-user", str()),
4297 unit_case("validate"),
4298 ])
4299 }
4300
4301 pub(crate) fn get_analysed_type_record() -> AnalysedType {
4302 record(vec![
4303 field(
4304 "request",
4305 record(vec![field("path", record(vec![field("user", str())]))]),
4306 ),
4307 field("y", str()),
4308 ])
4309 }
4310
4311 pub(crate) fn get_analysed_type_result() -> AnalysedType {
4312 result(u64(), str())
4313 }
4314
4315 pub(crate) fn get_analysed_type_enum() -> AnalysedType {
4316 r#enum(&["prod", "dev", "test"])
4317 }
4318
4319 pub(crate) fn get_analysed_typ_str() -> AnalysedType {
4320 str()
4321 }
4322
4323 pub(crate) fn get_analysed_typ_u64() -> AnalysedType {
4324 u64()
4325 }
4326
4327 pub(crate) fn get_analysed_type_tuple() -> AnalysedType {
4328 tuple(vec![
4329 get_analysed_typ_u64(),
4330 get_analysed_type_result(),
4331 get_analysed_typ_str(),
4332 get_analysed_type_record(),
4333 get_analysed_type_variant(),
4334 get_analysed_type_variant(),
4335 get_analysed_type_variant(),
4336 get_analysed_type_enum(),
4337 get_analysed_type_enum(),
4338 get_analysed_type_enum(),
4339 ])
4340 }
4341
4342 pub(crate) fn get_component_metadata(
4343 function_name: &str,
4344 input_types: Vec<AnalysedType>,
4345 output: Option<AnalysedType>,
4346 ) -> Vec<AnalysedExport> {
4347 let analysed_function_parameters = input_types
4348 .into_iter()
4349 .enumerate()
4350 .map(|(index, typ)| AnalysedFunctionParameter {
4351 name: format!("param{}", index),
4352 typ,
4353 })
4354 .collect();
4355
4356 let results = if let Some(output) = output {
4357 vec![AnalysedFunctionResult {
4358 name: None,
4359 typ: output,
4360 }]
4361 } else {
4362 vec![]
4364 };
4365
4366 vec![AnalysedExport::Function(AnalysedFunction {
4367 name: function_name.to_string(),
4368 parameters: analysed_function_parameters,
4369 results,
4370 })]
4371 }
4372
4373 pub(crate) fn get_metadata_with_resource_with_params() -> Vec<AnalysedExport> {
4374 get_metadata_with_resource(vec![AnalysedFunctionParameter {
4375 name: "user-id".to_string(),
4376 typ: str(),
4377 }])
4378 }
4379
4380 pub(crate) fn get_metadata_with_resource_without_params() -> Vec<AnalysedExport> {
4381 get_metadata_with_resource(vec![])
4382 }
4383
4384 pub(crate) fn get_metadata() -> Vec<AnalysedExport> {
4385 let analysed_function_in_api1 = AnalysedFunction {
4387 name: "foo".to_string(),
4388 parameters: vec![AnalysedFunctionParameter {
4389 name: "arg1".to_string(),
4390 typ: str(),
4391 }],
4392 results: vec![AnalysedFunctionResult {
4393 name: None,
4394 typ: str(),
4395 }],
4396 };
4397
4398 let analysed_function_in_api1_and_api2 = AnalysedFunction {
4400 name: "bar".to_string(),
4401 parameters: vec![AnalysedFunctionParameter {
4402 name: "arg1".to_string(),
4403 typ: str(),
4404 }],
4405 results: vec![AnalysedFunctionResult {
4406 name: None,
4407 typ: str(),
4408 }],
4409 };
4410
4411 let analysed_function_in_wasi = AnalysedFunction {
4413 name: "baz".to_string(),
4414 parameters: vec![AnalysedFunctionParameter {
4415 name: "arg1".to_string(),
4416 typ: str(),
4417 }],
4418 results: vec![AnalysedFunctionResult {
4419 name: None,
4420 typ: str(),
4421 }],
4422 };
4423
4424 let analysed_function_in_wasi_and_api1 = AnalysedFunction {
4426 name: "qux".to_string(),
4427 parameters: vec![AnalysedFunctionParameter {
4428 name: "arg1".to_string(),
4429 typ: str(),
4430 }],
4431 results: vec![AnalysedFunctionResult {
4432 name: None,
4433 typ: str(),
4434 }],
4435 };
4436
4437 let analysed_export1 = AnalysedExport::Instance(AnalysedInstance {
4438 name: "amazon:shopping-cart/api1".to_string(),
4439 functions: vec![
4440 analysed_function_in_api1,
4441 analysed_function_in_api1_and_api2.clone(),
4442 analysed_function_in_wasi_and_api1.clone(),
4443 ],
4444 });
4445
4446 let analysed_export2 = AnalysedExport::Instance(AnalysedInstance {
4447 name: "amazon:shopping-cart/api2".to_string(),
4448 functions: vec![analysed_function_in_api1_and_api2],
4449 });
4450
4451 let analysed_export3 = AnalysedExport::Instance(AnalysedInstance {
4452 name: "wasi:clocks/monotonic-clock".to_string(),
4453 functions: vec![
4454 analysed_function_in_wasi,
4455 analysed_function_in_wasi_and_api1,
4456 ],
4457 });
4458
4459 vec![analysed_export1, analysed_export2, analysed_export3]
4460 }
4461
4462 fn get_metadata_with_resource(
4463 resource_constructor_params: Vec<AnalysedFunctionParameter>,
4464 ) -> Vec<AnalysedExport> {
4465 let instance = AnalysedExport::Instance(AnalysedInstance {
4466 name: "golem:it/api".to_string(),
4467 functions: vec![
4468 AnalysedFunction {
4469 name: "[constructor]cart".to_string(),
4470 parameters: resource_constructor_params,
4471 results: vec![AnalysedFunctionResult {
4472 name: None,
4473 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
4474 }],
4475 },
4476 AnalysedFunction {
4477 name: "[method]cart.add-item".to_string(),
4478 parameters: vec![
4479 AnalysedFunctionParameter {
4480 name: "self".to_string(),
4481 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4482 },
4483 AnalysedFunctionParameter {
4484 name: "item".to_string(),
4485 typ: record(vec![
4486 field("product-id", str()),
4487 field("name", str()),
4488 field("price", f32()),
4489 field("quantity", u32()),
4490 ]),
4491 },
4492 ],
4493 results: vec![],
4494 },
4495 AnalysedFunction {
4496 name: "[method]cart.remove-item".to_string(),
4497 parameters: vec![
4498 AnalysedFunctionParameter {
4499 name: "self".to_string(),
4500 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4501 },
4502 AnalysedFunctionParameter {
4503 name: "product-id".to_string(),
4504 typ: str(),
4505 },
4506 ],
4507 results: vec![],
4508 },
4509 AnalysedFunction {
4510 name: "[method]cart.update-item-quantity".to_string(),
4511 parameters: vec![
4512 AnalysedFunctionParameter {
4513 name: "self".to_string(),
4514 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4515 },
4516 AnalysedFunctionParameter {
4517 name: "product-id".to_string(),
4518 typ: str(),
4519 },
4520 AnalysedFunctionParameter {
4521 name: "quantity".to_string(),
4522 typ: u32(),
4523 },
4524 ],
4525 results: vec![],
4526 },
4527 AnalysedFunction {
4528 name: "[method]cart.checkout".to_string(),
4529 parameters: vec![AnalysedFunctionParameter {
4530 name: "self".to_string(),
4531 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4532 }],
4533 results: vec![AnalysedFunctionResult {
4534 name: None,
4535 typ: variant(vec![
4536 case("error", str()),
4537 case("success", record(vec![field("order-id", str())])),
4538 ]),
4539 }],
4540 },
4541 AnalysedFunction {
4542 name: "[method]cart.get-cart-contents".to_string(),
4543 parameters: vec![AnalysedFunctionParameter {
4544 name: "self".to_string(),
4545 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4546 }],
4547 results: vec![AnalysedFunctionResult {
4548 name: None,
4549 typ: list(record(vec![
4550 field("product-id", str()),
4551 field("name", str()),
4552 field("price", f32()),
4553 field("quantity", u32()),
4554 ])),
4555 }],
4556 },
4557 AnalysedFunction {
4558 name: "[method]cart.merge-with".to_string(),
4559 parameters: vec![
4560 AnalysedFunctionParameter {
4561 name: "self".to_string(),
4562 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4563 },
4564 AnalysedFunctionParameter {
4565 name: "other-cart".to_string(),
4566 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Borrowed),
4567 },
4568 ],
4569 results: vec![],
4570 },
4571 AnalysedFunction {
4572 name: "[drop]cart".to_string(),
4573 parameters: vec![AnalysedFunctionParameter {
4574 name: "self".to_string(),
4575 typ: handle(AnalysedResourceId(0), AnalysedResourceMode::Owned),
4576 }],
4577 results: vec![],
4578 },
4579 ],
4580 });
4581
4582 vec![instance]
4583 }
4584
4585 pub(crate) fn get_value_and_type(
4586 analysed_type: &AnalysedType,
4587 wasm_wave_str: &str,
4588 ) -> ValueAndType {
4589 golem_wasm_rpc::parse_value_and_type(analysed_type, wasm_wave_str).unwrap()
4590 }
4591
4592 pub(crate) fn interpreter_static_response(
4595 result_value: &ValueAndType,
4596 input: Option<RibInput>,
4597 ) -> Interpreter {
4598 let value = result_value.clone();
4599
4600 let invoke = Arc::new(TestInvoke1 { value });
4601
4602 Interpreter {
4603 input: input.unwrap_or_default(),
4604 invoke,
4605 custom_stack: None,
4606 custom_env: None,
4607 }
4608 }
4609
4610 pub(crate) fn interpreter_worker_details_response(
4616 rib_input: Option<RibInput>,
4617 ) -> Interpreter {
4618 let invoke: Arc<dyn RibFunctionInvoke + Send + Sync> = Arc::new(TestInvoke2);
4619
4620 Interpreter {
4621 input: rib_input.unwrap_or_default(),
4622 invoke,
4623 custom_stack: None,
4624 custom_env: None,
4625 }
4626 }
4627
4628 pub(crate) fn parse_function_details(input: &str) -> ValueAndType {
4629 let analysed_type = record(vec![
4630 field("worker-name", option(str())),
4631 field("function-name", str()),
4632 field("args0", str()),
4633 ]);
4634
4635 get_value_and_type(&analysed_type, input)
4636 }
4637
4638 struct TestInvoke1 {
4639 value: ValueAndType,
4640 }
4641
4642 #[async_trait]
4643 impl RibFunctionInvoke for TestInvoke1 {
4644 async fn invoke(
4645 &self,
4646 _worker_name: Option<EvaluatedWorkerName>,
4647 _fqn: EvaluatedFqFn,
4648 _args: EvaluatedFnArgs,
4649 ) -> Result<ValueAndType, String> {
4650 let value = self.value.clone();
4651 Ok(ValueAndType::new(
4652 Value::Tuple(vec![value.value]),
4653 tuple(vec![value.typ]),
4654 ))
4655 }
4656 }
4657
4658 struct TestInvoke2;
4659
4660 #[async_trait]
4661 impl RibFunctionInvoke for TestInvoke2 {
4662 async fn invoke(
4663 &self,
4664 worker_name: Option<EvaluatedWorkerName>,
4665 function_name: EvaluatedFqFn,
4666 args: EvaluatedFnArgs,
4667 ) -> Result<ValueAndType, String> {
4668 let worker_name = worker_name.map(|x| x.0);
4669
4670 let function_name = function_name.0.into_value_and_type();
4671
4672 let args = args.0;
4673
4674 let mut arg_types = vec![];
4675
4676 for (index, value_and_type) in args.iter().enumerate() {
4677 let name = format!("args{}", index);
4678 let value = value_and_type.typ.clone();
4679 arg_types.push(field(name.as_str(), value));
4680 }
4681
4682 let mut analysed_type_pairs = vec![];
4683 analysed_type_pairs.push(field("worker-name", option(str())));
4684 analysed_type_pairs.push(field("function-name", str()));
4685 analysed_type_pairs.extend(arg_types);
4686
4687 let mut values = vec![];
4688
4689 values.push(Value::Option(
4690 worker_name.map(|x| Box::new(Value::String(x))),
4691 ));
4692 values.push(function_name.value);
4693
4694 for arg_value in args {
4695 values.push(arg_value.value);
4696 }
4697
4698 let value = ValueAndType::new(
4699 Value::Tuple(vec![Value::Record(values)]),
4700 tuple(vec![record(analysed_type_pairs)]),
4701 );
4702 Ok(value)
4703 }
4704 }
4705 }
4706}