swamp_script_code_gen/
lib.rs

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