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