The StaDyn Programming Language
Source code documentation of StaDyn, a hybrid static and dynamic typing language.
CGILMethodInvocationOperation.cs
Go to the documentation of this file.
1 // ------------------------------------------------------------------------------ //
3 // Project Stadyn //
4 // ------------------------------------------------------------------------------ //
5 // File: CGILMethodInvocationOperation.cs //
6 // Author: DanielZapico Rodríguez - daniel.zapico.rodriguez@gmail.com //
7 // Description: //
8 // This class encapsulates the operations to generate method calss in MSIL. //
9 // ------------------------------------------------------------------------------ //
10 // Create date: 3-3-2010 //
11 // Modification date: 3-3-2010 //
13 using System.Collections.Generic;
14 using AST;
15 using ErrorManagement;
16 using TypeSystem;
17 using TypeSystem.Operations;
18 using MethodInvocationArguments;
19 namespace CodeGeneration.Operations {
25  internal class CGILMethodInvocationOperation<T>:TypeSystemOperation where T:CLRCodeGenerator {
26 
30  private T codeGenerator;
34 
35  private VisitorCLRCodeGeneration<T> visitor;
36 
37  private int indent;
42 
47  InheritedAttributes inheritedAttributes;
48  InheritedAttributes objInv;
54  List<TypeExpression> nonValidObjectsList;
55 
56  private string endLabel;
57  private string nonValidObjectsLabel;
58  private string reflectionLabel;
59 
60  private bool areThereNonValidObjects;
61  private bool hasTypeVariable = false; // indi casi hay alguna variable de tipo en la TE
62  private bool firstTime = true; // indica si el trozo de expresion de tipo que estoy tratando es
63  //la expresion es completa y la primera vez que se accede. En el constructor siempre a true
64  object objArgs;
65 
66  public CGILMethodInvocationOperation(int indent, VisitorCLRCodeGeneration<T> visitor,
67  T codeGenerator, InvocationExpression node,
68  InheritedAttributes inheritedAttributes, object objArgs, InheritedAttributes objInv)
69  {
70  this.indent = indent;
71  this.codeGenerator = codeGenerator;
72  this.visitor = visitor;
73  this.node = node;
74  this.inheritedAttributes = inheritedAttributes;
75  this.objArgs = objArgs;
76  this.objInv = objInv;
77  this.endLabel = this.codeGenerator.NewLabel + "_END_LABEL";
78  this.nonValidObjectsLabel = this.codeGenerator.NewLabel + "_NON_VALID_OBJECT_CALLS";
79  this.reflectionLabel = this.codeGenerator.NewLabel + "_REFLECTION_CALLS";
80  this.areThereNonValidObjects = false;
81  this.hasTypeVariable = false;
82  this.firstTime = true;
83  FieldAccessExpression fieldAccessExpression = node.Identifier as FieldAccessExpression;
84  this.nonValidObjectsList = (List<TypeExpression>)fieldAccessExpression.Expression.ExpressionType.AcceptOperation(new CGPlainTypeExpressionOperation(), null);
85  }
86 
87 
88  public override object Exec(MethodType actualMethod, object arg) {
89  // * 1.1 The implicit object has a known type and can a lso have candidate methods maybe a candidate objec
90  if ( this.firstTime ) {
91  this.firstTime = false;
92  this.areThereNonValidObjects = TypeExpression.As<UnionType>(((FieldAccessExpression)this.node.Identifier).Expression.ExpressionType) != null;
93  if (areThereNonValidObjects)
94  {
95  this.nonValidObjectsLabel = codeGenerator.NewLabel;
96  this.node.Identifier.Accept(this.visitor, this.objArgs);
97  this.codeGenerator.isinst(this.indent, actualMethod.MemberInfo.Class);
98  this.codeGenerator.brfalse(this.indent, nonValidObjectsLabel);
99  }
100  this.InvokeSingleMethod(actualMethod, arg);
101  if(areThereNonValidObjects)
102  {
103  string end = codeGenerator.NewLabel;
104  this.codeGenerator.br(this.indent, end);
105  this.codeGenerator.WriteLabel(this.indent, this.nonValidObjectsLabel);
106  this.node.Identifier.Accept(this.visitor, this.objArgs);
107  this.codeGenerator.WriteThrowMissingMethodException(this.indent, ((AST.FieldAccessExpression)(this.node.Identifier)).FieldName.ILName);
108  this.codeGenerator.WriteLabel(this.indent, end);
109  }
110  return null;
111  }
112  this.InvokeUnionMethod(actualMethod, arg);
113  return null;
114 
115  }
116 
117  protected object InvokeSingleMethod(MethodType actualMethod, object arg) {
118  object decorationInformation = this.node.Identifier.Accept(this.visitor, this.objArgs);
119  // if (!this.nonValidObjectsList.Remove(actualMethod.MemberInfo.Class))
120  // this.codeGenerator.Comment("Removing..."+ actualMethod);
121  this.node.Arguments.Accept(this.visitor, this.objArgs);
122  this.codeGenerator.MakeCall(this.indent, this.node, decorationInformation, actualMethod, (FieldAccessExpression)this.node.Identifier, arg);
123  //If the actualMethod returns a TypeVariable and the InvocationExpression returns a ValueType an unboxing is needed, becasue there is not auto-unboxing from object to a ValueType.
124  if (actualMethod.Return is TypeVariable && actualMethod.Return.IsFreshVariable() && node.ExpressionType.IsValueType())
125  this.codeGenerator.UnboxAny(this.indent, node.ExpressionType);
126  // this.codeGenerator.br(this.indent, this.endLabel););
127  if (!this.inheritedAttributes.MessagePassed)
128  this.inheritedAttributes.MessagePassed = true;
129 
130  return decorationInformation;
131  }
132 
133  public override object Exec(TypeVariable t, object arg)
134  {
135  if (!t.IsFreshVariable())
136  return t.Substitution.AcceptOperation(this, arg);
137 
138  this.hasTypeVariable = true;
139  if (this.firstTime) {
140  this.firstTime = false;
141  this.areThereNonValidObjects = TypeExpression.As<UnionType>(((FieldAccessExpression)this.node.Identifier).Expression.ExpressionType) != null;
142  this.EndInvocationMethod(false);
143  }
144  return null;
145 
146  }
147 
148 
149  public override object Exec(UnionType ut, object arg) {
150  // No need to ask if is the original Expression (first time)
151  //this.areThereNonValidObjects = ut.IsDynamic; // ESTO NO SIRVe
152 
153  FieldAccessExpression fa = this.node.Identifier as FieldAccessExpression;
154  this.areThereNonValidObjects = fa.Expression.ExpressionType.IsDynamic;
155  bool oldFirstTime = this.firstTime;
156  this.firstTime = false;
157 
158  // * 1.2.1.1 The implicit object has unknown type (union types)
159  Dictionary<MethodInvocationArgument, object> dic = new Dictionary<MethodInvocationArgument, object>();
160  arg = dic;
161  dic[MethodInvocationArgument.Clean] = false;
162  dic[MethodInvocationArgument.MakeBox] = ut.ContainsDifferentReturns();
163  dic[MethodInvocationArgument.DecorationAttributes] = this.node.Identifier.Accept(this.visitor, this.objInv); // object o;
164 
165  foreach(TypeExpression ti in ut.TypeSet)
166  ti.AcceptOperation(this, arg);
167 
168  if (oldFirstTime) {
169  // we leave firstTime in false o maintain coherency in the object status
170  //this.codeGenerator.WriteLabel(this.indent, this.methodLabel);
171  this.EndInvocationMethod((bool)dic[MethodInvocationArgument.Clean]);
172  }
173 
174  return dic[MethodInvocationArgument.DecorationAttributes];
175  }
176 
177  private object InvokeUnionMethod(MethodType actualMethodCalled, object arg) {
178  List<string> nextMethod = new List<string>();
179  Dictionary<MethodInvocationArgument, object> dic = (Dictionary<MethodInvocationArgument, object>)arg;
180  if (this.nonValidObjectsList.Remove(actualMethodCalled.MemberInfo.Class))
181  this.codeGenerator.Comment("Removing..." + actualMethodCalled + " from non suitable objects");
182  string nextMethodLabel = this.codeGenerator.NewLabel;
183  if ( ( actualMethodCalled.MemberInfo.ModifierMask & Modifier.Static ) == 0 ) {
184  // check the invocation reference
185  dic[MethodInvocationArgument.Clean] = true;
186  this.codeGenerator.dup(this.indent);
187  this.codeGenerator.isinst(this.indent, actualMethodCalled.MemberInfo.Class);
188  this.codeGenerator.brfalse(this.indent, nextMethodLabel);
189  if ( actualMethodCalled.MemberInfo.Class.IsValueType() )
190  this.codeGenerator.Unbox(this.indent, actualMethodCalled.MemberInfo.Class);
191  }
192  InheritedAttributes ia = this.inheritedAttributes;
193  this.objArgs = new InheritedAttributes(ia.CurrentMethod, ia.Assignment, ia.Reference, ia.ArrayAccessFound, actualMethodCalled, ia.IsParentNodeAnInvocation);
194  // checks arguments with the parameters of the current method
195  this.visitor.RuntimeCheckArguments(this.node, this.objArgs, actualMethodCalled, nextMethod);
196  // call currentMethod
197  TypeExpression hasReturn = this.codeGenerator.MakeCall(this.indent, this.node, dic[MethodInvocationArgument.DecorationAttributes], actualMethodCalled, (FieldAccessExpression)this.node.Identifier, arg);
198  if ( hasReturn.IsValueType() && (bool) dic[MethodInvocationArgument.MakeBox])
199  this.codeGenerator.Box(this.indent, hasReturn);
200 
201  this.codeGenerator.br(this.indent, endLabel);
202  // Check next method
203  for ( int k = nextMethod.Count - 1; k >= 0; k-- ) {
204  this.codeGenerator.WriteLabel(this.indent, nextMethod[k]);
205  this.codeGenerator.pop(this.indent);
206  }
207  if ( (bool)dic[MethodInvocationArgument.Clean] )
208  this.codeGenerator.WriteLabel(this.indent, nextMethodLabel);
209 
210  return dic[MethodInvocationArgument.DecorationAttributes];
211  }
212 
213  private void EndInvocationMethod(bool clean)
214  {
215  if ( this.areThereNonValidObjects ) { //&& !this.hasTypeVariable) {
216  this.NonValidObjectsCodeGeneration();
217  }
218  if (this.hasTypeVariable) {
219  this.codeGenerator.Comment(indent, "Reflection Code");
220  if (clean)
221  this.codeGenerator.pop(indent);
222  this.codeGenerator.WriteLabel(this.indent, this.reflectionLabel);
223  InheritedAttributes ia = (InheritedAttributes) this.objArgs;
224  ia.IsIntrospectiveInvocation = true;
225  this.visitor.IntrospectiveInvocation(this.node, ia, this.inheritedAttributes, ( (FieldAccessExpression)this.node.Identifier ).FieldName.Identifier);
226 
227  }
228  this.codeGenerator.WriteLabel(this.indent, this.endLabel);
229  }
230 
231  private void NonValidObjectsCodeGeneration() {
232 
233  if (this.nonValidObjectsList.Count == 0) // It could be that all non suitable objects might be deleteded?
234  return;
235  string nextLabel = this.codeGenerator.NewLabel + "_END_NON_SUITABLE_OBJECTS_LABEL";
236  this.codeGenerator.Comment(this.indent, "Non suitable objects");
237  string te = string.Empty;;
238  foreach ( TypeExpression ti in this.nonValidObjectsList ) {
239  this.codeGenerator.dup(this.indent);
240  this.codeGenerator.Comment(this.indent, ti.FullName);
241  this.codeGenerator.isinst(this.indent, ti);
242  te = ti.ILType();
243  this.codeGenerator.brtrue(this.indent, this.nonValidObjectsLabel);
244 
245  }
246  this.codeGenerator.br(this.indent, nextLabel);
247  this.codeGenerator.WriteLabel(this.indent, this.nonValidObjectsLabel);
248  this.codeGenerator.WriteThrowNonSuitableObjectException(this.indent, te, ( (AST.FieldAccessExpression)( this.node.Identifier ) ).FieldName.ILName);
249  this.codeGenerator.Comment("Not reached");
250  this.codeGenerator.WriteLabel(this.indent, nextLabel); // not reached
251  }
252 
253  public override object Exec(TypeExpression t, object arg) {
254  this.codeGenerator.Comment(this.indent, "//entro por type expression");
255  return null;
256  }
257  public override object ReportError(TypeExpression tE) {
258  ErrorManager.Instance.NotifyError(new CodeGenerationError("//No se ha definido la operación solicitada. " + tE.FullName));
259  return null;
260  }
261 
262  }
263 }
Expression Identifier
Gets the expression to invoke
Encapsulates the expression to access a field.
Representa a union type.
Definition: UnionType.cs:36
Encapsulates a invocation expression.
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...
Modifier ModifierMask
Gets the modifier information
override bool IsFreshVariable()
To know if it is a type variable with no substitution
AccessModifier MemberInfo
Gets or sets the attribute information of method type
Definition: MethodType.cs:118
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 ...
TypeExpression Return
Gets type expression method return
Definition: MethodType.cs:100
Represents a error produced when a MethodType has class information and tries to assign other class i...
virtual bool IsFreshVariable()
To know if it is a type variable with no substitution
abstract bool IsValueType()
True if type expression is a ValueType. Otherwise, false.
Modifier
Indicates differents modifiers to use in class (only public, internal or static), fields or methods...
UserType Class
Gets or sets the class type reference
Representa a method type.
Definition: MethodType.cs:37
IList< TypeExpression > TypeSet
Gets the list of type expressions
Definition: UnionType.cs:57
TypeExpression Substitution
Gets the substitution; null if it does not exist
Expression Expression
Gets the expression to access a field.
virtual object AcceptOperation(TypeSystemOperation op, object arg)