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