datex_core/runtime/execution/execution_loop/mod.rs
1pub mod interrupts;
2mod operations;
3mod runtime_value;
4mod slots;
5pub mod state;
6
7use crate::core_compiler::value_compiler::compile_value_container;
8use crate::dxb_parser::body::{DXBParserError, iterate_instructions};
9use crate::dxb_parser::instruction_collector::{
10 CollectedResults, CollectionResultsPopper, FullOrPartialResult,
11 InstructionCollector, LastUnboundedResultCollector, ResultCollector,
12 StatementResultCollectionStrategy,
13};
14use crate::global::instruction_codes::InstructionCode;
15use crate::global::operators::{
16 AssignmentOperator, BinaryOperator, ComparisonOperator, UnaryOperator,
17};
18use crate::global::protocol_structures::instructions::{
19 ApplyData, DecimalData, Float32Data, Float64Data, FloatAsInt16Data,
20 FloatAsInt32Data, Instruction, IntegerData, RawPointerAddress,
21 RegularInstruction, ShortTextData, SlotAddress, TextData, TypeInstruction,
22};
23use crate::references::reference::{Reference, ReferenceMutability};
24use crate::runtime::execution::execution_loop::interrupts::{
25 ExecutionInterrupt, ExternalExecutionInterrupt, InterruptProvider,
26 InterruptResult,
27};
28use crate::runtime::execution::execution_loop::operations::{
29 handle_assignment_operation, handle_binary_operation,
30 handle_comparison_operation, handle_unary_operation, set_property,
31};
32use crate::runtime::execution::execution_loop::runtime_value::RuntimeValue;
33use crate::runtime::execution::execution_loop::slots::get_internal_slot_value;
34use crate::runtime::execution::execution_loop::state::RuntimeExecutionState;
35use crate::runtime::execution::macros::{
36 interrupt, interrupt_with_maybe_value, interrupt_with_value, yield_unwrap,
37};
38use crate::runtime::execution::{ExecutionError, InvalidProgramError};
39use crate::stdlib::boxed::Box;
40use crate::stdlib::rc::Rc;
41use crate::stdlib::vec::Vec;
42use crate::types::definition::TypeDefinition;
43use crate::utils::buffers::append_u32;
44use crate::values::core_value::CoreValue;
45use crate::values::core_values::decimal::Decimal;
46use crate::values::core_values::decimal::typed_decimal::TypedDecimal;
47use crate::values::core_values::integer::typed_integer::TypedInteger;
48use crate::values::core_values::list::List;
49use crate::values::core_values::map::{Map, MapKey};
50use crate::values::core_values::r#type::Type;
51use crate::values::pointer::PointerAddress;
52use crate::values::value::Value;
53use crate::values::value_container::{OwnedValueKey, ValueContainer};
54use core::cell::RefCell;
55use datex_core::runtime::execution::execution_loop::slots::get_slot_value;
56
57#[derive(Debug)]
58enum CollectedExecutionResult {
59 /// contains an optional runtime value that is intercepted by the consumer of a value or passed as the final result at the end of execution
60 Value(Option<RuntimeValue>),
61 /// contains a Type that is intercepted by a consumer of a type value
62 Type(Type),
63 /// contains a key-value pair that is intercepted by a map construction operation
64 KeyValuePair((MapKey, ValueContainer)),
65}
66
67impl From<Option<RuntimeValue>> for CollectedExecutionResult {
68 fn from(value: Option<RuntimeValue>) -> Self {
69 CollectedExecutionResult::Value(value)
70 }
71}
72impl From<RuntimeValue> for CollectedExecutionResult {
73 fn from(value: RuntimeValue) -> Self {
74 CollectedExecutionResult::Value(Some(value))
75 }
76}
77impl From<Type> for CollectedExecutionResult {
78 fn from(value: Type) -> Self {
79 CollectedExecutionResult::Type(value)
80 }
81}
82impl From<(MapKey, ValueContainer)> for CollectedExecutionResult {
83 fn from(value: (MapKey, ValueContainer)) -> Self {
84 CollectedExecutionResult::KeyValuePair(value)
85 }
86}
87
88impl
89 CollectionResultsPopper<
90 CollectedExecutionResult,
91 Option<RuntimeValue>,
92 MapKey,
93 ValueContainer,
94 Type,
95 > for CollectedResults<CollectedExecutionResult>
96{
97 fn try_extract_value_result(
98 result: CollectedExecutionResult,
99 ) -> Option<Option<RuntimeValue>> {
100 match result {
101 CollectedExecutionResult::Value(val) => Some(val),
102 _ => None,
103 }
104 }
105
106 fn try_extract_type_result(
107 result: CollectedExecutionResult,
108 ) -> Option<Type> {
109 match result {
110 CollectedExecutionResult::Type(ty) => Some(ty),
111 _ => None,
112 }
113 }
114
115 fn try_extract_key_value_pair_result(
116 result: CollectedExecutionResult,
117 ) -> Option<(MapKey, ValueContainer)> {
118 match result {
119 CollectedExecutionResult::KeyValuePair((key, value)) => {
120 Some((key, value))
121 }
122 _ => None,
123 }
124 }
125}
126
127impl CollectedResults<CollectedExecutionResult> {
128 fn collect_value_container_results_assert_existing(
129 mut self,
130 state: &RuntimeExecutionState,
131 ) -> Result<Vec<ValueContainer>, ExecutionError> {
132 let count = self.len();
133 let mut expressions = Vec::with_capacity(count);
134 for _ in 0..count {
135 expressions.push(
136 self.pop_cloned_value_container_result_assert_existing(state)?,
137 );
138 }
139 expressions.reverse();
140 Ok(expressions)
141 }
142
143 /// Pops a runtime value result, returning an error if none exists
144 fn pop_runtime_value_result_assert_existing(
145 &mut self,
146 ) -> Result<RuntimeValue, ExecutionError> {
147 self.pop_value_result()
148 .ok_or(ExecutionError::InvalidProgram(
149 InvalidProgramError::ExpectedValue,
150 ))
151 }
152
153 /// Pops a value container result, returning an error if none exists.
154 /// If the value is a slot address, it is resolved to a cloned value container.
155 /// Do not use this method if you want to work on the actual value without cloning it.
156 fn pop_cloned_value_container_result_assert_existing(
157 &mut self,
158 state: &RuntimeExecutionState,
159 ) -> Result<ValueContainer, ExecutionError> {
160 self.pop_runtime_value_result_assert_existing()?
161 .into_cloned_value_container(state)
162 }
163
164 fn collect_key_value_pair_results_assert_existing(
165 mut self,
166 ) -> Result<Vec<(MapKey, ValueContainer)>, ExecutionError> {
167 let count = self.len();
168 let mut pairs = Vec::with_capacity(count);
169 for _ in 0..count {
170 let (key, value) = self.pop_key_value_pair_result();
171 pairs.push((key, value));
172 }
173 pairs.reverse();
174 Ok(pairs)
175 }
176}
177
178/// Main execution loop that drives the execution of the DXB body
179/// The interrupt_provider is used to provide results for synchronous or asynchronous I/O operations
180pub fn execution_loop(
181 state: RuntimeExecutionState,
182 dxb_body: Rc<RefCell<Vec<u8>>>,
183 interrupt_provider: InterruptProvider,
184) -> impl Iterator<Item = Result<ExternalExecutionInterrupt, ExecutionError>> {
185 gen move {
186 let mut active_value: Option<ValueContainer> = None;
187
188 for interrupt in
189 inner_execution_loop(dxb_body, interrupt_provider.clone(), state)
190 {
191 match interrupt {
192 Ok(interrupt) => match interrupt {
193 ExecutionInterrupt::External(external_interrupt) => {
194 yield Ok(external_interrupt);
195 }
196 ExecutionInterrupt::SetActiveValue(value) => {
197 active_value = value;
198 }
199 },
200 Err(err) => {
201 match err {
202 ExecutionError::DXBParserError(
203 DXBParserError::ExpectingMoreInstructions,
204 ) => {
205 yield Err(
206 ExecutionError::IntermediateResultWithState(
207 active_value.take(),
208 None,
209 ),
210 );
211 // assume that when continuing after this yield, more instructions will have been loaded
212 // so we run the loop again to try to get the next instruction
213 continue;
214 }
215 _ => {
216 yield Err(err);
217 }
218 }
219 }
220 }
221 }
222 }
223}
224
225pub fn inner_execution_loop(
226 dxb_body: Rc<RefCell<Vec<u8>>>,
227 interrupt_provider: InterruptProvider,
228 mut state: RuntimeExecutionState,
229) -> impl Iterator<Item = Result<ExecutionInterrupt, ExecutionError>> {
230 gen move {
231 let mut collector =
232 InstructionCollector::<CollectedExecutionResult>::default();
233
234 for instruction_result in iterate_instructions(dxb_body) {
235 let instruction = match instruction_result {
236 Ok(instruction) => instruction,
237 Err(DXBParserError::ExpectingMoreInstructions) => {
238 yield Err(DXBParserError::ExpectingMoreInstructions.into());
239 // assume that when continuing after this yield, more instructions will have been loaded
240 // so we run the loop again to try to get the next instruction
241 continue;
242 }
243 Err(err) => {
244 return yield Err(err.into());
245 }
246 };
247
248 let result = match instruction {
249 // handle regular instructions
250 Instruction::RegularInstruction(regular_instruction) => {
251 let regular_instruction = collector
252 .default_regular_instruction_collection(
253 regular_instruction,
254 StatementResultCollectionStrategy::Last,
255 );
256
257 let expr: Option<Option<RuntimeValue>> = if let Some(
258 regular_instruction,
259 ) =
260 regular_instruction
261 {
262 Some(match regular_instruction {
263 // boolean
264 RegularInstruction::True => Some(ValueContainer::from(true).into()),
265 RegularInstruction::False => Some(ValueContainer::from(false).into()),
266
267 // integers
268 RegularInstruction::Int8(integer) => {
269 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
270 }
271 RegularInstruction::Int16(integer) => {
272 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
273 }
274 RegularInstruction::Int32(integer) => {
275 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
276 }
277 RegularInstruction::Int64(integer) => {
278 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
279 }
280 RegularInstruction::Int128(integer) => {
281 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
282 }
283
284 // unsigned integers
285 RegularInstruction::UInt8(integer) => {
286 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
287 }
288 RegularInstruction::UInt16(integer) => {
289 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
290 }
291 RegularInstruction::UInt32(integer) => {
292 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
293 }
294 RegularInstruction::UInt64(integer) => {
295 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
296 }
297 RegularInstruction::UInt128(integer) => {
298 Some(ValueContainer::from(TypedInteger::from(integer.0)).into())
299 }
300
301 // big integers
302 RegularInstruction::BigInteger(IntegerData(integer)) => {
303 Some(ValueContainer::from(TypedInteger::IBig(integer)).into())
304 }
305
306 // default integer
307 RegularInstruction::Integer(IntegerData(i8)) => {
308 Some(ValueContainer::from(i8).into())
309 }
310
311 // specific floats
312 RegularInstruction::DecimalF32(Float32Data(f32)) => {
313 Some(ValueContainer::from(TypedDecimal::from(f32)).into())
314 }
315 RegularInstruction::DecimalF64(Float64Data(f64)) => {
316 Some(ValueContainer::from(TypedDecimal::from(f64)).into())
317 }
318 // big decimal
319 RegularInstruction::BigDecimal(DecimalData(big_decimal)) => {
320 Some(ValueContainer::from(TypedDecimal::Decimal(big_decimal)).into())
321 }
322
323 // default decimals
324 RegularInstruction::DecimalAsInt16(FloatAsInt16Data(i16)) => {
325 Some(ValueContainer::from(Decimal::from(i16 as f32)).into())
326 }
327 RegularInstruction::DecimalAsInt32(FloatAsInt32Data(i32)) => {
328 Some(ValueContainer::from(Decimal::from(i32 as f32)).into())
329 }
330 RegularInstruction::Decimal(DecimalData(big_decimal)) => {
331 Some(ValueContainer::from(big_decimal).into())
332 }
333
334 // endpoint
335 RegularInstruction::Endpoint(endpoint) => Some(ValueContainer::from(endpoint).into()),
336
337 // null
338 RegularInstruction::Null => Some(ValueContainer::from(Value::null()).into()),
339
340 // text
341 RegularInstruction::ShortText(ShortTextData(text)) => {
342 Some(ValueContainer::from(text).into())
343 }
344 RegularInstruction::Text(TextData(text)) => Some(ValueContainer::from(text).into()),
345
346 RegularInstruction::GetRef(address) => Some(interrupt_with_value!(
347 interrupt_provider,
348 ExecutionInterrupt::External(
349 ExternalExecutionInterrupt::ResolvePointer(address)
350 )
351 ).into()),
352 RegularInstruction::GetLocalRef(address) => {
353 Some(interrupt_with_value!(
354 interrupt_provider,
355 ExecutionInterrupt::External(
356 ExternalExecutionInterrupt::ResolveLocalPointer(
357 address
358 )
359 )
360 ).into())
361 }
362 RegularInstruction::GetInternalRef(address) => {
363 Some(interrupt_with_value!(
364 interrupt_provider,
365 ExecutionInterrupt::External(
366 ExternalExecutionInterrupt::ResolveInternalPointer(
367 address
368 )
369 )
370 ).into())
371 }
372
373 RegularInstruction::GetSlot(SlotAddress(address)) => {
374 Some(RuntimeValue::SlotAddress(address))
375 }
376
377 RegularInstruction::GetInternalSlot(SlotAddress(address)) => {
378 Some(RuntimeValue::ValueContainer(yield_unwrap!(
379 get_internal_slot_value(
380 &state,
381 address,
382 )
383 )))
384 }
385
386
387 RegularInstruction::DropSlot(SlotAddress(address)) => {
388 yield_unwrap!(state.slots.drop_slot(address));
389 None
390 }
391
392 // NOTE: make sure that each possible match case is either implemented in the default collection or here
393 // If an instruction is implemented in the default collection, it should be marked as unreachable!() here
394 RegularInstruction::Statements(_) |
395 RegularInstruction::ShortStatements(_) |
396 RegularInstruction::UnboundedStatements |
397 RegularInstruction::UnboundedStatementsEnd(_) |
398 RegularInstruction::List(_) |
399 RegularInstruction::ShortList(_) |
400 RegularInstruction::Map(_) |
401 RegularInstruction::ShortMap(_) |
402 RegularInstruction::KeyValueDynamic |
403 RegularInstruction::KeyValueShortText(_) |
404 RegularInstruction::Add |
405 RegularInstruction::Subtract |
406 RegularInstruction::Multiply |
407 RegularInstruction::Divide |
408 RegularInstruction::UnaryMinus |
409 RegularInstruction::UnaryPlus |
410 RegularInstruction::BitwiseNot |
411 RegularInstruction::Apply(_) |
412 RegularInstruction::GetPropertyText(_) |
413 RegularInstruction::GetPropertyIndex(_) |
414 RegularInstruction::GetPropertyDynamic |
415 RegularInstruction::SetPropertyText(_) |
416 RegularInstruction::SetPropertyIndex(_) |
417 RegularInstruction::SetPropertyDynamic |
418 RegularInstruction::Is |
419 RegularInstruction::Matches |
420 RegularInstruction::StructuralEqual |
421 RegularInstruction::Equal |
422 RegularInstruction::NotStructuralEqual |
423 RegularInstruction::NotEqual |
424 RegularInstruction::AddAssign(_) |
425 RegularInstruction::SubtractAssign(_) |
426 RegularInstruction::MultiplyAssign(_) |
427 RegularInstruction::DivideAssign(_) |
428 RegularInstruction::CreateRef |
429 RegularInstruction::CreateRefMut |
430 RegularInstruction::GetOrCreateRef(_) |
431 RegularInstruction::GetOrCreateRefMut(_) |
432 RegularInstruction::AllocateSlot(_) |
433 RegularInstruction::SetSlot(_) |
434 RegularInstruction::SetReferenceValue(_) |
435 RegularInstruction::Deref |
436 RegularInstruction::TypedValue |
437 RegularInstruction::RemoteExecution(_) |
438 RegularInstruction::TypeExpression => unreachable!()
439 })
440 } else {
441 None
442 };
443
444 expr.map(CollectedExecutionResult::from)
445 }
446 Instruction::TypeInstruction(type_instruction) => {
447 let type_instruction = collector
448 .default_type_instruction_collection(type_instruction);
449
450 let type_expression: Option<Type> = if let Some(
451 type_instruction,
452 ) = type_instruction
453 {
454 Some(match type_instruction {
455 TypeInstruction::LiteralInteger(integer) => {
456 Type::structural(integer.0)
457 }
458 TypeInstruction::LiteralText(text_data) => {
459 Type::structural(text_data.0)
460 }
461
462 TypeInstruction::TypeReference(type_ref) => {
463 let metadata = type_ref.metadata;
464 let val = interrupt_with_maybe_value!(
465 interrupt_provider,
466 match type_ref.address {
467 RawPointerAddress::Local(address) => {
468 ExecutionInterrupt::External(
469 ExternalExecutionInterrupt::ResolveLocalPointer(
470 address,
471 ),
472 )
473 }
474 RawPointerAddress::Internal(
475 address,
476 ) => {
477 ExecutionInterrupt::External(ExternalExecutionInterrupt::ResolveInternalPointer(address))
478 }
479 RawPointerAddress::Full(address) => {
480 ExecutionInterrupt::External(
481 ExternalExecutionInterrupt::ResolvePointer(
482 address,
483 ),
484 )
485 }
486 }
487 );
488
489 match val {
490 // simple Type value
491 Some(ValueContainer::Value(Value {
492 inner: CoreValue::Type(ty),
493 ..
494 })) => ty,
495 // Type Reference
496 Some(ValueContainer::Reference(
497 Reference::TypeReference(type_ref),
498 )) => Type::new(
499 TypeDefinition::Reference(type_ref),
500 metadata.mutability.into(),
501 ),
502 _ => {
503 return yield Err(
504 ExecutionError::ExpectedTypeValue,
505 );
506 }
507 }
508 }
509
510 // NOTE: make sure that each possible match case is either implemented in the default collection or here
511 // If an instruction is implemented in the default collection, it should be marked as unreachable!() here
512 TypeInstruction::List(_)
513 | TypeInstruction::ImplType(_) => unreachable!(),
514 })
515 } else {
516 None
517 };
518
519 type_expression
520 .map(|ty_expr| CollectedExecutionResult::from(ty_expr))
521 }
522 };
523
524 if let Some(result) = result {
525 collector.push_result(result);
526 }
527
528 // handle collecting nested expressions
529 while let Some(result) = collector.try_pop_collected() {
530 let expr: CollectedExecutionResult = match result {
531 FullOrPartialResult::Full(
532 instruction,
533 mut collected_results,
534 ) => {
535 match instruction {
536 Instruction::RegularInstruction(
537 regular_instruction,
538 ) => match regular_instruction {
539 RegularInstruction::List(_)
540 | RegularInstruction::ShortList(_) => {
541 let elements = yield_unwrap!(collected_results.collect_value_container_results_assert_existing(&state));
542 RuntimeValue::ValueContainer(
543 ValueContainer::from(List::new(
544 elements,
545 )),
546 )
547 .into()
548 }
549 RegularInstruction::Map(_)
550 | RegularInstruction::ShortMap(_) => {
551 let entries = yield_unwrap!(collected_results.collect_key_value_pair_results_assert_existing());
552 RuntimeValue::ValueContainer(
553 ValueContainer::from(Map::from(
554 entries,
555 )),
556 )
557 .into()
558 }
559
560 RegularInstruction::KeyValueDynamic => {
561 let value = yield_unwrap!(
562 collected_results.pop_cloned_value_container_result_assert_existing(&state)
563 );
564 let key = yield_unwrap!(
565 collected_results
566 .pop_cloned_value_container_result_assert_existing(&state)
567 );
568 CollectedExecutionResult::KeyValuePair((
569 MapKey::Value(key),
570 value,
571 ))
572 }
573
574 RegularInstruction::KeyValueShortText(
575 short_text_data,
576 ) => {
577 let value = yield_unwrap!(
578 collected_results.pop_cloned_value_container_result_assert_existing(&state)
579 );
580 let key = MapKey::Text(short_text_data.0);
581 CollectedExecutionResult::KeyValuePair((
582 key, value,
583 ))
584 }
585
586 RegularInstruction::Add
587 | RegularInstruction::Subtract
588 | RegularInstruction::Multiply
589 | RegularInstruction::Divide => {
590 let right = yield_unwrap!(
591 collected_results
592 .pop_cloned_value_container_result_assert_existing(&state)
593 );
594 let left = yield_unwrap!(
595 collected_results
596 .pop_cloned_value_container_result_assert_existing(&state)
597 );
598
599 let res = handle_binary_operation(
600 BinaryOperator::from(
601 regular_instruction,
602 ),
603 &left,
604 &right,
605 );
606 RuntimeValue::ValueContainer(yield_unwrap!(
607 res
608 ))
609 .into()
610 }
611
612 RegularInstruction::Is
613 | RegularInstruction::StructuralEqual
614 | RegularInstruction::Equal
615 | RegularInstruction::NotStructuralEqual
616 | RegularInstruction::NotEqual => {
617 let right = yield_unwrap!(
618 collected_results
619 .pop_cloned_value_container_result_assert_existing(&state)
620 );
621 let left = yield_unwrap!(
622 collected_results
623 .pop_cloned_value_container_result_assert_existing(&state)
624 );
625
626 let res = handle_comparison_operation(
627 ComparisonOperator::from(
628 regular_instruction,
629 ),
630 &left,
631 &right,
632 );
633 RuntimeValue::ValueContainer(yield_unwrap!(
634 res
635 ))
636 .into()
637 }
638
639 RegularInstruction::Matches => {
640 let target = yield_unwrap!(
641 collected_results
642 .pop_runtime_value_result_assert_existing()
643 );
644 let type_pattern =
645 collected_results.pop_type_result();
646
647 todo!("#645 Undescribed by author.")
648 }
649
650 RegularInstruction::UnaryMinus
651 | RegularInstruction::UnaryPlus
652 | RegularInstruction::BitwiseNot
653 | RegularInstruction::CreateRef
654 | RegularInstruction::CreateRefMut
655 | RegularInstruction::Deref => {
656 let mut target = yield_unwrap!(
657 collected_results
658 .pop_runtime_value_result_assert_existing()
659 );
660 let res = target.with_mut_value_container(
661 &mut state,
662 |target| {
663 handle_unary_operation(
664 UnaryOperator::from(
665 regular_instruction,
666 ),
667 target.clone(), // TODO #646: is unary operation supposed to take ownership?
668 )
669 },
670 );
671 RuntimeValue::ValueContainer(yield_unwrap!(
672 yield_unwrap!(res)
673 ))
674 .into()
675 }
676
677 RegularInstruction::TypedValue => {
678 let mut value_container = yield_unwrap!(
679 collected_results
680 .pop_cloned_value_container_result_assert_existing(&state)
681 );
682 let ty =
683 collected_results.pop_type_result();
684
685 match &mut value_container {
686 ValueContainer::Value(value) => {
687 // FIXME #647: only using type definition here, refactor and/or add checks
688 value.actual_type =
689 Box::new(ty.type_definition);
690 }
691 _ => panic!(
692 "Expected ValueContainer::Value for type casting"
693 ),
694 }
695 RuntimeValue::ValueContainer(
696 value_container,
697 )
698 .into()
699 }
700
701 // type(...)
702 RegularInstruction::TypeExpression => {
703 let ty =
704 collected_results.pop_type_result();
705 RuntimeValue::ValueContainer(
706 ValueContainer::Value(Value {
707 inner: CoreValue::Type(ty),
708 actual_type: Box::new(
709 TypeDefinition::Unknown,
710 ), // TODO #648: type for type
711 }),
712 )
713 .into()
714 }
715
716 RegularInstruction::AddAssign(SlotAddress(
717 address,
718 ))
719 | RegularInstruction::MultiplyAssign(
720 SlotAddress(address),
721 )
722 | RegularInstruction::DivideAssign(
723 SlotAddress(address),
724 )
725 | RegularInstruction::SubtractAssign(
726 SlotAddress(address),
727 ) => {
728 let slot_value = yield_unwrap!(
729 get_slot_value(&state, address)
730 );
731 let value = yield_unwrap!(
732 collected_results
733 .pop_cloned_value_container_result_assert_existing(&state)
734 );
735
736 let new_val = yield_unwrap!(
737 handle_assignment_operation(
738 AssignmentOperator::from(
739 regular_instruction
740 ),
741 &slot_value,
742 value,
743 )
744 );
745 yield_unwrap!(
746 state
747 .slots
748 .set_slot_value(address, new_val)
749 );
750 None.into()
751 }
752
753 RegularInstruction::SetReferenceValue(
754 operator,
755 ) => {
756 let value_container = yield_unwrap!(
757 collected_results
758 .pop_cloned_value_container_result_assert_existing(&state)
759 );
760 let ref_value_container = yield_unwrap!(
761 collected_results
762 .pop_cloned_value_container_result_assert_existing(&state)
763 );
764
765 // assignment value must be a reference
766 if let Some(reference) =
767 ref_value_container.maybe_reference()
768 {
769 let lhs = reference.value_container();
770 let res = yield_unwrap!(
771 handle_assignment_operation(
772 operator,
773 &lhs,
774 value_container,
775 )
776 );
777 yield_unwrap!(
778 reference.set_value_container(res)
779 );
780 RuntimeValue::ValueContainer(
781 ref_value_container,
782 )
783 .into()
784 } else {
785 return yield Err(
786 ExecutionError::DerefOfNonReference,
787 );
788 }
789 }
790
791 RegularInstruction::SetSlot(SlotAddress(
792 address,
793 )) => {
794 let value = yield_unwrap!(
795 collected_results
796 .pop_cloned_value_container_result_assert_existing(&state)
797 );
798 yield_unwrap!(
799 state
800 .slots
801 .set_slot_value(address, value)
802 );
803 None.into()
804 }
805
806 RegularInstruction::AllocateSlot(
807 SlotAddress(address),
808 ) => {
809 let value = yield_unwrap!(
810 collected_results
811 .pop_cloned_value_container_result_assert_existing(&state)
812 );
813 state
814 .slots
815 .allocate_slot(address, Some(value));
816
817 None.into()
818 }
819
820 RegularInstruction::GetPropertyText(
821 property_data,
822 ) => {
823 let mut target = yield_unwrap!(
824 collected_results
825 .pop_runtime_value_result_assert_existing()
826 );
827 let property_name = property_data.0;
828
829 let res = target.with_mut_value_container(
830 &mut state,
831 |target| {
832 target.try_get_property(
833 &property_name,
834 )
835 },
836 );
837 RuntimeValue::ValueContainer(yield_unwrap!(
838 yield_unwrap!(res)
839 ))
840 .into()
841 }
842
843 RegularInstruction::GetPropertyIndex(
844 property_data,
845 ) => {
846 let mut target = yield_unwrap!(
847 collected_results
848 .pop_runtime_value_result_assert_existing()
849 );
850 let property_index = property_data.0;
851
852 let res = target.with_mut_value_container(
853 &mut state,
854 |target| {
855 target.try_get_property(
856 property_index,
857 )
858 },
859 );
860 RuntimeValue::ValueContainer(yield_unwrap!(
861 yield_unwrap!(res)
862 ))
863 .into()
864 }
865
866 RegularInstruction::GetPropertyDynamic => {
867 let key = yield_unwrap!(
868 collected_results
869 .pop_cloned_value_container_result_assert_existing(&state)
870 );
871 let mut target = yield_unwrap!(
872 collected_results
873 .pop_runtime_value_result_assert_existing()
874 );
875
876 let res = target.with_mut_value_container(
877 &mut state,
878 |target| target.try_get_property(&key),
879 );
880 RuntimeValue::ValueContainer(yield_unwrap!(
881 yield_unwrap!(res)
882 ))
883 .into()
884 }
885
886 RegularInstruction::SetPropertyText(
887 property_data,
888 ) => {
889 let mut target = yield_unwrap!(
890 collected_results
891 .pop_runtime_value_result_assert_existing()
892 );
893 let value = yield_unwrap!(
894 collected_results
895 .pop_cloned_value_container_result_assert_existing(&state)
896 );
897 let runtime_internal =
898 state.runtime_internal.clone();
899 let res = target.with_mut_value_container(
900 &mut state,
901 |target| {
902 set_property(
903 &runtime_internal,
904 target,
905 OwnedValueKey::Text(
906 property_data.0,
907 ),
908 value,
909 )
910 },
911 );
912 yield_unwrap!(yield_unwrap!(res));
913 None.into()
914 }
915
916 RegularInstruction::SetPropertyIndex(
917 property_data,
918 ) => {
919 let mut target = yield_unwrap!(
920 collected_results
921 .pop_runtime_value_result_assert_existing()
922 );
923 let value = yield_unwrap!(
924 collected_results
925 .pop_cloned_value_container_result_assert_existing(&state)
926 );
927
928 let runtime_internal =
929 state.runtime_internal.clone();
930 let res = target.with_mut_value_container(
931 &mut state,
932 |target| {
933 set_property(
934 &runtime_internal,
935 target,
936 OwnedValueKey::Index(
937 property_data.0 as i64,
938 ),
939 value,
940 )
941 },
942 );
943 yield_unwrap!(yield_unwrap!(res));
944 None.into()
945 }
946
947 RegularInstruction::SetPropertyDynamic => {
948 let mut target = yield_unwrap!(
949 collected_results
950 .pop_runtime_value_result_assert_existing()
951 );
952 let value = yield_unwrap!(
953 collected_results
954 .pop_cloned_value_container_result_assert_existing(&state)
955 );
956 let key = yield_unwrap!(
957 collected_results
958 .pop_cloned_value_container_result_assert_existing(&state)
959 );
960
961 let runtime_internal =
962 state.runtime_internal.clone();
963 let res = target.with_mut_value_container(
964 &mut state,
965 |target| {
966 set_property(
967 &runtime_internal,
968 target,
969 OwnedValueKey::Value(key),
970 value,
971 )
972 },
973 );
974 yield_unwrap!(yield_unwrap!(res));
975 None.into()
976 }
977
978 RegularInstruction::RemoteExecution(
979 exec_block_data,
980 ) => {
981 // build dxb
982 let mut buffer = Vec::with_capacity(256);
983 for (addr, local_slot) in exec_block_data
984 .injected_slots
985 .into_iter()
986 .enumerate()
987 {
988 buffer.push(
989 InstructionCode::ALLOCATE_SLOT
990 as u8,
991 );
992 append_u32(&mut buffer, addr as u32);
993
994 let slot_value = yield_unwrap!(
995 get_slot_value(&state, local_slot,)
996 );
997 buffer.extend_from_slice(
998 &compile_value_container(
999 &slot_value,
1000 ),
1001 );
1002 }
1003 buffer.extend_from_slice(
1004 &exec_block_data.body,
1005 );
1006
1007 let receivers = yield_unwrap!(
1008 collected_results
1009 .pop_cloned_value_container_result_assert_existing(&state)
1010 );
1011
1012 interrupt_with_maybe_value!(
1013 interrupt_provider,
1014 ExecutionInterrupt::External(
1015 ExternalExecutionInterrupt::RemoteExecution(
1016 receivers, buffer
1017 )
1018 )
1019 )
1020 .map(|val| RuntimeValue::ValueContainer(val))
1021 .into()
1022 }
1023
1024 RegularInstruction::Apply(ApplyData {
1025 ..
1026 }) => {
1027 let mut args = yield_unwrap!(collected_results.collect_value_container_results_assert_existing(&state));
1028 // last argument is the callee
1029 let callee = args.remove(args.len() - 1);
1030 interrupt_with_maybe_value!(
1031 interrupt_provider,
1032 ExecutionInterrupt::External(
1033 ExternalExecutionInterrupt::Apply(
1034 callee, args
1035 )
1036 )
1037 )
1038 .map(|val| {
1039 RuntimeValue::ValueContainer(val)
1040 })
1041 .into()
1042 }
1043
1044 RegularInstruction::UnboundedStatementsEnd(
1045 terminated,
1046 ) => {
1047 let result = yield_unwrap!(collector.try_pop_unbounded().ok_or(DXBParserError::NotInUnboundedRegularScopeError));
1048 if let FullOrPartialResult::Partial(
1049 _,
1050 mut collected_result,
1051 ) = result
1052 {
1053 if terminated {
1054 CollectedExecutionResult::Value(
1055 None,
1056 )
1057 } else {
1058 match collected_result {
1059 Some(CollectedExecutionResult::Value(val)) => val.into(),
1060 None => CollectedExecutionResult::Value(None),
1061 _ => unreachable!(),
1062 }
1063 }
1064 } else {
1065 unreachable!()
1066 }
1067 }
1068
1069 e => {
1070 todo!(
1071 "Unhandled collected regular instruction: {:?}",
1072 e
1073 );
1074 }
1075 },
1076
1077 Instruction::TypeInstruction(type_instruction) => {
1078 match type_instruction {
1079 TypeInstruction::ImplType(
1080 impl_type_data,
1081 ) => {
1082 let mutability: Option<
1083 ReferenceMutability,
1084 > = impl_type_data
1085 .metadata
1086 .mutability
1087 .into();
1088 let base_type =
1089 collected_results.pop_type_result();
1090 Type::new(
1091 TypeDefinition::ImplType(
1092 Box::new(base_type),
1093 impl_type_data
1094 .impls
1095 .iter()
1096 .map(PointerAddress::from)
1097 .collect(),
1098 ),
1099 mutability.clone(),
1100 )
1101 .into()
1102 }
1103 _ => todo!("#649 Undescribed by author."),
1104 }
1105 }
1106 }
1107 }
1108 FullOrPartialResult::Partial(
1109 instruction,
1110 collected_result,
1111 ) => match instruction {
1112 Instruction::RegularInstruction(
1113 regular_instruction,
1114 ) => match regular_instruction {
1115 RegularInstruction::Statements(statements_data) => {
1116 if statements_data.terminated {
1117 CollectedExecutionResult::Value(None)
1118 } else {
1119 match collected_result {
1120 Some(
1121 CollectedExecutionResult::Value(
1122 val,
1123 ),
1124 ) => val.into(),
1125 None => {
1126 CollectedExecutionResult::Value(
1127 None,
1128 )
1129 }
1130 _ => unreachable!(),
1131 }
1132 }
1133 }
1134 _ => unreachable!(),
1135 },
1136
1137 Instruction::TypeInstruction(data) => unreachable!(),
1138 },
1139 };
1140
1141 collector.push_result(expr);
1142 }
1143
1144 // if in unbounded statements, propagate active value via interrupt
1145 if let Some(ResultCollector::LastUnbounded(
1146 LastUnboundedResultCollector {
1147 last_result:
1148 Some(CollectedExecutionResult::Value(last_result)),
1149 ..
1150 },
1151 )) = collector.last()
1152 {
1153 let active_value = yield_unwrap!(
1154 last_result
1155 .clone()
1156 .map(|v| v.into_cloned_value_container(&state))
1157 .transpose()
1158 );
1159
1160 interrupt!(
1161 interrupt_provider,
1162 ExecutionInterrupt::SetActiveValue(active_value)
1163 );
1164 }
1165 }
1166
1167 if let Some(result) = collector.take_root_result() {
1168 yield Ok(ExecutionInterrupt::External(
1169 ExternalExecutionInterrupt::Result(match result {
1170 CollectedExecutionResult::Value(value) => {
1171 let value = yield_unwrap!(
1172 value
1173 .map(|v| v.into_cloned_value_container(&state))
1174 .transpose()
1175 );
1176
1177 value
1178 }
1179 _ => unreachable!("Expected root result"),
1180 }),
1181 ));
1182 } else {
1183 panic!("Execution finished without root result");
1184 }
1185 }
1186}