parent
7e6d4ebfe1
commit
2d43fdb42a
|
@ -1345,7 +1345,7 @@ fn (t Tree) selector_expr(node ast.SelectorExpr) &Node {
|
||||||
obj.add('typ', t.type_node(node.typ))
|
obj.add('typ', t.type_node(node.typ))
|
||||||
obj.add('name_type', t.type_node(node.name_type))
|
obj.add('name_type', t.type_node(node.name_type))
|
||||||
obj.add('gkind_field', t.enum_node(node.gkind_field))
|
obj.add('gkind_field', t.enum_node(node.gkind_field))
|
||||||
obj.add('from_embed_type', t.type_node(node.from_embed_type))
|
obj.add('from_embed_types', t.array_node_type(node.from_embed_types))
|
||||||
obj.add('next_token', t.token_node(node.next_token))
|
obj.add('next_token', t.token_node(node.next_token))
|
||||||
obj.add('pos', t.position(node.pos))
|
obj.add('pos', t.position(node.pos))
|
||||||
obj.add('scope', t.number_node(int(node.scope)))
|
obj.add('scope', t.number_node(int(node.scope)))
|
||||||
|
|
|
@ -223,13 +223,13 @@ pub:
|
||||||
mut_pos token.Position
|
mut_pos token.Position
|
||||||
next_token token.Kind
|
next_token token.Kind
|
||||||
pub mut:
|
pub mut:
|
||||||
expr Expr // expr.field_name
|
expr Expr // expr.field_name
|
||||||
expr_type Type // type of `Foo` in `Foo.bar`
|
expr_type Type // type of `Foo` in `Foo.bar`
|
||||||
typ Type // type of the entire thing (`Foo.bar`)
|
typ Type // type of the entire thing (`Foo.bar`)
|
||||||
name_type Type // T in `T.name` or typeof in `typeof(expr).name`
|
name_type Type // T in `T.name` or typeof in `typeof(expr).name`
|
||||||
gkind_field GenericKindField // `T.name` => ast.GenericKindField.name, `T.typ` => ast.GenericKindField.typ, or .unknown
|
gkind_field GenericKindField // `T.name` => ast.GenericKindField.name, `T.typ` => ast.GenericKindField.typ, or .unknown
|
||||||
scope &Scope
|
scope &Scope
|
||||||
from_embed_type Type // holds the type of the embed that the method is called from
|
from_embed_types []Type // holds the type of the embed that the method is called from
|
||||||
}
|
}
|
||||||
|
|
||||||
// root_ident returns the origin ident where the selector started.
|
// root_ident returns the origin ident where the selector started.
|
||||||
|
|
|
@ -503,22 +503,23 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
|
||||||
pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name string) ?(StructField, []Type) {
|
pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name string) ?(StructField, []Type) {
|
||||||
if sym.info is Struct {
|
if sym.info is Struct {
|
||||||
mut found_fields := []StructField{}
|
mut found_fields := []StructField{}
|
||||||
mut embeds_of_found_fields := [][]Type{}
|
mut embeds_of_found_fields := []Type{}
|
||||||
for embed in sym.info.embeds {
|
for embed in sym.info.embeds {
|
||||||
embed_sym := t.get_type_symbol(embed)
|
embed_sym := t.get_type_symbol(embed)
|
||||||
if field := t.find_field(embed_sym, field_name) {
|
if field := t.find_field(embed_sym, field_name) {
|
||||||
found_fields << field
|
found_fields << field
|
||||||
embeds_of_found_fields << [embed]
|
embeds_of_found_fields << embed
|
||||||
} else {
|
} else {
|
||||||
field, types := t.find_field_from_embeds_recursive(embed_sym, field_name) or {
|
field, types := t.find_field_from_embeds_recursive(embed_sym, field_name) or {
|
||||||
StructField{}, []Type{}
|
continue
|
||||||
}
|
}
|
||||||
found_fields << field
|
found_fields << field
|
||||||
|
embeds_of_found_fields << embed
|
||||||
embeds_of_found_fields << types
|
embeds_of_found_fields << types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if found_fields.len == 1 {
|
if found_fields.len == 1 {
|
||||||
return found_fields[0], embeds_of_found_fields[0]
|
return found_fields[0], embeds_of_found_fields
|
||||||
} else if found_fields.len > 1 {
|
} else if found_fields.len > 1 {
|
||||||
return error('ambiguous field `$field_name`')
|
return error('ambiguous field `$field_name`')
|
||||||
}
|
}
|
||||||
|
@ -526,7 +527,7 @@ pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name s
|
||||||
for typ in sym.info.types {
|
for typ in sym.info.types {
|
||||||
agg_sym := t.get_type_symbol(typ)
|
agg_sym := t.get_type_symbol(typ)
|
||||||
field, embed_types := t.find_field_from_embeds_recursive(agg_sym, field_name) or {
|
field, embed_types := t.find_field_from_embeds_recursive(agg_sym, field_name) or {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
if embed_types.len > 0 {
|
if embed_types.len > 0 {
|
||||||
return field, embed_types
|
return field, embed_types
|
||||||
|
@ -578,7 +579,7 @@ pub fn (t &Table) find_field_with_embeds(sym &TypeSymbol, field_name string) ?St
|
||||||
} else {
|
} else {
|
||||||
// look for embedded field
|
// look for embedded field
|
||||||
first_err := err
|
first_err := err
|
||||||
field, _ := t.find_field_from_embeds(sym, field_name) or { return first_err }
|
field, _ := t.find_field_from_embeds_recursive(sym, field_name) or { return first_err }
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3460,15 +3460,15 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
||||||
} else {
|
} else {
|
||||||
// look for embedded field
|
// look for embedded field
|
||||||
has_field = true
|
has_field = true
|
||||||
mut embed_type := ast.Type(0)
|
mut embed_types := []ast.Type{}
|
||||||
field, embed_type = c.table.find_field_from_embeds(sym, field_name) or {
|
field, embed_types = c.table.find_field_from_embeds_recursive(sym, field_name) or {
|
||||||
if err.msg != '' {
|
if err.msg != '' {
|
||||||
c.error(err.msg, node.pos)
|
c.error(err.msg, node.pos)
|
||||||
}
|
}
|
||||||
has_field = false
|
has_field = false
|
||||||
ast.StructField{}, ast.Type(0)
|
ast.StructField{}, []ast.Type{}
|
||||||
}
|
}
|
||||||
node.from_embed_type = embed_type
|
node.from_embed_types = embed_types
|
||||||
if sym.kind in [.aggregate, .sum_type] {
|
if sym.kind in [.aggregate, .sum_type] {
|
||||||
unknown_field_msg = err.msg
|
unknown_field_msg = err.msg
|
||||||
}
|
}
|
||||||
|
@ -3489,15 +3489,15 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
||||||
} else {
|
} else {
|
||||||
// look for embedded field
|
// look for embedded field
|
||||||
has_field = true
|
has_field = true
|
||||||
mut embed_type := ast.Type(0)
|
mut embed_types := []ast.Type{}
|
||||||
field, embed_type = c.table.find_field_from_embeds(gs, field_name) or {
|
field, embed_types = c.table.find_field_from_embeds_recursive(gs, field_name) or {
|
||||||
if err.msg != '' {
|
if err.msg != '' {
|
||||||
c.error(err.msg, node.pos)
|
c.error(err.msg, node.pos)
|
||||||
}
|
}
|
||||||
has_field = false
|
has_field = false
|
||||||
ast.StructField{}, ast.Type(0)
|
ast.StructField{}, []ast.Type{}
|
||||||
}
|
}
|
||||||
node.from_embed_type = embed_type
|
node.from_embed_types = embed_types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4226,8 +4226,8 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||||
}
|
}
|
||||||
// struct embedding
|
// struct embedding
|
||||||
if sym.info in [ast.Struct, ast.Aggregate] {
|
if sym.info in [ast.Struct, ast.Aggregate] {
|
||||||
if node.from_embed_type != 0 {
|
for embed in node.from_embed_types {
|
||||||
embed_sym := g.table.get_type_symbol(node.from_embed_type)
|
embed_sym := g.table.get_type_symbol(embed)
|
||||||
embed_name := embed_sym.embed_name()
|
embed_name := embed_sym.embed_name()
|
||||||
if node.expr_type.is_ptr() {
|
if node.expr_type.is_ptr() {
|
||||||
g.write('->')
|
g.write('->')
|
||||||
|
@ -4237,7 +4237,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||||
g.write(embed_name)
|
g.write(embed_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.expr_type.is_ptr() || sym.kind == .chan) && node.from_embed_type == 0 {
|
if (node.expr_type.is_ptr() || sym.kind == .chan) && node.from_embed_types.len == 0 {
|
||||||
g.write('->')
|
g.write('->')
|
||||||
} else {
|
} else {
|
||||||
// g.write('. /*typ= $it.expr_type */') // ${g.typ(it.expr_type)} /')
|
// g.write('. /*typ= $it.expr_type */') // ${g.typ(it.expr_type)} /')
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
struct Foo {
|
||||||
|
mut:
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
Foo
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Baz {
|
||||||
|
Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_nested_struct_embed() {
|
||||||
|
mut baz := Baz{}
|
||||||
|
baz.x = 3
|
||||||
|
|
||||||
|
println(baz.x)
|
||||||
|
assert baz.x == 3
|
||||||
|
}
|
Loading…
Reference in New Issue