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