1use crate::{
2 global::protocol_structures::instructions::*,
3 libs::core::{CoreLibPointerId, get_core_lib_value},
4 runtime::{
5 RuntimeInternal,
6 execution::{
7 context::{ExecutionMode, RemoteExecutionContext},
8 execution_loop::interrupts::{
9 ExternalExecutionInterrupt, InterruptResult,
10 },
11 },
12 },
13 traits::apply::Apply,
14 values::value_container::ValueContainer,
15};
16
17use crate::{
18 prelude::*,
19 shared_values::{
20 pointer::PointerReferenceMutability,
21 pointer_address::{PointerAddress, ReferencedPointerAddress},
22 },
23};
24use core::{result::Result, unreachable};
25pub use errors::*;
26pub use execution_input::{ExecutionInput, ExecutionOptions};
27pub use memory_dump::*;
28
29pub mod context;
30mod errors;
31mod execution_input;
32pub mod execution_loop;
33pub mod macros;
34mod memory_dump;
35
36#[cfg(all(test, feature = "std"))]
37mod test_remote_execution;
38
39pub fn execute_dxb_sync(
40 input: ExecutionInput,
41) -> Result<Option<ValueContainer>, ExecutionError> {
42 let runtime_internal = input.runtime.clone();
43 let (interrupt_provider, execution_loop) = input.execution_loop();
44
45 for output in execution_loop {
46 match output? {
47 ExternalExecutionInterrupt::Result(result) => return Ok(result),
48 ExternalExecutionInterrupt::GetReferenceToRemotePointer(
49 address,
50 mutability,
51 ) => interrupt_provider.provide_result(
52 InterruptResult::ResolvedValue(get_remote_pointer_value(
53 &runtime_internal,
54 address,
55 mutability,
56 )?),
57 ),
58 ExternalExecutionInterrupt::GetReferenceToLocalPointer(address) => {
59 interrupt_provider.provide_result(
61 InterruptResult::ResolvedValue(get_local_pointer_value(
62 &runtime_internal,
63 address,
64 )?),
65 );
66 }
67 ExternalExecutionInterrupt::GetReferenceInternalPointer(
68 address,
69 ) => {
70 interrupt_provider.provide_result(
71 InterruptResult::ResolvedValue(Some(
72 get_internal_pointer_value(&runtime_internal, address)?,
73 )),
74 );
75 }
76 ExternalExecutionInterrupt::Apply(callee, args) => {
77 let res = handle_apply(&callee, &args)?;
78 interrupt_provider
79 .provide_result(InterruptResult::ResolvedValue(res));
80 }
81 _ => return Err(ExecutionError::RequiresAsyncExecution),
82 }
83 }
84
85 Err(ExecutionError::RequiresAsyncExecution)
86}
87
88pub async fn execute_dxb(
89 input: ExecutionInput<'_>,
90) -> Result<Option<ValueContainer>, ExecutionError> {
91 let runtime_internal = input.runtime.clone();
92 let (interrupt_provider, execution_loop) = input.execution_loop();
93
94 for output in execution_loop {
95 match output? {
96 ExternalExecutionInterrupt::Result(result) => return Ok(result),
97 ExternalExecutionInterrupt::GetReferenceToRemotePointer(
98 address,
99 mutability,
100 ) => {
101 interrupt_provider.provide_result(
102 InterruptResult::ResolvedValue(get_remote_pointer_value(
103 &runtime_internal,
104 address,
105 mutability,
106 )?),
107 );
108 }
109 ExternalExecutionInterrupt::GetReferenceToLocalPointer(address) => {
110 interrupt_provider.provide_result(
112 InterruptResult::ResolvedValue(get_local_pointer_value(
113 &runtime_internal,
114 address,
115 )?),
116 );
117 }
118 ExternalExecutionInterrupt::GetReferenceInternalPointer(
119 address,
120 ) => {
121 interrupt_provider.provide_result(
122 InterruptResult::ResolvedValue(Some(
123 get_internal_pointer_value(&runtime_internal, address)?,
124 )),
125 );
126 }
127 ExternalExecutionInterrupt::RemoteExecution(receivers, body) => {
128 let receiver_endpoint =
131 receivers.to_value().borrow().cast_to_endpoint().unwrap();
132 let mut remote_execution_context = RemoteExecutionContext::new(
133 receiver_endpoint,
134 ExecutionMode::Static,
135 );
136 let res = RuntimeInternal::execute_remote(
137 runtime_internal.clone(),
138 &mut remote_execution_context,
139 body,
140 )
141 .await?;
142 interrupt_provider
143 .provide_result(InterruptResult::ResolvedValue(res));
144 }
145 ExternalExecutionInterrupt::Apply(callee, args) => {
146 let res = handle_apply(&callee, &args)?;
147 interrupt_provider
148 .provide_result(InterruptResult::ResolvedValue(res));
149 }
150 }
151 }
152
153 unreachable!("Execution loop should always return a result");
154}
155
156fn handle_apply(
157 callee: &ValueContainer,
158 args: &[ValueContainer],
159) -> Result<Option<ValueContainer>, ExecutionError> {
160 Ok(if args.len() == 1 {
163 callee.apply_single(&args[0])?
164 } else {
165 callee.apply(args)?
166 })
167}
168
169fn get_remote_pointer_value(
170 runtime_internal: &Rc<RuntimeInternal>,
171 address: RawRemotePointerAddress,
172 _mutability: PointerReferenceMutability,
173) -> Result<Option<ValueContainer>, ExecutionError> {
174 let memory = runtime_internal.memory.borrow();
175 let resolved_address =
176 memory.get_pointer_address_from_raw_full_address(address);
177 Ok(memory
180 .get_reference(&resolved_address)
181 .map(|r| ValueContainer::Shared(r.clone())))
182}
183
184fn get_internal_pointer_value(
185 runtime_internal: &Rc<RuntimeInternal>,
186 address: RawInternalPointerAddress,
187) -> Result<ValueContainer, ExecutionError> {
188 if let Ok(core_lib_id) =
190 get_internal_pointer_value_from_memory(runtime_internal, &address)
191 {
192 return Ok(core_lib_id);
193 }
194
195 let core_lib_id = CoreLibPointerId::try_from(&PointerAddress::Referenced(
196 ReferencedPointerAddress::Internal(address.id),
197 ));
198 core_lib_id
199 .map_err(|_| ExecutionError::ReferenceNotFound)
200 .map(|id| {
201 get_core_lib_value(id).ok_or(ExecutionError::ReferenceNotFound)
202 })?
203}
204
205fn get_internal_pointer_value_from_memory(
206 runtime_internal: &Rc<RuntimeInternal>,
207 address: &RawInternalPointerAddress,
208) -> Result<ValueContainer, ExecutionError> {
209 let pointer_address = PointerAddress::Referenced(
210 ReferencedPointerAddress::Internal(address.id),
211 );
212 let memory = runtime_internal.memory.borrow();
213 if let Some(reference) = memory.get_reference(&pointer_address) {
214 Ok(ValueContainer::Shared(reference.clone()))
215 } else {
216 Err(ExecutionError::ReferenceNotFound)
217 }
218}
219
220fn get_local_pointer_value(
221 runtime_internal: &Rc<RuntimeInternal>,
222 address: RawLocalPointerAddress,
223) -> Result<Option<ValueContainer>, ExecutionError> {
224 Ok(runtime_internal
226 .memory
227 .borrow()
228 .get_reference(&PointerAddress::owned(address.id))
229 .map(|r| ValueContainer::Shared(r.clone())))
230}
231
232#[cfg(test)]
233#[cfg(feature = "compiler")]
234mod tests {
235 use super::*;
236 use crate::{
237 assert_structural_eq, assert_value_eq,
238 compiler::{CompileOptions, compile_script, scope::CompilationScope},
239 datex_list,
240 global::instruction_codes::InstructionCode,
241 libs::core::get_core_lib_type_reference,
242 runtime::{
243 RuntimeConfig, RuntimeRunner,
244 execution::{
245 context::{ExecutionContext, LocalExecutionContext},
246 execution_input::ExecutionOptions,
247 },
248 },
249 shared_values::shared_container::{
250 SharedContainer, SharedContainerMutability,
251 },
252 traits::{structural_eq::StructuralEq, value_eq::ValueEq},
253 values::{
254 core_value::CoreValue,
255 core_values::{
256 decimal::Decimal,
257 integer::{Integer, typed_integer::TypedInteger},
258 list::List,
259 map::Map,
260 },
261 },
262 };
263 use binrw::meta::EndianKind::Runtime;
264 use core::assert_matches;
265 use log::{debug, info};
266
267 fn execute_datex_script_debug(
268 datex_script: &str,
269 ) -> Option<ValueContainer> {
270 let (dxb, _) =
271 compile_script(datex_script, CompileOptions::default()).unwrap();
272 let context = ExecutionInput::new(
273 &dxb,
274 ExecutionOptions { verbose: true },
275 Rc::new(RuntimeInternal::stub()),
276 );
277 execute_dxb_sync(context).unwrap_or_else(|err| {
278 core::panic!("Execution failed: {err}");
279 })
280 }
281
282 fn execute_datex_script_debug_unbounded(
283 datex_script_parts: impl Iterator<Item = &'static str>,
284 ) -> impl Iterator<Item = Result<Option<ValueContainer>, ExecutionError>>
285 {
286 gen move {
287 let datex_script_parts = datex_script_parts.collect::<Vec<_>>();
288 let mut execution_context =
289 ExecutionContext::Local(LocalExecutionContext::new(
290 ExecutionMode::unbounded(),
291 Rc::new(RuntimeInternal::stub()),
292 ));
293 let mut compilation_scope =
294 CompilationScope::new(ExecutionMode::unbounded());
295
296 let len = datex_script_parts.len();
297 for (index, script_part) in
298 datex_script_parts.into_iter().enumerate()
299 {
300 if index == len - 1 {
302 compilation_scope.mark_as_last_execution();
303 }
304
305 let (dxb, new_compilation_scope) = compile_script(
306 script_part,
307 CompileOptions::new_with_scope(compilation_scope),
308 )
309 .unwrap();
310 compilation_scope = new_compilation_scope;
311 yield execution_context.execute_dxb_sync(&dxb)
312 }
313 }
314 }
315
316 fn assert_unbounded_input_matches_output(
317 input: Vec<&'static str>,
318 expected_output: Vec<Option<ValueContainer>>,
319 ) {
320 let input = input.into_iter();
321 let expected_output = expected_output.into_iter();
322 for (result, expected) in
323 execute_datex_script_debug_unbounded(input.into_iter())
324 .zip(expected_output.into_iter())
325 {
326 let result = result.unwrap();
327 assert_eq!(result, expected);
328 }
329 }
330
331 fn execute_datex_script_debug_with_error(
332 datex_script: &str,
333 ) -> Result<Option<ValueContainer>, ExecutionError> {
334 let (dxb, _) =
335 compile_script(datex_script, CompileOptions::default()).unwrap();
336 let context = ExecutionInput::new(
337 &dxb,
338 ExecutionOptions { verbose: true },
339 Rc::new(RuntimeInternal::stub()),
340 );
341 execute_dxb_sync(context)
342 }
343
344 fn execute_datex_script_debug_with_result(
345 datex_script: &str,
346 ) -> ValueContainer {
347 execute_datex_script_debug(datex_script).unwrap()
348 }
349
350 fn execute_dxb_debug(
351 dxb_body: &[u8],
352 ) -> Result<Option<ValueContainer>, ExecutionError> {
353 let context = ExecutionInput::new(
354 dxb_body,
355 ExecutionOptions { verbose: true },
356 Rc::new(RuntimeInternal::stub()),
357 );
358 execute_dxb_sync(context)
359 }
360
361 async fn execute_datex_script_with_runtime(
362 config: RuntimeConfig,
363 datex_script: &str,
364 ) -> Result<Option<ValueContainer>, ExecutionError> {
365 RuntimeRunner::new(config)
366 .run(async |runtime| {
367 let (dxb, _) =
368 compile_script(datex_script, CompileOptions::default())
369 .unwrap();
370 let context = ExecutionInput::new(
371 &dxb,
372 ExecutionOptions { verbose: true },
373 runtime.internal,
374 );
375 execute_dxb(context).await
376 })
377 .await
378 }
379
380 #[test]
381 fn empty_script() {
382 assert_eq!(execute_datex_script_debug(""), None);
383 }
384
385 #[test]
386 fn empty_script_semicolon() {
387 assert_eq!(execute_datex_script_debug(";;;"), None);
388 }
389
390 #[test]
391 fn single_value() {
392 assert_eq!(
393 execute_datex_script_debug_with_result("42"),
394 Integer::from(42i8).into()
395 );
396 }
397
398 #[test]
399 fn single_value_semicolon() {
400 assert_eq!(execute_datex_script_debug("42;"), None)
401 }
402
403 #[test]
404 fn is() {
405 let result = execute_datex_script_debug_with_result("1 is 1");
406 assert_eq!(result, false.into());
407 assert_structural_eq!(result, ValueContainer::from(false));
408 }
409
410 #[test]
411 fn equality() {
412 let result = execute_datex_script_debug_with_result("1 == 1");
413 assert_eq!(result, true.into());
414 assert_structural_eq!(result, ValueContainer::from(true));
415
416 let result = execute_datex_script_debug_with_result("1 == 2");
417 assert_eq!(result, false.into());
418 assert_structural_eq!(result, ValueContainer::from(false));
419
420 let result = execute_datex_script_debug_with_result("1 != 2");
421 assert_eq!(result, true.into());
422 assert_structural_eq!(result, ValueContainer::from(true));
423
424 let result = execute_datex_script_debug_with_result("1 != 1");
425 assert_eq!(result, false.into());
426 assert_structural_eq!(result, ValueContainer::from(false));
427 let result = execute_datex_script_debug_with_result("1 === 1");
428 assert_eq!(result, true.into());
429
430 assert_structural_eq!(result, ValueContainer::from(true));
431 let result = execute_datex_script_debug_with_result("1 !== 2");
432 assert_eq!(result, true.into());
433 assert_structural_eq!(result, ValueContainer::from(true));
434
435 let result = execute_datex_script_debug_with_result("1 !== 1");
436 assert_eq!(result, false.into());
437 assert_structural_eq!(result, ValueContainer::from(false));
438 }
439
440 #[test]
441 fn single_value_scope() {
442 let result = execute_datex_script_debug_with_result("(42)");
443 assert_eq!(result, Integer::from(42i8).into());
444 assert_structural_eq!(result, ValueContainer::from(42_u128));
445 }
446
447 #[test]
448 fn add() {
449 let result = execute_datex_script_debug_with_result("1 + 2");
450 assert_eq!(result, Integer::from(3i8).into());
451 assert_structural_eq!(result, ValueContainer::from(3i8));
452 }
453
454 #[test]
455 fn nested_scope() {
456 let result = execute_datex_script_debug_with_result("1 + (2 + 3)");
457 assert_eq!(result, Integer::from(6i8).into());
458 }
459
460 #[test]
461 fn empty_list() {
462 let result = execute_datex_script_debug_with_result("[]");
463 let list: List = result.to_value().borrow().cast_to_list().unwrap();
464 assert_eq!(list.len(), 0);
465 assert_eq!(result, Vec::<ValueContainer>::new().into());
466 assert_eq!(result, ValueContainer::from(Vec::<ValueContainer>::new()));
467 }
468
469 #[test]
470 fn list() {
471 let result = execute_datex_script_debug_with_result("[1, 2, 3]");
472 let list: List = result.to_value().borrow().cast_to_list().unwrap();
473 let expected = datex_list![
474 Integer::from(1i8),
475 Integer::from(2i8),
476 Integer::from(3i8)
477 ];
478 assert_eq!(list.len(), 3);
479 assert_eq!(result, expected.into());
480 assert_ne!(result, ValueContainer::from(vec![1, 2, 3]));
481 assert_structural_eq!(result, ValueContainer::from(vec![1, 2, 3]));
482 }
483
484 #[test]
485 fn list_with_nested_scope() {
486 let result = execute_datex_script_debug_with_result("[1, (2 + 3), 4]");
487 let expected = datex_list![
488 Integer::from(1i8),
489 Integer::from(5i8),
490 Integer::from(4i8)
491 ];
492
493 assert_eq!(result, expected.into());
494 assert_ne!(result, ValueContainer::from(vec![1_u8, 5_u8, 4_u8]));
495 assert_structural_eq!(
496 result,
497 ValueContainer::from(vec![1_u8, 5_u8, 4_u8])
498 );
499 }
500
501 #[test]
502 fn boolean() {
503 let result = execute_datex_script_debug_with_result("true");
504 assert_eq!(result, true.into());
505 assert_structural_eq!(result, ValueContainer::from(true));
506
507 let result = execute_datex_script_debug_with_result("false");
508 assert_eq!(result, false.into());
509 assert_structural_eq!(result, ValueContainer::from(false));
510 }
511
512 #[test]
513 fn decimal() {
514 let result = execute_datex_script_debug_with_result("1.5");
515 assert_eq!(result, Decimal::from_string("1.5").unwrap().into());
516 assert_structural_eq!(result, ValueContainer::from(1.5));
517 }
518
519 #[test]
520 fn decimal_and_integer() {
521 let result = execute_datex_script_debug_with_result("-2341324.0");
522 assert_eq!(result, Decimal::from_string("-2341324").unwrap().into());
523 assert!(!result.structural_eq(&ValueContainer::from(-2341324)));
524 }
525
526 #[test]
527 fn integer() {
528 let result = execute_datex_script_debug_with_result("2");
529 assert_eq!(result, Integer::from(2).into());
530 assert_ne!(result, 2_u8.into());
531 assert_structural_eq!(result, ValueContainer::from(2_i8));
532 }
533
534 #[test]
535 fn typed_integer() {
536 let result = execute_datex_script_debug_with_result("-2i16");
537 assert_eq!(result, TypedInteger::from(-2i16).into());
538 assert_structural_eq!(result, ValueContainer::from(-2_i16));
539
540 let result = execute_datex_script_debug_with_result("2i32");
541 assert_eq!(result, TypedInteger::from(2i32).into());
542 assert_structural_eq!(result, ValueContainer::from(2_i32));
543
544 let result = execute_datex_script_debug_with_result("-2i64");
545 assert_eq!(result, TypedInteger::from(-2i64).into());
546 assert_structural_eq!(result, ValueContainer::from(-2_i64));
547
548 let result = execute_datex_script_debug_with_result("2i128");
549 assert_eq!(result, TypedInteger::from(2i128).into());
550 assert_structural_eq!(result, ValueContainer::from(2_i128));
551
552 let result = execute_datex_script_debug_with_result("2u8");
553 assert_eq!(result, TypedInteger::from(2_u8).into());
554 assert_structural_eq!(result, ValueContainer::from(2_u8));
555
556 let result = execute_datex_script_debug_with_result("2u16");
557 assert_eq!(result, TypedInteger::from(2_u16).into());
558 assert_structural_eq!(result, ValueContainer::from(2_u16));
559
560 let result = execute_datex_script_debug_with_result("2u32");
561 assert_eq!(result, TypedInteger::from(2_u32).into());
562 assert_structural_eq!(result, ValueContainer::from(2_u32));
563
564 let result = execute_datex_script_debug_with_result("2u64");
565 assert_eq!(result, TypedInteger::from(2_u64).into());
566 assert_structural_eq!(result, ValueContainer::from(2_u64));
567
568 let result = execute_datex_script_debug_with_result("2u128");
569 assert_eq!(result, TypedInteger::from(2_u128).into());
570 assert_structural_eq!(result, ValueContainer::from(2_u128));
571
572 let result = execute_datex_script_debug_with_result("2ibig");
573 assert_eq!(result, TypedInteger::IBig(Integer::from(2)).into());
574 assert_structural_eq!(result, ValueContainer::from(2));
575 }
576
577 #[test]
578 fn null() {
579 let result = execute_datex_script_debug_with_result("null");
580 assert_eq!(result, ValueContainer::from(CoreValue::Null));
581 assert_eq!(result, CoreValue::Null.into());
582 assert_structural_eq!(result, ValueContainer::from(CoreValue::Null));
583 }
584
585 #[test]
586 fn map() {
587 let result =
588 execute_datex_script_debug_with_result("{x: 1, y: 2, z: 42}");
589 let map: CoreValue = result.clone().to_value().borrow().clone().inner;
590 let map: Map = map.try_into().unwrap();
591
592 assert_eq!(map.to_string(), "{\"x\": 1, \"y\": 2, \"z\": 42}");
594 assert_eq!(map.size(), 3);
595
596 info!("Map: {:?}", map);
597
598 assert_eq!(map.get("x"), Ok(&Integer::from(1).into()));
600 assert_eq!(map.get("y"), Ok(&Integer::from(2).into()));
601 assert_eq!(map.get("z"), Ok(&Integer::from(42).into()));
602
603 let expected_se: Map = Map::from(vec![
605 ("x".to_string(), 1.into()),
606 ("y".to_string(), 2.into()),
607 ("z".to_string(), 42.into()),
608 ]);
609 assert_structural_eq!(map, expected_se);
610
611 let expected_strict: Map = Map::from(vec![
613 ("x".to_string(), Integer::from(1).into()),
614 ("y".to_string(), Integer::from(2).into()),
615 ("z".to_string(), Integer::from(42).into()),
616 ]);
617 debug!("Expected map: {expected_strict}");
618 debug!("Map result: {map}");
619 }
622
623 #[test]
624 fn empty_map() {
625 let result = execute_datex_script_debug_with_result("{}");
626 let map: CoreValue = result.clone().to_value().borrow().clone().inner;
627 let map: Map = map.try_into().unwrap();
628
629 assert_eq!(map.to_string(), "{}");
631 assert_eq!(map.size(), 0);
632
633 info!("Map: {:?}", map);
634 }
635
636 #[test]
637 fn statements() {
638 let result = execute_datex_script_debug_with_result("1; 2; 3");
639 assert_eq!(result, Integer::from(3).into());
640 }
641
642 #[test]
643 fn single_terminated_statement() {
644 let result = execute_datex_script_debug("1;");
645 assert_eq!(result, None);
646 }
647
648 #[test]
649 fn const_declaration() {
650 let result = execute_datex_script_debug_with_result("const x = 42; x");
651 assert_eq!(result, Integer::from(42).into());
652 }
653
654 #[test]
655 fn const_declaration_with_addition() {
656 let result =
657 execute_datex_script_debug_with_result("const x = 1 + 2; x");
658 assert_eq!(result, Integer::from(3).into());
659 }
660
661 #[test]
662 fn unbox_shared() {
663 let result =
664 execute_datex_script_debug_with_result("const x = shared 42; *x");
665 assert_eq!(result, ValueContainer::from(Integer::from(42)));
666 }
667
668 #[test]
669 fn shared_assignment() {
670 let result = execute_datex_script_debug_with_result(
671 "const x = 'mut shared 42; x",
672 );
673 assert_matches!(result, ValueContainer::Shared(..));
674 assert_value_eq!(result, ValueContainer::from(Integer::from(42)));
675 }
676
677 #[test]
678 fn shared_value_add_assignment() {
679 let result = execute_datex_script_debug_with_result(
680 "var x = shared mut 42; *x += 1; x",
681 );
682
683 assert_value_eq!(result, ValueContainer::from(Integer::from(43)));
684 assert_matches!(result, ValueContainer::Shared(..));
685 if let ValueContainer::Shared(shared) = &result {
686 assert_eq!(shared.mutability(), SharedContainerMutability::Mutable);
687 } else {
688 panic!("Expected shared value");
689 }
690 }
691
692 #[test]
693 fn shared_value_sub_assignment() {
694 let result = execute_datex_script_debug_with_result(
695 "const x = 'mut shared mut 42; *x -= 1",
696 );
697 assert_value_eq!(result, ValueContainer::from(Integer::from(41)));
698
699 let result = execute_datex_script_debug_with_result(
700 "const x = 'mut shared mut 42; *x -= 1; x",
701 );
702
703 assert_value_eq!(result, ValueContainer::from(Integer::from(41)));
707 }
708
709 #[tokio::test]
710 async fn env_slot() {
711 let res = execute_datex_script_with_runtime(
712 RuntimeConfig {
713 env: Some(HashMap::from([(
714 "TEST_ENV_VAR".to_string(),
715 "test_value".to_string(),
716 )])),
717 ..Default::default()
718 },
719 "#env",
720 )
721 .await
722 .unwrap();
723 assert!(res.is_some());
724 let env = res.unwrap().to_value().borrow().cast_to_map().unwrap();
725 assert_eq!(env.get("TEST_ENV_VAR"), Ok(&"test_value".into()));
726 }
727
728 #[test]
729 fn shebang() {
730 let result = execute_datex_script_debug_with_result("#!datex\n42");
731 assert_eq!(result, Integer::from(42).into());
732 }
733
734 #[test]
735 fn single_line_comment() {
736 let result =
737 execute_datex_script_debug_with_result("// this is a comment\n42");
738 assert_eq!(result, Integer::from(42).into());
739
740 let result = execute_datex_script_debug_with_result(
741 "// this is a comment\n// another comment\n42",
742 );
743 assert_eq!(result, Integer::from(42).into());
744 }
745
746 #[test]
747 fn multi_line_comment() {
748 let result = execute_datex_script_debug_with_result(
749 "/* this is a comment */\n42",
750 );
751 assert_eq!(result, Integer::from(42).into());
752
753 let result = execute_datex_script_debug_with_result(
754 "/* this is a comment\n with multiple lines */\n42",
755 );
756 assert_eq!(result, Integer::from(42).into());
757
758 let result = execute_datex_script_debug_with_result("[1, /* 2, */ 3]");
759 let expected = datex_list![Integer::from(1), Integer::from(3)];
760 assert_eq!(result, expected.into());
761 }
762
763 #[test]
764 fn continuous_execution() {
765 assert_unbounded_input_matches_output(
766 vec!["1", "2"],
767 vec![Some(Integer::from(1).into()), Some(Integer::from(2).into())],
768 )
769 }
770
771 #[test]
772 fn continuous_execution_multiple_external_interrupts() {
773 assert_unbounded_input_matches_output(
774 vec!["1", "integer", "integer"],
775 vec![
776 Some(Integer::from(1).into()),
777 Some(ValueContainer::Shared(SharedContainer::Type(
778 get_core_lib_type_reference(CoreLibPointerId::Integer(
779 None,
780 )),
781 ))),
782 Some(ValueContainer::Shared(SharedContainer::Type(
783 get_core_lib_type_reference(CoreLibPointerId::Integer(
784 None,
785 )),
786 ))),
787 ],
788 )
789 }
790}