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