ast: cleanup struct embeds related methods (#12719)

pull/12721/head
yuyi 2021-12-05 00:46:41 +08:00 committed by GitHub
parent 0cb4557a8d
commit 0f50ac3260
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 102 deletions

View File

@ -332,13 +332,13 @@ pub fn (t &Table) register_aggregate_method(mut sym TypeSymbol, name string) ?Fn
return new_fn
}
pub fn (t &Table) type_has_method(s &TypeSymbol, name string) bool {
t.type_find_method(s, name) or { return false }
pub fn (t &Table) has_method(s &TypeSymbol, name string) bool {
t.find_method(s, name) or { return false }
return true
}
// type_find_method searches from current type up through each parent looking for method
pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
// find_method searches from current type up through each parent looking for method
pub fn (t &Table) find_method(s &TypeSymbol, name string) ?Fn {
mut ts := unsafe { s }
for {
if method := ts.find_method(name) {
@ -379,49 +379,17 @@ pub fn (t &Table) get_embeds(sym &TypeSymbol, options GetEmbedsOptions) [][]Type
return embeds
}
pub fn (t &Table) type_find_method_from_embeds(sym &TypeSymbol, method_name string) ?(Fn, Type) {
pub fn (t &Table) find_method_from_embeds(sym &TypeSymbol, method_name string) ?(Fn, []Type) {
if sym.info is Struct {
mut found_methods := []Fn{}
mut embed_of_found_methods := []Type{}
for embed in sym.info.embeds {
embed_sym := t.get_type_symbol(embed)
if m := t.type_find_method(embed_sym, method_name) {
found_methods << m
embed_of_found_methods << embed
}
}
if found_methods.len == 1 {
return found_methods[0], embed_of_found_methods[0]
} else if found_methods.len > 1 {
return error('ambiguous method `$method_name`')
}
} else if sym.info is Aggregate {
for typ in sym.info.types {
agg_sym := t.get_type_symbol(typ)
method, embed_type := t.type_find_method_from_embeds(agg_sym, method_name) or {
return err
}
if embed_type != 0 {
return method, embed_type
}
}
}
return none
}
pub fn (t &Table) type_find_method_from_embeds_recursive(sym &TypeSymbol, method_name string) ?(Fn, []Type) {
if sym.info is Struct {
mut found_methods := []Fn{}
mut embed_of_found_methods := []Type{}
for embed in sym.info.embeds {
embed_sym := t.get_type_symbol(embed)
if m := t.type_find_method(embed_sym, method_name) {
if m := t.find_method(embed_sym, method_name) {
found_methods << m
embed_of_found_methods << embed
} else {
method, types := t.type_find_method_from_embeds_recursive(embed_sym, method_name) or {
continue
}
method, types := t.find_method_from_embeds(embed_sym, method_name) or { continue }
found_methods << method
embed_of_found_methods << embed
embed_of_found_methods << types
@ -435,9 +403,7 @@ pub fn (t &Table) type_find_method_from_embeds_recursive(sym &TypeSymbol, method
} else if sym.info is Aggregate {
for typ in sym.info.types {
agg_sym := t.get_type_symbol(typ)
method, embed_types := t.type_find_method_from_embeds_recursive(agg_sym, method_name) or {
continue
}
method, embed_types := t.find_method_from_embeds(agg_sym, method_name) or { continue }
if embed_types.len != 0 {
return method, embed_types
}
@ -537,7 +503,7 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
}
// find_field_from_embeds is the same as find_field_from_embeds but also looks into nested embeds
pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name string) ?(StructField, []Type) {
pub fn (t &Table) find_field_from_embeds(sym &TypeSymbol, field_name string) ?(StructField, []Type) {
if sym.info is Struct {
mut found_fields := []StructField{}
mut embeds_of_found_fields := []Type{}
@ -547,9 +513,7 @@ pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name s
found_fields << field
embeds_of_found_fields << embed
} else {
field, types := t.find_field_from_embeds_recursive(embed_sym, field_name) or {
continue
}
field, types := t.find_field_from_embeds(embed_sym, field_name) or { continue }
found_fields << field
embeds_of_found_fields << embed
embeds_of_found_fields << types
@ -563,45 +527,11 @@ pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name s
} else if sym.info is Aggregate {
for typ in sym.info.types {
agg_sym := t.get_type_symbol(typ)
field, embed_types := t.find_field_from_embeds_recursive(agg_sym, field_name) or {
continue
}
field, embed_types := t.find_field_from_embeds(agg_sym, field_name) or { continue }
if embed_types.len > 0 {
return field, embed_types
}
}
} else if sym.info is Alias {
unalias_sym := t.get_type_symbol(sym.info.parent_type)
return t.find_field_from_embeds_recursive(unalias_sym, field_name)
}
return none
}
// find_field_from_embeds finds and returns a field in the embeddings of a struct and the embedding type
pub fn (t &Table) find_field_from_embeds(sym &TypeSymbol, field_name string) ?(StructField, Type) {
if sym.info is Struct {
mut found_fields := []StructField{}
mut embed_of_found_fields := []Type{}
for embed in sym.info.embeds {
embed_sym := t.get_type_symbol(embed)
if field := t.find_field(embed_sym, field_name) {
found_fields << field
embed_of_found_fields << embed
}
}
if found_fields.len == 1 {
return found_fields[0], embed_of_found_fields[0]
} else if found_fields.len > 1 {
return error('ambiguous field `$field_name`')
}
} else if sym.info is Aggregate {
for typ in sym.info.types {
agg_sym := t.get_type_symbol(typ)
field, embed_type := t.find_field_from_embeds(agg_sym, field_name) or { return err }
if embed_type != 0 {
return field, embed_type
}
}
} else if sym.info is Alias {
unalias_sym := t.get_type_symbol(sym.info.parent_type)
return t.find_field_from_embeds(unalias_sym, field_name)
@ -616,7 +546,7 @@ pub fn (t &Table) find_field_with_embeds(sym &TypeSymbol, field_name string) ?St
} else {
// look for embedded field
first_err := err
field, _ := t.find_field_from_embeds_recursive(sym, field_name) or { return first_err }
field, _ := t.find_field_from_embeds(sym, field_name) or { return first_err }
return field
}
}

View File

@ -2059,7 +2059,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
mut method := ast.Fn{}
mut has_method := false
mut is_method_from_embed := false
if m := c.table.type_find_method(left_sym, method_name) {
if m := c.table.find_method(left_sym, method_name) {
method = m
has_method = true
} else {
@ -2074,7 +2074,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
}
if parent_type != 0 {
type_sym := c.table.get_type_symbol(parent_type)
if m := c.table.type_find_method(type_sym, method_name) {
if m := c.table.find_method(type_sym, method_name) {
method = m
has_method = true
is_generic = true
@ -2084,8 +2084,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
if !has_method {
has_method = true
mut embed_types := []ast.Type{}
method, embed_types = c.table.type_find_method_from_embeds_recursive(left_sym,
method_name) or {
method, embed_types = c.table.find_method_from_embeds(left_sym, method_name) or {
if err.msg != '' {
c.error(err.msg, node.pos)
}
@ -3462,7 +3461,7 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
// look for embedded field
has_field = true
mut embed_types := []ast.Type{}
field, embed_types = c.table.find_field_from_embeds_recursive(sym, field_name) or {
field, embed_types = c.table.find_field_from_embeds(sym, field_name) or {
if err.msg != '' {
c.error(err.msg, node.pos)
}
@ -3491,7 +3490,7 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
// look for embedded field
has_field = true
mut embed_types := []ast.Type{}
field, embed_types = c.table.find_field_from_embeds_recursive(gs, field_name) or {
field, embed_types = c.table.find_field_from_embeds(gs, field_name) or {
if err.msg != '' {
c.error(err.msg, node.pos)
}

View File

@ -2264,7 +2264,7 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
for field in (exp_sym.info as ast.SumType).fields {
mut ptr := 'ptr'
mut type_cname := got_cname
_, embed_types := g.table.find_field_from_embeds_recursive(got_sym, field.name) or {
_, embed_types := g.table.find_field_from_embeds(got_sym, field.name) or {
ast.StructField{}, []ast.Type{}
}
if embed_types.len > 0 {
@ -3171,7 +3171,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
return
} else {
g.write(' = ${styp}_${util.replace_op(extracted_op)}(')
method := g.table.type_find_method(left_sym, extracted_op) or {
method := g.table.find_method(left_sym, extracted_op) or {
// the checker will most likely have found this, already...
g.error('assignemnt operator `$extracted_op=` used but no `$extracted_op` method defined',
assign_stmt.pos)
@ -3369,7 +3369,7 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
}
ast.InfixExpr {
sym := g.table.get_type_symbol(val.left_type)
if _ := g.table.type_find_method(sym, val.op.str()) {
if _ := g.table.find_method(sym, val.op.str()) {
left_styp := g.typ(val.left_type.set_nr_muls(0))
g.write(left_styp)
g.write('_')

View File

@ -81,7 +81,7 @@ fn (mut g Gen) infix_expr_arrow_op(node ast.InfixExpr) {
fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_defined_eq_operator := g.table.type_has_method(left.sym, '==')
has_defined_eq_operator := g.table.has_method(left.sym, '==')
has_alias_eq_op_overload := left.sym.info is ast.Alias && left.sym.has_method('==')
if (left.typ.is_ptr() && right.typ.is_int()) || (right.typ.is_ptr() && left.typ.is_int()) {
g.gen_plain_infix_expr(node)
@ -278,7 +278,7 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
fn (mut g Gen) infix_expr_cmp_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '<')
has_operator_overloading := g.table.has_method(left.sym, '<')
if left.sym.kind == .struct_ && (left.sym.info as ast.Struct).generic_types.len > 0 {
if node.op in [.le, .ge] {
g.write('!')
@ -550,7 +550,7 @@ fn (mut g Gen) infix_expr_arithmetic_op(node ast.InfixExpr) {
g.expr(node.right)
g.write(')')
} else {
method := g.table.type_find_method(left.sym, node.op.str()) or {
method := g.table.find_method(left.sym, node.op.str()) or {
g.gen_plain_infix_expr(node)
return
}

View File

@ -38,7 +38,7 @@ fn (mut g JsGen) gen_plain_infix_expr(node ast.InfixExpr) {
fn (mut g JsGen) infix_expr_arithmetic_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
method := g.table.type_find_method(left.sym, node.op.str()) or {
method := g.table.find_method(left.sym, node.op.str()) or {
g.gen_plain_infix_expr(node)
return
}
@ -74,7 +74,7 @@ fn (mut g JsGen) op_arg(expr ast.Expr, expected ast.Type, got ast.Type) {
fn (mut g JsGen) infix_expr_eq_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '==')
has_operator_overloading := g.table.has_method(left.sym, '==')
g.write('new bool(')
if (left.typ.is_ptr() && right.typ.is_int()) || (right.typ.is_ptr() && left.typ.is_int()) {
g.gen_plain_infix_expr(node)
@ -209,7 +209,7 @@ fn (mut g JsGen) infix_expr_eq_op(node ast.InfixExpr) {
fn (mut g JsGen) infix_expr_cmp_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '<')
has_operator_overloading := g.table.has_method(left.sym, '<')
g.write('new bool(')
if left.sym.kind == right.sym.kind && has_operator_overloading {
if node.op in [.le, .ge] {

View File

@ -2137,8 +2137,7 @@ fn (mut g JsGen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var M
g.write(').val')
}
else {
has_operator_overloading := g.table.type_has_method(type_sym,
'==')
has_operator_overloading := g.table.has_method(type_sym, '==')
if has_operator_overloading {
left := g.unwrap(node.cond_type)
g.write(g.typ(left.unaliased.set_nr_muls(0)))
@ -2832,7 +2831,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
node := it
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '==')
has_operator_overloading := g.table.has_method(left.sym, '==')
if has_operator_overloading
|| (l_sym.kind in js.shallow_equatables && r_sym.kind in js.shallow_equatables) {
if node.op == .ne {
@ -2896,7 +2895,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
g.gen_deref_ptr(it.left_type)
g.write(' instanceof ')
g.write(g.typ(it.right_type))
} else if it.op in [.lt, .gt, .ge, .le] && g.table.type_has_method(l_sym, '<')
} else if it.op in [.lt, .gt, .ge, .le] && g.table.has_method(l_sym, '<')
&& l_sym.kind == r_sym.kind {
if it.op in [.le, .ge] {
g.write('!')
@ -2917,7 +2916,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
g.write(')')
}
} else {
has_operator_overloading := g.table.type_has_method(l_sym, it.op.str())
has_operator_overloading := g.table.has_method(l_sym, it.op.str())
if has_operator_overloading {
g.expr(it.left)
g.gen_deref_ptr(it.left_type)