parent
8c43d2450f
commit
665279938e
|
@ -1298,36 +1298,3 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
|||
}
|
||||
return none
|
||||
}
|
||||
|
||||
// generic struct instantiations to concrete types
|
||||
pub fn (mut t Table) generic_struct_insts_to_concrete() {
|
||||
for mut typ in t.type_symbols {
|
||||
if typ.kind == .generic_struct_inst {
|
||||
info := typ.info as GenericStructInst
|
||||
parent := t.type_symbols[info.parent_idx]
|
||||
if parent.kind == .placeholder {
|
||||
typ.kind = .placeholder
|
||||
continue
|
||||
}
|
||||
mut parent_info := parent.info as Struct
|
||||
mut fields := parent_info.fields.clone()
|
||||
if parent_info.generic_types.len == info.concrete_types.len {
|
||||
generic_names := parent_info.generic_types.map(t.get_type_symbol(it).name)
|
||||
for i in 0 .. fields.len {
|
||||
if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names,
|
||||
info.concrete_types)
|
||||
{
|
||||
fields[i].typ = t_typ
|
||||
}
|
||||
}
|
||||
parent_info.is_generic = false
|
||||
parent_info.concrete_types = info.concrete_types.clone()
|
||||
parent_info.fields = fields
|
||||
parent_info.parent_type = new_type(info.parent_idx).set_flag(.generic)
|
||||
typ.is_public = true
|
||||
typ.kind = .struct_
|
||||
typ.info = parent_info
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ pub fn (mut b Builder) front_stages(v_files []string) ? {
|
|||
|
||||
pub fn (mut b Builder) middle_stages() ? {
|
||||
util.timing_start('CHECK')
|
||||
b.table.generic_struct_insts_to_concrete()
|
||||
b.checker.generic_struct_insts_to_concrete()
|
||||
b.checker.check_files(b.parsed_files)
|
||||
util.timing_measure('CHECK')
|
||||
b.print_warnings_and_errors()
|
||||
|
|
|
@ -664,10 +664,18 @@ fn (mut c Checker) unwrap_generic_struct(struct_type ast.Type, generic_names []s
|
|||
// fields type translate to concrete type
|
||||
mut fields := ts.info.fields.clone()
|
||||
for i in 0 .. fields.len {
|
||||
if t_typ := c.table.resolve_generic_to_concrete(fields[i].typ, generic_names,
|
||||
concrete_types)
|
||||
{
|
||||
fields[i].typ = t_typ
|
||||
if fields[i].typ.has_flag(.generic) {
|
||||
sym := c.table.get_type_symbol(fields[i].typ)
|
||||
if sym.kind == .struct_ && fields[i].typ.idx() != struct_type.idx() {
|
||||
fields[i].typ = c.unwrap_generic_struct(fields[i].typ, generic_names,
|
||||
concrete_types)
|
||||
} else {
|
||||
if t_typ := c.table.resolve_generic_to_concrete(fields[i].typ,
|
||||
generic_names, concrete_types)
|
||||
{
|
||||
fields[i].typ = t_typ
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// update concrete types
|
||||
|
@ -698,6 +706,47 @@ fn (mut c Checker) unwrap_generic_struct(struct_type ast.Type, generic_names []s
|
|||
return struct_type
|
||||
}
|
||||
|
||||
// generic struct instantiations to concrete types
|
||||
pub fn (mut c Checker) generic_struct_insts_to_concrete() {
|
||||
for mut typ in c.table.type_symbols {
|
||||
if typ.kind == .generic_struct_inst {
|
||||
info := typ.info as ast.GenericStructInst
|
||||
parent := c.table.type_symbols[info.parent_idx]
|
||||
if parent.kind == .placeholder {
|
||||
typ.kind = .placeholder
|
||||
continue
|
||||
}
|
||||
mut parent_info := parent.info as ast.Struct
|
||||
mut fields := parent_info.fields.clone()
|
||||
if parent_info.generic_types.len == info.concrete_types.len {
|
||||
generic_names := parent_info.generic_types.map(c.table.get_type_symbol(it).name)
|
||||
for i in 0 .. fields.len {
|
||||
if fields[i].typ.has_flag(.generic) {
|
||||
sym := c.table.get_type_symbol(fields[i].typ)
|
||||
if sym.kind == .struct_ && fields[i].typ.idx() != info.parent_idx {
|
||||
fields[i].typ = c.unwrap_generic_struct(fields[i].typ, generic_names,
|
||||
info.concrete_types)
|
||||
} else {
|
||||
if t_typ := c.table.resolve_generic_to_concrete(fields[i].typ,
|
||||
generic_names, info.concrete_types)
|
||||
{
|
||||
fields[i].typ = t_typ
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parent_info.is_generic = false
|
||||
parent_info.concrete_types = info.concrete_types.clone()
|
||||
parent_info.fields = fields
|
||||
parent_info.parent_type = ast.new_type(info.parent_idx).set_flag(.generic)
|
||||
typ.is_public = true
|
||||
typ.kind = .struct_
|
||||
typ.info = parent_info
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||
if node.typ == ast.void_type {
|
||||
// Short syntax `({foo: bar})`
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
fn test_nested_generic_struct_init() {
|
||||
mut list1 := &List<int>{}
|
||||
println(list1)
|
||||
assert '$list1'.contains('head: &nil')
|
||||
|
||||
mut list2 := list_new<int>()
|
||||
println(list2)
|
||||
assert '$list2'.contains('head: &nil')
|
||||
}
|
||||
|
||||
struct List<T> {
|
||||
pub mut:
|
||||
head &ListNode<T> = 0
|
||||
}
|
||||
|
||||
struct ListNode<T> {
|
||||
pub mut:
|
||||
value T
|
||||
next &ListNode<T> = 0
|
||||
}
|
||||
|
||||
pub fn list_new<T>() &List<T> {
|
||||
return &List<T>{}
|
||||
}
|
Loading…
Reference in New Issue