diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index a3eb7fd2f16b7e..655d6c93ccf392 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -287,6 +287,7 @@ pub enum GenericKindField { name typ unaliased_typ + indirections } // `foo.bar` diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d079301b169f9b..573628446ae2f4 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1531,10 +1531,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { .name { return ast.string_type } - .unaliased_typ { - return ast.int_type - } - .typ { + .unaliased_typ, .typ, .indirections { return ast.int_type } else { @@ -1542,6 +1539,8 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { return ast.string_type } else if node.field_name == 'idx' { return ast.int_type + } else if node.field_name == 'indirections' { + return ast.int_type } c.error('invalid field `.${node.field_name}` for type `${node.expr}`', node.pos) diff --git a/vlib/v/checker/if.v b/vlib/v/checker/if.v index 5effb8a6933b1b..20e91c853453b5 100644 --- a/vlib/v/checker/if.v +++ b/vlib/v/checker/if.v @@ -268,6 +268,12 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { } } } + } else if left.expr is ast.TypeOf { + skip_state = if left.expr.typ.nr_muls() == right.val.i64() { + ComptimeBranchSkipState.eval + } else { + ComptimeBranchSkipState.skip + } } } else if branch.cond.op in [.eq, .ne] && left is ast.SelectorExpr && right is ast.StringLiteral { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 8c8276757b30e9..05d7b0c8b7fde6 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3875,6 +3875,10 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { g.write(int(g.table.unaliased_type(g.unwrap_generic(node.name_type))).str()) return } + .indirections { + g.write(int(g.unwrap_generic(node.name_type).nr_muls()).str()) + return + } .unknown { // ast.TypeOf of `typeof(string).idx` etc if node.field_name == 'name' { @@ -3893,6 +3897,14 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { // `typeof(expr).idx` g.write(int(g.unwrap_generic(name_type)).str()) return + } else if node.field_name == 'indirections' { + mut name_type := node.name_type + if node.expr is ast.TypeOf { + name_type = g.resolve_comptime_type(node.expr.expr, name_type) + } + // `typeof(expr).indirections` + g.write(int(g.unwrap_generic(name_type).nr_muls()).str()) + return } g.error('unknown generic field', node.pos) } diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index e4db56346e2718..2e8299e5135ac3 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -469,6 +469,8 @@ fn (mut g Gen) get_expr_type(cond ast.Expr) ast.Type { return g.unwrap_generic(cond.name_type) } else if cond.gkind_field == .unaliased_typ { return g.table.unaliased_type(g.unwrap_generic(cond.name_type)) + } else if cond.gkind_field == .indirections { + return ast.int_type } else { name := '${cond.expr}.${cond.field_name}' if name in g.comptime.type_map { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d2945969c78d46..71c39b16760a2e 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2923,6 +2923,7 @@ fn (mut p Parser) name_expr() ast.Expr { 'name' { ast.GenericKindField.name } 'typ' { ast.GenericKindField.typ } 'unaliased_typ' { ast.GenericKindField.unaliased_typ } + 'indirections' { ast.GenericKindField.indirections } else { ast.GenericKindField.unknown } } pos.extend(p.tok.pos()) diff --git a/vlib/v/tests/typeof_indirections_test.v b/vlib/v/tests/typeof_indirections_test.v new file mode 100644 index 00000000000000..751268ff3e2bc4 --- /dev/null +++ b/vlib/v/tests/typeof_indirections_test.v @@ -0,0 +1,18 @@ +fn indirections[T](val T) int { + return T.indirections +} + +fn test_main() { + a := 0 + assert typeof(a).indirections == 0 + assert indirections(a) == 0 + b := &a + assert typeof(b).indirections == 1 + assert indirections(b) == 1 + c := [1] + assert typeof(c).indirections == 0 + assert indirections(c) == 0 + d := &c + assert typeof(d).indirections == 1 + assert indirections(d) == 1 +}