table: use optional in find_method()

pull/2035/head
Alexander Medvednikov 2019-09-18 15:37:34 +03:00
parent 059cb9cb74
commit 13e4c79f58
7 changed files with 49 additions and 38 deletions

View File

@ -224,30 +224,22 @@ fn (p mut Parser) comptime_method_call(typ Type) {
} }
fn (p mut Parser) gen_array_str(typ Type) { fn (p mut Parser) gen_array_str(typ Type) {
//println('gen array str "$typ.name"') p.add_method(typ.name, Fn{
p.table.add_method(typ.name, Fn{ name: 'str'
name: 'str',
typ: 'string' typ: 'string'
args: [Var{typ: typ.name, is_arg:true}] args: [Var{typ: typ.name, is_arg:true}]
is_method: true is_method: true
is_public: true is_public: true
receiver_typ: typ.name receiver_typ: typ.name
}) })
/* elm_type := typ.name.right(6)
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_type2 := p.table.find_type(elm_type) elm_type2 := p.table.find_type(elm_type)
if p.typ_to_fmt(elm_type, 0) == '' && if p.typ_to_fmt(elm_type, 0) == '' &&
!p.table.type_has_method(elm_type2, 'str') { !p.table.type_has_method(elm_type2, 'str') {
p.error('cant print ${elm_type}[], unhandled print of ${elm_type}') p.error('cant print ${elm_type}[], unhandled print of ${elm_type}')
} }
p.cgen.fns << ' 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 sb = strings__new_builder(a.len * 3);
strings__Builder_write(&sb, tos2("[")) ; strings__Builder_write(&sb, tos2("[")) ;
for (int i = 0; i < a.len; i++) { for (int i = 0; i < a.len; i++) {

View File

@ -368,7 +368,7 @@ fn (p mut Parser) fn_decl() {
} }
p.table.register_type2(receiver_t) p.table.register_type2(receiver_t)
} }
p.table.add_method(receiver_t.name, f) p.add_method(receiver_t.name, f)
} }
else { else {
// println('register_fn typ=$typ isg=$is_generic') // println('register_fn typ=$typ isg=$is_generic')

View File

@ -37,7 +37,7 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
p.statements() p.statements()
p.genln('$typ $name = *($typ*) $tmp . data;') p.genln('$typ $name = *($typ*) $tmp . data;')
if !p.returns && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break { 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 p.returns = false
return typ return typ
@ -150,7 +150,7 @@ fn (table mut Table) fn_gen_name(f &Fn) string {
name = name.replace('-', 'minus') name = name.replace('-', 'minus')
} }
// Avoid name conflicts (with things like abs(), print() etc). // Avoid name conflicts (with things like abs(), print() etc).
// Generate b_abs(), b_print() // Generate v_abs(), v_print()
// TODO duplicate functionality // TODO duplicate functionality
if f.mod == 'builtin' && f.name in CReserved { if f.mod == 'builtin' && f.name in CReserved {
return 'v_$name' return 'v_$name'

View File

@ -626,7 +626,7 @@ fn (p mut Parser) struct_decl() {
if is_interface { if is_interface {
f := p.interface_method(field_name, name) f := p.interface_method(field_name, name)
if p.first_pass() { if p.first_pass() {
p.table.add_method(typ.name, f) p.add_method(typ.name, f)
} }
continue continue
} }
@ -1771,7 +1771,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
//println('ORM dot $str_typ') //println('ORM dot $str_typ')
//} //}
p.check(.dot) p.check(.dot)
typ := p.find_type(str_typ) mut typ := p.find_type(str_typ)
if typ.name.len == 0 { if typ.name.len == 0 {
p.error('dot(): cannot find type `$str_typ`') 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 field_name := p.lit
p.fgen(field_name) 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') { //if p.fileis('main.v') {
//println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}') //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.is_c && !p.is_c_fn_call && !has_field && !has_method && !p.first_pass() {
if typ.name.starts_with('Option_') { if typ.name.starts_with('Option_') {
opt_type := typ.name.right(7) 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('error in dot():')
//println('fields:') //println('fields:')
@ -1850,7 +1850,10 @@ struct $f.parent_fn {
return field.typ return field.typ
} }
// method // 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) p.fn_call(method, method_ph, '', str_typ)
// Methods returning `array` should return `array_string` // Methods returning `array` should return `array_string`
if method.typ == 'array' && typ.name.starts_with('array_') { if method.typ == 'array' && typ.name.starts_with('array_') {
@ -3543,7 +3546,7 @@ fn (p mut Parser) go_statement() {
p.next() p.next()
p.check(.dot) p.check(.dot)
typ := p.table.find_type(v.typ) 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) p.async_fn_call(method, 0, var_name, v.typ)
} }
// Normal function // Normal function

View File

@ -438,29 +438,38 @@ fn (table &Table) find_field(typ &Type, name string) ?Var {
return none 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 == '' { if type_name == '' {
print_backtrace() print_backtrace()
cerror('add_method: empty type') cerror('add_method: empty type')
} }
// TODO table.typesmap[type_name].methods << f // 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 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 { fn (t &Type) has_method(name string) bool {
method := t.find_method(name) _ := t.find_method(name) or { return false }
return (method.name != '') return true
} }
fn (table &Table) type_has_method(typ &Type, name string) bool { fn (table &Table) type_has_method(typ &Type, name string) bool {
method := table.find_method(typ, name) _ := table.find_method(typ, name) or { return false }
return (method.name != '') 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] t := table.typesmap[typ.name]
for method in t.methods { for method in t.methods {
if method.name == name { if method.name == name {
@ -469,12 +478,17 @@ fn (table &Table) find_method(typ &Type, name string) Fn {
} }
if typ.parent != '' { if typ.parent != '' {
parent := table.find_type(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 Fn{} }
return none
}
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') // println('$t.name find_method($name) methods.len=$t.methods.len')
for method in t.methods { for method in t.methods {
// println('method=$method.name') // println('method=$method.name')
@ -482,9 +496,7 @@ fn (t &Type) find_method(name string) Fn {
return method return method
} }
} }
//println('ret Fn{}') return none
return Fn{}
//return none
} }
/* /*
@ -512,6 +524,7 @@ fn (t &Table) find_type(name_ string) Type {
name = name.left(name.len - 1) name = name.left(name.len - 1)
} }
if !(name in t.typesmap) { if !(name in t.typesmap) {
//println('ret Type')
return Type{} return Type{}
} }
return t.typesmap[name] 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 { fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
mut got := got_ mut got := got_
mut expected := expected_ mut expected := expected_
p.log('check types got="$got" exp="$expected" ') //p.log('check types got="$got" exp="$expected" ')
if p.pref.translated { if p.pref.translated {
return true return true
} }

View File

@ -7,7 +7,7 @@ fn test_array_str() {
println(f) println(f)
//s := f.str() //s := f.str()
//println(s) //println(s)
n := [i64(1), 2, 3] n := [1, 2, 3]
assert n.str() == '[1, 2, 3]' assert n.str() == '[1, 2, 3]'
println(n) // make sure the array is printable println(n) // make sure the array is printable
n2 := [4,5,6] n2 := [4,5,6]

View File

@ -9,6 +9,7 @@
+ fix non-ascii rendering in gg (ä, å, etc) + fix non-ascii rendering in gg (ä, å, etc)
- cache all tokens once - cache all tokens once
- enable vfmt - enable vfmt
- bring back vdoc and regenerate all module docs
- optimize the parser (reduce map lookups) - optimize the parser (reduce map lookups)
- cache vlib (right now it's re-compiled every time) - cache vlib (right now it's re-compiled every time)
- fix openssl on older linux distros - fix openssl on older linux distros
@ -31,4 +32,6 @@
+ o(log n) type lookup + o(log n) type lookup
- prebuilt binaries for all platforms - prebuilt binaries for all platforms
- fix interfaces - fix interfaces
- `none` keyword for optionals
- table: migrate all find*** functions to optionals