From ee53a99cddfe15a234af0a28c1ec0adfff442b29 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 9 Nov 2024 08:34:24 -0300 Subject: [PATCH] v: add `typeof(var).indirections` and `T.indirections` (#22805) --- vlib/v/ast/ast.v | 1 + vlib/v/checker/checker.v | 7 +++---- vlib/v/checker/if.v | 6 ++++++ vlib/v/gen/c/cgen.v | 12 ++++++++++++ vlib/v/gen/c/comptime.v | 2 ++ vlib/v/gen/js/js.v | 6 +++++- vlib/v/parser/parser.v | 1 + vlib/v/tests/typeof_indirections_test.v | 18 ++++++++++++++++++ 8 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/typeof_indirections_test.v diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index a3eb7fd2f..655d6c93c 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 d079301b1..573628446 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 5effb8a69..20e91c853 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 8c8276757..05d7b0c8b 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 e4db56346..2e8299e51 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/gen/js/js.v b/vlib/v/gen/js/js.v index 3f18ff6e9..3aa1cc396 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -3252,13 +3252,17 @@ fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) { g.write('new int(') g.write('${int(g.unwrap_generic(it.name_type))}') g.write(')') - g.write(')') return } .unaliased_typ { g.write('new int(') g.write('${int(g.table.unaliased_type(g.unwrap_generic(it.name_type)))}') g.write(')') + return + } + .indirections { + g.write('new int(') + g.write('${int(g.unwrap_generic(it.name_type).nr_muls())}') g.write(')') return } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d2945969c..71c39b167 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 000000000..751268ff3 --- /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 +} -- 2.39.5