table: use an optional for find_fn()

pull/2023/head
Alexander Medvednikov 2019-09-18 15:06:34 +03:00
parent 1c6cbdace5
commit 040d03912b
3 changed files with 39 additions and 40 deletions

View File

@ -238,12 +238,15 @@ fn (p mut Parser) fn_decl() {
if !is_c && !p.builtin_mod && p.mod != 'main' && receiver_typ.len == 0 { if !is_c && !p.builtin_mod && p.mod != 'main' && receiver_typ.len == 0 {
f.name = p.prepend_mod(f.name) f.name = p.prepend_mod(f.name)
} }
if p.first_pass() && p.table.known_fn(f.name) && receiver_typ.len == 0 { if p.first_pass() && receiver_typ.len == 0 {
existing_fn := p.table.find_fn(f.name) for {
existing_fn := p.table.find_fn(f.name) or { break }
// This existing function could be defined as C decl before (no body), then we don't need to throw an erro // This existing function could be defined as C decl before (no body), then we don't need to throw an erro
if !existing_fn.is_decl { if !existing_fn.is_decl {
p.error('redefinition of `$f.name`') p.error('redefinition of `$f.name`')
} }
break
}
} }
// Generic? // Generic?
mut is_generic := false mut is_generic := false

View File

@ -1488,7 +1488,7 @@ fn (p mut Parser) name_expr() string {
for { // TODO remove for { // TODO remove
mut v := p.find_var_check_new_var(name) or { break } mut v := p.find_var_check_new_var(name) or { break }
if ptr { if ptr {
p.gen('& /*vvar*/ ') p.gen('& /*v*/ ')
} }
else if deref { else if deref {
p.gen('*') p.gen('*')
@ -1569,9 +1569,9 @@ fn (p mut Parser) name_expr() string {
p.next() p.next()
return 'int' return 'int'
} }
// C fn // C function
f := Fn { f := Fn {
name: name// .replace('c_', '') name: name
is_c: true is_c: true
} }
p.is_c_fn_call = true p.is_c_fn_call = true
@ -1579,9 +1579,8 @@ fn (p mut Parser) name_expr() string {
p.is_c_fn_call = false p.is_c_fn_call = false
// Try looking it up. Maybe its defined with "C.fn_name() fn_type", // Try looking it up. Maybe its defined with "C.fn_name() fn_type",
// then we know what type it returns // then we know what type it returns
cfn := p.table.find_fn(name) cfn := p.table.find_fn(name) or {
// Not Found? Return 'void*' // Not Found? Return 'void*'
if cfn.name == '' {
//return 'cvoid' //'void*' //return 'cvoid' //'void*'
return 'void*' return 'void*'
} }
@ -1605,42 +1604,41 @@ fn (p mut Parser) name_expr() string {
return typ return typ
} }
// Function (not method btw, methods are handled in dot()) // Function (not method btw, methods are handled in dot())
mut f := p.table.find_fn(name) mut f := p.table.find_fn(name) or {
if f.name == '' { // We are in the second pass, that means this function was not defined, throw an error.
// We are in a second pass, that means this function was not defined, throw an error.
if !p.first_pass() { if !p.first_pass() {
// V script? Try os module. // V script? Try os module.
// TODO
if p.v_script { if p.v_script {
name = name.replace('main__', 'os__') //name = name.replace('main__', 'os__')
f = p.table.find_fn(name) //f = p.table.find_fn(name)
} }
if f.name == '' { // check for misspelled function / variable / module
// check for misspelled function / variable / module suggested := p.table.identify_typo(name, p.cur_fn, p.import_table)
suggested := p.table.identify_typo(name, p.cur_fn, p.import_table) if suggested != '' {
if suggested != '' { p.error('undefined: `$name`. did you mean:$suggested')
p.error('undefined: `$name`. did you mean:$suggested') }
// If orig_name is a mod, then printing undefined: `mod` tells us nothing
// if p.table.known_mod(orig_name) {
if p.table.known_mod(orig_name) || p.import_table.known_alias(orig_name) {
name = name.replace('__', '.').replace('_dot_', '.')
p.error('undefined: `$name`')
}
else {
if orig_name == 'i32' {
println('`i32` alias was removed, use `int` instead')
} }
// If orig_name is a mod, then printing undefined: `mod` tells us nothing if orig_name == 'u8' {
// if p.table.known_mod(orig_name) { println('`u8` alias was removed, use `byte` instead')
if p.table.known_mod(orig_name) || p.import_table.known_alias(orig_name) {
name = name.replace('__', '.').replace('_dot_', '.')
p.error('undefined: `$name`')
}
else {
if orig_name == 'i32' {
println('`i32` alias was removed, use `int` instead')
}
if orig_name == 'u8' {
println('`u8` alias was removed, use `byte` instead')
}
p.error('undefined: `$orig_name`')
} }
p.error('undefined: `$orig_name`')
} }
} else { } else {
p.next() p.next()
// First pass, the function can be defined later. // First pass, the function can be defined later.
return 'void' return 'void'
} }
return 'void'
} }
// no () after func, so func is an argument, just gen its name // no () after func, so func is an argument, just gen its name
// TODO verify this and handle errors // TODO verify this and handle errors
@ -3550,11 +3548,10 @@ fn (p mut Parser) go_statement() {
} }
// Normal function // Normal function
else { else {
f := p.table.find_fn(p.lit) f := p.table.find_fn(p.lit) or { panic('fn') }
if f.name == 'println' { if f.name == 'println' {
p.error('`go` cannot be used with `println`') p.error('`go` cannot be used with `println`')
} }
// println(f.name)
p.async_fn_call(f, 0, '', '') p.async_fn_call(f, 0, '', '')
} }
} }

View File

@ -169,7 +169,7 @@ const (
) )
// This is used in generated C code // This is used for debugging only
fn (f Fn) str() string { fn (f Fn) str() string {
t := Table{} t := Table{}
str_args := f.str_args(t) str_args := f.str_args(t)
@ -318,18 +318,17 @@ fn (table &Table) known_type_fast(t &Type) bool {
return t.name.len > 0 && !t.is_placeholder return t.name.len > 0 && !t.is_placeholder
} }
fn (t &Table) find_fn(name string) Fn { fn (t &Table) find_fn(name string) ?Fn {
f := t.fns[name] f := t.fns[name]
if !isnil(f.name.str) { if !isnil(f.name.str) {
return f return f
} }
//println('ret find fn') return none
return Fn{}
} }
fn (t &Table) known_fn(name string) bool { fn (t &Table) known_fn(name string) bool {
f := t.find_fn(name) _ := t.find_fn(name) or { return false }
return f.name != '' return true
} }
fn (t &Table) known_const(name string) bool { fn (t &Table) known_const(name string) bool {