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)
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 {
.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
// 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
// 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
}
}
if field := c.table.struct_find_field(typ_sym, field_name) {
if typ_sym.mod != c.mod && !field.is_pub {
c.error('field `${typ_sym.name}.$field_name` is not public', selector_expr.pos)
if field := c.table.struct_find_field(sym, field_name) {
if sym.mod != c.mod && !field.is_pub {
c.error('field `${sym.name}.$field_name` is not public', selector_expr.pos)
}
return field.typ
}
if typ_sym.kind != .struct_ {
c.error('`$typ_sym.name` is not a struct', selector_expr.pos)
if sym.kind != .struct_ {
c.error('`$sym.name` is not a struct', selector_expr.pos)
} 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
}
@ -2163,7 +2163,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
if last_expr.typ.is_int() || last_expr.typ.is_float() {
node.typ = last_expr.typ
continue
}
}
} else { // node.typ == any_float
if last_expr.typ.is_float() {
node.typ = last_expr.typ
@ -2175,7 +2175,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
if last_expr.typ == table.any_int_type {
if node.typ.is_int() || node.typ.is_float() {
continue
}
}
} else { // expr_type == any_float
if node.typ.is_float() {
continue
@ -2410,7 +2410,8 @@ fn (mut c Checker) fn_decl(it ast.FnDecl) {
// 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())
//sym:=c.table.get_type_symbol(gen_type)
//println('\ncalling check for $it.name for type $sym.name')
c.fn_decl(it)
}
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 {
// `foo<int>(10)`
p.next() // `<`
p.expr_mod = ''
generic_type = p.parse_type()
p.check(.gt) // `>`
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'
} else if p.expr_mod != '' {
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`
name = p.mod + '.' + name
}

View File

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

View File

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