v / vlib / v2 / transformer / fixed_array_slice_bounds_test.v
183 lines · 173 sloc · 4.64 KB · 81a5657604ec6da99c25e26546870c6888d6fdde
Raw
1module transformer
2
3import os
4import v2.ast
5import v2.parser
6import v2.pref as vpref
7import v2.token
8import v2.types
9
10fn transform_fixed_array_slice_code_for_test(code string) []ast.File {
11 tmp_file := os.join_path(os.temp_dir(), 'v2_transformer_fixed_slice_${os.getpid()}.v')
12 os.write_file(tmp_file, code) or { panic('failed to write temp file') }
13 defer {
14 os.rm(tmp_file) or {}
15 }
16 prefs := &vpref.Preferences{
17 backend: .cleanc
18 no_parallel: true
19 }
20 mut file_set := token.FileSet.new()
21 mut par := parser.Parser.new(prefs)
22 files := par.parse_files([tmp_file], mut file_set)
23 mut env := types.Environment.new()
24 mut checker := types.Checker.new(prefs, file_set, env)
25 checker.check_files(files)
26 mut transformer := Transformer.new_with_pref(env, prefs)
27 return transformer.transform_files(files)
28}
29
30fn count_fixed_slice_call_in_expr(expr ast.Expr, name string) int {
31 match expr {
32 ast.ArrayInitExpr {
33 mut count := count_fixed_slice_call_in_expr(expr.typ, name)
34 for item in expr.exprs {
35 count += count_fixed_slice_call_in_expr(item, name)
36 }
37 count += count_fixed_slice_call_in_expr(expr.init, name)
38 count += count_fixed_slice_call_in_expr(expr.cap, name)
39 count += count_fixed_slice_call_in_expr(expr.len, name)
40 count += count_fixed_slice_call_in_expr(expr.update_expr, name)
41 return count
42 }
43 ast.CallExpr {
44 mut count := if expr.lhs is ast.Ident && expr.lhs.name == name { 1 } else { 0 }
45 count += count_fixed_slice_call_in_expr(expr.lhs, name)
46 for arg in expr.args {
47 count += count_fixed_slice_call_in_expr(arg, name)
48 }
49 return count
50 }
51 ast.CastExpr {
52 return count_fixed_slice_call_in_expr(expr.typ, name) +
53 count_fixed_slice_call_in_expr(expr.expr, name)
54 }
55 ast.IndexExpr {
56 return count_fixed_slice_call_in_expr(expr.lhs, name) +
57 count_fixed_slice_call_in_expr(expr.expr, name)
58 }
59 ast.InfixExpr {
60 return count_fixed_slice_call_in_expr(expr.lhs, name) +
61 count_fixed_slice_call_in_expr(expr.rhs, name)
62 }
63 ast.InitExpr {
64 mut count := count_fixed_slice_call_in_expr(expr.typ, name)
65 for field in expr.fields {
66 count += count_fixed_slice_call_in_expr(field.value, name)
67 }
68 return count
69 }
70 ast.KeywordOperator {
71 mut count := 0
72 for value in expr.exprs {
73 count += count_fixed_slice_call_in_expr(value, name)
74 }
75 return count
76 }
77 ast.MapInitExpr {
78 mut count := count_fixed_slice_call_in_expr(expr.typ, name)
79 for key in expr.keys {
80 count += count_fixed_slice_call_in_expr(key, name)
81 }
82 for value in expr.vals {
83 count += count_fixed_slice_call_in_expr(value, name)
84 }
85 return count
86 }
87 ast.ModifierExpr {
88 return count_fixed_slice_call_in_expr(expr.expr, name)
89 }
90 ast.ParenExpr {
91 return count_fixed_slice_call_in_expr(expr.expr, name)
92 }
93 ast.PrefixExpr {
94 return count_fixed_slice_call_in_expr(expr.expr, name)
95 }
96 ast.RangeExpr {
97 return count_fixed_slice_call_in_expr(expr.start, name) +
98 count_fixed_slice_call_in_expr(expr.end, name)
99 }
100 ast.SelectorExpr {
101 return count_fixed_slice_call_in_expr(expr.lhs, name)
102 }
103 ast.Tuple {
104 mut count := 0
105 for value in expr.exprs {
106 count += count_fixed_slice_call_in_expr(value, name)
107 }
108 return count
109 }
110 ast.UnsafeExpr {
111 return count_fixed_slice_call_in_stmts(expr.stmts, name)
112 }
113 else {
114 return 0
115 }
116 }
117}
118
119fn count_fixed_slice_call_in_stmt(stmt ast.Stmt, name string) int {
120 match stmt {
121 ast.AssignStmt {
122 mut count := 0
123 for lhs in stmt.lhs {
124 count += count_fixed_slice_call_in_expr(lhs, name)
125 }
126 for rhs in stmt.rhs {
127 count += count_fixed_slice_call_in_expr(rhs, name)
128 }
129 return count
130 }
131 ast.ExprStmt {
132 return count_fixed_slice_call_in_expr(stmt.expr, name)
133 }
134 else {
135 return 0
136 }
137 }
138}
139
140fn count_fixed_slice_call_in_stmts(stmts []ast.Stmt, name string) int {
141 mut count := 0
142 for stmt in stmts {
143 count += count_fixed_slice_call_in_stmt(stmt, name)
144 }
145 return count
146}
147
148fn transformed_fixed_slice_fn(files []ast.File, name string) ?ast.FnDecl {
149 for file in files {
150 for stmt in file.stmts {
151 if stmt is ast.FnDecl && stmt.name == name {
152 return stmt
153 }
154 }
155 }
156 return none
157}
158
159fn test_fixed_array_slice_bounds_are_materialized_once() {
160 files := transform_fixed_array_slice_code_for_test('
161fn next() int {
162 return 1
163}
164
165fn stop() int {
166 return 3
167}
168
169fn main() {
170 arr := [4]int{}
171 part := arr[next()..stop()]
172 _ = part
173}
174')
175 main_decl := transformed_fixed_slice_fn(files, 'main') or {
176 assert false, 'missing transformed main'
177 return
178 }
179
180 assert count_fixed_slice_call_in_stmts(main_decl.stmts, 'next') == 1
181 assert count_fixed_slice_call_in_stmts(main_decl.stmts, 'stop') == 1
182 assert count_fixed_slice_call_in_stmts(main_decl.stmts, 'new_array_from_c_array') == 1
183}
184