github.com/gotranspile/cxgo@v0.3.7/types/best.go (about) 1 package types 2 3 // CommonType find common type to convert two operands to. 4 func (e *Env) CommonType(x, y Type) (otyp Type) { 5 if x == y && !x.Kind().IsInt() && !y.Kind().IsInt() { 6 return x 7 } 8 if x.Sizeof() < y.Sizeof() { 9 return e.CommonType(y, x) 10 } 11 xk, yk := x.Kind(), y.Kind() 12 defer func() { 13 if otyp.Kind().IsUntyped() && (xk.IsInt() || yk.IsInt()) && (!xk.IsUntyped() || !yk.IsUntyped()) { 14 panic("returning untyped") 15 } 16 }() 17 18 def := e.DefIntT() 19 if xk != yk && ((xk.IsInt() && !yk.IsInt()) || (!xk.IsInt() && yk.IsInt())) { 20 if xk.IsInt() && yk.IsFloat() { 21 return y 22 } else if xk.IsFloat() && yk.IsInt() { 23 return x 24 } 25 if xk.IsInt() && yk.IsUntyped() { 26 return x 27 } 28 if xk.IsInt() && yk.IsInt() { 29 xi, yi := Unwrap(x).(IntType), Unwrap(y).(IntType) 30 if xi.Sizeof() == yi.Sizeof() && xi.Signed() == yi.Signed() { 31 if _, ok := x.(Named); ok { 32 return y // prefer unnamed types 33 } 34 return x 35 } 36 if xi.Sizeof() < def.Sizeof() && yi.Sizeof() < def.Sizeof() { 37 return def // C implicit type conversion to int 38 } 39 if xk.IsUntyped() && yk.IsInt() { 40 if x.Sizeof() == y.Sizeof() { 41 return y 42 } 43 // y is smaller 44 var xi Type 45 if yk.Is(Signed) { 46 xi = e.DefIntT() 47 } else { 48 xi = e.DefUintT() 49 } 50 return xi 51 } 52 } 53 } 54 55 switch x := x.(type) { 56 case IntType: 57 switch y := y.(type) { 58 case IntType: 59 if x.Kind().IsUntyped() { 60 x = AsTypedIntT(x) 61 } 62 if y.Kind().IsUntyped() { 63 y = AsTypedIntT(y) 64 } 65 if x.Sizeof() < def.Sizeof() && y.Sizeof() < def.Sizeof() { 66 return def // C implicit type conversion to int 67 } 68 if x.Signed() == y.Signed() { 69 // same sign -> pick largest 70 if x.Sizeof() >= y.Sizeof() { 71 return x 72 } 73 return y 74 } 75 // make X always correspond to unsigned 76 if !y.Signed() { 77 x, y = y, x 78 } 79 if x.Sizeof() >= y.Sizeof() { 80 // is unsigned is larger or equal - prefer it 81 return x 82 } 83 return y 84 case BoolType: 85 // int+bool = int 86 if x.Kind().IsUntyped() { 87 return e.DefIntT() 88 } 89 return x 90 } 91 case BoolType: 92 switch y := y.(type) { 93 case IntType: 94 // bool+int = int 95 if y.Kind().IsUntyped() { 96 return e.DefIntT() 97 } 98 return y 99 } 100 case ArrayType: 101 switch y.(type) { 102 case IntType: 103 e := e.PtrT(x.Elem()) 104 return e 105 } 106 } 107 if x.Kind().IsUntyped() { 108 return y 109 } else if y.Kind().IsUntyped() { 110 return x 111 } 112 // TODO 113 return x 114 }