/// <summary>
        /// This method check whether the firstOperand is has fresh varuabkes, in wich case it apply the operation
        /// to all the variable in the union
        /// </summary>
        /// <param name="firstOperand">A UnionType TypeExpression, to operate with the operator and second operand </param>
        /// <returns>in this case the TypeExpression associated with the field is valid it returns the result of aplying the operation
        /// with to the Union the operator and second operand, stored in the TypeSystemOperation Object.
        /// Null in case the Field does not contain a valid TypeExpression.
        /// </returns>
        public override object Exec(UnionType firstOperand, object arg)
        {
            // * If all the types in typeset generate a constraint, we simply generate one constraint using the whole union type
            if (firstOperand.IsFreshVariable() && methodAnalyzed != null)
            {
                // * A constraint is added to the method analyzed
                ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand, binaryOperator, location);
                methodAnalyzed.AddConstraint(constraint);
                return(constraint.ReturnType);
            }
            TypeExpression returnType = null;

            foreach (TypeExpression type in firstOperand.TypeSet)
            {
                TypeExpression ret = (TypeExpression)type.AcceptOperation(ArithmeticalOperation.Create(secondOperand, binaryOperator, methodAnalyzed, !firstOperand.IsDynamic && showErrorMessage, location), arg);
                if (ret == null && !firstOperand.IsDynamic)
                {
                    return(null);
                }
                if (ret != null)
                {
                    returnType = UnionType.collect(returnType, ret);
                }
            }
            // * If there has been some errors, they have not been shown because the type is dynamic, we show it
            if (showErrorMessage && firstOperand.IsDynamic && returnType == null)
            {
                ErrorManager.Instance.NotifyError(new NoTypeAcceptsOperation(firstOperand.FullName, this.binaryOperator.ToString(), secondOperand.FullName, location));
            }
            return(returnType);
        }
 /// <summary>
 /// This method check whether the firstOperand is valid, and in this case it returns the TypeExpression associated with the field
 /// and perform the operation with this property and the operator and second operand, stored in the TypeSystemOperation Object.
 /// </summary>
 /// <param name="firstOperand">A PropertyType TypeExpression, to operate with the operator and second operand </param>
 /// <returns>in case the TypeExpression associated with the property is valid it returns the result of aplying the operation
 /// with this property and the operator and second operand, stored in the TypeSystemOperation Object.
 /// Null in case the PropertyType does not contain a valid TypeExpression.
 /// </returns>
 public override object Exec(PropertyType firstOperand, object arg)
 {
     if (firstOperand.PropertyTypeExpression != null)
     {
         return(firstOperand.PropertyTypeExpression.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg));
     }
     return(null);
 }
 /// <summary>
 /// The first Operand is a CharType so the second must be promotable in such way that the whole operation must have sense.
 /// Implements a double dispatch pattern.
 /// </summary>
 /// <param name="firstOperand">an CharType to perform a binary arithmetical operatin with. The second operator must
 /// be promotable to Char, IntType, StringType, or DoubleType</param>
 /// <returns>A TypeExpression if the operation makes sense, otherwise if showMessages is true, an error is raised</returns>
 public override object Exec(CharType firstOperand, object arg)
 {
     if ((int)this.secondOperand.AcceptOperation(new PromotionLevelOperation(firstOperand), arg) != -1)
     {
         return(IntType.Instance);
     }
     if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
     {
         return(StringType.Instance);
     }
     return(this.secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg));
 }
 /// <summary>
 /// The first Operand is a Double so the second must be promotable to a DoubleType so the whole operation must have sense.
 /// Implements a double dispatch pattern.
 /// </summary>
 /// <param name="firstOperand">A double type to perform a binary arithmetica operation with. The second operate have to be promotable
 /// to Double, cause is the grater integral value.</param>
 /// <returns>A TypeExpression if the operation makes sense, otherwise if showMessages is true, an error is raised</returns>
 public override object Exec(DoubleType firstOperand, object arg)
 {
     if ((int)this.secondOperand.AcceptOperation(new PromotionLevelOperation(firstOperand), arg) != -1)
     {
         return(DoubleType.Instance);
     }
     if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
     {
         return(StringType.Instance);
     }
     // We rely in arithmetic conmutativiness to perform a cross recursion. Could it be dangerous?
     return(secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg));
 }
        //TODO: en la versión original, en vez de promotable to a string se preguntaba por string
        /// <summary>
        /// The first Operand is a StringType so the second must be promotable in such way that the whole operation returns StringType.
        /// Implements a double dispatch pattern.
        /// </summary>
        /// <param name="firstOperand">an CharType to perform a binary arithmetical operatin with. The second operator must
        /// be promotable to Char, IntType, StringType, or DoubleType</param>
        /// <returns>StringType if the operation makes sense, otherwise if showMessages is true, an error is raised</returns>
        public override object Exec(StringType firstOperand, object arg)
        {
            if (binaryOperator.Equals(ArithmeticOperator.Plus))
            {
                if (promotableToStringInAddition(this.secondOperand))
                {
                    return(StringType.Instance);
                }

                // * Commutative
                return(secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg));
            }
            return(ReportError(firstOperand));
        }
Ejemplo n.º 6
0
 /// <summary>
 /// The first Operand is a Double so the second must be promotable to a DoubleType so the whole operation must have sense.
 /// Implements a double dispatch pattern.
 /// </summary>
 /// <param name="firstOperand">A double type to perform a binary arithmetica operation with. The second operate have to be promotable
 /// to Double, cause is the grater integral value.</param>
 /// <returns>A TypeExpression if the operation makes sense, otherwise if showMessages is true, an error is raised</returns>
 public override object Exec(DoubleType firstOperand, object arg)
 {
     if ((int)this.secondOperand.AcceptOperation(new PromotionLevelOperation(firstOperand), arg) != -1)
     {
         if (secondOperand is TypeVariable)
         {
             if (methodAnalyzed != null && ((TypeVariable)secondOperand).Substitution == null)
             {
                 // * A constraint is added to the method analyzed
                 ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand, binaryOperator, location);
                 methodAnalyzed.AddConstraint(constraint);
                 return(constraint.ReturnType);
             }
         }
         return(DoubleType.Instance);
     }
     if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
     {
         return(StringType.Instance);
     }
     // We rely in arithmetic conmutativiness to perform a cross recursion. Could it be dangerous?
     return(secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg));
 }