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 TypeSystem.Operations;
2 using TypeSystem;
3 using ErrorManagement;
4 using AST;
5 using Tools;
6 using System.Collections.Generic;
7 using CodeGeneration.ExceptionManagement;
8 namespace CodeGeneration.Operations {
14  internal struct Info {
15  internal TypeExpression typeExpression;
16  internal bool allTypeExpressions;
17  internal bool box;
18  internal bool unbox;
19  };
20  internal Info[] info = new Info[2];
21  // type of the second operand of an arithmetic expression
22  public bool firstTime; // indicates whether it is the last expressión, that is after this expression it is necessary to generate the end Label
26  public int operandOrdinal = 0;
27 
28  public int size = 2;
29 
30  public bool isEnd = false;
31 
33  this.info[0].allTypeExpressions = false;
34  this.info[0].typeExpression = t1;
35  this.info[0].box = false;
36  this.info[0].unbox = false;
37  this.info[1].allTypeExpressions = false;
38  this.info[1].typeExpression = t2;
39  this.info[1].box = false;
40  this.info[1].unbox = false;
41 
42  }
43 
45  this.size = c.size;
46  this.firstTime = c.firstTime;
47  this.operandOrdinal = c.operandOrdinal;
48  this.info = new Info[c.size];
49  this.isEnd = c.isEnd;
50  for ( int i = 0; i < c.size; i++ ) {
51  this.info[i].typeExpression = c.info[i].typeExpression;
52  this.info[i].allTypeExpressions = c.info[i].allTypeExpressions;
53  this.info[i].box = c.info[i].box;
54  this.info[i].unbox = c.info[i].unbox;
55  }
56  }
57  public CGBinaryOperationsInfo(TypeExpression typeExpression1, TypeExpression typeExpression2,
58  //string notThisTypeLabel,
59  int operandOrdinal, bool firstTime, bool allTypeExpressions1,
60  bool allTypeExpressions2)
61  : this(typeExpression1, typeExpression2) {
62  this.operandOrdinal = operandOrdinal;
63 
64  this.info[0].allTypeExpressions = allTypeExpressions1;
65  this.info[1].allTypeExpressions = allTypeExpressions2;
66  this.info[0].box = false;
67  this.info[0].unbox = false;
68  this.info[1].box = false;
69  this.info[1].unbox = false;
70 
71  }
72 
74  return new CGBinaryOperationsInfo(this);
75  }
76  //public CGBinaryOperationsInfo NewLabel(string label) {
77  // return new CGBinaryOperationsInfo(this.typeExpression1, this.typeExpression2, label, this.operandOrdinal, this.firstTime, this.allTypeExpressions1, this.allTypeExpressions2);
78  //}
79 
80 
82  CGBinaryOperationsInfo cl = this.Clone();
83  cl.firstTime = false;
84  return cl;
85 
86  }
87 
88  }
89  internal abstract class CGBinaryOperation<T> : TypeSystemOperation where T : ILCodeGenerator {
90 
91 
96  protected BinaryExpression node;
97 
98 
99  protected string endOperationLabel;
100 
101  protected string errorLabel;
102 
103  protected VisitorILCodeGeneration<T> visitor;
107  protected T codeGenerator;
111  protected int indent;
115  protected object obj;
116  private string finalizeOperationLabel;
124  public CGBinaryOperation(VisitorILCodeGeneration<T> visitor, object obj, int indent, BinaryExpression node) {
125  this.codeGenerator = visitor.codeGenerator;
126  this.indent = indent;
127  this.visitor = visitor;
128  this.obj = obj;
129  this.node = node;
130  this.errorLabel = string.Format("{0}_ERROR_OPERATION", this.codeGenerator.NewLabel);
131  this.endOperationLabel = string.Format("{0}_END_OPERATION", this.codeGenerator.NewLabel);
132  this.finalizeOperationLabel = string.Format("{0}_FINALIZE_OPERATION", this.codeGenerator.NewLabel);
133  this.node.FirstOperand.Accept(this.visitor, this.obj);
134 
135  }
136 
137  public virtual CGBinaryOperationsInfo GetFirstInfo(TypeExpression t1, object arg) {
138  CGBinaryOperationsInfo ret;
139  if ( arg == null ) {// it's the first call of the operation
140  ret = new CGBinaryOperationsInfo(t1, node.SecondOperand.ILTypeExpression);
141  ret.isEnd = true;
142  ret.firstTime = true;
143  } else
144  ret = ( (CGBinaryOperationsInfo)arg ).Clone();
145 
146  return ret;
147  }
148 
149 
150  public override object Exec(TypeVariable t, object arg) {
151 
152  TypeExpression te;
153  CGBinaryOperationsInfo info = GetFirstInfo(t, arg);
154 
155  if ( t.HasFreshVariable() ) {
156  te = GenerateAll(info, this.node);
157  info.info[info.operandOrdinal].allTypeExpressions = true;
158 
159  } else
160  te = t.Substitution;
161 
162  info.info[info.operandOrdinal].typeExpression = te;
163  info.info[info.operandOrdinal].unbox = true;
164  return info.info[0].typeExpression.AcceptOperation(this, info);
165  }
166 
167 
168  public override object Exec(TypeExpression t1, object arg) {
169  CGBinaryOperationsInfo cga = GetFirstInfo(t1, arg);
170 
171  TypeExpression t2 = cga.info[1].typeExpression;
172  // we check if the second operand is an UnionType
173  if ( TypeExpression.Is<UnionType>(t2) ) {
174  cga.operandOrdinal = 1;
175  node.SecondOperand.Accept(this.visitor, this.obj);
176  ExecUnionSecondOperand(t1, TypeExpression.As<UnionType>(t2), cga);
177  } else if ( TypeExpression.Is<TypeVariable>(t2) ) {
178  cga.operandOrdinal = 1;
179  Exec(TypeExpression.As<TypeVariable>(t2), cga);
180  } else {
181 
182  TypeExpression result = GenerateOperands(cga, node);
183 
184  GenerateOperator(cga, result, node);
185  MakeBoxIfNeeded(result, node);
186  this.codeGenerator.br(this.indent, this.endOperationLabel);
187 
188 
189  }
190  // else
191  if ( cga.isEnd )
192  EndOperation();
193  return null;
194  }
195 
196  public override object Exec(UnionType ut, object arg) {
197 
198  CGBinaryOperationsInfo ai = GetFirstInfo(ut, arg);
199  ai.isEnd = false;
200  UnionType utn = ut;
201  if ( !ai.info[0].allTypeExpressions && ut.HasFreshVariable() ) {
202  utn = GenerateAll(ai, this.node);
203  ai.info[0].allTypeExpressions = true;
204  }
205  string next = null;
206 
207  for ( int i = 0; i < utn.TypeSet.Count; i++ ) {
208  TypeExpression ti = ut.TypeSet[i];
209  CGBinaryOperationsInfo cgi = new CGBinaryOperationsInfo(ai);
210  cgi.info[cgi.operandOrdinal].typeExpression = ti;
211 
212  if ( TypeExpression.Is<TypeVariable>(ti) )
213  ti.AcceptOperation(this, cgi);
214  else if ( TypeExpression.Is<UnionType>(ti) ) {
215  cgi.firstTime = false;
216  this.indent++;
217  ti.AcceptOperation(this, cgi);
218  this.indent--;
219 
220  } else {
221  cgi.info[0].unbox = true;
222  cgi.info[0].box = false;
223  next = string.Format("{0}_1Op_not_a_{1}", this.codeGenerator.NewLabel, ti.ILType());
224  this.codeGenerator.Comment(this.indent, string.Format("1Op_case: [{0}]", ti.ILType()));
225  this.codeGenerator.dup(this.indent);
226  this.codeGenerator.isinst(this.indent, ti);
227  this.codeGenerator.brfalse(this.indent, i == utn.Count - 1 ? this.errorLabel : next);
228  ti.AcceptOperation(this, cgi);
229  this.codeGenerator.WriteLabel(this.indent, next);
230 
231  }
232 
233  }
234  if ( ai.firstTime )
235  EndOperation();
236  return null;
237  }
238  protected virtual void EndOperation() {
239  this.codeGenerator.br(this.indent, this.endOperationLabel);
240  this.codeGenerator.WriteLabel(this.indent, this.errorLabel);
241  this.codeGenerator.WriteThrowException(this.indent, new WrongDynamicTypeExceptionManager());
242  this.codeGenerator.AddExceptionCode(new WrongDynamicTypeExceptionManager());
243  this.codeGenerator.WriteLabel(this.indent, this.endOperationLabel);
244  }
245 
246  protected virtual void ExecUnionSecondOperand(TypeExpression t1, UnionType unionType, CGBinaryOperationsInfo cg) {
247  CGBinaryOperationsInfo cga = cg.Clone();
248  cga.isEnd = false;
249  UnionType utn = unionType;
250  if ( !cga.info[1].allTypeExpressions && utn.HasFreshVariable() ) {
251  utn = GenerateAll(cga, this.node);
252  cga.info[1].allTypeExpressions = true;
253  }
254  string next = null;
255 
256  for ( int i = 0; i < utn.TypeSet.Count; i++ ) {
257  TypeExpression ti = utn.TypeSet[i];
258  CGBinaryOperationsInfo cgi = cga.Clone();
259  cgi.info[cgi.operandOrdinal].typeExpression = ti;
260  cgi.info[0].typeExpression = t1;
261  next = string.Format("{0}_2Op_not_a_{1}", this.codeGenerator.NewLabel, ti.ILType());
262  this.codeGenerator.Comment(this.indent, string.Format("2Op_case: [{0}]", ti.ILType()));
263  if ( TypeExpression.Is<TypeVariable>(ti) )
264  ti.AcceptOperation(this, cgi);
265  else if ( TypeExpression.Is<UnionType>(ti) ) {
266  cgi.firstTime = false;
267 
268  this.codeGenerator.pop(this.indent);
269  this.indent++;
270  ti.AcceptOperation(this, cgi);
271  this.indent--;
272 
273  } else {
274  //this.node.SecondOperand.Accept(this.visitor, this.obj);
275  cgi.info[1].unbox = true;
276  cgi.info[1].box = false;
277  this.codeGenerator.dup(this.indent);
278  this.codeGenerator.isinst(this.indent, ti);
279  this.codeGenerator.brfalse(this.indent, i == utn.Count - 1 ? this.errorLabel : next);
280  this.codeGenerator.pop(this.indent);
281  t1.AcceptOperation(this, cgi);
282  }
283  this.codeGenerator.WriteLabel(this.indent, next);
284  }
285 
286  }
287 
288 
289 
290 
291  abstract protected void GenerateOperator(CGBinaryOperationsInfo cga, TypeExpression result, BinaryExpression node);
292  abstract protected UnionType GenerateAll(CGBinaryOperationsInfo ai, BinaryExpression b);
293 
294  virtual protected TypeExpression GenerateOperands(CGBinaryOperationsInfo cga, BinaryExpression node) {
295  TypeExpression majorType = MajorType(cga.info[0].typeExpression, cga.info[1].typeExpression);
296  if (cga.info[0].unbox)
297  MakeUnboxIfNeeded(cga.info[0].typeExpression);
298  CGConversion(cga.info[0], majorType);
299 
300 
301  this.node.SecondOperand.Accept(this.visitor, this.obj);
302  if ( cga.info[1].unbox )
303  MakeUnboxIfNeeded(cga.info[1].typeExpression);
304 
305  CGConversion(cga.info[1], majorType);
306 
307  return majorType;
308  }
309 
310  virtual protected void CGConversion(CGBinaryOperationsInfo.Info info, TypeExpression majorType) {
311  info.typeExpression.AcceptOperation(new CGConvertToOperation<ILCodeGenerator>(majorType, this.codeGenerator, this.indent), null);
312  }
313 
314  virtual protected TypeExpression MajorType(TypeExpression typeExpression1, TypeExpression typeExpression2) {
315  return (TypeExpression)typeExpression1.AcceptOperation(new MajorTypeOperation(typeExpression2), null);
316  }
317  virtual protected void MakeBoxIfNeeded(TypeExpression t, BinaryExpression node) {
318 
319  if ( TypeExpression.Is<UnionType>(node.ExpressionType) )
320  this.codeGenerator.BoxIfNeeded(this.indent, t);
321 
322  }
323  virtual protected void MakeUnboxIfNeeded(TypeExpression t) {
324 
325  if ( t.IsValueType() )
326  this.codeGenerator.UnboxAny(this.indent, t);
327  }
328  public override object ReportError(TypeExpression tE) {
329  ErrorManager.Instance.NotifyError(new CodeGenerationError("No se ha definido la operación solicitada"));
330  return null;
331  }
332  }
333 }
Encapsulates a binary expression of our programming language.
It typechecks the runtime arguments, embeded in a method call, with the parametes of this method...
override bool HasFreshVariable()
To know if it is a type variable with no substitution
Definition: UnionType.cs:908
Representa a union type.
Definition: UnionType.cs:36
virtual bool HasFreshVariable()
To know if it is a type variable with no substitution
This class walks the AST to obtain the IL code.
TypeExpression ExpressionType
Gets or sets the type of the expression.
Definition: Expression.cs:71
This class represent the entry wnen sending a message to an operation object derived from TypeExpress...
CGBinaryOperationsInfo(TypeExpression typeExpression1, TypeExpression typeExpression2, int operandOrdinal, bool firstTime, bool allTypeExpressions1, bool allTypeExpressions2)
Abstract class that represents all different types.
Represents a generic type expression
Definition: TypeVariable.cs:36
CGBinaryOperationsInfo(TypeExpression t1, TypeExpression t2)
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.
This class encapsulates the IL code to generate an exception produced when the type on the top of the...