The StaDyn Programming Language
Source code documentation of StaDyn, a hybrid static and dynamic typing language.
CGBinaryOperation.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using CodeGeneration.Operations;
4 using TypeSystem.Operations;
5 using TypeSystem;
6 using ErrorManagement;
7 using AST;
8 
9 namespace CodeGeneration.NewOperations
10 {
11  abstract class CGBinaryOperation<T> : TypeSystemOperation where T : ILCodeGenerator {
12 
14 
16 
17  protected T codeGenerator;
18 
19  protected int indent;
20 
21  protected object obj;
22 
23  protected string label_result;
24  protected string label_op2;
25 
26  protected CGBinaryOperation(VisitorILCodeGeneration<T> visitor, object obj, int indent, BinaryExpression node) {
27  this.codeGenerator = visitor.codeGenerator;
28  this.indent = indent;
29  this.visitor = visitor;
30  this.obj = obj;
31  this.node = node;
32  this.node.FirstOperand.Accept(this.visitor, this.obj);
33  }
34 
35  protected abstract void GenerateOperator(BinaryExpression node, TypeExpression result);
36  protected abstract UnionType GenerateAllUnionTypes();
37  protected abstract TypeExpression MajorType(TypeExpression typeExpression1, TypeExpression typeExpression2);
38 
39  public override object ReportError(TypeExpression te)
40  {
41  ErrorManager.Instance.NotifyError(new CodeGenerationError("No se ha definido la operación solicitada"));
42  return null;
43  }
44 
45  public override object Exec(TypeExpression typeExpression, object arg)
46  {
47  if (typeExpression is UnionType)
48  this.Exec(typeExpression as UnionType, arg);
49  else if (typeExpression is TypeVariable)
50  this.Exec(typeExpression as TypeVariable, arg);
51  else if (typeExpression is PropertyType)
52  this.Exec(((PropertyType)typeExpression).PropertyTypeExpression, arg);
53  else if (typeExpression is FieldType)
54  {
55  FieldType fieldType = ((FieldType) typeExpression);
56  if (fieldType.FieldTypeExpression is TypeVariable && ((TypeVariable)fieldType.FieldTypeExpression).Substitution != null && ((TypeVariable)fieldType.FieldTypeExpression).Substitution.IsValueType())
57  {
58  UnionType union = new UnionType();
59  union.AddType(((TypeVariable)((FieldType)typeExpression).FieldTypeExpression).Substitution);
60  this.Exec(union, arg);
61  }
62  else
63  this.Exec(((FieldType) typeExpression).FieldTypeExpression, arg);
64  }
65  else if (IsValueType(typeExpression) || TypeExpression.Is<StringType>(typeExpression))
66  GenerateRightOperand(typeExpression, this.node.SecondOperand.ILTypeExpression);
67  else if (typeExpression is NullType)
68  {
69  this.codeGenerator.ldnull(this.indent);
70  GenerateRightOperand(typeExpression, this.node.SecondOperand.ILTypeExpression);
71  }
72  else if (typeExpression is UserType)
73  {
74  GenerateRightOperand(typeExpression, this.node.SecondOperand.ILTypeExpression);
75  }
76  return null;
77  }
78 
79  public override object Exec(UnionType teLeft, object arg)
80  {
81  String finalLabel = this.codeGenerator.NewLabel;
82  String nextLabel = "";
83 
84  List<TypeExpression> typeSet = new List<TypeExpression>();
85  for (int i = 0; i < teLeft.TypeSet.Count; i++)
86  typeSet.AddRange(GetTypes(teLeft.TypeSet[i]));
87  typeSet = new List<TypeExpression>(new HashSet<TypeExpression>(typeSet));
88  if (typeSet.Count == 0 && !(this.node.SecondOperand.ExpressionType is NullType))
89  {
90  typeSet = new List<TypeExpression>(new HashSet<TypeExpression>(GenerateAllUnionTypes().TypeSet));
91  }
92  if (typeSet.Count > 0)
93  {
94  for (int i = 0; i < typeSet.Count; i++)
95  {
96  if (!String.IsNullOrEmpty(nextLabel))
97  this.codeGenerator.WriteLabel(indent, nextLabel);
98  if (i != typeSet.Count - 1)
99  {
100  nextLabel = this.codeGenerator.NewLabel;
101  this.codeGenerator.dup(indent);
102  this.codeGenerator.isinst(indent, typeSet[i]);
103  this.codeGenerator.brfalse(indent, nextLabel);
104  }
105  GenerateRightOperand(typeSet[i], this.node.SecondOperand.ExpressionType);
106  if (i != typeSet.Count - 1)
107  this.codeGenerator.br(indent, finalLabel);
108  }
109  this.codeGenerator.WriteLabel(indent, finalLabel);
110  }
111  else //All types of the UnionType are TypeVariables without substitution, and default union is empty
112  {
113  GenerateRightOperand(TypeVariable.NewTypeVariable, this.node.SecondOperand.ExpressionType);
114  }
115  return null;
116  }
117 
118  public override object Exec(TypeVariable teLeft, object arg)
119  {
120  //if (this.node.FirstOperand.ExpressionType is NullType || this.node.SecondOperand.ExpressionType is NullType)
121  if (teLeft.Substitution == null)
122  return this.Exec(GenerateAllUnionTypes(), arg);
123  else
124  return this.Exec(teLeft.Substitution, arg);
125  }
126 
127  private void GenerateRightOperand(TypeExpression teLeft, TypeExpression teRight)
128  {
129  if (teRight is UnionType)
130  this.GenerateRightOperand(teLeft, teRight as UnionType);
131  else if (teRight is TypeVariable)
132  this.GenerateRightOperand(teLeft, teRight as TypeVariable);
133  else if (teRight is PropertyType)
134  GenerateRightOperand(teLeft, ((PropertyType)teRight).PropertyTypeExpression);
135  else if (teRight is FieldType)
136  {
137  FieldType fieldType = ((FieldType)teRight);
138  if (fieldType.FieldTypeExpression is TypeVariable && ((TypeVariable)fieldType.FieldTypeExpression).Substitution != null && ((TypeVariable)fieldType.FieldTypeExpression).Substitution.IsValueType())
139  {
140  UnionType union = new UnionType();
141  union.AddType(((TypeVariable)((FieldType)teRight).FieldTypeExpression).Substitution);
142  GenerateRightOperand(teLeft, union);
143  }
144  else
145  GenerateRightOperand(teLeft, ((FieldType) teRight).FieldTypeExpression);
146  }
147  else if (IsValueType(teRight) || TypeExpression.Is<StringType>(teRight))
148  {
149  if (IsInternallyAnObject(node.FirstOperand))
150  {
151  if (!(teLeft is StringType) && IsValueType(teRight))
152  this.codeGenerator.UnboxAny(indent, teLeft);
153  }
154  else
155  {
156  if (!CheckUnBox(teLeft, teRight))
157  CheckBox(teLeft, teRight);
158  }
159  LoadSecondOperand();
160  if (IsInternallyAnObject(node.SecondOperand))
161  {
162  if (!(teRight is StringType) && IsValueType(teLeft))
163  this.codeGenerator.UnboxAny(indent, teRight);
164  }
165  else
166  {
167  if (!CheckUnBox(teRight, teLeft))
168  CheckBox(teRight, teLeft);
169  }
170  GenerateOperator(node, MajorType(teLeft, teRight));
171  }
172  else if(teRight is NullType)
173  {
174  this.codeGenerator.ldnull(this.indent);
175  GenerateOperator(node, MajorType(teLeft, teRight));
176  }
177  }
178 
179  protected bool IsInternallyAnObject(Expression expression)
180  {
181  TypeExpression typeExpression = expression.ExpressionType;
182  if (typeExpression is UnionType)
183  return true;
184  else if (typeExpression is NullType)
185  return true;
186  else if (typeExpression is TypeVariable)
187  {
188  if (((TypeVariable)typeExpression).Substitution == null)
189  return true;
190  if (IsValueType(((TypeVariable)typeExpression).Substitution))
191  return false;
192  if (IsValueType(expression.ILTypeExpression))
193  return false;
194  return true;
195  }
196  else if (typeExpression is PropertyType)
197  return !IsValueType(((PropertyType)typeExpression).PropertyTypeExpression);
198  else if (typeExpression is FieldType && ((FieldType)typeExpression).FieldTypeExpression is TypeVariable)
199  return true;
200  else if (typeExpression is FieldType)
201  return !IsValueType(((FieldType)typeExpression).FieldTypeExpression);
202  else if (typeExpression is StringType)
203  return true;
204  return false;
205  }
206 
207  protected virtual void GenerateRightOperand(TypeExpression teLeft, UnionType teRight)
208  {
209  List<TypeExpression> typeSet = new List<TypeExpression>();
210  for (int i = 0; i < teRight.TypeSet.Count; i++)
211  typeSet.AddRange(GetTypes(teRight.TypeSet[i]));
212  typeSet = new List<TypeExpression>(new HashSet<TypeExpression>(typeSet));
213  String finalLabel = this.codeGenerator.NewLabel;
214  String nextLabel = "";
215  if (typeSet.Count == 0)
216  typeSet.AddRange(GenerateAllUnionTypes().TypeSet);
217  for (int i = 0; i < typeSet.Count; i++)
218  {
219  if (!String.IsNullOrEmpty(nextLabel))
220  this.codeGenerator.WriteLabel(indent, nextLabel);
221  if (i != typeSet.Count - 1)
222  {
223  LoadSecondOperand();
224  nextLabel = this.codeGenerator.NewLabel;
225  this.codeGenerator.isinst(indent, typeSet[i]);
226  this.codeGenerator.brfalse(indent, nextLabel);
227  }
228  if ((node.FirstOperand.ExpressionType is UnionType || node.FirstOperand.ExpressionType is TypeVariable) && IsValueType(typeSet[i]) && IsInternallyAnObject(node.FirstOperand))
229  this.codeGenerator.UnboxAny(indent, teLeft);
230  else if (this.node.FirstOperand.ExpressionType is FieldType && ((FieldType)this.node.FirstOperand.ExpressionType).MemberInfo.Modifiers.Contains(Modifier.Static) && ((FieldType)this.node.FirstOperand.ExpressionType).FieldTypeExpression is TypeVariable)
231  this.codeGenerator.UnboxAny(indent, teLeft);
232  else if (this.node.FirstOperand.ExpressionType is FieldType && ((FieldType)this.node.FirstOperand.ExpressionType).FieldTypeExpression is TypeVariable && node.SecondOperand.ExpressionType.IsValueType())
233  this.codeGenerator.UnboxAny(indent, teLeft);
234  else if (this.node.FirstOperand.ExpressionType is FieldType && ((FieldType)this.node.FirstOperand.ExpressionType).FieldTypeExpression is TypeVariable && ((TypeVariable)((FieldType)this.node.FirstOperand.ExpressionType).FieldTypeExpression).Substitution == null)
235  this.codeGenerator.UnboxAny(indent, teLeft);
236  else if (IsValueType(node.FirstOperand.ExpressionType) && typeSet[i] is StringType)
237  this.codeGenerator.Box(indent, teLeft);
238  LoadSecondOperand();
239  if (!(typeSet[i] is StringType) && !(teLeft is StringType))
240  this.codeGenerator.UnboxAny(this.indent, typeSet[i]);
241  GenerateOperator(node, MajorType(teLeft, typeSet[i]));
242  if (i != typeSet.Count - 1)
243  this.codeGenerator.br(indent, finalLabel);
244  }
245  this.codeGenerator.WriteLabel(indent, finalLabel);
246  if (!String.IsNullOrEmpty(label_result))
247  this.codeGenerator.ldloc(this.indent, label_result);
248  }
249 
250 
251  protected virtual void LoadSecondOperand()
252  {
253  this.node.SecondOperand.Accept(this.visitor, this.obj);
254  }
255 
256 
257  protected List<TypeExpression> GetTypes(TypeExpression typeExpression, List<TypeExpression> evaluated = null)
258  {
259  List<TypeExpression> typeSet = new List<TypeExpression>();
260  if(evaluated == null)
261  evaluated = new List<TypeExpression>();
262  if (evaluated.Contains(typeExpression))
263  return typeSet;
264  else
265  evaluated.Add(typeExpression);
266  if (IsValueType(typeExpression) || typeExpression is StringType)
267  typeSet.Add(typeExpression);
268  else if (typeExpression is TypeVariable)
269  {
270  if (((TypeVariable)typeExpression).Substitution != null)
271  typeSet.AddRange(GetTypes(((TypeVariable)typeExpression).Substitution,evaluated));
272  }
273  else if (typeExpression is UnionType)
274  {
275  UnionType union = typeExpression as UnionType;
276  foreach (var expression in union.TypeSet)
277  typeSet.AddRange(GetTypes(expression,evaluated));
278  }
279  else if (typeExpression is FieldType)
280  {
281  FieldType fieldType = typeExpression as FieldType;
282  typeSet.AddRange(GetTypes(fieldType.FieldTypeExpression,evaluated));
283  }
284  else if (typeExpression is PropertyType)
285  {
286  PropertyType propertyType = typeExpression as PropertyType;
287  typeSet.AddRange(GetTypes(propertyType.PropertyTypeExpression,evaluated));
288  }
289  return typeSet;
290  }
291 
292  private void GenerateRightOperand(TypeExpression teLeft, TypeVariable teRight)
293  {
294  if (teRight.Substitution == null)
295  this.GenerateRightOperand(teLeft, GenerateAllUnionTypes());
296  else
297  this.GenerateRightOperand(teLeft, teRight.Substitution);
298  }
299 
300  protected bool CheckUnBox(TypeExpression op1, TypeExpression op2)
301  {
302  if (op1 is TypeVariable || op1 is UnionType || op1.HasTypeVariables())
303  {
304  if (IsValueType(op2) || op2 is TypeVariable || op2 is UnionType)
305  {
306  this.codeGenerator.UnboxAny(indent, op1);
307  return true;
308  }
309  }
310  return false;
311  }
312 
313  protected bool CheckBox(TypeExpression op1, TypeExpression op2)
314  {
315  if (IsValueType(op1))
316  {
317  if (op2 is StringType)
318  {
319  this.codeGenerator.Box(indent, op1);
320  return true;
321  }
322  }
323  return false;
324  }
325 
326  protected bool IsValueType(TypeExpression exp)
327  {
328  if (exp is BoolType)
329  return true;
330  if (exp is CharType)
331  return true;
332  if (exp is IntType)
333  return true;
334  if (exp is DoubleType)
335  return true;
336  if (exp is TypeVariable)
337  return IsValueType(((TypeVariable) exp).Substitution);
338  return false;
339  }
340  }
341 }
Encapsulates a binary expression of our programming language.
override object ReportError(TypeExpression te)
Abstract class encapsulate a programming language expression.
Definition: Expression.cs:37
static TypeVariable NewTypeVariable
Gets a new identify to the variable type
Definition: TypeVariable.cs:67
Representa a union type.
Definition: UnionType.cs:36
List< TypeExpression > GetTypes(TypeExpression typeExpression, List< TypeExpression > evaluated=null)
This class walks the AST to obtain the IL code.
Represent a string type.
Definition: StringType.cs:36
This class represent the entry wnen sending a message to an operation object derived from TypeExpress...
override object Exec(TypeVariable teLeft, object arg)
Represent a character type.
Definition: CharType.cs:38
Abstract class that represents all different types.
Represents a generic type expression
Definition: TypeVariable.cs:36
CGBinaryOperation(VisitorILCodeGeneration< T > visitor, object obj, int indent, BinaryExpression node)
bool CheckUnBox(TypeExpression op1, TypeExpression op2)
Represent a integer type.
Definition: IntType.cs:37
Represents a error produced when a MethodType has class information and tries to assign other class i...
abstract bool IsValueType()
True if type expression is a ValueType. Otherwise, false.
Represents a double type.
Definition: DoubleType.cs:36
Represent a null type.
Definition: NullType.cs:36
TypeExpression FieldTypeExpression
Gets the field type.
Definition: FieldType.cs:58
bool CheckBox(TypeExpression op1, TypeExpression op2)
Modifier
Indicates differents modifiers to use in class (only public, internal or static), fields or methods...
virtual bool HasTypeVariables()
To know if the type expression has some type variables and requieres unification The default implemen...
override object Exec(UnionType teLeft, object arg)
Representa a property type.
Definition: PropertyType.cs:34
virtual void GenerateRightOperand(TypeExpression teLeft, UnionType teRight)
override object Exec(TypeExpression typeExpression, object arg)
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
Representa a field type.
Definition: FieldType.cs:37
virtual TypeExpression ILTypeExpression
Gets the type expression to use in code generation.
Definition: Expression.cs:98
Represents a class or interface type.
Definition: UserType.cs:31