Skip to content

Commit 0d00c76

Browse files
committed
v2: split up huge transformer and cleanc files into array.v expr.v fn.v if.v struct.v
1 parent 3c7a890 commit 0d00c76

12 files changed

Lines changed: 13021 additions & 12932 deletions

File tree

‎vlib/v2/gen/cleanc/array.v‎

Lines changed: 548 additions & 0 deletions
Large diffs are not rendered by default.

‎vlib/v2/gen/cleanc/cleancnew.v‎

Lines changed: 871 additions & 6698 deletions
Large diffs are not rendered by default.

‎vlib/v2/gen/cleanc/expr.v‎

Lines changed: 1946 additions & 0 deletions
Large diffs are not rendered by default.

‎vlib/v2/gen/cleanc/fn.v‎

Lines changed: 1855 additions & 0 deletions
Large diffs are not rendered by default.

‎vlib/v2/gen/cleanc/if.v‎

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
// Copyright (c) 2026 Alexander Medvednikov. All rights reserved.
2+
// Use of this source code is governed by an MIT license
3+
// that can be found in the LICENSE file.
4+
5+
module cleanc
6+
7+
import v2.ast
8+
9+
fn (mut g Gen) infer_tuple_field_types_from_if_expr(expr ast.IfExpr) ?[]string {
10+
if fields := g.infer_tuple_field_types_from_stmts(expr.stmts) {
11+
return fields
12+
}
13+
if expr.else_expr is ast.IfExpr {
14+
if fields := g.infer_tuple_field_types_from_if_expr(expr.else_expr) {
15+
return fields
16+
}
17+
} else if expr.else_expr is ast.UnsafeExpr {
18+
unsafe_expr := expr.else_expr as ast.UnsafeExpr
19+
if fields := g.infer_tuple_field_types_from_stmts(unsafe_expr.stmts) {
20+
return fields
21+
}
22+
}
23+
return none
24+
}
25+
26+
fn (mut g Gen) gen_decl_if_expr_branch(name string, stmts []ast.Stmt) {
27+
if stmts.len == 0 {
28+
return
29+
}
30+
for i, stmt in stmts {
31+
if i == stmts.len - 1 && stmt is ast.ExprStmt {
32+
if stmt.expr is ast.IfExpr {
33+
nested_if := stmt.expr as ast.IfExpr
34+
if !g.if_expr_can_be_ternary(nested_if) && nested_if.else_expr !is ast.EmptyExpr {
35+
g.gen_decl_if_expr(name, nested_if)
36+
continue
37+
}
38+
}
39+
g.write_indent()
40+
g.sb.write_string('${name} = ')
41+
g.gen_expr(stmt.expr)
42+
g.sb.writeln(';')
43+
} else {
44+
g.gen_stmt(stmt)
45+
}
46+
}
47+
}
48+
49+
fn (mut g Gen) gen_decl_if_expr(name string, if_expr ast.IfExpr) {
50+
if if_expr.cond is ast.EmptyExpr {
51+
g.gen_decl_if_expr_branch(name, if_expr.stmts)
52+
return
53+
}
54+
g.write_indent()
55+
g.sb.write_string('if (')
56+
g.gen_expr(if_expr.cond)
57+
g.sb.writeln(') {')
58+
g.indent++
59+
g.gen_decl_if_expr_branch(name, if_expr.stmts)
60+
g.indent--
61+
g.write_indent()
62+
g.sb.write_string('}')
63+
if if_expr.else_expr is ast.IfExpr {
64+
else_if := if_expr.else_expr as ast.IfExpr
65+
if else_if.cond is ast.EmptyExpr {
66+
g.sb.writeln(' else {')
67+
g.indent++
68+
g.gen_decl_if_expr_branch(name, else_if.stmts)
69+
g.indent--
70+
g.write_indent()
71+
g.sb.writeln('}')
72+
} else {
73+
g.sb.writeln(' else {')
74+
g.indent++
75+
g.gen_decl_if_expr(name, else_if)
76+
g.indent--
77+
g.write_indent()
78+
g.sb.writeln('}')
79+
}
80+
} else if if_expr.else_expr !is ast.EmptyExpr {
81+
g.sb.writeln(' else {')
82+
g.indent++
83+
g.write_indent()
84+
g.sb.write_string('${name} = ')
85+
g.gen_expr(if_expr.else_expr)
86+
g.sb.writeln(';')
87+
g.indent--
88+
g.write_indent()
89+
g.sb.writeln('}')
90+
} else {
91+
g.sb.writeln('')
92+
}
93+
}
94+
95+
fn (mut g Gen) gen_return_if_branch(stmts []ast.Stmt) {
96+
if stmts.len == 0 {
97+
return
98+
}
99+
for i, stmt in stmts {
100+
if i == stmts.len - 1 && stmt is ast.ExprStmt {
101+
if stmt.expr is ast.IfExpr {
102+
nested_if := stmt.expr as ast.IfExpr
103+
if !g.if_expr_can_be_ternary(nested_if) && nested_if.else_expr !is ast.EmptyExpr {
104+
g.gen_return_if_expr(nested_if, true)
105+
continue
106+
}
107+
}
108+
mut ret_exprs := []ast.Expr{cap: 1}
109+
ret_exprs << stmt.expr
110+
ret_stmt := ast.ReturnStmt{
111+
exprs: ret_exprs
112+
}
113+
g.gen_stmt(ret_stmt)
114+
} else {
115+
g.gen_stmt(stmt)
116+
}
117+
}
118+
}
119+
120+
fn (mut g Gen) gen_return_if_expr(if_expr ast.IfExpr, emit_indent bool) {
121+
if if_expr.cond is ast.EmptyExpr {
122+
g.gen_return_if_branch(if_expr.stmts)
123+
return
124+
}
125+
if emit_indent {
126+
g.write_indent()
127+
}
128+
g.sb.write_string('if (')
129+
g.gen_expr(if_expr.cond)
130+
g.sb.writeln(') {')
131+
g.indent++
132+
g.gen_return_if_branch(if_expr.stmts)
133+
g.indent--
134+
g.write_indent()
135+
g.sb.write_string('}')
136+
if if_expr.else_expr is ast.IfExpr {
137+
else_if := if_expr.else_expr as ast.IfExpr
138+
if else_if.cond is ast.EmptyExpr {
139+
g.sb.writeln(' else {')
140+
g.indent++
141+
g.gen_return_if_branch(else_if.stmts)
142+
g.indent--
143+
g.write_indent()
144+
g.sb.writeln('}')
145+
} else {
146+
g.sb.writeln(' else {')
147+
g.indent++
148+
g.gen_return_if_expr(else_if, true)
149+
g.indent--
150+
g.write_indent()
151+
g.sb.writeln('}')
152+
}
153+
} else if if_expr.else_expr !is ast.EmptyExpr {
154+
g.sb.writeln(' else {')
155+
g.indent++
156+
mut else_exprs := []ast.Expr{cap: 1}
157+
else_exprs << if_expr.else_expr
158+
else_stmt := ast.ReturnStmt{
159+
exprs: else_exprs
160+
}
161+
g.gen_stmt(else_stmt)
162+
g.indent--
163+
g.write_indent()
164+
g.sb.writeln('}')
165+
} else {
166+
g.sb.writeln('')
167+
}
168+
}
169+
170+
fn (g &Gen) if_expr_can_be_ternary(node ast.IfExpr) bool {
171+
if node.cond !is ast.EmptyExpr {
172+
if node.stmts.len != 1 || node.stmts[0] !is ast.ExprStmt {
173+
return false
174+
}
175+
if node.else_expr is ast.EmptyExpr {
176+
return false
177+
}
178+
}
179+
if node.cond is ast.EmptyExpr {
180+
return node.stmts.len == 1 && node.stmts[0] is ast.ExprStmt
181+
}
182+
if node.else_expr is ast.IfExpr {
183+
return g.if_expr_can_be_ternary(node.else_expr)
184+
}
185+
return true
186+
}
187+
188+
fn (g &Gen) extract_if_expr(expr ast.Expr) ?ast.IfExpr {
189+
match expr {
190+
ast.IfExpr {
191+
return expr
192+
}
193+
ast.ParenExpr {
194+
return g.extract_if_expr(expr.expr)
195+
}
196+
ast.ModifierExpr {
197+
return g.extract_if_expr(expr.expr)
198+
}
199+
ast.UnsafeExpr {
200+
if expr.stmts.len == 1 {
201+
stmt0 := expr.stmts[0]
202+
if stmt0 is ast.ExprStmt {
203+
expr_stmt := stmt0 as ast.ExprStmt
204+
return g.extract_if_expr(expr_stmt.expr)
205+
}
206+
}
207+
return none
208+
}
209+
else {
210+
return none
211+
}
212+
}
213+
}
214+
215+
fn (mut g Gen) gen_if_expr_stmt(node ast.IfExpr) {
216+
// Skip empty conditions (pure else blocks shouldn't appear at top level)
217+
if node.cond is ast.EmptyExpr {
218+
return
219+
}
220+
g.sb.write_string('if (')
221+
g.gen_expr(node.cond)
222+
g.sb.writeln(') {')
223+
g.indent++
224+
g.gen_stmts(node.stmts)
225+
g.indent--
226+
g.write_indent()
227+
g.sb.write_string('}')
228+
// Handle else / else-if
229+
if node.else_expr !is ast.EmptyExpr {
230+
if node.else_expr is ast.IfExpr {
231+
else_if := node.else_expr as ast.IfExpr
232+
if else_if.cond is ast.EmptyExpr {
233+
g.sb.writeln(' else {')
234+
g.indent++
235+
g.gen_stmts(else_if.stmts)
236+
g.indent--
237+
g.write_indent()
238+
g.sb.write_string('}')
239+
} else {
240+
g.sb.write_string(' else ')
241+
g.gen_if_expr_stmt(else_if)
242+
}
243+
} else {
244+
g.sb.writeln(' else {')
245+
g.indent++
246+
g.gen_stmts_from_expr(node.else_expr)
247+
g.indent--
248+
g.write_indent()
249+
g.sb.write_string('}')
250+
}
251+
}
252+
g.sb.writeln('')
253+
}
254+
255+
fn (mut g Gen) gen_if_expr_ternary(node ast.IfExpr) {
256+
if node.cond is ast.EmptyExpr {
257+
if node.stmts.len == 1 && node.stmts[0] is ast.ExprStmt {
258+
stmt := node.stmts[0] as ast.ExprStmt
259+
g.gen_expr(stmt.expr)
260+
} else {
261+
g.sb.write_string('0')
262+
}
263+
return
264+
}
265+
g.sb.write_string('(')
266+
g.gen_expr(node.cond)
267+
g.sb.write_string(' ? ')
268+
if node.stmts.len == 1 && node.stmts[0] is ast.ExprStmt {
269+
stmt := node.stmts[0] as ast.ExprStmt
270+
if nested := g.extract_if_expr(stmt.expr) {
271+
g.gen_if_expr_value(nested)
272+
} else {
273+
g.gen_expr(stmt.expr)
274+
}
275+
} else {
276+
g.sb.write_string('0')
277+
}
278+
g.sb.write_string(' : ')
279+
if node.else_expr is ast.IfExpr {
280+
else_if := node.else_expr as ast.IfExpr
281+
g.gen_if_expr_value(else_if)
282+
} else if node.else_expr is ast.EmptyExpr {
283+
g.sb.write_string('0')
284+
} else {
285+
if nested := g.extract_if_expr(node.else_expr) {
286+
g.gen_if_expr_value(nested)
287+
} else {
288+
g.gen_expr(node.else_expr)
289+
}
290+
}
291+
g.sb.write_string(')')
292+
}
293+
294+
fn (mut g Gen) gen_if_expr_value(node ast.IfExpr) {
295+
mut value_type := g.infer_if_expr_type(node)
296+
if g.if_expr_can_be_ternary(node) && value_type != '' && value_type != 'void' {
297+
g.gen_if_expr_ternary(node)
298+
return
299+
}
300+
if value_type == '' || value_type == 'void' {
301+
g.sb.write_string('({ ')
302+
g.gen_if_expr_stmt(node)
303+
g.sb.write_string('; 0; })')
304+
return
305+
}
306+
if value_type == 'int_literal' {
307+
value_type = 'int'
308+
}
309+
tmp_name := '_if_expr_t${g.tmp_counter}'
310+
g.tmp_counter++
311+
g.sb.write_string('({ ${value_type} ${tmp_name} = ${zero_value_for_type(value_type)}; ')
312+
g.gen_decl_if_expr(tmp_name, node)
313+
g.sb.write_string(' ${tmp_name}; })')
314+
}
315+
316+
fn (mut g Gen) infer_if_expr_type(node ast.IfExpr) string {
317+
if t := g.get_expr_type_from_env(node) {
318+
if t != '' {
319+
return t
320+
}
321+
}
322+
if node.stmts.len == 1 && node.stmts[0] is ast.ExprStmt {
323+
stmt := node.stmts[0] as ast.ExprStmt
324+
t := g.get_expr_type(stmt.expr)
325+
if t != '' && t != 'int' {
326+
return t
327+
}
328+
}
329+
if node.else_expr is ast.IfExpr {
330+
t := g.infer_if_expr_type(node.else_expr)
331+
if t != '' {
332+
return t
333+
}
334+
} else if node.else_expr !is ast.EmptyExpr {
335+
t := g.get_expr_type(node.else_expr)
336+
if t != '' {
337+
return t
338+
}
339+
}
340+
return 'int'
341+
}
342+
343+
// expr_produces_pointer checks if an expression produces a pointer value in C.
344+
// More comprehensive than expr_is_pointer - handles casts, pointer arithmetic, etc.
345+
// Used in gen_call_arg to avoid wrapping pointer expressions in compound literals.

0 commit comments

Comments
 (0)