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  }