tests: cleanup sum type tests (#6950)
							parent
							
								
									fa126b950a
								
							
						
					
					
						commit
						8e2b7fe3d6
					
				| 
						 | 
				
			
			@ -38,6 +38,51 @@ fn test_nested_if_smartcast() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Bar = string | Test
 | 
			
		||||
type Xya = int | string
 | 
			
		||||
 | 
			
		||||
struct Test {
 | 
			
		||||
	x string
 | 
			
		||||
	xya Xya
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct BarWrapper {
 | 
			
		||||
	y Bar
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_selector_smartcast() {
 | 
			
		||||
	f := BarWrapper{
 | 
			
		||||
		y: Bar(Test{
 | 
			
		||||
			x: 'Hi'
 | 
			
		||||
			xya: Xya(int(5))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if f.y is Test {
 | 
			
		||||
		z := f.y.x
 | 
			
		||||
		assert f.y.x == 'Hi'
 | 
			
		||||
		assert z == 'Hi'
 | 
			
		||||
		if f.y.xya is int {
 | 
			
		||||
			assert f.y.xya == 5
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Inner = int | string
 | 
			
		||||
struct InnerStruct {
 | 
			
		||||
	x Inner
 | 
			
		||||
}
 | 
			
		||||
type Outer = string | InnerStruct
 | 
			
		||||
 | 
			
		||||
fn test_nested_if_is() {
 | 
			
		||||
	b := Outer(InnerStruct{Inner(0)})
 | 
			
		||||
	if b is InnerStruct {
 | 
			
		||||
		if b.x is int {
 | 
			
		||||
			assert b.x == 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct MutContainer {
 | 
			
		||||
mut:
 | 
			
		||||
	abc Alphabet
 | 
			
		||||
| 
						 | 
				
			
			@ -122,3 +167,89 @@ fn test_mutability() {
 | 
			
		|||
		println('$cell.u')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Expr = CallExpr | CTempVarExpr
 | 
			
		||||
struct ExprWrapper {
 | 
			
		||||
mut:
 | 
			
		||||
	expr Expr
 | 
			
		||||
}
 | 
			
		||||
struct CallExpr {
 | 
			
		||||
	y int
 | 
			
		||||
	x string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct CTempVarExpr {
 | 
			
		||||
	x string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn gen(_ Expr) CTempVarExpr {
 | 
			
		||||
	return CTempVarExpr{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_reassign_from_function_with_parameter_selector() {
 | 
			
		||||
	mut f := ExprWrapper{Expr(CallExpr{})}
 | 
			
		||||
	if f.expr is CallExpr {
 | 
			
		||||
		f.expr = gen(f.expr)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Node = Expr | string
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype() {
 | 
			
		||||
	c := Node(Expr(CallExpr{y: 1}))
 | 
			
		||||
	if c is Expr {
 | 
			
		||||
		if c is CallExpr {
 | 
			
		||||
			assert c.y == 1
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		assert false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Food = Milk | Eggs
 | 
			
		||||
 | 
			
		||||
struct FoodWrapper {
 | 
			
		||||
mut:
 | 
			
		||||
	food Food
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Milk {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Eggs {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_if_mut_selector() {
 | 
			
		||||
	mut f := FoodWrapper{Food(Milk{'test'})}
 | 
			
		||||
	if mut f.food is Milk {
 | 
			
		||||
		f.food.name = 'milk'
 | 
			
		||||
		assert f.food.name == 'milk'
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct NodeWrapper {
 | 
			
		||||
	node Node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype_selector() {
 | 
			
		||||
	c := NodeWrapper{Node(Expr(CallExpr{y: 1}))}
 | 
			
		||||
	if c.node is Expr {
 | 
			
		||||
		if c.node is CallExpr {
 | 
			
		||||
			assert c.node.y == 1
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		assert false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
type Node = Expr | string
 | 
			
		||||
type Expr = IfExpr | IntegerLiteral
 | 
			
		||||
 | 
			
		||||
struct IntegerLiteral {}
 | 
			
		||||
struct IfExpr {
 | 
			
		||||
	pos int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct NodeWrapper {
 | 
			
		||||
	node Node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype_match_selector() {
 | 
			
		||||
	c := NodeWrapper{Node(Expr(IfExpr{pos: 1}))}
 | 
			
		||||
	match c.node {
 | 
			
		||||
		Expr {
 | 
			
		||||
			match c.node {
 | 
			
		||||
				IfExpr {
 | 
			
		||||
					assert c.node.pos == 1
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					assert false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype_match() {
 | 
			
		||||
	c := Node(Expr(IfExpr{pos: 1}))
 | 
			
		||||
	match c {
 | 
			
		||||
		Expr {
 | 
			
		||||
			match c {
 | 
			
		||||
				IfExpr {
 | 
			
		||||
					assert c.pos == 1
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					assert false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Milk {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Eggs {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Food = Milk | Eggs
 | 
			
		||||
 | 
			
		||||
struct FoodWrapper {
 | 
			
		||||
mut:
 | 
			
		||||
	food Food
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_mut() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	match mut f {
 | 
			
		||||
		Eggs {
 | 
			
		||||
			f.name = 'eggs'
 | 
			
		||||
			assert f.name == 'eggs'
 | 
			
		||||
		}
 | 
			
		||||
		Milk {
 | 
			
		||||
			f.name = 'milk'
 | 
			
		||||
			assert f.name == 'milk'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_mut_selector() {
 | 
			
		||||
	mut f := FoodWrapper{Food(Milk{'test'})}
 | 
			
		||||
	match mut f.food {
 | 
			
		||||
		Eggs {
 | 
			
		||||
			f.food.name = 'eggs'
 | 
			
		||||
			assert f.food.name == 'eggs'
 | 
			
		||||
		}
 | 
			
		||||
		Milk {
 | 
			
		||||
			f.food.name = 'milk'
 | 
			
		||||
			assert f.food.name == 'milk'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ struct StructDecl {
 | 
			
		|||
	pos int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct IfExpr {
 | 
			
		||||
	pos int
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -19,49 +18,24 @@ struct IntegerLiteral {
 | 
			
		|||
	val string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn handle(e Expr) string {
 | 
			
		||||
	is_literal := e is IntegerLiteral
 | 
			
		||||
	assert is_literal
 | 
			
		||||
	assert !(e !is IntegerLiteral)
 | 
			
		||||
	if e is IntegerLiteral {
 | 
			
		||||
		println('int')
 | 
			
		||||
	}
 | 
			
		||||
	match e {
 | 
			
		||||
		IntegerLiteral {
 | 
			
		||||
			assert e.val == '12'
 | 
			
		||||
			return 'int'
 | 
			
		||||
		}
 | 
			
		||||
		IfExpr {
 | 
			
		||||
			return 'if'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ''
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_expr() {
 | 
			
		||||
	expr := IntegerLiteral{
 | 
			
		||||
		val: '12'
 | 
			
		||||
	}
 | 
			
		||||
	assert handle(expr) == 'int'
 | 
			
		||||
	// assert expr is IntegerLiteral // TODO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_assignment_and_push() {
 | 
			
		||||
	mut expr1 := Expr{}
 | 
			
		||||
	mut arr1 := []Expr{}
 | 
			
		||||
	expr := IntegerLiteral{
 | 
			
		||||
		val: '111'
 | 
			
		||||
	}
 | 
			
		||||
	arr1 << expr
 | 
			
		||||
	match arr1[0] {
 | 
			
		||||
		IntegerLiteral {
 | 
			
		||||
			arr1 << arr1[0]
 | 
			
		||||
			// should ref/dereference on assignent be made automatic?
 | 
			
		||||
			// currently it is done for return stmt and fn args
 | 
			
		||||
			expr1 = arr1[0]
 | 
			
		||||
		}
 | 
			
		||||
		else {}
 | 
			
		||||
	}
 | 
			
		||||
fn test_sum_type_match() {
 | 
			
		||||
	// TODO: Remove these casts
 | 
			
		||||
	assert is_gt_simple('3', int(2))
 | 
			
		||||
	assert !is_gt_simple('3', int(5))
 | 
			
		||||
	assert is_gt_simple('3', f64(1.2))
 | 
			
		||||
	assert !is_gt_simple('3', f64(3.5))
 | 
			
		||||
	assert is_gt_nested('3', int(2))
 | 
			
		||||
	assert !is_gt_nested('3', int(5))
 | 
			
		||||
	assert is_gt_nested('3', f64(1.2))
 | 
			
		||||
	assert !is_gt_nested('3', f64(3.5))
 | 
			
		||||
	assert concat('3', int(2)) == '3(int)2'
 | 
			
		||||
	assert concat('3', int(5)) == '3(int)5'
 | 
			
		||||
	assert concat('3', f64(1.2)) == '3(float)1.2'
 | 
			
		||||
	assert concat('3', f64(3.5)) == '3(float)3.5'
 | 
			
		||||
	assert get_sum('3', int(2)) == 5.0
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test moving structs between master/sub arrays
 | 
			
		||||
| 
						 | 
				
			
			@ -105,18 +79,121 @@ fn test_converting_down() {
 | 
			
		|||
	assert res[1].name == 'three'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype() {
 | 
			
		||||
	c := Node(Expr(IfExpr{pos:1}))
 | 
			
		||||
	if c is Expr {
 | 
			
		||||
		if c is IfExpr {
 | 
			
		||||
			assert true
 | 
			
		||||
 | 
			
		||||
fn test_assignment_and_push() {
 | 
			
		||||
	mut expr1 := Expr{}
 | 
			
		||||
	mut arr1 := []Expr{}
 | 
			
		||||
	expr := IntegerLiteral{
 | 
			
		||||
		val: '111'
 | 
			
		||||
	}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
	arr1 << expr
 | 
			
		||||
	match arr1[0] {
 | 
			
		||||
		IntegerLiteral {
 | 
			
		||||
			arr1 << arr1[0]
 | 
			
		||||
			expr1 = arr1[0]
 | 
			
		||||
		}
 | 
			
		||||
		else {}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	else {
 | 
			
		||||
		assert false
 | 
			
		||||
 | 
			
		||||
fn test_expr() {
 | 
			
		||||
	expr := IntegerLiteral{
 | 
			
		||||
		val: '12'
 | 
			
		||||
	}
 | 
			
		||||
	assert handle(expr) == 'int'
 | 
			
		||||
	// assert expr is IntegerLiteral // TODO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Outer2 {
 | 
			
		||||
	e Expr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_zero_value_init() {
 | 
			
		||||
	// no c compiler error then it's successful
 | 
			
		||||
	_ := Outer2{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Bar = string | Test
 | 
			
		||||
type Xyz = int | string
 | 
			
		||||
 | 
			
		||||
struct Test {
 | 
			
		||||
	x string
 | 
			
		||||
	xyz Xyz
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_assignment() {
 | 
			
		||||
	y := 5
 | 
			
		||||
	mut x := Xyz(y)
 | 
			
		||||
	x = 'test'
 | 
			
		||||
 | 
			
		||||
	if x is string {
 | 
			
		||||
		x2 := x as string
 | 
			
		||||
		assert x2 == 'test'
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Foo {
 | 
			
		||||
	y Bar
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_as_cast() {
 | 
			
		||||
	f := Foo{
 | 
			
		||||
		y: Bar('test')
 | 
			
		||||
	}
 | 
			
		||||
	y := f.y as string
 | 
			
		||||
	assert y == 'test'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_typeof() {
 | 
			
		||||
    x := Expr(IfExpr{})
 | 
			
		||||
	assert typeof(x) == 'IfExpr'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Food = Milk | Eggs
 | 
			
		||||
 | 
			
		||||
struct FoodWrapper {
 | 
			
		||||
mut:
 | 
			
		||||
	food Food
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Milk {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Eggs {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_aggregate() {
 | 
			
		||||
	f := Food(Milk{'test'})
 | 
			
		||||
	match f {
 | 
			
		||||
		Milk, Eggs {
 | 
			
		||||
			assert f.name == 'test'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_if() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	if f is Milk {
 | 
			
		||||
		// only works without smartcast
 | 
			
		||||
		assert f is Milk
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	match f {
 | 
			
		||||
		Eggs {
 | 
			
		||||
			// only works without smartcast
 | 
			
		||||
			assert f is Eggs
 | 
			
		||||
		}
 | 
			
		||||
		Milk {
 | 
			
		||||
			// only works without smartcast
 | 
			
		||||
			assert f is Milk
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -158,15 +235,15 @@ fn test_int_cast_to_sumtype() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: change definition once types other than any_int and any_float (int, f64, etc) are supported in sumtype
 | 
			
		||||
type Number = any_int | any_float
 | 
			
		||||
// 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 {
 | 
			
		||||
	match dst {
 | 
			
		||||
		any_int {
 | 
			
		||||
		int {
 | 
			
		||||
			return val.int() > dst
 | 
			
		||||
		}
 | 
			
		||||
		any_float {
 | 
			
		||||
		f64 {
 | 
			
		||||
			return dst < val.f64()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -175,9 +252,9 @@ fn is_gt_simple(val string, dst Number) bool {
 | 
			
		|||
fn is_gt_nested(val string, dst Number) bool {
 | 
			
		||||
	dst2 := dst
 | 
			
		||||
	match dst {
 | 
			
		||||
		any_int {
 | 
			
		||||
		int {
 | 
			
		||||
			match dst2 {
 | 
			
		||||
				any_int {
 | 
			
		||||
				int {
 | 
			
		||||
					return val.int() > dst
 | 
			
		||||
				}
 | 
			
		||||
				// this branch should never been hit
 | 
			
		||||
| 
						 | 
				
			
			@ -186,9 +263,9 @@ fn is_gt_nested(val string, dst Number) bool {
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		any_float {
 | 
			
		||||
		f64 {
 | 
			
		||||
			match dst2 {
 | 
			
		||||
				any_float {
 | 
			
		||||
				f64 {
 | 
			
		||||
					return dst < val.f64()
 | 
			
		||||
				}
 | 
			
		||||
				// this branch should never been hit
 | 
			
		||||
| 
						 | 
				
			
			@ -202,12 +279,12 @@ fn is_gt_nested(val string, dst Number) bool {
 | 
			
		|||
 | 
			
		||||
fn concat(val string, dst Number) string {
 | 
			
		||||
	match dst {
 | 
			
		||||
		any_int {
 | 
			
		||||
		int {
 | 
			
		||||
			mut res := val + '(int)'
 | 
			
		||||
			res += dst.str()
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		any_float {
 | 
			
		||||
		f64 {
 | 
			
		||||
			mut res := val + '(float)'
 | 
			
		||||
			res += dst.str()
 | 
			
		||||
			return res
 | 
			
		||||
| 
						 | 
				
			
			@ -217,12 +294,12 @@ fn concat(val string, dst Number) string {
 | 
			
		|||
 | 
			
		||||
fn get_sum(val string, dst Number) f64 {
 | 
			
		||||
	match dst {
 | 
			
		||||
		any_int {
 | 
			
		||||
		int {
 | 
			
		||||
			mut res := val.int()
 | 
			
		||||
			res += dst
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		any_float {
 | 
			
		||||
		f64 {
 | 
			
		||||
			mut res := val.f64()
 | 
			
		||||
			res += dst
 | 
			
		||||
			return res
 | 
			
		||||
| 
						 | 
				
			
			@ -230,21 +307,22 @@ fn get_sum(val string, dst Number) f64 {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_sum_type_match() {
 | 
			
		||||
	assert is_gt_simple('3', 2)
 | 
			
		||||
	assert !is_gt_simple('3', 5)
 | 
			
		||||
	assert is_gt_simple('3', 1.2)
 | 
			
		||||
	assert !is_gt_simple('3', 3.5)
 | 
			
		||||
	assert is_gt_nested('3', 2)
 | 
			
		||||
	assert !is_gt_nested('3', 5)
 | 
			
		||||
	assert is_gt_nested('3', 1.2)
 | 
			
		||||
	assert !is_gt_nested('3', 3.5)
 | 
			
		||||
	assert concat('3', 2) == '3(int)2'
 | 
			
		||||
	assert concat('3', 5) == '3(int)5'
 | 
			
		||||
	assert concat('3', 1.2) == '3(float)1.2'
 | 
			
		||||
	assert concat('3', 3.5) == '3(float)3.5'
 | 
			
		||||
	assert get_sum('3', 2) == 5.0
 | 
			
		||||
	assert get_sum('3', 5) == 8.0
 | 
			
		||||
	assert get_sum('3', 1.2) == 4.2
 | 
			
		||||
	assert get_sum('3', 3.5) == 6.5
 | 
			
		||||
fn handle(e Expr) string {
 | 
			
		||||
	is_literal := e is IntegerLiteral
 | 
			
		||||
	assert is_literal
 | 
			
		||||
	assert !(e !is IntegerLiteral)
 | 
			
		||||
	if e is IntegerLiteral {
 | 
			
		||||
		assert typeof(e.val) == 'string'
 | 
			
		||||
	}
 | 
			
		||||
	match e {
 | 
			
		||||
		IntegerLiteral {
 | 
			
		||||
			assert e.val == '12'
 | 
			
		||||
			// assert e.val == '12' // TODO
 | 
			
		||||
			return 'int'
 | 
			
		||||
		}
 | 
			
		||||
		IfExpr {
 | 
			
		||||
			return 'if'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ''
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,511 +0,0 @@
 | 
			
		|||
type Expr = IfExpr | IntegerLiteral
 | 
			
		||||
type Stmt = FnDecl | StructDecl
 | 
			
		||||
type Node = Expr | Stmt
 | 
			
		||||
 | 
			
		||||
struct FnDecl {
 | 
			
		||||
	pos int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct StructDecl {
 | 
			
		||||
	pos int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct IfExpr {
 | 
			
		||||
	pos int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct IntegerLiteral {
 | 
			
		||||
	val string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn handle(e Expr) string {
 | 
			
		||||
	is_literal := e is IntegerLiteral
 | 
			
		||||
	assert is_literal
 | 
			
		||||
	assert !(e !is IntegerLiteral)
 | 
			
		||||
	if e is IntegerLiteral {
 | 
			
		||||
		assert typeof(e.val) == 'string'
 | 
			
		||||
	}
 | 
			
		||||
	match e {
 | 
			
		||||
		IntegerLiteral {
 | 
			
		||||
			assert e.val == '12'
 | 
			
		||||
			// assert e.val == '12' // TODO
 | 
			
		||||
			return 'int'
 | 
			
		||||
		}
 | 
			
		||||
		IfExpr {
 | 
			
		||||
			return 'if'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ''
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_expr() {
 | 
			
		||||
	expr := IntegerLiteral{
 | 
			
		||||
		val: '12'
 | 
			
		||||
	}
 | 
			
		||||
	assert handle(expr) == 'int'
 | 
			
		||||
	// assert expr is IntegerLiteral // TODO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_assignment_and_push() {
 | 
			
		||||
	mut expr1 := Expr{}
 | 
			
		||||
	mut arr1 := []Expr{}
 | 
			
		||||
	expr := IntegerLiteral{
 | 
			
		||||
		val: '111'
 | 
			
		||||
	}
 | 
			
		||||
	arr1 << expr
 | 
			
		||||
	match arr1[0] {
 | 
			
		||||
		IntegerLiteral {
 | 
			
		||||
			arr1 << arr1[0]
 | 
			
		||||
			// should ref/dereference on assignent be made automatic?
 | 
			
		||||
			// currently it is done for return stmt and fn args
 | 
			
		||||
			expr1 = arr1[0]
 | 
			
		||||
		}
 | 
			
		||||
		else {}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test moving structs between master/sub arrays
 | 
			
		||||
type Master = Sub1 | Sub2
 | 
			
		||||
 | 
			
		||||
struct Sub1 {
 | 
			
		||||
mut:
 | 
			
		||||
	val  int
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Sub2 {
 | 
			
		||||
	name string
 | 
			
		||||
	val  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_converting_down() {
 | 
			
		||||
	mut out := []Master{}
 | 
			
		||||
	out << Sub1{
 | 
			
		||||
		val: 1
 | 
			
		||||
		name: 'one'
 | 
			
		||||
	}
 | 
			
		||||
	out << Sub2{
 | 
			
		||||
		val: 2
 | 
			
		||||
		name: 'two'
 | 
			
		||||
	}
 | 
			
		||||
	out << Sub2{
 | 
			
		||||
		val: 3
 | 
			
		||||
		name: 'three'
 | 
			
		||||
	}
 | 
			
		||||
	mut res := []Sub2{cap: out.len}
 | 
			
		||||
	for d in out {
 | 
			
		||||
		match d {
 | 
			
		||||
			Sub2 { res << d }
 | 
			
		||||
			else {}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	assert res[0].val == 2
 | 
			
		||||
	assert res[0].name == 'two'
 | 
			
		||||
	assert res[1].val == 3
 | 
			
		||||
	assert res[1].name == 'three'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct NodeWrapper {
 | 
			
		||||
	node Node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype_selector() {
 | 
			
		||||
	c := NodeWrapper{Node(Expr(IfExpr{pos: 1}))}
 | 
			
		||||
	if c.node is Expr {
 | 
			
		||||
		if c.node is IfExpr {
 | 
			
		||||
			assert c.node.pos == 1
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		assert false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype_match_selector() {
 | 
			
		||||
	c := NodeWrapper{Node(Expr(IfExpr{pos: 1}))}
 | 
			
		||||
	match c.node {
 | 
			
		||||
		Expr {
 | 
			
		||||
			match c.node {
 | 
			
		||||
				IfExpr {
 | 
			
		||||
					assert c.node.pos == 1
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					assert false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype() {
 | 
			
		||||
	c := Node(Expr(IfExpr{pos:1}))
 | 
			
		||||
	if c is Expr {
 | 
			
		||||
		if c is IfExpr {
 | 
			
		||||
			assert c.pos == 1
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		assert false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_sumtype_match() {
 | 
			
		||||
	c := Node(Expr(IfExpr{pos: 1}))
 | 
			
		||||
	match c {
 | 
			
		||||
		Expr {
 | 
			
		||||
			match c {
 | 
			
		||||
				IfExpr {
 | 
			
		||||
					assert c.pos == 1
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					assert false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Abc = int | string
 | 
			
		||||
 | 
			
		||||
fn test_string_cast_to_sumtype() {
 | 
			
		||||
	a := Abc('test')
 | 
			
		||||
	match a {
 | 
			
		||||
		int {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
		string {
 | 
			
		||||
			assert true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_int_cast_to_sumtype() {
 | 
			
		||||
	// literal
 | 
			
		||||
	a := Abc(111)
 | 
			
		||||
	match a {
 | 
			
		||||
		int {
 | 
			
		||||
			assert true
 | 
			
		||||
		}
 | 
			
		||||
		string {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// var
 | 
			
		||||
	i := 111
 | 
			
		||||
	b := Abc(i)
 | 
			
		||||
	match b {
 | 
			
		||||
		int {
 | 
			
		||||
			assert true
 | 
			
		||||
		}
 | 
			
		||||
		string {
 | 
			
		||||
			assert false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
	match dst {
 | 
			
		||||
		int {
 | 
			
		||||
			return val.int() > dst
 | 
			
		||||
		}
 | 
			
		||||
		f64 {
 | 
			
		||||
			return dst < val.f64()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_gt_nested(val string, dst Number) bool {
 | 
			
		||||
	dst2 := dst
 | 
			
		||||
	match dst {
 | 
			
		||||
		int {
 | 
			
		||||
			match dst2 {
 | 
			
		||||
				int {
 | 
			
		||||
					return val.int() > dst
 | 
			
		||||
				}
 | 
			
		||||
				// this branch should never been hit
 | 
			
		||||
				else {
 | 
			
		||||
					return val.int() < dst
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		f64 {
 | 
			
		||||
			match dst2 {
 | 
			
		||||
				f64 {
 | 
			
		||||
					return dst < val.f64()
 | 
			
		||||
				}
 | 
			
		||||
				// this branch should never been hit
 | 
			
		||||
				else {
 | 
			
		||||
					return dst > val.f64()
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn concat(val string, dst Number) string {
 | 
			
		||||
	match dst {
 | 
			
		||||
		int {
 | 
			
		||||
			mut res := val + '(int)'
 | 
			
		||||
			res += dst.str()
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		f64 {
 | 
			
		||||
			mut res := val + '(float)'
 | 
			
		||||
			res += dst.str()
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_sum(val string, dst Number) f64 {
 | 
			
		||||
	match dst {
 | 
			
		||||
		int {
 | 
			
		||||
			mut res := val.int()
 | 
			
		||||
			res += dst
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
		f64 {
 | 
			
		||||
			mut res := val.f64()
 | 
			
		||||
			res += dst
 | 
			
		||||
			return res
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Bar = string | Test
 | 
			
		||||
type Xyz = int | string
 | 
			
		||||
 | 
			
		||||
struct Test {
 | 
			
		||||
	x string
 | 
			
		||||
	xyz Xyz
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Foo {
 | 
			
		||||
	y Bar
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_nested_selector_smartcast() {
 | 
			
		||||
	f := Foo{
 | 
			
		||||
		y: Bar(Test{
 | 
			
		||||
			x: 'Hi'
 | 
			
		||||
			xyz: Xyz(5)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if f.y is Test {
 | 
			
		||||
		z := f.y.x
 | 
			
		||||
		assert f.y.x == 'Hi'
 | 
			
		||||
		assert z == 'Hi'
 | 
			
		||||
		if f.y.xyz is int {
 | 
			
		||||
			assert f.y.xyz == 5
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_as_cast() {
 | 
			
		||||
	f := Foo{
 | 
			
		||||
		y: Bar('test')
 | 
			
		||||
	}
 | 
			
		||||
	y := f.y as string
 | 
			
		||||
	assert y == 'test'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_assignment() {
 | 
			
		||||
	y := 5
 | 
			
		||||
	mut x := Xyz(y)
 | 
			
		||||
	x = 'test'
 | 
			
		||||
 | 
			
		||||
	if x is string {
 | 
			
		||||
		x2 := x as string
 | 
			
		||||
		assert x2 == 'test'
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Inner = int | string
 | 
			
		||||
struct InnerStruct {
 | 
			
		||||
	x Inner
 | 
			
		||||
}
 | 
			
		||||
type Outer = string | InnerStruct
 | 
			
		||||
 | 
			
		||||
fn test_nested_if_is() {
 | 
			
		||||
	b := Outer(InnerStruct{Inner(0)})
 | 
			
		||||
	if b is InnerStruct {
 | 
			
		||||
		if b.x is int {
 | 
			
		||||
			assert b.x == 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Expr3 = CallExpr | CTempVarExpr
 | 
			
		||||
struct Expr3Wrapper {
 | 
			
		||||
mut:
 | 
			
		||||
	expr Expr3
 | 
			
		||||
}
 | 
			
		||||
struct CallExpr {
 | 
			
		||||
	y int
 | 
			
		||||
	x string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct CTempVarExpr {
 | 
			
		||||
	x string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn gen(_ Expr3) CTempVarExpr {
 | 
			
		||||
	return CTempVarExpr{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_reassign_from_function_with_parameter() {
 | 
			
		||||
	mut f := Expr3(CallExpr{})
 | 
			
		||||
	if f is CallExpr {
 | 
			
		||||
		f = gen(f)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_reassign_from_function_with_parameter_selector() {
 | 
			
		||||
	mut f := Expr3Wrapper{Expr3(CallExpr{})}
 | 
			
		||||
	if f.expr is CallExpr {
 | 
			
		||||
		f.expr = gen(f.expr)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_typeof() {
 | 
			
		||||
    x := Expr3(CTempVarExpr{})
 | 
			
		||||
	assert typeof(x) == 'CTempVarExpr'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Outer2 {
 | 
			
		||||
	e Expr3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_zero_value_init() {
 | 
			
		||||
	// no c compiler error then it's successful
 | 
			
		||||
	_ := Outer2{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Milk {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Eggs {
 | 
			
		||||
mut:
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Food = Milk | Eggs
 | 
			
		||||
 | 
			
		||||
struct FoodWrapper {
 | 
			
		||||
mut:
 | 
			
		||||
	food Food
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_aggregate() {
 | 
			
		||||
	f := Food(Milk{'test'})
 | 
			
		||||
	match f {
 | 
			
		||||
		Milk, Eggs {
 | 
			
		||||
			assert f.name == 'test'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_mut() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	match mut f {
 | 
			
		||||
		Eggs {
 | 
			
		||||
			f.name = 'eggs'
 | 
			
		||||
			assert f.name == 'eggs'
 | 
			
		||||
		}
 | 
			
		||||
		Milk {
 | 
			
		||||
			f.name = 'milk'
 | 
			
		||||
			assert f.name == 'milk'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_not_mut() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	match f {
 | 
			
		||||
		Eggs {
 | 
			
		||||
			// only works without smartcast
 | 
			
		||||
			assert f is Eggs
 | 
			
		||||
		}
 | 
			
		||||
		Milk {
 | 
			
		||||
			// only works without smartcast
 | 
			
		||||
			assert f is Milk
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_if_mut() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	if mut f is Milk {
 | 
			
		||||
		f.name = 'milk'
 | 
			
		||||
		assert f.name == 'milk'
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_if_not_mut() {
 | 
			
		||||
	mut f := Food(Milk{'test'})
 | 
			
		||||
	if f is Milk {
 | 
			
		||||
		// only works without smartcast
 | 
			
		||||
		assert f is Milk
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_match_mut_selector() {
 | 
			
		||||
	mut f := FoodWrapper{Food(Milk{'test'})}
 | 
			
		||||
	match mut f.food {
 | 
			
		||||
		Eggs {
 | 
			
		||||
			f.food.name = 'eggs'
 | 
			
		||||
			assert f.food.name == 'eggs'
 | 
			
		||||
		}
 | 
			
		||||
		Milk {
 | 
			
		||||
			f.food.name = 'milk'
 | 
			
		||||
			assert f.food.name == 'milk'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_if_mut_selector() {
 | 
			
		||||
	mut f := FoodWrapper{Food(Milk{'test'})}
 | 
			
		||||
	if mut f.food is Milk {
 | 
			
		||||
		f.food.name = 'milk'
 | 
			
		||||
		assert f.food.name == 'milk'
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_sum_type_match() {
 | 
			
		||||
	// TODO: Remove these casts
 | 
			
		||||
	assert is_gt_simple('3', int(2))
 | 
			
		||||
	assert !is_gt_simple('3', int(5))
 | 
			
		||||
	assert is_gt_simple('3', f64(1.2))
 | 
			
		||||
	assert !is_gt_simple('3', f64(3.5))
 | 
			
		||||
	assert is_gt_nested('3', int(2))
 | 
			
		||||
	assert !is_gt_nested('3', int(5))
 | 
			
		||||
	assert is_gt_nested('3', f64(1.2))
 | 
			
		||||
	assert !is_gt_nested('3', f64(3.5))
 | 
			
		||||
	assert concat('3', int(2)) == '3(int)2'
 | 
			
		||||
	assert concat('3', int(5)) == '3(int)5'
 | 
			
		||||
	assert concat('3', f64(1.2)) == '3(float)1.2'
 | 
			
		||||
	assert concat('3', f64(3.5)) == '3(float)3.5'
 | 
			
		||||
	assert get_sum('3', int(2)) == 5.0
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue