From 0f50ac3260dc1e3103ba630cc350f07885cb66d2 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 5 Dec 2021 00:46:41 +0800 Subject: [PATCH] ast: cleanup struct embeds related methods (#12719) --- vlib/v/ast/table.v | 94 +++++---------------------------------- vlib/v/checker/checker.v | 11 +++-- vlib/v/gen/c/cgen.v | 6 +-- vlib/v/gen/c/infix_expr.v | 6 +-- vlib/v/gen/js/infix.v | 6 +-- vlib/v/gen/js/js.v | 9 ++-- 6 files changed, 30 insertions(+), 102 deletions(-) diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index cf25e2cc9d..4b89f21991 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -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 } } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 58a843d2d8..a36e5920f4 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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) } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index c340d45d75..e3678fe2f7 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -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('_') diff --git a/vlib/v/gen/c/infix_expr.v b/vlib/v/gen/c/infix_expr.v index c787bc8cbc..adbc978dbb 100644 --- a/vlib/v/gen/c/infix_expr.v +++ b/vlib/v/gen/c/infix_expr.v @@ -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 } diff --git a/vlib/v/gen/js/infix.v b/vlib/v/gen/js/infix.v index 9dc4dd35fe..7ea32d4322 100644 --- a/vlib/v/gen/js/infix.v +++ b/vlib/v/gen/js/infix.v @@ -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] { diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 9f8ec2ff9c..b6b4306ae0 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -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)