1#![deny(missing_docs)]
2
3use std::collections::{HashMap, HashSet};
8use std::fmt::Write;
9
10use t_ree::{
11 declaration::{Declaration, FunctionDefinition, Module, Newtype, Parameter, ParameterList},
12 expression::{Binding, Block, Expression, ExpressionKind, Statement},
13 types::{FloatWidth, IntWidth, Mutability, Signedness, Type},
14};
15
16fn element_byte_size(element: &Type) -> usize {
17 match element {
18 Type::Int(width, _) => width.byte_size(),
19 Type::Float(width) => width.byte_size(),
20 Type::Bool => 1,
21 Type::Pointer(..) => 8,
22 _ => 4,
23 }
24}
25
26pub fn compile(module: &Module) -> String {
28 let mut emitter = Emitter::new();
29 emitter.emit_module(module);
30 emitter.output
31}
32
33struct Emitter {
34 output: String,
35 indent_level: usize,
36 labels: HashMap<String, Vec<Parameter>>,
37 newtypes: HashMap<String, Type>,
38 auto_ref_variables: HashSet<String>,
39 pointer_param_variables: HashSet<String>,
40 label_param_names: HashMap<String, String>,
41 in_main: bool,
42 temp_counter: usize,
43 function_defers: Vec<Statement>,
44 shadow_scopes: Vec<HashMap<String, String>>,
45 shadow_counter: usize,
46 has_stdio: bool,
47}
48
49impl Emitter {
50 fn new() -> Self {
51 Self {
52 output: String::new(),
53 indent_level: 0,
54 labels: HashMap::new(),
55 newtypes: HashMap::new(),
56 auto_ref_variables: HashSet::new(),
57 pointer_param_variables: HashSet::new(),
58 label_param_names: HashMap::new(),
59 function_defers: Vec::new(),
60 in_main: false,
61 temp_counter: 0,
62 shadow_scopes: Vec::new(),
63 shadow_counter: 0,
64 has_stdio: false,
65 }
66 }
67
68 fn push(&mut self, text: &str) {
69 self.output.push_str(text);
70 }
71
72 fn newline(&mut self) {
73 self.output.push('\n');
74 }
75
76 fn indent(&mut self) {
77 for _ in 0..self.indent_level {
78 self.push(" ");
79 }
80 }
81
82 fn emit_module(&mut self, module: &Module) {
83 self.push("#include <stdint.h>\n");
84 self.push("#include <stdbool.h>\n");
85 self.push("#include <stddef.h>\n");
86 self.has_stdio = self.uses_print(module)
87 || module.iter().any(|d| {
88 matches!(d, Declaration::Import(path) if path == "stdio.h" || path.ends_with("/stdio.h"))
89 });
90 if self.has_stdio {
91 self.push("#include <stdio.h>\n");
92 }
93 self.newline();
94
95 for declaration in module {
96 if let Declaration::Type(newtype) = declaration {
97 self.newtypes
98 .insert(newtype.name.clone(), newtype.inner_type.clone());
99 if matches!(&newtype.inner_type, Type::Tuple(fields) if !fields.is_empty())
100 || matches!(&newtype.inner_type, Type::Enum(_))
101 {
102 writeln!(self.output, "struct {};", newtype.name).unwrap();
103 }
104 }
105 }
106 self.newline();
107
108 for declaration in module {
109 self.emit_declaration(declaration);
110 self.newline();
111 }
112 }
113
114 fn uses_print(&self, module: &Module) -> bool {
115 module.iter().any(|decl| {
116 if let Declaration::Function(func) = decl {
117 self.block_uses_print(&func.body)
118 } else {
119 false
120 }
121 })
122 }
123
124 fn block_uses_print(&self, block: &Block) -> bool {
125 block
126 .statements
127 .iter()
128 .any(|s| self.statement_uses_print(s))
129 || block
130 .result
131 .as_ref()
132 .is_some_and(|e| self.expression_uses_print(e))
133 }
134
135 fn statement_uses_print(&self, statement: &Statement) -> bool {
136 match statement {
137 Statement::Expression(e) | Statement::Return(Some(e)) => self.expression_uses_print(e),
138 Statement::Let { value, .. } => self.expression_uses_print(value),
139 Statement::Assign(target, value) => {
140 self.expression_uses_print(target) || self.expression_uses_print(value)
141 }
142 Statement::Label {
143 initial_arguments, ..
144 } => initial_arguments
145 .iter()
146 .any(|e| self.expression_uses_print(e)),
147 Statement::Jump { arguments, .. } => {
148 arguments.iter().any(|e| self.expression_uses_print(e))
149 }
150 Statement::Return(None) | Statement::MultiReplace { .. } => false,
151 Statement::Defer(inner) => self.statement_uses_print(inner),
152 }
153 }
154
155 fn expression_uses_print(&self, expression: &Expression) -> bool {
156 match &expression.kind {
157 ExpressionKind::Print(_) => true,
158 ExpressionKind::Block(block) => self.block_uses_print(block),
159 ExpressionKind::If {
160 condition,
161 then_branch,
162 else_branch,
163 } => {
164 self.expression_uses_print(condition)
165 || self.block_uses_print(then_branch)
166 || else_branch
167 .as_ref()
168 .is_some_and(|b| self.block_uses_print(b))
169 }
170 ExpressionKind::Match { value, arms } => {
171 self.expression_uses_print(value)
172 || arms.iter().any(|arm| self.block_uses_print(&arm.body))
173 }
174 ExpressionKind::Call(callee, args) => {
175 self.expression_uses_print(callee)
176 || args.iter().any(|e| self.expression_uses_print(e))
177 }
178 ExpressionKind::BinaryOperation(_, left, right) => {
179 self.expression_uses_print(left) || self.expression_uses_print(right)
180 }
181 ExpressionKind::UnaryOperation(_, operand)
182 | ExpressionKind::Dereference(operand)
183 | ExpressionKind::Convert(operand, _)
184 | ExpressionKind::Transmute(operand, _) => self.expression_uses_print(operand),
185 ExpressionKind::Replace(target, value) => {
186 self.expression_uses_print(target) || self.expression_uses_print(value)
187 }
188 _ => false,
189 }
190 }
191
192 fn emit_type(&mut self, ty: &Type) {
193 match ty {
194 Type::Never => self.push("void"),
195 Type::Bool => self.push("bool"),
196 Type::Int(IntWidth::WSize, Signedness::Unsigned) => self.push("size_t"),
197 Type::Int(IntWidth::WSize, Signedness::Signed) => self.push("ptrdiff_t"),
198 Type::Int(width, signedness) => {
199 if matches!(signedness, Signedness::Unsigned) {
200 self.push("u");
201 }
202 write!(self.output, "int{}_t", width.bit_size()).unwrap();
203 }
204 Type::Float(FloatWidth::W32) => self.push("float"),
205 Type::Float(FloatWidth::W64) => self.push("double"),
206 Type::Pointer(mutability, inner) => {
207 if matches!(mutability, Mutability::Shared) {
208 self.push("const ");
209 }
210 self.emit_type(inner);
211 self.push(" *");
212 }
213 Type::Array(element, size) => {
214 self.emit_type(element);
215 write!(self.output, "[{size}]").unwrap();
216 }
217 Type::Vector(element, lanes) => {
218 let byte_size = lanes * element_byte_size(element);
219 self.emit_type(element);
220 write!(self.output, " __attribute__((vector_size({byte_size})))").unwrap();
221 }
222 Type::Slice(mutability, inner) => {
223 self.push("struct { ");
224 if matches!(mutability, Mutability::Shared) {
225 self.push("const ");
226 }
227 self.emit_type(inner);
228 self.push(" *data; size_t length; }");
229 }
230 Type::Tuple(fields) if fields.is_empty() => self.push("void"),
231 Type::Tuple(fields) => {
232 self.push("struct { ");
233 for (index, field) in fields.iter().enumerate() {
234 self.emit_type(field);
235 write!(self.output, " _{index}; ").unwrap();
236 }
237 self.push("}");
238 }
239 Type::Enum(variants) => {
240 self.push("struct { uint8_t tag; union { ");
241 for variant in variants {
242 self.emit_type(variant);
243 if let Type::Named(name) = variant {
244 write!(self.output, " {name}; ").unwrap();
245 }
246 }
247 self.push("} value; }");
248 }
249 Type::Named(name) => {
250 let needs_struct = self.newtypes.get(name).is_some_and(|inner| {
251 matches!(inner, Type::Tuple(fields) if !fields.is_empty())
252 || matches!(inner, Type::Enum(_))
253 || matches!(inner, Type::Array(..))
254 });
255 if needs_struct {
256 self.push("struct ");
257 }
258 self.push(name);
259 }
260 Type::Function(signature) => {
261 self.emit_type(&signature.return_type);
262 self.push(" (*)(");
263 for (index, param) in signature.parameters.iter().enumerate() {
264 if index > 0 {
265 self.push(", ");
266 }
267 self.emit_type(param);
268 }
269 self.push(")");
270 }
271 }
272 }
273
274 fn emit_typed_name(&mut self, ty: &Type, name: &str) {
275 match ty {
276 Type::Array(element, size) => {
277 self.emit_type(element);
278 write!(self.output, " {name}[{size}]").unwrap();
279 }
280 Type::Function(signature) => {
281 self.emit_type(&signature.return_type);
282 write!(self.output, " (*{name})(").unwrap();
283 for (index, param) in signature.parameters.iter().enumerate() {
284 if index > 0 {
285 self.push(", ");
286 }
287 self.emit_type(param);
288 }
289 self.push(")");
290 }
291 _ => {
292 self.emit_type(ty);
293 write!(self.output, " {name}").unwrap();
294 }
295 }
296 }
297
298 fn emit_parameter_list(&mut self, params: &ParameterList) {
299 self.push("(");
300 let parameters = params.parameters();
301 if parameters.is_empty() {
302 self.push("void");
303 } else {
304 self.emit_parameters(parameters);
305 if matches!(params, ParameterList::Variadic(_)) {
306 self.push(", ...");
307 }
308 }
309 self.push(")");
310 }
311
312 fn emit_parameters(&mut self, parameters: &[Parameter]) {
313 for (index, param) in parameters.iter().enumerate() {
314 if index > 0 {
315 self.push(", ");
316 }
317 if let Some(ty) = ¶m.parameter_type {
318 let c_name = if self.newtypes.contains_key(¶m.name)
319 && *ty != Type::Named(param.name.clone())
320 {
321 format!("_{}", param.name)
322 } else {
323 param.name.clone()
324 };
325 if c_name != param.name
326 && let Some(scope) = self.shadow_scopes.last_mut()
327 {
328 scope.insert(param.name.clone(), c_name.clone());
329 }
330 self.emit_typed_name(ty, &c_name);
331 if matches!(ty, Type::Pointer(..))
332 || self
333 .newtypes
334 .get(¶m.name)
335 .is_some_and(|inner| matches!(inner, Type::Pointer(..)))
336 {
337 self.auto_ref_variables.insert(c_name.clone());
338 self.pointer_param_variables.insert(c_name);
339 }
340 }
341 }
342 }
343
344 fn emit_declaration(&mut self, declaration: &Declaration) {
345 match declaration {
346 Declaration::Type(newtype) => {
347 self.newtypes
348 .insert(newtype.name.clone(), newtype.inner_type.clone());
349 self.emit_newtype(newtype);
350 }
351 Declaration::Function(function) => self.emit_function(function, function.public),
352 Declaration::Extern(extern_function) => {
353 if !(self.has_stdio && Self::is_stdio_function(&extern_function.name)) {
354 self.emit_type(&extern_function.return_type);
355 write!(self.output, " {}", extern_function.name).unwrap();
356 self.emit_parameter_list(&extern_function.parameters);
357 self.push(";\n");
358 }
359 }
360 Declaration::Constant(constant) => {
361 if !constant.public {
362 self.push("static ");
363 }
364 self.push("const ");
365 self.emit_typed_name(&constant.constant_type, &constant.name);
366 self.push(" = ");
367 self.emit_expression(&constant.value);
368 self.push(";\n");
369 }
370 Declaration::Import(path) => {
371 if !(self.has_stdio && (path == "stdio.h" || path.ends_with("/stdio.h"))) {
372 writeln!(self.output, "#include \"{path}\"").unwrap();
373 }
374 }
375 }
376 }
377
378 fn emit_newtype(&mut self, newtype: &Newtype) {
379 match &newtype.inner_type {
380 Type::Tuple(fields) if !fields.is_empty() => {
381 writeln!(self.output, "struct {} {{", newtype.name).unwrap();
382 self.indent_level += 1;
383 for field_type in fields {
384 self.indent();
385 let field_name = if let Type::Named(name) = field_type {
386 name.clone()
387 } else {
388 format!("_{}", self.output.len())
389 };
390 self.emit_typed_name(field_type, &field_name);
391 self.push(";\n");
392 }
393 self.indent_level -= 1;
394 self.push("};\n");
395 }
396 Type::Enum(variants) => {
397 writeln!(self.output, "struct {} {{", newtype.name).unwrap();
398 self.indent_level += 1;
399 self.indent();
400 self.push("uint8_t tag;\n");
401 self.indent();
402 self.push("union {\n");
403 self.indent_level += 1;
404 for variant in variants {
405 self.indent();
406 let variant_name = if let Type::Named(name) = variant {
407 name.clone()
408 } else {
409 format!("_{}", self.output.len())
410 };
411 self.emit_typed_name(variant, &variant_name);
412 self.push(";\n");
413 }
414 self.indent_level -= 1;
415 self.indent();
416 self.push("} value;\n");
417 self.indent_level -= 1;
418 self.push("};\n");
419 }
420 Type::Array(element, size) => {
421 writeln!(self.output, "struct {} {{", newtype.name).unwrap();
422 self.indent_level += 1;
423 self.indent();
424 self.emit_type(element);
425 writeln!(self.output, " data[{size}];").unwrap();
426 self.indent_level -= 1;
427 self.push("};\n");
428 }
429 _ => {
430 self.push("typedef ");
431 self.emit_typed_name(&newtype.inner_type, &newtype.name);
432 self.push(";\n");
433 }
434 }
435 }
436
437 fn emit_label_declarations(&mut self) {
438 for (label_name, params) in &self.labels.clone() {
439 for param in params {
440 if let Some(ty) = ¶m.parameter_type {
441 let qualified = format!("{label_name}_{}", param.name);
442 self.indent();
443 self.emit_typed_name(ty, &qualified);
444 self.push(";\n");
445 }
446 }
447 }
448 }
449
450 fn register_label(&mut self, name: &str, parameters: &[Parameter]) {
451 self.labels.insert(name.to_string(), parameters.to_vec());
452 for param in parameters {
453 self.label_param_names
454 .insert(param.name.clone(), format!("{name}_{}", param.name));
455 }
456 }
457
458 fn collect_labels(&mut self, block: &Block) {
459 for statement in &block.statements {
460 self.collect_labels_statement(statement);
461 }
462 if let Some(result) = &block.result {
463 self.collect_labels_expression(result);
464 }
465 }
466
467 fn collect_labels_statement(&mut self, statement: &Statement) {
468 match statement {
469 Statement::Label {
470 name, parameters, ..
471 } => self.register_label(name, parameters),
472 Statement::Expression(expression) => self.collect_labels_expression(expression),
473 Statement::Defer(inner) => self.collect_labels_statement(inner),
474 _ => {}
475 }
476 }
477
478 fn collect_labels_expression(&mut self, expression: &Expression) {
479 match &expression.kind {
480 ExpressionKind::Block(block) => self.collect_labels(block),
481 ExpressionKind::If {
482 then_branch,
483 else_branch,
484 ..
485 } => {
486 self.collect_labels(then_branch);
487 if let Some(else_block) = else_branch {
488 self.collect_labels(else_block);
489 }
490 }
491 ExpressionKind::Match { arms, .. } => {
492 for arm in arms {
493 self.collect_labels(&arm.body);
494 }
495 }
496 _ => {}
497 }
498 }
499
500 fn push_shadow_scope(&mut self) {
501 self.shadow_scopes.push(HashMap::new());
502 }
503
504 fn pop_shadow_scope(&mut self) {
505 self.shadow_scopes.pop();
506 }
507
508 fn register_shadow(&mut self, name: &str) -> String {
509 let already_declared = self
510 .shadow_scopes
511 .iter()
512 .any(|scope| scope.contains_key(name));
513 let emit_name = if already_declared {
514 self.shadow_counter += 1;
515 format!("{name}${}", self.shadow_counter)
516 } else {
517 name.into()
518 };
519 if let Some(scope) = self.shadow_scopes.last_mut() {
520 scope.insert(name.into(), emit_name.clone());
521 }
522 emit_name
523 }
524
525 fn resolve_shadow<'a>(&'a self, name: &'a str) -> &'a str {
526 for scope in self.shadow_scopes.iter().rev() {
527 if let Some(resolved) = scope.get(name) {
528 return resolved;
529 }
530 }
531 name
532 }
533
534 fn emit_function(&mut self, function: &FunctionDefinition, public: bool) {
535 self.labels.clear();
536 self.auto_ref_variables.clear();
537 self.pointer_param_variables.clear();
538 self.label_param_names.clear();
539 self.shadow_scopes.clear();
540 self.shadow_counter = 0;
541 self.push_shadow_scope();
542 self.collect_labels(&function.body);
543 let is_main = function.name == "main";
544 let is_void = function.return_type == Type::Tuple(Vec::new());
545 if !is_main && !public {
546 self.push("static ");
547 }
548 if is_main {
549 self.push("int32_t");
550 } else {
551 self.emit_type(&function.return_type);
552 }
553 write!(self.output, " {}(", function.name).unwrap();
554 if function.parameters.is_empty() {
555 self.push("void");
556 } else {
557 self.emit_parameters(&function.parameters);
558 }
559 self.push(") {\n");
560 self.indent_level += 1;
561 self.in_main = is_main;
562 self.emit_label_declarations();
563 let has_result = function.body.result.is_some();
564 if is_void || (is_main && !has_result) {
565 self.emit_function_body_void(&function.body);
566 } else {
567 self.emit_function_body(&function.body);
568 }
569 let ends_with_return = function
570 .body
571 .statements
572 .last()
573 .is_some_and(|s| matches!(s, Statement::Return(_)));
574 if is_main && (is_void || !has_result) && !ends_with_return {
575 self.indent();
576 self.push("return 0;\n");
577 }
578 self.in_main = false;
579 self.indent_level -= 1;
580 self.push("}\n");
581 }
582
583 fn emit_function_body(&mut self, block: &Block) {
584 self.function_defers = Self::collect_defers(&block.statements)
585 .into_iter()
586 .cloned()
587 .collect();
588 for statement in &block.statements {
589 self.emit_statement(statement);
590 }
591 let defers = std::mem::take(&mut self.function_defers);
592 for defer in defers.iter().rev() {
593 self.emit_statement(defer);
594 }
595 if let Some(result) = &block.result {
596 self.indent();
597 self.push("return ");
598 self.emit_expression(result);
599 self.push(";\n");
600 }
601 self.function_defers.clear();
602 }
603
604 fn emit_function_body_void(&mut self, block: &Block) {
605 self.function_defers = Self::collect_defers(&block.statements)
606 .into_iter()
607 .cloned()
608 .collect();
609 for statement in &block.statements {
610 self.emit_statement(statement);
611 }
612 if let Some(result) = &block.result {
613 self.indent();
614 self.emit_expression(result);
615 self.push(";\n");
616 }
617 let defers = std::mem::take(&mut self.function_defers);
618 for defer in defers.iter().rev() {
619 self.emit_statement(defer);
620 }
621 }
622
623 fn emit_block_content(&mut self, block: &Block) {
624 let defers = Self::collect_defers(&block.statements);
625 for statement in &block.statements {
626 self.emit_statement(statement);
627 }
628 if let Some(result) = &block.result {
629 self.indent();
630 self.emit_expression(result);
631 self.push(";\n");
632 }
633 self.emit_defers(&defers);
634 }
635
636 fn emit_statement(&mut self, statement: &Statement) {
637 self.indent();
638 match statement {
639 Statement::Expression(expression) => {
640 if let ExpressionKind::Replace(target, value) = &expression.kind {
641 self.emit_assign_target(target);
642 self.push(" = ");
643 self.emit_expression(value);
644 } else {
645 self.emit_expression(expression);
646 }
647 self.push(";\n");
648 }
649 Statement::Let {
650 name,
651 binding,
652 declared_type,
653 value,
654 } => {
655 let mut value_output = String::new();
656 std::mem::swap(&mut self.output, &mut value_output);
657 self.emit_expression(value);
658 let wrap_array_early = self.is_array_newtype(declared_type.as_ref())
659 && matches!(value.kind, ExpressionKind::ArrayLiteral(_));
660 std::mem::swap(&mut self.output, &mut value_output);
661 let effective_name = if self.newtypes.contains_key(name) {
662 format!("_{name}")
663 } else {
664 name.clone()
665 };
666 let emit_name = self.register_shadow(&effective_name);
667 if effective_name != *name
668 && let Some(scope) = self.shadow_scopes.last_mut()
669 {
670 scope.insert(name.clone(), emit_name.clone());
671 }
672 if matches!(binding, Binding::Variable | Binding::Reference) {
673 self.auto_ref_variables.insert(emit_name.clone());
674 }
675 let is_const = matches!(binding, Binding::Value | Binding::Reference);
676 let ty = declared_type.as_ref().or(value.resolved_type.as_ref());
677 if is_const && matches!(ty, Some(Type::Pointer(..))) {
678 self.emit_type(ty.unwrap());
679 write!(self.output, " const {emit_name}").unwrap();
680 } else {
681 if is_const {
682 self.push("const ");
683 }
684 if let Some(ty) = ty {
685 self.emit_typed_name(ty, &emit_name);
686 } else {
687 write!(self.output, "auto {emit_name}").unwrap();
688 }
689 }
690 self.push(" = ");
691 if wrap_array_early {
692 self.push("{");
693 }
694 self.push(&value_output);
695 if wrap_array_early {
696 self.push("}");
697 }
698 self.push(";\n");
699 }
700 Statement::Assign(target, value) => {
701 self.emit_assign_target(target);
702 self.push(" = ");
703 self.emit_expression(value);
704 self.push(";\n");
705 }
706 Statement::Return(value) => {
707 if !self.function_defers.is_empty() {
708 let defers = self.function_defers.clone();
709 for defer in defers.iter().rev() {
710 self.emit_statement(defer);
711 }
712 }
713 if let Some(value) = value {
714 self.push("return ");
715 self.emit_expression(value);
716 self.push(";\n");
717 } else if self.in_main {
718 self.push("return 0;\n");
719 } else {
720 self.push("return;\n");
721 }
722 }
723 Statement::Label {
724 name,
725 parameters,
726 initial_arguments,
727 } => {
728 for (param, arg) in parameters.iter().zip(initial_arguments) {
729 let qualified = format!("{name}_{}", param.name);
730 self.push(&qualified);
731 self.push(" = ");
732 self.emit_expression(arg);
733 self.push(";\n");
734 self.indent();
735 }
736 self.output.truncate(self.output.trim_end().len());
737 writeln!(self.output, "\n{name}:;").unwrap();
738 }
739 Statement::Jump { label, arguments } => {
740 if !arguments.is_empty() {
741 let Some(params) = self.labels.get(label).cloned() else {
742 eprintln!("internal error: label '{label}' not found in function");
743 return;
744 };
745 let base = self.temp_counter;
746 self.temp_counter += params.len();
747 for (index, (param, arg)) in params.iter().zip(arguments).enumerate() {
748 let temp_id = base + index;
749 if let Some(ty) = ¶m.parameter_type {
750 self.emit_type(ty);
751 }
752 write!(self.output, " _tmp_{temp_id} = ").unwrap();
753 self.emit_expression(arg);
754 self.push(";\n");
755 self.indent();
756 }
757 for (index, param) in params.iter().enumerate() {
758 let temp_id = base + index;
759 let qualified = self
760 .label_param_names
761 .get(¶m.name)
762 .cloned()
763 .unwrap_or_else(|| param.name.clone());
764 write!(self.output, "{qualified} = _tmp_{temp_id}").unwrap();
765 self.push(";\n");
766 self.indent();
767 }
768 }
769 writeln!(self.output, "goto {label};").unwrap();
770 }
771 Statement::MultiReplace {
772 bindings,
773 targets,
774 values,
775 } => {
776 let base = self.temp_counter;
777 self.temp_counter += values.len();
778 for (index, value) in values.iter().enumerate() {
779 let temp_id = base + index;
780 if let Some(ty) = &value.resolved_type {
781 self.emit_type(ty);
782 } else {
783 self.push("auto");
784 }
785 write!(self.output, " _swap_{temp_id} = ").unwrap();
786 self.emit_expression(value);
787 self.push(";\n");
788 self.indent();
789 }
790 for (index, binding) in bindings.iter().enumerate() {
791 if let Some((name, bind_mode)) = binding {
792 let is_const = matches!(bind_mode, Binding::Value | Binding::Reference);
793 if matches!(bind_mode, Binding::Variable | Binding::Reference) {
794 self.auto_ref_variables.insert(name.clone());
795 }
796 if is_const {
797 self.push("const ");
798 }
799 if let Some(ty) = &values[index].resolved_type {
800 self.emit_type(ty);
801 }
802 write!(self.output, " {name} = ").unwrap();
803 self.emit_place(&targets[index]);
804 self.push(";\n");
805 self.indent();
806 }
807 }
808 for (index, target) in targets.iter().enumerate() {
809 let temp_id = base + index;
810 self.emit_assign_target(target);
811 writeln!(self.output, " = _swap_{temp_id};").unwrap();
812 if index + 1 < targets.len() {
813 self.indent();
814 }
815 }
816 }
817 Statement::Defer(_) => {}
818 }
819 }
820
821 fn collect_defers(statements: &[Statement]) -> Vec<&Statement> {
822 let mut defers = Vec::new();
823 for statement in statements {
824 if let Statement::Defer(inner) = statement {
825 defers.push(inner.as_ref());
826 }
827 }
828 defers
829 }
830
831 fn emit_defers(&mut self, defers: &[&Statement]) {
832 for statement in defers.iter().rev() {
833 self.emit_statement(statement);
834 }
835 }
836
837 fn is_direct_auto_ref(&self, expression: &Expression) -> bool {
838 matches!(&expression.kind, ExpressionKind::Variable(name) if self.auto_ref_variables.contains(self.resolve_shadow(name)))
839 }
840
841 fn is_auto_ref_chain(&self, expression: &Expression) -> bool {
842 match &expression.kind {
843 ExpressionKind::Variable(name) => {
844 self.auto_ref_variables.contains(self.resolve_shadow(name))
845 }
846 ExpressionKind::Field(inner, _) | ExpressionKind::Index(inner, _) => {
847 self.is_auto_ref_chain(inner)
848 }
849 _ => false,
850 }
851 }
852
853 fn resolve_variable_name(&self, name: &str) -> String {
854 self.label_param_names
855 .get(name)
856 .cloned()
857 .unwrap_or_else(|| self.resolve_shadow(name).into())
858 }
859
860 fn is_pointer_param(&self, expression: &Expression) -> bool {
861 if let ExpressionKind::Variable(name) = &expression.kind {
862 let resolved = self.resolve_variable_name(name);
863 self.pointer_param_variables.contains(&resolved)
864 } else {
865 false
866 }
867 }
868
869 fn emit_assign_target(&mut self, expression: &Expression) {
870 if let ExpressionKind::Variable(name) = &expression.kind {
871 let resolved = self.resolve_variable_name(name);
872 if self.pointer_param_variables.contains(&resolved) {
873 write!(self.output, "(*{resolved})").unwrap();
874 return;
875 }
876 }
877 if let ExpressionKind::Dereference(inner) = &expression.kind
878 && let ExpressionKind::Variable(name) = &inner.kind
879 {
880 let resolved = self.resolve_variable_name(name);
881 if self.pointer_param_variables.contains(&resolved) {
882 write!(self.output, "(*{resolved})").unwrap();
883 return;
884 }
885 }
886 self.emit_place(expression);
887 }
888
889 fn emit_place(&mut self, expression: &Expression) {
890 match &expression.kind {
891 ExpressionKind::Variable(name) => {
892 let resolved = self.resolve_variable_name(name);
893 self.push(&resolved);
894 }
895 ExpressionKind::Field(inner, field) => {
896 let effective_inner = if let ExpressionKind::Field(grandchild, inner_field) =
897 &inner.kind
898 {
899 if self.is_identity_downcast(grandchild.resolved_type.as_ref(), inner_field) {
900 grandchild.as_ref()
901 } else {
902 inner.as_ref()
903 }
904 } else {
905 inner.as_ref()
906 };
907 if self.is_identity_downcast(effective_inner.resolved_type.as_ref(), field) {
908 self.emit_place(effective_inner);
909 } else if self.is_typedef_downcast(effective_inner.resolved_type.as_ref()) {
910 self.push("(*(");
911 if let Some(resolved_type) = expression.resolved_type.as_ref() {
912 self.emit_type(resolved_type);
913 }
914 self.push("*)&");
915 self.emit_place(effective_inner);
916 self.push(")");
917 } else {
918 self.emit_place(effective_inner);
919 let use_arrow = if let ExpressionKind::Variable(name) = &effective_inner.kind {
920 let resolved = self.resolve_variable_name(name);
921 self.pointer_param_variables.contains(&resolved)
922 } else {
923 false
924 };
925 if use_arrow
926 || (self.is_pointer_type(effective_inner.resolved_type.as_ref())
927 && !self.is_direct_auto_ref(effective_inner))
928 {
929 self.push("->");
930 } else {
931 self.push(".");
932 }
933 self.push(field);
934 }
935 }
936 ExpressionKind::Index(array, index) => {
937 self.emit_place(array);
938 if self.is_array_newtype(array.resolved_type.as_ref()) {
939 self.push(".data");
940 }
941 self.push("[");
942 self.emit_expression(index);
943 self.push("]");
944 }
945 ExpressionKind::Dereference(inner)
946 if self.is_auto_ref_chain(inner) && !self.is_pointer_param(inner) =>
947 {
948 self.emit_place(inner);
949 }
950 ExpressionKind::Dereference(inner) => {
951 self.push("(*");
952 self.emit_expression(inner);
953 self.push(")");
954 }
955 _ => self.emit_expression(expression),
956 }
957 }
958}
959
960mod emit;
961
962#[cfg(test)]
963mod tests;