From f1f9e423c3f236ec21af0d8abc258f0efcb67622 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 25 Apr 2020 08:00:28 +0200 Subject: [PATCH] interfaces: preparatory fixes --- cmd/tools/vtest-fixed.v | 1 + vlib/v/gen/cgen.v | 116 ++++++++++++++++++++++++---------- vlib/v/gen/fn.v | 2 +- vlib/v/parser/struct.v | 9 +-- vlib/v/table/atypes.v | 8 ++- vlib/v/table/table.v | 18 ++++-- vlib/v/tests/interface_test.v | 4 +- 7 files changed, 109 insertions(+), 49 deletions(-) diff --git a/cmd/tools/vtest-fixed.v b/cmd/tools/vtest-fixed.v index 6e037e962f..aca809d767 100644 --- a/cmd/tools/vtest-fixed.v +++ b/cmd/tools/vtest-fixed.v @@ -18,6 +18,7 @@ const ( 'vlib/v/tests/pointers_test.v', 'vlib/v/tests/string_interpolation_variadic_test.v', 'vlib/v/tests/type_test.v', + 'vlib/v/tests/interface_test.v', 'vlib/v/tests/valgrind/valgrind_test.v', // ubuntu-musl only 'vlib/v/tests/pointers_str_test.v', 'vlib/net/http/cookie_test.v', diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index b43e7441e1..32017a07fe 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -153,11 +153,11 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string } // g.finish() - return g.hashes() + g.comptime_defines.str() + '\n// V typedefs:\n' + g.typedefs.str() + '\n// V typedefs2:\n' + g.typedefs2.str() + - '\n// V cheaders:\n' + g.cheaders.str() + '\n// V includes:\n' + g.includes.str() + '\n// V definitions:\n' + - g.definitions.str() + g.interface_table() + '\n// V gowrappers:\n' + g.gowrappers.str() + '\n// V stringliterals:\n' + - g.stringliterals.str() + '\n// V auto str functions:\n' + g.auto_str_funcs.str() + '\n// V out\n' + - g.out.str() + '\n// THE END.' + return g.hashes() + g.comptime_defines.str() + '\n// V typedefs:\n' + g.typedefs.str() + + '\n// V typedefs2:\n' + g.typedefs2.str() + '\n// V cheaders:\n' + g.cheaders.str() + '\n// V includes:\n' + + g.includes.str() + '\n// V definitions:\n' + g.definitions.str() + g.interface_table() + '\n// V gowrappers:\n' + + g.gowrappers.str() + '\n// V stringliterals:\n' + g.stringliterals.str() + '\n// V auto str functions:\n' + + g.auto_str_funcs.str() + '\n// V out\n' + g.out.str() + '\n// THE END.' } pub fn (g Gen) hashes() string { @@ -189,7 +189,6 @@ pub fn (mut g Gen) init() { if g.pref.build_mode != .build_module { g.stringliterals.writeln('void vinit_string_literals(){') } - if g.pref.compile_defines_all.len > 0 { g.comptime_defines.writeln('// V compile time defines by -d or -define flags:') g.comptime_defines.writeln('// All custom defines : ' + g.pref.compile_defines_all.join(',')) @@ -2313,7 +2312,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.write('%"PRId64"') } else if node.expr_types[i] == table.u64_type { g.write('%"PRIu64"') - } else if g.typ( node.expr_types[i] ).starts_with('Option') { + } else if g.typ(node.expr_types[i]).starts_with('Option') { g.write('%.*s') } else { g.write('%"PRId32"') @@ -2405,7 +2404,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.write('${str_fn_name}(') g.expr(expr) g.write(',0).str') - } else if g.typ( node.expr_types[i] ).starts_with('Option') { + } else if g.typ(node.expr_types[i]).starts_with('Option') { str_fn_name := 'Option_str' g.write('${str_fn_name}(*(Option*)&') g.expr(expr) @@ -2560,34 +2559,84 @@ fn op_to_fn_name(name string) string { fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) string { match name { // platforms/os-es: - 'windows' { return '_WIN32' } - 'mac' { return '__APPLE__' } - 'macos' { return '__APPLE__' } - 'linux' { return '__linux__' } - 'freebsd' { return '__FreeBSD__' } - 'openbsd' { return '__OpenBSD__' } - 'netbsd' { return '__NetBSD__' } - 'dragonfly' { return '__DragonFly__' } - 'android' { return '__ANDROID__' } - 'solaris' { return '__sun' } - 'haiku' { return '__haiku__' } - 'linux_or_macos' { return '' } + 'windows' { + return '_WIN32' + } + 'mac' { + return '__APPLE__' + } + 'macos' { + return '__APPLE__' + } + 'linux' { + return '__linux__' + } + 'freebsd' { + return '__FreeBSD__' + } + 'openbsd' { + return '__OpenBSD__' + } + 'netbsd' { + return '__NetBSD__' + } + 'dragonfly' { + return '__DragonFly__' + } + 'android' { + return '__ANDROID__' + } + 'solaris' { + return '__sun' + } + 'haiku' { + return '__haiku__' + } + 'linux_or_macos' { + return '' + } // - 'js' { return '_VJS' } + 'js' { + return '_VJS' + } // compilers: - 'tinyc' { return '__TINYC__' } - 'clang' { return '__clang__' } - 'mingw' { return '__MINGW32__' } - 'msvc' { return '_MSC_VER' } + 'tinyc' { + return '__TINYC__' + } + 'clang' { + return '__clang__' + } + 'mingw' { + return '__MINGW32__' + } + 'msvc' { + return '_MSC_VER' + } // other: - 'debug' { return '_VDEBUG' } - 'glibc' { return '__GLIBC__' } - 'prealloc' { return 'VPREALLOC' } - 'no_bounds_checking' { return 'CUSTOM_DEFINE_no_bounds_checking' } - 'x64' { return 'TARGET_IS_64BIT' } - 'x32' { return 'TARGET_IS_32BIT' } - 'little_endian' { return 'TARGET_ORDER_IS_LITTLE' } - 'big_endian' { return 'TARGET_ORDER_IS_BIG' } + 'debug' { + return '_VDEBUG' + } + 'glibc' { + return '__GLIBC__' + } + 'prealloc' { + return 'VPREALLOC' + } + 'no_bounds_checking' { + return 'CUSTOM_DEFINE_no_bounds_checking' + } + 'x64' { + return 'TARGET_IS_64BIT' + } + 'x32' { + return 'TARGET_IS_32BIT' + } + 'little_endian' { + return 'TARGET_ORDER_IS_LITTLE' + } + 'big_endian' { + return 'TARGET_ORDER_IS_BIG' + } else { if is_comptime_optional || g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all { return 'CUSTOM_DEFINE_${name}' @@ -3129,6 +3178,7 @@ fn (v &Gen) interface_table() string { continue } info := t.info as table.Interface + println(info.gen_types) // interface_name is for example Speaker interface_name := t.name mut methods := '' diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 793ac7eb86..c95bd75afe 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -203,7 +203,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.expr(node.left) g.write('._interface_idx][1]))(') g.expr(node.left) - g.writeln('._object );') + g.write('._object)') return } // rec_sym := g.table.get_type_symbol(node.receiver_type) diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 0e8cedef33..c69328a9ac 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -226,14 +226,15 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { } p.next() // `interface` interface_name := p.check_name() - //println('interface decl $interface_name') + // println('interface decl $interface_name') p.check(.lcbr) // Declare the type t := table.TypeSymbol{ kind: .interface_ name: interface_name - info: table.Struct{ - //is_interface: true + info: table.Interface{ + gen_types: [] + foo: 'foo' } } typ := p.table.register_type_symbol(t) @@ -260,7 +261,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { method.return_type = p.parse_type() } methods << method - //println('register method $name') + // println('register method $name') ts.register_method(table.Fn{ name: name args: args diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index 8d80a4a325..656f1ab721 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -214,9 +214,10 @@ pub const ( pub const ( builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16' - 'u32', 'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', - 'array_fixed', 'map' - 'struct', 'mapnode', 'size_t'] + 'u32' + 'u64', 'f32', 'f64', 'string', 'ustring', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed' + 'map', 'struct' + 'mapnode', 'size_t'] ) pub struct MultiReturn { @@ -499,6 +500,7 @@ pub mut: pub struct Interface { gen_types []string + foo string } pub struct Enum { diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index b05b1ee5fa..514ceeb5ec 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -119,13 +119,11 @@ pub fn (s &TypeSymbol) has_field(name string) bool { pub fn (s &TypeSymbol) find_field(name string) ?Field { match s.info { - Struct { - for field in it.fields { + Struct { for field in it.fields { if field.name == name { return field } - } - } + } } else {} } return none @@ -390,7 +388,7 @@ pub fn (mut t Table) find_or_register_multi_return(mr_typs []Type) int { return t.register_type_symbol(mr_type) } -pub fn (mut t Table) find_or_register_fn_type(f Fn, is_anon bool, has_decl bool) int { +pub fn (mut t Table) find_or_register_fn_type(f Fn, is_anon, has_decl bool) int { name := if f.name.len == 0 { 'anon_fn_$f.signature()' } else { f.name } return t.register_type_symbol(TypeSymbol{ kind: .function @@ -485,6 +483,16 @@ pub fn (t &Table) check(got, expected Type) bool { // # NOTE: use symbols from this point on for perf got_type_sym := t.get_type_symbol(got) exp_type_sym := t.get_type_symbol(expected) + // + if exp_type_sym.kind == .interface_ { + info := got_type_sym.info as Interface + println('gen_types before') + println(info.gen_types) + info.gen_types << got_type_sym.name + println('adding gen_type $got_type_sym.name') + println(info.gen_types) + return true + } // allow enum value to be used as int if (got_type_sym.is_int() && exp_type_sym.kind == .enum_) || (exp_type_sym.is_int() && got_type_sym.kind == .enum_) { diff --git a/vlib/v/tests/interface_test.v b/vlib/v/tests/interface_test.v index 6e69ad5c9e..0a365e9bb1 100644 --- a/vlib/v/tests/interface_test.v +++ b/vlib/v/tests/interface_test.v @@ -33,15 +33,14 @@ interface Speaker { speak() } -/* fn perform_speak(s Speaker) { s.speak() assert true /* name := s.name() assert name == 'Dog' || name == 'Cat' - println(s.name()) */ + println(s.name()) } fn test_perform_speak() { @@ -56,7 +55,6 @@ fn test_perform_speak() { } */ } -*/ /* interface Speak2er {