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