diff --git a/compiler/comptime.v b/compiler/comptime.v index 2d7937b1f7..fe32c1a4c1 100644 --- a/compiler/comptime.v +++ b/compiler/comptime.v @@ -224,30 +224,22 @@ fn (p mut Parser) comptime_method_call(typ Type) { } fn (p mut Parser) gen_array_str(typ Type) { - //println('gen array str "$typ.name"') - p.table.add_method(typ.name, Fn{ - name: 'str', + p.add_method(typ.name, Fn{ + name: 'str' typ: 'string' args: [Var{typ: typ.name, is_arg:true}] is_method: true is_public: true receiver_typ: typ.name }) - /* - tt := p.table.find_type(typ.name) - for m in tt.methods { - println(m.name + ' ' + m.typ) - } - */ - t := typ.name - elm_type := t.right(6) + elm_type := typ.name.right(6) elm_type2 := p.table.find_type(elm_type) if p.typ_to_fmt(elm_type, 0) == '' && !p.table.type_has_method(elm_type2, 'str') { p.error('cant print ${elm_type}[], unhandled print of ${elm_type}') } p.cgen.fns << ' -string ${t}_str($t a) { +string ${typ.name}_str($typ.name a) { strings__Builder sb = strings__new_builder(a.len * 3); strings__Builder_write(&sb, tos2("[")) ; for (int i = 0; i < a.len; i++) { diff --git a/compiler/fn.v b/compiler/fn.v index 6cb0f2c944..676b4d8366 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -368,7 +368,7 @@ fn (p mut Parser) fn_decl() { } p.table.register_type2(receiver_t) } - p.table.add_method(receiver_t.name, f) + p.add_method(receiver_t.name, f) } else { // println('register_fn typ=$typ isg=$is_generic') diff --git a/compiler/gen_c.v b/compiler/gen_c.v index c7698a143c..3585fd88d4 100644 --- a/compiler/gen_c.v +++ b/compiler/gen_c.v @@ -37,7 +37,7 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string { p.statements() p.genln('$typ $name = *($typ*) $tmp . data;') if !p.returns && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break { - p.error('`or` block must return/continue/break/panic') + p.error('`or` block must return/exit/continue/break/panic') } p.returns = false return typ @@ -150,7 +150,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string { name = name.replace('-', 'minus') } // Avoid name conflicts (with things like abs(), print() etc). - // Generate b_abs(), b_print() + // Generate v_abs(), v_print() // TODO duplicate functionality if f.mod == 'builtin' && f.name in CReserved { return 'v_$name' diff --git a/compiler/parser.v b/compiler/parser.v index 0c4d41a1ac..35c682cfa0 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -626,7 +626,7 @@ fn (p mut Parser) struct_decl() { if is_interface { f := p.interface_method(field_name, name) if p.first_pass() { - p.table.add_method(typ.name, f) + p.add_method(typ.name, f) } continue } @@ -1771,7 +1771,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string { //println('ORM dot $str_typ') //} p.check(.dot) - typ := p.find_type(str_typ) + mut typ := p.find_type(str_typ) if typ.name.len == 0 { p.error('dot(): cannot find type `$str_typ`') } @@ -1781,7 +1781,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string { } field_name := p.lit p.fgen(field_name) - p.log('dot() field_name=$field_name typ=$str_typ') + //p.log('dot() field_name=$field_name typ=$str_typ') //if p.fileis('main.v') { //println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}') //} @@ -1795,7 +1795,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string { if !typ.is_c && !p.is_c_fn_call && !has_field && !has_method && !p.first_pass() { if typ.name.starts_with('Option_') { opt_type := typ.name.right(7) - p.error('unhandled option type: $opt_type?') + p.error('unhandled option type: `?$opt_type`') } //println('error in dot():') //println('fields:') @@ -1850,7 +1850,10 @@ struct $f.parent_fn { return field.typ } // method - method := p.table.find_method(typ, field_name) + method := p.table.find_method(typ, field_name) or { + p.error('could not find method `$field_name`') // should never happen + exit(1) + } p.fn_call(method, method_ph, '', str_typ) // Methods returning `array` should return `array_string` if method.typ == 'array' && typ.name.starts_with('array_') { @@ -3543,7 +3546,7 @@ fn (p mut Parser) go_statement() { p.next() p.check(.dot) typ := p.table.find_type(v.typ) - method := p.table.find_method(typ, p.lit) + method := p.table.find_method(typ, p.lit) or { panic('go method') } p.async_fn_call(method, 0, var_name, v.typ) } // Normal function diff --git a/compiler/table.v b/compiler/table.v index 1219065749..4fbcb1a656 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -438,29 +438,38 @@ fn (table &Table) find_field(typ &Type, name string) ?Var { return none } -fn (table mut Table) add_method(type_name string, f Fn) { +fn (p mut Parser) add_method(type_name string, f Fn) { + if !p.first_pass() && f.name != 'str' { + return + } if type_name == '' { print_backtrace() cerror('add_method: empty type') } // TODO table.typesmap[type_name].methods << f - mut t := table.typesmap[type_name] + mut t := p.table.typesmap[type_name] + if type_name == 'str' { + println(t.methods.len) + } + t.methods << f - table.typesmap[type_name] = t + if type_name == 'str' { + println(t.methods.len) + } + p.table.typesmap[type_name] = t } fn (t &Type) has_method(name string) bool { - method := t.find_method(name) - return (method.name != '') + _ := t.find_method(name) or { return false } + return true } fn (table &Table) type_has_method(typ &Type, name string) bool { - method := table.find_method(typ, name) - return (method.name != '') + _ := table.find_method(typ, name) or { return false } + return true } -// TODO use `?Fn` -fn (table &Table) find_method(typ &Type, name string) Fn { +fn (table &Table) find_method(typ &Type, name string) ?Fn { t := table.typesmap[typ.name] for method in t.methods { if method.name == name { @@ -469,12 +478,17 @@ fn (table &Table) find_method(typ &Type, name string) Fn { } if typ.parent != '' { parent := table.find_type(typ.parent) - return parent.find_method(name) + for method in parent.methods { + if method.name == name { + return method + } + } + return none } - return Fn{} + return none } -fn (t &Type) find_method(name string) Fn { +fn (t &Type) find_method(name string) ?Fn { // println('$t.name find_method($name) methods.len=$t.methods.len') for method in t.methods { // println('method=$method.name') @@ -482,9 +496,7 @@ fn (t &Type) find_method(name string) Fn { return method } } - //println('ret Fn{}') - return Fn{} - //return none + return none } /* @@ -512,6 +524,7 @@ fn (t &Table) find_type(name_ string) Type { name = name.left(name.len - 1) } if !(name in t.typesmap) { + //println('ret Type') return Type{} } return t.typesmap[name] @@ -520,7 +533,7 @@ fn (t &Table) find_type(name_ string) Type { fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool { mut got := got_ mut expected := expected_ - p.log('check types got="$got" exp="$expected" ') + //p.log('check types got="$got" exp="$expected" ') if p.pref.translated { return true } diff --git a/compiler/tests/str_gen_test.v b/compiler/tests/str_gen_test.v index 8e83c485dd..200796a9ed 100644 --- a/compiler/tests/str_gen_test.v +++ b/compiler/tests/str_gen_test.v @@ -7,7 +7,7 @@ fn test_array_str() { println(f) //s := f.str() //println(s) - n := [i64(1), 2, 3] + n := [1, 2, 3] assert n.str() == '[1, 2, 3]' println(n) // make sure the array is printable n2 := [4,5,6] diff --git a/september.plan b/september.plan index ddafbb633e..b04d7e3d88 100644 --- a/september.plan +++ b/september.plan @@ -9,6 +9,7 @@ + fix non-ascii rendering in gg (ä, å, etc) - cache all tokens once - enable vfmt +- bring back vdoc and regenerate all module docs - optimize the parser (reduce map lookups) - cache vlib (right now it's re-compiled every time) - fix openssl on older linux distros @@ -31,4 +32,6 @@ + o(log n) type lookup - prebuilt binaries for all platforms - fix interfaces +- `none` keyword for optionals +- table: migrate all find*** functions to optionals