swamp_code_gen/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6pub mod alloc;
7pub mod alloc_util;
8pub mod constants;
9pub mod ctx;
10mod location;
11mod vec;
12
13use crate::alloc::{ConstantMemoryRegion, FrameMemoryRegion, ScopeAllocator};
14use crate::alloc_util::{
15    is_map, is_vec, layout_struct, layout_tuple, layout_tuple_elements, reserve_space_for_type,
16    type_size_and_alignment,
17};
18use crate::constants::ConstantsManager;
19use crate::ctx::Context;
20use seq_map::SeqMap;
21use swamp_node::Node;
22use swamp_semantic::intr::IntrinsicFunction;
23use swamp_semantic::{
24    AnonymousStructLiteral, ArgumentExpressionOrLocation, BinaryOperator, BinaryOperatorKind,
25    BooleanExpression, CompoundOperatorKind, ConstantId, ConstantRef, EnumLiteralData, Expression,
26    ExpressionKind, ForPattern, Function, Guard, InternalFunctionDefinitionRef, InternalFunctionId,
27    InternalMainExpression, Iterable, Literal, Match, MutOrImmutableExpression, NormalPattern,
28    Pattern, Postfix, PostfixKind, SingleLocationExpression, SingleMutLocationExpression,
29    StructInstantiation, UnaryOperator, UnaryOperatorKind, VariableRef, WhenBinding,
30};
31use swamp_source_map_lookup::{SourceMapLookup, SourceMapWrapper};
32use swamp_types::{AnonymousStructType, EnumVariantType, Signature, StructTypeField, Type};
33use swamp_vm_disasm::{disasm_color, disasm_instructions_color};
34use swamp_vm_instr_build::{InstructionBuilder, PatchPosition};
35use swamp_vm_types::{
36    BOOL_SIZE, BinaryInstruction, CountU16, FrameMemoryAddress, FrameMemoryAddressIndirectPointer,
37    FrameMemorySize, HEAP_PTR_ALIGNMENT, HEAP_PTR_SIZE, HeapMemoryAddress, INT_SIZE,
38    InstructionPosition, MemoryAlignment, MemoryOffset, MemorySize, PTR_SIZE,
39    TempFrameMemoryAddress, VEC_ITERATOR_ALIGNMENT, VEC_ITERATOR_SIZE,
40};
41use tracing::{error, info, trace};
42
43pub struct GeneratedExpressionResult {
44    pub has_set_bool_z_flag: bool,
45}
46
47impl Default for GeneratedExpressionResult {
48    fn default() -> Self {
49        Self {
50            has_set_bool_z_flag: false,
51        }
52    }
53}
54
55#[derive(Debug)]
56pub enum ErrorKind {
57    IllegalCompoundAssignment,
58    VariableNotUnique,
59    IllegalCollection,
60    NotAnIterableCollection,
61}
62
63#[derive(Debug)]
64pub struct Error {
65    pub kind: ErrorKind,
66    pub node: Node,
67}
68
69pub struct SlicePairInfo {
70    pub addr: TempFrameMemoryAddress,
71    pub key_size: MemorySize,
72    pub value_size: MemorySize,
73    pub element_count: CountU16,
74    pub element_size: MemorySize,
75}
76
77pub struct FunctionInfo {
78    pub starts_at_ip: InstructionPosition,
79    pub internal_function_definition: InternalFunctionDefinitionRef,
80}
81
82pub struct FunctionFixup {
83    pub patch_position: PatchPosition,
84    pub fn_id: InternalFunctionId,
85    //pub internal_function_definition: InternalFunctionDefinitionRef,
86}
87
88pub struct ConstantInfo {
89    pub ip: InstructionPosition,
90    pub constant_ref: ConstantRef,
91    pub target_constant_memory: ConstantMemoryRegion,
92}
93
94pub struct CodeGenState {
95    builder: InstructionBuilder,
96    constants: ConstantsManager,
97    constant_offsets: SeqMap<ConstantId, ConstantMemoryRegion>,
98    constant_functions: SeqMap<ConstantId, ConstantInfo>,
99    function_infos: SeqMap<InternalFunctionId, FunctionInfo>,
100    function_fixups: Vec<FunctionFixup>,
101    //source_map_lookup: &'b SourceMapWrapper<'b>,
102    debug_last_ip: usize,
103}
104
105pub struct GenOptions {
106    pub is_halt_function: bool,
107}
108
109impl CodeGenState {
110    #[must_use]
111    pub fn new() -> Self {
112        Self {
113            builder: InstructionBuilder::default(),
114            constants: ConstantsManager::new(),
115            constant_offsets: SeqMap::default(),
116            function_infos: SeqMap::default(),
117            constant_functions: SeqMap::default(),
118            function_fixups: vec![],
119            debug_last_ip: 0,
120        }
121    }
122
123    #[must_use]
124    pub fn instructions(&self) -> &[BinaryInstruction] {
125        &self.builder.instructions
126    }
127    pub fn create_function_sections(&self) -> SeqMap<InstructionPosition, String> {
128        let mut lookups = SeqMap::new();
129        for (_func_id, function_info) in &self.function_infos {
130            let description = function_info
131                .internal_function_definition
132                .assigned_name
133                .clone();
134            lookups
135                .insert(function_info.starts_at_ip.clone(), description)
136                .unwrap();
137        }
138
139        for (_func_id, function_info) in &self.constant_functions {
140            let description = format!("constant {}", function_info.constant_ref.assigned_name);
141            lookups
142                .insert(function_info.ip.clone(), description)
143                .unwrap();
144        }
145
146        lookups
147    }
148    #[must_use]
149    pub fn builder(&self) -> &InstructionBuilder {
150        &self.builder
151    }
152    pub fn constant_functions(&self) -> &SeqMap<ConstantId, ConstantInfo> {
153        &self.constant_functions
154    }
155    pub(crate) fn add_call(&mut self, internal_fn: &InternalFunctionDefinitionRef, comment: &str) {
156        let call_comment = &format!("calling {} ({})", internal_fn.assigned_name, comment);
157
158        if let Some(found) = self.function_infos.get(&internal_fn.program_unique_id) {
159            self.builder.add_call(&found.starts_at_ip, call_comment);
160        } else {
161            let patch_position = self.builder.add_call_placeholder(call_comment);
162            self.function_fixups.push(FunctionFixup {
163                patch_position,
164                fn_id: internal_fn.program_unique_id,
165            });
166        }
167    }
168    #[must_use]
169    pub fn comments(&self) -> &[String] {
170        &self.builder.comments
171    }
172
173    pub fn finalize(&mut self) {
174        for function_fixup in &self.function_fixups {
175            let func = self.function_infos.get(&function_fixup.fn_id).unwrap();
176            self.builder.patch_call(
177                PatchPosition(InstructionPosition(function_fixup.patch_position.0.0)),
178                &func.starts_at_ip,
179            );
180        }
181    }
182
183    #[must_use]
184    pub fn take_instructions_and_constants(
185        self,
186    ) -> (
187        Vec<BinaryInstruction>,
188        Vec<u8>,
189        SeqMap<ConstantId, ConstantInfo>,
190    ) {
191        (
192            self.builder.instructions,
193            self.constants.take_data(),
194            self.constant_functions,
195        )
196    }
197
198    pub fn gen_function_def(
199        &mut self,
200        internal_fn_def: &InternalFunctionDefinitionRef,
201        options: &GenOptions,
202        source_map_wrapper: &SourceMapWrapper,
203    ) -> Result<(), Error> {
204        assert_ne!(internal_fn_def.program_unique_id, 0);
205        self.function_infos
206            .insert(
207                internal_fn_def.program_unique_id,
208                FunctionInfo {
209                    starts_at_ip: self.builder.position(),
210                    internal_function_definition: internal_fn_def.clone(),
211                },
212            )
213            .unwrap();
214
215        let mut function_generator = FunctionCodeGen::new(self, source_map_wrapper);
216
217        function_generator.layout_variables(
218            &internal_fn_def.function_scope_state,
219            &internal_fn_def.signature.signature.return_type,
220        )?;
221
222        let ExpressionKind::Block(block_expressions) = &internal_fn_def.body.kind else {
223            panic!("function body should be a block")
224        };
225
226        if let ExpressionKind::IntrinsicCallEx(found_intrinsic_fn, _non_instantiated_arguments) =
227            &block_expressions[0].kind
228        {
229            // Intentionally do nothing
230            todo!()
231        } else {
232            let (return_type_size, _return_alignment) =
233                type_size_and_alignment(&internal_fn_def.signature.signature.return_type);
234            let ctx = Context::new(FrameMemoryRegion::new(
235                FrameMemoryAddress(0),
236                return_type_size,
237            ));
238            function_generator.gen_expression(&internal_fn_def.body, &ctx)?;
239        }
240
241        self.finalize_function(options);
242
243        Ok(())
244    }
245
246    pub fn finalize_function(&mut self, options: &GenOptions) {
247        if options.is_halt_function {
248            self.builder.add_hlt("");
249        } else {
250            self.builder.add_ret("");
251        }
252    }
253
254    pub fn reserve_space_for_constants(&mut self, constants: &[ConstantRef]) -> Result<(), Error> {
255        for constant in constants {
256            let (size, alignment) = type_size_and_alignment(&constant.resolved_type);
257
258            let constant_memory_address = self.constants.reserve(size, alignment);
259
260            let constant_memory_region = ConstantMemoryRegion {
261                addr: constant_memory_address,
262                size,
263            };
264
265            self.constant_offsets
266                .insert(constant.id, constant_memory_region)
267                .unwrap();
268        }
269
270        Ok(())
271    }
272    pub fn gen_constants_expression_functions_in_order(
273        &mut self,
274        constants: &[ConstantRef],
275        source_map_wrapper: &SourceMapWrapper,
276    ) -> Result<(), Error> {
277        for constant in constants {
278            let target_region = *self.constant_offsets.get(&constant.id).unwrap();
279            let ip = self.builder.position();
280            {
281                let mut function_generator = FunctionCodeGen::new(self, source_map_wrapper);
282
283                let constant_target_ctx = Context::new(FrameMemoryRegion::new(
284                    FrameMemoryAddress(0),
285                    target_region.size,
286                ));
287                function_generator.gen_expression(&constant.expr, &constant_target_ctx)?;
288                self.finalize_function(&GenOptions {
289                    is_halt_function: true,
290                });
291            }
292
293            let constant_info = ConstantInfo {
294                ip,
295                target_constant_memory: target_region,
296                constant_ref: constant.clone(),
297            };
298
299            self.constant_functions
300                .insert(constant.id, constant_info)
301                .unwrap();
302        }
303
304        Ok(())
305    }
306
307    /// # Errors
308    ///
309    pub fn gen_main_function(
310        &mut self,
311        main: &InternalMainExpression,
312        options: &GenOptions,
313        source_map_lookup: &SourceMapWrapper,
314    ) -> Result<(), Error> {
315        let mut function_generator = FunctionCodeGen::new(self, source_map_lookup);
316
317        function_generator.layout_variables(&main.function_scope_state, &main.expression.ty)?;
318        let empty_ctx = Context::new(FrameMemoryRegion::default());
319        function_generator.gen_expression(&main.expression, &empty_ctx)?;
320        self.finalize_function(options);
321        Ok(())
322    }
323}
324
325pub struct FunctionCodeGen<'a> {
326    state: &'a mut CodeGenState,
327    variable_offsets: SeqMap<usize, FrameMemoryRegion>,
328    frame_size: FrameMemorySize,
329    //extra_frame_allocator: ScopeAllocator,
330    temp_allocator: ScopeAllocator,
331    argument_allocator: ScopeAllocator,
332    source_map_lookup: &'a SourceMapWrapper<'a>,
333}
334
335impl<'a> FunctionCodeGen<'a> {
336    #[must_use]
337    pub fn new(state: &'a mut CodeGenState, source_map_lookup: &'a SourceMapWrapper) -> Self {
338        Self {
339            state,
340            variable_offsets: SeqMap::default(),
341            frame_size: FrameMemorySize(0),
342            //  extra_frame_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
343            temp_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
344            argument_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
345            source_map_lookup,
346        }
347    }
348}
349
350impl FunctionCodeGen<'_> {
351    #[allow(clippy::too_many_lines)]
352    pub(crate) fn gen_single_intrinsic_call(
353        &mut self,
354        intrinsic_fn: &IntrinsicFunction,
355        self_addr: Option<FrameMemoryRegion>,
356        arguments: &[ArgumentExpressionOrLocation],
357        ctx: &Context,
358    ) -> Result<(), Error> {
359        match intrinsic_fn {
360            // Fixed
361            IntrinsicFunction::FloatRound => todo!(),
362            IntrinsicFunction::FloatFloor => todo!(),
363            IntrinsicFunction::FloatSqrt => todo!(),
364            IntrinsicFunction::FloatSign => todo!(),
365            IntrinsicFunction::FloatAbs => todo!(),
366            IntrinsicFunction::FloatRnd => todo!(),
367            IntrinsicFunction::FloatCos => todo!(),
368            IntrinsicFunction::FloatSin => todo!(),
369            IntrinsicFunction::FloatAcos => todo!(),
370            IntrinsicFunction::FloatAsin => todo!(),
371            IntrinsicFunction::FloatAtan2 => todo!(),
372            IntrinsicFunction::FloatMin => todo!(),
373            IntrinsicFunction::FloatMax => todo!(),
374            IntrinsicFunction::FloatClamp => todo!(),
375            // Int
376            IntrinsicFunction::IntAbs => todo!(),
377            IntrinsicFunction::IntRnd => todo!(),
378            IntrinsicFunction::IntMax => todo!(),
379            IntrinsicFunction::IntMin => todo!(),
380            IntrinsicFunction::IntClamp => todo!(),
381            IntrinsicFunction::IntToFloat => todo!(),
382
383            // String
384            IntrinsicFunction::StringLen => {
385                self.state.builder.add_string_len(
386                    ctx.addr(),
387                    FrameMemoryAddressIndirectPointer(self_addr.unwrap().addr),
388                    "get the length",
389                );
390                Ok(())
391            }
392
393            // Vec
394            IntrinsicFunction::VecFromSlice => {
395                let slice_variable = &arguments[0];
396                let slice_region = self.gen_for_access_or_location_ex(slice_variable)?;
397                let (element_size, element_alignment) =
398                    type_size_and_alignment(&slice_variable.ty());
399                self.state.builder.add_vec_from_slice(
400                    ctx.addr(),
401                    slice_region.addr,
402                    element_size,
403                    CountU16(slice_region.size.0 / element_size.0),
404                    "create vec from slice",
405                );
406                Ok(())
407            }
408            IntrinsicFunction::VecPush => todo!(),
409            IntrinsicFunction::VecPop => todo!(),
410            IntrinsicFunction::VecRemoveIndex => todo!(),
411            IntrinsicFunction::VecClear => todo!(),
412            IntrinsicFunction::VecCreate => todo!(),
413            IntrinsicFunction::VecSubscript => todo!(),
414            IntrinsicFunction::VecSubscriptMut => todo!(),
415            IntrinsicFunction::VecSubscriptRange => todo!(),
416            IntrinsicFunction::VecIter => todo!(),
417            IntrinsicFunction::VecIterMut => todo!(),
418            IntrinsicFunction::VecFor => todo!(),
419            IntrinsicFunction::VecWhile => todo!(),
420            IntrinsicFunction::VecFind => todo!(),
421            IntrinsicFunction::VecSelfPush => todo!(),
422            IntrinsicFunction::VecSelfExtend => todo!(),
423            IntrinsicFunction::VecLen => todo!(),
424            IntrinsicFunction::VecIsEmpty => todo!(),
425
426            // Map
427            IntrinsicFunction::MapCreate => todo!(),
428            IntrinsicFunction::MapFromSlicePair => {
429                let slice_pair_argument = &arguments[0];
430                let ArgumentExpressionOrLocation::Expression(expr) = slice_pair_argument else {
431                    panic!();
432                };
433
434                let ExpressionKind::Literal(some_lit) = &expr.kind else {
435                    panic!();
436                };
437
438                let Literal::SlicePair(slice_type, expression_pairs) = some_lit else {
439                    panic!();
440                };
441
442                let slice_pair_info = self.gen_slice_pair_literal(slice_type, expression_pairs);
443                self.state.builder.add_map_new_from_slice(
444                    ctx.addr(),
445                    slice_pair_info.addr.to_addr(),
446                    slice_pair_info.key_size,
447                    slice_pair_info.value_size,
448                    slice_pair_info.element_count,
449                    "create map from temporary slice pair",
450                );
451
452                Ok(())
453            }
454            IntrinsicFunction::MapHas => todo!(),
455            IntrinsicFunction::MapRemove => {
456                let ArgumentExpressionOrLocation::Expression(key_argument) = &arguments[0] else {
457                    panic!("must be expression for key");
458                };
459                self.gen_intrinsic_map_remove(self_addr.unwrap(), key_argument, ctx)
460            }
461            IntrinsicFunction::MapIter => todo!(),
462            IntrinsicFunction::MapIterMut => todo!(),
463            IntrinsicFunction::MapLen => todo!(),
464            IntrinsicFunction::MapIsEmpty => todo!(),
465            IntrinsicFunction::MapSubscript => todo!(),
466            IntrinsicFunction::MapSubscriptSet => todo!(),
467            IntrinsicFunction::MapSubscriptMut => todo!(),
468            IntrinsicFunction::MapSubscriptMutCreateIfNeeded => todo!(),
469
470            // Map2
471            IntrinsicFunction::Map2Remove => todo!(),
472            IntrinsicFunction::Map2Insert => todo!(),
473            IntrinsicFunction::Map2GetColumn => todo!(),
474            IntrinsicFunction::Map2GetRow => todo!(),
475            IntrinsicFunction::Map2Get => todo!(),
476            IntrinsicFunction::Map2Has => todo!(),
477            IntrinsicFunction::Map2Create => todo!(),
478
479            // Sparse
480            IntrinsicFunction::SparseCreate => todo!(),
481            IntrinsicFunction::SparseFromSlice => todo!(),
482            IntrinsicFunction::SparseIter => todo!(),
483            IntrinsicFunction::SparseIterMut => todo!(),
484            IntrinsicFunction::SparseSubscript => todo!(),
485            IntrinsicFunction::SparseSubscriptMut => todo!(),
486            IntrinsicFunction::SparseHas => todo!(),
487            IntrinsicFunction::SparseRemove => todo!(),
488
489            // Grid
490            IntrinsicFunction::GridCreate => todo!(),
491            IntrinsicFunction::GridFromSlice => todo!(),
492            IntrinsicFunction::GridSet => todo!(),
493            IntrinsicFunction::GridGet => todo!(),
494            IntrinsicFunction::GridGetColumn => todo!(),
495
496            IntrinsicFunction::Float2Magnitude => todo!(),
497
498            IntrinsicFunction::SparseAdd => todo!(),
499            IntrinsicFunction::SparseNew => todo!(),
500        }
501    }
502
503    fn gen_intrinsic_map_remove(
504        &mut self,
505        map_region: FrameMemoryRegion,
506        key_expr: &Expression,
507        ctx: &Context,
508    ) -> Result<(), Error> {
509        let key_region = self.gen_expression_for_access(key_expr)?;
510
511        self.state
512            .builder
513            .add_map_remove(map_region.addr, key_region.addr, "");
514
515        Ok(())
516    }
517
518    pub fn reserve(ty: &Type, allocator: &mut ScopeAllocator) -> FrameMemoryRegion {
519        let (size, alignment) = type_size_and_alignment(ty);
520        allocator.reserve(size, alignment)
521    }
522
523    /// # Errors
524    ///
525    pub fn layout_variables(
526        &mut self,
527        variables: &Vec<VariableRef>,
528        return_type: &Type,
529    ) -> Result<(), Error> {
530        let mut allocator = ScopeAllocator::new(FrameMemoryRegion::new(
531            FrameMemoryAddress(0),
532            MemorySize(1024),
533        ));
534        let _current_offset = Self::reserve(return_type, &mut allocator);
535
536        let mut enter_comment = "variables:\n".to_string();
537
538        for var_ref in variables {
539            let var_target = Self::reserve(&var_ref.resolved_type, &mut allocator);
540            trace!(?var_ref.assigned_name, ?var_target, "laying out");
541            enter_comment += &format!(
542                "  ${:04X}:{} {}\n",
543                var_target.addr.0, var_target.size.0, var_ref.assigned_name
544            );
545            self.variable_offsets
546                .insert(var_ref.unique_id_within_function, var_target)
547                .map_err(|_| self.create_err(ErrorKind::VariableNotUnique, &var_ref.name))?;
548        }
549
550        let extra_frame_size = MemorySize(80);
551        let extra_target = FrameMemoryRegion::new(allocator.addr(), extra_frame_size);
552        self.frame_size = allocator.addr().as_size().add(extra_frame_size);
553
554        self.state
555            .builder
556            .add_enter(self.frame_size, &enter_comment);
557
558        const ARGUMENT_MAX_SIZE: u16 = 256;
559        self.argument_allocator = ScopeAllocator::new(FrameMemoryRegion::new(
560            FrameMemoryAddress(self.frame_size.0),
561            MemorySize(ARGUMENT_MAX_SIZE),
562        ));
563
564        self.temp_allocator = ScopeAllocator::new(FrameMemoryRegion::new(
565            FrameMemoryAddress(self.frame_size.0 + ARGUMENT_MAX_SIZE),
566            MemorySize(1024),
567        ));
568
569        Ok(())
570    }
571
572    pub fn temp_memory_region_for_type(&mut self, ty: &Type, comment: &str) -> FrameMemoryRegion {
573        let new_target_info = reserve_space_for_type(ty, &mut self.temp_allocator);
574        new_target_info
575    }
576
577    pub fn temp_space_for_type(&mut self, ty: &Type, comment: &str) -> Context {
578        Context::new(self.temp_memory_region_for_type(ty, comment))
579    }
580
581    /// # Panics
582    ///
583    #[allow(clippy::single_match_else)]
584    pub fn gen_expression_for_access(
585        &mut self,
586        expr: &Expression,
587    ) -> Result<FrameMemoryRegion, Error> {
588        let (region, _gen_result) = self.gen_expression_for_access_internal(expr)?;
589
590        Ok(region)
591    }
592
593    /// # Panics
594    ///
595    #[allow(clippy::single_match_else)]
596    pub fn gen_expression_for_access_internal(
597        &mut self,
598        expr: &Expression,
599    ) -> Result<(FrameMemoryRegion, GeneratedExpressionResult), Error> {
600        match &expr.kind {
601            ExpressionKind::VariableAccess(var_ref) => {
602                let frame_address = self
603                    .variable_offsets
604                    .get(&var_ref.unique_id_within_function)
605                    .unwrap();
606
607                return Ok((*frame_address, GeneratedExpressionResult::default()));
608            }
609
610            ExpressionKind::Literal(lit) => match lit {
611                Literal::Slice(slice_type, expressions) => {
612                    return Ok((
613                        self.gen_slice_literal(slice_type, expressions)?,
614                        GeneratedExpressionResult::default(),
615                    ));
616                }
617                Literal::SlicePair(slice_pair_type, pairs) => {
618                    let info = self.gen_slice_pair_literal(slice_pair_type, pairs);
619                    return Ok((
620                        FrameMemoryRegion::new(
621                            info.addr.0,
622                            MemorySize(info.element_count.0 * info.element_size.0),
623                        ),
624                        GeneratedExpressionResult::default(),
625                    ));
626                }
627                _ => {}
628            },
629            _ => {}
630        };
631
632        let temp_ctx = self.temp_space_for_type(&expr.ty, "expression");
633
634        let expression_result = self.gen_expression(expr, &temp_ctx)?;
635
636        Ok((temp_ctx.target(), expression_result))
637    }
638
639    pub(crate) fn extra_frame_space_for_type(&mut self, ty: &Type) -> Context {
640        let target = Self::reserve(ty, &mut self.temp_allocator);
641        Context::new(target)
642    }
643
644    fn debug_node(&self, node: &Node) {
645        let line_info = self.source_map_lookup.get_line(&node.span);
646        let span_text = self.source_map_lookup.get_text_span(&node.span);
647        eprintln!(
648            "{}:{}:{}> {}",
649            line_info.relative_file_name, line_info.row, line_info.col, span_text,
650        );
651        //info!(?source_code_line, "generating");
652    }
653
654    fn debug_instructions(&mut self) {
655        let end_ip = self.state.builder.instructions.len() - 1;
656        let instructions_to_disasm =
657            &self.state.builder.instructions[self.state.debug_last_ip..=end_ip];
658        let mut descriptions = Vec::new();
659        for x in instructions_to_disasm {
660            descriptions.push(String::new());
661        }
662        let output = disasm_instructions_color(
663            instructions_to_disasm,
664            &InstructionPosition(self.state.debug_last_ip as u16),
665            &descriptions,
666            &SeqMap::default(),
667        );
668        eprintln!("{output}");
669        self.state.debug_last_ip = end_ip + 1;
670    }
671
672    pub fn gen_expression(
673        &mut self,
674        expr: &Expression,
675        ctx: &Context,
676    ) -> Result<GeneratedExpressionResult, Error> {
677        self.debug_node(&expr.node);
678        let result = match &expr.kind {
679            ExpressionKind::InterpolatedString(_) => todo!(),
680
681            ExpressionKind::ConstantAccess(constant_ref) => self
682                .gen_constant_access(constant_ref, ctx)
683                .map(|_| GeneratedExpressionResult::default()),
684            ExpressionKind::TupleDestructuring(variables, tuple_types, tuple_expression) => self
685                .gen_tuple_destructuring(variables, tuple_types, tuple_expression)
686                .map(|_| GeneratedExpressionResult::default()),
687
688            ExpressionKind::Assignment(target_mut_location_expr, source_expr) => self
689                .gen_assignment(target_mut_location_expr, source_expr)
690                .map(|_| GeneratedExpressionResult::default()),
691            ExpressionKind::VariableAccess(variable_ref) => self
692                .gen_variable_access(variable_ref, ctx)
693                .map(|_| GeneratedExpressionResult::default()),
694            ExpressionKind::InternalFunctionAccess(function) => self
695                .internal_function_access(function, ctx)
696                .map(|_| GeneratedExpressionResult::default()),
697            ExpressionKind::BinaryOp(operator) => self.gen_binary_operator(operator, ctx),
698            ExpressionKind::UnaryOp(operator) => self
699                .gen_unary_operator(operator, ctx)
700                .map(|_| GeneratedExpressionResult::default()),
701            ExpressionKind::PostfixChain(start, chain) => self
702                .gen_postfix_chain(start, chain, ctx)
703                .map(|_| GeneratedExpressionResult::default()),
704            ExpressionKind::VariableDefinition(variable, expression) => self
705                .gen_variable_definition(variable, expression, ctx)
706                .map(|_| GeneratedExpressionResult::default()),
707            ExpressionKind::VariableReassignment(variable, expression) => self
708                .gen_variable_reassignment(variable, expression, ctx)
709                .map(|_| GeneratedExpressionResult::default()),
710            ExpressionKind::StructInstantiation(struct_literal) => self
711                .gen_struct_literal(struct_literal, ctx)
712                .map(|()| GeneratedExpressionResult::default()),
713            ExpressionKind::AnonymousStructLiteral(anon_struct) => self
714                .gen_anonymous_struct_literal(anon_struct, ctx)
715                .map(|_| GeneratedExpressionResult::default()),
716            ExpressionKind::Literal(basic_literal) => self
717                .gen_literal(basic_literal, ctx)
718                .map(|_| GeneratedExpressionResult::default()),
719            ExpressionKind::Option(maybe_option) => self
720                .gen_option_expression(maybe_option.as_deref(), ctx)
721                .map(|_| GeneratedExpressionResult::default()),
722            ExpressionKind::ForLoop(a, b, c) => self
723                .gen_for_loop(a, b, c)
724                .map(|_| GeneratedExpressionResult::default()),
725            ExpressionKind::WhileLoop(condition, expression) => self
726                .gen_while_loop(condition, expression, ctx)
727                .map(|_| GeneratedExpressionResult::default()),
728            ExpressionKind::Block(expressions) => self
729                .gen_block(expressions, ctx)
730                .map(|_| GeneratedExpressionResult::default()),
731            ExpressionKind::Match(match_expr) => self
732                .gen_match(match_expr, ctx)
733                .map(|_| GeneratedExpressionResult::default()),
734            ExpressionKind::Guard(guards) => self
735                .gen_guard(guards, ctx)
736                .map(|_| GeneratedExpressionResult::default()),
737            ExpressionKind::If(conditional, true_expr, false_expr) => self
738                .gen_if(conditional, true_expr, false_expr.as_deref(), ctx)
739                .map(|_| GeneratedExpressionResult::default()),
740            ExpressionKind::When(bindings, true_expr, false_expr) => self
741                .gen_when(bindings, true_expr, false_expr.as_deref(), ctx)
742                .map(|_| GeneratedExpressionResult::default()),
743            ExpressionKind::CompoundAssignment(target_location, operator_kind, source_expr) => self
744                .compound_assignment(target_location, operator_kind, source_expr, ctx)
745                .map(|_| GeneratedExpressionResult::default()),
746            ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments) => self
747                .gen_intrinsic_call_ex(intrinsic_fn, arguments, ctx)
748                .map(|_| GeneratedExpressionResult::default()),
749
750            ExpressionKind::Lambda(vec, x) => {
751                todo!()
752            }
753            // --------- Not high prio
754            ExpressionKind::CoerceOptionToBool(_) => todo!(),
755            ExpressionKind::FunctionValueCall(_, _, _) => todo!(),
756
757            // --------- TO BE REMOVED
758            ExpressionKind::IntrinsicFunctionAccess(_) => todo!(), // TODO: IntrinsicFunctionAccess should be reduced away in analyzer
759            ExpressionKind::ExternalFunctionAccess(_) => todo!(), // TODO: ExternalFunctionAccess should be reduced away in analyzer
760        };
761
762        self.debug_instructions();
763
764        result
765    }
766
767    fn gen_unary_operator(
768        &mut self,
769        unary_operator: &UnaryOperator,
770        ctx: &Context,
771    ) -> Result<(), Error> {
772        match &unary_operator.kind {
773            UnaryOperatorKind::Not => {}
774            UnaryOperatorKind::Negate => match (&unary_operator.left.ty) {
775                Type::Int => {
776                    let left_source = self.gen_expression_for_access(&unary_operator.left)?;
777                    self.state
778                        .builder
779                        .add_neg_i32(ctx.addr(), left_source.addr, "negate i32");
780                }
781
782                Type::Float => {
783                    let left_source = self.gen_expression_for_access(&unary_operator.left)?;
784                    self.state
785                        .builder
786                        .add_neg_f32(ctx.addr(), left_source.addr, "negate f32");
787                }
788                _ => todo!(),
789            },
790        }
791
792        Ok(())
793    }
794
795    fn gen_binary_operator(
796        &mut self,
797        binary_operator: &BinaryOperator,
798        ctx: &Context,
799    ) -> Result<GeneratedExpressionResult, Error> {
800        match (&binary_operator.left.ty, &binary_operator.right.ty) {
801            (Type::Int, Type::Int) => self.gen_binary_operator_i32(binary_operator, ctx),
802            (Type::Bool, Type::Bool) => self.gen_binary_operator_bool(binary_operator),
803            (Type::String, Type::String) => self.gen_binary_operator_string(binary_operator, ctx),
804            _ => todo!(),
805        }
806    }
807
808    fn gen_binary_operator_i32(
809        &mut self,
810        binary_operator: &BinaryOperator,
811        ctx: &Context,
812    ) -> Result<GeneratedExpressionResult, Error> {
813        let left_source = self.gen_expression_for_access(&binary_operator.left)?;
814        let right_source = self.gen_expression_for_access(&binary_operator.right)?;
815
816        match binary_operator.kind {
817            BinaryOperatorKind::Add => {
818                self.state.builder.add_add_i32(
819                    ctx.addr(),
820                    left_source.addr(),
821                    right_source.addr(),
822                    "i32 add",
823                );
824            }
825
826            BinaryOperatorKind::Subtract => todo!(),
827            BinaryOperatorKind::Multiply => {
828                self.state.builder.add_mul_i32(
829                    ctx.addr(),
830                    left_source.addr(),
831                    right_source.addr(),
832                    "i32 add",
833                );
834            }
835            BinaryOperatorKind::Divide => todo!(),
836            BinaryOperatorKind::Modulo => todo!(),
837            BinaryOperatorKind::LogicalOr => todo!(),
838            BinaryOperatorKind::LogicalAnd => todo!(),
839            BinaryOperatorKind::Equal => {
840                self.state
841                    .builder
842                    .add_eq_32(left_source.addr(), right_source.addr(), "i32 eq");
843            }
844            BinaryOperatorKind::NotEqual => todo!(),
845            BinaryOperatorKind::LessThan => {
846                self.state
847                    .builder
848                    .add_lt_i32(left_source.addr(), right_source.addr(), "i32 lt");
849            }
850            BinaryOperatorKind::LessEqual => todo!(),
851            BinaryOperatorKind::GreaterThan => {
852                self.state
853                    .builder
854                    .add_gt_i32(left_source.addr(), right_source.addr(), "i32 gt");
855            }
856            BinaryOperatorKind::GreaterEqual => todo!(),
857            BinaryOperatorKind::RangeExclusive => todo!(),
858        }
859
860        Ok(GeneratedExpressionResult {
861            has_set_bool_z_flag: true,
862        })
863    }
864
865    fn gen_binary_operator_string(
866        &mut self,
867        binary_operator: &BinaryOperator,
868        ctx: &Context,
869    ) -> Result<GeneratedExpressionResult, Error> {
870        let left_source = self.gen_expression_for_access(&binary_operator.left)?;
871        let right_source = self.gen_expression_for_access(&binary_operator.right)?;
872
873        match binary_operator.kind {
874            BinaryOperatorKind::Add => {
875                self.state.builder.add_string_append(
876                    ctx.addr(),
877                    left_source.addr(),
878                    right_source.addr(),
879                    "string add",
880                );
881            }
882
883            BinaryOperatorKind::Equal => todo!(),
884            BinaryOperatorKind::NotEqual => todo!(),
885            _ => panic!("illegal string operator"),
886        }
887
888        Ok(GeneratedExpressionResult {
889            has_set_bool_z_flag: false,
890        })
891    }
892
893    fn gen_binary_operator_bool(
894        &mut self,
895        binary_operator: &BinaryOperator,
896    ) -> Result<GeneratedExpressionResult, Error> {
897        match binary_operator.kind {
898            BinaryOperatorKind::LogicalOr => {
899                // this updates the z flag
900                self.gen_boolean_access_set_z_flag(&binary_operator.left);
901
902                let jump_after_patch = self
903                    .state
904                    .builder
905                    .add_jmp_if_equal_placeholder("skip rhs `or` expression");
906
907                // this updates the z flag
908                self.gen_boolean_access_set_z_flag(&binary_operator.right);
909
910                self.state.builder.patch_jump_here(jump_after_patch);
911            }
912            BinaryOperatorKind::LogicalAnd => {
913                // this updates the z flag
914                self.gen_boolean_access_set_z_flag(&binary_operator.left);
915
916                let jump_after_patch = self
917                    .state
918                    .builder
919                    .add_jmp_if_not_equal_placeholder("skip rhs `and` expression");
920
921                // this updates the z flag
922                self.gen_boolean_access_set_z_flag(&binary_operator.right);
923
924                self.state.builder.patch_jump_here(jump_after_patch);
925            }
926            _ => {
927                panic!("unknown operator")
928            }
929        }
930
931        Ok(GeneratedExpressionResult {
932            has_set_bool_z_flag: true,
933        })
934    }
935
936    fn gen_condition_context(
937        &mut self,
938        condition: &BooleanExpression,
939    ) -> Result<(Context, PatchPosition), Error> {
940        let condition_ctx = self.extra_frame_space_for_type(&Type::Bool);
941        self.gen_expression(&condition.expression, &condition_ctx)?;
942
943        let jump_on_false_condition = self
944            .state
945            .builder
946            .add_jmp_if_not_equal_placeholder("jump boolean condition false");
947
948        Ok((condition_ctx, jump_on_false_condition))
949    }
950
951    fn gen_boolean_access_set_z_flag(&mut self, condition: &Expression) -> Result<(), Error> {
952        let (frame_memory_region, gen_result) =
953            self.gen_expression_for_access_internal(condition)?;
954
955        if !gen_result.has_set_bool_z_flag {
956            self.state.builder.add_tst8(
957                frame_memory_region.addr,
958                "convert to boolean expression (update z flag)",
959            );
960        }
961
962        Ok(())
963    }
964
965    fn gen_boolean_expression(&mut self, condition: &BooleanExpression) -> Result<(), Error> {
966        self.gen_boolean_access_set_z_flag(&condition.expression)
967    }
968
969    fn gen_if(
970        &mut self,
971        condition: &BooleanExpression,
972        true_expr: &Expression,
973        maybe_false_expr: Option<&Expression>,
974        ctx: &Context,
975    ) -> Result<(), Error> {
976        let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition)?;
977
978        // True expression just takes over our target
979        self.gen_expression(true_expr, ctx)?;
980
981        if let Some(false_expr) = maybe_false_expr {
982            // we need to help the true expression to jump over false
983            let skip_false_if_true = self
984                .state
985                .builder
986                .add_jump_placeholder("condition is false skip");
987
988            // If the expression was false, it should continue here
989            self.state.builder.patch_jump_here(jump_on_false_condition);
990
991            // Else expression also can just take over our if target
992            self.gen_expression(false_expr, ctx)?;
993
994            self.state.builder.patch_jump_here(skip_false_if_true);
995        } else {
996            self.state.builder.patch_jump_here(jump_on_false_condition);
997        }
998
999        Ok(())
1000    }
1001
1002    fn gen_while_loop(
1003        &mut self,
1004        condition: &BooleanExpression,
1005        expression: &Expression,
1006        ctx: &Context,
1007    ) -> Result<(), Error> {
1008        // `while` loops are only for side effects, make sure that the target size is zero (Unit)
1009        assert_eq!(ctx.target_size().0, 0);
1010
1011        let ip_for_condition = self.state.builder.position();
1012
1013        let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition)?;
1014
1015        // Expression is only for side effects
1016        let mut unit_ctx = self.temp_space_for_type(&Type::Unit, "while body expression");
1017        self.gen_expression(expression, &mut unit_ctx)?;
1018
1019        // Always jump to the condition again to see if it is true
1020        self.state
1021            .builder
1022            .add_jmp(ip_for_condition, "jmp to while condition");
1023
1024        self.state.builder.patch_jump_here(jump_on_false_condition);
1025
1026        Ok(())
1027    }
1028
1029    fn gen_location_argument(
1030        &mut self,
1031        argument: &SingleLocationExpression,
1032        ctx: &Context,
1033        comment: &str,
1034    ) -> Result<(), Error> {
1035        let region = self.gen_lvalue_address(argument)?;
1036
1037        self.state
1038            .builder
1039            .add_mov(ctx.addr(), region.addr, region.size, comment);
1040
1041        Ok(())
1042    }
1043
1044    fn gen_variable_assignment(
1045        &mut self,
1046        variable: &VariableRef,
1047        mut_or_immutable_expression: &MutOrImmutableExpression,
1048        ctx: &Context,
1049    ) -> Result<(), Error> {
1050        let target_relative_frame_pointer = self
1051            .variable_offsets
1052            .get(&variable.unique_id_within_function)
1053            .unwrap_or_else(|| panic!("{}", variable.assigned_name));
1054
1055        let init_ctx =
1056            ctx.with_target(*target_relative_frame_pointer, "variable assignment target");
1057
1058        self.gen_mut_or_immute(mut_or_immutable_expression, &init_ctx)
1059    }
1060
1061    fn gen_assignment(
1062        &mut self,
1063        lhs: &SingleMutLocationExpression,
1064        rhs: &Expression,
1065    ) -> Result<(), Error> {
1066        let lhs_addr = self.gen_lvalue_address(&lhs.0)?;
1067        let access = self.gen_expression_for_access(rhs)?;
1068
1069        self.state
1070            .builder
1071            .add_mov(lhs_addr.addr, access.addr, access.size, "assignment");
1072
1073        Ok(())
1074    }
1075
1076    fn gen_variable_definition(
1077        &mut self,
1078        variable: &VariableRef,
1079        mut_or_immutable_expression: &MutOrImmutableExpression,
1080        ctx: &Context,
1081    ) -> Result<(), Error> {
1082        self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx)
1083    }
1084
1085    fn gen_variable_reassignment(
1086        &mut self,
1087        variable: &VariableRef,
1088        mut_or_immutable_expression: &Box<MutOrImmutableExpression>,
1089        ctx: &Context,
1090    ) -> Result<(), Error> {
1091        self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx)
1092    }
1093
1094    fn copy_back_mutable_arguments(
1095        &mut self,
1096        signature: &Signature,
1097        maybe_self: Option<FrameMemoryRegion>,
1098        arguments: &Vec<ArgumentExpressionOrLocation>,
1099    ) -> Result<(), Error> {
1100        let arguments_memory_region = self.infinite_above_frame_size();
1101        let mut arguments_allocator = ScopeAllocator::new(arguments_memory_region);
1102
1103        let _argument_addr = Self::reserve(&signature.return_type, &mut arguments_allocator);
1104
1105        let mut parameters = signature.parameters.clone();
1106        if let Some(found_self) = maybe_self {
1107            let source_region =
1108                Self::reserve(&parameters[0].resolved_type, &mut arguments_allocator);
1109            self.state.builder.add_mov(
1110                found_self.addr,
1111                source_region.addr,
1112                source_region.size,
1113                "copy back to <self>",
1114            );
1115            parameters.remove(0);
1116        }
1117        for (parameter, argument) in parameters.iter().zip(arguments) {
1118            let source_region = Self::reserve(&parameter.resolved_type, &mut arguments_allocator);
1119            if !parameter.is_mutable {
1120                continue;
1121            }
1122
1123            if let ArgumentExpressionOrLocation::Location(found_location) = argument {
1124                let argument_target = self.gen_lvalue_address(found_location)?;
1125                self.state.builder.add_mov(
1126                    argument_target.addr,
1127                    source_region.addr,
1128                    source_region.size,
1129                    &format!(
1130                        "copy back mutable argument {}",
1131                        found_location.starting_variable.assigned_name
1132                    ),
1133                );
1134            } else {
1135                panic!("internal error. argument is mut but not a location")
1136            }
1137        }
1138        Ok(())
1139    }
1140    fn gen_arguments(
1141        &mut self,
1142        signature: &Signature,
1143        self_region: Option<FrameMemoryRegion>,
1144        arguments: &Vec<ArgumentExpressionOrLocation>,
1145    ) -> Result<FrameMemoryRegion, Error> {
1146        self.argument_allocator.reset();
1147        // Layout return and arguments, must be continuous space
1148        let argument_addr = Self::reserve(&signature.return_type, &mut self.argument_allocator);
1149        assert_eq!(argument_addr.addr.0, self.frame_size.0);
1150
1151        let mut argument_targets = Vec::new();
1152        let mut argument_comments = Vec::new();
1153
1154        // Layout arguments, must be continuous space
1155        for (index, type_for_parameter) in signature.parameters.iter().enumerate() {
1156            let argument_target = Self::reserve(
1157                &type_for_parameter.resolved_type,
1158                &mut self.argument_allocator,
1159            );
1160            let arg_ctx = Context::new(argument_target);
1161            argument_targets.push(arg_ctx);
1162            argument_comments.push(format!("argument {}", type_for_parameter.name));
1163        }
1164
1165        if let Some(push_self) = self_region {
1166            self.state.builder.add_mov(
1167                argument_targets[0].addr(),
1168                push_self.addr,
1169                push_self.size,
1170                "<self>",
1171            );
1172            argument_targets.remove(0);
1173        }
1174
1175        for ((argument_target_ctx, argument_expr_or_loc), argument_comment) in argument_targets
1176            .iter()
1177            .zip(arguments)
1178            .zip(argument_comments)
1179        {
1180            let debug_addr = argument_target_ctx.target().addr();
1181            self.gen_argument(
1182                argument_expr_or_loc,
1183                &argument_target_ctx,
1184                &argument_comment,
1185            )?;
1186        }
1187
1188        let memory_size = argument_targets
1189            .last()
1190            .map_or(MemorySize(0), |last_target| {
1191                MemorySize(
1192                    last_target.addr().add(last_target.target_size()).0
1193                        - argument_targets[0].addr().0,
1194                )
1195            });
1196
1197        let start_addr = argument_targets
1198            .first()
1199            .map_or(FrameMemoryAddress(0), |first| first.addr());
1200
1201        Ok(FrameMemoryRegion {
1202            addr: start_addr,
1203            size: memory_size,
1204        })
1205    }
1206
1207    #[allow(clippy::too_many_lines)]
1208    fn gen_postfix_chain(
1209        &mut self,
1210        start_expression: &Expression,
1211        chain: &[Postfix],
1212        ctx: &Context,
1213    ) -> Result<(), Error> {
1214        if let ExpressionKind::InternalFunctionAccess(internal_fn) = &start_expression.kind {
1215            if chain.len() == 1 {
1216                if let PostfixKind::FunctionCall(args) = &chain[0].kind {
1217                    if let Some(intrinsic_fn) = single_intrinsic_fn(&internal_fn.body) {
1218                        self.gen_single_intrinsic_call(intrinsic_fn, None, args, ctx)?;
1219                    } else {
1220                        self.gen_arguments(&internal_fn.signature.signature, None, args)?;
1221                        self.state
1222                            .add_call(internal_fn, &format!("frame size: {}", self.frame_size)); // will be fixed up later
1223                        let (return_size, _alignment) =
1224                            type_size_and_alignment(&internal_fn.signature.signature.return_type);
1225                        if return_size.0 != 0 {
1226                            self.state.builder.add_mov(
1227                                ctx.addr(),
1228                                self.infinite_above_frame_size().addr,
1229                                return_size,
1230                                "copy the ret value to destination",
1231                            );
1232                        }
1233                        self.copy_back_mutable_arguments(
1234                            &internal_fn.signature.signature,
1235                            None,
1236                            args,
1237                        )?;
1238                    }
1239
1240                    return Ok(());
1241                }
1242            }
1243        }
1244
1245        if let ExpressionKind::ExternalFunctionAccess(external_fn) = &start_expression.kind {
1246            if chain.len() == 1 {
1247                if let PostfixKind::FunctionCall(args) = &chain[0].kind {
1248                    let total_region = self.gen_arguments(&external_fn.signature, None, args)?;
1249                    self.state.builder.add_host_call(
1250                        external_fn.id as u16,
1251                        total_region.size,
1252                        &format!("call external '{}'", external_fn.assigned_name),
1253                    );
1254                    let (return_size, _alignment) =
1255                        type_size_and_alignment(&external_fn.signature.return_type);
1256                    if return_size.0 != 0 {
1257                        self.state.builder.add_mov(
1258                            ctx.addr(),
1259                            self.infinite_above_frame_size().addr,
1260                            return_size,
1261                            "copy the ret value to destination",
1262                        );
1263                    }
1264
1265                    return Ok(());
1266                }
1267            }
1268        }
1269
1270        let mut start_source = self.gen_expression_for_access(start_expression)?;
1271
1272        for element in chain {
1273            match &element.kind {
1274                PostfixKind::StructField(anonymous_struct, field_index) => {
1275                    let (memory_offset, memory_size, _max_alignment) =
1276                        Self::get_struct_field_offset(
1277                            &anonymous_struct.field_name_sorted_fields,
1278                            *field_index,
1279                        );
1280                    start_source = FrameMemoryRegion::new(
1281                        start_source.addr.advance(memory_offset),
1282                        memory_size,
1283                    );
1284                }
1285                PostfixKind::MemberCall(function_to_call, arguments) => {
1286                    match &**function_to_call {
1287                        Function::Internal(internal_fn) => {
1288                            if let Some(intrinsic_fn) = single_intrinsic_fn(&internal_fn.body) {
1289                                self.gen_single_intrinsic_call(
1290                                    intrinsic_fn,
1291                                    Some(start_source),
1292                                    arguments,
1293                                    ctx,
1294                                )?;
1295                            } else {
1296                                self.gen_arguments(
1297                                    &internal_fn.signature.signature,
1298                                    Some(start_source),
1299                                    arguments,
1300                                )?;
1301                                self.state.add_call(
1302                                    internal_fn,
1303                                    &format!("frame size: {}", self.frame_size),
1304                                ); // will be fixed up later
1305
1306                                let (return_size, _alignment) = type_size_and_alignment(
1307                                    &internal_fn.signature.signature.return_type,
1308                                );
1309                                if return_size.0 != 0 {
1310                                    self.state.builder.add_mov(
1311                                        ctx.addr(),
1312                                        self.infinite_above_frame_size().addr,
1313                                        return_size,
1314                                        "copy the return value to destination",
1315                                    );
1316                                }
1317
1318                                self.copy_back_mutable_arguments(
1319                                    &internal_fn.signature.signature,
1320                                    Some(start_source),
1321                                    arguments,
1322                                )?;
1323                            }
1324                        }
1325                        Function::External(external_fn) => {
1326                            //self.state.builder.add_host_call(external_fn.id);
1327                        }
1328                    }
1329                }
1330                PostfixKind::FunctionCall(arguments) => {
1331                    //self.gen_arguments(arguments);
1332                    //self.state.add_call(start_expression)
1333                }
1334                PostfixKind::OptionalChainingOperator => todo!(),
1335                PostfixKind::NoneCoalescingOperator(_) => todo!(),
1336            }
1337        }
1338
1339        Ok(())
1340    }
1341
1342    fn gen_tuple(&mut self, expressions: &[Expression], ctx: &Context) -> Result<(), Error> {
1343        let mut scope = ScopeAllocator::new(ctx.target());
1344
1345        for expr in expressions {
1346            let (memory_size, alignment) = type_size_and_alignment(&expr.ty);
1347            let start_addr = scope.allocate(memory_size, alignment);
1348            let element_region = FrameMemoryRegion::new(start_addr, memory_size);
1349            let element_ctx = Context::new(element_region);
1350            self.gen_expression(expr, &element_ctx)?;
1351        }
1352
1353        Ok(())
1354    }
1355
1356    fn get_struct_field_offset(
1357        fields: &SeqMap<String, StructTypeField>,
1358        index_to_find: usize,
1359    ) -> (MemoryOffset, MemorySize, MemoryAlignment) {
1360        let mut offset = 0;
1361
1362        for (index, (_name, field)) in fields.iter().enumerate() {
1363            let (struct_field_size, struct_field_align) =
1364                type_size_and_alignment(&field.field_type);
1365            if index == index_to_find {
1366                return (MemoryOffset(offset), struct_field_size, struct_field_align);
1367            }
1368
1369            offset += struct_field_size.0;
1370        }
1371
1372        panic!("field not found");
1373    }
1374
1375    fn gen_anonymous_struct(
1376        &mut self,
1377        anon_struct_type: &AnonymousStructType,
1378        source_order_expressions: &Vec<(usize, Expression)>,
1379        base_context: &Context,
1380    ) -> Result<(), Error> {
1381        for (field_index, expression) in source_order_expressions {
1382            let (field_memory_offset, field_size, _field_alignment) = Self::get_struct_field_offset(
1383                &anon_struct_type.field_name_sorted_fields,
1384                *field_index,
1385            );
1386            let field_ctx = base_context.with_offset(field_memory_offset, field_size);
1387            self.gen_expression(expression, &field_ctx)?;
1388        }
1389
1390        Ok(())
1391    }
1392
1393    fn gen_literal(&mut self, literal: &Literal, ctx: &Context) -> Result<(), Error> {
1394        match literal {
1395            Literal::IntLiteral(int) => {
1396                self.state.builder.add_ld32(ctx.addr(), *int, "int literal");
1397            }
1398            Literal::FloatLiteral(fixed_point) => {
1399                self.state
1400                    .builder
1401                    .add_ld32(ctx.addr(), fixed_point.inner(), "float literal");
1402            }
1403            Literal::NoneLiteral => {
1404                self.state.builder.add_ld8(ctx.addr(), 0, "none literal");
1405            }
1406            Literal::BoolLiteral(truthy) => {
1407                self.state
1408                    .builder
1409                    .add_ld8(ctx.addr(), u8::from(*truthy), "bool literal");
1410            }
1411
1412            Literal::EnumVariantLiteral(enum_type, a, b) => {
1413                self.state.builder.add_ld8(
1414                    ctx.addr(),
1415                    a.common().container_index,
1416                    &format!("enum variant {} tag", a.common().assigned_name),
1417                );
1418
1419                let starting_offset = MemoryOffset(1);
1420
1421                let (data_size, data_alignment) = match a {
1422                    EnumVariantType::Struct(enum_variant_struct) => {
1423                        layout_struct(&enum_variant_struct.anon_struct)
1424                    }
1425                    EnumVariantType::Tuple(tuple_type) => layout_tuple(&tuple_type.fields_in_order),
1426                    EnumVariantType::Nothing(_) => (MemorySize(0), MemoryAlignment::U8),
1427                };
1428
1429                let skip_octets: usize = data_alignment.into();
1430                let skip = MemorySize(skip_octets as u16);
1431                let inner_addr = ctx.addr().add(skip);
1432                let region = FrameMemoryRegion::new(inner_addr, data_size);
1433                let inner_ctx = Context::new(region);
1434
1435                //layout_union(a)
1436                match b {
1437                    EnumLiteralData::Nothing => {}
1438                    EnumLiteralData::Tuple(expressions) => {
1439                        self.gen_tuple(expressions, &inner_ctx)?;
1440                    }
1441                    EnumLiteralData::Struct(sorted_expressions) => {
1442                        if let EnumVariantType::Struct(variant_struct_type) = a {
1443                            self.gen_anonymous_struct(
1444                                &variant_struct_type.anon_struct,
1445                                sorted_expressions,
1446                                &inner_ctx,
1447                            )?;
1448                        }
1449                    }
1450                }
1451            }
1452            Literal::TupleLiteral(_tuple_type, expressions) => self.gen_tuple(expressions, ctx)?,
1453            Literal::StringLiteral(str) => {
1454                self.gen_string_literal(str, ctx);
1455            }
1456            Literal::Slice(ty, expressions) => {
1457                //self.gen_slice_literal(ty, expressions, ctx)
1458                todo!()
1459            }
1460            Literal::SlicePair(ty, expression_pairs) => {
1461                todo!()
1462            }
1463        }
1464
1465        Ok(())
1466    }
1467
1468    fn gen_string_literal(&mut self, string: &str, ctx: &Context) {
1469        let string_bytes = string.as_bytes();
1470        let string_byte_count = string_bytes.len();
1471
1472        let data_ptr = self
1473            .state
1474            .constants
1475            .allocate(string_bytes, MemoryAlignment::U8);
1476
1477        let mem_size = MemorySize(string_byte_count as u16);
1478
1479        self.state.builder.add_string_from_constant_slice(
1480            ctx.addr(),
1481            data_ptr,
1482            mem_size,
1483            "create string",
1484        );
1485        // self.gen_vec_immediate(data_ptr, mem_size, mem_size, "string", ctx);
1486    }
1487
1488    /*
1489    fn gen_vec_immediate(
1490        &mut self,
1491        data_ptr: MemoryAddress,
1492        len: MemorySize,
1493        capacity: MemorySize,
1494        comment_prefix: &str,
1495        ctx: &Context,
1496    ) {
1497        self.state
1498            .builder
1499            .add_ld_u16(ctx.addr(), len.0, &format!("{} len", comment_prefix));
1500
1501        self.state.builder.add_ld_u16(
1502            ctx.addr().add(MemorySize(2)),
1503            capacity.0,
1504            &format!("{} capacity", comment_prefix),
1505        );
1506
1507        self.state.builder.add_ld_u16(
1508            ctx.addr().add(MemorySize(4)),
1509            data_ptr.0,
1510            &format!("{} ptr", comment_prefix),
1511        );
1512    }
1513
1514
1515     */
1516    fn gen_option_expression(
1517        &mut self,
1518        maybe_option: Option<&Expression>,
1519        ctx: &Context,
1520    ) -> Result<(), Error> {
1521        if let Some(found_value) = maybe_option {
1522            self.state.builder.add_ld8(ctx.addr(), 1, "option Some tag"); // 1 signals `Some`
1523            let (inner_size, inner_alignment) = type_size_and_alignment(&found_value.ty);
1524            let one_offset_ctx = ctx.with_offset(inner_alignment.into(), inner_size);
1525
1526            self.gen_expression(found_value, &one_offset_ctx)?; // Fills in more of the union
1527        } else {
1528            self.state.builder.add_ld8(ctx.addr(), 0, "option None tag"); // 0 signals `None`
1529            // No real need to clear the rest of the memory
1530        }
1531
1532        Ok(())
1533    }
1534
1535    fn gen_for_loop_vec(
1536        &mut self,
1537        for_pattern: &ForPattern,
1538        collection_expr: &MutOrImmutableExpression,
1539    ) -> Result<(InstructionPosition, PatchPosition), Error> {
1540        let collection_region = self.gen_for_access_or_location(collection_expr)?;
1541
1542        let temp_iterator_region = self
1543            .temp_allocator
1544            .allocate(MemorySize(VEC_ITERATOR_SIZE), VEC_ITERATOR_ALIGNMENT);
1545        self.state.builder.add_vec_iter_init(
1546            temp_iterator_region,
1547            FrameMemoryAddressIndirectPointer(collection_region.addr),
1548            "initialize vec iterator",
1549        );
1550
1551        let loop_ip = self.state.builder.position();
1552
1553        let placeholder_position = match for_pattern {
1554            ForPattern::Single(variable) => {
1555                let target_variable = self
1556                    .variable_offsets
1557                    .get(&variable.unique_id_within_function)
1558                    .unwrap();
1559                self.state.builder.add_vec_iter_next_placeholder(
1560                    temp_iterator_region,
1561                    target_variable.addr,
1562                    "move to next or jump over",
1563                )
1564            }
1565            ForPattern::Pair(variable_a, variable_b) => {
1566                let target_variable_a = self
1567                    .variable_offsets
1568                    .get(&variable_a.unique_id_within_function)
1569                    .unwrap();
1570                let target_variable_b = self
1571                    .variable_offsets
1572                    .get(&variable_b.unique_id_within_function)
1573                    .unwrap();
1574                self.state.builder.add_vec_iter_next_pair_placeholder(
1575                    temp_iterator_region,
1576                    target_variable_a.addr,
1577                    target_variable_b.addr,
1578                    "move to next or jump over",
1579                )
1580            }
1581        };
1582
1583        Ok((loop_ip, placeholder_position))
1584    }
1585
1586    fn gen_for_loop_map(
1587        &mut self,
1588        for_pattern: &ForPattern,
1589    ) -> Result<(InstructionPosition, PatchPosition), Error> {
1590        self.state.builder.add_map_iter_init(
1591            FrameMemoryAddress(0x80),
1592            FrameMemoryAddressIndirectPointer(FrameMemoryAddress(0xffff)),
1593            "initialize map iterator",
1594        );
1595
1596        let jump_ip = self.state.builder.position();
1597
1598        match for_pattern {
1599            ForPattern::Single(_) => {
1600                self.state.builder.add_map_iter_next(
1601                    FrameMemoryAddress(0x80),
1602                    FrameMemoryAddress(0x16),
1603                    InstructionPosition(256),
1604                    "move to next or jump over",
1605                );
1606            }
1607            ForPattern::Pair(_, _) => {
1608                self.state.builder.add_map_iter_next_pair(
1609                    FrameMemoryAddress(0x80),
1610                    FrameMemoryAddress(0x16),
1611                    FrameMemoryAddress(0x16),
1612                    InstructionPosition(256),
1613                    "move to next or jump over",
1614                );
1615            }
1616        }
1617
1618        Ok((jump_ip, PatchPosition(InstructionPosition(0))))
1619    }
1620
1621    fn gen_for_loop(
1622        &mut self,
1623        for_pattern: &ForPattern,
1624        iterable: &Iterable,
1625        closure: &Box<Expression>,
1626    ) -> Result<(), Error> {
1627        // Add check if the collection is empty, to skip everything
1628
1629        // get some kind of iteration pointer
1630
1631        // check if it has reached its end
1632
1633        let collection_type = &iterable.resolved_expression.expression_or_location.ty();
1634        let (jump_ip, placeholder_position) = match collection_type {
1635            Type::String => {
1636                todo!();
1637            }
1638            Type::NamedStruct(_vec) => {
1639                if let Some(found_info) = is_vec(collection_type) {
1640                    self.gen_for_loop_vec(for_pattern, &iterable.resolved_expression)?
1641                } else if let Some(found_info) = is_map(collection_type) {
1642                    self.gen_for_loop_map(for_pattern)?
1643                } else {
1644                    return Err(self.create_err(
1645                        ErrorKind::NotAnIterableCollection,
1646                        iterable.resolved_expression.node(),
1647                    ));
1648                }
1649            }
1650            _ => {
1651                return Err(self.create_err(
1652                    ErrorKind::IllegalCollection,
1653                    iterable.resolved_expression.node(),
1654                ));
1655            }
1656        };
1657
1658        match for_pattern {
1659            ForPattern::Single(value_variable) => {}
1660            ForPattern::Pair(key_variable, value_variable) => {}
1661        }
1662
1663        let unit_expr = self.temp_space_for_type(&Type::Unit, "for loop body");
1664        self.gen_expression(closure, &unit_expr)?;
1665
1666        self.state
1667            .builder
1668            .add_jmp(jump_ip, "jump to next iteration");
1669        // advance iterator pointer
1670        // jump to check if iterator pointer has reached its end
1671        self.state.builder.patch_jump_here(placeholder_position);
1672
1673        Ok(())
1674    }
1675
1676    fn gen_for_loop_for_vec(
1677        &mut self,
1678        element_type: &Type,
1679        vector_expr: Expression,
1680        ctx: &mut Context,
1681    ) -> Result<GeneratedExpressionResult, Error> {
1682        // get the vector that is referenced
1683        let vector_ctx = self.temp_space_for_type(&vector_expr.ty, "vector space");
1684        self.gen_expression(&vector_expr, &vector_ctx)
1685
1686        /*
1687        let value_var_addr = match for_pattern {
1688            ForPattern::Single(value_variable) => self
1689                .variable_offsets
1690                .get(&value_variable.unique_id_within_function)
1691                .expect("Variable not found"),
1692            ForPattern::Pair(_, _) => {
1693                panic!("Cannot use key-value pattern with vectors");
1694            }
1695        };
1696
1697         */
1698
1699        /*
1700        let element_size = type_size(element_type);
1701               // Temporary for the counter
1702               let counter_addr = ctx.allocate_temp(MemorySize(2)); // u16 counter
1703               self.state
1704                   .builder
1705                   .add_ld_u16(counter_addr, 0, "temporary counter");
1706
1707               let loop_start_pos = self.state.builder.position();
1708
1709               // vector length
1710               let length_addr = ctx.allocate_temp(MemorySize(2));
1711               self.state.builder.add_mov(
1712                   length_addr,
1713                   vector_ctx.addr().add(MemorySize(VECTOR_LENGTH_OFFSET)),
1714                   MemorySize(2),
1715                   "vector length",
1716               );
1717
1718               // Compare counter < length
1719               let compare_result_addr = ctx.allocate_temp(MemorySize(1)); // boolean result
1720               self.state.builder.add_lt_u16(
1721                   compare_result_addr,
1722                   counter_addr,
1723                   length_addr,
1724                   "counter < length",
1725               );
1726
1727               // Exit loop if counter >= length
1728               let exit_jump = self
1729                   .state
1730                   .builder
1731                   .add_conditional_jump_placeholder(compare_result_addr, "counter >= length exit");
1732
1733               let data_ptr_addr = ctx.allocate_temp(MemorySize(2));
1734               self.state.builder.add_mov(
1735                   data_ptr_addr,
1736                   vector_ctx.addr().add(MemorySize(VECTOR_DATA_PTR_OFFSET)),
1737                   MemorySize(PTR_SIZE),
1738                   "copy vector data ptr",
1739               );
1740
1741
1742        */
1743        /*
1744        let offset_addr = ctx.allocate_temp(2);
1745        self.state.builder.add_mul_u16(
1746            offset_addr,
1747            counter_addr,
1748            element_size
1749        );
1750
1751        self.state.builder.add_ld_indirect(
1752            *value_var_addr,     // Destination: loop variable
1753            data_ptr_addr,       // Base: vector's data pointer
1754            offset_addr,         // Offset: counter * element_size
1755            element_size         // Size to copy
1756        );
1757
1758        let mut body_ctx = ctx.temp_space_for_type(&Type::Unit);
1759        self.gen_expression(body, &mut body_ctx);
1760
1761        self.state.builder.add_inc_u16(counter_addr);
1762
1763        self.state.builder.add_jmp_to_position(loop_start_pos);
1764
1765        let end_pos = self.state.builder.current_position();
1766        self.state.builder.patch_jump(exit_jump, end_pos);
1767
1768         */
1769    }
1770
1771    fn gen_block(&mut self, expressions: &[Expression], ctx: &Context) -> Result<(), Error> {
1772        if let Some((last, others)) = expressions.split_last() {
1773            for expr in others {
1774                let temp_context = self.temp_space_for_type(&Type::Unit, "block target");
1775                self.gen_expression(expr, &temp_context)?;
1776            }
1777            self.gen_expression(last, ctx)?;
1778        }
1779
1780        Ok(())
1781    }
1782
1783    fn get_variable_region(&self, variable: &VariableRef) -> (FrameMemoryRegion, MemoryAlignment) {
1784        let frame_address = self
1785            .variable_offsets
1786            .get(&variable.unique_id_within_function)
1787            .unwrap();
1788        let (_size, align) = type_size_and_alignment(&variable.resolved_type);
1789
1790        (*frame_address, align)
1791    }
1792
1793    fn gen_variable_access(&mut self, variable: &VariableRef, ctx: &Context) -> Result<(), Error> {
1794        let (region, alignment) = self.get_variable_region(variable);
1795        self.state.builder.add_mov(
1796            ctx.addr(),
1797            region.addr,
1798            region.size,
1799            &format!(
1800                "variable access '{}' ({})",
1801                variable.assigned_name,
1802                ctx.comment()
1803            ),
1804        );
1805
1806        Ok(())
1807    }
1808
1809    fn referenced_or_not_type(ty: &Type) -> Type {
1810        if let Type::MutableReference(inner_type) = ty {
1811            *inner_type.clone()
1812        } else {
1813            ty.clone()
1814        }
1815    }
1816
1817    fn compound_assignment(
1818        &mut self,
1819        target_location: &SingleMutLocationExpression,
1820        op: &CompoundOperatorKind,
1821        source: &Expression,
1822        ctx: &Context,
1823    ) -> Result<(), Error> {
1824        let target_location = self.gen_lvalue_address(&target_location.0)?;
1825
1826        let source_info = self.gen_expression_for_access(source)?;
1827
1828        let type_to_consider = Self::referenced_or_not_type(&source.ty);
1829
1830        match &type_to_consider {
1831            Type::Int => {
1832                self.gen_compound_assignment_i32(&target_location, op, &source_info);
1833            }
1834            Type::Float => {
1835                self.gen_compound_assignment_f32(&target_location, op, &source_info);
1836            }
1837            Type::String => todo!(),
1838            _ => return Err(self.create_err(ErrorKind::IllegalCompoundAssignment, &source.node)),
1839        }
1840
1841        Ok(())
1842    }
1843
1844    fn gen_compound_assignment_i32(
1845        &mut self,
1846        target: &FrameMemoryRegion,
1847        op: &CompoundOperatorKind,
1848        source_ctx: &FrameMemoryRegion,
1849    ) {
1850        match op {
1851            CompoundOperatorKind::Add => {
1852                self.state.builder.add_add_i32(
1853                    target.addr(),
1854                    target.addr(),
1855                    source_ctx.addr(),
1856                    "+=  (i32)",
1857                );
1858            }
1859            CompoundOperatorKind::Sub => todo!(),
1860            CompoundOperatorKind::Mul => todo!(),
1861            CompoundOperatorKind::Div => todo!(),
1862            CompoundOperatorKind::Modulo => todo!(),
1863        }
1864    }
1865
1866    fn gen_compound_assignment_f32(
1867        &mut self,
1868        target: &FrameMemoryRegion,
1869        op: &CompoundOperatorKind,
1870        source_ctx: &FrameMemoryRegion,
1871    ) {
1872        match op {
1873            CompoundOperatorKind::Add => {
1874                self.state.builder.add_add_f32(
1875                    target.addr(),
1876                    target.addr(),
1877                    source_ctx.addr(),
1878                    "+=  (f32)",
1879                );
1880            }
1881            CompoundOperatorKind::Sub => todo!(),
1882            CompoundOperatorKind::Mul => todo!(),
1883            CompoundOperatorKind::Div => todo!(),
1884            CompoundOperatorKind::Modulo => todo!(),
1885        }
1886    }
1887
1888    fn internal_function_access(
1889        &mut self,
1890        internal: &InternalFunctionDefinitionRef,
1891        ctx: &Context,
1892    ) -> Result<(), Error> {
1893        self.state.builder.add_ld_u16(
1894            ctx.addr(),
1895            internal.program_unique_id,
1896            &format!("function access '{}'", internal.assigned_name),
1897        );
1898        Ok(())
1899    }
1900
1901    fn infinite_above_frame_size(&self) -> FrameMemoryRegion {
1902        FrameMemoryRegion::new(FrameMemoryAddress(self.frame_size.0), MemorySize(1024))
1903    }
1904
1905    fn gen_struct_literal(
1906        &mut self,
1907        struct_literal: &StructInstantiation,
1908        ctx: &Context,
1909    ) -> Result<(), Error> {
1910        self.gen_struct_literal_helper(
1911            &struct_literal.struct_type_ref.anon_struct_type,
1912            &struct_literal.source_order_expressions,
1913            ctx,
1914        )
1915    }
1916
1917    fn gen_anonymous_struct_literal(
1918        &mut self,
1919        anon_struct_literal: &AnonymousStructLiteral,
1920        ctx: &Context,
1921    ) -> Result<(), Error> {
1922        self.gen_struct_literal_helper(
1923            &anon_struct_literal.anonymous_struct_type,
1924            &anon_struct_literal.source_order_expressions,
1925            ctx,
1926        )
1927    }
1928
1929    fn gen_struct_literal_helper(
1930        &mut self,
1931        struct_type_ref: &AnonymousStructType,
1932        source_order_expressions: &Vec<(usize, Expression)>,
1933        ctx: &Context,
1934    ) -> Result<(), Error> {
1935        let struct_type = Type::AnonymousStruct(struct_type_ref.clone());
1936        let (whole_struct_size, whole_struct_alignment) = type_size_and_alignment(&struct_type);
1937        if ctx.target_size().0 != whole_struct_size.0 {
1938            info!("problem");
1939        }
1940        assert_eq!(ctx.target_size().0, whole_struct_size.0);
1941
1942        for (field_index, expression) in source_order_expressions {
1943            let (field_offset, field_size, field_alignment) =
1944                struct_field_offset(*field_index, struct_type_ref);
1945            //info!(?field_offset, ?field_index, "field offset");
1946            let new_address = ctx.addr().advance(field_offset);
1947            let field_ctx = Context::new(FrameMemoryRegion::new(new_address, field_size));
1948            self.gen_expression(expression, &field_ctx)?;
1949        }
1950
1951        Ok(())
1952    }
1953
1954    fn gen_slice_literal(
1955        &mut self,
1956        ty: &Type,
1957        expressions: &Vec<Expression>,
1958    ) -> Result<FrameMemoryRegion, Error> {
1959        let (element_size, element_alignment) = type_size_and_alignment(ty);
1960        let element_count = expressions.len() as u16;
1961        let total_slice_size = MemorySize(element_size.0 * element_count);
1962
1963        let start_frame_address_to_transfer = self
1964            .temp_allocator
1965            .allocate(total_slice_size, element_alignment);
1966        for (index, expr) in expressions.iter().enumerate() {
1967            let memory_offset = MemoryOffset((index as u16) * element_size.0);
1968            let region = FrameMemoryRegion::new(
1969                start_frame_address_to_transfer.advance(memory_offset),
1970                element_size,
1971            );
1972            let element_ctx = Context::new(region);
1973            self.gen_expression(expr, &element_ctx)?;
1974        }
1975
1976        Ok(FrameMemoryRegion::new(
1977            start_frame_address_to_transfer,
1978            total_slice_size,
1979        ))
1980    }
1981
1982    fn gen_slice_pair_literal(
1983        &mut self,
1984        slice_type: &Type,
1985        expressions: &[(Expression, Expression)],
1986    ) -> SlicePairInfo {
1987        let Type::SlicePair(key_type, value_type) = slice_type else {
1988            panic!("should have been slice pair type")
1989        };
1990
1991        let constructed_tuple = Type::Tuple(vec![*key_type.clone(), *value_type.clone()]);
1992
1993        let (key_size, key_alignment) = type_size_and_alignment(key_type);
1994        let (value_size, value_alignment) = type_size_and_alignment(value_type);
1995        let (element_size, tuple_alignment) = type_size_and_alignment(&constructed_tuple);
1996        let element_count = expressions.len() as u16;
1997        let total_slice_size = MemorySize(element_size.0 * element_count);
1998
1999        let start_frame_address_to_transfer = self
2000            .temp_allocator
2001            .allocate(total_slice_size, tuple_alignment);
2002
2003        for (index, (key_expr, value_expr)) in expressions.iter().enumerate() {
2004            let memory_offset = MemoryOffset((index as u16) * element_size.0);
2005            let key_region = FrameMemoryRegion::new(
2006                start_frame_address_to_transfer.advance(memory_offset),
2007                element_size,
2008            );
2009            let key_ctx = Context::new(key_region);
2010            self.gen_expression(key_expr, &key_ctx);
2011
2012            let value_region = FrameMemoryRegion::new(
2013                start_frame_address_to_transfer.advance(memory_offset.add(key_size, key_alignment)),
2014                value_size,
2015            );
2016            let value_ctx = Context::new(value_region);
2017            self.gen_expression(value_expr, &value_ctx);
2018        }
2019
2020        SlicePairInfo {
2021            addr: TempFrameMemoryAddress(start_frame_address_to_transfer),
2022            key_size,
2023            value_size,
2024            element_count: CountU16(element_count),
2025            element_size,
2026        }
2027    }
2028
2029    fn gen_slice_helper(
2030        &mut self,
2031        start_temp_frame_address_to_transfer: FrameMemoryAddress,
2032        element_count: u16,
2033        element_size: MemorySize,
2034        ctx: &Context,
2035    ) {
2036        let total_slice_size = MemorySize(element_size.0 * element_count);
2037        let vec_len_addr = ctx.addr().advance(MemoryOffset(0));
2038        self.state
2039            .builder
2040            .add_ld_u16(vec_len_addr, element_count, "slice len");
2041
2042        let vec_capacity_addr = ctx.addr().advance(MemoryOffset(2));
2043        self.state
2044            .builder
2045            .add_ld_u16(vec_capacity_addr, element_count, "slice capacity");
2046
2047        let vec_element_size_addr = ctx.addr().advance(MemoryOffset(4));
2048        self.state
2049            .builder
2050            .add_ld_u16(vec_element_size_addr, element_size.0, "slice element size");
2051
2052        /*
2053        let allocated_vec_address = ctx.addr().advance(MemoryOffset(6));
2054        self.state
2055        .builder
2056        add_alloc(allocated_vec_address, total_slice_size, "slice literal");
2057
2058        self.state.builder.add_stx(
2059            allocated_vec_address,
2060            MemoryOffset(0),
2061            start_temp_frame_address_to_transfer,
2062            total_slice_size,
2063            "copy from slice continuous temporary frame memory to allocated vec ptr heap area",
2064        );
2065
2066         */
2067    }
2068
2069    fn gen_intrinsic_call_ex(
2070        &mut self,
2071        intrinsic_fn: &IntrinsicFunction,
2072        arguments: &Vec<ArgumentExpressionOrLocation>,
2073        ctx: &Context,
2074    ) -> Result<(), Error> {
2075        //        info!(?intrinsic_fn, "generating intrinsic call");
2076
2077        match intrinsic_fn {
2078            // Fixed
2079            IntrinsicFunction::FloatRound => todo!(),
2080            IntrinsicFunction::FloatFloor => todo!(),
2081            IntrinsicFunction::FloatSqrt => todo!(),
2082            IntrinsicFunction::FloatSign => todo!(),
2083            IntrinsicFunction::FloatAbs => todo!(),
2084            IntrinsicFunction::FloatRnd => todo!(),
2085            IntrinsicFunction::FloatCos => todo!(),
2086            IntrinsicFunction::FloatSin => todo!(),
2087            IntrinsicFunction::FloatAcos => todo!(),
2088            IntrinsicFunction::FloatAsin => todo!(),
2089            IntrinsicFunction::FloatAtan2 => todo!(),
2090            IntrinsicFunction::FloatMin => todo!(),
2091            IntrinsicFunction::FloatMax => todo!(),
2092            IntrinsicFunction::FloatClamp => todo!(),
2093
2094            // i32
2095            IntrinsicFunction::IntAbs => todo!(),
2096            IntrinsicFunction::IntRnd => todo!(),
2097            IntrinsicFunction::IntMax => todo!(),
2098            IntrinsicFunction::IntMin => todo!(),
2099            IntrinsicFunction::IntClamp => todo!(),
2100            IntrinsicFunction::IntToFloat => todo!(),
2101
2102            // String
2103            IntrinsicFunction::StringLen => todo!(),
2104
2105            // Vector
2106            IntrinsicFunction::VecFromSlice => self.gen_intrinsic_vec_from_slice(arguments, ctx),
2107            IntrinsicFunction::VecPush => todo!(),
2108            IntrinsicFunction::VecPop => todo!(),
2109            IntrinsicFunction::VecFor => todo!(),
2110            IntrinsicFunction::VecWhile => todo!(),
2111            IntrinsicFunction::VecFind => todo!(),
2112            IntrinsicFunction::VecRemoveIndex => todo!(),
2113            IntrinsicFunction::VecClear => todo!(),
2114            IntrinsicFunction::VecCreate => {
2115                self.gen_intrinsic_vec_create(arguments);
2116                Ok(())
2117            }
2118            IntrinsicFunction::VecSubscript => todo!(),
2119            IntrinsicFunction::VecSubscriptMut => todo!(),
2120            IntrinsicFunction::VecSubscriptRange => todo!(),
2121            IntrinsicFunction::VecIter => todo!(), // intentionally disregard, since it is never called
2122            IntrinsicFunction::VecIterMut => todo!(), // intentionally disregard, since it is never called
2123            IntrinsicFunction::VecLen => todo!(),
2124            IntrinsicFunction::VecIsEmpty => todo!(),
2125            IntrinsicFunction::VecSelfPush => todo!(),
2126            IntrinsicFunction::VecSelfExtend => todo!(),
2127
2128            // Map
2129            IntrinsicFunction::MapCreate => todo!(),
2130            IntrinsicFunction::MapFromSlicePair => todo!(),
2131            IntrinsicFunction::MapHas => todo!(),
2132            IntrinsicFunction::MapRemove => todo!(),
2133            IntrinsicFunction::MapIter => todo!(),
2134            IntrinsicFunction::MapIterMut => todo!(),
2135            IntrinsicFunction::MapLen => todo!(),
2136            IntrinsicFunction::MapIsEmpty => todo!(),
2137            IntrinsicFunction::MapSubscript => todo!(),
2138            IntrinsicFunction::MapSubscriptSet => todo!(),
2139            IntrinsicFunction::MapSubscriptMut => todo!(),
2140            IntrinsicFunction::MapSubscriptMutCreateIfNeeded => todo!(),
2141
2142            IntrinsicFunction::Map2GetColumn => todo!(),
2143            IntrinsicFunction::Map2GetRow => todo!(),
2144            IntrinsicFunction::Map2Remove => todo!(),
2145            IntrinsicFunction::Map2Has => todo!(),
2146            IntrinsicFunction::Map2Get => todo!(),
2147            IntrinsicFunction::Map2Insert => todo!(),
2148            IntrinsicFunction::Map2Create => todo!(),
2149
2150            // Sparse
2151            IntrinsicFunction::SparseAdd => todo!(),
2152            IntrinsicFunction::SparseNew => todo!(),
2153            IntrinsicFunction::SparseCreate => todo!(),
2154            IntrinsicFunction::SparseFromSlice => todo!(),
2155            IntrinsicFunction::SparseIter => todo!(),
2156            IntrinsicFunction::SparseIterMut => todo!(),
2157            IntrinsicFunction::SparseSubscript => todo!(),
2158            IntrinsicFunction::SparseSubscriptMut => todo!(),
2159            IntrinsicFunction::SparseHas => todo!(),
2160            IntrinsicFunction::SparseRemove => todo!(),
2161
2162            // Grid
2163            IntrinsicFunction::GridCreate => todo!(),
2164            IntrinsicFunction::GridFromSlice => todo!(),
2165            IntrinsicFunction::GridSet => todo!(),
2166            IntrinsicFunction::GridGet => todo!(),
2167            IntrinsicFunction::GridGetColumn => todo!(),
2168
2169            // Other
2170            IntrinsicFunction::Float2Magnitude => todo!(),
2171        };
2172
2173        Ok(())
2174    }
2175
2176    fn gen_intrinsic_vec_create(&self, arguments: &Vec<ArgumentExpressionOrLocation>) {
2177        for arg in arguments {
2178            info!(?arg, "argument");
2179        }
2180    }
2181
2182    fn gen_intrinsic_vec_from_slice(
2183        &mut self,
2184        arguments: &[ArgumentExpressionOrLocation],
2185        ctx: &Context,
2186    ) -> Result<(), Error> {
2187        if let ArgumentExpressionOrLocation::Expression(found_expr) = &arguments[0] {
2188            let memory = self.gen_expression_for_access(found_expr)?;
2189            self.state.builder.add_vec_from_slice(
2190                ctx.addr(),
2191                memory.addr,
2192                MemorySize(0),
2193                CountU16(0),
2194                "create vec",
2195            );
2196        } else {
2197            panic!("vec_from_slice");
2198        }
2199
2200        Ok(())
2201    }
2202
2203    fn gen_match(&mut self, match_expr: &Match, ctx: &Context) -> Result<(), Error> {
2204        let region_to_match = self.gen_for_access_or_location(&match_expr.expression)?;
2205
2206        let mut jump_to_exit_placeholders = Vec::new();
2207
2208        let arm_len_to_consider = if match_expr.contains_wildcard() {
2209            match_expr.arms.len()
2210        } else {
2211            match_expr.arms.len()
2212        };
2213        for (index, arm) in match_expr.arms.iter().enumerate() {
2214            let is_last = index == arm_len_to_consider - 1;
2215
2216            //  Each arm must set the CPU zero flag
2217            let maybe_guard = match &arm.pattern {
2218                Pattern::Normal(normal_pattern, maybe_guard) => match normal_pattern {
2219                    NormalPattern::PatternList(_) => None,
2220                    NormalPattern::EnumPattern(enum_variant, maybe_patterns) => {
2221                        self.state.builder.add_eq_u8_immediate(
2222                            region_to_match.addr,
2223                            enum_variant.common().container_index,
2224                            "check for enum variant",
2225                        );
2226                        maybe_guard.as_ref()
2227                    }
2228                    NormalPattern::Literal(_) => {
2229                        todo!()
2230                    }
2231                },
2232                Pattern::Wildcard(_) => {
2233                    // Wildcard is always true, so no comparison code is needed here at all
2234                    None
2235                }
2236            };
2237
2238            let did_add_comparison = !matches!(arm.pattern, Pattern::Wildcard(_));
2239
2240            let maybe_skip_added = if did_add_comparison {
2241                Some(
2242                    self.state
2243                        .builder
2244                        .add_jmp_if_not_equal_placeholder("placeholder for enum match"),
2245                )
2246            } else {
2247                None
2248            };
2249
2250            let maybe_guard_skip = if let Some(guard) = maybe_guard {
2251                self.gen_boolean_expression(guard)?;
2252                // z flag should have been updated now
2253
2254                Some(
2255                    self.state
2256                        .builder
2257                        .add_jmp_if_not_equal_placeholder("placeholder for skip guard"),
2258                )
2259            } else {
2260                None
2261            };
2262
2263            self.gen_expression(&arm.expression, ctx)?;
2264
2265            if !is_last {
2266                let jump_to_exit_placeholder =
2267                    self.state.builder.add_jump_placeholder("jump to exit");
2268                jump_to_exit_placeholders.push(jump_to_exit_placeholder);
2269            }
2270
2271            if let Some(skip) = maybe_skip_added {
2272                self.state.builder.patch_jump_here(skip);
2273            }
2274            if let Some(guard_skip) = maybe_guard_skip {
2275                self.state.builder.patch_jump_here(guard_skip);
2276            }
2277        }
2278
2279        for placeholder in jump_to_exit_placeholders {
2280            self.state.builder.patch_jump_here(placeholder);
2281        }
2282
2283        Ok(())
2284    }
2285
2286    fn gen_guard(&mut self, guards: &Vec<Guard>, ctx: &Context) -> Result<(), Error> {
2287        let mut jump_to_exit_placeholders = Vec::new();
2288        for guard in guards {
2289            if let Some(condition) = &guard.condition {
2290                self.gen_boolean_expression(condition); // update z flag
2291                let skip_expression_patch = self
2292                    .state
2293                    .builder
2294                    .add_jmp_if_not_equal_placeholder("guard condition");
2295                self.gen_expression(&guard.result, ctx)?;
2296                let jump_to_exit_placeholder =
2297                    self.state.builder.add_jump_placeholder("jump to exit");
2298                jump_to_exit_placeholders.push(jump_to_exit_placeholder);
2299                self.state.builder.patch_jump_here(skip_expression_patch);
2300            } else {
2301                // _ -> wildcard
2302                self.gen_expression(&guard.result, ctx)?;
2303            }
2304        }
2305
2306        for placeholder in jump_to_exit_placeholders {
2307            self.state.builder.patch_jump_here(placeholder);
2308        }
2309
2310        Ok(())
2311    }
2312
2313    fn gen_when(
2314        &mut self,
2315        bindings: &Vec<WhenBinding>,
2316        true_expr: &Expression,
2317        maybe_false_expr: Option<&Expression>,
2318        ctx: &Context,
2319    ) -> Result<(), Error> {
2320        let mut all_false_jumps = Vec::new();
2321
2322        for binding in bindings {
2323            let (variable_region, _alignment) = self.get_variable_region(&binding.variable);
2324
2325            let old_variable_region = self.gen_for_access_or_location(&binding.expr)?;
2326
2327            self.state
2328                .builder
2329                .add_tst8(old_variable_region.addr, "check binding");
2330            let patch = self
2331                .state
2332                .builder
2333                .add_jmp_if_not_equal_placeholder("jump if none");
2334            all_false_jumps.push(patch);
2335        }
2336
2337        // if we are here all bindings are `Some`
2338        for binding in bindings {
2339            let (variable_region, alignment) = self.get_variable_region(&binding.variable);
2340
2341            if binding.has_expression() {
2342                let var_ctx = Context::new(variable_region);
2343                self.gen_mut_or_immute(&binding.expr, &var_ctx)?;
2344            } else {
2345                let ArgumentExpressionOrLocation::Expression(variable_access_expression) =
2346                    &binding.expr.expression_or_location
2347                else {
2348                    panic!("must be expression");
2349                };
2350                let old_variable_region =
2351                    self.gen_expression_for_access(variable_access_expression)?;
2352                let alignment_offset: MemoryOffset = alignment.into();
2353                let some_value_region = FrameMemoryRegion::new(
2354                    old_variable_region.addr.advance(alignment_offset),
2355                    MemorySize(variable_region.size.0),
2356                );
2357                self.state.builder.add_movlp(
2358                    variable_region.addr,
2359                    some_value_region.addr,
2360                    some_value_region.size,
2361                    "move from Some to value",
2362                );
2363            }
2364        }
2365
2366        self.gen_expression(true_expr, ctx)?;
2367        let maybe_jump_over_false = if let Some(_else_expr) = maybe_false_expr {
2368            Some(
2369                self.state
2370                    .builder
2371                    .add_jump_placeholder("jump over false section"),
2372            )
2373        } else {
2374            None
2375        };
2376
2377        for false_jump_patch in all_false_jumps {
2378            self.state.builder.patch_jump_here(false_jump_patch);
2379        }
2380
2381        if let Some(else_expr) = maybe_false_expr {
2382            self.gen_expression(else_expr, ctx);
2383            self.state
2384                .builder
2385                .patch_jump_here(maybe_jump_over_false.unwrap());
2386        }
2387
2388        Ok(())
2389    }
2390
2391    fn create_err(&mut self, kind: ErrorKind, node: &Node) -> Error {
2392        error!(?kind, "encountered error");
2393        Error {
2394            kind,
2395            node: node.clone(),
2396        }
2397    }
2398
2399    fn gen_tuple_destructuring(
2400        &mut self,
2401        target_variables: &Vec<VariableRef>,
2402        tuple_type: &Vec<Type>,
2403        source_tuple_expression: &Expression,
2404    ) -> Result<(), Error> {
2405        let source_region = self.gen_expression_for_access(source_tuple_expression)?;
2406
2407        let (total_size, _max_alignment, element_offsets) = layout_tuple_elements(tuple_type);
2408        assert_eq!(total_size.0, source_region.size.0);
2409
2410        for (target_variable, (element_offset, element_size)) in
2411            target_variables.iter().zip(element_offsets)
2412        {
2413            if target_variable.is_unused {
2414            } else {
2415                let (target_region, _variable_alignment) =
2416                    self.get_variable_region(target_variable);
2417                assert_eq!(target_region.size.0, element_size.0);
2418
2419                let source_element_region = FrameMemoryRegion::new(
2420                    source_region.addr.advance(element_offset),
2421                    element_size,
2422                );
2423                self.state.builder.add_mov(
2424                    target_region.addr,
2425                    source_element_region.addr,
2426                    source_element_region.size,
2427                    &format!(
2428                        "destructuring to variable {}",
2429                        target_variable.assigned_name
2430                    ),
2431                );
2432            }
2433        }
2434
2435        Ok(())
2436    }
2437
2438    fn gen_constant_access(
2439        &mut self,
2440        constant_reference: &ConstantRef,
2441        ctx: &Context,
2442    ) -> Result<(), Error> {
2443        let constant_region = self
2444            .state
2445            .constant_offsets
2446            .get(&constant_reference.id)
2447            .unwrap();
2448        assert_eq!(constant_region.size.0, ctx.target_size().0);
2449
2450        self.state.builder.add_ld_constant(
2451            ctx.addr(),
2452            constant_region.addr,
2453            constant_region.size,
2454            &format!("load constant '{}'", constant_reference.assigned_name),
2455        );
2456
2457        Ok(())
2458    }
2459}
2460
2461fn single_intrinsic_fn(body: &Expression) -> Option<&IntrinsicFunction> {
2462    let ExpressionKind::Block(block_expressions) = &body.kind else {
2463        panic!("function body should be a block")
2464    };
2465
2466    if let ExpressionKind::IntrinsicCallEx(found_intrinsic_fn, _non_instantiated_arguments) =
2467        &block_expressions[0].kind
2468    {
2469        Some(found_intrinsic_fn)
2470    } else {
2471        None
2472    }
2473}
2474
2475fn struct_field_offset(
2476    index_to_look_for: usize,
2477    anon_struct_type: &AnonymousStructType,
2478) -> (MemoryOffset, MemorySize, MemoryAlignment) {
2479    let mut offset = MemoryOffset(0);
2480    for (field_index, (_name, field)) in
2481        anon_struct_type.field_name_sorted_fields.iter().enumerate()
2482    {
2483        let (field_size, field_alignment) = type_size_and_alignment(&field.field_type);
2484        let field_start_offset = offset.space(field_size, field_alignment);
2485        if field_index == index_to_look_for {
2486            return (field_start_offset, field_size, field_alignment);
2487        }
2488    }
2489
2490    panic!("field index is wrong")
2491}