v / vlib / v2 / ssa / build_fn_literal_from_flat_test.v
106 lines · 98 sloc · 2.91 KB · 07d7d0a475915ac672c8ed1ed3128131e29be755
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 cursor-native rewrite of `build_fn_literal_from_flat`.
7// The previous helper rehydrated the FnLiteral payload via three `decode_*`
8// rounds — `decode_expr` on the FnType edge, `decode_expr` on every captured
9// var edge, `decode_stmt` on every body-stmt edge — and dispatched to legacy
10// `build_fn_literal`. The cursor-native rewrite walks the `.typ_fn` child for
11// params + return_type, drops the captured-var rehydration entirely (legacy
12// `build_fn_literal` never reads `captured_vars`), and routes body-stmt edges
13// through `build_stmt_from_flat`. Pin asserts module-count parity for a
14// fixture that constructs an anonymous fn with one int param and an int return.
15module ssa
16
17import v2.ast
18import v2.types
19
20fn fl_ident(name string) ast.Expr {
21 return ast.Expr(ast.Ident{
22 name: name
23 })
24}
25
26fn fl_num(value string) ast.Expr {
27 return ast.Expr(ast.BasicLiteral{
28 kind: .number
29 value: value
30 })
31}
32
33fn make_fn_literal_fixture() []ast.File {
34 mut stmts := [
35 ast.Stmt(ast.ModuleStmt{
36 name: 'main'
37 }),
38 ]
39 // fn use_anon() { f := fn (n int) int { return n } }
40 stmts << ast.Stmt(ast.FnDecl{
41 name: 'use_anon'
42 typ: ast.FnType{
43 return_type: ast.empty_expr
44 }
45 stmts: [
46 ast.Stmt(ast.AssignStmt{
47 op: .decl_assign
48 lhs: [fl_ident('f')]
49 rhs: [
50 ast.Expr(ast.FnLiteral{
51 typ: ast.FnType{
52 params: [
53 ast.Parameter{
54 name: 'n'
55 typ: fl_ident('int')
56 },
57 ]
58 return_type: fl_ident('int')
59 }
60 stmts: [
61 ast.Stmt(ast.ReturnStmt{
62 exprs: [fl_ident('n')]
63 }),
64 ]
65 }),
66 ]
67 }),
68 ]
69 })
70 return [
71 ast.File{
72 name: 'main.v'
73 mod: 'main'
74 stmts: stmts
75 },
76 ]
77}
78
79fn build_via_legacy_fn_literal(files []ast.File, env &types.Environment, name string) &Module {
80 mut mod := Module.new(name)
81 mut b := Builder.new_with_env(mod, env)
82 b.register_fn_signatures(files[0])
83 b.build_fn_bodies(files[0])
84 return mod
85}
86
87fn build_via_flat_fn_literal(files []ast.File, env &types.Environment, name string) &Module {
88 flat := ast.flatten_files(files)
89 mut mod := Module.new(name)
90 mut b := Builder.new_with_env(mod, env)
91 b.register_fn_signatures_from_flat(flat.file_cursor(0))
92 b.build_fn_bodies_from_flat(flat.file_cursor(0))
93 return mod
94}
95
96fn test_build_fn_literal_from_flat_matches_legacy() {
97 files := make_fn_literal_fixture()
98 env := types.Environment.new()
99 mod_legacy := build_via_legacy_fn_literal(files, env, 'fn_literal_legacy')
100 mod_flat := build_via_flat_fn_literal(files, env, 'fn_literal_flat')
101
102 assert mod_legacy.funcs.len == mod_flat.funcs.len
103 assert mod_legacy.blocks.len == mod_flat.blocks.len
104 assert mod_legacy.instrs.len == mod_flat.instrs.len
105 assert mod_legacy.values.len == mod_flat.values.len
106}
107