checker: check each generic function for each type
parent
b2b0461218
commit
d3ce6fd2e7
|
@ -37,6 +37,7 @@ pub mut:
|
||||||
mod string // current module name
|
mod string // current module name
|
||||||
is_builtin_mod bool // are we in `builtin`?
|
is_builtin_mod bool // are we in `builtin`?
|
||||||
inside_unsafe bool
|
inside_unsafe bool
|
||||||
|
cur_generic_type table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
||||||
|
@ -1158,11 +1159,13 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
// c.error('wrong number of return arguments:\n\texpected: $expected_table.str()\n\tgot: $got_types.str()', return_stmt.pos)
|
// c.error('wrong number of return arguments:\n\texpected: $expected_table.str()\n\tgot: $got_types.str()', return_stmt.pos)
|
||||||
c.error('wrong number of return arguments', return_stmt.pos)
|
c.error('wrong number of return arguments', return_stmt.pos)
|
||||||
}
|
}
|
||||||
for i, exp_typ in expected_types {
|
for i, exp_type in expected_types {
|
||||||
got_typ := got_types[i]
|
got_typ := got_types[i]
|
||||||
if !c.table.check(got_typ, exp_typ) {
|
ok := if exp_type == table.t_type { c.table.check(got_typ, c.cur_generic_type) } else { c.table.check(got_typ,
|
||||||
|
exp_type) }
|
||||||
|
if !ok { // !c.table.check(got_typ, exp_typ) {
|
||||||
got_typ_sym := c.table.get_type_symbol(got_typ)
|
got_typ_sym := c.table.get_type_symbol(got_typ)
|
||||||
exp_typ_sym := c.table.get_type_symbol(exp_typ)
|
exp_typ_sym := c.table.get_type_symbol(exp_type)
|
||||||
pos := return_stmt.exprs[i].position()
|
pos := return_stmt.exprs[i].position()
|
||||||
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument',
|
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument',
|
||||||
pos)
|
pos)
|
||||||
|
@ -1815,6 +1818,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
|
|
||||||
pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
if ident.name == c.var_decl_name { // c.checked_ident {
|
if ident.name == c.var_decl_name { // c.checked_ident {
|
||||||
|
// Do not allow `x := x`
|
||||||
c.error('unresolved: `$ident.name`', ident.pos)
|
c.error('unresolved: `$ident.name`', ident.pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
@ -1836,6 +1840,10 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
// second use
|
// second use
|
||||||
if ident.kind == .variable {
|
if ident.kind == .variable {
|
||||||
info := ident.info as ast.IdentVar
|
info := ident.info as ast.IdentVar
|
||||||
|
if info.typ == table.t_type {
|
||||||
|
// Got a var with type T, return current generic type
|
||||||
|
return c.cur_generic_type
|
||||||
|
}
|
||||||
return info.typ
|
return info.typ
|
||||||
} else if ident.kind == .constant {
|
} else if ident.kind == .constant {
|
||||||
info := ident.info as ast.IdentVar
|
info := ident.info as ast.IdentVar
|
||||||
|
@ -1859,6 +1867,10 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
typ: typ
|
typ: typ
|
||||||
is_optional: is_optional
|
is_optional: is_optional
|
||||||
}
|
}
|
||||||
|
if typ == table.t_type {
|
||||||
|
// Got a var with type T, return current generic type
|
||||||
|
typ = c.cur_generic_type
|
||||||
|
}
|
||||||
it.typ = typ
|
it.typ = typ
|
||||||
// unwrap optional (`println(x)`)
|
// unwrap optional (`println(x)`)
|
||||||
if is_optional {
|
if is_optional {
|
||||||
|
@ -2315,6 +2327,16 @@ fn (c &Checker) fileis(s string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) fn_decl(it ast.FnDecl) {
|
fn (mut c Checker) fn_decl(it ast.FnDecl) {
|
||||||
|
if it.is_generic && c.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
|
||||||
|
// loop thru each generic type and generate a function
|
||||||
|
for gen_type in c.table.fn_gen_types[it.name] {
|
||||||
|
c.cur_generic_type = gen_type
|
||||||
|
// println('\ncalling check for $it.name for type ' + gen_type.str())
|
||||||
|
c.fn_decl(it)
|
||||||
|
}
|
||||||
|
c.cur_generic_type = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
if it.language == .v && !c.is_builtin_mod {
|
if it.language == .v && !c.is_builtin_mod {
|
||||||
c.check_valid_snake_case(it.name, 'function name', it.pos)
|
c.check_valid_snake_case(it.name, 'function name', it.pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
for gen_type in g.table.fn_gen_types[it.name] {
|
for gen_type in g.table.fn_gen_types[it.name] {
|
||||||
g.cur_generic_type = gen_type
|
g.cur_generic_type = gen_type
|
||||||
g.gen_fn_decl(it)
|
g.gen_fn_decl(it)
|
||||||
println(gen_type)
|
|
||||||
}
|
}
|
||||||
g.cur_generic_type = 0
|
g.cur_generic_type = 0
|
||||||
return
|
return
|
||||||
|
|
|
@ -438,12 +438,12 @@ pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
name: 'char'
|
name: 'char'
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
})
|
})
|
||||||
t.register_type_symbol(TypeSymbol{
|
t.register_type_symbol({
|
||||||
kind: .bool
|
kind: .bool
|
||||||
name: 'bool'
|
name: 'bool'
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
})
|
})
|
||||||
t.register_type_symbol(TypeSymbol{
|
t.register_type_symbol({
|
||||||
kind: .none_
|
kind: .none_
|
||||||
name: 'none'
|
name: 'none'
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
|
@ -473,6 +473,11 @@ pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
name: 'any'
|
name: 'any'
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
})
|
})
|
||||||
|
t.register_type_symbol(TypeSymbol{
|
||||||
|
kind: .any
|
||||||
|
name: 'T'
|
||||||
|
mod: 'builtin'
|
||||||
|
})
|
||||||
t.register_type_symbol(TypeSymbol{
|
t.register_type_symbol(TypeSymbol{
|
||||||
kind: .size_t
|
kind: .size_t
|
||||||
name: 'size_t'
|
name: 'size_t'
|
||||||
|
@ -493,11 +498,6 @@ pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
parent_idx: map_string_int_idx
|
parent_idx: map_string_int_idx
|
||||||
})
|
})
|
||||||
t.register_type_symbol(TypeSymbol{
|
|
||||||
kind: .any
|
|
||||||
name: 'T'
|
|
||||||
mod: 'builtin'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
|
|
@ -6,7 +6,8 @@ fn simple<T>(p T) T {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn plus<T>(a, b T) T {
|
fn plus<T>(a, b T) T {
|
||||||
// q := a + 1
|
// ww := ww
|
||||||
|
// q := xx + 1
|
||||||
return a + b
|
return a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +16,9 @@ fn test_generic_fn() {
|
||||||
assert simple<int>(1 + 0) == 1
|
assert simple<int>(1 + 0) == 1
|
||||||
assert simple<string>('g') == 'g'
|
assert simple<string>('g') == 'g'
|
||||||
assert simple<string>('g') + 'h' == 'gh'
|
assert simple<string>('g') + 'h' == 'gh'
|
||||||
// plus<int>(2, 3)
|
a := plus<int>(2, 3)
|
||||||
|
// plus<string>('a', 'b')
|
||||||
|
println(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue