Inference/src/CodeGeneration/ILCodeGenerator.cs
/// <summary>
/// Writes the il code to promote typeExp1 to typeExp2
/// </summary>
/// <param name="typeExp1">The type of the element that is in the stack</param>
/// <param name="typeExp2">The type to promote to</param>
Writes the il code to promote typeExp1 to typeExp2
Writes the il code to promote typeExp1 to typeExp2
public void Promotion(int indent, TypeExpression typeExp1, TypeExpression certainType1, TypeExpression typeExp2, TypeExpression certainType2, bool unidirectionalConversion, bool makeBoxing) {
            FieldType aux;
            bool isFieldType1 = false;
            bool isFieldType2 = false;
            UnionType union = null;
            if ((aux = TypeExpression.As<FieldType>(typeExp1)) != null) {
                typeExp1 = aux.FieldTypeExpression;
                isFieldType1 = true;
            }
            if ((aux = TypeExpression.As<FieldType>(typeExp2)) != null) {
                typeExp2 = aux.FieldTypeExpression;
                isFieldType2 = true;
            }
            if ((aux = TypeExpression.As<FieldType>(certainType1)) != null)
                certainType1 = aux.FieldTypeExpression;
            if ((aux = TypeExpression.As<FieldType>(certainType2)) != null)
                certainType2 = aux.FieldTypeExpression;
            if (!certainType1.IsFreshVariable() && !TypeExpression.Is<UnionType>(certainType1))
            {
                if (certainType1.IsValueType() && certainType2.IsValueType()) {
                    if (TypeExpression.Is<DoubleType>(certainType2) &&
                        (TypeExpression.Is<CharType>(certainType1) || TypeExpression.Is<IntType>(certainType1))) {
                        if (typeExp1 is TypeVariable && makeBoxing)
                            this.UnboxAny(indent, certainType1);
                        this.convToDouble(indent);
                    } else {
                        if (!(TypeExpression.Is<IntType>(certainType2) && TypeExpression.Is<CharType>(certainType1))) {
                            if (certainType1 == certainType2 || certainType1.ILType().Equals(certainType2.ILType()))
                            {
                                if (isFieldType1) {
                                    if (typeExp1 is TypeVariable)
                                        this.UnboxAny(indent, certainType1);
                                } else {
                                    if (!isFieldType1 && isFieldType2) {
                                        if (typeExp2 is TypeVariable)
                                            this.Box(indent, certainType2);
                                    }
                                }
                            } else {
                                if (typeExp1 is TypeVariable && makeBoxing)
                                {
                                    if (!TypeExpression.Is<UnionType>(certainType2))
                                        this.UnboxAny(indent, certainType2);
                                }
                                else
                                {
                                    if (!TypeExpression.Is<UnionType>(certainType1) && TypeExpression.Is<UnionType>(certainType2))
                                    {
                                        if (unidirectionalConversion)
                                            this.Box(indent, certainType1);
                                    }
                                    if ((union = TypeExpression.As<UnionType>(certainType1)) != null && !TypeExpression.Is<UnionType>(certainType2))
                                    {
                                        if (!IsUnionOfProperties(union))
                                            certainType2.AcceptOperation(new CGRuntimeUnionTypePromotionOperation<ILCodeGenerator>(indent, this, union), null);
                                        else if(union.Count > 0)
                                        {
                                            PropertyType propertyType = TypeExpression.As<PropertyType>(union.TypeSet[0]);
                                            Promotion(indent, propertyType.PropertyTypeExpression, propertyType.PropertyTypeExpression, typeExp2, certainType2, unidirectionalConversion, makeBoxing);
                                        }
                                    }
                                }
                                if (unidirectionalConversion) {
                                    if (!(typeExp1 is TypeVariable) && typeExp2 is TypeVariable && makeBoxing)
                                        this.Box(indent, certainType2);
                                }
                            }
                        }
                    }
                    return;
                }
                if (certainType1.IsValueType() && !certainType2.IsValueType()) {
                    if (unidirectionalConversion) {
                        if ((!(typeExp1 is TypeVariable)) || (TypeExpression.Is<UnionType>(certainType2)))
                            this.Box(indent, certainType1);
                        else if(!makeBoxing && !(TypeExpression.Is<UnionType>(certainType1)) && certainType2.FullName.Equals(typeof(Object).FullName))
                            this.Box(indent, certainType1);
                        else if (certainType2 is TypeVariable && ((TypeVariable)certainType2).Substitution == null && !isFieldType1)                        
                            this.Box(indent, certainType1);
                        else if (certainType2 is TypeVariable && ((TypeVariable)certainType2).Substitution == null && ((TypeVariable)certainType2).EquivalenceClass != null)
                            this.Box(indent, certainType1);
                    }
                    if (TypeExpression.Is<StringType>(certainType2))
                        this.CallVirt(indent, "instance", "string", "[mscorlib]System.Object", "ToString", null);
                    return;
                }
                if (!certainType1.IsValueType() && certainType2.IsValueType()) {
                    if (TypeExpression.Is<UnionType>(certainType1))
                        this.RuntimeFreshTypeExpressionPromotion(indent, certainType2);
                        ////
                        certainType2.AcceptOperation(new CGRuntimeFreshTEPromotionOperation<ILCodeGenerator>(indent, this), null);
                    else
                        this.UnboxAny(indent, certainType2);                    
                    return;
                }
                if ((union = TypeExpression.As<UnionType>(certainType1)) != null && !TypeExpression.Is<UnionType>(certainType2) && (certainType2.IsValueType() || TypeExpression.Is<StringType>(certainType2)))
                    certainType2.AcceptOperation(new CGRuntimeUnionTypePromotionOperation<ILCodeGenerator>(indent, this, union), null);
            }
            else if (certainType1.IsFreshVariable())
            {
                this.RuntimeFreshTypeExpressionPromotion(indent, certainType2);
                ////IL
                certainType2.AcceptOperation(new CGRuntimeFreshTEPromotionOperation<ILCodeGenerator>(indent, this), null);
            }
            else if (TypeExpression.Is<UnionType>(certainType1) && IsValueType(certainType2))
            {
                certainType2.AcceptOperation(new CGRuntimeFreshTEPromotionOperation<ILCodeGenerator>(indent, this), null);
            }
        }
public void Promotion ( int indent , TypeExpression typeExp1 , TypeExpression certainType1 , TypeExpression typeExp2 , TypeExpression certainType2 , bool unidirectionalConversion , bool makeBoxing ) { FieldType aux ; bool isFieldType1 = false ; bool isFieldType2 = false ; UnionType union = null ; if ( ( aux = TypeExpression . As < FieldType > ( typeExp1 ) ) != null ) { typeExp1 = aux . FieldTypeExpression ; isFieldType1 = true ; } if ( ( aux = TypeExpression . As < FieldType > ( typeExp2 ) ) != null ) { typeExp2 = aux . FieldTypeExpression ; isFieldType2 = true ; } if ( ( aux = TypeExpression . As < FieldType > ( certainType1 ) ) != null ) certainType1 = aux . FieldTypeExpression ; if ( ( aux = TypeExpression . As < FieldType > ( certainType2 ) ) != null ) certainType2 = aux . FieldTypeExpression ; if ( ! certainType1 . IsFreshVariable ( ) && ! TypeExpression . Is < UnionType > ( certainType1 ) ) { if ( certainType1 . IsValueType ( ) && certainType2 . IsValueType ( ) ) { if ( TypeExpression . Is < DoubleType > ( certainType2 ) && ( TypeExpression . Is < CharType > ( certainType1 ) || TypeExpression . Is < IntType > ( certainType1 ) ) ) { if ( typeExp1 is TypeVariable && makeBoxing ) this . UnboxAny ( indent , certainType1 ) ; this . convToDouble ( indent ) ; } else { if ( ! ( TypeExpression . Is < IntType > ( certainType2 ) && TypeExpression . Is < CharType > ( certainType1 ) ) ) { if ( certainType1 == certainType2 || certainType1 . ILType ( ) . Equals ( certainType2 . ILType ( ) ) ) { if ( isFieldType1 ) { if ( typeExp1 is TypeVariable ) this . UnboxAny ( indent , certainType1 ) ; } else { if ( ! isFieldType1 && isFieldType2 ) { if ( typeExp2 is TypeVariable ) this . Box ( indent , certainType2 ) ; } } } else { if ( typeExp1 is TypeVariable && makeBoxing ) { if ( ! TypeExpression . Is < UnionType > ( certainType2 ) ) this . UnboxAny ( indent , certainType2 ) ; } else { if ( ! TypeExpression . Is < UnionType > ( certainType1 ) && TypeExpression . Is < UnionType > ( certainType2 ) ) { if ( unidirectionalConversion ) this . Box ( indent , certainType1 ) ; } if ( ( union = TypeExpression . As < UnionType > ( certainType1 ) ) != null && ! TypeExpression . Is < UnionType > ( certainType2 ) ) { if ( ! IsUnionOfProperties ( union ) ) certainType2 . AcceptOperation ( new CGRuntimeUnionTypePromotionOperation < ILCodeGenerator > ( indent , this , union ) , null ) ; else if ( union . Count > 0 ) { PropertyType propertyType = TypeExpression . As < PropertyType > ( union . TypeSet [ 0 ] ) ; Promotion ( indent , propertyType . PropertyTypeExpression , propertyType . PropertyTypeExpression , typeExp2 , certainType2 , unidirectionalConversion , makeBoxing ) ; } } } if ( unidirectionalConversion ) { if ( ! ( typeExp1 is TypeVariable ) && typeExp2 is TypeVariable && makeBoxing ) this . Box ( indent , certainType2 ) ; } } } } return ; } if ( certainType1 . IsValueType ( ) && ! certainType2 . IsValueType ( ) ) { if ( unidirectionalConversion ) { if ( ( ! ( typeExp1 is TypeVariable ) ) || ( TypeExpression . Is < UnionType > ( certainType2 ) ) ) this . Box ( indent , certainType1 ) ; else if ( ! makeBoxing && ! ( TypeExpression . Is < UnionType > ( certainType1 ) ) && certainType2 . FullName . Equals ( typeof ( Object ) . FullName ) ) this . Box ( indent , certainType1 ) ; else if ( certainType2 is TypeVariable && ( ( TypeVariable ) certainType2 ) . Substitution == null && ! isFieldType1 ) this . Box ( indent , certainType1 ) ; else if ( certainType2 is TypeVariable && ( ( TypeVariable ) certainType2 ) . Substitution == null && ( ( TypeVariable ) certainType2 ) . EquivalenceClass != null ) this . Box ( indent , certainType1 ) ; } if ( TypeExpression . Is < StringType > ( certainType2 ) ) this . CallVirt ( indent , " " , " " , " " , " " , null ) ; return ; } if ( ! certainType1 . IsValueType ( ) && certainType2 . IsValueType ( ) ) { if ( TypeExpression . Is < UnionType > ( certainType1 ) ) certainType2 . AcceptOperation ( new CGRuntimeFreshTEPromotionOperation < ILCodeGenerator > ( indent , this ) , null ) ; else this . UnboxAny ( indent , certainType2 ) ; return ; } if ( ( union = TypeExpression . As < UnionType > ( certainType1 ) ) != null && ! TypeExpression . Is < UnionType > ( certainType2 ) && ( certainType2 . IsValueType ( ) || TypeExpression . Is < StringType > ( certainType2 ) ) ) certainType2 . AcceptOperation ( new CGRuntimeUnionTypePromotionOperation < ILCodeGenerator > ( indent , this , union ) , null ) ; } else if ( certainType1 . IsFreshVariable ( ) ) { certainType2 . AcceptOperation ( new CGRuntimeFreshTEPromotionOperation < ILCodeGenerator > ( indent , this ) , null ) ; } else if ( TypeExpression . Is < UnionType > ( certainType1 ) && IsValueType ( certainType2 ) ) { certainType2 . AcceptOperation ( new CGRuntimeFreshTEPromotionOperation < ILCodeGenerator > ( indent , this ) , null ) ; } }
Writes the il code to promote typeExp1 to typeExp2
Writes the il code to promote typeExp1 to typeExp2
// * If both values are built-in, check promotion of int to double // Only converts integer to double. If certain type1==Double laconversión es necesaria // if certainType1 and certainType2 are the same value type, and one of this is a field variable type, then make boxing. // ValueType to TypeVariable // - This code is only execute if the conversion is unidirectional (e.g. argument to parameter) // - The conversion can be bidirectional (e.g a != b; type(a) to type(b) or type(b) to type(a)  //   In this case, the correct conversion is to make an Unbox on TypeVariable and not to make a Box on ValueType. //   Note: Relational expressions are different of the rest of binary expression. //         e.g. a + b; 'a' or 'b' are going to promote to the type of arithmetical node. But, in relational expression,  //         the type of this expression is always bool, but it is possible that 'a' has to promote to 'b' or viceversa. // * If the built-in must promote to an object, boxing is required //if (!(typeExp1 is TypeVariable)) //If TypeExp1 is a TypeVariable boxing is no needed // * If the expected type is an String, we must call its ToString method // If the object must promote to an built-in, unboxing is required ///// /////this.RuntimeFreshTypeExpressionPromotion(indent, certainType2); //////////////////////// // * We require a runtime check to know if a promotion is needed ///// /////this.RuntimeFreshTypeExpressionPromotion(indent, certainType2); ////////////////////////IL
indent
int
typeExp1
TypeExpression
The type of the element that is in the stack
The type of the element that is in the stack
certainType1
TypeExpression
typeExp2
TypeExpression
The type to promote to
The type to promote to
certainType2
TypeExpression
unidirectionalConversion
bool
makeBoxing
bool