v / vlib / v2 / ssa / build_init_from_flat_test.v
148 lines · 142 sloc · 3.98 KB · d358576851079d4716834cc86627307d28acd1ae
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// Bit-equality pin for s197: `build_init_from_flat` is the thirteenth
7// per-kind arm inside `build_expr_from_flat`. InitExpr flat encoding
8// (flat.v:1962) is (.expr_init, pos, -1, -1, 0, 0,
9// [edge0=typ, edge1..n=aux_field_init]). The cursor port decodes the type and
10// every field value via `decode_expr` (unavoidable: build_init_expr resolves
11// the type through ast_type_to_ssa and recursively builds FieldInit.value),
12// then constructs ast.InitExpr{typ, fields, pos} and dispatches to existing
13// build_init_expr.
14module ssa
15
16import v2.ast
17import v2.types
18
19// Fixture: `struct Point { x int y int } fn make_point() Point {
20// return Point{x: 1, y: 2} }`. Exercises named struct-literal field init in
21// declaration order without needing array/map literal lowering.
22fn make_init_fixture() []ast.File {
23 return [
24 ast.File{
25 name: 'main.v'
26 mod: 'main'
27 stmts: [
28 ast.Stmt(ast.ModuleStmt{
29 name: 'main'
30 }),
31 ast.Stmt(ast.StructDecl{
32 name: 'Point'
33 fields: [
34 ast.FieldDecl{
35 name: 'x'
36 typ: ast.Expr(ast.Ident{
37 name: 'int'
38 })
39 },
40 ast.FieldDecl{
41 name: 'y'
42 typ: ast.Expr(ast.Ident{
43 name: 'int'
44 })
45 },
46 ]
47 }),
48 ast.Stmt(ast.FnDecl{
49 name: 'make_point'
50 typ: ast.FnType{
51 return_type: ast.Expr(ast.Ident{
52 name: 'Point'
53 })
54 }
55 stmts: [
56 ast.Stmt(ast.ReturnStmt{
57 exprs: [
58 ast.Expr(ast.InitExpr{
59 typ: ast.Expr(ast.Ident{
60 name: 'Point'
61 })
62 fields: [
63 ast.FieldInit{
64 name: 'x'
65 value: ast.Expr(ast.BasicLiteral{
66 kind: .number
67 value: '1'
68 })
69 },
70 ast.FieldInit{
71 name: 'y'
72 value: ast.Expr(ast.BasicLiteral{
73 kind: .number
74 value: '2'
75 })
76 },
77 ]
78 }),
79 ]
80 }),
81 ]
82 }),
83 ]
84 },
85 ]
86}
87
88fn build_via_legacy_init(files []ast.File, env &types.Environment, name string) &Module {
89 mut mod := Module.new(name)
90 mut b := Builder.new_with_env(mod, env)
91 b.register_types_pass1(files[0])
92 b.register_types_pass2(files[0])
93 b.register_fn_signatures(files[0])
94 b.build_fn_bodies(files[0])
95 return mod
96}
97
98fn build_via_flat_init(files []ast.File, env &types.Environment, name string) &Module {
99 flat := ast.flatten_files(files)
100 fc := flat.file_cursor(0)
101 mut mod := Module.new(name)
102 mut b := Builder.new_with_env(mod, env)
103 b.register_types_pass1_from_flat(fc)
104 b.register_types_pass2_from_flat(fc)
105 b.register_fn_signatures_from_flat(fc)
106 stmts := fc.stmts()
107 for si in 0 .. stmts.len() {
108 c := stmts.at(si)
109 if c.kind() != .stmt_fn_decl {
110 continue
111 }
112 decl := c.fn_decl_signature()
113 fn_name := b.mangle_fn_name(decl)
114 func_idx := b.fn_index[fn_name] or { continue }
115 b.cur_func = func_idx
116 b.label_blocks = map[string]BlockID{}
117 b.vars = map[string]ValueID{}
118 entry := mod.add_block(func_idx, 'entry')
119 b.cur_block = entry
120 body := c.list_at(3)
121 for bi in 0 .. body.len() {
122 stmt_c := body.at(bi)
123 if stmt_c.kind() == .stmt_return {
124 ret_expr_c := stmt_c.edge(0)
125 val := b.build_expr_from_flat(ret_expr_c)
126 mod.add_instr(.ret, b.cur_block, 0, [val])
127 } else {
128 b.build_stmt_from_flat(stmt_c)
129 }
130 }
131 if !b.block_has_terminator(b.cur_block) {
132 mod.add_instr(.ret, b.cur_block, 0, []ValueID{})
133 }
134 }
135 return mod
136}
137
138fn test_build_init_from_flat_matches_legacy() {
139 files := make_init_fixture()
140 env := types.Environment.new()
141 mod_legacy := build_via_legacy_init(files, env, 'init_legacy')
142 mod_flat := build_via_flat_init(files, env, 'init_flat')
143
144 assert mod_legacy.funcs.len == mod_flat.funcs.len
145 assert mod_legacy.blocks.len == mod_flat.blocks.len
146 assert mod_legacy.instrs.len == mod_flat.instrs.len
147 assert mod_legacy.values.len == mod_flat.values.len
148}
149