Skip to main content

datex_core/runtime/execution/execution_loop/
mod.rs

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