@@ -378,6 +378,32 @@ fn (mut g Gen) comptime_if(node ast.IfExpr) {
378
378
}
379
379
}
380
380
381
+ fn (mut g Gen) get_expr_type (cond ast.Expr) ast.Type {
382
+ match cond {
383
+ ast.Ident {
384
+ return g.unwrap_generic (cond.obj.typ)
385
+ }
386
+ ast.TypeNode {
387
+ return g.unwrap_generic (cond.typ)
388
+ }
389
+ ast.SelectorExpr {
390
+ if cond.gkind_field == .typ {
391
+ return g.unwrap_generic (cond.name_type)
392
+ } else {
393
+ name := '${cond.expr} .${cond.field_name} '
394
+ if name in g.comptime_var_type_map {
395
+ return g.comptime_var_type_map[name]
396
+ } else {
397
+ return g.unwrap_generic (cond.typ)
398
+ }
399
+ }
400
+ }
401
+ else {
402
+ return ast.void_type
403
+ }
404
+ }
405
+ }
406
+
381
407
// returns the value of the bool comptime expression and if next branches may be discarded
382
408
// returning `false` means the statements inside the $if can be skipped
383
409
fn (mut g Gen) comptime_if_cond (cond ast.Expr, pkg_exist bool ) (bool , bool ) {
@@ -420,78 +446,57 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
420
446
}
421
447
.key_is, .not_is {
422
448
left := cond.left
423
- mut name := ''
424
- if left is ast.TypeNode && cond.right is ast.ComptimeType {
425
- checked_type := g.unwrap_generic (left.typ)
426
- is_true := g.table.is_comptime_type (checked_type, cond.right)
427
- if cond.op == .key_is {
428
- if is_true {
429
- g.write ('1' )
430
- } else {
431
- g.write ('0' )
432
- }
433
- return is_true, true
434
- } else {
435
- if is_true {
436
- g.write ('0' )
437
- } else {
438
- g.write ('1' )
439
- }
440
- return ! is_true, true
441
- }
442
- }
443
- mut exp_type := ast.Type (0 )
444
- got_type := (cond.right as ast.TypeNode ).typ
445
- // Handle `$if x is Interface {`
446
- // mut matches_interface := 'false'
447
- if left is ast.TypeNode && cond.right is ast.TypeNode
448
- && g.table.sym (got_type).kind == .interface_ {
449
- // `$if Foo is Interface {`
450
- interface_sym := g.table.sym (got_type)
451
- if interface_sym.info is ast.Interface {
452
- // q := g.table.sym(interface_sym.info.types[0])
453
- checked_type := g.unwrap_generic (left.typ)
454
- // TODO PERF this check is run twice (also in the checker)
455
- // store the result in a field
456
- is_true := g.table.does_type_implement_interface (checked_type,
457
- got_type)
458
- // true // exp_type in interface_sym.info.types
449
+ if left in [ast.TypeNode, ast.Ident, ast.SelectorExpr]
450
+ && cond.right in [ast.ComptimeType, ast.TypeNode] {
451
+ exp_type := g.get_expr_type (left)
452
+ if cond.right is ast.ComptimeType {
453
+ is_true := g.table.is_comptime_type (exp_type, cond.right)
459
454
if cond.op == .key_is {
460
455
if is_true {
461
456
g.write ('1' )
462
457
} else {
463
458
g.write ('0' )
464
459
}
465
460
return is_true, true
466
- } else if cond. op == .not_is {
461
+ } else {
467
462
if is_true {
468
463
g.write ('0' )
469
464
} else {
470
465
g.write ('1' )
471
466
}
472
467
return ! is_true, true
473
468
}
474
- // matches_interface = '/*iface:$got_type $exp_type*/ true'
475
- // }
476
- }
477
- } else if left is ast.SelectorExpr {
478
- if left.gkind_field == .typ {
479
- exp_type = g.unwrap_generic (left.name_type)
480
469
} else {
481
- name = '${left.expr} .${left.field_name} '
482
- exp_type = g.comptime_var_type_map[name]
483
- }
484
- } else if left is ast.TypeNode {
485
- // this is only allowed for generics currently, otherwise blocked by checker
486
- exp_type = g.unwrap_generic (left.typ)
487
- }
470
+ got_type := g.unwrap_generic ((cond.right as ast.TypeNode ).typ)
471
+ got_sym := g.table.sym (got_type)
488
472
489
- if cond.op == .key_is {
490
- g.write ('${exp_type.idx()} == ${got_type.idx()} && ${exp_type.has_flag(.option)} == ${got_type.has_flag(.option)} ' )
491
- return exp_type == got_type, true
492
- } else {
493
- g.write ('${exp_type.idx()} != ${got_type.idx()} ' )
494
- return exp_type != got_type, true
473
+ if got_sym.kind == .interface_ && got_sym.info is ast.Interface {
474
+ is_true := g.table.does_type_implement_interface (exp_type,
475
+ got_type)
476
+ if cond.op == .key_is {
477
+ if is_true {
478
+ g.write ('1' )
479
+ } else {
480
+ g.write ('0' )
481
+ }
482
+ return is_true, true
483
+ } else if cond.op == .not_is {
484
+ if is_true {
485
+ g.write ('0' )
486
+ } else {
487
+ g.write ('1' )
488
+ }
489
+ return ! is_true, true
490
+ }
491
+ }
492
+ if cond.op == .key_is {
493
+ g.write ('${exp_type.idx()} == ${got_type.idx()} && ${exp_type.has_flag(.option)} == ${got_type.has_flag(.option)} ' )
494
+ return exp_type == got_type, true
495
+ } else {
496
+ g.write ('${exp_type.idx()} != ${got_type.idx()} ' )
497
+ return exp_type != got_type, true
498
+ }
499
+ }
495
500
}
496
501
}
497
502
.eq, .ne {
@@ -523,17 +528,7 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
523
528
.key_in, .not_in {
524
529
if (cond.left is ast.TypeNode || cond.left is ast.SelectorExpr )
525
530
&& cond.right is ast.ArrayInit {
526
- mut checked_type := ast.Type (0 )
527
- if cond.left is ast.SelectorExpr {
528
- if cond.left.gkind_field == .typ {
529
- checked_type = g.unwrap_generic (cond.left.name_type)
530
- } else {
531
- name := '${cond.left.expr} .${cond.left.field_name} '
532
- checked_type = g.comptime_var_type_map[name]
533
- }
534
- } else {
535
- checked_type = g.unwrap_generic ((cond.left as ast.TypeNode ).typ)
536
- }
531
+ checked_type := g.get_expr_type (cond.left)
537
532
538
533
for expr in cond.right.exprs {
539
534
if expr is ast.ComptimeType {
@@ -767,6 +762,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
767
762
g.writeln ('\t ${node.val_var} .indirections = ${field.typ.nr_muls()} ;' )
768
763
//
769
764
g.comptime_var_type_map['${node.val_var} .typ' ] = styp
765
+ g.comptime_var_type_map['${node.val_var} .unaliased_typ' ] = unaliased_styp
770
766
g.stmts (node.stmts)
771
767
i++
772
768
g.writeln ('}' )
0 commit comments