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