factorio_codegen/generator/
statement.rs1use factorio_ir::{module::Module, scope::Scope, statement::Statement};
2
3use crate::{LuaGenerator, LuaGeneratorResult};
4
5fn body_has_continue(body: &[Statement]) -> bool {
6 body.iter().any(|s| match s {
7 Statement::Continue => true,
8 Statement::Conditional {
9 then_block,
10 else_block,
11 ..
12 } => body_has_continue(then_block) || body_has_continue(else_block),
13 _ => false,
14 })
15}
16
17impl LuaGenerator {
18 pub(crate) fn generate_statement(
20 &mut self,
21 statement: &Statement,
22 module: Option<&Module>,
23 module_name: Option<&str>,
24 scope: Scope,
25 ) -> LuaGeneratorResult<()> {
26 match statement {
27 Statement::FunctionDecl(function) => {
28 self.generate_function(function, module, scope, module_name)?;
29 }
30 Statement::StructDecl(struct_decl) => {
31 self.generate_struct(struct_decl, module, scope, module_name)?;
32 }
33 Statement::VariableDecl {
34 name,
35 value,
36 source_type,
37 ..
38 } => {
39 let value = self.generate_expression(value);
40 let type_comment = self.variable_type_comment(source_type.as_deref());
41 let line = match (scope, module_name) {
42 (Scope::Public, Some(module_name)) => {
43 format!("{module_name}.{name}{type_comment} = {value}")
44 }
45 _ => format!("local {name}{type_comment} = {value}"),
46 };
47 self.write_line(&line);
48 }
49 Statement::Assignment { target, value } => {
50 let target = self.generate_expression(target);
51 let value = self.generate_expression(value);
52 self.write_line(&format!("{target} = {value}"));
53 }
54 Statement::Conditional {
55 condition,
56 then_block,
57 else_block,
58 } => {
59 let condition = self.generate_expression(condition);
60 self.write_line(&format!("if {condition} then"));
61
62 self.indent_level += 1;
63 for statement in then_block {
64 self.generate_statement(statement, module, module_name, Scope::Private)?;
65 }
66 self.indent_level -= 1;
67
68 if !else_block.is_empty() {
69 self.write_line("else");
70 self.indent_level += 1;
71 for statement in else_block {
72 self.generate_statement(statement, module, module_name, Scope::Private)?;
73 }
74 self.indent_level -= 1;
75 }
76 self.write_line("end");
77 }
78 Statement::Return(value) => {
79 let line = value.as_ref().map_or_else(
80 || "return".to_string(),
81 |value| format!("return {}", self.generate_expression(value)),
82 );
83 self.write_line(&line);
84 }
85 Statement::Expr(expression) => {
86 self.write_line(&self.generate_expression(expression));
87 }
88 Statement::ForIn { var, iter, body } => {
89 self.for_depth += 1;
90 let depth = self.for_depth;
91 let iter = self.generate_expression(iter);
92 self.write_line(&format!("for _, {var} in pairs({iter}) do"));
93 self.indent_level += 1;
94 for stmt in body {
95 self.generate_statement(stmt, module, module_name, Scope::Private)?;
96 }
97 if body_has_continue(body) {
98 self.write_line(&format!("::__continue_{depth}::"));
99 }
100 self.indent_level -= 1;
101 self.write_line("end");
102 self.for_depth -= 1;
103 }
104 Statement::Continue => {
105 self.write_line(&format!("goto __continue_{}", self.for_depth));
106 }
107 }
108
109 Ok(())
110 }
111}