swamp_script_code_gen/
lib.rs

1pub mod alloc;
2pub mod alloc_util;
3pub mod constants;
4pub mod ctx;
5mod vec;
6
7use crate::alloc::{FrameMemoryRegion, ScopeAllocator};
8use crate::alloc_util::{
9    layout_struct, layout_tuple, layout_union, reserve_space_for_type, type_size_and_alignment,
10};
11use crate::ctx::Context;
12use crate::vec::{VECTOR_DATA_PTR_OFFSET, VECTOR_LENGTH_OFFSET};
13use seq_map::SeqMap;
14use std::ops::Deref;
15use swamp_script_semantic::{
16    ArgumentExpressionOrLocation, BinaryOperator, BinaryOperatorKind, BooleanExpression,
17    CompoundOperatorKind, EnumLiteralData, Expression, ExpressionKind, ForPattern, Function,
18    FunctionScopeState, InternalFunctionDefinition, InternalFunctionDefinitionRef,
19    InternalFunctionId, InternalMainExpression, Iterable, Literal, LocationAccessKind,
20    MutOrImmutableExpression, Postfix, PostfixKind, SingleLocationExpression,
21    SingleMutLocationExpression, StructInstantiation, VariableRef,
22};
23use swamp_script_types::{AnonymousStructType, EnumVariantType, Signature, StructTypeField, Type};
24
25use crate::constants::ConstantsManager;
26use swamp_script_semantic::intr::IntrinsicFunction;
27use swamp_vm_instr_build::{InstructionBuilder, PTR_SIZE, PatchPosition, VEC_SIZE};
28use swamp_vm_types::opcode::OpCode;
29use swamp_vm_types::{
30    BinaryInstruction, FrameMemoryAddress, FrameMemorySize, InstructionPosition, MemoryAddress,
31    MemoryAlignment, MemoryOffset, MemorySize,
32};
33use tracing::{info, trace};
34
35pub struct FunctionInfo {
36    pub starts_at_ip: InstructionPosition,
37    pub internal_function_definition: InternalFunctionDefinitionRef,
38}
39
40pub struct FunctionFixup {
41    pub patch_position: PatchPosition,
42    pub fn_id: InternalFunctionId,
43    //pub internal_function_definition: InternalFunctionDefinitionRef,
44}
45
46pub struct CodeGenState {
47    builder: InstructionBuilder,
48    constants: ConstantsManager,
49    function_infos: SeqMap<InternalFunctionId, FunctionInfo>,
50    function_fixups: Vec<FunctionFixup>,
51}
52
53impl CodeGenState {
54    pub fn create_function_sections(&self) -> SeqMap<InstructionPosition, String> {
55        let mut lookups = SeqMap::new();
56        for (_func_id, function_info) in &self.function_infos {
57            let description = format!(
58                "{}",
59                function_info.internal_function_definition.assigned_name
60            );
61            lookups
62                .insert(function_info.starts_at_ip.clone(), description)
63                .unwrap()
64        }
65
66        lookups
67    }
68}
69
70impl CodeGenState {
71    pub(crate) fn add_call(&mut self, internal_fn: &InternalFunctionDefinitionRef, comment: &str) {
72        let call_comment = &format!("calling {} ({})", internal_fn.assigned_name, comment);
73
74        if let Some(found) = self.function_infos.get(&internal_fn.program_unique_id) {
75            self.builder.add_call(&found.starts_at_ip, call_comment);
76        } else {
77            let patch_position = self.builder.add_call_placeholder(call_comment);
78            self.function_fixups.push(FunctionFixup {
79                patch_position,
80                fn_id: internal_fn.program_unique_id,
81            });
82        }
83    }
84}
85
86impl CodeGenState {
87    #[must_use]
88    pub fn instructions(&self) -> &[BinaryInstruction] {
89        &self.builder.instructions
90    }
91
92    #[must_use]
93    pub fn comments(&self) -> &[String] {
94        &self.builder.comments
95    }
96
97    pub fn finalize(&mut self) {
98        for function_fixup in &self.function_fixups {
99            let func = self.function_infos.get(&function_fixup.fn_id).unwrap();
100            self.builder.patch_call(
101                PatchPosition(InstructionPosition(function_fixup.patch_position.0.0)),
102                &func.starts_at_ip,
103            );
104        }
105    }
106}
107
108pub struct GenOptions {
109    pub is_halt_function: bool,
110}
111impl Default for CodeGenState {
112    fn default() -> Self {
113        Self::new()
114    }
115}
116
117impl CodeGenState {
118    #[must_use]
119    pub fn new() -> Self {
120        Self {
121            builder: InstructionBuilder::default(),
122            constants: ConstantsManager::new(),
123            function_infos: SeqMap::default(),
124            function_fixups: vec![],
125        }
126    }
127
128    #[must_use]
129    pub fn take_instructions_and_constants(self) -> (Vec<BinaryInstruction>, Vec<u8>) {
130        (self.builder.instructions, self.constants.take_data())
131    }
132
133    pub fn gen_function_def(
134        &mut self,
135        internal_fn_def: &InternalFunctionDefinitionRef,
136        options: &GenOptions,
137    ) {
138        info!(?internal_fn_def.assigned_name, ?internal_fn_def.program_unique_id, "generating function");
139        assert_ne!(internal_fn_def.program_unique_id, 0);
140        self.function_infos
141            .insert(
142                internal_fn_def.program_unique_id,
143                FunctionInfo {
144                    starts_at_ip: self.builder.position(),
145                    internal_function_definition: internal_fn_def.clone(),
146                },
147            )
148            .unwrap();
149
150        let mut function_generator = FunctionCodeGen::new(self, internal_fn_def.program_unique_id);
151
152        let mut ctx = Context::new(FrameMemoryRegion::new(
153            FrameMemoryAddress(0),
154            MemorySize(512),
155        ));
156
157        function_generator.layout_variables(
158            &internal_fn_def.function_scope_state,
159            &internal_fn_def.signature.return_type,
160        );
161
162        function_generator.gen_expression(&internal_fn_def.body, &mut ctx);
163
164        self.finalize_function(options);
165    }
166
167    pub fn finalize_function(&mut self, options: &GenOptions) {
168        if options.is_halt_function {
169            self.builder.add_hlt("");
170        } else {
171            self.builder.add_ret("");
172        }
173    }
174
175    pub fn gen_main_function(&mut self, main: &InternalMainExpression, options: &GenOptions) {
176        let mut function_generator = FunctionCodeGen::new(self, main.program_unique_id);
177
178        function_generator.layout_variables(&main.function_scope_state, &main.expression.ty);
179        let mut empty_ctx = Context::new(FrameMemoryRegion::default()); //"main return (unit)");
180        function_generator.gen_expression(&main.expression, &mut empty_ctx);
181        self.finalize_function(options);
182    }
183}
184
185pub struct FunctionCodeGen<'a> {
186    state: &'a mut CodeGenState,
187    variable_offsets: SeqMap<usize, FrameMemoryRegion>,
188    frame_size: FrameMemorySize,
189    extra_frame_allocator: ScopeAllocator,
190    temp_allocator: ScopeAllocator,
191    fn_id: InternalFunctionId,
192}
193
194impl<'a> FunctionCodeGen<'a> {
195    #[must_use]
196    pub fn new(state: &'a mut CodeGenState, fn_id: InternalFunctionId) -> Self {
197        Self {
198            fn_id,
199            state,
200            variable_offsets: SeqMap::default(),
201            frame_size: FrameMemorySize(0),
202            extra_frame_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
203            temp_allocator: ScopeAllocator::new(FrameMemoryRegion::default()),
204        }
205    }
206
207    pub fn reserve(ty: &Type, allocator: &mut ScopeAllocator) -> FrameMemoryRegion {
208        let (size, alignment) = type_size_and_alignment(ty);
209        allocator.reserve(size, alignment)
210    }
211
212    pub fn layout_variables(&mut self, variables: &Vec<VariableRef>, return_type: &Type) {
213        let mut allocator = ScopeAllocator::new(FrameMemoryRegion::new(
214            FrameMemoryAddress(0),
215            MemorySize(1024),
216        ));
217        let _current_offset = Self::reserve(return_type, &mut allocator);
218
219        let mut enter_comment = "variables:\n".to_string();
220
221        for var_ref in variables {
222            let var_target = Self::reserve(&var_ref.resolved_type, &mut allocator);
223            trace!(?var_ref.assigned_name, ?var_target, "laying out");
224            enter_comment += &format!(
225                "  ${:04X}:{} {}\n",
226                var_target.addr.0, var_target.size.0, var_ref.assigned_name
227            );
228            self.variable_offsets
229                .insert(var_ref.unique_id_within_function, var_target)
230                .unwrap();
231        }
232
233        let extra_frame_size = MemorySize(80);
234        let extra_target = FrameMemoryRegion::new(allocator.addr(), extra_frame_size);
235        self.extra_frame_allocator = ScopeAllocator::new(extra_target);
236        self.frame_size = allocator.addr().as_size().add(extra_frame_size);
237
238        self.state
239            .builder
240            .add_enter(self.frame_size, &enter_comment);
241
242        self.temp_allocator = ScopeAllocator::new(FrameMemoryRegion::new(
243            FrameMemoryAddress(self.frame_size.0),
244            MemorySize(1024),
245        ));
246    }
247
248    pub fn temp_memory_region_for_type(&mut self, ty: &Type, comment: &str) -> FrameMemoryRegion {
249        let new_target_info = reserve_space_for_type(ty, &mut self.temp_allocator);
250        trace!(?new_target_info, "creating temporary space");
251        new_target_info
252    }
253    pub fn temp_space_for_type(&mut self, ty: &Type, comment: &str) -> Context {
254        Context::new(self.temp_memory_region_for_type(ty, comment))
255    }
256
257    /// # Panics
258    ///
259    #[allow(clippy::single_match_else)]
260    pub fn gen_expression_for_access(
261        &mut self,
262        expr: &Expression,
263        ctx: &Context,
264    ) -> FrameMemoryRegion {
265        match &expr.kind {
266            ExpressionKind::VariableAccess(var_ref) => {
267                let frame_address = self
268                    .variable_offsets
269                    .get(&var_ref.unique_id_within_function)
270                    .unwrap();
271
272                *frame_address
273            }
274
275            _ => {
276                let mut temp_ctx = self.temp_space_for_type(&expr.ty, "expression");
277
278                self.gen_expression(expr, &mut temp_ctx);
279
280                temp_ctx.target()
281            }
282        }
283    }
284
285    pub(crate) fn extra_frame_space_for_type(&mut self, ty: &Type) -> Context {
286        let target = Self::reserve(ty, &mut self.extra_frame_allocator);
287        Context::new(target)
288    }
289
290    pub fn gen_expression(&mut self, expr: &Expression, ctx: &Context) {
291        match &expr.kind {
292            ExpressionKind::ConstantAccess(_) => todo!(),
293            ExpressionKind::VariableAccess(variable_ref) => {
294                self.gen_variable_access(variable_ref, ctx);
295            }
296            ExpressionKind::IntrinsicFunctionAccess(_) => todo!(),
297            ExpressionKind::InternalFunctionAccess(function) => {
298                self.internal_function_access(function, ctx);
299            }
300            ExpressionKind::ExternalFunctionAccess(_) => todo!(),
301            ExpressionKind::BinaryOp(operator) => self.gen_binary_operator(operator, ctx),
302            ExpressionKind::UnaryOp(_) => todo!(),
303            ExpressionKind::PostfixChain(start, chain) => self.gen_postfix_chain(start, chain, ctx),
304            ExpressionKind::CoerceOptionToBool(_) => todo!(),
305            ExpressionKind::FunctionCall(_, _, _) => todo!(),
306            ExpressionKind::InterpolatedString(_) => todo!(),
307            ExpressionKind::VariableDefinition(variable, expression) => {
308                self.gen_variable_definition(variable, expression, ctx);
309            }
310            ExpressionKind::VariableReassignment(variable, expression) => {
311                self.gen_variable_reassignment(variable, expression, ctx);
312            }
313            ExpressionKind::StructInstantiation(struct_literal) => {
314                self.gen_struct_literal(struct_literal, ctx)
315            }
316            ExpressionKind::AnonymousStructLiteral(_) => todo!(),
317            ExpressionKind::Literal(basic_literal) => self.gen_literal(basic_literal, ctx),
318            ExpressionKind::Option(maybe_option) => {
319                self.gen_option_expression(maybe_option.as_deref(), ctx)
320            }
321            ExpressionKind::Range(_, _, _) => todo!(),
322            ExpressionKind::ForLoop(a, b, c) => self.gen_for_loop(a, b, c, ctx),
323            ExpressionKind::WhileLoop(condition, expression) => {
324                self.gen_while_loop(condition, expression, ctx);
325            }
326            ExpressionKind::Block(expressions) => self.gen_block(expressions, ctx),
327            ExpressionKind::Match(_) => todo!(),
328            ExpressionKind::Guard(_) => todo!(),
329            ExpressionKind::If(conditional, true_expr, false_expr) => {
330                self.gen_if(conditional, true_expr, false_expr.as_deref(), ctx);
331            }
332            ExpressionKind::When(_, _, _) => todo!(),
333            ExpressionKind::TupleDestructuring(_, _, _) => todo!(),
334            ExpressionKind::Assignment(_, _) => todo!(),
335            ExpressionKind::CompoundAssignment(target_location, operator_kind, source_expr) => {
336                self.compound_assignment(target_location, operator_kind, source_expr, ctx);
337            }
338            ExpressionKind::IntrinsicCallMut(_, _, _) => todo!(),
339            ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments) => {
340                self.gen_intrinsic_call_ex(intrinsic_fn, arguments, ctx);
341            }
342        }
343    }
344
345    fn gen_binary_operator(&mut self, binary_operator: &BinaryOperator, ctx: &Context) {
346        match (&binary_operator.left.ty, &binary_operator.right.ty) {
347            (Type::Int, Type::Int) => self.gen_binary_operator_i32(binary_operator, ctx),
348            _ => todo!(),
349        }
350    }
351
352    fn gen_binary_operator_i32(&mut self, binary_operator: &BinaryOperator, ctx: &Context) {
353        let left_source = self.gen_expression_for_access(&binary_operator.left, ctx);
354        let right_source = self.gen_expression_for_access(&binary_operator.right, ctx);
355
356        match binary_operator.kind {
357            BinaryOperatorKind::Add => {
358                self.state.builder.add_add_i32(
359                    ctx.addr(),
360                    left_source.addr(),
361                    right_source.addr(),
362                    "i32 add",
363                );
364            }
365
366            BinaryOperatorKind::Subtract => todo!(),
367            BinaryOperatorKind::Multiply => todo!(),
368            BinaryOperatorKind::Divide => todo!(),
369            BinaryOperatorKind::Modulo => todo!(),
370            BinaryOperatorKind::LogicalOr => todo!(),
371            BinaryOperatorKind::LogicalAnd => todo!(),
372            BinaryOperatorKind::Equal => todo!(),
373            BinaryOperatorKind::NotEqual => todo!(),
374            BinaryOperatorKind::LessThan => {
375                self.state.builder.add_lt_i32(
376                    ctx.addr(),
377                    left_source.addr(),
378                    right_source.addr(),
379                    "i32 lt",
380                );
381            }
382            BinaryOperatorKind::LessEqual => todo!(),
383            BinaryOperatorKind::GreaterThan => todo!(),
384            BinaryOperatorKind::GreaterEqual => todo!(),
385            BinaryOperatorKind::RangeExclusive => todo!(),
386        }
387    }
388
389    fn gen_condition_context(
390        &mut self,
391        condition: &BooleanExpression,
392        ctx: &Context,
393    ) -> (Context, PatchPosition) {
394        let mut condition_ctx = self.extra_frame_space_for_type(&Type::Bool);
395        self.gen_expression(&condition.expression, &mut condition_ctx);
396
397        let jump_on_false_condition = self
398            .state
399            .builder
400            .add_conditional_jump_placeholder(condition_ctx.addr(), "jump boolean condition false");
401
402        (condition_ctx, jump_on_false_condition)
403    }
404
405    fn gen_if(
406        &mut self,
407        condition: &BooleanExpression,
408        true_expr: &Expression,
409        maybe_false_expr: Option<&Expression>,
410        ctx: &Context,
411    ) {
412        let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition, ctx);
413
414        // True expression just takes over our target
415        self.gen_expression(true_expr, ctx);
416
417        if let Some(false_expr) = maybe_false_expr {
418            // we need to help the true expression to jump over false
419            let skip_false_if_true = self
420                .state
421                .builder
422                .add_jump_placeholder("condition is false skip");
423
424            // If the expression was false, it should continue here
425            self.state.builder.patch_jump_here(jump_on_false_condition);
426
427            // Else expression also can just take over our if target
428            self.gen_expression(false_expr, ctx);
429
430            self.state.builder.patch_jump_here(skip_false_if_true);
431        } else {
432            self.state.builder.patch_jump_here(jump_on_false_condition);
433        }
434    }
435
436    fn gen_while_loop(
437        &mut self,
438        condition: &BooleanExpression,
439        expression: &Expression,
440        ctx: &Context,
441    ) {
442        // `while` loops are only for side effects, make sure that the target size is zero (Unit)
443        assert_eq!(ctx.target_size().0, 0);
444
445        let ip_for_condition = self.state.builder.position();
446
447        let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition, ctx);
448
449        // Expression is only for side effects
450        let mut unit_ctx = self.temp_space_for_type(&Type::Unit, "while body expression");
451        self.gen_expression(expression, &mut unit_ctx);
452
453        // Always jump to the condition again to see if it is true
454        self.state
455            .builder
456            .add_jmp(ip_for_condition, "jmp to while condition");
457
458        self.state.builder.patch_jump_here(jump_on_false_condition);
459    }
460
461    fn gen_location_argument(
462        &mut self,
463        argument: &SingleLocationExpression,
464        ctx: &Context,
465        comment: &str,
466    ) {
467        let region = self.gen_lvalue_address(argument);
468
469        self.state
470            .builder
471            .add_mov(ctx.addr(), region.addr, region.size, comment)
472    }
473
474    fn gen_argument(
475        &mut self,
476        argument: &ArgumentExpressionOrLocation,
477        ctx: &Context,
478        comment: &str,
479    ) {
480        match &argument {
481            ArgumentExpressionOrLocation::Expression(found_expression) => {
482                self.gen_expression(found_expression, ctx);
483            }
484            ArgumentExpressionOrLocation::Location(location_expression) => {
485                self.gen_location_argument(location_expression, ctx, comment);
486            }
487        }
488    }
489
490    fn gen_mut_or_immute(
491        &mut self,
492        mut_or_immutable_expression: &MutOrImmutableExpression,
493        ctx: &mut Context,
494    ) {
495        match &mut_or_immutable_expression.expression_or_location {
496            ArgumentExpressionOrLocation::Expression(found_expression) => {
497                self.gen_expression(found_expression, ctx);
498            }
499            ArgumentExpressionOrLocation::Location(location_expression) => {
500                self.gen_lvalue_address(location_expression);
501            }
502        }
503    }
504    fn gen_variable_assignment(
505        &mut self,
506        variable: &VariableRef,
507        mut_or_immutable_expression: &MutOrImmutableExpression,
508        ctx: &Context,
509    ) {
510        let target_relative_frame_pointer = self
511            .variable_offsets
512            .get(&variable.unique_id_within_function)
513            .unwrap_or_else(|| panic!("{}", variable.assigned_name));
514
515        let mut init_ctx =
516            ctx.with_target(*target_relative_frame_pointer, "variable assignment target");
517
518        self.gen_mut_or_immute(mut_or_immutable_expression, &mut init_ctx);
519    }
520
521    fn gen_variable_definition(
522        &mut self,
523        variable: &VariableRef,
524        mut_or_immutable_expression: &MutOrImmutableExpression,
525        ctx: &Context,
526    ) {
527        self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx);
528    }
529
530    fn gen_variable_reassignment(
531        &mut self,
532        variable: &VariableRef,
533        mut_or_immutable_expression: &Box<MutOrImmutableExpression>,
534        ctx: &Context,
535    ) {
536        self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx);
537    }
538
539    fn gen_lvalue_address(
540        &mut self,
541        location_expression: &SingleLocationExpression,
542    ) -> FrameMemoryRegion {
543        let frame_relative_base_address = self
544            .variable_offsets
545            .get(
546                &location_expression
547                    .starting_variable
548                    .unique_id_within_function,
549            )
550            .unwrap();
551
552        *frame_relative_base_address
553
554        /*
555
556        // Loop over the consecutive accesses until we find the actual location
557        for access in &location_expression.access_chain {
558            match &access.kind {
559                LocationAccessKind::FieldIndex(_anonymous_struct_type, field_index) => {
560                    // Calculate the offset somehow?
561                }
562                LocationAccessKind::IntrinsicCallMut(
563                    intrinsic_function,
564                    arguments_to_the_intrinsic,
565                ) => {
566                    // Fetching from vector, map, etc. are done using intrinsic calls
567                    // arguments can be things like the key_value or the int index in a vector
568                }
569            }
570        }
571
572         */
573    }
574
575    fn copy_back_mutable_arguments(
576        &mut self,
577        signature: &Signature,
578        maybe_self: Option<FrameMemoryRegion>,
579        arguments: &Vec<ArgumentExpressionOrLocation>,
580    ) {
581        let arguments_memory_region = self.infinite_above_frame_size();
582        let mut arguments_allocator = ScopeAllocator::new(arguments_memory_region);
583
584        let _argument_addr = Self::reserve(&signature.return_type, &mut arguments_allocator);
585
586        let mut parameters = signature.parameters.clone();
587        if let Some(found_self) = maybe_self {
588            let source_region =
589                Self::reserve(&parameters[0].resolved_type, &mut arguments_allocator);
590            self.state.builder.add_mov(
591                found_self.addr,
592                source_region.addr,
593                source_region.size,
594                "copy back to <self>",
595            );
596            parameters.remove(0);
597        }
598        for (parameter, argument) in parameters.iter().zip(arguments) {
599            let source_region = Self::reserve(&parameter.resolved_type, &mut arguments_allocator);
600            if !parameter.is_mutable {
601                continue;
602            }
603
604            if let ArgumentExpressionOrLocation::Location(found_location) = argument {
605                let argument_target = self.gen_lvalue_address(found_location);
606                self.state.builder.add_mov(
607                    argument_target.addr,
608                    source_region.addr,
609                    source_region.size,
610                    &format!(
611                        "copy back mutable argument {}",
612                        found_location.starting_variable.assigned_name
613                    ),
614                );
615            } else {
616                panic!("internal error. argument is mut but not a location")
617            }
618        }
619    }
620    fn gen_arguments(
621        &mut self,
622        signature: &Signature,
623        self_region: Option<FrameMemoryRegion>,
624        arguments: &Vec<ArgumentExpressionOrLocation>,
625    ) {
626        let arguments_memory_region = self.infinite_above_frame_size();
627        let mut arguments_allocator = ScopeAllocator::new(arguments_memory_region);
628
629        let _argument_addr = Self::reserve(&signature.return_type, &mut arguments_allocator);
630
631        let mut argument_targets = Vec::new();
632        let mut argument_comments = Vec::new();
633
634        for type_for_parameter in &signature.parameters {
635            let argument_target =
636                Self::reserve(&type_for_parameter.resolved_type, &mut arguments_allocator);
637            let arg_ctx = Context::new(argument_target);
638            argument_targets.push(arg_ctx);
639            argument_comments.push(format!("argument {}", type_for_parameter.name));
640        }
641
642        if let Some(push_self) = self_region {
643            self.state.builder.add_mov(
644                argument_targets[0].addr(),
645                push_self.addr,
646                push_self.size,
647                "<self>",
648            );
649            argument_targets.remove(0);
650        }
651
652        for ((argument_target_ctx, argument_expr_or_loc), argument_comment) in argument_targets
653            .iter()
654            .zip(arguments)
655            .zip(argument_comments)
656        {
657            self.gen_argument(
658                argument_expr_or_loc,
659                &argument_target_ctx,
660                &argument_comment,
661            );
662        }
663    }
664
665    fn gen_postfix_chain(
666        &mut self,
667        start_expression: &Expression,
668        chain: &[Postfix],
669        ctx: &Context,
670    ) {
671        if let ExpressionKind::InternalFunctionAccess(internal_fn) = &start_expression.kind {
672            if chain.len() == 1 {
673                if let PostfixKind::FunctionCall(args) = &chain[0].kind {
674                    self.gen_arguments(&internal_fn.signature, None, args);
675                    self.state
676                        .add_call(internal_fn, &format!("frame size: {}", self.frame_size)); // will be fixed up later
677                    let (return_size, _alignment) =
678                        type_size_and_alignment(&internal_fn.signature.return_type);
679                    if return_size.0 != 0 {
680                        self.state.builder.add_mov(
681                            ctx.addr(),
682                            self.infinite_above_frame_size().addr,
683                            return_size,
684                            "copy the return value to destination",
685                        );
686                    }
687                    self.copy_back_mutable_arguments(&internal_fn.signature, None, args);
688
689                    return;
690                }
691            }
692        }
693
694        let start_source = self.gen_expression_for_access(start_expression, ctx);
695
696        for element in chain {
697            match &element.kind {
698                PostfixKind::StructField(_, _) => todo!(),
699                PostfixKind::MemberCall(function_to_call, arguments) => {
700                    match &**function_to_call {
701                        Function::Internal(internal_fn) => {
702                            self.gen_arguments(
703                                &internal_fn.signature,
704                                Some(start_source),
705                                arguments,
706                            );
707                            self.state
708                                .add_call(internal_fn, &format!("frame size: {}", self.frame_size)); // will be fixed up later
709                            let (return_size, _alignment) =
710                                type_size_and_alignment(&internal_fn.signature.return_type);
711                            if return_size.0 != 0 {
712                                self.state.builder.add_mov(
713                                    ctx.addr(),
714                                    self.infinite_above_frame_size().addr,
715                                    return_size,
716                                    "copy the return value to destination",
717                                );
718                            }
719
720                            self.copy_back_mutable_arguments(
721                                &internal_fn.signature,
722                                Some(start_source),
723                                arguments,
724                            );
725                        }
726                        Function::External(external_fn) => {
727                            //self.state.builder.add_host_call(external_fn.id);
728                        }
729                    }
730                }
731                PostfixKind::FunctionCall(arguments) => {
732                    //self.gen_arguments(arguments);
733                    //self.state.add_call(start_expression)
734                }
735                PostfixKind::OptionUnwrap => todo!(),
736                PostfixKind::NoneCoalesce(_) => todo!(),
737                PostfixKind::IntrinsicCall(_, _) => todo!(),
738            }
739        }
740    }
741
742    fn gen_tuple(&mut self, expressions: &[Expression], ctx: &Context) {
743        let mut scope = ScopeAllocator::new(ctx.target());
744
745        for expr in expressions {
746            let (memory_size, alignment) = type_size_and_alignment(&expr.ty);
747            let start_addr = scope.allocate(memory_size, alignment);
748            let element_region = FrameMemoryRegion::new(start_addr, memory_size);
749            let element_ctx = Context::new(element_region);
750            self.gen_expression(expr, &element_ctx);
751        }
752    }
753
754    fn get_struct_field_offset(
755        fields: &SeqMap<String, StructTypeField>,
756        index_to_find: usize,
757    ) -> MemoryOffset {
758        let mut offset = 0;
759
760        for (index, (_name, field)) in fields.iter().enumerate() {
761            if index == index_to_find {
762                break;
763            }
764
765            let (struct_field, struct_field_align) = type_size_and_alignment(&field.field_type);
766            offset += struct_field.0;
767        }
768
769        MemoryOffset(offset)
770    }
771
772    fn gen_anonymous_struct(
773        &mut self,
774        anon_struct_type: &AnonymousStructType,
775        source_order_expressions: &Vec<(usize, Expression)>,
776        base_context: &Context,
777    ) {
778        for (field_index, expression) in source_order_expressions {
779            let field_memory_offset = Self::get_struct_field_offset(
780                &anon_struct_type.field_name_sorted_fields,
781                *field_index,
782            );
783            let mut field_ctx = base_context.with_offset(MemorySize(field_memory_offset.0));
784            self.gen_expression(expression, &mut field_ctx);
785        }
786    }
787
788    fn gen_literal(&mut self, literal: &Literal, ctx: &Context) {
789        match literal {
790            Literal::IntLiteral(int) => {
791                self.state.builder.add_ld32(ctx.addr(), *int, "int literal");
792            }
793            Literal::FloatLiteral(fixed_point) => {
794                self.state
795                    .builder
796                    .add_ld32(ctx.addr(), fixed_point.inner(), "float literal");
797            }
798            Literal::NoneLiteral => {
799                self.state.builder.add_ld8(ctx.addr(), 0, "none literal");
800            }
801            Literal::BoolLiteral(truthy) => {
802                self.state
803                    .builder
804                    .add_ld8(ctx.addr(), u8::from(*truthy), "bool literal");
805            }
806
807            Literal::EnumVariantLiteral(enum_type, a, b) => {
808                self.state.builder.add_ld8(
809                    ctx.addr(),
810                    a.common().container_index,
811                    &format!("enum variant {} tag", a.common().assigned_name),
812                );
813
814                let starting_offset = MemoryOffset(1);
815
816                let (data_size, data_alignment) = match a {
817                    EnumVariantType::Struct(enum_variant_struct) => {
818                        layout_struct(&enum_variant_struct.anon_struct)
819                    }
820                    EnumVariantType::Tuple(tuple_type) => layout_tuple(&tuple_type.fields_in_order),
821                    EnumVariantType::Nothing(_) => (MemorySize(0), MemoryAlignment::U8),
822                };
823
824                let skip_octets: usize = data_alignment.into();
825                let skip = MemorySize(skip_octets as u16);
826                let inner_addr = ctx.addr().add(skip);
827                let region = FrameMemoryRegion::new(inner_addr, data_size);
828                let inner_ctx = Context::new(region);
829
830                //layout_union(a)
831                match b {
832                    EnumLiteralData::Nothing => {}
833                    EnumLiteralData::Tuple(expressions) => {
834                        self.gen_tuple(expressions, &inner_ctx);
835                    }
836                    EnumLiteralData::Struct(sorted_expressions) => {
837                        if let EnumVariantType::Struct(variant_struct_type) = a {
838                            self.gen_anonymous_struct(
839                                &variant_struct_type.anon_struct,
840                                sorted_expressions,
841                                &inner_ctx,
842                            );
843                        }
844                    }
845                }
846            }
847            Literal::TupleLiteral(_, _) => todo!(),
848            Literal::StringLiteral(str) => {
849                self.gen_string_literal(str, ctx);
850            }
851            Literal::Slice(ty, expressions) => self.gen_slice_literal(ty, expressions, ctx),
852            Literal::SlicePair(_, _) => todo!(),
853        }
854    }
855
856    fn gen_string_literal(&mut self, string: &str, ctx: &Context) {
857        let data_ptr = self
858            .state
859            .constants
860            .allocate(string.as_bytes(), MemoryAlignment::U8);
861        let mem_size = MemorySize(string.len() as u16);
862
863        self.gen_vec_immediate(data_ptr, mem_size, mem_size, "string", ctx);
864    }
865
866    fn gen_vec_immediate(
867        &mut self,
868        data_ptr: MemoryAddress,
869        len: MemorySize,
870        capacity: MemorySize,
871        comment_prefix: &str,
872        ctx: &Context,
873    ) {
874        self.state
875            .builder
876            .add_ld_u16(ctx.addr(), len.0, &format!("{} len", comment_prefix));
877
878        self.state.builder.add_ld_u16(
879            ctx.addr().add(MemorySize(2)),
880            capacity.0,
881            &format!("{} capacity", comment_prefix),
882        );
883
884        self.state.builder.add_ld_u16(
885            ctx.addr().add(MemorySize(4)),
886            data_ptr.0,
887            &format!("{} ptr", comment_prefix),
888        );
889    }
890
891    fn gen_option_expression(&mut self, maybe_option: Option<&Expression>, ctx: &Context) {
892        if let Some(found_value) = maybe_option {
893            self.state.builder.add_ld8(ctx.addr(), 1, "option Some tag"); // 1 signals `Some`
894            let mut one_offset_ctx = ctx.with_offset(MemorySize(1));
895            self.gen_expression(found_value, &mut one_offset_ctx); // Fills in more of the union
896        } else {
897            self.state.builder.add_ld8(ctx.addr(), 0, "option None tag"); // 0 signals `None`
898            // No real need to clear the rest of the memory
899        }
900    }
901
902    fn gen_for_loop(
903        &mut self,
904        for_pattern: &ForPattern,
905        iterable: &Iterable,
906        body: &Box<Expression>,
907        ctx: &Context,
908    ) {
909        // Add check if the collection is empty, to skip everything
910
911        // get some kind of iteration pointer
912
913        // check if it has reached its end
914
915        match for_pattern {
916            ForPattern::Single(value_variable) => {}
917            ForPattern::Pair(key_variable, value_variable) => {}
918        }
919
920        let mut unit_expr = self.temp_space_for_type(&Type::Unit, "for loop body");
921        self.gen_expression(body, &mut unit_expr);
922
923        // advance iterator pointer
924        // jump to check if iterator pointer has reached its end
925    }
926
927    fn gen_for_loop_for_vec(
928        &mut self,
929        element_type: &Type,
930        vector_expr: Expression,
931        ctx: &mut Context,
932    ) {
933        // get the vector that is referenced
934        let mut vector_ctx = self.temp_space_for_type(&vector_expr.ty, "vector space");
935        self.gen_expression(&vector_expr, &mut vector_ctx);
936
937        /*
938        let value_var_addr = match for_pattern {
939            ForPattern::Single(value_variable) => self
940                .variable_offsets
941                .get(&value_variable.unique_id_within_function)
942                .expect("Variable not found"),
943            ForPattern::Pair(_, _) => {
944                panic!("Cannot use key-value pattern with vectors");
945            }
946        };
947
948         */
949
950        /*
951        let element_size = type_size(element_type);
952               // Temporary for the counter
953               let counter_addr = ctx.allocate_temp(MemorySize(2)); // u16 counter
954               self.state
955                   .builder
956                   .add_ld_u16(counter_addr, 0, "temporary counter");
957
958               let loop_start_pos = self.state.builder.position();
959
960               // vector length
961               let length_addr = ctx.allocate_temp(MemorySize(2));
962               self.state.builder.add_mov(
963                   length_addr,
964                   vector_ctx.addr().add(MemorySize(VECTOR_LENGTH_OFFSET)),
965                   MemorySize(2),
966                   "vector length",
967               );
968
969               // Compare counter < length
970               let compare_result_addr = ctx.allocate_temp(MemorySize(1)); // boolean result
971               self.state.builder.add_lt_u16(
972                   compare_result_addr,
973                   counter_addr,
974                   length_addr,
975                   "counter < length",
976               );
977
978               // Exit loop if counter >= length
979               let exit_jump = self
980                   .state
981                   .builder
982                   .add_conditional_jump_placeholder(compare_result_addr, "counter >= length exit");
983
984               let data_ptr_addr = ctx.allocate_temp(MemorySize(2));
985               self.state.builder.add_mov(
986                   data_ptr_addr,
987                   vector_ctx.addr().add(MemorySize(VECTOR_DATA_PTR_OFFSET)),
988                   MemorySize(PTR_SIZE),
989                   "copy vector data ptr",
990               );
991
992
993        */
994        /*
995        let offset_addr = ctx.allocate_temp(2);
996        self.state.builder.add_mul_u16(
997            offset_addr,
998            counter_addr,
999            element_size
1000        );
1001
1002        self.state.builder.add_ld_indirect(
1003            *value_var_addr,     // Destination: loop variable
1004            data_ptr_addr,       // Base: vector's data pointer
1005            offset_addr,         // Offset: counter * element_size
1006            element_size         // Size to copy
1007        );
1008
1009        let mut body_ctx = ctx.temp_space_for_type(&Type::Unit);
1010        self.gen_expression(body, &mut body_ctx);
1011
1012        self.state.builder.add_inc_u16(counter_addr);
1013
1014        self.state.builder.add_jmp_to_position(loop_start_pos);
1015
1016        let end_pos = self.state.builder.current_position();
1017        self.state.builder.patch_jump(exit_jump, end_pos);
1018
1019         */
1020    }
1021
1022    fn gen_block(&mut self, expressions: &[Expression], ctx: &Context) {
1023        if let Some((last, others)) = expressions.split_last() {
1024            for expr in others {
1025                let mut temp_context = self.temp_space_for_type(&Type::Unit, "block target");
1026                self.gen_expression(expr, &mut temp_context);
1027            }
1028            self.gen_expression(last, ctx);
1029        }
1030    }
1031
1032    fn gen_variable_access(&mut self, variable: &VariableRef, ctx: &Context) {
1033        let frame_address = self
1034            .variable_offsets
1035            .get(&variable.unique_id_within_function)
1036            .unwrap();
1037        let (size, _align) = type_size_and_alignment(&variable.resolved_type);
1038        self.state.builder.add_mov(
1039            ctx.addr(),
1040            frame_address.addr,
1041            size,
1042            &format!(
1043                "variable access '{}' ({})",
1044                variable.assigned_name,
1045                ctx.comment()
1046            ),
1047        );
1048    }
1049
1050    fn referenced_or_not_type(ty: &Type) -> Type {
1051        if let Type::MutableReference(inner_type) = ty {
1052            *inner_type.clone()
1053        } else {
1054            ty.clone()
1055        }
1056    }
1057
1058    fn compound_assignment(
1059        &mut self,
1060        target_location: &SingleMutLocationExpression,
1061        op: &CompoundOperatorKind,
1062        source: &Expression,
1063        ctx: &Context,
1064    ) {
1065        let target_location = self.gen_lvalue_address(&target_location.0);
1066
1067        let source_info = self.gen_expression_for_access(source, ctx);
1068
1069        let type_to_consider = Self::referenced_or_not_type(&source.ty);
1070
1071        match &type_to_consider {
1072            Type::Int => {
1073                self.gen_compound_assignment_i32(&target_location, op, &source_info);
1074            }
1075            Type::Float => todo!(),
1076            Type::String => todo!(),
1077            Type::Bool => todo!(),
1078            Type::Unit => todo!(),
1079            Type::Never => todo!(),
1080            Type::Tuple(_) => todo!(),
1081            Type::NamedStruct(_) => todo!(),
1082            Type::AnonymousStruct(_) => todo!(),
1083            Type::Enum(_) => todo!(),
1084            Type::Function(_) => todo!(),
1085            Type::Iterable(_) => todo!(),
1086            Type::Optional(_) => todo!(),
1087            Type::Generic(_, _) => todo!(),
1088            Type::Blueprint(_) => todo!(),
1089            Type::Variable(_) => todo!(),
1090            Type::External(_) => todo!(),
1091            Type::MutableReference(x) => panic!("should have been checked"),
1092            Type::Slice(_) => todo!(),
1093            Type::SlicePair(_, _) => todo!(),
1094        }
1095    }
1096
1097    fn gen_compound_assignment_i32(
1098        &mut self,
1099        target: &FrameMemoryRegion,
1100        op: &CompoundOperatorKind,
1101        source_ctx: &FrameMemoryRegion,
1102    ) {
1103        match op {
1104            CompoundOperatorKind::Add => {
1105                self.state.builder.add_add_i32(
1106                    target.addr(),
1107                    target.addr(),
1108                    source_ctx.addr(),
1109                    "+=  (i32)",
1110                );
1111            }
1112            CompoundOperatorKind::Sub => todo!(),
1113            CompoundOperatorKind::Mul => todo!(),
1114            CompoundOperatorKind::Div => todo!(),
1115            CompoundOperatorKind::Modulo => todo!(),
1116        }
1117    }
1118
1119    fn internal_function_access(
1120        &mut self,
1121        internal: &InternalFunctionDefinitionRef,
1122        ctx: &Context,
1123    ) {
1124        self.state.builder.add_ld_u16(
1125            ctx.addr(),
1126            internal.program_unique_id,
1127            &format!("function access '{}'", internal.assigned_name),
1128        );
1129    }
1130
1131    fn infinite_above_frame_size(&self) -> FrameMemoryRegion {
1132        FrameMemoryRegion::new(FrameMemoryAddress(self.frame_size.0), MemorySize(1024))
1133    }
1134
1135    fn gen_struct_literal(&mut self, struct_literal: &StructInstantiation, ctx: &Context) {
1136        let struct_type =
1137            Type::AnonymousStruct(struct_literal.struct_type_ref.anon_struct_type.clone());
1138        let (whole_struct_size, whole_struct_alignment) = type_size_and_alignment(&struct_type);
1139        if ctx.target_size().0 != whole_struct_size.0 {
1140            info!("problem");
1141        }
1142        assert_eq!(ctx.target_size().0, whole_struct_size.0);
1143
1144        for (field_index, expression) in &struct_literal.source_order_expressions {
1145            let (field_offset, field_size, field_alignment) = struct_field_offset(
1146                *field_index,
1147                &struct_literal.struct_type_ref.anon_struct_type,
1148            );
1149            //info!(?field_offset, ?field_index, "field offset");
1150            let new_address = ctx.addr().advance(field_offset);
1151            let mut field_ctx = Context::new(FrameMemoryRegion::new(new_address, field_size));
1152            self.gen_expression(expression, &mut field_ctx);
1153        }
1154    }
1155
1156    fn gen_slice_literal(&mut self, ty: &Type, expressions: &Vec<Expression>, ctx: &Context) {
1157        let (element_size, element_alignment) = type_size_and_alignment(ty);
1158        let element_count = expressions.len() as u16;
1159        let total_slice_size = MemorySize(element_size.0 * element_count);
1160
1161        let start_frame_address_to_transfer = self
1162            .temp_allocator
1163            .allocate(total_slice_size, element_alignment);
1164        for (index, expr) in expressions.iter().enumerate() {
1165            let memory_offset = MemoryOffset((index as u16) * element_size.0);
1166            let region = FrameMemoryRegion::new(
1167                start_frame_address_to_transfer.advance(memory_offset),
1168                element_size,
1169            );
1170            let element_ctx = Context::new(region);
1171            self.gen_expression(expr, &element_ctx);
1172        }
1173
1174        let vec_len_addr = self
1175            .extra_frame_allocator
1176            .allocate(MemorySize(2), MemoryAlignment::U16);
1177        self.state
1178            .builder
1179            .add_ld_u16(vec_len_addr, element_count, "vec len");
1180
1181        let vec_capacity_addr = self
1182            .extra_frame_allocator
1183            .allocate(MemorySize(2), MemoryAlignment::U16);
1184        self.state
1185            .builder
1186            .add_ld_u16(vec_capacity_addr, element_count, "vec capacity");
1187
1188        let vec_element_size_addr = self
1189            .extra_frame_allocator
1190            .allocate(MemorySize(2), MemoryAlignment::U16);
1191        self.state
1192            .builder
1193            .add_ld_u16(vec_element_size_addr, element_size.0, "element size");
1194
1195        let allocated_vec_address = self
1196            .extra_frame_allocator
1197            .allocate(MemorySize(PTR_SIZE), MemoryAlignment::U16);
1198        self.state
1199            .builder
1200            .add_alloc(allocated_vec_address, total_slice_size, "slice literal");
1201
1202        self.state.builder.add_stx(
1203            allocated_vec_address,
1204            MemoryOffset(0),
1205            start_frame_address_to_transfer,
1206            total_slice_size,
1207            "copy from slice continuous temporary frame memory to allocated vec ptr heap area",
1208        );
1209    }
1210
1211    fn gen_intrinsic_call_ex(
1212        &mut self,
1213        intrinsic_fn: &IntrinsicFunction,
1214        arguments: &Vec<ArgumentExpressionOrLocation>,
1215        ctx: &Context,
1216    ) {
1217        //        info!(?intrinsic_fn, "generating intrinsic call");
1218
1219        match intrinsic_fn {
1220            IntrinsicFunction::FloatRound => todo!(),
1221            IntrinsicFunction::FloatFloor => todo!(),
1222            IntrinsicFunction::FloatSqrt => todo!(),
1223            IntrinsicFunction::FloatSign => todo!(),
1224            IntrinsicFunction::FloatAbs => todo!(),
1225            IntrinsicFunction::FloatRnd => todo!(),
1226            IntrinsicFunction::FloatCos => todo!(),
1227            IntrinsicFunction::FloatSin => todo!(),
1228            IntrinsicFunction::FloatAcos => todo!(),
1229            IntrinsicFunction::FloatAsin => todo!(),
1230            IntrinsicFunction::FloatAtan2 => todo!(),
1231            IntrinsicFunction::FloatMin => todo!(),
1232            IntrinsicFunction::FloatMax => todo!(),
1233            IntrinsicFunction::FloatClamp => todo!(),
1234            IntrinsicFunction::IntAbs => todo!(),
1235            IntrinsicFunction::IntRnd => todo!(),
1236            IntrinsicFunction::IntMax => todo!(),
1237            IntrinsicFunction::IntMin => todo!(),
1238            IntrinsicFunction::IntClamp => todo!(),
1239            IntrinsicFunction::IntToFloat => todo!(),
1240            IntrinsicFunction::StringLen => todo!(),
1241            IntrinsicFunction::VecFromSlice => self.gen_intrinsic_vec_from_slice(arguments, ctx),
1242            IntrinsicFunction::VecPush => {}
1243            IntrinsicFunction::VecPop => {}
1244            IntrinsicFunction::VecRemoveIndex => {}
1245            IntrinsicFunction::VecClear => {}
1246            IntrinsicFunction::VecCreate => self.gen_intrinsic_vec_create(arguments),
1247            IntrinsicFunction::VecSubscript => {}
1248            IntrinsicFunction::VecSubscriptMut => {}
1249            IntrinsicFunction::VecIter => {} // intentionally disregard, since it is never called
1250            IntrinsicFunction::VecIterMut => {} // intentionally disregard, since it is never called
1251            IntrinsicFunction::VecLen => {}
1252            IntrinsicFunction::VecIsEmpty => {}
1253
1254            IntrinsicFunction::VecSelfPush => todo!(),
1255            IntrinsicFunction::VecSelfExtend => todo!(),
1256            IntrinsicFunction::MapCreate => todo!(),
1257            IntrinsicFunction::MapFromSlicePair => todo!(),
1258            IntrinsicFunction::MapHas => todo!(),
1259            IntrinsicFunction::MapRemove => todo!(),
1260            IntrinsicFunction::MapIter => todo!(),
1261            IntrinsicFunction::MapIterMut => todo!(),
1262            IntrinsicFunction::MapLen => todo!(),
1263            IntrinsicFunction::MapIsEmpty => todo!(),
1264            IntrinsicFunction::MapSubscript => todo!(),
1265            IntrinsicFunction::MapSubscriptSet => todo!(),
1266            IntrinsicFunction::MapSubscriptMut => todo!(),
1267            IntrinsicFunction::MapSubscriptMutCreateIfNeeded => todo!(),
1268            IntrinsicFunction::SparseCreate => todo!(),
1269            IntrinsicFunction::SparseFromSlice => todo!(),
1270            IntrinsicFunction::SparseIter => todo!(),
1271            IntrinsicFunction::SparseIterMut => todo!(),
1272            IntrinsicFunction::SparseSubscript => todo!(),
1273            IntrinsicFunction::SparseSubscriptMut => todo!(),
1274            IntrinsicFunction::SparseHas => todo!(),
1275            IntrinsicFunction::SparseRemove => todo!(),
1276            IntrinsicFunction::GridCreate => todo!(),
1277            IntrinsicFunction::GridFromSlice => todo!(),
1278            IntrinsicFunction::GridSubscript => todo!(),
1279            IntrinsicFunction::GridSubscriptMut => todo!(),
1280            IntrinsicFunction::Float2Magnitude => todo!(),
1281            IntrinsicFunction::SparseAdd => todo!(),
1282            IntrinsicFunction::SparseNew => todo!(),
1283        };
1284    }
1285
1286    fn gen_intrinsic_vec_create(&self, arguments: &Vec<ArgumentExpressionOrLocation>) {
1287        for arg in arguments {
1288            info!(?arg, "argument");
1289        }
1290    }
1291
1292    fn gen_intrinsic_vec_from_slice(
1293        &mut self,
1294        arguments: &Vec<ArgumentExpressionOrLocation>,
1295        ctx: &Context,
1296    ) {
1297        if let ArgumentExpressionOrLocation::Expression(found_expr) = &arguments[0] {
1298            self.gen_expression_for_access(found_expr, ctx);
1299        } else {
1300            panic!("vec_from_slice");
1301        }
1302    }
1303}
1304
1305fn struct_field_offset(
1306    index_to_look_for: usize,
1307    anon_struct_type: &AnonymousStructType,
1308) -> (MemoryOffset, MemorySize, MemoryAlignment) {
1309    let mut offset = MemoryOffset(0);
1310    for (field_index, (_name, field)) in
1311        anon_struct_type.field_name_sorted_fields.iter().enumerate()
1312    {
1313        let (field_size, field_alignment) = type_size_and_alignment(&field.field_type);
1314        let field_start_offset = offset.space(field_size, field_alignment);
1315        if field_index == index_to_look_for {
1316            return (field_start_offset, field_size, field_alignment);
1317        }
1318    }
1319
1320    panic!("field index is wrong")
1321}