From 788de9938ae07c94a033f33643c108dc85c4b505 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 2 Nov 2020 21:59:48 +0000 Subject: [PATCH] cgen: fix typeof(expr).name for generic type, pointers, etc (#6712) --- vlib/v/gen/cgen.v | 22 ++++++++++++---------- vlib/v/tests/typeof_test.v | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 773ae27119..cb85cdf33d 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2386,17 +2386,19 @@ 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 { + mut typ := node.expr_type + if typ.has_flag(.generic) { + typ = g.cur_generic_type + } + sym := g.table.get_type_symbol(typ) + // TODO: fix table.type_to_str and use instead + if sym.kind == .function { g.typeof_expr(node) + } else { + // Note: typeof() must be known at compile-time + // sum types should not be handled dynamically + s := g.table.type_to_str(typ) + g.write('tos_lit("${util.strip_main_name(s)}")') } } diff --git a/vlib/v/tests/typeof_test.v b/vlib/v/tests/typeof_test.v index 5870b426f7..e314addd17 100644 --- a/vlib/v/tests/typeof_test.v +++ b/vlib/v/tests/typeof_test.v @@ -15,14 +15,24 @@ fn test_typeof_on_simple_expressions() { // assert typeof(1.0 * 12.2) == 'any_float' } -fn test_typeof_on_atypes() { +fn test_arrays() { aint := []int{} astring := []string{} assert typeof(aint) == 'array_int' assert typeof(astring) == 'array_string' + assert typeof(aint).name == '[]int' assert typeof(astring).name == '[]string' } +fn test_type_constructors() { + v := `c` + assert typeof(&v).name == '&rune' + assert typeof(&[v]).name == '&[]rune' + assert typeof([v]!!).name == '[1]rune' + assert typeof(&[v]!!).name == '&[1]rune' + assert typeof(&FooBar{}).name == '&FooBar' +} + struct FooBar { x int } @@ -55,6 +65,7 @@ fn test_typeof_on_sumtypes() { assert typeof(a) == 'int' assert typeof(b) == 'f32' assert typeof(c) == 'FooBar' + // typeof should be known at compile-time for all types assert typeof(a).name == 'MySumType' assert typeof(b).name == 'MySumType' assert typeof(c).name == 'MySumType' @@ -108,3 +119,25 @@ fn test_typeof_on_fn() { assert typeof(myfn3).name == typeof(myfn3) assert typeof(myfn4).name == typeof(myfn4) } + +fn type_name(v T) string { + return typeof(v).name +} + +fn array_item_type(v []T) string { + return typeof(v[0]).name +} + +fn test_generic_type() { + v := 5 + assert type_name(v) == 'int' + //assert type_name(&v) == '&int' + //assert type_name([v]!!) == '[1]int' + assert type_name([v]) == '[]int' + assert type_name([[v]]) == '[][]int' + assert type_name(FooBar{}) == 'FooBar' + + assert array_item_type([v]) == 'int' + assert array_item_type([[v]]) == '[]int' + //assert array_item_type([&v]) == '&int' +}