v / vlib / v2 / ssa / register_consts_and_globals_from_flat_test.v
113 lines · 101 sloc · 3.42 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// Bit-equality pin for s171: `register_consts_and_globals_from_flat`
7// (flat-cursor port) must register the same globals + const_values as the
8// legacy `register_consts_and_globals`. The flat port walks one file's
9// top-level stmts via FileCursor and only rehydrates `.stmt_const_decl` /
10// `.stmt_global_decl` nodes via `flat.decode_stmt`. ModuleStmt, FnDecl,
11// StructDecl, EnumDecl, TypeDecl, ImportStmt etc. are never decoded.
12module ssa
13
14import v2.ast
15import v2.types
16
17fn make_consts_and_globals_fixture() []ast.File {
18 return [
19 ast.File{
20 name: 'main.v'
21 mod: 'main'
22 stmts: [
23 ast.Stmt(ast.ModuleStmt{
24 name: 'main'
25 }),
26 ast.Stmt(ast.ConstDecl{
27 fields: [
28 ast.FieldInit{
29 name: 'answer'
30 value: ast.Expr(ast.BasicLiteral{
31 kind: .number
32 value: '42'
33 })
34 },
35 ]
36 }),
37 ast.Stmt(ast.GlobalDecl{
38 fields: [
39 ast.FieldDecl{
40 name: 'g_counter'
41 typ: ast.Expr(ast.Ident{
42 name: 'int'
43 })
44 value: ast.Expr(ast.BasicLiteral{
45 kind: .number
46 value: '7'
47 })
48 },
49 ]
50 }),
51 ]
52 },
53 ]
54}
55
56// register_consts_and_globals_from_flat on a file with no const/global decls
57// must produce zero new entries — same as register_consts_and_globals.
58fn test_register_consts_and_globals_from_flat_empty_file_matches_legacy() {
59 files := [
60 ast.File{
61 name: 'empty.v'
62 mod: 'main'
63 stmts: [ast.Stmt(ast.ModuleStmt{
64 name: 'main'
65 })]
66 },
67 ]
68 flat := ast.flatten_files(files)
69
70 env := types.Environment.new()
71
72 mut mod_legacy := Module.new('cg_empty_legacy')
73 mut b_legacy := Builder.new_with_env(mod_legacy, env)
74 b_legacy.register_consts_and_globals(files[0])
75
76 mut mod_flat := Module.new('cg_empty_flat')
77 mut b_flat := Builder.new_with_env(mod_flat, env)
78 b_flat.register_consts_and_globals_from_flat(flat.file_cursor(0))
79
80 // No const/global decls -> no new globals on either side.
81 assert mod_legacy.globals.len == mod_flat.globals.len
82 assert b_legacy.const_values.len == b_flat.const_values.len
83}
84
85// register_consts_and_globals_from_flat on a file with one ConstDecl + one
86// GlobalDecl must register identical entries via both code paths.
87fn test_register_consts_and_globals_from_flat_matches_legacy_for_consts_and_globals() {
88 files := make_consts_and_globals_fixture()
89 flat := ast.flatten_files(files)
90
91 env := types.Environment.new()
92
93 mut mod_legacy := Module.new('cg_mix_legacy')
94 mut b_legacy := Builder.new_with_env(mod_legacy, env)
95 b_legacy.register_consts_and_globals(files[0])
96
97 mut mod_flat := Module.new('cg_mix_flat')
98 mut b_flat := Builder.new_with_env(mod_flat, env)
99 b_flat.register_consts_and_globals_from_flat(flat.file_cursor(0))
100
101 // Both paths registered one const + one global => 2 globals each.
102 assert mod_legacy.globals.len == mod_flat.globals.len
103 assert mod_legacy.globals.len == 2
104 for i in 0 .. mod_legacy.globals.len {
105 assert mod_legacy.globals[i].name == mod_flat.globals[i].name
106 }
107 // const_values map must match for the answer constant.
108 assert b_legacy.const_values.len == b_flat.const_values.len
109 assert 'answer' in b_legacy.const_values
110 assert 'answer' in b_flat.const_values
111 assert b_legacy.const_values['answer'] == b_flat.const_values['answer']
112 assert b_legacy.const_values['answer'] == 42
113}
114