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