From c6a8c3cad58ff15dc3390b5fb532e816b72ef684 Mon Sep 17 00:00:00 2001 From: Ruofan XU <47302112+SleepyRoy@users.noreply.github.com> Date: Thu, 26 Nov 2020 22:29:23 +0800 Subject: [PATCH] cgen: remove unneeded sumtype logic and add more tests (#6959) --- vlib/v/gen/cgen.v | 43 --------- vlib/v/gen/fn.v | 3 +- vlib/v/tests/sum_type_test.v | 180 ++++++++++++++++++++++++++++++++++- 3 files changed, 180 insertions(+), 46 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 79e180c695..c35d5014c1 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -109,8 +109,6 @@ mut: inside_const bool comp_for_method string // $for method in T { comptime_var_type_map map[string]table.Type - match_sumtype_exprs []ast.Expr - match_sumtype_syms []table.TypeSymbol // tmp_arg_vars_to_free []string // autofree_pregen map[string]string // autofree_pregen_buf strings.Builder @@ -2342,9 +2340,6 @@ fn (mut g Gen) expr(node ast.Expr) { g.write(node.val) } ast.Ident { - if g.should_write_asterisk_due_to_match_sumtype(node) { - g.write('*') - } g.ident(node) } ast.IfExpr { @@ -3040,13 +3035,6 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) { } fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string) { - type_sym := g.table.get_type_symbol(node.cond_type) - g.match_sumtype_exprs << node.cond - g.match_sumtype_syms << type_sym - defer { - g.match_sumtype_exprs.delete_last() - g.match_sumtype_syms.delete_last() - } for j, branch in node.branches { mut sumtype_index := 0 // iterates through all types in sumtype branches @@ -3392,37 +3380,6 @@ fn (mut g Gen) ident(node ast.Ident) { g.write(g.get_ternary_name(name)) } -[unlikely] -fn (mut g Gen) should_write_asterisk_due_to_match_sumtype(expr ast.Expr) bool { - if expr is ast.Ident { - typ := if expr.info is ast.IdentVar { (expr.info as ast.IdentVar).typ } else { (expr.info as ast.IdentFn).typ } - return typ.is_ptr() && g.match_sumtype_has_no_struct_and_contains(expr) - } else { - return false - } -} - -[unlikely] -fn (mut g Gen) match_sumtype_has_no_struct_and_contains(node ast.Ident) bool { - for i, expr in g.match_sumtype_exprs { - if expr is ast.Ident && node.name == (expr as ast.Ident).name { - info := g.match_sumtype_syms[i].info - match info { - table.SumType { - for typ in info.variants { - if g.table.get_type_symbol(typ).kind == .struct_ { - return false - } - } - } - else {} - } - return true - } - } - return false -} - fn (mut g Gen) concat_expr(node ast.ConcatExpr) { styp := g.typ(node.return_type) sym := g.table.get_type_symbol(node.return_type) diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index da56b0e8c1..c78f47171a 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -419,8 +419,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) { // g.write('/*${g.typ(node.receiver_type)}*/') // g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/') // } - if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name == 'str' && - !g.should_write_asterisk_due_to_match_sumtype(node.left) { + if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name == 'str' { g.write('ptr_str(') } else { g.write('${name}(') diff --git a/vlib/v/tests/sum_type_test.v b/vlib/v/tests/sum_type_test.v index 96b98683b6..9f216d33df 100644 --- a/vlib/v/tests/sum_type_test.v +++ b/vlib/v/tests/sum_type_test.v @@ -36,6 +36,25 @@ fn test_sum_type_match() { assert get_sum('3', int(5)) == 8.0 assert get_sum('3', f64(1.2)) == 4.2 assert get_sum('3', f64(3.5)) == 6.5 + assert verify_complex_expr(int(1), false) + assert !verify_complex_expr(int(2), false) + assert verify_complex_expr(f64(2.5), false) + assert !verify_complex_expr(f64(1.5), false) + assert verify_complex_expr(int(0), true) + assert as_string(int(1)) == 'This is the string representation of "1"' + assert as_string(f64(3.14)) == 'This is the string representation of "3.14"' + assert as_string('String') == 'This is the string representation of "String"' + assert as_string(IntAndStr{foo: 2, bar: 'hi', baz: &IntAndStr{foo: 3, bar: 'hello', baz: 0}}) == 'This is the string representation of "5_hi_hello"' + assert as_string(true) == 'This is the string representation of "true"' + assert as_string(CommonType(Color.red)) == 'This is the string representation of "enum1_red"' + assert as_string(CommonType(Color.green)) == 'This is the string representation of "enum2_green"' + assert as_string(CommonType(Color.blue)) == 'This is the string representation of "enum3_blue"' + assert sumtype_match_with_string_interpolation(1) == "it's an int: 5" + assert sumtype_match_with_string_interpolation(2) == "it's a string: hello" + assert sumtype_match_with_string_interpolation(3) == "green_green" + assert sumtype_match_with_string_interpolation(4) == "it's a f64: 1.5" + assert sumtype_match_with_string_interpolation(5) == "it's a bool: false" + assert sumtype_match_with_string_interpolation(6) == "it's an IntAndStr: 2_hi_3_hello" } // Test moving structs between master/sub arrays @@ -235,7 +254,6 @@ fn test_int_cast_to_sumtype() { } } -// TODO: change definition once types other than int and f64 (int, f64, etc) are supported in sumtype type Number = int | f64 fn is_gt_simple(val string, dst Number) bool { @@ -307,6 +325,166 @@ fn get_sum(val string, dst Number) f64 { } } +fn verify_complex_expr(dst Number, get_final bool) bool { + if !get_final { + match dst { + int { + dst2 := dst + dst3 := dst2 + dst4 := (dst2 + dst3).str() + temp := 2 * dst3 + 1 + res := temp - 3 + foo := 1 + dst - dst2 + dst5 := foo.str().int().str() + return (foo + res) * res - res == 0 && dst4.len == 1 && dst5.len == 1 + } + f64 { + dst2 := dst + dst3, foo := dst2, 2 + mut dst4 := dst3 + 1 + dst4 = dst / 1 + dst4 -= dst2 + mut temp := foo - 4 + temp += foo * (foo - 1) + bar := !(dst2 < 1) && dst3 - foo - temp > 0 && dst4 == 0 + return bar + } + } + } + foo := 10 + temp := foo + return temp + 10 == 20 +} + +struct IntAndStr { + foo int + bar string + baz &IntAndStr +} + +enum Color { red green blue } + +type CommonType = int | f64 | string | IntAndStr | bool | Color + +fn as_string(val CommonType) string { + return 'This is the string representation of "' + val.str() + '"' +} + +fn (c CommonType) str() string { + match c { + string { + d := c.int() + e := d + return c + } + int { + d := c + e := c + d - d + return e.str() + } + f64 { + return c.str() + } + IntAndStr { + return (c.foo + c.baz.foo).str() + '_' + c.bar + '_' + c.baz.bar + } + bool { + d := c + return if d { 'true' } else { 'false' } + } + Color { + d := c + match d { + .red { return 'enum1_' + d.str() } + .green { return 'enum2_' + d.str() } + .blue { return 'enum3_' + d.str() } + } + } + } +} + +fn sumtype_match_with_string_interpolation(code int) string { + match code { + 1 { + bar := CommonType(5) + match bar { + f64 { return "shouldn't happen" } + bool { return "shouldn't happen" } + IntAndStr { return "shouldn't happen" } + int { return "it's an int: $bar" } + string { return "shouldn't happen" } + Color { return "shouldn't happen" } + } + } + 2 { + bar := CommonType('hello') + match bar { + string { return "it's a string: $bar" } + int { return "shouldn't happen" } + Color { return "shouldn't happen" } + f64 { return "shouldn't happen" } + bool { return "shouldn't happen" } + IntAndStr { return "shouldn't happen" } + } + } + 3 { + bar := CommonType(Color.green) + match bar { + string { return "shouldn't happen" } + int { return "shouldn't happen" } + f64 { return "shouldn't happen" } + bool { return "shouldn't happen" } + IntAndStr { return "shouldn't happen" } + Color { + match bar { + .red { return 'red_$bar'} + .green { return 'green_$bar' } + .blue { return 'blue_$bar' } + } + } + } + } + 4 { + bar := CommonType(1.5) + match bar { + string { return "shouldn't happen" } + int { return "shouldn't happen" } + Color { return "shouldn't happen" } + f64 { return "it's a f64: $bar" } + bool { return "shouldn't happen" } + IntAndStr { return "shouldn't happen" } + } + } + 5 { + mut bar := CommonType('hello') + bar = CommonType(false) + match bar { + string { return "shouldn't happen" } + int { return "shouldn't happen" } + Color { return "shouldn't happen" } + f64 { return "shouldn't happen" } + bool { return "it's a bool: $bar" } + IntAndStr { return "shouldn't happen" } + } + } + 6 { + // TODO: this should work + // mut bar := CommonType(100) + // bar = CommonType(IntAndStr{foo: 2, bar: 'hi', baz: &IntAndStr{foo: 3, bar: 'hello', baz: 0}}) + bar := CommonType(IntAndStr{foo: 2, bar: 'hi', baz: &IntAndStr{foo: 3, bar: 'hello', baz: 0}}) + match bar { + string { return "shouldn't happen" } + int { return "shouldn't happen" } + Color { return "shouldn't happen" } + f64 { return "shouldn't happen" } + bool { return "shouldn't happen" } + IntAndStr { return "it's an IntAndStr: ${bar.foo}_${bar.bar}_${bar.baz.foo}_${bar.baz.bar}" } + } + } + else { return 'wrong' } + } +} + fn handle(e Expr) string { is_literal := e is IntegerLiteral assert is_literal