The StaDyn Programming Language
Source code documentation of StaDyn, a hybrid static and dynamic typing language.
BinaryArithmeticalOperation.cs
Go to the documentation of this file.
1 using TypeSystem;
2 using AST;
3 using ErrorManagement;
4 using System;
5 using DynVarManagement;
6 using TypeSystem.Constraints;
7 namespace TypeSystem.Operations {
16  #region Fields
17  protected TypeExpression secondOperand;
24  protected Enum binaryOperator;
32  protected bool showErrorMessage;
36  protected Location location;
37  #endregion
38 
39  #region Constructor
40  public BinaryArithmeticalOperation(TypeExpression secondOperand, Enum binaryOperator, MethodType methodAnalyzed, bool showErrorMessage, Location location) {
54 
55  this.secondOperand = secondOperand;
56  this.binaryOperator = binaryOperator;
57  this.methodAnalyzed = methodAnalyzed;
58  this.showErrorMessage = showErrorMessage;
59  this.location = location;
60  }
61  #endregion
62 
63  #region BoolType +-secondOperand
64  public override object Exec(BoolType firstOperand, object arg) {
74  if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
75  return StringType.Instance;
76  if (this.showErrorMessage) //TODO: REvisar ESta SIgnaTURA
77  ErrorManager.Instance.NotifyError(new TypePromotionError(firstOperand.FullName, this.secondOperand.FullName, this.binaryOperator.ToString(), this.location));
78  return null;
79  }
80  #endregion
81 
82  #region DoubleType +-secondOperand
83  public override object Exec(DoubleType firstOperand, object arg) {
91  if ((int)this.secondOperand.AcceptOperation(new PromotionLevelOperation(firstOperand), arg) != -1)
92  {
93  if (secondOperand is TypeVariable)
94  {
95  if (methodAnalyzed != null && ((TypeVariable)secondOperand).Substitution == null)
96  {
97  // * A constraint is added to the method analyzed
98  ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand, binaryOperator, location);
99  methodAnalyzed.AddConstraint(constraint);
100  return constraint.ReturnType;
101  }
102  }
103  return DoubleType.Instance;
104  }
105  if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
106  return StringType.Instance;
107  // We rely in arithmetic conmutativiness to perform a cross recursion. Could it be dangerous?
108  return secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg);
109  }
110  #endregion
111 
112  #region IntType +-secondOperand
113  public override object Exec(IntType firstOperand, object arg) {
121  if ((int)this.secondOperand.AcceptOperation(new PromotionLevelOperation(firstOperand), arg) != -1)
122  {
123  if (secondOperand is TypeVariable && ((TypeVariable) secondOperand).Substitution == null)
124  {
125  if (methodAnalyzed != null)
126  {
127  // * A constraint is added to the method analyzed
128  ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand,
129  binaryOperator, location);
130  methodAnalyzed.AddConstraint(constraint);
131  return constraint.ReturnType;
132  }
133  }
134  return IntType.Instance;
135  }
136  if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
137  return StringType.Instance;
138  return this.secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg);
139  }
140  #endregion
141 
142  #region CharType +-secondOperand
143  public override object Exec(CharType firstOperand, object arg) {
151  if ((int)this.secondOperand.AcceptOperation(new PromotionLevelOperation(firstOperand), arg) != -1)
152  {
153  if (secondOperand is TypeVariable && ((TypeVariable)secondOperand).Substitution == null)
154  {
155  if (methodAnalyzed != null)
156  {
157  // * A constraint is added to the method analyzed
158  ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand,
159  binaryOperator, location);
160  methodAnalyzed.AddConstraint(constraint);
161  return constraint.ReturnType;
162  }
163  }
164  return IntType.Instance;
165  }
166  if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
167  return StringType.Instance;
168  return this.secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg);
169  }
170  #endregion
171 
172  #region StringType +-secondOperand
173 
174  //TODO: en la versión original, en vez de promotable to a string se preguntaba por string
182  public override object Exec(StringType firstOperand, object arg) {
183  if (binaryOperator.Equals(ArithmeticOperator.Plus)) {
184  if (promotableToStringInAddition(this.secondOperand))
185  return StringType.Instance;
186 
187  // * Commutative
188  return secondOperand.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg);
189  }
190  return ReportError(firstOperand);
191  }
192  #endregion
193 
194  #region
195  protected bool promotableToStringInAddition(TypeExpression tE) {
205  return (int)tE.AcceptOperation(new PromotionLevelOperation(DoubleType.Instance), null) != -1
206  || (bool)tE.AcceptOperation(new EquivalentOperation(CharType.Instance), null)
207  || (bool)tE.AcceptOperation(new EquivalentOperation(StringType.Instance), null)
208  || (bool)tE.AcceptOperation(new EquivalentOperation(NullType.Instance), null);
209 
210  }
211  #endregion
212 
213  #region NullType +-secondOperand
214  public override object Exec(NullType firstOperand, object arg) {
222  if (this.binaryOperator.Equals(ArithmeticOperator.Plus) && (bool)this.secondOperand.AcceptOperation(new EquivalentOperation(StringType.Instance), arg))
223  return StringType.Instance;
224  if (showErrorMessage)
225  ErrorManager.Instance.NotifyError(new TypePromotionError(this.secondOperand.FullName, firstOperand.FullName, this.binaryOperator.ToString(), this.location));
226  return null;
227  }
228  #endregion
229 
230  #region FieldType +-secondOperand
231  public override object Exec(FieldType firstOperand, object arg) {
241  if (firstOperand.FieldTypeExpression != null)
242  return firstOperand.FieldTypeExpression.AcceptOperation(this, arg);
243  return null;
244  }
245  #endregion
246 
247  #region PropertyType +-secondOperand
248  public override object Exec(PropertyType firstOperand, object arg) {
258  if (firstOperand.PropertyTypeExpression != null)
259  return firstOperand.PropertyTypeExpression.AcceptOperation(ArithmeticalOperation.Create(firstOperand, this.binaryOperator, this.methodAnalyzed, this.showErrorMessage, this.location), arg);
260  return null;
261 
262  }
263  #endregion
264 
265  #region TypeVariable +-secondOperand
266  public override object Exec(TypeVariable firstOperand, object arg) {
274  if (firstOperand.Substitution != null) {
275  DynVarOptions.Instance.AssignDynamism(firstOperand.Substitution, firstOperand.IsDynamic);
276  return firstOperand.Substitution.AcceptOperation(this, arg);
277  }
278  if (methodAnalyzed != null) {
279  // * A constraint is added to the method analyzed
280  ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand, binaryOperator, location);
281  methodAnalyzed.AddConstraint(constraint);
282  return constraint.ReturnType;
283  }
284  if (showErrorMessage)
285  ErrorManager.Instance.NotifyError(new OperationNotAllowedError(binaryOperator.ToString(), firstOperand.FullName, secondOperand.FullName, location));
286 
287  return null;
288  }
289  #endregion
290 
291  #region UnionType +-secondOperand
292  public override object Exec(UnionType firstOperand, object arg) {
302  // * If all the types in typeset generate a constraint, we simply generate one constraint using the whole union type
303  if (firstOperand.IsFreshVariable() && methodAnalyzed != null) {
304  // * A constraint is added to the method analyzed
305  ArithmeticConstraint constraint = new ArithmeticConstraint(firstOperand, secondOperand, binaryOperator, location);
306  methodAnalyzed.AddConstraint(constraint);
307  return constraint.ReturnType;
308  }
309  TypeExpression returnType = null;
310  foreach (TypeExpression type in firstOperand.TypeSet) {
311  TypeExpression ret = (TypeExpression)type.AcceptOperation(ArithmeticalOperation.Create(secondOperand, binaryOperator, methodAnalyzed, !firstOperand.IsDynamic && showErrorMessage, location), arg);
312  if (ret == null && !firstOperand.IsDynamic)
313  return null;
314  if (ret != null)
315  returnType = UnionType.collect(returnType, ret);
316  }
317  // * If there has been some errors, they have not been shown because the type is dynamic, we show it
318  if (showErrorMessage && firstOperand.IsDynamic && returnType == null)
319  ErrorManager.Instance.NotifyError(new NoTypeAcceptsOperation(firstOperand.FullName, this.binaryOperator.ToString(), secondOperand.FullName, location));
320  return returnType;
321  }
322  #endregion
323 
324  #region Report Errors
325 
326  // in our case we only notify operations not allowed
327  // for other pruposes invoke explicitly another kind of error
328 
334  public override object ReportError(TypeExpression tE) {
335  if (this.showErrorMessage)
336  ErrorManager.Instance.NotifyError(new OperationNotAllowedError(this.binaryOperator.ToString(), tE.FullName, this.secondOperand.FullName, this.location));
337  return null;
338  }
339  #endregion
340 
341  }
342 }
static StringType Instance
Gets the unique instance of StringType
Definition: StringType.cs:57
Its operation AcceptOperation() returns an integer value that indicates a promotion level between two...
override string FullName
The full name in type variables is calculated just in time
Representa a union type.
Definition: UnionType.cs:36
Represents a error produced when tries to make an operation not allowed for the specified type...
static DoubleType Instance
Gets the unique instance of DoubleType
Definition: DoubleType.cs:57
Represent a string type.
Definition: StringType.cs:36
This class encapsulates a location in a specific file. Implements an Inmutable pattern. So it can be used in any context, that is his internal fields never change.
Definition: Location.cs:24
Represents a error produced when the type promotion can not be applied to specified expressions...
Represent a character type.
Definition: CharType.cs:38
Abstract class that represents all different types.
Represents a generic type expression
Definition: TypeVariable.cs:36
virtual string FullName
Gets the full name of the type Note: WriteType expression is the longest recursive representation of ...
No location information is provided within this class, because the exec methods invoked by the proper...
Represent a integer type.
Definition: IntType.cs:37
Represents a double type.
Definition: DoubleType.cs:36
ArithmeticOperator
Arithmetic binary operators
Represent a null type.
Definition: NullType.cs:36
TypeExpression FieldTypeExpression
Gets the field type.
Definition: FieldType.cs:58
override object ReportError(TypeExpression tE)
If showMessages is true it raises and error. It returns null
virtual bool IsDynamic
Indicates if the type has been set as dynamic
Location location
The location (file, line, column) of text being analysed.
override object Exec(StringType firstOperand, object arg)
The first Operand is a StringType so the second must be promotable in such way that the whole operati...
This class instantiates elements of type UnaryArithmeticalOperation, and BinaryArithmeticalOperation...
override bool IsFreshVariable()
To know if it is a type variable with no substitution
Definition: UnionType.cs:630
Representa a property type.
Definition: PropertyType.cs:34
override object AcceptOperation(TypeSystemOperation op, object arg)
Definition: StringType.cs:83
Representa a method type.
Definition: MethodType.cs:37
It represents constraints of the form: ret := op1 op op2 Where op is an arithmetic operator ...
override object AcceptOperation(TypeSystemOperation op, object arg)
static IntType Instance
Gets the unique instance of IntType
Definition: IntType.cs:57
Enum binaryOperator
operand to apply to the operands.
bool showErrorMessage
Indicates if an error message should be shown (used for dynamic types)
IList< TypeExpression > TypeSet
Gets the list of type expressions
Definition: UnionType.cs:57
TypeExpression Substitution
Gets the substitution; null if it does not exist
Represent a bool type.
Definition: BoolType.cs:36
TypeExpression PropertyTypeExpression
Gets the property type.
Definition: PropertyType.cs:64
static ArithmeticalOperation Create(UnaryOperator unaryOperator, MethodType methodAnalyzed, bool showErrorMessage, Location location)
A factory Method to create UnaryAritmeticaslOperation objects Implements a factory method...
Representa a field type.
Definition: FieldType.cs:37
MethodType methodAnalyzed
the actual method being analised.
Represents a error produced when a dynamic union type has no valid type to be applied an operation ...
virtual object AcceptOperation(TypeSystemOperation op, object arg)