Skip to main content

t_backend_c/
lib.rs

1#![deny(missing_docs)]
2
3//! C code generator for the T programming language.
4//!
5//! Transforms a typed AST (`Module`) into C99/C11 source code.
6
7use 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
26/// Compiles a T module into C source code.
27pub 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) = &param.parameter_type {
318                let c_name = if self.newtypes.contains_key(&param.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(&param.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) = &param.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) = &param.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(&param.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;