From e3649ec4d35e2fc201310b7faaa0e522af12d3e7 Mon Sep 17 00:00:00 2001 From: spaceface Date: Mon, 15 Feb 2021 14:29:44 +0100 Subject: [PATCH] all: implement `type_name()` for interfaces too (#8767) --- vlib/v/checker/checker.v | 2 +- vlib/v/gen/c/cgen.v | 11 ++++++++++- vlib/v/gen/c/fn.v | 6 ++++++ vlib/v/parser/struct.v | 4 ++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2a9d238e55..61bd07d1ad 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1356,7 +1356,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type { c.error('optional type cannot be called directly', call_expr.left.position()) return table.void_type } - if left_type_sym.kind == .sum_type && method_name == 'type_name' { + if left_type_sym.kind in [.sum_type, .interface_] && method_name == 'type_name' { return table.string_type } mut has_generic_generic := false // x.foo() instead of x.foo() diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 649393a562..f2f5c211ae 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -484,7 +484,7 @@ pub fn (mut g Gen) finish() { pub fn (mut g Gen) write_typeof_functions() { g.writeln('') - g.writeln('// >> typeof() support for sum types') + g.writeln('// >> typeof() support for sum types / interfaces') for typ in g.table.types { if typ.kind == .sum_type { sum_info := typ.info as table.SumType @@ -508,6 +508,15 @@ pub fn (mut g Gen) write_typeof_functions() { g.writeln('\t}') } g.writeln('}') + } else if typ.kind == .interface_ { + inter_info := typ.info as table.Interface + g.writeln('static char * v_typeof_interface_${typ.cname}(int sidx) { /* $typ.name */ ') + for t in inter_info.types { + subtype := g.table.get_type_symbol(t) + g.writeln('\tif (sidx == _${typ.cname}_${subtype.cname}_index) return "${util.strip_main_name(subtype.name)}";') + } + g.writeln('\treturn "unknown ${util.strip_main_name(typ.name)}";') + g.writeln('}') } } g.writeln('// << typeof() support for sum types') diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 59964fce9a..3d6737a104 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -537,6 +537,12 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.write(').typ ))') return } + if left_sym.kind == .interface_ && node.name == 'type_name' { + g.write('tos3( /* $left_sym.name */ v_typeof_interface_${typ_sym.cname}( (') + g.expr(node.left) + g.write(')._interface_idx ))') + return + } if node.name == 'str' { g.gen_str_for_type(node.receiver_type) } diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index ae27b96d65..981e9b4727 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -475,6 +475,10 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { method_start_pos := p.tok.position() line_nr := p.tok.line_nr name := p.check_name() + if name == 'type_name' { + p.error_with_pos('cannot override built-in method `type_name`', method_start_pos) + return ast.InterfaceDecl{} + } if ts.has_method(name) { p.error_with_pos('duplicate method `$name`', method_start_pos) return ast.InterfaceDecl{}