/// <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)); }
/// <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)); }