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, ArgumentExpressionOrLocation, BinaryOperator, BinaryOperatorKind,
26 BooleanExpression, CompoundOperatorKind, ConstantId, ConstantRef, EnumLiteralData, Expression,
27 ExpressionKind, ForPattern, Function, Guard, InternalFunctionDefinitionRef, InternalFunctionId,
28 InternalMainExpression, Iterable, Literal, Match, MutOrImmutableExpression, NormalPattern,
29 Pattern, Postfix, PostfixKind, SingleLocationExpression, SingleMutLocationExpression,
30 StructInstantiation, 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: &[ArgumentExpressionOrLocation],
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 ArgumentExpressionOrLocation::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 ArgumentExpressionOrLocation::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 }
515
516 fn gen_intrinsic_map_remove(
517 &mut self,
518 map_region: FrameMemoryRegion,
519 key_expr: &Expression,
520 ctx: &Context,
521 ) -> Result<(), Error> {
522 let key_region = self.gen_expression_for_access(key_expr)?;
523
524 self.state
525 .builder
526 .add_map_remove(map_region.addr, key_region.addr, "");
527
528 Ok(())
529 }
530
531 pub fn reserve(ty: &Type, allocator: &mut ScopeAllocator) -> FrameMemoryRegion {
532 let (size, alignment) = type_size_and_alignment(ty);
533 allocator.reserve(size, alignment)
534 }
535
536 pub fn layout_variables(
539 &mut self,
540 variables: &Vec<VariableRef>,
541 return_type: &Type,
542 ) -> Result<(), Error> {
543 let mut allocator = ScopeAllocator::new(FrameMemoryRegion::new(
544 FrameMemoryAddress(0),
545 MemorySize(1024),
546 ));
547 let _current_offset = Self::reserve(return_type, &mut allocator);
548
549 let mut enter_comment = "variables:\n".to_string();
550
551 for var_ref in variables {
552 let var_target = Self::reserve(&var_ref.resolved_type, &mut allocator);
553 trace!(?var_ref.assigned_name, ?var_target, "laying out");
554 enter_comment += &format!(
555 " ${:04X}:{} {}\n",
556 var_target.addr.0, var_target.size.0, var_ref.assigned_name
557 );
558 self.variable_offsets
559 .insert(var_ref.unique_id_within_function, var_target)
560 .map_err(|_| self.create_err(ErrorKind::VariableNotUnique, &var_ref.name))?;
561 }
562
563 let extra_frame_size = MemorySize(80);
564 let extra_target = FrameMemoryRegion::new(allocator.addr(), extra_frame_size);
565 self.frame_size = allocator.addr().as_size().add(extra_frame_size);
566
567 self.state
568 .builder
569 .add_enter(self.frame_size, &enter_comment);
570
571 const ARGUMENT_MAX_SIZE: u16 = 256;
572 self.argument_allocator = ScopeAllocator::new(FrameMemoryRegion::new(
573 FrameMemoryAddress(self.frame_size.0),
574 MemorySize(ARGUMENT_MAX_SIZE),
575 ));
576
577 self.temp_allocator = ScopeAllocator::new(FrameMemoryRegion::new(
578 FrameMemoryAddress(self.frame_size.0 + ARGUMENT_MAX_SIZE),
579 MemorySize(1024),
580 ));
581
582 Ok(())
583 }
584
585 pub fn temp_memory_region_for_type(&mut self, ty: &Type, comment: &str) -> FrameMemoryRegion {
586 let new_target_info = reserve_space_for_type(ty, &mut self.temp_allocator);
587 new_target_info
588 }
589
590 pub fn temp_space_for_type(&mut self, ty: &Type, comment: &str) -> Context {
591 Context::new(self.temp_memory_region_for_type(ty, comment))
592 }
593
594 #[allow(clippy::single_match_else)]
597 pub fn gen_expression_for_access(
598 &mut self,
599 expr: &Expression,
600 ) -> Result<FrameMemoryRegion, Error> {
601 let (region, _gen_result) = self.gen_expression_for_access_internal(expr)?;
602
603 Ok(region)
604 }
605
606 #[allow(clippy::single_match_else)]
609 pub fn gen_expression_for_access_internal(
610 &mut self,
611 expr: &Expression,
612 ) -> Result<(FrameMemoryRegion, GeneratedExpressionResult), Error> {
613 match &expr.kind {
614 ExpressionKind::VariableAccess(var_ref) => {
615 let frame_address = self
616 .variable_offsets
617 .get(&var_ref.unique_id_within_function)
618 .unwrap();
619
620 return Ok((*frame_address, GeneratedExpressionResult::default()));
621 }
622
623 ExpressionKind::Literal(lit) => match lit {
624 Literal::Slice(slice_type, expressions) => {
625 return Ok((
626 self.gen_slice_literal(slice_type, expressions)?,
627 GeneratedExpressionResult::default(),
628 ));
629 }
630 Literal::SlicePair(slice_pair_type, pairs) => {
631 let info = self.gen_slice_pair_literal(slice_pair_type, pairs);
632 return Ok((
633 FrameMemoryRegion::new(
634 info.addr.0,
635 MemorySize(info.element_count.0 * info.element_size.0),
636 ),
637 GeneratedExpressionResult::default(),
638 ));
639 }
640 _ => {}
641 },
642 _ => {}
643 };
644
645 let temp_ctx = self.temp_space_for_type(&expr.ty, "expression");
646
647 let expression_result = self.gen_expression(expr, &temp_ctx)?;
648
649 Ok((temp_ctx.target(), expression_result))
650 }
651
652 pub(crate) fn extra_frame_space_for_type(&mut self, ty: &Type) -> Context {
653 let target = Self::reserve(ty, &mut self.temp_allocator);
654 Context::new(target)
655 }
656
657 fn debug_node(&self, node: &Node) {
658 let line_info = self.source_map_lookup.get_line(&node.span);
659 let span_text = self.source_map_lookup.get_text_span(&node.span);
660 eprintln!(
661 "{}:{}:{}> {}",
662 line_info.relative_file_name, line_info.row, line_info.col, span_text,
663 );
664 }
666
667 fn debug_instructions(&mut self) {
668 let end_ip = self.state.builder.instructions.len() - 1;
669 let instructions_to_disasm =
670 &self.state.builder.instructions[self.state.debug_last_ip..=end_ip];
671 let mut descriptions = Vec::new();
672 for x in instructions_to_disasm {
673 descriptions.push(String::new());
674 }
675 let output = disasm_instructions_color(
676 instructions_to_disasm,
677 &InstructionPosition(self.state.debug_last_ip as u16),
678 &descriptions,
679 &SeqMap::default(),
680 );
681 eprintln!("{output}");
682 self.state.debug_last_ip = end_ip + 1;
683 }
684
685 pub fn gen_expression(
686 &mut self,
687 expr: &Expression,
688 ctx: &Context,
689 ) -> Result<GeneratedExpressionResult, Error> {
690 self.debug_node(&expr.node);
691 let result = match &expr.kind {
692 ExpressionKind::InterpolatedString(_) => todo!(),
693
694 ExpressionKind::ConstantAccess(constant_ref) => self
695 .gen_constant_access(constant_ref, ctx)
696 .map(|_| GeneratedExpressionResult::default()),
697 ExpressionKind::TupleDestructuring(variables, tuple_types, tuple_expression) => self
698 .gen_tuple_destructuring(variables, tuple_types, tuple_expression)
699 .map(|_| GeneratedExpressionResult::default()),
700
701 ExpressionKind::Assignment(target_mut_location_expr, source_expr) => self
702 .gen_assignment(target_mut_location_expr, source_expr)
703 .map(|_| GeneratedExpressionResult::default()),
704 ExpressionKind::VariableAccess(variable_ref) => self
705 .gen_variable_access(variable_ref, ctx)
706 .map(|_| GeneratedExpressionResult::default()),
707 ExpressionKind::InternalFunctionAccess(function) => self
708 .internal_function_access(function, ctx)
709 .map(|_| GeneratedExpressionResult::default()),
710 ExpressionKind::BinaryOp(operator) => self.gen_binary_operator(operator, ctx),
711 ExpressionKind::UnaryOp(operator) => self
712 .gen_unary_operator(operator, ctx)
713 .map(|_| GeneratedExpressionResult::default()),
714 ExpressionKind::PostfixChain(start, chain) => self
715 .gen_postfix_chain(start, chain, ctx)
716 .map(|_| GeneratedExpressionResult::default()),
717 ExpressionKind::VariableDefinition(variable, expression) => self
718 .gen_variable_definition(variable, expression, ctx)
719 .map(|_| GeneratedExpressionResult::default()),
720 ExpressionKind::VariableReassignment(variable, expression) => self
721 .gen_variable_reassignment(variable, expression, ctx)
722 .map(|_| GeneratedExpressionResult::default()),
723 ExpressionKind::StructInstantiation(struct_literal) => self
724 .gen_struct_literal(struct_literal, ctx)
725 .map(|()| GeneratedExpressionResult::default()),
726 ExpressionKind::AnonymousStructLiteral(anon_struct) => self
727 .gen_anonymous_struct_literal(anon_struct, ctx)
728 .map(|_| GeneratedExpressionResult::default()),
729 ExpressionKind::Literal(basic_literal) => self
730 .gen_literal(basic_literal, ctx)
731 .map(|_| GeneratedExpressionResult::default()),
732 ExpressionKind::Option(maybe_option) => self
733 .gen_option_expression(maybe_option.as_deref(), ctx)
734 .map(|_| GeneratedExpressionResult::default()),
735 ExpressionKind::ForLoop(a, b, c) => self
736 .gen_for_loop(a, b, c)
737 .map(|_| GeneratedExpressionResult::default()),
738 ExpressionKind::WhileLoop(condition, expression) => self
739 .gen_while_loop(condition, expression, ctx)
740 .map(|_| GeneratedExpressionResult::default()),
741 ExpressionKind::Block(expressions) => self
742 .gen_block(expressions, ctx)
743 .map(|_| GeneratedExpressionResult::default()),
744 ExpressionKind::Match(match_expr) => self
745 .gen_match(match_expr, ctx)
746 .map(|_| GeneratedExpressionResult::default()),
747 ExpressionKind::Guard(guards) => self
748 .gen_guard(guards, ctx)
749 .map(|_| GeneratedExpressionResult::default()),
750 ExpressionKind::If(conditional, true_expr, false_expr) => self
751 .gen_if(conditional, true_expr, false_expr.as_deref(), ctx)
752 .map(|_| GeneratedExpressionResult::default()),
753 ExpressionKind::When(bindings, true_expr, false_expr) => self
754 .gen_when(bindings, true_expr, false_expr.as_deref(), ctx)
755 .map(|_| GeneratedExpressionResult::default()),
756 ExpressionKind::CompoundAssignment(target_location, operator_kind, source_expr) => self
757 .compound_assignment(target_location, operator_kind, source_expr, ctx)
758 .map(|_| GeneratedExpressionResult::default()),
759 ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments) => self
760 .gen_intrinsic_call_ex(intrinsic_fn, arguments, ctx)
761 .map(|_| GeneratedExpressionResult::default()),
762
763 ExpressionKind::Lambda(vec, x) => {
764 todo!()
765 }
766 ExpressionKind::CoerceOptionToBool(_) => todo!(),
768 ExpressionKind::FunctionValueCall(_, _, _) => todo!(),
769
770 ExpressionKind::IntrinsicFunctionAccess(_) => todo!(), ExpressionKind::ExternalFunctionAccess(_) => todo!(), };
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 => {}
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 }
804
805 Ok(())
806 }
807
808 fn gen_binary_operator(
809 &mut self,
810 binary_operator: &BinaryOperator,
811 ctx: &Context,
812 ) -> Result<GeneratedExpressionResult, Error> {
813 match (&binary_operator.left.ty, &binary_operator.right.ty) {
814 (Type::Int, Type::Int) => self.gen_binary_operator_i32(binary_operator, ctx),
815 (Type::Bool, Type::Bool) => self.gen_binary_operator_bool(binary_operator),
816 (Type::String, Type::String) => self.gen_binary_operator_string(binary_operator, ctx),
817 _ => todo!(),
818 }
819 }
820
821 fn gen_binary_operator_i32(
822 &mut self,
823 binary_operator: &BinaryOperator,
824 ctx: &Context,
825 ) -> Result<GeneratedExpressionResult, Error> {
826 let left_source = self.gen_expression_for_access(&binary_operator.left)?;
827 let right_source = self.gen_expression_for_access(&binary_operator.right)?;
828
829 match binary_operator.kind {
830 BinaryOperatorKind::Add => {
831 self.state.builder.add_add_i32(
832 ctx.addr(),
833 left_source.addr(),
834 right_source.addr(),
835 "i32 add",
836 );
837 }
838
839 BinaryOperatorKind::Subtract => todo!(),
840 BinaryOperatorKind::Multiply => {
841 self.state.builder.add_mul_i32(
842 ctx.addr(),
843 left_source.addr(),
844 right_source.addr(),
845 "i32 add",
846 );
847 }
848 BinaryOperatorKind::Divide => todo!(),
849 BinaryOperatorKind::Modulo => todo!(),
850 BinaryOperatorKind::LogicalOr => todo!(),
851 BinaryOperatorKind::LogicalAnd => todo!(),
852 BinaryOperatorKind::Equal => {
853 self.state
854 .builder
855 .add_eq_32(left_source.addr(), right_source.addr(), "i32 eq");
856 }
857 BinaryOperatorKind::NotEqual => todo!(),
858 BinaryOperatorKind::LessThan => {
859 self.state
860 .builder
861 .add_lt_i32(left_source.addr(), right_source.addr(), "i32 lt");
862 }
863 BinaryOperatorKind::LessEqual => todo!(),
864 BinaryOperatorKind::GreaterThan => {
865 self.state
866 .builder
867 .add_gt_i32(left_source.addr(), right_source.addr(), "i32 gt");
868 }
869 BinaryOperatorKind::GreaterEqual => todo!(),
870 BinaryOperatorKind::RangeExclusive => todo!(),
871 }
872
873 Ok(GeneratedExpressionResult {
874 has_set_bool_z_flag: true,
875 })
876 }
877
878 fn gen_binary_operator_string(
879 &mut self,
880 binary_operator: &BinaryOperator,
881 ctx: &Context,
882 ) -> Result<GeneratedExpressionResult, Error> {
883 let left_source = self.gen_expression_for_access(&binary_operator.left)?;
884 let right_source = self.gen_expression_for_access(&binary_operator.right)?;
885
886 match binary_operator.kind {
887 BinaryOperatorKind::Add => {
888 self.state.builder.add_string_append(
889 ctx.addr(),
890 left_source.addr(),
891 right_source.addr(),
892 "string add",
893 );
894 }
895
896 BinaryOperatorKind::Equal => todo!(),
897 BinaryOperatorKind::NotEqual => todo!(),
898 _ => panic!("illegal string operator"),
899 }
900
901 Ok(GeneratedExpressionResult {
902 has_set_bool_z_flag: false,
903 })
904 }
905
906 fn gen_binary_operator_bool(
907 &mut self,
908 binary_operator: &BinaryOperator,
909 ) -> Result<GeneratedExpressionResult, Error> {
910 match binary_operator.kind {
911 BinaryOperatorKind::LogicalOr => {
912 self.gen_boolean_access_set_z_flag(&binary_operator.left);
914
915 let jump_after_patch = self
916 .state
917 .builder
918 .add_jmp_if_equal_placeholder("skip rhs `or` expression");
919
920 self.gen_boolean_access_set_z_flag(&binary_operator.right);
922
923 self.state.builder.patch_jump_here(jump_after_patch);
924 }
925 BinaryOperatorKind::LogicalAnd => {
926 self.gen_boolean_access_set_z_flag(&binary_operator.left);
928
929 let jump_after_patch = self
930 .state
931 .builder
932 .add_jmp_if_not_equal_placeholder("skip rhs `and` expression");
933
934 self.gen_boolean_access_set_z_flag(&binary_operator.right);
936
937 self.state.builder.patch_jump_here(jump_after_patch);
938 }
939 _ => {
940 panic!("unknown operator")
941 }
942 }
943
944 Ok(GeneratedExpressionResult {
945 has_set_bool_z_flag: true,
946 })
947 }
948
949 fn gen_condition_context(
950 &mut self,
951 condition: &BooleanExpression,
952 ) -> Result<(Context, PatchPosition), Error> {
953 let condition_ctx = self.extra_frame_space_for_type(&Type::Bool);
954 self.gen_expression(&condition.expression, &condition_ctx)?;
955
956 let jump_on_false_condition = self
957 .state
958 .builder
959 .add_jmp_if_not_equal_placeholder("jump boolean condition false");
960
961 Ok((condition_ctx, jump_on_false_condition))
962 }
963
964 fn gen_boolean_access_set_z_flag(&mut self, condition: &Expression) -> Result<(), Error> {
965 let (frame_memory_region, gen_result) =
966 self.gen_expression_for_access_internal(condition)?;
967
968 if !gen_result.has_set_bool_z_flag {
969 self.state.builder.add_tst8(
970 frame_memory_region.addr,
971 "convert to boolean expression (update z flag)",
972 );
973 }
974
975 Ok(())
976 }
977
978 fn gen_boolean_expression(&mut self, condition: &BooleanExpression) -> Result<(), Error> {
979 self.gen_boolean_access_set_z_flag(&condition.expression)
980 }
981
982 fn gen_if(
983 &mut self,
984 condition: &BooleanExpression,
985 true_expr: &Expression,
986 maybe_false_expr: Option<&Expression>,
987 ctx: &Context,
988 ) -> Result<(), Error> {
989 let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition)?;
990
991 self.gen_expression(true_expr, ctx)?;
993
994 if let Some(false_expr) = maybe_false_expr {
995 let skip_false_if_true = self
997 .state
998 .builder
999 .add_jump_placeholder("condition is false skip");
1000
1001 self.state.builder.patch_jump_here(jump_on_false_condition);
1003
1004 self.gen_expression(false_expr, ctx)?;
1006
1007 self.state.builder.patch_jump_here(skip_false_if_true);
1008 } else {
1009 self.state.builder.patch_jump_here(jump_on_false_condition);
1010 }
1011
1012 Ok(())
1013 }
1014
1015 fn gen_while_loop(
1016 &mut self,
1017 condition: &BooleanExpression,
1018 expression: &Expression,
1019 ctx: &Context,
1020 ) -> Result<(), Error> {
1021 assert_eq!(ctx.target_size().0, 0);
1023
1024 let ip_for_condition = self.state.builder.position();
1025
1026 let (_condition_ctx, jump_on_false_condition) = self.gen_condition_context(condition)?;
1027
1028 let mut unit_ctx = self.temp_space_for_type(&Type::Unit, "while body expression");
1030 self.gen_expression(expression, &mut unit_ctx)?;
1031
1032 self.state
1034 .builder
1035 .add_jmp(ip_for_condition, "jmp to while condition");
1036
1037 self.state.builder.patch_jump_here(jump_on_false_condition);
1038
1039 Ok(())
1040 }
1041
1042 fn gen_location_argument(
1043 &mut self,
1044 argument: &SingleLocationExpression,
1045 ctx: &Context,
1046 comment: &str,
1047 ) -> Result<(), Error> {
1048 let region = self.gen_lvalue_address(argument)?;
1049
1050 self.state
1051 .builder
1052 .add_mov(ctx.addr(), region.addr, region.size, comment);
1053
1054 Ok(())
1055 }
1056
1057 fn gen_variable_assignment(
1058 &mut self,
1059 variable: &VariableRef,
1060 mut_or_immutable_expression: &MutOrImmutableExpression,
1061 ctx: &Context,
1062 ) -> Result<(), Error> {
1063 let target_relative_frame_pointer = self
1064 .variable_offsets
1065 .get(&variable.unique_id_within_function)
1066 .unwrap_or_else(|| panic!("{}", variable.assigned_name));
1067
1068 let init_ctx =
1069 ctx.with_target(*target_relative_frame_pointer, "variable assignment target");
1070
1071 self.gen_mut_or_immute(mut_or_immutable_expression, &init_ctx)
1072 }
1073
1074 fn gen_assignment(
1075 &mut self,
1076 lhs: &SingleMutLocationExpression,
1077 rhs: &Expression,
1078 ) -> Result<(), Error> {
1079 let lhs_addr = self.gen_lvalue_address(&lhs.0)?;
1080 let access = self.gen_expression_for_access(rhs)?;
1081
1082 self.state
1083 .builder
1084 .add_mov(lhs_addr.addr, access.addr, access.size, "assignment");
1085
1086 Ok(())
1087 }
1088
1089 fn gen_variable_definition(
1090 &mut self,
1091 variable: &VariableRef,
1092 mut_or_immutable_expression: &MutOrImmutableExpression,
1093 ctx: &Context,
1094 ) -> Result<(), Error> {
1095 self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx)
1096 }
1097
1098 fn gen_variable_reassignment(
1099 &mut self,
1100 variable: &VariableRef,
1101 mut_or_immutable_expression: &Box<MutOrImmutableExpression>,
1102 ctx: &Context,
1103 ) -> Result<(), Error> {
1104 self.gen_variable_assignment(variable, mut_or_immutable_expression, ctx)
1105 }
1106
1107 fn copy_back_mutable_arguments(
1108 &mut self,
1109 signature: &Signature,
1110 maybe_self: Option<FrameMemoryRegion>,
1111 arguments: &Vec<ArgumentExpressionOrLocation>,
1112 ) -> Result<(), Error> {
1113 let arguments_memory_region = self.infinite_above_frame_size();
1114 let mut arguments_allocator = ScopeAllocator::new(arguments_memory_region);
1115
1116 let _argument_addr = Self::reserve(&signature.return_type, &mut arguments_allocator);
1117
1118 let mut parameters = signature.parameters.clone();
1119 if let Some(found_self) = maybe_self {
1120 let source_region =
1121 Self::reserve(¶meters[0].resolved_type, &mut arguments_allocator);
1122 self.state.builder.add_mov(
1123 found_self.addr,
1124 source_region.addr,
1125 source_region.size,
1126 "copy back to <self>",
1127 );
1128 parameters.remove(0);
1129 }
1130 for (parameter, argument) in parameters.iter().zip(arguments) {
1131 let source_region = Self::reserve(¶meter.resolved_type, &mut arguments_allocator);
1132 if !parameter.is_mutable {
1133 continue;
1134 }
1135
1136 if let ArgumentExpressionOrLocation::Location(found_location) = argument {
1137 let argument_target = self.gen_lvalue_address(found_location)?;
1138 self.state.builder.add_mov(
1139 argument_target.addr,
1140 source_region.addr,
1141 source_region.size,
1142 &format!(
1143 "copy back mutable argument {}",
1144 found_location.starting_variable.assigned_name
1145 ),
1146 );
1147 } else {
1148 panic!("internal error. argument is mut but not a location")
1149 }
1150 }
1151 Ok(())
1152 }
1153 fn gen_arguments(
1154 &mut self,
1155 signature: &Signature,
1156 self_region: Option<FrameMemoryRegion>,
1157 arguments: &Vec<ArgumentExpressionOrLocation>,
1158 ) -> Result<FrameMemoryRegion, Error> {
1159 self.argument_allocator.reset();
1160 let argument_addr = Self::reserve(&signature.return_type, &mut self.argument_allocator);
1162 assert_eq!(argument_addr.addr.0, self.frame_size.0);
1163
1164 let mut argument_targets = Vec::new();
1165 let mut argument_comments = Vec::new();
1166
1167 for (index, type_for_parameter) in signature.parameters.iter().enumerate() {
1169 let argument_target = Self::reserve(
1170 &type_for_parameter.resolved_type,
1171 &mut self.argument_allocator,
1172 );
1173 let arg_ctx = Context::new(argument_target);
1174 argument_targets.push(arg_ctx);
1175 argument_comments.push(format!("argument {}", type_for_parameter.name));
1176 }
1177
1178 if let Some(push_self) = self_region {
1179 self.state.builder.add_mov(
1180 argument_targets[0].addr(),
1181 push_self.addr,
1182 push_self.size,
1183 "<self>",
1184 );
1185 argument_targets.remove(0);
1186 }
1187
1188 for ((argument_target_ctx, argument_expr_or_loc), argument_comment) in argument_targets
1189 .iter()
1190 .zip(arguments)
1191 .zip(argument_comments)
1192 {
1193 let debug_addr = argument_target_ctx.target().addr();
1194 self.gen_argument(
1195 argument_expr_or_loc,
1196 &argument_target_ctx,
1197 &argument_comment,
1198 )?;
1199 }
1200
1201 let memory_size = argument_targets
1202 .last()
1203 .map_or(MemorySize(0), |last_target| {
1204 MemorySize(
1205 last_target.addr().add(last_target.target_size()).0
1206 - argument_targets[0].addr().0,
1207 )
1208 });
1209
1210 let start_addr = argument_targets
1211 .first()
1212 .map_or(FrameMemoryAddress(0), |first| first.addr());
1213
1214 Ok(FrameMemoryRegion {
1215 addr: start_addr,
1216 size: memory_size,
1217 })
1218 }
1219
1220 #[allow(clippy::too_many_lines)]
1221 fn gen_postfix_chain(
1222 &mut self,
1223 start_expression: &Expression,
1224 chain: &[Postfix],
1225 ctx: &Context,
1226 ) -> Result<(), Error> {
1227 if let ExpressionKind::InternalFunctionAccess(internal_fn) = &start_expression.kind {
1228 if chain.len() == 1 {
1229 if let PostfixKind::FunctionCall(args) = &chain[0].kind {
1230 if let Some(intrinsic_fn) = single_intrinsic_fn(&internal_fn.body) {
1231 self.gen_single_intrinsic_call(intrinsic_fn, None, args, ctx)?;
1232 } else {
1233 self.gen_arguments(&internal_fn.signature.signature, None, args)?;
1234 self.state
1235 .add_call(internal_fn, &format!("frame size: {}", self.frame_size)); let (return_size, _alignment) =
1237 type_size_and_alignment(&internal_fn.signature.signature.return_type);
1238 if return_size.0 != 0 {
1239 self.state.builder.add_mov(
1240 ctx.addr(),
1241 self.infinite_above_frame_size().addr,
1242 return_size,
1243 "copy the ret value to destination",
1244 );
1245 }
1246 self.copy_back_mutable_arguments(
1247 &internal_fn.signature.signature,
1248 None,
1249 args,
1250 )?;
1251 }
1252
1253 return Ok(());
1254 }
1255 }
1256 }
1257
1258 if let ExpressionKind::ExternalFunctionAccess(external_fn) = &start_expression.kind {
1259 if chain.len() == 1 {
1260 if let PostfixKind::FunctionCall(args) = &chain[0].kind {
1261 let total_region = self.gen_arguments(&external_fn.signature, None, args)?;
1262 self.state.builder.add_host_call(
1263 external_fn.id as u16,
1264 total_region.size,
1265 &format!("call external '{}'", external_fn.assigned_name),
1266 );
1267 let (return_size, _alignment) =
1268 type_size_and_alignment(&external_fn.signature.return_type);
1269 if return_size.0 != 0 {
1270 self.state.builder.add_mov(
1271 ctx.addr(),
1272 self.infinite_above_frame_size().addr,
1273 return_size,
1274 "copy the ret value to destination",
1275 );
1276 }
1277
1278 return Ok(());
1279 }
1280 }
1281 }
1282
1283 let mut start_source = self.gen_expression_for_access(start_expression)?;
1284
1285 for element in chain {
1286 match &element.kind {
1287 PostfixKind::StructField(anonymous_struct, field_index) => {
1288 let (memory_offset, memory_size, _max_alignment) =
1289 Self::get_struct_field_offset(
1290 &anonymous_struct.field_name_sorted_fields,
1291 *field_index,
1292 );
1293 start_source = FrameMemoryRegion::new(
1294 start_source.addr.advance(memory_offset),
1295 memory_size,
1296 );
1297 }
1298 PostfixKind::MemberCall(function_to_call, arguments) => {
1299 match &**function_to_call {
1300 Function::Internal(internal_fn) => {
1301 if let Some(intrinsic_fn) = single_intrinsic_fn(&internal_fn.body) {
1302 self.gen_single_intrinsic_call(
1303 intrinsic_fn,
1304 Some(start_source),
1305 arguments,
1306 ctx,
1307 )?;
1308 } else {
1309 self.gen_arguments(
1310 &internal_fn.signature.signature,
1311 Some(start_source),
1312 arguments,
1313 )?;
1314 self.state.add_call(
1315 internal_fn,
1316 &format!("frame size: {}", self.frame_size),
1317 ); let (return_size, _alignment) = type_size_and_alignment(
1320 &internal_fn.signature.signature.return_type,
1321 );
1322 if return_size.0 != 0 {
1323 self.state.builder.add_mov(
1324 ctx.addr(),
1325 self.infinite_above_frame_size().addr,
1326 return_size,
1327 "copy the return value to destination",
1328 );
1329 }
1330
1331 self.copy_back_mutable_arguments(
1332 &internal_fn.signature.signature,
1333 Some(start_source),
1334 arguments,
1335 )?;
1336 }
1337 }
1338 Function::External(external_fn) => {
1339 }
1341 }
1342 }
1343 PostfixKind::FunctionCall(arguments) => {
1344 }
1347 PostfixKind::OptionalChainingOperator => todo!(),
1348 PostfixKind::NoneCoalescingOperator(_) => todo!(),
1349 }
1350 }
1351
1352 Ok(())
1353 }
1354
1355 fn gen_tuple(&mut self, expressions: &[Expression], ctx: &Context) -> Result<(), Error> {
1356 let mut scope = ScopeAllocator::new(ctx.target());
1357
1358 for expr in expressions {
1359 let (memory_size, alignment) = type_size_and_alignment(&expr.ty);
1360 let start_addr = scope.allocate(memory_size, alignment);
1361 let element_region = FrameMemoryRegion::new(start_addr, memory_size);
1362 let element_ctx = Context::new(element_region);
1363 self.gen_expression(expr, &element_ctx)?;
1364 }
1365
1366 Ok(())
1367 }
1368
1369 fn get_struct_field_offset(
1370 fields: &SeqMap<String, StructTypeField>,
1371 index_to_find: usize,
1372 ) -> (MemoryOffset, MemorySize, MemoryAlignment) {
1373 let mut offset = 0;
1374
1375 for (index, (_name, field)) in fields.iter().enumerate() {
1376 let (struct_field_size, struct_field_align) =
1377 type_size_and_alignment(&field.field_type);
1378 if index == index_to_find {
1379 return (MemoryOffset(offset), struct_field_size, struct_field_align);
1380 }
1381
1382 offset += struct_field_size.0;
1383 }
1384
1385 panic!("field not found");
1386 }
1387
1388 fn gen_anonymous_struct(
1389 &mut self,
1390 anon_struct_type: &AnonymousStructType,
1391 source_order_expressions: &Vec<(usize, Expression)>,
1392 base_context: &Context,
1393 ) -> Result<(), Error> {
1394 for (field_index, expression) in source_order_expressions {
1395 let (field_memory_offset, field_size, _field_alignment) = Self::get_struct_field_offset(
1396 &anon_struct_type.field_name_sorted_fields,
1397 *field_index,
1398 );
1399 let field_ctx = base_context.with_offset(field_memory_offset, field_size);
1400 self.gen_expression(expression, &field_ctx)?;
1401 }
1402
1403 Ok(())
1404 }
1405
1406 fn gen_literal(&mut self, literal: &Literal, ctx: &Context) -> Result<(), Error> {
1407 match literal {
1408 Literal::IntLiteral(int) => {
1409 self.state.builder.add_ld32(ctx.addr(), *int, "int literal");
1410 }
1411 Literal::FloatLiteral(fixed_point) => {
1412 self.state
1413 .builder
1414 .add_ld32(ctx.addr(), fixed_point.inner(), "float literal");
1415 }
1416 Literal::NoneLiteral => {
1417 self.state.builder.add_ld8(ctx.addr(), 0, "none literal");
1418 }
1419 Literal::BoolLiteral(truthy) => {
1420 self.state
1421 .builder
1422 .add_ld8(ctx.addr(), u8::from(*truthy), "bool literal");
1423 }
1424
1425 Literal::EnumVariantLiteral(enum_type, a, b) => {
1426 self.state.builder.add_ld8(
1427 ctx.addr(),
1428 a.common().container_index,
1429 &format!("enum variant {} tag", a.common().assigned_name),
1430 );
1431
1432 let starting_offset = MemoryOffset(1);
1433
1434 let (data_size, data_alignment) = match a {
1435 EnumVariantType::Struct(enum_variant_struct) => {
1436 layout_struct(&enum_variant_struct.anon_struct)
1437 }
1438 EnumVariantType::Tuple(tuple_type) => layout_tuple(&tuple_type.fields_in_order),
1439 EnumVariantType::Nothing(_) => (MemorySize(0), MemoryAlignment::U8),
1440 };
1441
1442 let skip_octets: usize = data_alignment.into();
1443 let skip = MemorySize(skip_octets as u16);
1444 let inner_addr = ctx.addr().add(skip);
1445 let region = FrameMemoryRegion::new(inner_addr, data_size);
1446 let inner_ctx = Context::new(region);
1447
1448 match b {
1450 EnumLiteralData::Nothing => {}
1451 EnumLiteralData::Tuple(expressions) => {
1452 self.gen_tuple(expressions, &inner_ctx)?;
1453 }
1454 EnumLiteralData::Struct(sorted_expressions) => {
1455 if let EnumVariantType::Struct(variant_struct_type) = a {
1456 self.gen_anonymous_struct(
1457 &variant_struct_type.anon_struct,
1458 sorted_expressions,
1459 &inner_ctx,
1460 )?;
1461 }
1462 }
1463 }
1464 }
1465 Literal::TupleLiteral(_tuple_type, expressions) => self.gen_tuple(expressions, ctx)?,
1466 Literal::StringLiteral(str) => {
1467 self.gen_string_literal(str, ctx);
1468 }
1469 Literal::Slice(ty, expressions) => {
1470 todo!()
1472 }
1473 Literal::SlicePair(ty, expression_pairs) => {
1474 todo!()
1475 }
1476 }
1477
1478 Ok(())
1479 }
1480
1481 fn gen_string_literal(&mut self, string: &str, ctx: &Context) {
1482 let string_bytes = string.as_bytes();
1483 let string_byte_count = string_bytes.len();
1484
1485 let data_ptr = self
1486 .state
1487 .constants
1488 .allocate(string_bytes, MemoryAlignment::U8);
1489
1490 let mem_size = MemorySize(string_byte_count as u16);
1491
1492 self.state.builder.add_string_from_constant_slice(
1493 ctx.addr(),
1494 data_ptr,
1495 mem_size,
1496 "create string",
1497 );
1498 }
1500
1501 fn gen_option_expression(
1530 &mut self,
1531 maybe_option: Option<&Expression>,
1532 ctx: &Context,
1533 ) -> Result<(), Error> {
1534 if let Some(found_value) = maybe_option {
1535 self.state.builder.add_ld8(ctx.addr(), 1, "option Some tag"); let (inner_size, inner_alignment) = type_size_and_alignment(&found_value.ty);
1537 let one_offset_ctx = ctx.with_offset(inner_alignment.into(), inner_size);
1538
1539 self.gen_expression(found_value, &one_offset_ctx)?; } else {
1541 self.state.builder.add_ld8(ctx.addr(), 0, "option None tag"); }
1544
1545 Ok(())
1546 }
1547
1548 fn gen_for_loop_vec(
1549 &mut self,
1550 for_pattern: &ForPattern,
1551 collection_expr: &MutOrImmutableExpression,
1552 ) -> Result<(InstructionPosition, PatchPosition), Error> {
1553 let collection_region = self.gen_for_access_or_location(collection_expr)?;
1554
1555 let temp_iterator_region = self
1556 .temp_allocator
1557 .allocate(MemorySize(VEC_ITERATOR_SIZE), VEC_ITERATOR_ALIGNMENT);
1558 self.state.builder.add_vec_iter_init(
1559 temp_iterator_region,
1560 FrameMemoryAddressIndirectPointer(collection_region.addr),
1561 "initialize vec iterator",
1562 );
1563
1564 let loop_ip = self.state.builder.position();
1565
1566 let placeholder_position = match for_pattern {
1567 ForPattern::Single(variable) => {
1568 let target_variable = self
1569 .variable_offsets
1570 .get(&variable.unique_id_within_function)
1571 .unwrap();
1572 self.state.builder.add_vec_iter_next_placeholder(
1573 temp_iterator_region,
1574 target_variable.addr,
1575 "move to next or jump over",
1576 )
1577 }
1578 ForPattern::Pair(variable_a, variable_b) => {
1579 let target_variable_a = self
1580 .variable_offsets
1581 .get(&variable_a.unique_id_within_function)
1582 .unwrap();
1583 let target_variable_b = self
1584 .variable_offsets
1585 .get(&variable_b.unique_id_within_function)
1586 .unwrap();
1587 self.state.builder.add_vec_iter_next_pair_placeholder(
1588 temp_iterator_region,
1589 target_variable_a.addr,
1590 target_variable_b.addr,
1591 "move to next or jump over",
1592 )
1593 }
1594 };
1595
1596 Ok((loop_ip, placeholder_position))
1597 }
1598
1599 fn gen_for_loop_map(
1600 &mut self,
1601 for_pattern: &ForPattern,
1602 ) -> Result<(InstructionPosition, PatchPosition), Error> {
1603 self.state.builder.add_map_iter_init(
1604 FrameMemoryAddress(0x80),
1605 FrameMemoryAddressIndirectPointer(FrameMemoryAddress(0xffff)),
1606 "initialize map iterator",
1607 );
1608
1609 let jump_ip = self.state.builder.position();
1610
1611 match for_pattern {
1612 ForPattern::Single(_) => {
1613 self.state.builder.add_map_iter_next(
1614 FrameMemoryAddress(0x80),
1615 FrameMemoryAddress(0x16),
1616 InstructionPosition(256),
1617 "move to next or jump over",
1618 );
1619 }
1620 ForPattern::Pair(_, _) => {
1621 self.state.builder.add_map_iter_next_pair(
1622 FrameMemoryAddress(0x80),
1623 FrameMemoryAddress(0x16),
1624 FrameMemoryAddress(0x16),
1625 InstructionPosition(256),
1626 "move to next or jump over",
1627 );
1628 }
1629 }
1630
1631 Ok((jump_ip, PatchPosition(InstructionPosition(0))))
1632 }
1633
1634 fn gen_for_loop(
1635 &mut self,
1636 for_pattern: &ForPattern,
1637 iterable: &Iterable,
1638 closure: &Box<Expression>,
1639 ) -> Result<(), Error> {
1640 let collection_type = &iterable.resolved_expression.expression_or_location.ty();
1647 let (jump_ip, placeholder_position) = match collection_type {
1648 Type::String => {
1649 todo!();
1650 }
1651 Type::NamedStruct(_vec) => {
1652 if let Some(found_info) = is_vec(collection_type) {
1653 self.gen_for_loop_vec(for_pattern, &iterable.resolved_expression)?
1654 } else if let Some(found_info) = is_map(collection_type) {
1655 self.gen_for_loop_map(for_pattern)?
1656 } else {
1657 return Err(self.create_err(
1658 ErrorKind::NotAnIterableCollection,
1659 iterable.resolved_expression.node(),
1660 ));
1661 }
1662 }
1663 _ => {
1664 return Err(self.create_err(
1665 ErrorKind::IllegalCollection,
1666 iterable.resolved_expression.node(),
1667 ));
1668 }
1669 };
1670
1671 match for_pattern {
1672 ForPattern::Single(value_variable) => {}
1673 ForPattern::Pair(key_variable, value_variable) => {}
1674 }
1675
1676 let unit_expr = self.temp_space_for_type(&Type::Unit, "for loop body");
1677 self.gen_expression(closure, &unit_expr)?;
1678
1679 self.state
1680 .builder
1681 .add_jmp(jump_ip, "jump to next iteration");
1682 self.state.builder.patch_jump_here(placeholder_position);
1685
1686 Ok(())
1687 }
1688
1689 fn gen_for_loop_for_vec(
1690 &mut self,
1691 element_type: &Type,
1692 vector_expr: Expression,
1693 ctx: &mut Context,
1694 ) -> Result<GeneratedExpressionResult, Error> {
1695 let vector_ctx = self.temp_space_for_type(&vector_expr.ty, "vector space");
1697 self.gen_expression(&vector_expr, &vector_ctx)
1698
1699 }
1783
1784 fn gen_block(&mut self, expressions: &[Expression], ctx: &Context) -> Result<(), Error> {
1785 if let Some((last, others)) = expressions.split_last() {
1786 for expr in others {
1787 let temp_context = self.temp_space_for_type(&Type::Unit, "block target");
1788 self.gen_expression(expr, &temp_context)?;
1789 }
1790 self.gen_expression(last, ctx)?;
1791 }
1792
1793 Ok(())
1794 }
1795
1796 fn get_variable_region(&self, variable: &VariableRef) -> (FrameMemoryRegion, MemoryAlignment) {
1797 let frame_address = self
1798 .variable_offsets
1799 .get(&variable.unique_id_within_function)
1800 .unwrap();
1801 let (_size, align) = type_size_and_alignment(&variable.resolved_type);
1802
1803 (*frame_address, align)
1804 }
1805
1806 fn gen_variable_access(&mut self, variable: &VariableRef, ctx: &Context) -> Result<(), Error> {
1807 let (region, alignment) = self.get_variable_region(variable);
1808 self.state.builder.add_mov(
1809 ctx.addr(),
1810 region.addr,
1811 region.size,
1812 &format!(
1813 "variable access '{}' ({})",
1814 variable.assigned_name,
1815 ctx.comment()
1816 ),
1817 );
1818
1819 Ok(())
1820 }
1821
1822 fn referenced_or_not_type(ty: &Type) -> Type {
1823 if let Type::MutableReference(inner_type) = ty {
1824 *inner_type.clone()
1825 } else {
1826 ty.clone()
1827 }
1828 }
1829
1830 fn compound_assignment(
1831 &mut self,
1832 target_location: &SingleMutLocationExpression,
1833 op: &CompoundOperatorKind,
1834 source: &Expression,
1835 ctx: &Context,
1836 ) -> Result<(), Error> {
1837 let target_location = self.gen_lvalue_address(&target_location.0)?;
1838
1839 let source_info = self.gen_expression_for_access(source)?;
1840
1841 let type_to_consider = Self::referenced_or_not_type(&source.ty);
1842
1843 match &type_to_consider {
1844 Type::Int => {
1845 self.gen_compound_assignment_i32(&target_location, op, &source_info);
1846 }
1847 Type::Float => {
1848 self.gen_compound_assignment_f32(&target_location, op, &source_info);
1849 }
1850 Type::String => todo!(),
1851 _ => return Err(self.create_err(ErrorKind::IllegalCompoundAssignment, &source.node)),
1852 }
1853
1854 Ok(())
1855 }
1856
1857 fn gen_compound_assignment_i32(
1858 &mut self,
1859 target: &FrameMemoryRegion,
1860 op: &CompoundOperatorKind,
1861 source_ctx: &FrameMemoryRegion,
1862 ) {
1863 match op {
1864 CompoundOperatorKind::Add => {
1865 self.state.builder.add_add_i32(
1866 target.addr(),
1867 target.addr(),
1868 source_ctx.addr(),
1869 "+= (i32)",
1870 );
1871 }
1872 CompoundOperatorKind::Sub => todo!(),
1873 CompoundOperatorKind::Mul => todo!(),
1874 CompoundOperatorKind::Div => todo!(),
1875 CompoundOperatorKind::Modulo => todo!(),
1876 }
1877 }
1878
1879 fn gen_compound_assignment_f32(
1880 &mut self,
1881 target: &FrameMemoryRegion,
1882 op: &CompoundOperatorKind,
1883 source_ctx: &FrameMemoryRegion,
1884 ) {
1885 match op {
1886 CompoundOperatorKind::Add => {
1887 self.state.builder.add_add_f32(
1888 target.addr(),
1889 target.addr(),
1890 source_ctx.addr(),
1891 "+= (f32)",
1892 );
1893 }
1894 CompoundOperatorKind::Sub => todo!(),
1895 CompoundOperatorKind::Mul => todo!(),
1896 CompoundOperatorKind::Div => todo!(),
1897 CompoundOperatorKind::Modulo => todo!(),
1898 }
1899 }
1900
1901 fn internal_function_access(
1902 &mut self,
1903 internal: &InternalFunctionDefinitionRef,
1904 ctx: &Context,
1905 ) -> Result<(), Error> {
1906 self.state.builder.add_ld_u16(
1907 ctx.addr(),
1908 internal.program_unique_id,
1909 &format!("function access '{}'", internal.assigned_name),
1910 );
1911 Ok(())
1912 }
1913
1914 fn infinite_above_frame_size(&self) -> FrameMemoryRegion {
1915 FrameMemoryRegion::new(FrameMemoryAddress(self.frame_size.0), MemorySize(1024))
1916 }
1917
1918 fn gen_struct_literal(
1919 &mut self,
1920 struct_literal: &StructInstantiation,
1921 ctx: &Context,
1922 ) -> Result<(), Error> {
1923 self.gen_struct_literal_helper(
1924 &struct_literal.struct_type_ref.anon_struct_type,
1925 &struct_literal.source_order_expressions,
1926 ctx,
1927 )
1928 }
1929
1930 fn gen_anonymous_struct_literal(
1931 &mut self,
1932 anon_struct_literal: &AnonymousStructLiteral,
1933 ctx: &Context,
1934 ) -> Result<(), Error> {
1935 self.gen_struct_literal_helper(
1936 &anon_struct_literal.anonymous_struct_type,
1937 &anon_struct_literal.source_order_expressions,
1938 ctx,
1939 )
1940 }
1941
1942 fn gen_struct_literal_helper(
1943 &mut self,
1944 struct_type_ref: &AnonymousStructType,
1945 source_order_expressions: &Vec<(usize, Expression)>,
1946 ctx: &Context,
1947 ) -> Result<(), Error> {
1948 let struct_type = Type::AnonymousStruct(struct_type_ref.clone());
1949 let (whole_struct_size, whole_struct_alignment) = type_size_and_alignment(&struct_type);
1950 if ctx.target_size().0 != whole_struct_size.0 {
1951 info!("problem");
1952 }
1953 assert_eq!(ctx.target_size().0, whole_struct_size.0);
1954
1955 for (field_index, expression) in source_order_expressions {
1956 let (field_offset, field_size, field_alignment) =
1957 struct_field_offset(*field_index, struct_type_ref);
1958 let new_address = ctx.addr().advance(field_offset);
1960 let field_ctx = Context::new(FrameMemoryRegion::new(new_address, field_size));
1961 self.gen_expression(expression, &field_ctx)?;
1962 }
1963
1964 Ok(())
1965 }
1966
1967 fn gen_slice_literal(
1968 &mut self,
1969 ty: &Type,
1970 expressions: &Vec<Expression>,
1971 ) -> Result<FrameMemoryRegion, Error> {
1972 let (element_size, element_alignment) = type_size_and_alignment(ty);
1973 let element_count = expressions.len() as u16;
1974 let total_slice_size = MemorySize(element_size.0 * element_count);
1975
1976 let start_frame_address_to_transfer = self
1977 .temp_allocator
1978 .allocate(total_slice_size, element_alignment);
1979 for (index, expr) in expressions.iter().enumerate() {
1980 let memory_offset = MemoryOffset((index as u16) * element_size.0);
1981 let region = FrameMemoryRegion::new(
1982 start_frame_address_to_transfer.advance(memory_offset),
1983 element_size,
1984 );
1985 let element_ctx = Context::new(region);
1986 self.gen_expression(expr, &element_ctx)?;
1987 }
1988
1989 Ok(FrameMemoryRegion::new(
1990 start_frame_address_to_transfer,
1991 total_slice_size,
1992 ))
1993 }
1994
1995 fn gen_slice_pair_literal(
1996 &mut self,
1997 slice_type: &Type,
1998 expressions: &[(Expression, Expression)],
1999 ) -> SlicePairInfo {
2000 let Type::SlicePair(key_type, value_type) = slice_type else {
2001 panic!("should have been slice pair type")
2002 };
2003
2004 let constructed_tuple = Type::Tuple(vec![*key_type.clone(), *value_type.clone()]);
2005
2006 let (key_size, key_alignment) = type_size_and_alignment(key_type);
2007 let (value_size, value_alignment) = type_size_and_alignment(value_type);
2008 let (element_size, tuple_alignment) = type_size_and_alignment(&constructed_tuple);
2009 let element_count = expressions.len() as u16;
2010 let total_slice_size = MemorySize(element_size.0 * element_count);
2011
2012 let start_frame_address_to_transfer = self
2013 .temp_allocator
2014 .allocate(total_slice_size, tuple_alignment);
2015
2016 for (index, (key_expr, value_expr)) in expressions.iter().enumerate() {
2017 let memory_offset = MemoryOffset((index as u16) * element_size.0);
2018 let key_region = FrameMemoryRegion::new(
2019 start_frame_address_to_transfer.advance(memory_offset),
2020 element_size,
2021 );
2022 let key_ctx = Context::new(key_region);
2023 self.gen_expression(key_expr, &key_ctx);
2024
2025 let value_region = FrameMemoryRegion::new(
2026 start_frame_address_to_transfer.advance(memory_offset.add(key_size, key_alignment)),
2027 value_size,
2028 );
2029 let value_ctx = Context::new(value_region);
2030 self.gen_expression(value_expr, &value_ctx);
2031 }
2032
2033 SlicePairInfo {
2034 addr: TempFrameMemoryAddress(start_frame_address_to_transfer),
2035 key_size,
2036 value_size,
2037 element_count: CountU16(element_count),
2038 element_size,
2039 }
2040 }
2041
2042 fn gen_slice_helper(
2043 &mut self,
2044 start_temp_frame_address_to_transfer: FrameMemoryAddress,
2045 element_count: u16,
2046 element_size: MemorySize,
2047 ctx: &Context,
2048 ) {
2049 let total_slice_size = MemorySize(element_size.0 * element_count);
2050 let vec_len_addr = ctx.addr().advance(MemoryOffset(0));
2051 self.state
2052 .builder
2053 .add_ld_u16(vec_len_addr, element_count, "slice len");
2054
2055 let vec_capacity_addr = ctx.addr().advance(MemoryOffset(2));
2056 self.state
2057 .builder
2058 .add_ld_u16(vec_capacity_addr, element_count, "slice capacity");
2059
2060 let vec_element_size_addr = ctx.addr().advance(MemoryOffset(4));
2061 self.state
2062 .builder
2063 .add_ld_u16(vec_element_size_addr, element_size.0, "slice element size");
2064
2065 }
2081
2082 fn gen_intrinsic_call_ex(
2083 &mut self,
2084 intrinsic_fn: &IntrinsicFunction,
2085 arguments: &Vec<ArgumentExpressionOrLocation>,
2086 ctx: &Context,
2087 ) -> Result<(), Error> {
2088 match intrinsic_fn {
2091 IntrinsicFunction::FloatRound => todo!(),
2093 IntrinsicFunction::FloatFloor => todo!(),
2094 IntrinsicFunction::FloatSqrt => todo!(),
2095 IntrinsicFunction::FloatSign => todo!(),
2096 IntrinsicFunction::FloatAbs => todo!(),
2097 IntrinsicFunction::FloatRnd => todo!(),
2098 IntrinsicFunction::FloatCos => todo!(),
2099 IntrinsicFunction::FloatSin => todo!(),
2100 IntrinsicFunction::FloatAcos => todo!(),
2101 IntrinsicFunction::FloatAsin => todo!(),
2102 IntrinsicFunction::FloatAtan2 => todo!(),
2103 IntrinsicFunction::FloatMin => todo!(),
2104 IntrinsicFunction::FloatMax => todo!(),
2105 IntrinsicFunction::FloatClamp => todo!(),
2106
2107 IntrinsicFunction::IntAbs => todo!(),
2109 IntrinsicFunction::IntRnd => todo!(),
2110 IntrinsicFunction::IntMax => todo!(),
2111 IntrinsicFunction::IntMin => todo!(),
2112 IntrinsicFunction::IntClamp => todo!(),
2113 IntrinsicFunction::IntToFloat => todo!(),
2114
2115 IntrinsicFunction::StringLen => todo!(),
2117
2118 IntrinsicFunction::VecFromSlice => self.gen_intrinsic_vec_from_slice(arguments, ctx),
2120 IntrinsicFunction::VecPush => todo!(),
2121 IntrinsicFunction::VecPop => todo!(),
2122 IntrinsicFunction::VecFor => todo!(),
2123 IntrinsicFunction::VecWhile => todo!(),
2124 IntrinsicFunction::VecFindMap => todo!(),
2125 IntrinsicFunction::VecRemoveIndex => todo!(),
2126 IntrinsicFunction::VecRemoveIndexGetValue => todo!(),
2127 IntrinsicFunction::VecClear => todo!(),
2128 IntrinsicFunction::VecCreate => {
2129 self.gen_intrinsic_vec_create(arguments);
2130 Ok(())
2131 }
2132 IntrinsicFunction::VecSubscript => todo!(),
2133 IntrinsicFunction::VecSubscriptMut => todo!(),
2134 IntrinsicFunction::VecSubscriptRange => todo!(),
2135 IntrinsicFunction::VecIter => todo!(), IntrinsicFunction::VecIterMut => todo!(), IntrinsicFunction::VecLen => todo!(),
2138 IntrinsicFunction::VecIsEmpty => todo!(),
2139 IntrinsicFunction::VecSelfPush => todo!(),
2140 IntrinsicFunction::VecSelfExtend => todo!(),
2141 IntrinsicFunction::VecFold => todo!(),
2142 IntrinsicFunction::VecGet => todo!(),
2143
2144 IntrinsicFunction::MapCreate => todo!(),
2146 IntrinsicFunction::MapFromSlicePair => todo!(),
2147 IntrinsicFunction::MapHas => todo!(),
2148 IntrinsicFunction::MapRemove => todo!(),
2149 IntrinsicFunction::MapIter => todo!(),
2150 IntrinsicFunction::MapIterMut => todo!(),
2151 IntrinsicFunction::MapLen => todo!(),
2152 IntrinsicFunction::MapIsEmpty => todo!(),
2153 IntrinsicFunction::MapSubscript => todo!(),
2154 IntrinsicFunction::MapSubscriptSet => todo!(),
2155 IntrinsicFunction::MapSubscriptMut => todo!(),
2156 IntrinsicFunction::MapSubscriptMutCreateIfNeeded => todo!(),
2157
2158 IntrinsicFunction::Map2GetColumn => todo!(),
2159 IntrinsicFunction::Map2GetRow => todo!(),
2160 IntrinsicFunction::Map2Remove => todo!(),
2161 IntrinsicFunction::Map2Has => todo!(),
2162 IntrinsicFunction::Map2Get => todo!(),
2163 IntrinsicFunction::Map2Insert => todo!(),
2164 IntrinsicFunction::Map2Create => todo!(),
2165
2166 IntrinsicFunction::SparseAdd => todo!(),
2168 IntrinsicFunction::SparseNew => todo!(),
2169 IntrinsicFunction::SparseCreate => todo!(),
2170 IntrinsicFunction::SparseFromSlice => todo!(),
2171 IntrinsicFunction::SparseIter => todo!(),
2172 IntrinsicFunction::SparseIterMut => todo!(),
2173 IntrinsicFunction::SparseSubscript => todo!(),
2174 IntrinsicFunction::SparseSubscriptMut => todo!(),
2175 IntrinsicFunction::SparseHas => todo!(),
2176 IntrinsicFunction::SparseRemove => todo!(),
2177
2178 IntrinsicFunction::GridCreate => todo!(),
2180 IntrinsicFunction::GridFromSlice => todo!(),
2181 IntrinsicFunction::GridSet => todo!(),
2182 IntrinsicFunction::GridGet => todo!(),
2183 IntrinsicFunction::GridGetColumn => todo!(),
2184
2185 IntrinsicFunction::Float2Magnitude => todo!(),
2187 IntrinsicFunction::VecAny => todo!(),
2188 IntrinsicFunction::VecAll => todo!(),
2189 IntrinsicFunction::VecMap => todo!(),
2190 IntrinsicFunction::VecFilter => todo!(),
2191 IntrinsicFunction::VecFilterMap => todo!(),
2192 IntrinsicFunction::VecFind => todo!(),
2193 IntrinsicFunction::VecSwap => todo!(),
2194 IntrinsicFunction::VecInsert => todo!(),
2195 IntrinsicFunction::VecFirst => todo!(),
2196 IntrinsicFunction::VecLast => todo!(),
2197 };
2198
2199 Ok(())
2200 }
2201
2202 fn gen_intrinsic_vec_create(&self, arguments: &Vec<ArgumentExpressionOrLocation>) {
2203 for arg in arguments {
2204 info!(?arg, "argument");
2205 }
2206 }
2207
2208 fn gen_intrinsic_vec_from_slice(
2209 &mut self,
2210 arguments: &[ArgumentExpressionOrLocation],
2211 ctx: &Context,
2212 ) -> Result<(), Error> {
2213 if let ArgumentExpressionOrLocation::Expression(found_expr) = &arguments[0] {
2214 let memory = self.gen_expression_for_access(found_expr)?;
2215 self.state.builder.add_vec_from_slice(
2216 ctx.addr(),
2217 memory.addr,
2218 MemorySize(0),
2219 CountU16(0),
2220 "create vec",
2221 );
2222 } else {
2223 panic!("vec_from_slice");
2224 }
2225
2226 Ok(())
2227 }
2228
2229 fn gen_match(&mut self, match_expr: &Match, ctx: &Context) -> Result<(), Error> {
2230 let region_to_match = self.gen_for_access_or_location(&match_expr.expression)?;
2231
2232 let mut jump_to_exit_placeholders = Vec::new();
2233
2234 let arm_len_to_consider = if match_expr.contains_wildcard() {
2235 match_expr.arms.len()
2236 } else {
2237 match_expr.arms.len()
2238 };
2239 for (index, arm) in match_expr.arms.iter().enumerate() {
2240 let is_last = index == arm_len_to_consider - 1;
2241
2242 let maybe_guard = match &arm.pattern {
2244 Pattern::Normal(normal_pattern, maybe_guard) => match normal_pattern {
2245 NormalPattern::PatternList(_) => None,
2246 NormalPattern::EnumPattern(enum_variant, maybe_patterns) => {
2247 self.state.builder.add_eq_u8_immediate(
2248 region_to_match.addr,
2249 enum_variant.common().container_index,
2250 "check for enum variant",
2251 );
2252 maybe_guard.as_ref()
2253 }
2254 NormalPattern::Literal(_) => {
2255 todo!()
2256 }
2257 },
2258 Pattern::Wildcard(_) => {
2259 None
2261 }
2262 };
2263
2264 let did_add_comparison = !matches!(arm.pattern, Pattern::Wildcard(_));
2265
2266 let maybe_skip_added = if did_add_comparison {
2267 Some(
2268 self.state
2269 .builder
2270 .add_jmp_if_not_equal_placeholder("placeholder for enum match"),
2271 )
2272 } else {
2273 None
2274 };
2275
2276 let maybe_guard_skip = if let Some(guard) = maybe_guard {
2277 self.gen_boolean_expression(guard)?;
2278 Some(
2281 self.state
2282 .builder
2283 .add_jmp_if_not_equal_placeholder("placeholder for skip guard"),
2284 )
2285 } else {
2286 None
2287 };
2288
2289 self.gen_expression(&arm.expression, ctx)?;
2290
2291 if !is_last {
2292 let jump_to_exit_placeholder =
2293 self.state.builder.add_jump_placeholder("jump to exit");
2294 jump_to_exit_placeholders.push(jump_to_exit_placeholder);
2295 }
2296
2297 if let Some(skip) = maybe_skip_added {
2298 self.state.builder.patch_jump_here(skip);
2299 }
2300 if let Some(guard_skip) = maybe_guard_skip {
2301 self.state.builder.patch_jump_here(guard_skip);
2302 }
2303 }
2304
2305 for placeholder in jump_to_exit_placeholders {
2306 self.state.builder.patch_jump_here(placeholder);
2307 }
2308
2309 Ok(())
2310 }
2311
2312 fn gen_guard(&mut self, guards: &Vec<Guard>, ctx: &Context) -> Result<(), Error> {
2313 let mut jump_to_exit_placeholders = Vec::new();
2314 for guard in guards {
2315 if let Some(condition) = &guard.condition {
2316 self.gen_boolean_expression(condition); let skip_expression_patch = self
2318 .state
2319 .builder
2320 .add_jmp_if_not_equal_placeholder("guard condition");
2321 self.gen_expression(&guard.result, ctx)?;
2322 let jump_to_exit_placeholder =
2323 self.state.builder.add_jump_placeholder("jump to exit");
2324 jump_to_exit_placeholders.push(jump_to_exit_placeholder);
2325 self.state.builder.patch_jump_here(skip_expression_patch);
2326 } else {
2327 self.gen_expression(&guard.result, ctx)?;
2329 }
2330 }
2331
2332 for placeholder in jump_to_exit_placeholders {
2333 self.state.builder.patch_jump_here(placeholder);
2334 }
2335
2336 Ok(())
2337 }
2338
2339 fn gen_when(
2340 &mut self,
2341 bindings: &Vec<WhenBinding>,
2342 true_expr: &Expression,
2343 maybe_false_expr: Option<&Expression>,
2344 ctx: &Context,
2345 ) -> Result<(), Error> {
2346 let mut all_false_jumps = Vec::new();
2347
2348 for binding in bindings {
2349 let (variable_region, _alignment) = self.get_variable_region(&binding.variable);
2350
2351 let old_variable_region = self.gen_for_access_or_location(&binding.expr)?;
2352
2353 self.state
2354 .builder
2355 .add_tst8(old_variable_region.addr, "check binding");
2356 let patch = self
2357 .state
2358 .builder
2359 .add_jmp_if_not_equal_placeholder("jump if none");
2360 all_false_jumps.push(patch);
2361 }
2362
2363 for binding in bindings {
2365 let (variable_region, alignment) = self.get_variable_region(&binding.variable);
2366
2367 if binding.has_expression() {
2368 let var_ctx = Context::new(variable_region);
2369 self.gen_mut_or_immute(&binding.expr, &var_ctx)?;
2370 } else {
2371 let ArgumentExpressionOrLocation::Expression(variable_access_expression) =
2372 &binding.expr.expression_or_location
2373 else {
2374 panic!("must be expression");
2375 };
2376 let old_variable_region =
2377 self.gen_expression_for_access(variable_access_expression)?;
2378 let alignment_offset: MemoryOffset = alignment.into();
2379 let some_value_region = FrameMemoryRegion::new(
2380 old_variable_region.addr.advance(alignment_offset),
2381 MemorySize(variable_region.size.0),
2382 );
2383 self.state.builder.add_movlp(
2384 variable_region.addr,
2385 some_value_region.addr,
2386 some_value_region.size,
2387 "move from Some to value",
2388 );
2389 }
2390 }
2391
2392 self.gen_expression(true_expr, ctx)?;
2393 let maybe_jump_over_false = if let Some(_else_expr) = maybe_false_expr {
2394 Some(
2395 self.state
2396 .builder
2397 .add_jump_placeholder("jump over false section"),
2398 )
2399 } else {
2400 None
2401 };
2402
2403 for false_jump_patch in all_false_jumps {
2404 self.state.builder.patch_jump_here(false_jump_patch);
2405 }
2406
2407 if let Some(else_expr) = maybe_false_expr {
2408 self.gen_expression(else_expr, ctx);
2409 self.state
2410 .builder
2411 .patch_jump_here(maybe_jump_over_false.unwrap());
2412 }
2413
2414 Ok(())
2415 }
2416
2417 fn create_err(&mut self, kind: ErrorKind, node: &Node) -> Error {
2418 error!(?kind, "encountered error");
2419 Error {
2420 kind,
2421 node: node.clone(),
2422 }
2423 }
2424
2425 fn gen_tuple_destructuring(
2426 &mut self,
2427 target_variables: &Vec<VariableRef>,
2428 tuple_type: &Vec<Type>,
2429 source_tuple_expression: &Expression,
2430 ) -> Result<(), Error> {
2431 let source_region = self.gen_expression_for_access(source_tuple_expression)?;
2432
2433 let (total_size, _max_alignment, element_offsets) = layout_tuple_elements(tuple_type);
2434 assert_eq!(total_size.0, source_region.size.0);
2435
2436 for (target_variable, (element_offset, element_size)) in
2437 target_variables.iter().zip(element_offsets)
2438 {
2439 if target_variable.is_unused {
2440 } else {
2441 let (target_region, _variable_alignment) =
2442 self.get_variable_region(target_variable);
2443 assert_eq!(target_region.size.0, element_size.0);
2444
2445 let source_element_region = FrameMemoryRegion::new(
2446 source_region.addr.advance(element_offset),
2447 element_size,
2448 );
2449 self.state.builder.add_mov(
2450 target_region.addr,
2451 source_element_region.addr,
2452 source_element_region.size,
2453 &format!(
2454 "destructuring to variable {}",
2455 target_variable.assigned_name
2456 ),
2457 );
2458 }
2459 }
2460
2461 Ok(())
2462 }
2463
2464 fn gen_constant_access(
2465 &mut self,
2466 constant_reference: &ConstantRef,
2467 ctx: &Context,
2468 ) -> Result<(), Error> {
2469 let constant_region = self
2470 .state
2471 .constant_offsets
2472 .get(&constant_reference.id)
2473 .unwrap();
2474 assert_eq!(constant_region.size.0, ctx.target_size().0);
2475
2476 self.state.builder.add_ld_constant(
2477 ctx.addr(),
2478 constant_region.addr,
2479 constant_region.size,
2480 &format!("load constant '{}'", constant_reference.assigned_name),
2481 );
2482
2483 Ok(())
2484 }
2485}
2486
2487fn single_intrinsic_fn(body: &Expression) -> Option<&IntrinsicFunction> {
2488 let ExpressionKind::Block(block_expressions) = &body.kind else {
2489 panic!("function body should be a block")
2490 };
2491
2492 if let ExpressionKind::IntrinsicCallEx(found_intrinsic_fn, _non_instantiated_arguments) =
2493 &block_expressions[0].kind
2494 {
2495 Some(found_intrinsic_fn)
2496 } else {
2497 None
2498 }
2499}
2500
2501fn struct_field_offset(
2502 index_to_look_for: usize,
2503 anon_struct_type: &AnonymousStructType,
2504) -> (MemoryOffset, MemorySize, MemoryAlignment) {
2505 let mut offset = MemoryOffset(0);
2506 for (field_index, (_name, field)) in
2507 anon_struct_type.field_name_sorted_fields.iter().enumerate()
2508 {
2509 let (field_size, field_alignment) = type_size_and_alignment(&field.field_type);
2510 let field_start_offset = offset.space(field_size, field_alignment);
2511 if field_index == index_to_look_for {
2512 return (field_start_offset, field_size, field_alignment);
2513 }
2514 }
2515
2516 panic!("field index is wrong")
2517}