13 using System.Collections.Generic;
15 using ErrorManagement;
17 using TypeSystem.Operations;
18 using MethodInvocationArguments;
19 namespace CodeGeneration.Operations {
25 internal class CGILMethodInvocationOperation<T>:
TypeSystemOperation where T:CLRCodeGenerator {
30 private T codeGenerator;
35 private VisitorCLRCodeGeneration<T> visitor;
47 InheritedAttributes inheritedAttributes;
48 InheritedAttributes objInv;
54 List<TypeExpression> nonValidObjectsList;
56 private string endLabel;
57 private string nonValidObjectsLabel;
58 private string reflectionLabel;
60 private bool areThereNonValidObjects;
61 private bool hasTypeVariable =
false;
62 private bool firstTime =
true;
66 public CGILMethodInvocationOperation(
int indent, VisitorCLRCodeGeneration<T> visitor,
68 InheritedAttributes inheritedAttributes,
object objArgs, InheritedAttributes objInv)
71 this.codeGenerator = codeGenerator;
72 this.visitor = visitor;
74 this.inheritedAttributes = inheritedAttributes;
75 this.objArgs = objArgs;
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;
88 public override object Exec(
MethodType actualMethod,
object arg) {
90 if ( this.firstTime ) {
91 this.firstTime =
false;
92 this.areThereNonValidObjects = TypeExpression.As<
UnionType>(((FieldAccessExpression)this.node.
Identifier).Expression.ExpressionType) != null;
93 if (areThereNonValidObjects)
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);
100 this.InvokeSingleMethod(actualMethod, arg);
101 if(areThereNonValidObjects)
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);
108 this.codeGenerator.WriteLabel(this.indent, end);
112 this.InvokeUnionMethod(actualMethod, arg);
117 protected object InvokeSingleMethod(
MethodType actualMethod,
object arg) {
118 object decorationInformation = this.node.Identifier.Accept(this.visitor, this.objArgs);
121 this.node.Arguments.Accept(this.visitor, this.objArgs);
122 this.codeGenerator.MakeCall(this.indent, this.node, decorationInformation, actualMethod, (FieldAccessExpression)this.node.
Identifier, arg);
125 this.codeGenerator.UnboxAny(this.indent, node.ExpressionType);
127 if (!this.inheritedAttributes.MessagePassed)
128 this.inheritedAttributes.MessagePassed =
true;
130 return decorationInformation;
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);
149 public override object Exec(
UnionType ut,
object arg) {
153 FieldAccessExpression fa = this.node.Identifier as FieldAccessExpression;
154 this.areThereNonValidObjects = fa.Expression.ExpressionType.IsDynamic;
155 bool oldFirstTime = this.firstTime;
156 this.firstTime =
false;
159 Dictionary<MethodInvocationArgument, object> dic =
new Dictionary<MethodInvocationArgument, object>();
161 dic[MethodInvocationArgument.Clean] =
false;
162 dic[MethodInvocationArgument.MakeBox] = ut.ContainsDifferentReturns();
163 dic[MethodInvocationArgument.DecorationAttributes] = this.node.Identifier.Accept(this.visitor, this.objInv);
166 ti.AcceptOperation(
this, arg);
174 return dic[MethodInvocationArgument.DecorationAttributes];
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;
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);
190 this.codeGenerator.Unbox(
this.indent, actualMethodCalled.
MemberInfo.
Class);
192 InheritedAttributes ia = this.inheritedAttributes;
193 this.objArgs =
new InheritedAttributes(ia.CurrentMethod, ia.Assignment, ia.Reference, ia.ArrayAccessFound, actualMethodCalled, ia.IsParentNodeAnInvocation);
195 this.visitor.RuntimeCheckArguments(this.node, this.objArgs, actualMethodCalled, nextMethod);
197 TypeExpression hasReturn = this.codeGenerator.MakeCall(this.indent, this.node, dic[MethodInvocationArgument.DecorationAttributes], actualMethodCalled, (FieldAccessExpression)this.node.
Identifier, arg);
199 this.codeGenerator.Box(this.indent, hasReturn);
201 this.codeGenerator.br(this.indent, endLabel);
203 for (
int k = nextMethod.Count - 1; k >= 0; k-- ) {
204 this.codeGenerator.WriteLabel(this.indent, nextMethod[k]);
205 this.codeGenerator.pop(this.indent);
207 if ( (
bool)dic[MethodInvocationArgument.Clean] )
208 this.codeGenerator.WriteLabel(
this.indent, nextMethodLabel);
210 return dic[MethodInvocationArgument.DecorationAttributes];
213 private void EndInvocationMethod(
bool clean)
215 if ( this.areThereNonValidObjects ) {
216 this.NonValidObjectsCodeGeneration();
218 if (this.hasTypeVariable) {
219 this.codeGenerator.Comment(indent,
"Reflection Code");
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);
228 this.codeGenerator.WriteLabel(this.indent, this.endLabel);
231 private void NonValidObjectsCodeGeneration() {
233 if (this.nonValidObjectsList.Count == 0)
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;;
239 this.codeGenerator.dup(this.indent);
240 this.codeGenerator.Comment(this.indent, ti.FullName);
241 this.codeGenerator.isinst(this.indent, ti);
243 this.codeGenerator.brtrue(this.indent, this.nonValidObjectsLabel);
246 this.codeGenerator.br(this.indent, nextLabel);
247 this.codeGenerator.WriteLabel(this.indent, this.nonValidObjectsLabel);
249 this.codeGenerator.Comment(
"Not reached");
250 this.codeGenerator.WriteLabel(this.indent, nextLabel);
254 this.codeGenerator.Comment(this.indent,
"//entro por type expression");
Expression Identifier
Gets the expression to invoke
Encapsulates the expression to access a field.
Encapsulates a invocation expression.
TypeExpression ExpressionType
Gets or sets the type of the expression.
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
Abstract class that represents all different types.
Represents a generic type expression
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
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.
IList< TypeExpression > TypeSet
Gets the list of type expressions
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)