v / vlib / v2 / transformer / inject_generated_fns_to_flat_test.v
127 lines · 115 sloc · 4.39 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 the third flat-aware post_pass port (s153):
7// `inject_generated_fns_to_flat` must produce a FlatAst whose
8// `signature()` matches what `inject_generated_fns_to_files` (the
9// extracted legacy splice) + `flatten_files` produces. Each bucket
10// (core_fns / module_fns[mod] / user_fns) is exercised in isolation
11// against a single-file fixture — the multi-file intern-order quirk
12// (same as s151/s152) makes multi-file signature comparison brittle, so
13// we test the routing fallbacks of each bucket independently.
14module transformer
15
16import v2.ast
17import v2.pref as vpref
18import v2.types
19
20// Local helper — `v test` compiles each `_test.v` file in isolation, so
21// `create_test_transformer` from `transformer_test.v` is not visible here.
22fn create_generated_fns_to_flat_test_transformer() &Transformer {
23 env := &types.Environment{}
24 return &Transformer{
25 pref: &vpref.Preferences{}
26 env: unsafe { env }
27 needed_clone_fns: map[string]string{}
28 needed_array_contains_fns: map[string]ArrayMethodInfo{}
29 needed_array_index_fns: map[string]ArrayMethodInfo{}
30 needed_array_last_index_fns: map[string]ArrayMethodInfo{}
31 local_decl_types: map[string]types.Type{}
32 }
33}
34
35fn make_file_for_mod(mod string) ast.File {
36 return ast.File{
37 name: '${mod}_min.v'
38 mod: mod
39 stmts: [
40 ast.Stmt(ast.ModuleStmt{
41 name: mod
42 }),
43 ]
44 }
45}
46
47fn make_fn_decl(name string) ast.Stmt {
48 return ast.Stmt(ast.FnDecl{
49 name: name
50 })
51}
52
53// Bucket 1: core_fns → builtin file.
54fn test_inject_generated_fns_to_flat_core_fns_into_builtin() {
55 parts := GeneratedFnsParts{
56 core_fns: [make_fn_decl('int_str'), make_fn_decl('f64_str')]
57 module_fns: map[string][]ast.Stmt{}
58 user_fns: []ast.Stmt{}
59 }
60 mut ref_files := [make_file_for_mod('builtin')]
61 inject_generated_fns_to_files(mut ref_files, parts)
62 ref_sig := ast.flatten_files(ref_files).signature()
63
64 mut b := ast.new_flat_builder()
65 b.append_file(make_file_for_mod('builtin'))
66 mut t := create_generated_fns_to_flat_test_transformer()
67 t.inject_generated_fns_to_flat(mut b, parts)
68 assert b.flat.signature() == ref_sig
69}
70
71// Bucket 2: module_fns[mod] → mod file.
72fn test_inject_generated_fns_to_flat_module_fns_into_mod() {
73 mut module_fns := map[string][]ast.Stmt{}
74 module_fns['time'] = [make_fn_decl('time__FormatDate__str')]
75 parts := GeneratedFnsParts{
76 core_fns: []ast.Stmt{}
77 module_fns: module_fns
78 user_fns: []ast.Stmt{}
79 }
80 mut ref_files := [make_file_for_mod('time')]
81 inject_generated_fns_to_files(mut ref_files, parts)
82 ref_sig := ast.flatten_files(ref_files).signature()
83
84 mut b := ast.new_flat_builder()
85 b.append_file(make_file_for_mod('time'))
86 mut t := create_generated_fns_to_flat_test_transformer()
87 t.inject_generated_fns_to_flat(mut b, parts)
88 assert b.flat.signature() == ref_sig
89}
90
91// Bucket 3: user_fns → main file.
92fn test_inject_generated_fns_to_flat_user_fns_into_main() {
93 parts := GeneratedFnsParts{
94 core_fns: []ast.Stmt{}
95 module_fns: map[string][]ast.Stmt{}
96 user_fns: [make_fn_decl('Array_Test2_str'), make_fn_decl('Map_int_string_str')]
97 }
98 mut ref_files := [make_file_for_mod('main')]
99 inject_generated_fns_to_files(mut ref_files, parts)
100 ref_sig := ast.flatten_files(ref_files).signature()
101
102 mut b := ast.new_flat_builder()
103 b.append_file(make_file_for_mod('main'))
104 mut t := create_generated_fns_to_flat_test_transformer()
105 t.inject_generated_fns_to_flat(mut b, parts)
106 assert b.flat.signature() == ref_sig
107}
108
109// Fallback: core_fns lands in user_fns when no builtin file exists.
110// With a single main file, user_fns → main → both legacy and flat-aware
111// should splice core_fns into main via the user_fns route.
112fn test_inject_generated_fns_to_flat_core_fns_fallback_no_builtin() {
113 parts := GeneratedFnsParts{
114 core_fns: [make_fn_decl('int_str')]
115 module_fns: map[string][]ast.Stmt{}
116 user_fns: []ast.Stmt{}
117 }
118 mut ref_files := [make_file_for_mod('main')]
119 inject_generated_fns_to_files(mut ref_files, parts)
120 ref_sig := ast.flatten_files(ref_files).signature()
121
122 mut b := ast.new_flat_builder()
123 b.append_file(make_file_for_mod('main'))
124 mut t := create_generated_fns_to_flat_test_transformer()
125 t.inject_generated_fns_to_flat(mut b, parts)
126 assert b.flat.signature() == ref_sig
127}
128