v / vlib / v2 / ssa / build_block_from_flat_test.v
104 lines · 98 sloc · 3.02 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 s179: `build_block_from_flat` (fourth per-kind port
7// inside the s175 seam) must walk a `.stmt_block`'s child edges the same
8// way the legacy `ast.BlockStmt` arm forwards `stmt.stmts` to
9// `build_stmts`. The flat schema (`flat.v:1610`) stores BlockStmt's inner
10// stmts as direct child edges of the `.stmt_block` node — no aux_list
11// wrapper — so the cursor port walks them via `c.edge(i)`.
12module ssa
13
14import v2.ast
15import v2.types
16
17// Fixture: a fn with a nested BlockStmt containing a ReturnStmt(0).
18// Through `build_stmts_from_flat`, the outer body dispatches the
19// BlockStmt to `build_block_from_flat`, which then re-enters
20// `build_stmt_from_flat` for the inner ReturnStmt — exercising both the
21// new arm and dispatch through it.
22fn make_block_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.FnDecl{
32 name: 'do_block'
33 typ: ast.FnType{
34 return_type: ast.Expr(ast.Ident{
35 name: 'int'
36 })
37 }
38 stmts: [
39 ast.Stmt(ast.BlockStmt{
40 stmts: [
41 ast.Stmt(ast.ReturnStmt{
42 exprs: [
43 ast.Expr(ast.BasicLiteral{
44 kind: .number
45 value: '7'
46 }),
47 ]
48 }),
49 ]
50 }),
51 ]
52 }),
53 ]
54 },
55 ]
56}
57
58fn build_via_legacy_block(files []ast.File, env &types.Environment, name string) &Module {
59 mut mod := Module.new(name)
60 mut b := Builder.new_with_env(mod, env)
61 b.register_fn_signatures(files[0])
62 b.build_fn_bodies(files[0])
63 return mod
64}
65
66fn build_via_flat_block(files []ast.File, env &types.Environment, name string) &Module {
67 flat := ast.flatten_files(files)
68 mut mod := Module.new(name)
69 mut b := Builder.new_with_env(mod, env)
70 b.register_fn_signatures_from_flat(flat.file_cursor(0))
71 stmts := flat.file_cursor(0).stmts()
72 for si in 0 .. stmts.len() {
73 c := stmts.at(si)
74 if c.kind() != .stmt_fn_decl {
75 continue
76 }
77 decl := c.fn_decl_signature()
78 fn_name := b.mangle_fn_name(decl)
79 func_idx := b.fn_index[fn_name] or { continue }
80 b.cur_func = func_idx
81 b.label_blocks = map[string]BlockID{}
82 entry := mod.add_block(func_idx, 'entry')
83 b.cur_block = entry
84 body := c.list_at(3)
85 b.build_stmts_from_flat(body)
86 if !b.block_has_terminator(b.cur_block) {
87 mod.add_instr(.ret, b.cur_block, 0, []ValueID{})
88 }
89 }
90 return mod
91}
92
93fn test_build_block_from_flat_matches_legacy() {
94 files := make_block_fixture()
95 env := types.Environment.new()
96 mod_legacy := build_via_legacy_block(files, env, 'block_legacy')
97 mod_flat := build_via_flat_block(files, env, 'block_flat')
98
99 assert mod_legacy.funcs.len == mod_flat.funcs.len
100 assert mod_legacy.funcs.len == 1
101 assert mod_legacy.blocks.len == mod_flat.blocks.len
102 assert mod_legacy.instrs.len == mod_flat.instrs.len
103 assert mod_legacy.values.len == mod_flat.values.len
104}
105