v / vlib / v2 / ast / flat_field_decl_flags_test.v
222 lines · 212 sloc · 6.02 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.
4module ast
5
6import v2.token
7
8fn field_flags_ident_expr(name string) Expr {
9 return Expr(Ident{
10 name: name
11 })
12}
13
14fn field_flags_int_expr() Expr {
15 return field_flags_ident_expr('int')
16}
17
18fn make_field_flags_file() File {
19 return File{
20 name: 'field_flags.v'
21 mod: 'field_flags'
22 stmts: [
23 Stmt(ModuleStmt{
24 name: 'field_flags'
25 }),
26 Stmt(StructDecl{
27 name: 'Config'
28 fields: [
29 FieldDecl{
30 name: 'public_value'
31 typ: field_flags_int_expr()
32 is_public: true
33 },
34 FieldDecl{
35 name: 'mutable_value'
36 typ: field_flags_int_expr()
37 is_mut: true
38 },
39 FieldDecl{
40 name: 'module_mut_value'
41 typ: field_flags_int_expr()
42 is_module_mut: true
43 },
44 ]
45 }),
46 Stmt(InterfaceDecl{
47 name: 'Runner'
48 fields: [
49 FieldDecl{
50 name: 'run'
51 typ: field_flags_int_expr()
52 is_interface_method: true
53 },
54 ]
55 }),
56 ]
57 }
58}
59
60fn test_field_decl_flags_survive_flat_roundtrip() {
61 mut b := new_flat_builder()
62 b.append_file(make_field_flags_file())
63 files := b.flat.to_files()
64 assert files.len == 1
65 assert files[0].stmts.len == 3
66 assert files[0].stmts[1] is StructDecl
67 struct_decl := files[0].stmts[1] as StructDecl
68 assert struct_decl.fields.len == 3
69 assert struct_decl.fields[0].is_public
70 assert !struct_decl.fields[0].is_mut
71 assert !struct_decl.fields[0].is_module_mut
72 assert !struct_decl.fields[0].is_interface_method
73 assert !struct_decl.fields[1].is_public
74 assert struct_decl.fields[1].is_mut
75 assert !struct_decl.fields[1].is_module_mut
76 assert !struct_decl.fields[1].is_interface_method
77 assert !struct_decl.fields[2].is_public
78 assert !struct_decl.fields[2].is_mut
79 assert struct_decl.fields[2].is_module_mut
80 assert !struct_decl.fields[2].is_interface_method
81 assert files[0].stmts[2] is InterfaceDecl
82 interface_decl := files[0].stmts[2] as InterfaceDecl
83 assert interface_decl.fields.len == 1
84 assert !interface_decl.fields[0].is_public
85 assert !interface_decl.fields[0].is_mut
86 assert !interface_decl.fields[0].is_module_mut
87 assert interface_decl.fields[0].is_interface_method
88}
89
90fn test_global_decl_public_flag_survives_flat_roundtrip() {
91 mut b := new_flat_builder()
92 b.append_file(File{
93 name: 'global_decl_public.v'
94 mod: 'field_flags'
95 stmts: [
96 Stmt(ModuleStmt{
97 name: 'field_flags'
98 }),
99 Stmt(GlobalDecl{
100 is_public: true
101 fields: [
102 FieldDecl{
103 name: 'counter'
104 typ: field_flags_int_expr()
105 },
106 ]
107 }),
108 ]
109 })
110 files := b.flat.to_files()
111 assert files[0].stmts.len == 2
112 assert files[0].stmts[1] is GlobalDecl
113 global_decl := files[0].stmts[1] as GlobalDecl
114 assert global_decl.is_public
115 assert global_decl.fields.len == 1
116}
117
118fn test_emit_field_decl_by_ids_preserves_field_flags() {
119 field := FieldDecl{
120 name: 'global_counter'
121 typ: field_flags_int_expr()
122 is_public: true
123 is_mut: true
124 }
125 mut b := new_flat_builder()
126 b.append_file(File{
127 name: 'direct_field_flags.v'
128 mod: 'field_flags'
129 stmts: [
130 Stmt(ModuleStmt{
131 name: 'field_flags'
132 }),
133 ]
134 })
135 typ_id := b.emit_expr(field.typ)
136 value_id := b.emit_expr(field.value)
137 attrs_id := b.emit_attribute_list(field.attributes)
138 field_id := b.emit_field_decl_by_ids(field, typ_id, value_id, attrs_id)
139 fields_id := b.emit_aux_list_from_ids([field_id])
140 decl_attrs_id := b.emit_attribute_list([])
141 global_id := b.emit_global_decl_by_ids(true, decl_attrs_id, fields_id)
142 b.append_file_stmts(0, [global_id])
143 files := b.flat.to_files()
144 assert files[0].stmts.len == 2
145 assert files[0].stmts[1] is GlobalDecl
146 global_decl := files[0].stmts[1] as GlobalDecl
147 assert global_decl.is_public
148 assert global_decl.fields.len == 1
149 assert global_decl.fields[0].is_public
150 assert global_decl.fields[0].is_mut
151 assert !global_decl.fields[0].is_module_mut
152 assert !global_decl.fields[0].is_interface_method
153}
154
155fn field_flags_array_update_from_stmt(stmt Stmt) ArrayInitExpr {
156 assert stmt is ExprStmt
157 expr_stmt := stmt as ExprStmt
158 assert expr_stmt.expr is ArrayInitExpr
159 return expr_stmt.expr as ArrayInitExpr
160}
161
162fn test_array_init_update_expr_survives_flat_roundtrip() {
163 mut b := new_flat_builder()
164 b.append_file(File{
165 name: 'array_update_expr.v'
166 mod: 'field_flags'
167 stmts: [
168 Stmt(ModuleStmt{
169 name: 'field_flags'
170 }),
171 Stmt(ExprStmt{
172 expr: Expr(ArrayInitExpr{
173 typ: field_flags_int_expr()
174 update_expr: field_flags_ident_expr('base')
175 exprs: [
176 field_flags_ident_expr('item'),
177 ]
178 })
179 }),
180 ]
181 })
182 files := b.flat.to_files()
183 assert files[0].stmts.len == 2
184 array_expr := field_flags_array_update_from_stmt(files[0].stmts[1])
185 assert array_expr.update_expr is Ident
186 assert (array_expr.update_expr as Ident).name == 'base'
187 assert array_expr.exprs.len == 1
188 assert array_expr.exprs[0] is Ident
189 assert (array_expr.exprs[0] as Ident).name == 'item'
190}
191
192fn test_emit_array_init_expr_by_ids_preserves_update_expr() {
193 mut b := new_flat_builder()
194 b.append_file(File{
195 name: 'direct_array_update_expr.v'
196 mod: 'field_flags'
197 stmts: [
198 Stmt(ModuleStmt{
199 name: 'field_flags'
200 }),
201 ]
202 })
203 typ_id := b.emit_expr(field_flags_int_expr())
204 init_id := b.emit_expr(empty_expr)
205 cap_id := b.emit_expr(empty_expr)
206 len_id := b.emit_expr(empty_expr)
207 update_expr_id := b.emit_expr(field_flags_ident_expr('base'))
208 elem_id := b.emit_expr(field_flags_ident_expr('item'))
209 array_id := b.emit_array_init_expr_by_ids(typ_id, init_id, cap_id, len_id, update_expr_id, [
210 elem_id,
211 ], token.Pos{})
212 stmt_id := b.emit_expr_stmt_by_id(array_id)
213 b.append_file_stmts(0, [stmt_id])
214 files := b.flat.to_files()
215 assert files[0].stmts.len == 2
216 array_expr := field_flags_array_update_from_stmt(files[0].stmts[1])
217 assert array_expr.update_expr is Ident
218 assert (array_expr.update_expr as Ident).name == 'base'
219 assert array_expr.exprs.len == 1
220 assert array_expr.exprs[0] is Ident
221 assert (array_expr.exprs[0] as Ident).name == 'item'
222}
223