From 5d3d14da538401aa669adc21985c484f3bdd4bba Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 30 Aug 2020 07:56:18 +0100 Subject: [PATCH] cgen: support `typeof(expr).name` (#6253) --- vlib/v/checker/checker.v | 8 ++++++++ vlib/v/gen/cgen.v | 21 +++++++++++++++++++++ vlib/v/tests/typeof_test.v | 13 ++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 029ec9da22..53b9c96111 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1474,6 +1474,14 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T c.error('unknown selector expression', selector_expr.pos) return table.void_type } + if selector_expr.expr is ast.TypeOf as left { + if selector_expr.field_name == 'name' { + return table.string_type + } else { + c.error('expected `.name`, not `.$selector_expr.field_name` after `typeof` expression', + selector_expr.pos) + } + } selector_expr.expr_type = typ sym := c.table.get_type_symbol(c.unwrap_generic(typ)) field_name := selector_expr.field_name diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index db6e53c836..c743153178 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2102,6 +2102,11 @@ fn (mut g Gen) expr(node ast.Expr) { g.struct_init(node) } ast.SelectorExpr { + if node.expr is ast.TypeOf as left { + // typeof(expr).name + g.typeof_name(left) + return + } sym := g.table.get_type_symbol(node.expr_type) if sym.kind == .array_fixed { assert node.field_name == 'len' @@ -2157,6 +2162,22 @@ fn (mut g Gen) expr(node ast.Expr) { } } +// typeof(expr).name +fn (mut g Gen) typeof_name(node ast.TypeOf) { + sym := g.table.get_type_symbol(node.expr_type) + if sym.kind == .array { + info := sym.info as table.Array + mut s := g.table.get_type_name(info.elem_type) + s = util.strip_main_name(s) + g.write('tos_lit("[]$s")') + } else if sym.kind == .sum_type { + // new typeof() must be known at compile-time + g.write('tos_lit("${util.strip_main_name(sym.name)}")') + } else { + g.typeof_expr(node) + } +} + fn (mut g Gen) typeof_expr(node ast.TypeOf) { sym := g.table.get_type_symbol(node.expr_type) if sym.kind == .sum_type { diff --git a/vlib/v/tests/typeof_test.v b/vlib/v/tests/typeof_test.v index 6a1b3a76c3..5870b426f7 100644 --- a/vlib/v/tests/typeof_test.v +++ b/vlib/v/tests/typeof_test.v @@ -6,6 +6,7 @@ fn test_typeof_on_simple_expressions() { assert typeof(f64(1.0) * 12.2) == 'f64' // assert typeof(1.0 * f32(12.2)) == 'f32' assert typeof(a) == 'int' + assert typeof(a).name == 'int' // a2 := 123 // assert typeof(a2) == 'any_int' // assert typeof(42) == 'any_int' @@ -19,6 +20,7 @@ fn test_typeof_on_atypes() { astring := []string{} assert typeof(aint) == 'array_int' assert typeof(astring) == 'array_string' + assert typeof(astring).name == '[]string' } struct FooBar { @@ -27,10 +29,12 @@ struct FooBar { fn test_typeof_on_structs() { assert typeof(FooBar{}) == 'FooBar' - astruct_static := [2]FooBar + astruct_static := [2]FooBar{} astruct_dynamic := [FooBar{}, FooBar{}] assert typeof(astruct_static) == '[2]FooBar' + assert typeof(astruct_static).name == '[2]FooBar' assert typeof(astruct_dynamic) == 'array_FooBar' + assert typeof(astruct_dynamic).name == '[]FooBar' } type MySumType = int | f32 | FooBar @@ -51,6 +55,9 @@ fn test_typeof_on_sumtypes() { assert typeof(a) == 'int' assert typeof(b) == 'f32' assert typeof(c) == 'FooBar' + assert typeof(a).name == 'MySumType' + assert typeof(b).name == 'MySumType' + assert typeof(c).name == 'MySumType' } // @@ -96,4 +103,8 @@ fn test_typeof_on_fn() { assert typeof(myfn2) == 'fn ()' assert typeof(myfn3) == 'fn (int, string) byte' assert typeof(myfn4) == 'fn () i8' + assert typeof(myfn).name == typeof(myfn) + assert typeof(myfn2).name == typeof(myfn2) + assert typeof(myfn3).name == typeof(myfn3) + assert typeof(myfn4).name == typeof(myfn4) }