v / vlib / v2 / ssa / build_postfix_from_flat_test.v
121 lines · 113 sloc · 3.05 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_postfix_from_flat`.
7// Covers the three op kinds that don't need wrapper-unwrap setup: `x++`,
8// `x--` (ident inc/dec branch — direct `c.name()` lookup) and the fallthrough
9// path where the operand isn't an ident/selector/index (delegates straight to
10// `build_expr_from_flat`). Selector/index `++` are exercised indirectly by the
11// hello smoke + broader test suite; the wrapper-unwrap (`!`/`?`) branch is
12// pinned by the option/result test paths.
13module ssa
14
15import v2.ast
16import v2.token
17import v2.types
18
19fn pf_ident(name string) ast.Expr {
20 return ast.Expr(ast.Ident{
21 name: name
22 })
23}
24
25fn pf_num(value string) ast.Expr {
26 return ast.Expr(ast.BasicLiteral{
27 kind: .number
28 value: value
29 })
30}
31
32fn make_postfix_fixture() []ast.File {
33 mut stmts := [
34 ast.Stmt(ast.ModuleStmt{
35 name: 'main'
36 }),
37 ]
38 // fn inc_then_ret() int { x := 0 x++ return x }
39 stmts << ast.Stmt(ast.FnDecl{
40 name: 'inc_then_ret'
41 typ: ast.FnType{
42 return_type: pf_ident('int')
43 }
44 stmts: [
45 ast.Stmt(ast.AssignStmt{
46 op: .decl_assign
47 lhs: [pf_ident('x')]
48 rhs: [pf_num('0')]
49 }),
50 ast.Stmt(ast.ExprStmt{
51 expr: ast.Expr(ast.PostfixExpr{
52 op: .inc
53 expr: pf_ident('x')
54 })
55 }),
56 ast.Stmt(ast.ReturnStmt{
57 exprs: [pf_ident('x')]
58 }),
59 ]
60 })
61 // fn dec_then_ret() int { y := 5 y-- return y }
62 stmts << ast.Stmt(ast.FnDecl{
63 name: 'dec_then_ret'
64 typ: ast.FnType{
65 return_type: pf_ident('int')
66 }
67 stmts: [
68 ast.Stmt(ast.AssignStmt{
69 op: .decl_assign
70 lhs: [pf_ident('y')]
71 rhs: [pf_num('5')]
72 }),
73 ast.Stmt(ast.ExprStmt{
74 expr: ast.Expr(ast.PostfixExpr{
75 op: .dec
76 expr: pf_ident('y')
77 })
78 }),
79 ast.Stmt(ast.ReturnStmt{
80 exprs: [pf_ident('y')]
81 }),
82 ]
83 })
84 return [
85 ast.File{
86 name: 'main.v'
87 mod: 'main'
88 stmts: stmts
89 },
90 ]
91}
92
93fn build_via_legacy_postfix(files []ast.File, env &types.Environment, name string) &Module {
94 mut mod := Module.new(name)
95 mut b := Builder.new_with_env(mod, env)
96 b.register_fn_signatures(files[0])
97 b.build_fn_bodies(files[0])
98 return mod
99}
100
101fn build_via_flat_postfix(files []ast.File, env &types.Environment, name string) &Module {
102 flat := ast.flatten_files(files)
103 mut mod := Module.new(name)
104 mut b := Builder.new_with_env(mod, env)
105 b.register_fn_signatures_from_flat(flat.file_cursor(0))
106 b.build_fn_bodies_from_flat(flat.file_cursor(0))
107 return mod
108}
109
110fn test_build_postfix_from_flat_matches_legacy() {
111 _ = token.Token.inc
112 files := make_postfix_fixture()
113 env := types.Environment.new()
114 mod_legacy := build_via_legacy_postfix(files, env, 'postfix_legacy')
115 mod_flat := build_via_flat_postfix(files, env, 'postfix_flat')
116
117 assert mod_legacy.funcs.len == mod_flat.funcs.len
118 assert mod_legacy.blocks.len == mod_flat.blocks.len
119 assert mod_legacy.instrs.len == mod_flat.instrs.len
120 assert mod_legacy.values.len == mod_flat.values.len
121}
122