| 1 | import os |
| 2 | import v3.flat |
| 3 | import v3.parser |
| 4 | import v3.pref |
| 5 | import v3.transform |
| 6 | import v3.types |
| 7 | |
| 8 | // parse_transform_source reads parse transform source input for v3 tests. |
| 9 | fn parse_transform_source(source string) &flat.FlatAst { |
| 10 | src := os.join_path(os.temp_dir(), 'v3_transformer_parity_test.v') |
| 11 | return parse_transform_file(src, source) |
| 12 | } |
| 13 | |
| 14 | // parse_transform_file reads parse transform file input for v3 tests. |
| 15 | fn parse_transform_file(src string, source string) &flat.FlatAst { |
| 16 | os.write_file(src, source) or { panic(err) } |
| 17 | prefs := pref.new_preferences() |
| 18 | mut p := parser.Parser.new(prefs) |
| 19 | mut a := p.parse_file(src) |
| 20 | mut tc := types.TypeChecker.new(a) |
| 21 | tc.collect(a) |
| 22 | tc.annotate_types() |
| 23 | transform.transform(mut a, &tc) |
| 24 | return a |
| 25 | } |
| 26 | |
| 27 | // find_fn resolves find fn information for v3 tests. |
| 28 | fn find_fn(a &flat.FlatAst, name string) flat.Node { |
| 29 | for node in a.nodes { |
| 30 | if node.kind == .fn_decl && node.value == name { |
| 31 | return node |
| 32 | } |
| 33 | } |
| 34 | assert false |
| 35 | return flat.Node{} |
| 36 | } |
| 37 | |
| 38 | // first_decl_rhs returns first decl rhs data for v3 tests. |
| 39 | fn first_decl_rhs(a &flat.FlatAst, fn_name string) flat.Node { |
| 40 | f := find_fn(a, fn_name) |
| 41 | for i in 0 .. f.children_count { |
| 42 | stmt := a.child_node(&f, i) |
| 43 | if stmt.kind == .decl_assign && stmt.children_count == 2 { |
| 44 | return *a.child_node(stmt, 1) |
| 45 | } |
| 46 | } |
| 47 | assert false |
| 48 | return flat.Node{} |
| 49 | } |
| 50 | |
| 51 | // decl_rhs supports decl rhs handling for v3 tests. |
| 52 | fn decl_rhs(a &flat.FlatAst, fn_name string, name string) flat.Node { |
| 53 | f := find_fn(a, fn_name) |
| 54 | for i in 0 .. f.children_count { |
| 55 | stmt := a.child_node(&f, i) |
| 56 | if stmt.kind == .decl_assign && stmt.children_count == 2 { |
| 57 | lhs := a.child_node(stmt, 0) |
| 58 | if lhs.kind == .ident && lhs.value == name { |
| 59 | return *a.child_node(stmt, 1) |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 | assert false |
| 64 | return flat.Node{} |
| 65 | } |
| 66 | |
| 67 | // first_return_expr returns first return expr data for v3 tests. |
| 68 | fn first_return_expr(a &flat.FlatAst, fn_name string) flat.Node { |
| 69 | f := find_fn(a, fn_name) |
| 70 | for i in 0 .. f.children_count { |
| 71 | stmt := a.child_node(&f, i) |
| 72 | if stmt.kind == .return_stmt && stmt.children_count > 0 { |
| 73 | return *a.child_node(stmt, 0) |
| 74 | } |
| 75 | } |
| 76 | assert false |
| 77 | return flat.Node{} |
| 78 | } |
| 79 | |
| 80 | // count_kind supports count kind handling for v3 tests. |
| 81 | fn count_kind(a &flat.FlatAst, id flat.NodeId, kind flat.NodeKind) int { |
| 82 | if int(id) < 0 { |
| 83 | return 0 |
| 84 | } |
| 85 | node := a.nodes[int(id)] |
| 86 | mut total := if node.kind == kind { 1 } else { 0 } |
| 87 | for i in 0 .. node.children_count { |
| 88 | total += count_kind(a, a.child(&node, i), kind) |
| 89 | } |
| 90 | return total |
| 91 | } |
| 92 | |
| 93 | // count_call_name supports count call name handling for v3 tests. |
| 94 | fn count_call_name(a &flat.FlatAst, id flat.NodeId, name string) int { |
| 95 | if int(id) < 0 { |
| 96 | return 0 |
| 97 | } |
| 98 | node := a.nodes[int(id)] |
| 99 | mut total := 0 |
| 100 | if node.kind == .call && node.children_count > 0 { |
| 101 | fn_node := a.child_node(&node, 0) |
| 102 | if fn_node.kind == .ident && fn_node.value == name { |
| 103 | total++ |
| 104 | } |
| 105 | } |
| 106 | for i in 0 .. node.children_count { |
| 107 | total += count_call_name(a, a.child(&node, i), name) |
| 108 | } |
| 109 | return total |
| 110 | } |
| 111 | |
| 112 | // count_infix_op supports count infix op handling for v3 tests. |
| 113 | fn count_infix_op(a &flat.FlatAst, id flat.NodeId, op flat.Op) int { |
| 114 | if int(id) < 0 { |
| 115 | return 0 |
| 116 | } |
| 117 | node := a.nodes[int(id)] |
| 118 | mut total := if node.kind == .infix && node.op == op { 1 } else { 0 } |
| 119 | for i in 0 .. node.children_count { |
| 120 | total += count_infix_op(a, a.child(&node, i), op) |
| 121 | } |
| 122 | return total |
| 123 | } |
| 124 | |
| 125 | // count_wide_decl_assigns supports count wide decl assigns handling for v3 tests. |
| 126 | fn count_wide_decl_assigns(a &flat.FlatAst, id flat.NodeId) int { |
| 127 | if int(id) < 0 { |
| 128 | return 0 |
| 129 | } |
| 130 | node := a.nodes[int(id)] |
| 131 | mut total := if node.kind == .decl_assign && node.children_count > 2 { 1 } else { 0 } |
| 132 | for i in 0 .. node.children_count { |
| 133 | total += count_wide_decl_assigns(a, a.child(&node, i)) |
| 134 | } |
| 135 | return total |
| 136 | } |
| 137 | |
| 138 | // count_wide_assigns supports count wide assigns handling for v3 tests. |
| 139 | fn count_wide_assigns(a &flat.FlatAst, id flat.NodeId) int { |
| 140 | if int(id) < 0 { |
| 141 | return 0 |
| 142 | } |
| 143 | node := a.nodes[int(id)] |
| 144 | mut total := if node.kind == .assign && node.children_count > 2 { 1 } else { 0 } |
| 145 | for i in 0 .. node.children_count { |
| 146 | total += count_wide_assigns(a, a.child(&node, i)) |
| 147 | } |
| 148 | return total |
| 149 | } |
| 150 | |
| 151 | // count_selector_value supports count selector value handling for v3 tests. |
| 152 | fn count_selector_value(a &flat.FlatAst, id flat.NodeId, value string) int { |
| 153 | if int(id) < 0 { |
| 154 | return 0 |
| 155 | } |
| 156 | node := a.nodes[int(id)] |
| 157 | mut total := if node.kind == .selector && node.value == value { 1 } else { 0 } |
| 158 | for i in 0 .. node.children_count { |
| 159 | total += count_selector_value(a, a.child(&node, i), value) |
| 160 | } |
| 161 | return total |
| 162 | } |
| 163 | |
| 164 | // test_typeof_expression_lowers_to_string_literal validates this v3 regression case. |
| 165 | fn test_typeof_expression_lowers_to_string_literal() { |
| 166 | a := parse_transform_source(' |
| 167 | fn main() { |
| 168 | name := typeof(123) |
| 169 | } |
| 170 | ') |
| 171 | main_fn := find_fn(a, 'main') |
| 172 | for i in 0 .. main_fn.children_count { |
| 173 | stmt := a.child_node(&main_fn, i) |
| 174 | if stmt.kind == .decl_assign && stmt.children_count == 2 { |
| 175 | rhs := a.child_node(stmt, 1) |
| 176 | assert rhs.kind == .string_literal |
| 177 | assert rhs.value == 'int literal' |
| 178 | return |
| 179 | } |
| 180 | } |
| 181 | assert false |
| 182 | } |
| 183 | |
| 184 | // test_vmodroot_lowers_to_nearest_vmod_dir validates this v3 regression case. |
| 185 | fn test_vmodroot_lowers_to_nearest_vmod_dir() { |
| 186 | root := os.join_path(os.temp_dir(), 'v3_vmodroot_transformer_parity') |
| 187 | os.mkdir_all(root) or { panic(err) } |
| 188 | os.write_file(os.join_path(root, 'v.mod'), 'Module { name: "parity" }') or { panic(err) } |
| 189 | src := os.join_path(root, 'main.v') |
| 190 | a := parse_transform_file(src, ' |
| 191 | fn main() { |
| 192 | root := @VMODROOT |
| 193 | } |
| 194 | ') |
| 195 | rhs := first_decl_rhs(a, 'main') |
| 196 | assert rhs.kind == .string_literal |
| 197 | assert rhs.value == root |
| 198 | } |
| 199 | |
| 200 | // test_return_match_lowers_to_explicit_branch_returns validates this v3 regression case. |
| 201 | fn test_return_match_lowers_to_explicit_branch_returns() { |
| 202 | a := parse_transform_source(' |
| 203 | fn choose(x int) int { |
| 204 | return match x { |
| 205 | 0 { |
| 206 | 10 |
| 207 | } |
| 208 | else { |
| 209 | 20 |
| 210 | } |
| 211 | } |
| 212 | } |
| 213 | ') |
| 214 | choose_fn := find_fn(a, 'choose') |
| 215 | mut match_count := 0 |
| 216 | mut return_count := 0 |
| 217 | for i in 0 .. choose_fn.children_count { |
| 218 | child_id := a.child(&choose_fn, i) |
| 219 | match_count += count_kind(a, child_id, .match_stmt) |
| 220 | return_count += count_kind(a, child_id, .return_stmt) |
| 221 | } |
| 222 | assert match_count == 0 |
| 223 | assert return_count == 2 |
| 224 | } |
| 225 | |
| 226 | // test_return_if_keeps_or_lowering_inside_branch validates this v3 regression case. |
| 227 | fn test_return_if_keeps_or_lowering_inside_branch() { |
| 228 | a := parse_transform_source(' |
| 229 | fn maybe_int() ?int { |
| 230 | return 8 |
| 231 | } |
| 232 | |
| 233 | fn choose(flag bool) int { |
| 234 | return if flag { |
| 235 | maybe_int() or { |
| 236 | 1 |
| 237 | } |
| 238 | } else { |
| 239 | 2 |
| 240 | } |
| 241 | } |
| 242 | ') |
| 243 | choose_fn := find_fn(a, 'choose') |
| 244 | mut body_ids := []flat.NodeId{} |
| 245 | for i in 0 .. choose_fn.children_count { |
| 246 | child_id := a.child(&choose_fn, i) |
| 247 | child := a.nodes[int(child_id)] |
| 248 | if child.kind != .param { |
| 249 | body_ids << child_id |
| 250 | } |
| 251 | } |
| 252 | assert body_ids.len == 1 |
| 253 | assert a.nodes[int(body_ids[0])].kind == .if_expr |
| 254 | } |
| 255 | |
| 256 | // test_if_expr_value_lowers_to_temp_and_branch_assigns validates this v3 regression case. |
| 257 | fn test_if_expr_value_lowers_to_temp_and_branch_assigns() { |
| 258 | a := parse_transform_source(' |
| 259 | fn main() { |
| 260 | x := if true { |
| 261 | 1 |
| 262 | } else { |
| 263 | 2 |
| 264 | } |
| 265 | } |
| 266 | ') |
| 267 | rhs := decl_rhs(a, 'main', 'x') |
| 268 | assert rhs.kind == .ident |
| 269 | assert rhs.value.starts_with('__if_val_') |
| 270 | main_fn := find_fn(a, 'main') |
| 271 | mut if_count := 0 |
| 272 | mut assign_count := 0 |
| 273 | for i in 0 .. main_fn.children_count { |
| 274 | child_id := a.child(&main_fn, i) |
| 275 | if_count += count_kind(a, child_id, .if_expr) |
| 276 | assign_count += count_kind(a, child_id, .assign) |
| 277 | } |
| 278 | assert if_count == 1 |
| 279 | assert assign_count == 2 |
| 280 | } |
| 281 | |
| 282 | // test_if_expr_call_arg_lowers_before_call validates this v3 regression case. |
| 283 | fn test_if_expr_call_arg_lowers_before_call() { |
| 284 | a := parse_transform_source(' |
| 285 | fn use(x int) int { |
| 286 | return x |
| 287 | } |
| 288 | |
| 289 | fn main() { |
| 290 | x := use(if true { 1 } else { 2 }) |
| 291 | } |
| 292 | ') |
| 293 | rhs := decl_rhs(a, 'main', 'x') |
| 294 | assert rhs.kind == .call |
| 295 | assert rhs.children_count == 2 |
| 296 | arg := a.child_node(&rhs, 1) |
| 297 | assert arg.kind == .ident |
| 298 | assert arg.value.starts_with('__if_val_') |
| 299 | } |
| 300 | |
| 301 | // test_nested_if_expr_branch_lowers_to_outer_temp_assignment validates this v3 regression case. |
| 302 | fn test_nested_if_expr_branch_lowers_to_outer_temp_assignment() { |
| 303 | a := parse_transform_source(' |
| 304 | fn main() { |
| 305 | x := if true { |
| 306 | if false { |
| 307 | 1 |
| 308 | } else { |
| 309 | 2 |
| 310 | } |
| 311 | } else { |
| 312 | 3 |
| 313 | } |
| 314 | } |
| 315 | ') |
| 316 | rhs := decl_rhs(a, 'main', 'x') |
| 317 | assert rhs.kind == .ident |
| 318 | assert rhs.value.starts_with('__if_val_') |
| 319 | main_fn := find_fn(a, 'main') |
| 320 | mut if_count := 0 |
| 321 | mut assign_count := 0 |
| 322 | for i in 0 .. main_fn.children_count { |
| 323 | child_id := a.child(&main_fn, i) |
| 324 | if_count += count_kind(a, child_id, .if_expr) |
| 325 | assign_count += count_kind(a, child_id, .assign) |
| 326 | } |
| 327 | assert if_count == 2 |
| 328 | assert assign_count == 4 |
| 329 | } |
| 330 | |
| 331 | // test_multi_return_decl_lowers_to_temp_field_decls validates this v3 regression case. |
| 332 | fn test_multi_return_decl_lowers_to_temp_field_decls() { |
| 333 | a := parse_transform_source(" |
| 334 | fn pair() (int, string) { |
| 335 | return 1, 'ok' |
| 336 | } |
| 337 | |
| 338 | fn main() { |
| 339 | a, b := pair() |
| 340 | } |
| 341 | ") |
| 342 | main_fn := find_fn(a, 'main') |
| 343 | mut wide_decl_count := 0 |
| 344 | for i in 0 .. main_fn.children_count { |
| 345 | wide_decl_count += count_wide_decl_assigns(a, a.child(&main_fn, i)) |
| 346 | } |
| 347 | assert wide_decl_count == 0 |
| 348 | a_rhs := decl_rhs(a, 'main', 'a') |
| 349 | b_rhs := decl_rhs(a, 'main', 'b') |
| 350 | assert a_rhs.kind == .selector |
| 351 | assert a_rhs.value == 'arg0' |
| 352 | assert b_rhs.kind == .selector |
| 353 | assert b_rhs.value == 'arg1' |
| 354 | } |
| 355 | |
| 356 | // test_multi_return_assign_lowers_to_temp_field_assigns validates this v3 regression case. |
| 357 | fn test_multi_return_assign_lowers_to_temp_field_assigns() { |
| 358 | a := parse_transform_source(" |
| 359 | fn pair() (int, string) { |
| 360 | return 1, 'ok' |
| 361 | } |
| 362 | |
| 363 | fn main() { |
| 364 | mut a := 0 |
| 365 | mut b := '' |
| 366 | a, b = pair() |
| 367 | } |
| 368 | ") |
| 369 | main_fn := find_fn(a, 'main') |
| 370 | mut wide_assign_count := 0 |
| 371 | mut arg0_count := 0 |
| 372 | mut arg1_count := 0 |
| 373 | for i in 0 .. main_fn.children_count { |
| 374 | child_id := a.child(&main_fn, i) |
| 375 | wide_assign_count += count_wide_assigns(a, child_id) |
| 376 | arg0_count += count_selector_value(a, child_id, 'arg0') |
| 377 | arg1_count += count_selector_value(a, child_id, 'arg1') |
| 378 | } |
| 379 | assert wide_assign_count == 0 |
| 380 | assert arg0_count == 1 |
| 381 | assert arg1_count == 1 |
| 382 | } |
| 383 | |
| 384 | // test_assoc_expr_lowers_to_temp_and_field_assigns validates this v3 regression case. |
| 385 | fn test_assoc_expr_lowers_to_temp_and_field_assigns() { |
| 386 | a := parse_transform_source(' |
| 387 | struct Point { |
| 388 | x int |
| 389 | y int |
| 390 | } |
| 391 | |
| 392 | fn main() { |
| 393 | p := Point{x: 1, y: 2} |
| 394 | q := Point{...p, y: 3} |
| 395 | } |
| 396 | ') |
| 397 | rhs := decl_rhs(a, 'main', 'q') |
| 398 | assert rhs.kind == .ident |
| 399 | assert rhs.value.starts_with('__assoc_') |
| 400 | main_fn := find_fn(a, 'main') |
| 401 | mut assoc_count := 0 |
| 402 | mut assign_count := 0 |
| 403 | for i in 0 .. main_fn.children_count { |
| 404 | child_id := a.child(&main_fn, i) |
| 405 | assoc_count += count_kind(a, child_id, .assoc) |
| 406 | assign_count += count_kind(a, child_id, .assign) |
| 407 | } |
| 408 | assert assoc_count == 0 |
| 409 | assert assign_count == 1 |
| 410 | } |
| 411 | |
| 412 | // test_return_assoc_expr_lowers_before_return validates this v3 regression case. |
| 413 | fn test_return_assoc_expr_lowers_before_return() { |
| 414 | a := parse_transform_source(' |
| 415 | struct Point { |
| 416 | x int |
| 417 | y int |
| 418 | } |
| 419 | |
| 420 | fn moved(p Point) Point { |
| 421 | return Point{...p, x: 4} |
| 422 | } |
| 423 | ') |
| 424 | ret := first_return_expr(a, 'moved') |
| 425 | assert ret.kind == .ident |
| 426 | assert ret.value.starts_with('__assoc_') |
| 427 | moved_fn := find_fn(a, 'moved') |
| 428 | mut assoc_count := 0 |
| 429 | for i in 0 .. moved_fn.children_count { |
| 430 | assoc_count += count_kind(a, a.child(&moved_fn, i), .assoc) |
| 431 | } |
| 432 | assert assoc_count == 0 |
| 433 | } |
| 434 | |
| 435 | // test_array_append_stmt_lowers_to_runtime_push validates this v3 regression case. |
| 436 | fn test_array_append_stmt_lowers_to_runtime_push() { |
| 437 | a := parse_transform_source(' |
| 438 | fn main() { |
| 439 | mut xs := []int{} |
| 440 | xs << 3 |
| 441 | } |
| 442 | ') |
| 443 | main_fn := find_fn(a, 'main') |
| 444 | mut push_count := 0 |
| 445 | mut left_shift_count := 0 |
| 446 | for i in 0 .. main_fn.children_count { |
| 447 | child_id := a.child(&main_fn, i) |
| 448 | push_count += count_call_name(a, child_id, 'array_push') |
| 449 | left_shift_count += count_infix_op(a, child_id, .left_shift) |
| 450 | } |
| 451 | assert push_count == 1 |
| 452 | assert left_shift_count == 0 |
| 453 | } |
| 454 | |
| 455 | // test_array_append_many_stmt_lowers_to_runtime_push_many validates this v3 regression case. |
| 456 | fn test_array_append_many_stmt_lowers_to_runtime_push_many() { |
| 457 | a := parse_transform_source(' |
| 458 | fn main() { |
| 459 | mut xs := []int{} |
| 460 | ys := []int{} |
| 461 | xs << ys |
| 462 | } |
| 463 | ') |
| 464 | main_fn := find_fn(a, 'main') |
| 465 | mut push_many_count := 0 |
| 466 | mut left_shift_count := 0 |
| 467 | for i in 0 .. main_fn.children_count { |
| 468 | child_id := a.child(&main_fn, i) |
| 469 | push_many_count += count_call_name(a, child_id, 'array__push_many') |
| 470 | left_shift_count += count_infix_op(a, child_id, .left_shift) |
| 471 | } |
| 472 | assert push_many_count == 1 |
| 473 | assert left_shift_count == 0 |
| 474 | } |
| 475 | |
| 476 | fn test_array_push_many_method_lowers_to_runtime_ptr_call() { |
| 477 | a := parse_transform_source(' |
| 478 | fn main() { |
| 479 | mut xs := []u8{} |
| 480 | mut b := u8(7) |
| 481 | unsafe { |
| 482 | xs.push_many(&b, 1) |
| 483 | } |
| 484 | } |
| 485 | ') |
| 486 | main_fn := find_fn(a, 'main') |
| 487 | mut push_many_ptr_count := 0 |
| 488 | mut push_many_selector_count := 0 |
| 489 | for i in 0 .. main_fn.children_count { |
| 490 | child_id := a.child(&main_fn, i) |
| 491 | push_many_ptr_count += count_call_name(a, child_id, 'array_push_many_ptr') |
| 492 | push_many_selector_count += count_selector_value(a, child_id, 'push_many') |
| 493 | } |
| 494 | assert push_many_ptr_count == 1 |
| 495 | assert push_many_selector_count == 0 |
| 496 | } |
| 497 | |
| 498 | fn test_array_push_many_type_marker_lowers_to_runtime_ptr_call() { |
| 499 | a := parse_transform_source(' |
| 500 | struct PushManyItem { |
| 501 | value int |
| 502 | } |
| 503 | |
| 504 | fn main() { |
| 505 | mut xs := []PushManyItem{} |
| 506 | item := PushManyItem{value: 7} |
| 507 | xs.push_many(item, PushManyItem) |
| 508 | } |
| 509 | ') |
| 510 | main_fn := find_fn(a, 'main') |
| 511 | mut push_many_ptr_count := 0 |
| 512 | mut push_many_selector_count := 0 |
| 513 | for i in 0 .. main_fn.children_count { |
| 514 | child_id := a.child(&main_fn, i) |
| 515 | push_many_ptr_count += count_call_name(a, child_id, 'array_push_many_ptr') |
| 516 | push_many_selector_count += count_selector_value(a, child_id, 'push_many') |
| 517 | } |
| 518 | assert push_many_ptr_count == 1 |
| 519 | assert push_many_selector_count == 0 |
| 520 | } |
| 521 | |
| 522 | fn test_sql_expr_lowers_to_success_result_default() { |
| 523 | a := parse_transform_source(' |
| 524 | struct User { |
| 525 | id int |
| 526 | } |
| 527 | |
| 528 | fn main() { |
| 529 | db := 0 |
| 530 | users := sql db { |
| 531 | select from User |
| 532 | } |
| 533 | count := sql db { |
| 534 | select count from User |
| 535 | } |
| 536 | created := sql db { |
| 537 | create table User |
| 538 | } |
| 539 | } |
| 540 | ') |
| 541 | main_fn := find_fn(a, 'main') |
| 542 | mut sql_expr_count := 0 |
| 543 | for i in 0 .. main_fn.children_count { |
| 544 | sql_expr_count += count_kind(a, a.child(&main_fn, i), .sql_expr) |
| 545 | } |
| 546 | assert sql_expr_count == 0 |
| 547 | users := decl_rhs(a, 'main', 'users') |
| 548 | assert users.kind == .struct_init |
| 549 | assert users.value == '![]User' |
| 550 | count := decl_rhs(a, 'main', 'count') |
| 551 | assert count.kind == .struct_init |
| 552 | assert count.value == '!int' |
| 553 | created := decl_rhs(a, 'main', 'created') |
| 554 | assert created.kind == .struct_init |
| 555 | assert created.value == '!void' |
| 556 | } |
| 557 | |
| 558 | // test_or_expr_lowers_to_temp_and_if validates this v3 regression case. |
| 559 | fn test_or_expr_lowers_to_temp_and_if() { |
| 560 | a := parse_transform_source(' |
| 561 | fn maybe_int() ?int { |
| 562 | return 3 |
| 563 | } |
| 564 | |
| 565 | fn main() { |
| 566 | x := maybe_int() or { |
| 567 | 7 |
| 568 | } |
| 569 | } |
| 570 | ') |
| 571 | main_fn := find_fn(a, 'main') |
| 572 | mut or_count := 0 |
| 573 | mut if_count := 0 |
| 574 | for i in 0 .. main_fn.children_count { |
| 575 | child_id := a.child(&main_fn, i) |
| 576 | or_count += count_kind(a, child_id, .or_expr) |
| 577 | if_count += count_kind(a, child_id, .if_expr) |
| 578 | } |
| 579 | assert or_count == 0 |
| 580 | assert if_count == 1 |
| 581 | } |
| 582 | |
| 583 | // test_map_index_or_lowers_to_get_check validates this v3 regression case. |
| 584 | fn test_map_index_or_lowers_to_get_check() { |
| 585 | a := parse_transform_source(' |
| 586 | fn main() { |
| 587 | mut m := map[string]int{} |
| 588 | x := m["a"] or { |
| 589 | 7 |
| 590 | } |
| 591 | } |
| 592 | ') |
| 593 | main_fn := find_fn(a, 'main') |
| 594 | mut or_count := 0 |
| 595 | mut get_check_count := 0 |
| 596 | for i in 0 .. main_fn.children_count { |
| 597 | child_id := a.child(&main_fn, i) |
| 598 | or_count += count_kind(a, child_id, .or_expr) |
| 599 | get_check_count += count_call_name(a, child_id, 'map__get_check') |
| 600 | } |
| 601 | assert or_count == 0 |
| 602 | assert get_check_count == 1 |
| 603 | } |
| 604 | |