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