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