cgen: remove unneeded sumtype logic and add more tests (#6959)
							parent
							
								
									52b627feb3
								
							
						
					
					
						commit
						c6a8c3cad5
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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}(')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue