1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: remove unneeded sumtype logic and add more tests (#6959)

This commit is contained in:
Ruofan XU 2020-11-26 22:29:23 +08:00 committed by GitHub
parent 52b627feb3
commit c6a8c3cad5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 180 additions and 46 deletions

View File

@ -109,8 +109,6 @@ mut:
inside_const bool inside_const bool
comp_for_method string // $for method in T { comp_for_method string // $for method in T {
comptime_var_type_map map[string]table.Type comptime_var_type_map map[string]table.Type
match_sumtype_exprs []ast.Expr
match_sumtype_syms []table.TypeSymbol
// tmp_arg_vars_to_free []string // tmp_arg_vars_to_free []string
// autofree_pregen map[string]string // autofree_pregen map[string]string
// autofree_pregen_buf strings.Builder // autofree_pregen_buf strings.Builder
@ -2342,9 +2340,6 @@ fn (mut g Gen) expr(node ast.Expr) {
g.write(node.val) g.write(node.val)
} }
ast.Ident { ast.Ident {
if g.should_write_asterisk_due_to_match_sumtype(node) {
g.write('*')
}
g.ident(node) g.ident(node)
} }
ast.IfExpr { 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) { 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 { for j, branch in node.branches {
mut sumtype_index := 0 mut sumtype_index := 0
// iterates through all types in sumtype branches // 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)) 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) { fn (mut g Gen) concat_expr(node ast.ConcatExpr) {
styp := g.typ(node.return_type) styp := g.typ(node.return_type)
sym := g.table.get_type_symbol(node.return_type) sym := g.table.get_type_symbol(node.return_type)

View File

@ -419,8 +419,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
// g.write('/*${g.typ(node.receiver_type)}*/') // g.write('/*${g.typ(node.receiver_type)}*/')
// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${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' && if !node.receiver_type.is_ptr() && node.left_type.is_ptr() && node.name == 'str' {
!g.should_write_asterisk_due_to_match_sumtype(node.left) {
g.write('ptr_str(') g.write('ptr_str(')
} else { } else {
g.write('${name}(') g.write('${name}(')

View File

@ -36,6 +36,25 @@ fn test_sum_type_match() {
assert get_sum('3', int(5)) == 8.0 assert get_sum('3', int(5)) == 8.0
assert get_sum('3', f64(1.2)) == 4.2 assert get_sum('3', f64(1.2)) == 4.2
assert get_sum('3', f64(3.5)) == 6.5 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 // 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 type Number = int | f64
fn is_gt_simple(val string, dst Number) bool { 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 { fn handle(e Expr) string {
is_literal := e is IntegerLiteral is_literal := e is IntegerLiteral
assert is_literal assert is_literal