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