generics: more fixes

pull/5075/head
Alexander Medvednikov 2020-05-27 15:56:21 +02:00
parent 8c753ddf8d
commit 5423a15f46
5 changed files with 27 additions and 21 deletions

View File

@ -586,7 +586,7 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) {
c.error('0 type in SelectorExpr', it.pos) c.error('0 type in SelectorExpr', it.pos)
return return
} }
typ_sym := c.table.get_type_symbol(it.expr_type) typ_sym := c.table.get_type_symbol(c.unwrap_generic(it.expr_type))
match typ_sym.kind { match typ_sym.kind {
.struct_ { .struct_ {
struct_info := typ_sym.info as table.Struct struct_info := typ_sym.info as table.Struct
@ -1120,7 +1120,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
} }
selector_expr.expr_type = typ selector_expr.expr_type = typ
// println('sel expr line_nr=$selector_expr.pos.line_nr typ=$selector_expr.expr_type') // println('sel expr line_nr=$selector_expr.pos.line_nr typ=$selector_expr.expr_type')
typ_sym := c.table.get_type_symbol(typ) sym := c.table.get_type_symbol(c.unwrap_generic(typ))
field_name := selector_expr.field_name field_name := selector_expr.field_name
// variadic // variadic
if typ.flag_is(.variadic) { if typ.flag_is(.variadic) {
@ -1128,16 +1128,16 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
return table.int_type return table.int_type
} }
} }
if field := c.table.struct_find_field(typ_sym, field_name) { if field := c.table.struct_find_field(sym, field_name) {
if typ_sym.mod != c.mod && !field.is_pub { if sym.mod != c.mod && !field.is_pub {
c.error('field `${typ_sym.name}.$field_name` is not public', selector_expr.pos) c.error('field `${sym.name}.$field_name` is not public', selector_expr.pos)
} }
return field.typ return field.typ
} }
if typ_sym.kind != .struct_ { if sym.kind != .struct_ {
c.error('`$typ_sym.name` is not a struct', selector_expr.pos) c.error('`$sym.name` is not a struct', selector_expr.pos)
} else { } else {
c.error('unknown field `${typ_sym.name}.$field_name`', selector_expr.pos) c.error('type `$sym.name` has no field or method `$field_name`', selector_expr.pos)
} }
return table.void_type return table.void_type
} }
@ -2410,7 +2410,8 @@ fn (mut c Checker) fn_decl(it ast.FnDecl) {
// loop thru each generic type and generate a function // loop thru each generic type and generate a function
for gen_type in c.table.fn_gen_types[it.name] { for gen_type in c.table.fn_gen_types[it.name] {
c.cur_generic_type = gen_type c.cur_generic_type = gen_type
// println('\ncalling check for $it.name for type ' + gen_type.str()) //sym:=c.table.get_type_symbol(gen_type)
//println('\ncalling check for $it.name for type $sym.name')
c.fn_decl(it) c.fn_decl(it)
} }
c.cur_generic_type = 0 c.cur_generic_type = 0

View File

@ -29,6 +29,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
if p.tok.kind == .lt { if p.tok.kind == .lt {
// `foo<int>(10)` // `foo<int>(10)`
p.next() // `<` p.next() // `<`
p.expr_mod = ''
generic_type = p.parse_type() generic_type = p.parse_type()
p.check(.gt) // `>` p.check(.gt) // `>`
p.table.register_fn_gen_type(fn_name, generic_type) p.table.register_fn_gen_type(fn_name, generic_type)

View File

@ -165,7 +165,7 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool) table
name = '${p.imports[name]}.$p.tok.lit' name = '${p.imports[name]}.$p.tok.lit'
} else if p.expr_mod != '' { } else if p.expr_mod != '' {
name = p.expr_mod + '.' + name name = p.expr_mod + '.' + name
} else if p.mod !in ['builtin', 'main'] && name !in table.builtin_type_names { } else if p.mod !in ['builtin', 'main'] && name !in table.builtin_type_names && name.len > 1 {
// `Foo` in module `mod` means `mod.Foo` // `Foo` in module `mod` means `mod.Foo`
name = p.mod + '.' + name name = p.mod + '.' + name
} }

View File

@ -453,15 +453,9 @@ pub fn (t &Table) value_type(typ Type) Type {
[inline] [inline]
pub fn (t &Table) mktyp(typ Type) Type { pub fn (t &Table) mktyp(typ Type) Type {
match typ { match typ {
any_flt_type { any_flt_type { return f64_type }
return table.f64_type any_int_type { return int_type }
} else { return typ }
any_int_type {
return table.int_type
}
else {
return typ
}
} }
} }
@ -486,5 +480,7 @@ pub fn (table &Table) register_fn_gen_type(fn_name string, typ Type) {
return return
} }
a << typ a << typ
// sym := table.get_type_symbol(typ)
// println('registering fn gen type $sym.name')
table.fn_gen_types[fn_name] = a table.fn_gen_types[fn_name] = a
} }

View File

@ -40,12 +40,20 @@ fn test_foo() {
fn create<T>() { fn create<T>() {
a := T{} a := T{}
mut b := T{}
b.foo = 'foo'
println(b.foo)
assert b.foo == 'foo'
} }
struct User { struct User {
mut:
foo string
} }
struct City { struct City {
mut:
foo string
} }
fn test_create() { fn test_create() {