v / vlib / v2 / ssa / build_remaining_exprs_from_flat_test.v
206 lines · 196 sloc · 5.15 KB · f3c5760b8838272e4789c38a1be9e03f9ceac351
Raw
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// vtest build: macos
5//
6// Parity pin for the final build_expr_from_flat sweep after s197. The fixture
7// intentionally mixes value-producing arms (postfix, array init, string
8// interpolation, call-or-cast, as-cast, tuple, or, fn literal) with legacy
9// zero-fallback arms (range, map, match, assoc, if-guard, comptime, generic,
10// lambda, lifetime, lock, select, sql).
11module ssa
12
13import v2.ast
14import v2.token
15import v2.types
16
17fn rem_ident(name string) ast.Expr {
18 return ast.Expr(ast.Ident{
19 name: name
20 })
21}
22
23fn rem_num(value string) ast.Expr {
24 return ast.Expr(ast.BasicLiteral{
25 kind: .number
26 value: value
27 })
28}
29
30fn rem_ret_fn(name string, expr ast.Expr) ast.Stmt {
31 return ast.Stmt(ast.FnDecl{
32 name: name
33 typ: ast.FnType{
34 return_type: rem_ident('int')
35 }
36 stmts: [
37 ast.Stmt(ast.ReturnStmt{
38 exprs: [expr]
39 }),
40 ]
41 })
42}
43
44fn rem_expr_fn(name string, expr ast.Expr) ast.Stmt {
45 return ast.Stmt(ast.FnDecl{
46 name: name
47 typ: ast.FnType{}
48 stmts: [
49 ast.Stmt(ast.ExprStmt{
50 expr: expr
51 }),
52 ]
53 })
54}
55
56fn make_remaining_expr_fixture() []ast.File {
57 mut stmts := [
58 ast.Stmt(ast.ModuleStmt{
59 name: 'main'
60 }),
61 ]
62 stmts << rem_ret_fn('keyword_true', ast.Expr(ast.Keyword{
63 tok: .key_true
64 }))
65 stmts << rem_ret_fn('sizeof_int', ast.Expr(ast.KeywordOperator{
66 op: .key_sizeof
67 exprs: [rem_ident('int')]
68 }))
69 stmts << ast.Stmt(ast.FnDecl{
70 name: 'postfix_inc'
71 typ: ast.FnType{
72 return_type: rem_ident('int')
73 }
74 stmts: [
75 ast.Stmt(ast.AssignStmt{
76 op: .decl_assign
77 lhs: [rem_ident('x')]
78 rhs: [rem_num('1')]
79 }),
80 ast.Stmt(ast.ExprStmt{
81 expr: ast.Expr(ast.PostfixExpr{
82 op: .inc
83 expr: rem_ident('x')
84 })
85 }),
86 ast.Stmt(ast.ReturnStmt{
87 exprs: [rem_ident('x')]
88 }),
89 ]
90 })
91 stmts << rem_expr_fn('array_literal', ast.Expr(ast.ArrayInitExpr{
92 exprs: [rem_num('1'), rem_num('2')]
93 }))
94 stmts << rem_expr_fn('string_inter', ast.Expr(ast.StringInterLiteral{
95 kind: .v
96 values: ["'hi'"]
97 }))
98 stmts << rem_ret_fn('or_inner', ast.Expr(ast.OrExpr{
99 expr: rem_num('9')
100 }))
101 stmts << rem_expr_fn('anon_fn', ast.Expr(ast.FnLiteral{
102 typ: ast.FnType{}
103 }))
104 stmts << rem_ret_fn('call_or_cast', ast.Expr(ast.CallOrCastExpr{
105 lhs: rem_ident('int')
106 expr: rem_num('7')
107 }))
108 stmts << rem_ret_fn('as_cast', ast.Expr(ast.AsCastExpr{
109 expr: rem_num('8')
110 typ: rem_ident('int')
111 }))
112 stmts << rem_ret_fn('tuple_first', ast.Expr(ast.Tuple{
113 exprs: [rem_num('3'), rem_num('4')]
114 }))
115 stmts << rem_ret_fn('map_zero', ast.Expr(ast.MapInitExpr{
116 keys: [rem_num('1')]
117 vals: [rem_num('2')]
118 }))
119 stmts << rem_ret_fn('range_zero', ast.Expr(ast.RangeExpr{
120 op: .dotdot
121 start: rem_num('0')
122 end: rem_num('3')
123 }))
124 stmts << rem_ret_fn('match_zero', ast.Expr(ast.MatchExpr{
125 expr: rem_num('1')
126 }))
127 stmts << rem_ret_fn('assoc_zero', ast.Expr(ast.AssocExpr{
128 typ: rem_ident('Point')
129 expr: rem_ident('p')
130 }))
131 stmts << rem_ret_fn('if_guard_zero', ast.Expr(ast.IfGuardExpr{
132 stmt: ast.AssignStmt{
133 op: .decl_assign
134 lhs: [rem_ident('x')]
135 rhs: [rem_num('1')]
136 }
137 }))
138 stmts << rem_ret_fn('comptime_zero', ast.Expr(ast.ComptimeExpr{
139 expr: rem_num('1')
140 }))
141 stmts << rem_ret_fn('generic_index_zero', ast.Expr(ast.GenericArgOrIndexExpr{
142 lhs: rem_ident('foo')
143 expr: rem_ident('int')
144 }))
145 stmts << rem_ret_fn('generic_args_zero', ast.Expr(ast.GenericArgs{
146 lhs: rem_ident('foo')
147 args: [rem_ident('int')]
148 }))
149 stmts << rem_ret_fn('lambda_zero', ast.Expr(ast.LambdaExpr{
150 args: [ast.Ident{
151 name: 'x'
152 }]
153 expr: rem_num('1')
154 }))
155 stmts << rem_ret_fn('lifetime_zero', ast.Expr(ast.LifetimeExpr{
156 name: 'a'
157 }))
158 stmts << rem_ret_fn('lock_zero', ast.Expr(ast.LockExpr{
159 lock_exprs: [rem_ident('x')]
160 }))
161 stmts << rem_ret_fn('select_zero', ast.Expr(ast.SelectExpr{
162 stmt: ast.empty_stmt
163 next: ast.empty_expr
164 }))
165 stmts << rem_ret_fn('sql_zero', ast.Expr(ast.SqlExpr{
166 expr: rem_ident('db')
167 table_name: 'User'
168 }))
169 return [
170 ast.File{
171 name: 'main.v'
172 mod: 'main'
173 stmts: stmts
174 },
175 ]
176}
177
178fn build_remaining_via_legacy(files []ast.File, env &types.Environment, name string) &Module {
179 mut mod := Module.new(name)
180 mut b := Builder.new_with_env(mod, env)
181 b.register_fn_signatures(files[0])
182 b.build_fn_bodies(files[0])
183 return mod
184}
185
186fn build_remaining_via_flat(files []ast.File, env &types.Environment, name string) &Module {
187 flat := ast.flatten_files(files)
188 mut mod := Module.new(name)
189 mut b := Builder.new_with_env(mod, env)
190 b.register_fn_signatures_from_flat(flat.file_cursor(0))
191 b.build_fn_bodies_from_flat(flat.file_cursor(0))
192 return mod
193}
194
195fn test_build_remaining_exprs_from_flat_match_legacy() {
196 _ = token.Token.dotdot
197 files := make_remaining_expr_fixture()
198 env := types.Environment.new()
199 mod_legacy := build_remaining_via_legacy(files, env, 'remaining_legacy')
200 mod_flat := build_remaining_via_flat(files, env, 'remaining_flat')
201
202 assert mod_legacy.funcs.len == mod_flat.funcs.len
203 assert mod_legacy.blocks.len == mod_flat.blocks.len
204 assert mod_legacy.instrs.len == mod_flat.instrs.len
205 assert mod_legacy.values.len == mod_flat.values.len
206}
207