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