Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="type">the current type being extended</param>
        /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, this is a reference to the
        /// non-specialized method, e.g. System.Linq.Enumerable.Select``2.
        /// </param>
        /// <param name="specialization">When the current type implements or inherits from a specialization of a generic type,
        /// this parameter has a TypeNode for the type used as apecialization of the generic type's first template param.
        /// </param>
        private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization)
        {
            // If this is a specialization of a generic method, construct a Method object that describes the specialization
            Method extensionMethodTemplate2 = extensionMethodTemplate;

            if (extensionMethodTemplate2.IsGeneric && (specialization != null))
            {
                // the specialization type is the first of the method's template arguments
                TypeNodeList templateArgs = new TypeNodeList();
                templateArgs.Add(specialization);
                // add any additional template arguments
                for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++)
                {
                    templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]);
                }
                extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs);
            }
            TypeNode      extensionMethodTemplateReturnType = extensionMethodTemplate2.ReturnType;
            ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters;

            ParameterList extensionMethodParameters = new ParameterList();

            for (int i = 1; i < extensionMethodTemplateParameters.Count; i++)
            {
                Parameter extensionMethodParameter = extensionMethodTemplateParameters[i];
                extensionMethodParameters.Add(extensionMethodParameter);
            }
            Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate.ReturnType, null);

            extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static;

            // for generic methods, set the template args and params so the template data is included in the id and the method data
            if (extensionMethodTemplate2.IsGeneric)
            {
                extensionMethod.IsGeneric = true;
                if (specialization != null)
                {
                    // set the template args for the specialized generic method
                    extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments;
                }
                else
                {
                    // set the generic template params for the non-specialized generic method
                    extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters;
                }
            }

            // Get the id
            string extensionMethodTemplateId = reflector.ApiNamer.GetMemberName(extensionMethodTemplate);

            // write the element node
            writer.WriteStartElement("element");
            writer.WriteAttributeString("api", extensionMethodTemplateId);
            writer.WriteAttributeString("source", "extension");
            isExtensionMethod = true;
            reflector.WriteMember(extensionMethod);
            isExtensionMethod = false;
            writer.WriteEndElement();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="type">the current type being extended</param>
        /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, this is a reference to the 
        /// non-specialized method, e.g. System.Linq.Enumerable.Select``2.
        /// </param>
        /// <param name="specialization">When the current type implements or inherits from a specialization of a generic type,
        /// this parameter has a TypeNode for the type used as apecialization of the generic type's first template param. 
        /// </param>
        private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization)
        {
            // If this is a specialization of a generic method, construct a Method object that describes the specialization
            Method extensionMethodTemplate2 = extensionMethodTemplate;
            if (extensionMethodTemplate2.IsGeneric && (specialization != null))
            {
                // the specialization type is the first of the method's template arguments
                TypeNodeList templateArgs = new TypeNodeList();
                templateArgs.Add(specialization);
                // add any additional template arguments
                for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++)
                    templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]);
                extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs);
            }
            TypeNode extensionMethodTemplateReturnType = extensionMethodTemplate2.ReturnType;
            ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters;

            ParameterList extensionMethodParameters = new ParameterList();
            for (int i = 1; i < extensionMethodTemplateParameters.Count; i++)
            {
                Parameter extensionMethodParameter = extensionMethodTemplateParameters[i];
                extensionMethodParameters.Add(extensionMethodParameter);
            }
            Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate.ReturnType, null);
            extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static;

            // for generic methods, set the template args and params so the template data is included in the id and the method data
            if (extensionMethodTemplate2.IsGeneric)
            {
                extensionMethod.IsGeneric = true;
                if (specialization != null)
                {
                    // set the template args for the specialized generic method
                    extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments;
                }
                else
                {
                    // set the generic template params for the non-specialized generic method
                    extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters;
                }
            }

            // Get the id
            string extensionMethodTemplateId = reflector.ApiNamer.GetMemberName(extensionMethodTemplate);

            // write the element node
            writer.WriteStartElement("element");
            writer.WriteAttributeString("api", extensionMethodTemplateId);
            writer.WriteAttributeString("source", "extension");
            isExtensionMethod = true;
            reflector.WriteMember(extensionMethod);
            isExtensionMethod = false;
            writer.WriteEndElement();
        }
Exemplo n.º 3
0
 internal static TypeNodeList GetTypeList(string typeList, IDebugContext context){
   TypeNodeList list = new TypeNodeList();
   int startIndex = typeList.LastIndexOf(".")+1;
   int endIndex;
   IDebugType typ;
   while((endIndex = typeList.IndexOf("Or", startIndex)) > 0){
     typ = context.GetType(typeList.Substring(startIndex, endIndex - startIndex));
     if (typ != null) list.Add(typ.CompilerType);
     startIndex = endIndex+2;
   }
   typ = context.GetType(typeList.Substring(startIndex));
   if (typ != null) list.Add(typ.CompilerType);
   return list;
 }
Exemplo n.º 4
0
        public void PopulateTypeList(TypeNodeList types, TypeNode t)
        {
            if (types == null || t == null)
            {
                Debug.Assert(false); return;
            }
            types.Add(t);
            MemberList members = t.Members;

            for (int i = 0, n = members == null ? 0 : members.Length; i < n; i++)
            {
                t = members[i] as TypeNode;
                if (t == null)
                {
                    continue;
                }
                this.PopulateTypeList(types, t);
            }
        }
Exemplo n.º 5
0
        private static TypeNodeList CreateTemplateParameters(Class closureClass, Method @from, TypeNode declaringType)
        {
            var dup = new Duplicator(declaringType.DeclaringModule, declaringType);

            var templateParameters = new TypeNodeList();

            var parentCount = declaringType.ConsolidatedTemplateParameters.CountOrDefault();

            for (int i = 0; i < from.TemplateParameters.Count; i++)
            {
                var tp = HelperMethods.NewEqualTypeParameter(
                    dup, (ITypeParameter)from.TemplateParameters[i],
                    closureClass, parentCount + i);

                templateParameters.Add(tp);
            }

            return(templateParameters);
        }
Exemplo n.º 6
0
        //----------------------------------------------------------------------

        private static TypeNodeList findAll(string name)
        {
            if (allNamespaces == null)
            {
                init();
            }
            TypeNodeList nsl = new TypeNodeList();

            nsCached.Add(name, nsl);
            for (int i = 0, n = allNamespaces.Length; i < n; i++)
            {
                if (allNamespaces[i].Name.Name == name)
                {
                    Namespace    ns   = allNamespaces[i];
                    TypeNodeList tnls = ns.Types;
                    for (int k = 0; k < tnls.Length; k++)
                    {
                        nsl.Add(tnls[k]);
                    }
                }
            }
            return(nsl);
        }
        public override Member VisitMemberReference(Member member)
        {
            Contract.Ensures(Contract.Result <Member>() != null || member == null);

            var asType = member as TypeNode;

            if (asType != null)
            {
                return(this.VisitTypeReference(asType));
            }

            var targetDeclaringType = this.VisitTypeReference(member.DeclaringType);

            Method sourceMethod = member as Method;

            if (sourceMethod != null)
            {
                // Here's how this works:
                //
                // 2. Identify MArgs (type arguments of method instance)
                //
                // 4. Find index i of method template in TargetDeclaringTypeTemplate by name and type names
                // 5. TargetDeclaringType = instantiate TargetDeclaringType with mapped TArgs
                // 6. MethodTemplate = TargetDeclaringType[i]
                // 7. Instantiate MethodTemplate with MArgs
                //
                var sourceMethodTemplate = sourceMethod;
                // Find source method template, but leave type instantiation
                while (sourceMethodTemplate.Template != null && sourceMethodTemplate.TemplateArguments != null &&
                       sourceMethodTemplate.TemplateArguments.Count > 0)
                {
                    sourceMethodTemplate = sourceMethodTemplate.Template;
                }

                // Steps 1 and 2

                TypeNodeList targetMArgs = null;
                TypeNodeList sourceMArgs = sourceMethod.TemplateArguments;
                if (sourceMArgs != null)
                {
                    targetMArgs = new TypeNodeList(sourceMArgs.Count);
                    foreach (var mArg in sourceMArgs)
                    {
                        targetMArgs.Add(this.VisitTypeReference(mArg));
                    }
                }

                Method targetMethod;

                var targetMethodTemplate = targetDeclaringType.FindShadow(sourceMethodTemplate);
                if (targetMethodTemplate == null)
                {
                    // something is wrong. Let's not crash and simply keep the original
                    return(sourceMethod);
                }

                if (targetMArgs != null)
                {
                    targetMethod = targetMethodTemplate.GetTemplateInstance(targetMethodTemplate.DeclaringType,
                                                                            targetMArgs);
                }
                else
                {
                    targetMethod = targetMethodTemplate;
                }

                return(targetMethod);
            }

            Field sourceField = member as Field;

            if (sourceField != null)
            {
                return(targetDeclaringType.FindShadow(sourceField));
            }

            Property sourceProperty = member as Property;

            if (sourceProperty != null)
            {
                return(targetDeclaringType.FindShadow(sourceProperty));
            }

            Event sourceEvent = member as Event;

            if (sourceEvent != null)
            {
                return(targetDeclaringType.FindShadow(sourceEvent));
            }

            Debug.Assert(false, "what other members are there?");

            Member result = base.VisitMemberReference(member);

            return(result);
        }
Exemplo n.º 8
0
    private Method CreateWrapperMethod(bool virtcall, TypeNode virtcallConstraint, Method templateMethod, TypeNode templateType, TypeNode wrapperType, Method methodWithContract, Method instanceMethod, SourceContext callingContext)
    {
      bool isProtected = IsProtected(templateMethod);
      Identifier name = templateMethod.Name;
      if (virtcall) {
        if (virtcallConstraint != null) {
          name = Identifier.For("CV$" + name.Name);
        }
        else {
          name = Identifier.For("V$" + name.Name);
        }
      }
      else {
        name = Identifier.For("NV$" + name.Name);
      }
      Duplicator dup = new Duplicator(this.assemblyBeingRewritten, wrapperType);
      TypeNodeList typeParameters = null;
      TypeNodeList typeParameterFormals = new TypeNodeList();
      TypeNodeList typeParameterActuals = new TypeNodeList();

      if (templateMethod.TemplateParameters != null) {
        dup.FindTypesToBeDuplicated(templateMethod.TemplateParameters);
        typeParameters = dup.VisitTypeParameterList(templateMethod.TemplateParameters);
        for (int i = 0; i < typeParameters.Count; i++) {
          typeParameterFormals.Add(typeParameters[i]);
          typeParameterActuals.Add(templateMethod.TemplateParameters[i]);
        }
      }
      ITypeParameter constraintTypeParam = null;
      if (virtcallConstraint != null) {
        if (typeParameters == null) { typeParameters = new TypeNodeList(); }
        var constraint = templateMethod.DeclaringType;
        var classConstraint = constraint as Class;
        if (classConstraint != null) {
          var classParam = new MethodClassParameter();
          classParam.BaseClass = classConstraint;
          classParam.Name = Identifier.For("TC");
          classParam.DeclaringType = wrapperType;
          typeParameters.Add(classParam);
          constraintTypeParam = classParam;
        }
        else {
          var mtp = new MethodTypeParameter();
          Interface intf = constraint as Interface;
          if (intf != null) {
            mtp.Interfaces.Add(intf);
          }
          mtp.Name = Identifier.For("TC");
          mtp.DeclaringType = wrapperType;
          typeParameters.Add(mtp);
          constraintTypeParam = mtp;
        }
      }
      var consolidatedTemplateTypeParameters = templateType.ConsolidatedTemplateParameters;
      if (consolidatedTemplateTypeParameters != null && consolidatedTemplateTypeParameters.Count > 0) {
        var consolidatedWrapperTypeParameters = wrapperType.ConsolidatedTemplateParameters;
        for (int i = 0; i < consolidatedTemplateTypeParameters.Count; i++) {
          typeParameterFormals.Add(consolidatedWrapperTypeParameters[i]);
          typeParameterActuals.Add(consolidatedTemplateTypeParameters[i]);
        }
      }
      Specializer spec = null;
      if (typeParameterActuals.Count > 0) {
        spec = new Specializer(this.assemblyBeingRewritten, typeParameterActuals, typeParameterFormals);
      }
      var parameters = new ParameterList();
      var asTypeConstraintTypeParam = constraintTypeParam as TypeNode;

      if (!isProtected && !templateMethod.IsStatic) {
        TypeNode thisType = GetThisTypeInstance(templateType, wrapperType, asTypeConstraintTypeParam);
        parameters.Add(new Parameter(Identifier.For("@this"), thisType));
      }
      for (int i = 0; i < templateMethod.Parameters.Count; i++) {
        parameters.Add((Parameter)dup.VisitParameter(templateMethod.Parameters[i]));
      }
      var retType = dup.VisitTypeReference(templateMethod.ReturnType);
      if (spec != null) {
        parameters = spec.VisitParameterList(parameters);
        retType = spec.VisitTypeReference(retType);
      }

      var wrapperMethod = new Method(wrapperType, null, name, parameters, retType, null);
      RewriteHelper.TryAddCompilerGeneratedAttribute(wrapperMethod);

      if (isProtected) {
        wrapperMethod.Flags = templateMethod.Flags & ~MethodFlags.Abstract;
        wrapperMethod.CallingConvention = templateMethod.CallingConvention;
      }
      else {
        wrapperMethod.Flags |= MethodFlags.Static | MethodFlags.Assembly;
      }
      if (constraintTypeParam != null) {
        constraintTypeParam.DeclaringMember = wrapperMethod;
      }
      if (typeParameters != null) {
        if (spec != null) {
          typeParameters = spec.VisitTypeParameterList(typeParameters);
        }
        wrapperMethod.IsGeneric = true;
        wrapperMethod.TemplateParameters = typeParameters;
      }

      // create body
      var sl = new StatementList();
      Block b = new Block(sl);

      // insert requires
      AddRequiresToWrapperMethod(wrapperMethod, b, methodWithContract);

      // create original call
      var targetType = templateType;
      if (isProtected)
      {
        // need to use base chain instantiation of target type.
        targetType = instanceMethod.DeclaringType;
      }
      else
      {
        if (targetType.ConsolidatedTemplateParameters != null && targetType.ConsolidatedTemplateParameters.Count > 0)
        {
          // need selfinstantiation
          targetType = targetType.GetGenericTemplateInstance(this.assemblyBeingRewritten, wrapperType.ConsolidatedTemplateParameters);
        }
      }
      Method targetMethod = GetMatchingMethod(targetType, templateMethod, wrapperMethod);
      if (targetMethod.IsGeneric) {
        if (typeParameters.Count > targetMethod.TemplateParameters.Count) {
          // omit the extra constrained type arg.
          TypeNodeList origArgs = new TypeNodeList();
          for (int i = 0; i < targetMethod.TemplateParameters.Count; i++) {
            origArgs.Add(typeParameters[i]);
          }
          targetMethod = targetMethod.GetTemplateInstance(wrapperType, origArgs);
        }
        else {
          targetMethod = targetMethod.GetTemplateInstance(wrapperType, typeParameters);
        }
      }
      MethodCall call;
      NodeType callType = virtcall ? NodeType.Callvirt : NodeType.Call;
      if (isProtected) {
        var mb = new MemberBinding(wrapperMethod.ThisParameter, targetMethod);
        var elist = new ExpressionList(wrapperMethod.Parameters.Count);
        for (int i = 0; i < wrapperMethod.Parameters.Count; i++) {
          elist.Add(wrapperMethod.Parameters[i]);
        }
        call = new MethodCall(mb, elist, callType);
      }
      else if (templateMethod.IsStatic) {
        var elist = new ExpressionList(wrapperMethod.Parameters.Count);
        for (int i = 0; i < wrapperMethod.Parameters.Count; i++) {
          elist.Add(wrapperMethod.Parameters[i]);
        }
        call = new MethodCall(new MemberBinding(null, targetMethod), elist, callType);
      }
      else {
        var mb = new MemberBinding(wrapperMethod.Parameters[0], targetMethod);
        var elist = new ExpressionList(wrapperMethod.Parameters.Count - 1);
        for (int i = 1; i < wrapperMethod.Parameters.Count; i++) {
          elist.Add(wrapperMethod.Parameters[i]);
        }
        call = new MethodCall(mb, elist, callType);
      }
      if (constraintTypeParam != null) {
        call.Constraint = asTypeConstraintTypeParam;
      }
      if (HelperMethods.IsVoidType(templateMethod.ReturnType)) {
        sl.Add(new ExpressionStatement(call,callingContext));
        sl.Add(new Return(callingContext));
      }
      else {
        sl.Add(new Return(call,callingContext));
      }
      wrapperMethod.Body = b;

      wrapperType.Members.Add(wrapperMethod);
      return wrapperMethod;
    }
Exemplo n.º 9
0
        private FunctionPointer/*!*/ ParseFunctionPointer(MemoryCursor/*!*/ sigReader)
        {
            CallingConventionFlags convention = (CallingConventionFlags)sigReader.ReadByte();
            int n = sigReader.ReadCompressedInt();
            TypeNode returnType = this.ParseTypeSignature(sigReader);

            if(returnType == null)
                returnType = CoreSystemTypes.Object;

            TypeNodeList parameterTypes = new TypeNodeList();
            int m = n;

            for(int i = 0; i < n; i++)
            {
                TypeNode t = this.ParseTypeSignature(sigReader);

                if (t == null)
                    m = i--;
                else
                    parameterTypes.Add(t);
            }

            FunctionPointer fp = FunctionPointer.For(parameterTypes, returnType);
            fp.CallingConvention = convention;
            fp.VarArgStart = m;

            return fp;
        }
Exemplo n.º 10
0
        /// <summary>
        /// If there is an anonymous delegate within a postcondition, then there
        /// will be a call to a delegate constructor.
        /// That call looks like "d..ctor(o,m)" where d is the type of the delegate.
        /// There are two cases depending on whether the anonymous delegate captured
        /// anything. In both cases, m is the method implementing the anonymous delegate.
        /// (1) It does capture something. Then o is the instance of the closure class
        /// implementing the delegate, and m is an instance method in the closure
        /// class.
        /// (2) It does *not* capture anything. Then o is the literal for null and
        /// m is a static method that was added directly to the class.
        ///
        /// This method will cause the method (i.e., m) to be visited to collect any
        /// Result&lt;T&gt;() expressions that occur in it.
        /// </summary>
        /// <param name="cons">The AST representing the call to the constructor
        /// of the delegate type.</param>
        /// <returns>Whatever the base visitor returns</returns>
        public override Expression VisitConstruct(Construct cons)
        {
            if (cons.Type is DelegateNode)
            {
                UnaryExpression ue = cons.Operands[1] as UnaryExpression;
                if (ue == null)
                {
                    goto JustVisit;
                }

                MemberBinding mb = ue.Operand as MemberBinding;
                if (mb == null)
                {
                    goto JustVisit;
                }

                Method m = mb.BoundMember as Method;
                if (!HelperMethods.IsCompilerGenerated(m))
                {
                    goto JustVisit;
                }

                Contract.Assume(m != null);

                m = Definition(m);
                this.delegateNestingLevel++;

                TypeNode   savedClosureClass  = this.currentClosureClassInstance;
                Method     savedClosureMethod = this.currentClosureMethod;
                Expression savedCurrentAccessToTopLevelClosure = this.currentAccessToTopLevelClosure;

                try
                {
                    this.currentClosureMethod = m;

                    if (m.IsStatic)
                    {
                        this.currentClosureClassInstance = null; // no closure object
                    }
                    else
                    {
                        this.currentClosureClassInstance = cons.Operands[0].Type;
                        if (savedClosureClass == null)
                        {
                            // Then this is the top-level closure class.
                            this.topLevelClosureClassInstance   = this.currentClosureClassInstance;
                            this.topLevelClosureClassDefinition = Definition(this.topLevelClosureClassInstance);

                            this.currentAccessToTopLevelClosure = new This(this.topLevelClosureClassDefinition);
                            this.properlyInstantiatedFieldType  = this.originalLocalForResult.Type;

                            if (this.topLevelMethodFormals != null)
                            {
                                Contract.Assume(this.topLevelClosureClassDefinition.IsGeneric);
                                Contract.Assume(topLevelClosureClassDefinition.TemplateParameters.Count >=
                                                this.topLevelMethodFormals.Count);

                                // replace method type parameters in result properly with last n corresponding type parameters of closure class
                                TypeNodeList closureFormals = topLevelClosureClassDefinition.TemplateParameters;
                                if (closureFormals.Count > this.topLevelMethodFormals.Count)
                                {
                                    int offset = closureFormals.Count - this.topLevelMethodFormals.Count;
                                    closureFormals = new TypeNodeList(this.topLevelMethodFormals.Count);
                                    for (int i = 0; i < this.topLevelMethodFormals.Count; i++)
                                    {
                                        closureFormals.Add(topLevelClosureClassDefinition.TemplateParameters[i + offset]);
                                    }
                                }

                                Duplicator dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType);

                                Specializer spec = new Specializer(this.declaringType.DeclaringModule,
                                                                   topLevelMethodFormals, closureFormals);

                                var type = dup.VisitTypeReference(this.originalLocalForResult.Type);
                                type = spec.VisitTypeReference(type);
                                this.properlyInstantiatedFieldType = type;
                            }
                        }
                        else
                        {
                            while (currentClosureClassInstance.Template != null)
                            {
                                currentClosureClassInstance = currentClosureClassInstance.Template;
                            }

                            // Find the field in this.closureClass that the C# compiler generated
                            // to point to the top-level closure
                            foreach (Member mem in this.currentClosureClassInstance.Members)
                            {
                                Field f = mem as Field;
                                if (f == null)
                                {
                                    continue;
                                }
                                if (f.Type == this.topLevelClosureClassDefinition)
                                {
                                    var consolidatedTemplateParams = this.currentClosureClassInstance.ConsolidatedTemplateParameters;

                                    TypeNode thisType;
                                    if (consolidatedTemplateParams != null && consolidatedTemplateParams.Count > 0)
                                    {
                                        thisType =
                                            this.currentClosureClassInstance.GetGenericTemplateInstance(
                                                this.assemblyBeingRewritten, consolidatedTemplateParams);
                                    }
                                    else
                                    {
                                        thisType = this.currentClosureClassInstance;
                                    }

                                    this.currentAccessToTopLevelClosure = new MemberBinding(new This(thisType), f);

                                    break;
                                }
                            }
                        }
                    }

                    this.VisitBlock(m.Body);
                }
                finally
                {
                    this.delegateNestingLevel--;
                    this.currentClosureMethod           = savedClosureMethod;
                    this.currentClosureClassInstance    = savedClosureClass;
                    this.currentAccessToTopLevelClosure = savedCurrentAccessToTopLevelClosure;
                }
            }

JustVisit:
            return(base.VisitConstruct(cons));
        }
Exemplo n.º 11
0
 public virtual Method InferMethodTemplateArgumentsAndReturnTemplateInstance(Method method, ExpressionList arguments, bool allowPartialInference, TypeNode paramArrayElemType){
   if (method == null || method.Parameters == null || method.Parameters.Count == 0 || 
     method.TemplateParameters == null || method.TemplateParameters.Count == 0){Debug.Assert(false); return method;}
   if (arguments == null) return method;
   int numArgs = arguments.Count;
   int numPars = method.Parameters.Count;
   if (numArgs == 0 || (numArgs != numPars && paramArrayElemType == null && (!allowPartialInference || numArgs > numPars))){
     Debug.Assert(false); 
     return method;
   }
   TrivialHashtable inferredTypeFor = new TrivialHashtable();
   for (int i = 0; i < numArgs; i++){
     Expression arg = arguments[i]; if (arg == null) continue;
     TypeNode argType = TypeNode.StripModifiers(arg.Type);
     if (arg is Literal && argType == SystemTypes.Object && ((Literal)arg).Value == null) continue;
     if (arg is AnonymousNestedFunction) continue;
     Parameter par = method.Parameters[i]; if (par == null) continue;
     TypeNode parType = TypeNode.StripModifiers(par.Type);
     Reference reft = argType as Reference;
     if (reft != null && !(arg is UnaryExpression)) argType = reft.ElementType;
     if (i == numPars - 1 && paramArrayElemType != null)
       if (!(argType is ArrayType && parType is ArrayType))
         parType = paramArrayElemType;
     if (!this.InferMethodTemplateArguments(argType, arg as MemberBinding, parType, inferredTypeFor)) return method;
     if (i == numPars-1) break;
   }
   int numTypeArgs = method.TemplateParameters.Count;
   TypeNodeList typeArguments = new TypeNodeList(numTypeArgs);
   for (int i = 0; i < numTypeArgs; i++){
     TypeNode templPar = method.TemplateParameters[i]; 
     if (templPar == null) return method;
     TypeNode templArg = inferredTypeFor[templPar.UniqueKey] as TypeNode;
     if (templArg == null && !allowPartialInference) return method;
     if (templArg == null) templArg = templPar;
     typeArguments.Add(templArg);
   }
   return method.GetTemplateInstance(this.currentType, typeArguments);
 }
Exemplo n.º 12
0
  public override Expression VisitComprehension(Comprehension comprehension){
   if (comprehension == null) return null;
   if (comprehension.Elements == null) return null;
   if (comprehension.IsDisplay){
     if (comprehension.Elements.Count == 0) {
       comprehension.Type = SystemTypes.GenericIEnumerable.GetTemplateInstance(this.currentType,SystemTypes.Object);
       return comprehension;
     }
   }else{
     if (comprehension.Elements.Count != 1 && comprehension.Elements.Count != 2)
       return null;
   }
   comprehension.BindingsAndFilters = this.VisitExpressionList(comprehension.BindingsAndFilters);
   comprehension.Elements = this.VisitExpressionList(comprehension.Elements);
   TypeNode unifiedType = null;
   TypeNodeList tl = new TypeNodeList();
   for (int i = 0, n = comprehension.Elements == null ? 0 : comprehension.Elements.Count; i < n; i++){
     Expression e = comprehension.Elements[i];
     if (e == null || e.Type == null) continue;
     Literal lit = e as Literal;
     if (lit != null && lit.Value == null) continue; //This prevents null from participating in the type unification, which is by design.
     if (e.Type == null) continue; //e is a bad expression
     tl.Add(e.Type);
   }
   unifiedType = this.typeSystem.UnifiedType(tl, this.TypeViewer);
   if (unifiedType == null) unifiedType = SystemTypes.Object;
   comprehension.Type = OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.GenericIEnumerable.GetTemplateInstance(this.currentType, unifiedType));
   return comprehension;
 }
Exemplo n.º 13
0
    /// <summary>
    /// Computes an upper bound in the type hierarchy for the set of argument types.
    /// This upper bound is a type that all types in the list are assignable to.
    /// If the types are all classes, then *the* least-upper-bound in the class
    /// hierarchy is returned.
    /// If the types contain at least one interface, then *a* deepest upper-bound
    /// is found from the intersection of the upward closure of each type.
    /// Note that if one of the types is System.Object, then that is immediately
    /// returned as the unified type without further examination of the list.
    /// </summary>
    /// <param name="ts">A list containing the set of types from which to compute the unified type.</param>
    /// <returns>The type corresponding to the least-upper-bound.</returns>
    public virtual TypeNode UnifiedType(TypeNodeList ts, TypeViewer typeViewer){
      if (ts == null || ts.Count == 0) return null;
      TypeNode unifiedType = SystemTypes.Object; // default unified type
      bool atLeastOneInterface = false;
      #region If at least one of the types is System.Object, then that is the unified type
      for (int i = 0, n = ts.Count; i < n; i++){
        TypeNode t = this.Unwrap(ts[i]);
        if (t == SystemTypes.Object){
          return SystemTypes.Object;
        }
      }
      #endregion If at least one of the types is System.Object, then that is the unified type
      // assert forall{TypeNode t in ts; t != SystemTypes.Object};
      #region See if any of the types are interfaces
      for (int i = 0, n = ts.Count; i < n; i++){
        TypeNode t = this.Unwrap(ts[i]);
        if (t.NodeType == NodeType.Interface){
          atLeastOneInterface = true;
          break;
        }
      }
      #endregion See if any of the types are interfaces

      #region Find the LUB in the class hierarchy (if there are no interfaces)
      if (!atLeastOneInterface){
        TrivialHashtable h = new TrivialHashtable(ts.Count);
        // Create the list [s, .., t] for each element t of ts where for each item
        // in the list, t_i, t_i = t_{i+1}.BaseType. (s.BaseType == SystemTypes.Object)
        // Store the list in a hashtable keyed by t.
        // Do this only for classes. Handle interfaces in a different way because of
        // multiple inheritance.
        for (int i = 0, n = ts.Count; i < n; i++){
          TypeNodeList tl = new TypeNodeList();
          TypeNode t = this.Unwrap(ts[i]);
          tl.Add(t);
          TypeNode t2 = t.BaseType;
          while (t2 != null && t2 != SystemTypes.Object){ // avoid including System.Object in the list for classes
            tl.Insert(t2,0);
            t2 = this.Unwrap(t2.BaseType);
          }
          h[ts[i].UniqueKey] = tl;
        }
        bool stop = false;
        int depth = 0;
        while (!stop){
          TypeNode putativeUnifiedType = null;
          int i = 0;
          int n = ts.Count;
          putativeUnifiedType = ((TypeNodeList) h[ts[0].UniqueKey])[depth];
          while (i < n){
            TypeNode t = ts[i];
            TypeNodeList subTypes = (TypeNodeList) h[t.UniqueKey];
            if (subTypes.Count <= depth || subTypes[depth] != putativeUnifiedType){
              // either reached the top of the hierarchy for t_i or it is on a different branch
              // than the current one.
              stop = true;
              break;
            }
            i++;
          }
          if (i == n){ // made it all the way through: all types are subtypes of the current one
            unifiedType = putativeUnifiedType;
          }
          depth++;
        }
      }
      #endregion Find the LUB in the class hierarchy (if there are no interfaces)
      #region Find *a* LUB in the interface hierarchy (if there is at least one interface or current LUB is object)
      if (unifiedType == SystemTypes.Object || atLeastOneInterface){
        TrivialHashtable interfaces = new TrivialHashtable();
        for (int i = 0, n = ts.Count; i < n; i++){
          InterfaceList il = new InterfaceList();
          interfaces[ts[i].UniqueKey] = il;
          this.SupportedInterfaces(ts[i],il,typeViewer); // side-effect: il gets added to
        }
        // interfaces[ts[i]] is the upward closure of all of the interfaces supported by ts[i]
        // compute the intersection of all of the upward closures
        // might as well start with the first type in the list ts
        InterfaceList intersection = new InterfaceList();
        InterfaceList firstIfaceList = (InterfaceList)interfaces[ts[0].UniqueKey];
        for (int i = 0, n = firstIfaceList.Count; i < n; i++){
          Interface iface = firstIfaceList[i];
          bool found = false;
          int j = 1; // start at second type in the list ts
          while (j < ts.Count){
            InterfaceList cur = (InterfaceList)interfaces[ts[j].UniqueKey];
            found = false;
            for (int k = 0, p = cur.Count; k < p; k++){
              if (cur[k] == iface){
                found = true;
                break;
              }
            }
            if (!found){
              // then the j-th type doesn't support iface, don't bother looking in the rest
              break;
            }
            j++;
          }
          if (found){
            intersection.Add(iface);
          }
        }
        // TODO: take the "deepest" interface in the intersection.
        // "deepest" means that if any other type in the intersection is a subtype
        // of it, then *don't* consider it.
        if (intersection.Count > 0){
          InterfaceList finalIntersection = new InterfaceList(intersection.Count);
          Interface iface = intersection[0];
          for (int i = 0, n = intersection.Count; i < n; i++){
            Interface curFace = intersection [i];
            int j = 0;
            int m = intersection.Count;
            while (j < m){
              if (j != i){
                Interface jFace = intersection[j];
                if (TypeViewer.GetTypeView(typeViewer, jFace).IsAssignableTo(curFace))
                  break;
              }
              j++;
            }
            if (j == m){ // made it all the way through, no other iface is a subtype of curFace
              finalIntersection.Add(curFace);
            }
          }
          if (finalIntersection.Count > 0){
            unifiedType = finalIntersection[0]; // heuristic: just take the first one
          }
        }
      }
      #endregion Find *a* LUB in the interface hierarchy (if there is at least one interface or current LUB is object)
      return unifiedType;
    }
Exemplo n.º 14
0
	void PTypeRef(out TypeNode tn) {
		Module assem = null;
		string ns, tname, nestedname;
		ArrayList/*<string>*/ typeNames;
		TypeNodeList templateArgs = null;
		
		if (la.kind == 28) {
			Assembly(out assem);
		}
		QualName(out ns, out tname);
		NestedTypeName(out typeNames, out nestedname);
		if (la.kind == 31) {
			Get();
			TypeNode arg; 
			PType(out arg);
			templateArgs = new TypeNodeList(); templateArgs.Add(arg); 
			while (la.kind == 23) {
				Get();
				PType(out arg);
				templateArgs.Add(arg); 
			}
			Expect(32);
		}
		if ( assem == null ){
		 assem = currentAssembly;
		}
		#if !WHIDBEY
		if (templateArgs != null){
		 /* then need to create the pseudo-generic name */
		 string pseudoGenericName = tname;
		 /*pseudoGenericName += SystemTypes.GenericTypeNamesMangleChar;*/
		 /*pseudoGenericName += templateArgs.Count.ToString();*/
		 pseudoGenericName += "<";
		 for (int i = 0, n = templateArgs.Count; i < n; i++){
		   if (i > 0)
		     pseudoGenericName += ",";
		   pseudoGenericName += templateArgs[i].FullName;
		 }
		 pseudoGenericName += ">";
		 tname = pseudoGenericName;
		}
		#endif
		tn = assem.GetType(Identifier.For(ns),Identifier.For(tname));
		if (tn == null) {
		 this.errors.SemErr(t.filename, t.line, t.col,
		               String.Format("could not resolve namespace {0}, type {1}", ns, tname));
		 throw new Exception("cannot continue"); //Errors.Exception("cannot continue");
		}
		// now do nested types
		for (int i=0; i<typeNames.Count; i++){
		 tn = tn.GetNestedType(Identifier.For((string)typeNames[i]));
		}
		if (tn == null) {
		 this.errors.SemErr(t.filename, t.line, t.col,
		               String.Format("could not resolve namespace {0} type {1} nesting {2}", ns, tname, nestedname));
		 throw new Exception("cannot continue"); //Errors.Exception("cannot continue");
		}
		#if WHIDBEY
		/* Pre-Whidbey, templateArgs are used to construct a pseudo-generic name */
		if (templateArgs != null)
		{
		 tn = tn.GetTemplateInstance(assem, null, null, templateArgs);
		}
		#endif
		
	}
Exemplo n.º 15
0
 private TypeNodeList ParseTypeArguments(bool returnNullIfError, bool Typeof, TokenSet followers, out int endCol, out int arity){
   Debug.Assert(this.currentToken == Token.LessThan);
   if (this.sink != null) this.sink.StartTemplateParameters(this.scanner.CurrentSourceContext);
   arity = 1;
   this.GetNextToken();
   if (Typeof && this.currentToken == Token.GreaterThan){
     endCol = this.scanner.endPos;
     this.GetNextToken();
     if (this.sink != null) this.sink.EndTemplateParameters(this.scanner.CurrentSourceContext);
     return null;
   }
   SourceContext commaContext = this.scanner.CurrentSourceContext;
   TypeNodeList arguments = new TypeNodeList();
   for(;;){
     if (arity > 0 && Typeof && this.currentToken == Token.Comma){
       arity++;
       this.GetNextToken();
       continue;
     }
     if (arity > 1){
       if (Typeof && this.currentToken == Token.GreaterThan) break;
       this.HandleError(commaContext, Error.TypeExpected);
     }
     arity = 0;
     SourceContext sctx = this.scanner.CurrentSourceContext;
     TypeNode t = this.ParseTypeExpression(null, followers|Token.Comma|Token.GreaterThan|Token.RightShift, true);
     if (this.sink != null && t != null) {
       sctx.EndPos = this.scanner.endPos;
       this.sink.NextTemplateParameter(sctx);
     }
     endCol = this.scanner.endPos;
     if (returnNullIfError && t == null) {
         if (this.sink != null) this.sink.EndTemplateParameters(this.scanner.CurrentSourceContext);
         return null;
     }
     arguments.Add(t);
     if (this.currentToken != Token.Comma) break;
     this.GetNextToken();
   }
   if (this.sink != null) this.sink.EndTemplateParameters(this.scanner.CurrentSourceContext);
   endCol = this.scanner.endPos;
   if (returnNullIfError && this.currentToken != Token.GreaterThan && this.currentToken != Token.RightShift && this.currentToken != Token.EndOfFile)
     return null;
   if (this.currentToken == Token.RightShift)
     this.currentToken = Token.GreaterThan;
   else if (this.currentToken == Token.GreaterThan)
     this.Skip(Token.GreaterThan);
   return arguments;
 }
Exemplo n.º 16
0
        //=====================================================================

        /// <summary>
        /// Add extension method information to a type
        /// </summary>
        /// <param name="writer">The reflection data XML writer</param>
        /// <param name="type">the current type being extended</param>
        /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods,
        /// this is a reference to the non-specialized method, e.g. System.Linq.Enumerable.Select``2.</param>
        /// <param name="specialization">When the current type implements or inherits from a specialization
        /// of a generic type, this parameter has a TypeNode for the type used as a specialization of the
        /// generic type's first template parameter.</param>
        private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate,
                                        TypeNode specialization)
        {
            // !EFW - Bug fix
            // Don't add extension method support to enumerations and static classes
            if (type != null && (type.NodeType == NodeType.EnumNode || (type.NodeType == NodeType.Class &&
                                                                        type.IsAbstract && type.IsSealed)))
            {
                return;
            }

            // If this is a specialization of a generic method, construct a Method object that describes
            // the specialization.
            Method extensionMethodTemplate2 = extensionMethodTemplate;

            if (extensionMethodTemplate2.IsGeneric && specialization != null)
            {
                // The specialization type is the first of the method's template arguments
                TypeNodeList templateArgs = new TypeNodeList();
                templateArgs.Add(specialization);

                // Add any additional template arguments
                for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++)
                {
                    templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]);
                }

                extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs);
            }

            ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters;

            ParameterList extensionMethodParameters = new ParameterList();

            for (int i = 1; i < extensionMethodTemplateParameters.Count; i++)
            {
                Parameter extensionMethodParameter = extensionMethodTemplateParameters[i];
                extensionMethodParameters.Add(extensionMethodParameter);
            }

            Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(),
                                                extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate2.ReturnType,
                                                null);

            extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static;

            // For generic methods, set the template arguments and parameters so the template data is included in
            // the ID and the method data.
            if (extensionMethodTemplate2.IsGeneric)
            {
                extensionMethod.IsGeneric = true;

                if (specialization != null)
                {
                    // Set the template arguments for the specialized generic method
                    extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments;
                }
                else
                {
                    // Set the generic template parameters for the non-specialized generic method
                    extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters;
                }
            }

            // Get the ID
            string extensionMethodTemplateId = mrw.ApiNamer.GetMemberName(extensionMethodTemplate);

            // Write the element node
            writer.WriteStartElement("element");
            writer.WriteAttributeString("api", extensionMethodTemplateId);
            writer.WriteAttributeString("source", "extension");

            isExtensionMethod = true;
            mrw.WriteMember(extensionMethod, false);
            isExtensionMethod = false;

            writer.WriteEndElement();
        }
Exemplo n.º 17
0
 private InterfaceList ParseInterfaceList(TokenSet followers, bool expectLeftBrace){
   InterfaceList ilist = new InterfaceList();
   TokenSet followersOrComma = followers|Token.Comma;
   for(;;){
     Expression id = this.scanner.GetIdentifier();
     switch(this.currentToken){
       case Token.Bool:
       case Token.Decimal:
       case Token.Sbyte:
       case Token.Byte:
       case Token.Short:
       case Token.Ushort:
       case Token.Int:
       case Token.Uint:
       case Token.Long:
       case Token.Ulong:
       case Token.Char:
       case Token.Float:
       case Token.Double:
       case Token.Object:
       case Token.String:
       case Token.Void:
         TypeExpression texpr = this.TypeExpressionFor(this.currentToken);
         this.GetNextToken();
         ilist.Add(new InterfaceExpression(texpr.Expression, texpr.SourceContext));
         goto lookForComma;
       default:
         bool idOK = Parser.IdentifierOrNonReservedKeyword[this.currentToken];
         if (idOK){
           this.GetNextToken();
           if (this.currentToken == Token.DoubleColon){
             this.GetNextToken();
             Identifier id2 = this.scanner.GetIdentifier();
             id2.Prefix = (Identifier)id;
             id2.SourceContext.StartPos = id.SourceContext.StartPos;
             this.SkipIdentifierOrNonReservedKeyword();
             id = id2;
           }
           if (this.currentToken == Token.Dot)
             id = this.ParseQualifiedIdentifier(id, followersOrComma|Token.LessThan);
         }else{
           int col = this.scanner.endPos;
           this.SkipIdentifierOrNonReservedKeyword(Error.TypeExpected);
           if (col == this.scanner.endPos && this.currentToken != Token.EndOfFile){
             //Did not consume a token, but just gave an error
             if (!followersOrComma[this.currentToken]) this.GetNextToken();
             if (followers[this.currentToken]) return ilist;
             if (this.currentToken != Token.Comma){
               if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) continue;
               break;
             }
             this.GetNextToken();
             continue;
           }
           if (this.currentToken == Token.Dot)
             id = this.ParseQualifiedIdentifier(id, followersOrComma|Token.LessThan);
           if (!idOK) goto lookForComma;
         }
         break;
     }
     //I really want an Identifier here for StartName
     if (this.sink != null) {
       Identifier name = id as Identifier;
       if (id is QualifiedIdentifier) {
         name = ((QualifiedIdentifier)id).Identifier;
       }
       if (name != null) {
         this.sink.StartName(name);
       }
     }
     InterfaceExpression ifaceExpr = new InterfaceExpression(id, id.SourceContext);
     if (this.currentToken == Token.LessThan){
     yetAnotherTypeArgumentList:
       this.GetNextToken();
       TypeNodeList arguments = new TypeNodeList();
       for(;;){
         TypeNode t = this.ParseTypeExpression(null, followers|Token.Comma|Token.GreaterThan);
         arguments.Add(t);
         if (this.currentToken != Token.Comma) break;
         this.GetNextToken();
       }
       ifaceExpr.TemplateArguments = arguments;
       ifaceExpr.TemplateArgumentExpressions = arguments.Clone();
       ifaceExpr.SourceContext.EndPos = this.scanner.endPos;
       this.Skip(Token.GreaterThan);
       if (this.currentToken == Token.Dot) {
         TemplateInstance tempInst = new TemplateInstance(ifaceExpr.Expression, ifaceExpr.TemplateArguments);
         tempInst.TypeArgumentExpressions = ifaceExpr.TemplateArguments == null ? null : ifaceExpr.TemplateArguments.Clone();
         tempInst.SourceContext = ifaceExpr.SourceContext;
         ifaceExpr.Expression = this.ParseQualifiedIdentifier(tempInst, followersOrComma|Token.LessThan);
         ifaceExpr.TemplateArguments = null;
         ifaceExpr.TemplateArgumentExpressions = null;
         if (ifaceExpr.Expression != null) ifaceExpr.SourceContext = ifaceExpr.Expression.SourceContext;
         if (this.currentToken == Token.LessThan) goto yetAnotherTypeArgumentList;
       }
     }
     ilist.Add(ifaceExpr);
   lookForComma:
     if (Parser.TypeOperator[this.currentToken] && !(expectLeftBrace && this.currentToken == Token.LeftBrace)){
       this.HandleError(Error.BadBaseType);
       this.GetNextToken();
       if (this.currentToken == Token.RightBracket || this.currentToken == Token.RightBrace)
         this.GetNextToken();
       this.SkipTo(followersOrComma, Error.None);
     }else if (!followersOrComma[this.currentToken])
       this.SkipTo(followersOrComma, Error.TypeExpected);
     if (this.currentToken == Token.Comma){
       if (followers[Token.Comma] && followers[Token.GreaterThan])
         break; //Parsing the constraint of a type parameter
       this.GetNextToken();
       if (expectLeftBrace && (this.currentToken == Token.Class || this.currentToken == Token.Struct || this.currentToken == Token.New))
         break;
     }else if (!Parser.TypeStart[this.currentToken] || this.currentToken == Token.Where)
       break;
     else if (Parser.ContractStart[this.currentToken])
       break;
   }
   return ilist;
 }
Exemplo n.º 18
0
 private void ParseTypeParameters(Member parent, TokenSet followers, TypeNodeList parameters){
   TypeNode declaringType = parent as TypeNode;
   if (declaringType == null) declaringType = parent.DeclaringType;
   Debug.Assert(this.currentToken == Token.LessThan);
   this.GetNextToken();
   for(int i = 0; ; i++){
     AttributeList attributes = null;
     if (this.currentToken == Token.LeftBracket)
       attributes = this.ParseAttributes(null, followers|Token.Identifier|Token.Comma|Token.GreaterThan|Token.RightShift);
     if (this.currentToken != Token.Identifier) {
       this.HandleError(Error.ExpectedIdentifier);
       break;
     }
     Identifier id = this.scanner.GetIdentifier();
     TypeParameter param = parent is Method ? new MethodTypeParameter() : new TypeParameter();
     param.Attributes = attributes;
     param.DeclaringMember = parent;
     param.ParameterListIndex = i;
     param.Name = id;
     param.DeclaringModule = declaringType.DeclaringModule;
     if (!this.useGenerics){
       param.DeclaringType = declaringType;
       if (!(parent is Method)) declaringType.Members.Add(param);
     }
     parameters.Add(param);
     param.SourceContext = this.scanner.CurrentSourceContext;
     this.GetNextToken();
     if (this.currentToken == Token.Dot){
       QualifiedIdentifier qualid = (QualifiedIdentifier)this.ParseQualifiedIdentifier(id, followers|Token.Colon|Token.Comma|Token.GreaterThan);
       param.Namespace = Identifier.For(qualid.Qualifier.ToString());
       param.Name = qualid.Identifier;
       param.SourceContext = qualid.SourceContext;
     }
     param.Interfaces = new InterfaceList();
     if (this.currentToken != Token.Comma) break;
     this.GetNextToken();
   }
   this.Skip(Token.GreaterThan);
   this.SkipTo(followers);
 }
Exemplo n.º 19
0
 public void PopulateTypeList(TypeNodeList types, TypeNode t){
   if (types == null || t == null){Debug.Assert(false); return;}
   types.Add(t);
   MemberList members = t.Members;
   for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++){
     t = members[i] as TypeNode;
     if (t == null) continue;
     this.PopulateTypeList(types, t);
   }
 }
Exemplo n.º 20
0
	void ArgPTypes(out TypeNodeList tns) {
		tns = new TypeNodeList();
		TypeNode tn;
		
		Expect(22);
		if (StartOf(4)) {
			PTypedRef(out tn);
			tns.Add(tn); 
			while (la.kind == 23) {
				Get();
				PTypedRef(out tn);
				tns.Add(tn); 
			}
		}
		Expect(24);
	}
Exemplo n.º 21
0
 public override Expression VisitConstructArray(ConstructArray consArr){
   if (consArr == null) return consArr;
   TypeNode et = consArr.ElementType = this.VisitTypeReference(consArr.ElementType);
   ExpressionList dims = consArr.Operands = this.VisitExpressionList(consArr.Operands);
   consArr.Initializers = this.VisitExpressionList(consArr.Initializers);
   if (et == null && consArr.ElementTypeExpression == null) {
     TypeNodeList tl = new TypeNodeList();
     for (int i = 0, n = consArr.Initializers == null ? 0 : consArr.Initializers.Count; i < n; i++) {
       Expression e = consArr.Initializers[i];
       if (e == null || e.Type == null) continue;
       Literal lit = e as Literal;
       if (lit != null && lit.Value == null) continue; //This prevents null from participating in the type unification, which is by design.
       if (e.Type == null) continue; //e is a bad expression
       tl.Add(e.Type);
     }
     et = this.typeSystem.UnifiedType(tl, this.TypeViewer);
     if (et == null) et = SystemTypes.Object;
     consArr.ElementType = et;
   }
   if (et is DelegateNode) {
     for (int i = 0, n = consArr.Initializers == null ? 0 : consArr.Initializers.Count; i < n; i++) {
       Expression e = consArr.Initializers[i];
       if (e is MemberBinding && ((MemberBinding)e).BoundMember is Method)
         consArr.Initializers[i] = this.VisitExpression(new Construct(new MemberBinding(null, et), new ExpressionList(e)));
     }
   }
   consArr.Owner = this.VisitExpression(consArr.Owner);
   consArr.Type = SystemTypes.Object;
   if (et == null) return null;
   consArr.Type = et.GetArrayType(consArr.Rank);
   if (this.currentPreprocessorDefinedSymbols != null && this.NonNullChecking)
     consArr.Type = OptionalModifier.For(SystemTypes.NonNullType, consArr.Type);
   return consArr;
 }
Exemplo n.º 22
0
	void InstPTypes(out TypeNodeList tns) {
		tns = new TypeNodeList();
		TypeNode tn;
		
		Expect(31);
		if (StartOf(5)) {
			PType(out tn);
			tns.Add(tn); 
			while (la.kind == 23) {
				Get();
				PType(out tn);
				tns.Add(tn); 
			}
		}
		Expect(32);
	}
Exemplo n.º 23
0
    /// <summary>
    /// If type has an explicit or implicit implementation of a method that has an out-of-band contract,
    /// then need to create a proxy that has the same signature as the "real" interface
    /// method and have it call the one the programmer wrote.
    /// </summary>
    /// <param name="type">The type whose members should be checked to find such methods.</param>
    public virtual void CheckForInterfaceImplementationsOfOutOfBandContractedMethods(TypeNode type) {
      MemberList members = this.GetTypeView(type).Members;  // do we need to check all methods?
      for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++) {
        Method method = members[i] as Method;
        if (method == null) continue;

        // If a method is a proxy (created in CheckAbstractMethods), then it can be ignored.
        ProxyMethod pMethod = method as ProxyMethod;
        if (pMethod != null) continue;

        #region Implicit implementation
        // If the method isn't virtual, then it will have been given a proxy as part of CheckAbstractMethods
        if (method.IsVirtual && method.ImplicitlyImplementedInterfaceMethods != null) {
          MethodList remainingImplicitImplementedInterfaceMethods = new MethodList(method.ImplicitlyImplementedInterfaceMethods.Count);
          for (int j = 0, m = method.ImplicitlyImplementedInterfaceMethods.Count; j < m; j++) {
            Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[j];
            if (ifaceMethod != null && ifaceMethod.HasOutOfBandContract) {
              this.CreateProxy(type, ifaceMethod, method);
            } else {
              remainingImplicitImplementedInterfaceMethods.Add(ifaceMethod);
            }
          }
          method.ImplicitlyImplementedInterfaceMethods = remainingImplicitImplementedInterfaceMethods;
        }
        #endregion Implicit implementation

        #region Explicit implementation
        if (method.ImplementedInterfaceMethods != null) {
          MethodList remainingImplementedInterfaceMethods = new MethodList(method.ImplementedInterfaceMethods.Count);
          TypeNodeList remainingImplementedTypes = new TypeNodeList(method.ImplementedTypes.Count);
          for (int j = 0, m = method.ImplementedInterfaceMethods.Count; j < m; j++) {
            Method ifaceMethod = method.ImplementedInterfaceMethods[j];
            TypeNode ifaceType = method.ImplementedTypes[j];
            if (ifaceMethod != null && ifaceMethod.HasOutOfBandContract) {
              this.CreateProxy(type, ifaceMethod, method);
              // We may need to modify the name if there is another method
              // in the type that has the same name. That is, method's name
              // was written by the programmer as I.f where I is the name of
              // the interface. But since it no longer implements the interface
              // (the proxy does instead), its name will be just "f" in the
              // assembly. If there is another method in the same type with
              // that name, the IL will be bad. So just to play it safe, make
              // the name "fully qualified", i.e., I.f.
              method.Name = new Identifier(ifaceMethod.FullName, method.Name.SourceContext);
            } else {
              remainingImplementedInterfaceMethods.Add(ifaceMethod);
              remainingImplementedTypes.Add(ifaceType);
            }
          }
          method.ImplementedInterfaceMethods = remainingImplementedInterfaceMethods;
          method.ImplementedTypes = remainingImplementedTypes;
        }
        #endregion Explicit implementation
      }
    }
Exemplo n.º 24
0
 public override Method VisitMethod(Method method){
   if (method == null) return null;
   if (method.IsNormalized) return method;
   if (method.Scope != null) method.Scope.ThisTypeInstance = this.currentTypeInstance;
   method.Attributes = this.VisitAttributeList(method.Attributes);
   method.ReturnAttributes = this.VisitAttributeList(method.ReturnAttributes);
   method.SecurityAttributes = this.VisitSecurityAttributeList(method.SecurityAttributes);
   Method savedCurrentMethod = this.currentMethod;
   this.currentMethod = method;
   method.ReturnType = this.VisitTypeReference(method.ReturnType);
   TypeNodeList implementedTypes = method.ImplementedTypes = this.VisitTypeReferenceList(method.ImplementedTypes);
   method.Parameters = this.VisitParameterList(method.Parameters);
   method.TemplateArguments = this.VisitTypeReferenceList(method.TemplateArguments);
   method.TemplateParameters = this.VisitTypeParameterList(method.TemplateParameters);
   method.Contract = this.VisitMethodContract(method.Contract);
   method = this.CheckMethodProperties(method);
   if (method == null) {
     this.currentMethod = savedCurrentMethod;
     return method;
   }
   method.Body = this.VisitBlock(method.Body);
   StreamTypeExpression stExpr = method.ReturnType as StreamTypeExpression;
   TypeUnionExpression tuExpr = stExpr != null ? (TypeUnionExpression)stExpr.ElementType : (method.ReturnType as TypeUnionExpression);
   if (tuExpr != null){
     TypeNodeList types = new TypeNodeList();
     TrivialHashtable alreadyPresent = new TrivialHashtable();
     //REVIEW: this seems redundant
     for (int i = 0, m = tuExpr.Types == null ? 0 : tuExpr.Types.Count; i < m; i++){
       TypeNode t = tuExpr.Types[i];
       if (t == null) continue;
       if (alreadyPresent[t.UniqueKey] != null) continue;
       types.Add(t);
       alreadyPresent[t.UniqueKey] = t;
     }
     if (types.Count == 1) 
       method.ReturnType = types[0];
     else
       method.ReturnType = TypeUnion.For(types, this.currentType);
   }
   if (stExpr != null)
     method.ReturnType = SystemTypes.GenericIEnumerable.GetTemplateInstance(this.currentType, method.ReturnType);
   int n = implementedTypes == null ? 0 : implementedTypes.Count;
   MethodList implementedInterfaceMethods = method.ImplementedInterfaceMethods = n == 0 ? null : new MethodList(n);
   for (int i = 0; i < n; i++){
     Interface iface = implementedTypes[i] as Interface;
     Method meth = null;
     if (iface != null){
       MemberList members = this.GetTypeView(iface).GetMembersNamed(method.Name);
       for (int j = 0, m = members.Count; j < m; j++){
         Method im = members[j] as Method;
         if (im == null) continue;
         if (im.ReturnType == null || !im.ReturnType.IsStructurallyEquivalentTo(method.ReturnType)) continue;
         if (!im.ParametersMatchStructurally(method.Parameters)) continue;
         meth = im;
         break;
       }
     }
     implementedInterfaceMethods.Add(meth);
   }
   this.currentMethod = savedCurrentMethod;
   return method;
 }
Exemplo n.º 25
0
        private static void DuplicateMember(DuplicatorForContractsAndClosures dup, FindClosurePartsToDuplicate fmd,
            int memindex, TypeNode targetType)
        {
            Member mem = fmd.MembersToDuplicate[memindex];
            
            TypeNode nestedType = mem as TypeNode;
            Method closureInstanceMethod = mem as Method;
            Method closureMethodTemplate = closureInstanceMethod;
            
            while (closureMethodTemplate != null && closureMethodTemplate.Template != null)
            {
                closureMethodTemplate = closureMethodTemplate.Template;
            }

            if (nestedType != null)
            {
                // if nested type is nested inside another type to be duplicated, skip it
                if (nestedType.DeclaringType != null && fmd.MembersToDuplicate.Contains(nestedType.DeclaringType))
                    return;
                
                // For call-site wrappers, we end up having multiple methods from the same original contract method
                // thus we have to avoid duplicating the same closure type multiple times.
                var duplicatedNestedType = FindExistingClosureType(targetType, nestedType);
                if (duplicatedNestedType == null)
                {
                    dup.FindTypesToBeDuplicated(new TypeNodeList(nestedType));

                    // if parent type is generic and different from the target type, then we may have to include all the
                    // consolidated type parameters excluding the ones from the target type.
                    TypeNodeList originalTemplateParameters = FindNonStandardTypeParametersToBeDuplicated(fmd,
                        nestedType, targetType);

                    duplicatedNestedType = dup.Visit(mem) as TypeNode;
                    if (originalTemplateParameters != null)
                    {
                        int parentParameters = (targetType.ConsolidatedTemplateParameters == null)
                            ? 0
                            : targetType.ConsolidatedTemplateParameters.Count;

                        if (parentParameters > 0 &&
                            (nestedType.DeclaringType.ConsolidatedTemplateParameters == null ||
                             nestedType.DeclaringType.ConsolidatedTemplateParameters.Count == 0))
                        {
                            // type is turning from non-generic to generic
                            Debug.Assert(false);
                        }

                        TypeNodeList dupTPs = DuplicateTypeParameterList(originalTemplateParameters, parentParameters, duplicatedNestedType);

                        duplicatedNestedType.TemplateParameters = dupTPs;
                        dup.SafeAddMember(targetType, duplicatedNestedType, mem);


                        // populate the self specialization forwarding
                        //  OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C>
                        //var oldSelfInstanceType = nestedType.GetGenericTemplateInstance(targetModule, nestedType.ConsolidatedTemplateParameters);
                        //var newSelfInstanceType = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters);
                        //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = newSelfInstanceType;
                        // specialize duplicated type
                        var specializer = new Specializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs);
                        
                        specializer.VisitTypeParameterList(dupTPs); // for constraints etc.
                        specializer.VisitTypeNode(duplicatedNestedType);

                        var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule,
                            originalTemplateParameters, dupTPs);

                        bodySpecializer.Visit(duplicatedNestedType);
                        
                        // after copying the closure class, clear the self specialization forwarding
                        //  OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C>
                        //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = null;
                    }
                    else
                    {
                        dup.SafeAddMember(targetType, duplicatedNestedType, mem);
                    }
                }
                else
                {
                    // already copied type previously
                    dup.DuplicateFor[nestedType.UniqueKey] = duplicatedNestedType;
#if false
        if (nestedType.ConsolidatedTemplateArguments != null)
        {
            // populate the self specialization forwarding
            //  NestedType<Self1,Self2> -> NewNestedType<NewSelf1,NewSelf2>
            var origSelfInstantiation = nestedType.DeclaringType.GetTemplateInstance(nestedType, nestedType.DeclaringType.TemplateParameters).GetNestedType(nestedType.Name);
            var newSelfInstantiation = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters);
            dup.DuplicateFor[origSelfInstantiation.UniqueKey] = newSelfInstantiation;
            // Also forward ContractType<A,B>.NestedType instantiated at target ContractType<X,Y>.NestedType to
            // TargetType<X,Y,Z>.NewNestedType<X,Y>, since this reference may appear in the contract itself.
            var consolidatedContractTemplateArguments = sourceMethod.DeclaringType.ConsolidatedTemplateArguments;
            var instantiatedNestedOriginal = nestedType.DeclaringType.GetGenericTemplateInstance(targetModule, consolidatedContractTemplateArguments).GetNestedType(nestedType.Name);
            dup.DuplicateFor[instantiatedNestedOriginal.UniqueKey] = duplicatedNestedType.GetTemplateInstance(targetType, consolidatedContractTemplateArguments);
        }
        else
        {
            Debugger.Break();
        }
#endif
                }
            }
            else if (closureInstanceMethod != null && closureMethodTemplate != null &&
                     !fmd.MembersToDuplicate.Contains(closureMethodTemplate.DeclaringType))
            {
                Method closureMethod = closureMethodTemplate;

                Debug.Assert(closureMethod.Template == null);
                
                //var m = FindExistingClosureMethod(targetType, closureMethod);
                Method m = null;
                
                // why did we ever try to find an existing one? This can capture a completely unrelated closure that happens to match by name.
                if (m == null)
                {
                    Method dupMethod = dup.Visit(closureMethod) as Method;
                    TypeNodeList actuals;

                    TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(dupMethod, closureMethod,
                        closureInstanceMethod, out actuals);

                    // now setup a forwarding from the closureInstanceMethod to the new instance
                    Method newInstance = dupMethod.GetTemplateInstance(dupMethod.DeclaringType, actuals);
                    newInstance.Name = dupMethod.Name;

                    dup.DuplicateFor[closureInstanceMethod.UniqueKey] = newInstance;

                    dup.SafeAddMember(targetType, dupMethod, closureMethod);

                    // special case when resulting method is generic and instance, then we need to make "this" a parameter
                    // and the method static, otherwise, there's a type mismatch between the "this" and the explicitly generic parameter types used
                    // in arguments.
                    var originalParentTemplateParameters = closureMethod.DeclaringType.ConsolidatedTemplateParameters;
                    if (!dupMethod.IsStatic && originalParentTemplateParameters != null && originalParentTemplateParameters.Count > 0)
                    {
                        var oldThis = dupMethod.ThisParameter;
                        oldThis.Type = dup.PossiblyRemapContractClassToInterface(oldThis.Type);
                        
                        dupMethod.Flags |= MethodFlags.Static;
                        dupMethod.CallingConvention &= ~CallingConventionFlags.HasThis;
                        
                        var oldParameters = dupMethod.Parameters;
                        
                        dupMethod.Parameters = new ParameterList(oldParameters.Count + 1);
                        dupMethod.Parameters.Add(oldThis); // make explicit
                        
                        for (int i = 0; i < oldParameters.Count; i++)
                        {
                            dupMethod.Parameters.Add(oldParameters[i]);
                        }

                        // now need to specialize transforming original parameters into first n method template parameters
                        var targetTypeParameters = new TypeNodeList(originalParentTemplateParameters.Count);
                        for (int i = 0; i < originalParentTemplateParameters.Count; i++)
                        {
                            targetTypeParameters.Add(dupMethod.TemplateParameters[i]);
                        }

                        var specializer = new Specializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters);
                        specializer.VisitMethod(dupMethod);

                        var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule,
                            originalParentTemplateParameters, targetTypeParameters);

                        bodySpecializer.VisitMethod(dupMethod);
                    }
                }
            }
            else if (closureInstanceMethod != null)
            {
                var m = FindExistingClosureMethod(targetType, closureInstanceMethod);
                if (m == null)
                {
                    Member duplicatedMember = dup.Visit(mem) as Member;
                    dup.SafeAddMember(targetType, duplicatedMember, mem);
                }
            }
            else
            {
                Member duplicatedMember = dup.Visit(mem) as Member;
                dup.SafeAddMember(targetType, duplicatedMember, mem);
            }
        }
Exemplo n.º 26
0
 public virtual Method InferMethodTemplateArgumentsAndReturnTemplateInstance(Method method, ParameterList delegateParameters){
   if (method == null || method.Parameters == null || method.Parameters.Count == 0 || 
     method.TemplateParameters == null || method.TemplateParameters.Count == 0){Debug.Assert(false); return method;}
   if (delegateParameters == null) return method;
   int numParams = delegateParameters.Count;
   if (numParams == 0 || numParams != method.Parameters.Count){Debug.Assert(false); return method;}
   TrivialHashtable inferredTypeFor = new TrivialHashtable();
   for (int i = 0; i < numParams; i++){
     Parameter dpar = delegateParameters[i]; if (dpar == null || dpar.Type == null) continue;
     Parameter mpar = method.Parameters[i]; if (mpar == null) continue;
     if (!this.InferMethodTemplateArguments(dpar.Type, null, mpar.Type, inferredTypeFor)) return method;
   }
   int numTypeArgs = method.TemplateParameters.Count;
   TypeNodeList typeArguments = new TypeNodeList(numTypeArgs);
   for (int i = 0; i < numTypeArgs; i++){
     TypeNode templPar = method.TemplateParameters[i]; 
     if (templPar == null) return method;
     TypeNode templArg = inferredTypeFor[templPar.UniqueKey] as TypeNode;
     if (templArg == null) return method;
     typeArguments.Add(templArg);
   }
   return method.GetTemplateInstance(this.currentType, typeArguments);
 }
Exemplo n.º 27
0
        private static void TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(Method dupMethod,
            Method closureMethod, Method closureInstanceMethod, out TypeNodeList actuals)
        {
            // make sure that if we copy it from a generic context, the method becomes generic in the target context
            // if we are copying from the same declaring type (not instantiated), then don't add enclosing type parameters.
            var originals = closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments == null
                ? null
                : closureMethod.DeclaringType.ConsolidatedTemplateParameters;

            if (originals != null)
            {
                originals = originals.Clone();
            }
            
            if (closureMethod.TemplateParameters != null && closureMethod.TemplateParameters.Count > 0)
            {
                if (originals == null)
                {
                    originals = closureMethod.TemplateParameters.Clone();
                }
                else
                {
                    foreach (var tp in closureMethod.TemplateParameters)
                    {
                        originals.Add(tp);
                    }
                }
            }

            if (originals == null)
            {
                actuals = null;
                return;
            }

            actuals = closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments == null
                ? null
                : closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments.Clone();
            
            if (closureInstanceMethod.TemplateArguments != null && closureInstanceMethod.TemplateArguments.Count > 0)
            {
                if (actuals == null)
                {
                    actuals = closureInstanceMethod.TemplateArguments.Clone();
                }
                else
                {
                    foreach (var tp in closureInstanceMethod.TemplateArguments)
                    {
                        actuals.Add(tp);
                    }
                }
            }

            var declaringModule = dupMethod.DeclaringType.DeclaringModule;

            // new method formals
            var tparams = originals.Clone();

            for (int i = 0; i < originals.Count; i++)
            {
                // setup forwarding of tparams to method params
                ITypeParameter tp = originals[i] as ITypeParameter;
                
                TypeNode mtp = NewEqualMethodTypeParameter(tp, dupMethod, i);
                
                tparams[i] = mtp;
            }

            var specializer = new Specializer(declaringModule, originals, tparams);
            
            // System.Console.WriteLine("Made {0} a generic method", dupMethod.FullName);
            dupMethod.TemplateParameters = tparams;
            dupMethod.IsGeneric = true;

            specializer.VisitMethod(dupMethod);
            
            var bodySpecializer = new MethodBodySpecializer(declaringModule, originals, tparams);
            
            bodySpecializer.CurrentType = dupMethod.DeclaringType;
            bodySpecializer.CurrentMethod = dupMethod;
            bodySpecializer.VisitBlock(dupMethod.Body);
        }
Exemplo n.º 28
0
 public virtual Member ResolveOverload(MemberList members, ExpressionList arguments, bool doNotDiscardOverloadsWithMoreParameters){
   if (members == null || members.Count == 0) return null;
   TypeNode declaringType = members[0].DeclaringType;
   Identifier id = members[0].Name;
   int n = arguments == null ? 0 : arguments.Count;
   TypeNode[] argTypes = new TypeNode[n];
   for (int i = 0; i < n; i++){
     Expression arg = arguments[i];
     if (arg == null){
       argTypes[i] = SystemTypes.Object;
     }else{
       Literal lit = arg as Literal;
       if (lit != null && lit.Type != null && lit.Type.IsPrimitiveInteger && !lit.TypeWasExplicitlySpecifiedInSource)
         argTypes[i] = this.typeSystem.SmallestIntegerType(lit.Value);
       else
         argTypes[i] = TypeNode.StripModifiers(arg.Type);
     }
   }
   TypeNodeList bestParamTypes = new TypeNodeList(n);
   for (int i = 0; i < n; i++) bestParamTypes.Add(TypeSystem.DoesNotMatchAnyType);
   TypeNode bestElementType = null;
   Member bestMember = this.GetBestMatch(members, arguments, argTypes, bestParamTypes, null, ref bestElementType, doNotDiscardOverloadsWithMoreParameters);
   if (bestMember == Resolver.MethodNotFound) return null;
   if (!(members[0] is InstanceInitializer || members[0] is StaticInitializer)){
     while (declaringType != SystemTypes.Object && (declaringType = declaringType.BaseType) != null){
       MemberList baseMembers = this.GetTypeView(declaringType).GetMembersNamed(id);
       if (baseMembers.Count == 0) continue;
       bestMember = this.GetBestMatch(baseMembers, arguments, argTypes, bestParamTypes, bestMember, ref bestElementType);
     }
   }
   if (bestMember == null){
     //Search again, but consider inaccessible members. Otherwise the error message does not distinguish between no member no accessible member.
     this.considerInaccessibleMethods = true;
     declaringType = members[0].DeclaringType;
     for (int i = 0; i < n; i++) bestParamTypes[i] = TypeSystem.DoesNotMatchAnyType; 
     bestElementType = null;
     bestMember = this.GetBestMatch(members, arguments, argTypes, bestParamTypes, null, ref bestElementType);
     if (bestMember == Resolver.MethodNotFound) return null;
     if (!(members[0] is InstanceInitializer || members[0] is StaticInitializer)){
       while ((declaringType = declaringType.BaseType) != null){
         MemberList baseMembers = this.GetTypeView(declaringType).GetMembersNamed(id);
         if (baseMembers.Count == 0) continue;
         Member bestMember2 = this.GetBestMatch(baseMembers, arguments, argTypes, bestParamTypes, bestMember, ref bestElementType);
         if (bestMember2 != null) bestMember = bestMember2;
       }
     }
     this.considerInaccessibleMethods = false;
   }
   return bestMember;
 }
Exemplo n.º 29
0
        /// <summary>
        /// Updates the state of the drop down bars to match the current contents of the text editor window. Call this initially and every time
        /// the cursor position changes.
        /// </summary>
        /// <param name="textView">The editor window</param>
        /// <param name="line">The line on which the cursor is now positioned</param>
        /// <param name="col">The column on which the cursor is now position</param>
        public void SynchronizeDropdowns(IVsTextView textView, int line, int col)
        {
            this.textView = textView;
            string fname = this.languageService.GetFileName(textView); if (fname == null)

            {
                return;
            }

            LanguageService.Project proj = this.languageService.GetProjectFor(fname); if (proj == null)
            {
                return;
            }
            object indx = proj.IndexForFileName[Identifier.For(fname).UniqueKey]; if (!(indx is int))
            {
                return;
            }
            int index = (int)indx;

            if (index >= proj.parseTrees.Length)
            {
                return;
            }
            CompilationUnit cu = proj.parseTrees[index] as CompilationUnit;

            if (cu == null)
            {
                return;
            }
            AuthoringHelper helper      = this.languageService.GetAuthoringHelper();
            TypeNodeList    types       = this.dropDownTypes;
            TypeNodeList    sortedTypes = this.sortedDropDownTypes;

            if (cu != this.currentCompilationUnit)
            {
                this.currentCompilationUnit = cu;
                //Need to reconstruct the type lists. First get the types in text order.
                types = this.dropDownTypes = new TypeNodeList();
                this.PopulateTypeList(types, cu.Namespaces);
                //Now sort by full text name.
                int n = types.Length;
                if (n == 0)
                {
                    return;
                }
                sortedTypes = this.sortedDropDownTypes = new TypeNodeList(n);
                int[] dropDownTypeGlyphs = this.dropDownTypeGlyphs = new int[n];
                for (int i = 0; i < n; i++)
                {
                    TypeNode t = types[i];
                    if (t == null)
                    {
                        Debug.Assert(false); continue;
                    }
                    string tName = t.FullName;
                    int    glyph = dropDownTypeGlyphs[sortedTypes.Length] = helper.GetGlyph(t);
                    sortedTypes.Add(t);
                    for (int j = i - 1; j >= 0; j--)
                    {
                        if (string.Compare(tName, sortedTypes[j].FullName) >= 0)
                        {
                            break;
                        }
                        sortedTypes[j + 1]        = sortedTypes[j];
                        sortedTypes[j]            = t;
                        dropDownTypeGlyphs[j + 1] = dropDownTypeGlyphs[j];
                        dropDownTypeGlyphs[j]     = glyph;
                    }
                }
                this.selectedType = -1;
            }
            //Find the type matching the given source position
            int newType = 0;

            for (int i = 0, n = types.Length; i < n; i++)
            {
                TypeNode t = types[i];
                if (t.SourceContext.StartLine > line + 1 || (t.SourceContext.StartLine == line + 1 && t.SourceContext.StartColumn > col + 1))
                {
                    if (i > 0)
                    {
                        t = types[i - 1];
                    }
                }
                else if (i < n - 1)
                {
                    continue;
                }
                for (int j = 0; j < n; j++)
                {
                    if (sortedTypes[j] != t)
                    {
                        continue;
                    }
                    newType = j;
                    break;
                }
                break;
            }
            MemberList members       = this.dropDownMembers;
            MemberList sortedMembers = this.sortedDropDownMembers;

            if (newType != this.selectedType)
            {
                TypeNode t = sortedTypes[newType];
                if (t.Members == null)
                {
                    return;
                }
                //Need to reconstruct the member list. First get the members in text order.
                members = t.Members;
                int        n          = members == null ? 0 : members.Length;
                MemberList newMembers = this.dropDownMembers = new MemberList(n);
                //Now sort them
                sortedMembers = this.sortedDropDownMembers = new MemberList(n);
                string[] memSignatures        = this.dropDownMemberSignatures = new string[n];
                int[]    dropDownMemberGlyphs = this.dropDownMemberGlyphs = new int[n];
                for (int i = 0; i < n; i++)
                {
                    Member mem = members[i];
                    if (mem == null)
                    {
                        continue;
                    }
                    string memSignature = this.languageService.errorHandler.GetUnqualifiedMemberSignature(mem);
                    if (memSignature == null)
                    {
                        continue;
                    }
                    memSignatures[sortedMembers.Length] = memSignature;
                    int glyph = dropDownMemberGlyphs[sortedMembers.Length] = helper.GetGlyph(mem);
                    newMembers.Add(mem);
                    sortedMembers.Add(mem);
                    for (int j = i - 1; j >= 0; j--)
                    {
                        if (string.Compare(memSignature, memSignatures[j]) >= 0)
                        {
                            break;
                        }
                        memSignatures[j + 1]        = memSignatures[j];
                        memSignatures[j]            = memSignature;
                        sortedMembers[j + 1]        = sortedMembers[j];
                        sortedMembers[j]            = mem;
                        dropDownMemberGlyphs[j + 1] = dropDownMemberGlyphs[j];
                        dropDownMemberGlyphs[j]     = glyph;
                    }
                }
                this.selectedMember = -1;
            }
            //Find the member matching the given source position
            members = this.dropDownMembers;
            int newMember = 0;

            for (int i = 0, n = sortedMembers.Length; i < n; i++)
            {
                Member mem = members[i];
                if (mem == null)
                {
                    continue;
                }
                if (mem.SourceContext.StartLine > line + 1 || (mem.SourceContext.StartLine == line + 1 && mem.SourceContext.StartColumn > col + 1))
                {
                    if (i > 0)
                    {
                        mem = members[i - 1];
                    }
                }
                else if (i < n - 1)
                {
                    continue;
                }
                for (int j = 0; j < n; j++)
                {
                    if (sortedMembers[j] != mem)
                    {
                        continue;
                    }
                    newMember = j;
                    break;
                }
                break;
            }
            if (this.dropDownBar == null)
            {
                return;
            }
            if (this.selectedType != newType)
            {
                this.selectedType = newType;
                this.dropDownBar.RefreshCombo(TypeAndMemberDropdownBars.DropClasses, newType);
            }
            if (this.selectedMember != newMember)
            {
                this.selectedMember = newMember;
                this.dropDownBar.RefreshCombo(TypeAndMemberDropdownBars.DropMethods, newMember);
            }
        }
Exemplo n.º 30
0
    public override Method VisitMethod(Method method) {
      if (method == null) return null;
      if (method.IsNormalized) return method;
      this.MayReferenceThisAndBase = !(method is InstanceInitializer) || method.DeclaringType == null || method.DeclaringType.IsValueType;
      if (method.Name != null && method.Name.UniqueIdKey == StandardIds.Finalize.UniqueIdKey && method.HasCompilerGeneratedSignature &&
        method.DeclaringType is Class && ((Class)method.DeclaringType).IsAbstractSealedContainerForStatics)
        this.HandleError(method.Name, Error.DestructorInAbstractSealedClass);
      method.Attributes = this.VisitAttributeList(method.Attributes, method);
      method.ReturnAttributes = this.VisitAttributeList(method.ReturnAttributes);
      method.SecurityAttributes = this.VisitSecurityAttributeList(method.SecurityAttributes);
      if ((method.ReturnType == SystemTypes.DynamicallyTypedReference || method.ReturnType == SystemTypes.ArgIterator) && 
      (this.currentOptions == null || !this.currentOptions.NoStandardLibrary) ) {
        this.HandleError(method.Name, Error.CannotReturnTypedReference, this.GetTypeName(method.ReturnType));
        method.ReturnType = SystemTypes.Object;
      }
      if (method.Body != null) {
        if (method.DeclaringType is Interface && !method.IsStatic) {
          this.HandleError(method.Name, Error.InterfaceMemberHasBody, this.GetMethodSignature(method));
          method.Body = null;
        } else if (method.IsAbstract) {
          this.HandleError(method.Name, Error.AbstractHasBody, this.GetMethodSignature(method));
          method.Body = null;
        }
      } else if (!method.IsAbstract && !method.IsExtern && !this.isCompilingAContractAssembly) {
        this.HandleError(method.Name, Error.ConcreteMissingBody, this.GetMethodSignature(method));
        return null;
      } else if (method.TemplateParameters != null && method.TemplateParameters.Count > 0 && !this.useGenerics) {
        SourceContext ctx = method.TemplateParameters[0].SourceContext;
        ctx.EndPos = method.TemplateParameters[method.TemplateParameters.Count-1].SourceContext.EndPos;
        Debug.Assert(ctx.EndPos >= ctx.StartPos);
        Node n = new UnaryExpression();
        n.SourceContext = ctx;
        if (method.DeclaringType is Interface)
          this.HandleError(n, Error.AbstractInterfaceMethod);
        else
          this.HandleError(n, Error.AbstractMethodTemplate);
        return null;
      }
      BlockScope savedCurrentFinallyClause = this.currentFinallyClause;
      Method savedCurrentMethod = this.currentMethod;
      Return savedReturnNode = this.returnNode;
      Yield savedYieldNode = this.yieldNode;
      this.currentFinallyClause = null;
      this.currentMethod = method;
      this.returnNode = null;
      this.yieldNode = null;
      MethodScope scope = method.Scope;
      this.CheckForDuplicateDeclarations(scope);

      if ((this.currentPreprocessorDefinedSymbols != null && this.currentPreprocessorDefinedSymbols.ContainsKey("DefaultExposeBlocks")) &&
        !method.IsStatic && !(method is InstanceInitializer) && method.DeclaringType is Class && 
        !method.IsAbstract && method.CciKind == CciMemberKind.Regular && method.ApplyDefaultContract) {
        This thisOb = method.ThisParameter;
        MethodCall thisIsExposable = new MethodCall(
          new MemberBinding(null, SystemTypes.Guard.GetMethod(Identifier.For("FrameIsExposable"),
            SystemTypes.Object, SystemTypes.Type)),
            new ExpressionList(thisOb, new UnaryExpression(new Literal(method.DeclaringType, SystemTypes.Type),
            NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type))), NodeType.Call,
            SystemTypes.Boolean, method.Body.SourceContext);
        Assumption assumption = new Assumption(thisIsExposable);
        Expose expose = new Expose(NodeType.Write);
        expose.SourceContext = method.Body.SourceContext;
        expose.Instance = thisOb;
        expose.Body = method.Body;
        if (this.currentOptions != null && this.currentOptions.DisableGuardedClassesChecks)
          method.Body = new Block(new StatementList(assumption, expose));
        else
          method.Body = new Block(new StatementList(expose));
      }


      #region Check contract rules for all interface methods and base methods this method implements/overrides
      bool ok = true;
      if (method.IsVirtual && !method.IsCompilerControlled) {
        // use FindNearest..., can't rely on method.OverriddenMethod since it might not be set further up the chain
        Method overridden = method.DeclaringType.FindNearestOverriddenMethod(method);
        if (overridden != null) {
          ok &= this.CheckContractRules(overridden, method, method.DeclaringType);
        }
        for (int i = 0, n = method.ImplementedInterfaceMethods == null ? 0 : method.ImplementedInterfaceMethods.Count; i < n; i++) {
          Method ifaceMethod = method.ImplementedInterfaceMethods[i];
          ok &= this.CheckContractRules(ifaceMethod, method, method.DeclaringType);
        }
        for (int i = 0, n = method.ImplicitlyImplementedInterfaceMethods == null ? 0 : method.ImplicitlyImplementedInterfaceMethods.Count; i < n; i++) {
          Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[i];
          ok &= this.CheckContractRules(ifaceMethod, method, method.DeclaringType);
        }
      }
      #endregion

      #region Contract Inheritance for method overrides and interface implementations (do this somewhere else?)
      // This needs to be done here (and not in VisitMethodContract) because method might not even have a contract
      if (method.IsVirtual && ok && !method.IsCompilerControlled) {
        // use FindNearest..., can't rely on method.OverriddenMethod since it might not be set further up the chain
        Method overridden = method.DeclaringType.FindNearestOverriddenMethod(method);
        // FindNearestOverriddenMethod doesn't care if method is "new" or an "override", so explicity test IsVirtual property
        MethodContract cumulativeContract = method.Contract == null ? new MethodContract(method) : method.Contract;
        bool somethingWasCopied = false;
        while (overridden != null && overridden.IsVirtual) {
          if (overridden.Contract != null) {
            cumulativeContract.CopyFrom(overridden.Contract);
            somethingWasCopied = true;
            break;
          }
          overridden = overridden.DeclaringType.FindNearestOverriddenMethod(overridden);
        }
        // Can inherit from at most one interface method
        bool ifaceContractWasCopied = false;
        for (int i = 0, n = method.ImplementedInterfaceMethods == null ? 0 : method.ImplementedInterfaceMethods.Count; i < n; i++) {
          Method ifaceMethod = method.ImplementedInterfaceMethods[i];
          if (ifaceMethod == null) continue;
          if (ifaceMethod.Contract != null) {
            if (ifaceContractWasCopied) {
              this.HandleError(method, Error.RequiresNotAllowedInInterfaceImplementation, this.GetMethodSignature(ifaceMethod));
              break;
            }
            cumulativeContract.CopyFrom(ifaceMethod.Contract);
            somethingWasCopied = true;
            ifaceContractWasCopied = true;
          }
        }
        for (int i = 0, n = method.ImplicitlyImplementedInterfaceMethods == null ? 0 : method.ImplicitlyImplementedInterfaceMethods.Count; i < n; i++) {
          Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[i];
          if (ifaceMethod == null) continue;
          if (ifaceMethod.Contract != null) {
            if (ifaceContractWasCopied) {
              this.HandleError(method, Error.RequiresNotAllowedInInterfaceImplementation, this.GetMethodSignature(ifaceMethod));
              break;
            }
            cumulativeContract.CopyFrom(ifaceMethod.Contract);
            somethingWasCopied = true;
            ifaceContractWasCopied = true;
          }
        }
        if (method.Contract == null && somethingWasCopied) { // otherwise it was already copied into the method's contract 
          method.Contract = cumulativeContract;
        }
      }
      #endregion
      
      // For checked exceptions, the actual exceptions thrown must be a subset of the allowed exceptions
      TypeNodeList aes = new TypeNodeList();
      if (method.Contract != null && method.Contract.Ensures != null) {
        for (int i = 0, n = method.Contract.Ensures.Count; i < n; i++) {
          EnsuresExceptional ee = method.Contract.Ensures[i] as EnsuresExceptional;
          if (ee == null || ee.Inherited) continue;
          aes.Add(ee.Type);
        }
      }
      TypeNodeList saveAllowedExceptions = this.allowedExceptions;
      this.allowedExceptions = aes;
      // don't check method body of proxy methods.
      Method result = (method is ProxyMethod) ? method : base.VisitMethod(method);
      this.allowedExceptions = saveAllowedExceptions;


      if (this.yieldNode != null && TypeNode.StripModifiers(method.ReturnType) is Interface) {
        StatementList statements = new StatementList(1);
        TypeNode elementType = SystemTypes.Object;
        Interface stype = (Interface)TypeNode.StripModifiers(method.ReturnType);
        if (stype.TemplateArguments != null && stype.TemplateArguments.Count == 1) elementType = stype.TemplateArguments[0];
        Class state = scope.ClosureClass;
        elementType = scope.FixTypeReference(elementType);
        state.Flags |= TypeFlags.Abstract; //So that no complaints are given about missing methods added by Normalizer
        state.Interfaces = new InterfaceList(5);
        state.Interfaces.Add(SystemTypes.IEnumerable);
        state.Interfaces.Add((Interface)SystemTypes.GenericIEnumerator.GetTemplateInstance(this.currentType, elementType));
        state.Interfaces.Add(SystemTypes.IEnumerator);
        state.Interfaces.Add(SystemTypes.IDisposable);
        state.Interfaces.Add((Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(this.currentType, elementType));
        //Add these methods so that Normalizer can find them even when reference to iterator is forward
        Method moveNext = new Method(state, null, StandardIds.MoveNext, null, SystemTypes.Boolean, null);
        moveNext.CallingConvention = CallingConventionFlags.HasThis;
        moveNext.Flags = MethodFlags.Public|MethodFlags.Virtual;
        moveNext.Body = new Block(new StatementList());
        state.Members.Add(moveNext);
        Method getCurrent = new Method(state, null, StandardIds.getCurrent, null, elementType, null);
        getCurrent.CallingConvention = CallingConventionFlags.HasThis;
        getCurrent.Flags = MethodFlags.Public|MethodFlags.Virtual|MethodFlags.SpecialName;
        getCurrent.Body = new Block(new StatementList());
        state.Members.Add(getCurrent);
        Return ret = new Return(new ConstructIterator(state, method.Body, elementType, state));
        if (method.Name.SourceContext.Document != null) {
          ret.SourceContext = method.SourceContext;
          ret.SourceContext.EndPos = method.Name.SourceContext.EndPos;
          Debug.Assert(ret.SourceContext.EndPos >= ret.SourceContext.StartPos);
        }
        statements.Add(ret);
        method.Body = new Block(statements);
        method.Body.Scope = new BlockScope(scope, method.Body);
      }
      if (method.IsStatic && method.IsVirtual && !method.IsSpecialName) {
        method.Flags &= ~MethodFlags.Static;
        this.HandleError(method.Name, Error.StaticNotVirtual, this.GetMethodSignature(method));
      }
      if (!method.OverridesBaseClassMember) {
        if (method.NodeType == NodeType.InstanceInitializer || !method.IsSpecialName) {
          if (!(method.DeclaringType is Interface) && !(method.DeclaringType is DelegateNode)) {
            if (this.IsLessAccessible(method.ReturnType, method)) {
              this.HandleError(method.Name, Error.ReturnTypeLessAccessibleThanMethod, this.GetTypeName(method.ReturnType), this.GetMethodSignature(method));
              this.HandleRelatedError(method.ReturnType);
            }
            this.CheckParameterTypeAccessibility(method.Parameters, method);
          }
        } else {
          if (method.Name != null && Checker.OperatorName[method.Name.UniqueIdKey] != null) {
            if (this.IsLessAccessible(method.ReturnType, method)) {
              this.HandleError(method.Name, Error.ReturnTypeLessAccessibleThanOperator, this.GetTypeName(method.ReturnType), this.GetMethodSignature(method));
              this.HandleRelatedError(method.ReturnType);
            }
            this.CheckParameterTypeAccessibility(method.Parameters, method);
          }
        }
      }

      if (!method.IsSpecialName) {
        TypeNodeList implementedTypes = method.ImplementedTypes;
        if (implementedTypes != null) {
          InterfaceList declaringTypeInterfaces = this.GetTypeView(method.DeclaringType).Interfaces;
          for (int i = 0, n = implementedTypes.Count; i < n; i++) {
            Interface iface = implementedTypes[i] as Interface;
            if (iface == null) continue;
            if (!this.IsAllowedAsImplementedType(declaringTypeInterfaces, iface)) {
              Node offendingNode = method.ImplementedTypeExpressions[i];
              this.HandleError(offendingNode, Error.ContainingTypeDoesNotImplement, this.GetMethodSignature(method), this.GetTypeName(iface));
              this.HandleRelatedError(iface);
              implementedTypes = null;
              break;
            }
          }
        }
        MethodList implementedMethods = method.ImplementedInterfaceMethods;
        for (int i = 0, n = implementedTypes == null ? 0 : implementedTypes.Count; i < n; i++) {
          Interface iface = implementedTypes[i] as Interface;
          if (iface == null) continue;
          Method m = implementedMethods == null ? null : implementedMethods[i];
          if (m == null) {
            this.HandleError(method.Name, Error.InterfaceMemberNotFound, this.GetMemberSignature(method), this.GetTypeName(iface));
            this.HandleRelatedError(iface);
          } else if (m.IsSpecialName)
            this.HandleError(method.Name, Error.CannotExplicitlyImplementAccessor, this.GetMethodSignature(method), this.GetMethodSignature(m));
        }
      }
      if ((method.Flags & MethodFlags.PInvokeImpl) != 0) {
        Error e = Error.None;
        if (this.shadowedAssembly != null) {
          // Make sure this method has a counterpart in the shadowed method
          TypeNode type = this.GetCorrespondingShadowedTypeNode(method.DeclaringType);
          if (type == null) {
            this.HandleError(method.DeclaringType, Error.TypeMissingInShadowedAssembly, this.GetTypeName(method.DeclaringType));
          } else {
            int numParams = method.Parameters == null ? 0 : method.Parameters.Count;
            TypeNode[] types = new TypeNode[numParams];
            for (int i = 0; i < numParams; i++) { types[i] = this.GetCorrespondingShadowedTypeNode(TypeNode.StripModifiers(method.Parameters[i].Type)); }
            if (this.GetTypeView(type).GetMethod(method.Name, types) == null) {
              this.HandleError(method, Error.MethodMissingInShadowedAssembly, this.GetMethodSignature(method));
            }
          }
        } else if (this.isCompilingAContractAssembly)
          e = Error.None;
        else if (method.Body != null)
          e = Error.PInvokeHasBody;
        else if (method.IsAbstract)
          e = Error.AbstractAndExtern;
        else if (method.PInvokeImportName == null || method.PInvokeModule == null) {
          if (method.Attributes == null || method.Attributes.Count == 0)
            e = Error.PInvokeWithoutModuleOrImportName;
          else
            method.Flags &= ~MethodFlags.PInvokeImpl;
        }
        if (e != Error.None)
          this.HandleError(method.Name, e, this.GetMethodSignature(method));
      }
      if (method.IsPropertySetter && (method.IsPure || method.IsConfined || method.IsStateIndependent)) {
        this.HandleError(method, Error.MemberCannotBeAnnotatedAsPure, this.GetMethodSignature(method));
      }
      this.currentFinallyClause = savedCurrentFinallyClause;
      this.currentMethod = savedCurrentMethod;
      this.returnNode = savedReturnNode;
      this.yieldNode = savedYieldNode;
      return result;
    }
Exemplo n.º 31
0
        public EmitAsyncClosure(Method from, Rewriter rewriter)
        {
            Contract.Requires(from != null);
            Contract.Requires(from.DeclaringType != null);
            Contract.Requires(rewriter != null);

            if (TaskExtensionsTypeNode == null)
            {
                throw new InvalidOperationException(
                          "Can't generate async closure because System.Threading.Tasks.TaskExceptions class is unavailable.");
            }

            this.rewriter      = rewriter;
            this.declaringType = from.DeclaringType;

            var closureName = HelperMethods.NextUnusedMemberName(declaringType, "<" + from.Name.Name + ">AsyncContractClosure");

            this.closureClass = new Class(
                declaringModule: declaringType.DeclaringModule,
                declaringType: declaringType,
                attributes: null,
                flags: TypeFlags.NestedPrivate,
                Namespace: null,
                name: Identifier.For(closureName),
                baseClass: SystemTypes.Object,
                interfaces: null,
                members: null);

            declaringType.Members.Add(this.closureClass);
            RewriteHelper.TryAddCompilerGeneratedAttribute(this.closureClass);

            var taskType = from.ReturnType;

            this.aggregateExceptionType = new Cache <TypeNode>(() =>
                                                               HelperMethods.FindType(rewriter.AssemblyBeingRewritten, StandardIds.System,
                                                                                      Identifier.For("AggregateException")));

            this.func2Type = new Cache <TypeNode>(() =>
                                                  HelperMethods.FindType(SystemTypes.SystemAssembly, StandardIds.System, Identifier.For("Func`2")));

            if (from.IsGeneric)
            {
                this.closureClass.TemplateParameters = CreateTemplateParameters(closureClass, from, declaringType);

                this.closureClass.IsGeneric = true;
                this.closureClass.EnsureMangledName();

                this.forwarder = new Specializer(
                    targetModule: this.declaringType.DeclaringModule,
                    pars: from.TemplateParameters,
                    args: this.closureClass.TemplateParameters);

                this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters);

                taskType = this.forwarder.VisitTypeReference(taskType);
            }
            else
            {
                this.closureClassInstance = this.closureClass;
            }

            this.checkMethodTaskType = taskType;

            // Emiting CheckPost method declaration
            EmitCheckPostMethodCore(checkMethodTaskType);

            // Generate closure constructor.
            // Constructor should be generated AFTER visiting type parameters in
            // the previous block of code. Otherwise current class would not have
            // appropriate number of generic arguments!
            var ctor = CreateConstructor(closureClass);

            closureClass.Members.Add(ctor);

            // Now that we added the ctor and the check method, let's instantiate the closure class if necessary
            if (this.closureClassInstance == null)
            {
                var consArgs = new TypeNodeList();
                var args     = new TypeNodeList();

                var parentCount = this.closureClass.DeclaringType.ConsolidatedTemplateParameters == null
                    ? 0
                    : this.closureClass.DeclaringType.ConsolidatedTemplateParameters.Count;

                for (int i = 0; i < parentCount; i++)
                {
                    consArgs.Add(this.closureClass.DeclaringType.ConsolidatedTemplateParameters[i]);
                }

                var methodCount = from.TemplateParameters == null ? 0 : from.TemplateParameters.Count;
                for (int i = 0; i < methodCount; i++)
                {
                    consArgs.Add(from.TemplateParameters[i]);
                    args.Add(from.TemplateParameters[i]);
                }

                this.closureClassInstance =
                    (Class)
                    this.closureClass.GetConsolidatedTemplateInstance(this.rewriter.AssemblyBeingRewritten,
                                                                      closureClass.DeclaringType, closureClass.DeclaringType, args, consArgs);
            }

            // create closure initializer for context method
            this.closureLocal       = new Local(this.ClosureClass);
            this.ClosureInitializer = new Block(new StatementList());

            // TODO: What is this?
            // Add ClosureLocal instantiation?
            this.ClosureInitializer.Statements.Add(
                new AssignmentStatement(
                    this.closureLocal,
                    new Construct(new MemberBinding(null, this.Ctor), new ExpressionList())));
        }
Exemplo n.º 32
0
        private static MapClosureExpressionToOriginalExpression BuildMappingFromClosureToOriginal(TypeNode ClosureClass,
            Method MoveNextMethod, Method OriginalMethod)
        {
            Contract.Ensures(Contract.Result<MapClosureExpressionToOriginalExpression>() != null);

            Dictionary<string, Parameter> closureFieldsMapping = GetClosureFieldsMapping(ClosureClass, OriginalMethod);

            TypeNodeList TPListSource = ClosureClass.ConsolidatedTemplateParameters;

            if (TPListSource == null) TPListSource = new TypeNodeList();

            TypeNodeList TPListTarget = new TypeNodeList();

            if (OriginalMethod.DeclaringType != null &&
                OriginalMethod.DeclaringType.ConsolidatedTemplateParameters != null)
            {
                foreach (TypeNode tn in OriginalMethod.DeclaringType.ConsolidatedTemplateParameters)
                    TPListTarget.Add(tn);
            }

            if (OriginalMethod.TemplateParameters != null)
            {
                foreach (TypeNode tn in OriginalMethod.TemplateParameters)
                {
                    TPListTarget.Add(tn);
                }
            }

            Debug.Assert((TPListSource == null && TPListTarget == null) || TPListSource.Count == TPListTarget.Count);

            return new MapClosureExpressionToOriginalExpression(
                ClosureClass, closureFieldsMapping, TPListSource,
                TPListTarget, OriginalMethod);
        }
Exemplo n.º 33
0
    /// <summary>
    /// If there is an anonymous delegate within a postcondition, then there
    /// will be a call to a delegate constructor.
    /// That call looks like "d..ctor(o,m)" where d is the type of the delegate.
    /// There are two cases depending on whether the anonymous delegate captured
    /// anything. In both cases, m is the method implementing the anonymous delegate.
    /// (1) It does capture something. Then o is the instance of the closure class
    /// implementing the delegate, and m is an instance method in the closure
    /// class.
    /// (2) It does *not* capture anything. Then o is the literal for null and
    /// m is a static method that was added directly to the class.
    /// 
    /// This method will cause the method (i.e., m) to be visited to collect any
    /// Result&lt;T&gt;() expressions that occur in it.
    /// </summary>
    /// <param name="cons">The AST representing the call to the constructor
    /// of the delegate type.</param>
    /// <returns>Whatever the base visitor returns</returns>
    public override Expression VisitConstruct(Construct cons) {
      if (cons.Type is DelegateNode) {
        UnaryExpression ue = cons.Operands[1] as UnaryExpression;
        if (ue == null) goto JustVisit;
        MemberBinding mb = ue.Operand as MemberBinding;
        if (mb == null) goto JustVisit;
        Method m = mb.BoundMember as Method;
        if (!HelperMethods.IsCompilerGenerated(m)) goto JustVisit;

        Contract.Assume(m != null);

        m = Definition(m);
        this.delegateNestingLevel++;
        TypeNode savedClosureClass = this.currentClosureClassInstance;
        Method savedClosureMethod = this.currentClosureMethod;
        Expression savedCurrentAccessToTopLevelClosure = this.currentAccessToTopLevelClosure;

        try
        {
          this.currentClosureMethod = m;

          if (m.IsStatic)
          {
            this.currentClosureClassInstance = null; // no closure object
          }
          else
          {
            this.currentClosureClassInstance = cons.Operands[0].Type;
            if (savedClosureClass == null)
            {
              // Then this is the top-level closure class.
              this.topLevelClosureClassInstance = this.currentClosureClassInstance;
              this.topLevelClosureClassDefinition = Definition(this.topLevelClosureClassInstance);
              this.currentAccessToTopLevelClosure = new This(this.topLevelClosureClassDefinition);
              this.properlyInstantiatedFieldType = this.originalLocalForResult.Type;

              if (this.topLevelMethodFormals != null) 
              {
                Contract.Assume(this.topLevelClosureClassDefinition.IsGeneric);
                Contract.Assume(topLevelClosureClassDefinition.TemplateParameters.Count >= this.topLevelMethodFormals.Count);

                // replace method type parameters in result properly with last n corresponding type parameters of closure class
                TypeNodeList closureFormals = topLevelClosureClassDefinition.TemplateParameters;
                if (closureFormals.Count > this.topLevelMethodFormals.Count)
                {
                  int offset = closureFormals.Count - this.topLevelMethodFormals.Count;
                  closureFormals = new TypeNodeList(this.topLevelMethodFormals.Count);
                  for (int i = 0; i < this.topLevelMethodFormals.Count; i++)
                  {
                    closureFormals.Add(topLevelClosureClassDefinition.TemplateParameters[i + offset]);
                  }
                }
                Duplicator dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType);
                Specializer spec = new Specializer(this.declaringType.DeclaringModule, topLevelMethodFormals, closureFormals);
                var type = dup.VisitTypeReference(this.originalLocalForResult.Type);
                type = spec.VisitTypeReference(type);
                this.properlyInstantiatedFieldType = type;
              }
            }
            else
            {
              while (currentClosureClassInstance.Template != null) currentClosureClassInstance = currentClosureClassInstance.Template;

              // Find the field in this.closureClass that the C# compiler generated
              // to point to the top-level closure
              foreach (Member mem in this.currentClosureClassInstance.Members)
              {
                Field f = mem as Field;
                if (f == null) continue;
                if (f.Type == this.topLevelClosureClassDefinition)
                {
                  var consolidatedTemplateParams = this.currentClosureClassInstance.ConsolidatedTemplateParameters;
                  TypeNode thisType;
                  if (consolidatedTemplateParams != null && consolidatedTemplateParams.Count > 0) {
                    thisType = this.currentClosureClassInstance.GetGenericTemplateInstance(this.assemblyBeingRewritten, consolidatedTemplateParams);
                  }
                  else {
                    thisType = this.currentClosureClassInstance;
                  }
                  this.currentAccessToTopLevelClosure = new MemberBinding(new This(thisType), f);

                  break;
                }
              }
            }
          }
          this.VisitBlock(m.Body);
        }
        finally
        {
          this.delegateNestingLevel--;
          this.currentClosureMethod = savedClosureMethod;
          this.currentClosureClassInstance = savedClosureClass;
          this.currentAccessToTopLevelClosure = savedCurrentAccessToTopLevelClosure;
        }
      }
    JustVisit:
      return base.VisitConstruct(cons);
    }
Exemplo n.º 34
0
        /// <summary>
        /// If source type is insided target type, only grab the type parameters up to the target type. Otherwise, grab consolidated.
        /// </summary>
        private static TypeNodeList FindNonStandardTypeParametersToBeDuplicated(FindClosurePartsToDuplicate fmd, TypeNode sourceType, TypeNode targetType)
        {
            Debug.Assert(TypeNode.IsCompleteTemplate(sourceType));
            Debug.Assert(TypeNode.IsCompleteTemplate(targetType));

            TypeNodeList result = null;
            if (sourceType.DeclaringType != null)
            {
                if (fmd.MembersToDuplicate.Contains(sourceType.DeclaringType))
                {
                    Debug.Assert(false);
                    return null;
                }

                if (sourceType.DeclaringType == targetType) return null;

                if (IsInsideOf(sourceType, targetType))
                {
                    // difficult case. Grab consolidated type parameters, except the ones up from the target type
                    var sourceConsolidated = sourceType.ConsolidatedTemplateParameters;
                    if (sourceConsolidated == null || sourceConsolidated.Count == 0) return null;

                    var targetConsolidated = targetType.ConsolidatedTemplateParameters;
                    if (targetConsolidated == null || targetConsolidated.Count == 0) return sourceConsolidated;
                    
                    if (sourceConsolidated.Count == targetConsolidated.Count) return null; // no extra type parameters

                    result = new TypeNodeList(sourceConsolidated.Count - targetConsolidated.Count);
                    for (int i = 0; i < sourceConsolidated.Count; i++)
                    {
                        if (i < targetConsolidated.Count) continue;
                        result.Add(sourceConsolidated[i]);
                        
                        return result;
                    }
                }
                else
                {
                    // For Roslyn-based closures we need to combine all the types from source and target types together.
                    if (sourceType.IsRoslynBasedStaticClosure())
                    {
                        var sourceConsolidated = sourceType.ConsolidatedTemplateParameters;
                        if (sourceConsolidated == null || sourceConsolidated.Count == 0) return null;
                        
                        var targetConsolidated = targetType.ConsolidatedTemplateParameters;
                        
                        if (targetConsolidated == null || targetConsolidated.Count == 0) return sourceConsolidated;
                        
                        if (sourceConsolidated.Count == targetConsolidated.Count)
                            return null; // no extra type parameters

                        result = new TypeNodeList(sourceConsolidated.Count + targetConsolidated.Count);

                        for (int i = 0; i < targetConsolidated.Count; i++)
                        {
                            result.Add(targetConsolidated[i]);
                        }

                        for (int i = 0; i < sourceConsolidated.Count; i++)
                        {
                            result.Add(sourceConsolidated[i]);
                        }

                        return result;
                    }

                    result = sourceType.ConsolidatedTemplateParameters;
                }
            }

            return result;
        }
Exemplo n.º 35
0
        /// <summary>
        /// There are 2 cases:
        /// 1) Task has no return value. In this case, we emit
        ///      void CheckMethod(Task t) {
        ///         var ae = t.Exception as AggregateException;
        ///         if (ae != null) { ae.Handle(this.CheckException); throw ae; }
        ///      }
        ///      bool CheckException(Exception e) {
        ///          .. check exceptional post
        ///      }
        /// 2) Task(T) returns a T value
        ///      T CheckMethod(Task t) {
        ///         try {
        ///            var r = t.Result;
        ///            .. check ensures on r ..
        ///            return r;
        ///         }
        ///         catch (AggregateException ae) {
        ///            ae.Handle(this.CheckException); 
        ///            throw;
        ///         }
        ///      }
        ///      bool CheckException(Exception e) {
        ///          .. check exceptional post
        ///      }
        /// </summary>
        public EmitAsyncClosure(Method from, Rewriter parent)
        {
            this.fromMethod = from;
            this.parent = parent;
            this.checkMethodId = Identifier.For("CheckPost");
            this.checkExceptionMethodId = Identifier.For("CheckException");
            this.declaringType = from.DeclaringType;
            var closureName = HelperMethods.NextUnusedMemberName(declaringType, "<" + from.Name.Name + ">AsyncContractClosure");
            this.closureClass = new Class(declaringType.DeclaringModule, declaringType, null, TypeFlags.NestedPrivate, null, Identifier.For(closureName), SystemTypes.Object, null, null);
            declaringType.Members.Add(this.closureClass);
            RewriteHelper.TryAddCompilerGeneratedAttribute(this.closureClass);

            this.dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType);

            var taskType = from.ReturnType;
            var taskArgs = taskType.TemplateArguments == null ? 0 : taskType.TemplateArguments.Count;

            this.AggregateExceptionType = new Cache<TypeNode>(() =>
                HelperMethods.FindType(parent.assemblyBeingRewritten, StandardIds.System, Identifier.For("AggregateException")));
            this.Func2Type = new Cache<TypeNode>(() =>
                HelperMethods.FindType(SystemTypes.SystemAssembly, StandardIds.System, Identifier.For("Func`2")));

            if (from.IsGeneric)
            {
                this.closureClass.TemplateParameters = new TypeNodeList();
                var parentCount = this.declaringType.ConsolidatedTemplateParameters == null ? 0 : this.declaringType.ConsolidatedTemplateParameters.Count;
                for (int i = 0; i < from.TemplateParameters.Count; i++)
                {
                    var tp = HelperMethods.NewEqualTypeParameter(dup, (ITypeParameter)from.TemplateParameters[i], this.closureClass, parentCount + i);

                    this.closureClass.TemplateParameters.Add(tp);
                }
                this.closureClass.IsGeneric = true;
                this.closureClass.EnsureMangledName();
                this.forwarder = new Specializer(this.declaringType.DeclaringModule, from.TemplateParameters, this.closureClass.TemplateParameters);
                this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters);

                taskType = this.forwarder.VisitTypeReference(taskType);
            }
            else
            {
                this.closureClassInstance = this.closureClass;
            }

            var taskTemplate = HelperMethods.Unspecialize(taskType);
            var continueWithCandidates = taskTemplate.GetMembersNamed(Identifier.For("ContinueWith"));
            Method continueWithMethod = null;
            for (int i = 0; i < continueWithCandidates.Count; i++)
            {
                var cand = continueWithCandidates[i] as Method;
                if (cand == null) continue;
                if (taskArgs == 0)
                {
                    if (cand.IsGeneric) continue;
                    if (cand.ParameterCount != 1) continue;

                    var p = cand.Parameters[0];
                    var ptype = p.Type;
                    var ptypeTemplate = ptype;

                    while (ptypeTemplate.Template != null)
                    {
                        ptypeTemplate = ptypeTemplate.Template;
                    }

                    if (ptypeTemplate.Name.Name != "Action`1") continue;

                    continueWithMethod = cand;
                    break;
                }
                else
                {
                    if (!cand.IsGeneric) continue;
                    if (cand.TemplateParameters.Count != 1) continue;
                    if (cand.ParameterCount != 1) continue;
                    var p = cand.Parameters[0];
                    var ptype = p.Type;
                    var ptypeTemplate = ptype;
                    while (ptypeTemplate.Template != null)
                    {
                        ptypeTemplate = ptypeTemplate.Template;
                    }
                    if (ptypeTemplate.Name.Name != "Func`2") continue;

                    // now create instance, first of task
                    var taskInstance = taskTemplate.GetTemplateInstance(this.closureClass.DeclaringModule, taskType.TemplateArguments[0]);
                    var candMethod = taskInstance.GetMembersNamed(Identifier.For("ContinueWith"))[i] as Method;
                    continueWithMethod = candMethod.GetTemplateInstance(null, taskType.TemplateArguments[0]);
                    break;
                }
            }

            if (continueWithMethod != null)
            {
                this.continuewithMethod = continueWithMethod;
                EmitCheckMethod(taskType, taskArgs == 1);

                var ctor = new InstanceInitializer(this.closureClass, null, null, null);
                this.constructor = ctor;
                ctor.CallingConvention = CallingConventionFlags.HasThis;
                ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig;
                ctor.Body = new Block(new StatementList(
                    new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, SystemTypes.Object.GetConstructor()), new ExpressionList())),
                    new Return()
                    ));
                this.closureClass.Members.Add(ctor);

            }

            // now that we added the ctor and the check method, let's instantiate the closure class if necessary
            if (this.closureClassInstance == null)
            {
                var consArgs = new TypeNodeList();
                var args = new TypeNodeList();
                var parentCount = this.closureClass.DeclaringType.ConsolidatedTemplateParameters == null ? 0 : this.closureClass.DeclaringType.ConsolidatedTemplateParameters.Count;
                
                for (int i = 0; i < parentCount; i++)
                {
                    consArgs.Add(this.closureClass.DeclaringType.ConsolidatedTemplateParameters[i]);
                }
                
                var methodCount = from.TemplateParameters == null ? 0: from.TemplateParameters.Count;
                for (int i = 0; i < methodCount; i++)
                {
                    consArgs.Add(from.TemplateParameters[i]);
                    args.Add(from.TemplateParameters[i]);
                }

                this.closureClassInstance = (Class)this.closureClass.GetConsolidatedTemplateInstance(this.parent.assemblyBeingRewritten, closureClass.DeclaringType, closureClass.DeclaringType, args, consArgs);
            }

            // create closure initializer for context method
            this.ClosureLocal = new Local(this.ClosureClass);
            this.ClosureInitializer = new Block(new StatementList());

            this.ClosureInitializer.Statements.Add(new AssignmentStatement(this.ClosureLocal, new Construct(new MemberBinding(null, this.Ctor), new ExpressionList())));
        }
Exemplo n.º 36
0
 public virtual Differences VisitTypeNodeList(TypeNodeList list1, TypeNodeList list2,
   out TypeNodeList changes, out TypeNodeList deletions, out TypeNodeList insertions){
   changes = list1 == null ? null : list1.Clone();
   deletions = list1 == null ? null : list1.Clone();
   insertions = list1 == null ? new TypeNodeList() : list1.Clone();
   //^ assert insertions != null;
   Differences differences = new Differences();
   //Compare definitions that have matching key attributes
   TrivialHashtable matchingPosFor = new TrivialHashtable();
   TrivialHashtable matchedNodes = new TrivialHashtable();
   for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){
     //^ assert list2 != null;
     TypeNode nd2 = list2[j];
     if (nd2 == null || nd2.Name == null) continue;
     string fullName = nd2.FullName;
     if (fullName == null) continue;
     matchingPosFor[Identifier.For(fullName).UniqueIdKey] = j;
     insertions.Add(null);
   }
   for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){
     //^ assert list1 != null && changes != null && deletions != null;
     TypeNode nd1 = list1[i];
     if (nd1 == null || nd1.Name == null) continue;
     string fullName = nd1.FullName;
     if (fullName == null) continue;
     object pos = matchingPosFor[Identifier.For(fullName).UniqueIdKey];
     if (!(pos is int)) continue;
     //^ assert pos != null;
     //^ assume list2 != null; //since there was entry int matchingPosFor
     int j = (int)pos;
     TypeNode nd2 = list2[j];
     //^ assume nd2 != null;
     //nd1 and nd2 have the same key attributes and are therefore treated as the same entity
     matchedNodes[nd1.UniqueKey] = nd1;
     matchedNodes[nd2.UniqueKey] = nd2;
     //nd1 and nd2 may still be different, though, so find out how different
     Differences diff = this.VisitTypeNode(nd1, nd2);
     if (diff == null){Debug.Assert(false); continue;}
     if (diff.NumberOfDifferences != 0){
       changes[i] = diff.Changes as TypeNode;
       deletions[i] = diff.Deletions as TypeNode;
       insertions[i] = diff.Insertions as TypeNode;
       insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation
       //Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]);
       differences.NumberOfDifferences += diff.NumberOfDifferences;
       differences.NumberOfSimilarities += diff.NumberOfSimilarities;
       if (nd1.DeclaringModule == this.OriginalModule || 
         (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){
         if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList();
         this.MembersThatHaveChanged.Add(nd1);
       }
       continue;
     }
     changes[i] = null;
     deletions[i] = null;
     insertions[i] = null;
     insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation
   }
   //Find deletions
   for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){
     //^ assert list1 != null && changes != null && deletions != null;
     TypeNode nd1 = list1[i]; 
     if (nd1 == null) continue;
     if (matchedNodes[nd1.UniqueKey] != null) continue;
     changes[i] = null;
     deletions[i] = nd1;
     insertions[i] = null;
     differences.NumberOfDifferences += 1;
     if (nd1.DeclaringModule == this.OriginalModule || 
       (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){
       if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList();
       this.MembersThatHaveChanged.Add(nd1);
     }
   }
   //Find insertions
   for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){
     //^ assert list2 != null;
     TypeNode nd2 = list2[j]; 
     if (nd2 == null) continue;
     if (matchedNodes[nd2.UniqueKey] != null) continue;
     insertions[n+j] = nd2;  //Records nd2 as an insertion into list1, along with its position in list2
     differences.NumberOfDifferences += 1; //REVIEW: put the size of the tree here?
   }
   if (differences.NumberOfDifferences == 0){
     changes = null;
     deletions = null;
     insertions = null;
   }
   return differences;
 }
Exemplo n.º 37
0
    /// <summary>
    /// properly instantiate wrapper according to original instance (including declaring type and method instance)
    /// </summary>
    private Method InstantiateWrapperMethod(TypeNode virtcallConstraint, Method wrapperMethod, Method originalInstanceMethod)
    {
      // if CCI does it for us, great. Otherwise, we have to fake it:
      var instWrapperType = wrapperMethod.DeclaringType;
      if (instWrapperType.TemplateParameters != null && instWrapperType.TemplateParameters.Count > 0) {
        instWrapperType = instWrapperType.GetGenericTemplateInstance(this.assemblyBeingRewritten, originalInstanceMethod.DeclaringType.ConsolidatedTemplateArguments);
      }


      Method instMethod = GetMethodInstanceReference(wrapperMethod, instWrapperType);
      // instantiate method if generic
      if (instMethod.TemplateParameters != null && instMethod.TemplateParameters.Count > 0) {
        if (virtcallConstraint != null) {
          TypeNodeList args = new TypeNodeList();
          var templateArgCount = (originalInstanceMethod.TemplateArguments == null) ? 0 : originalInstanceMethod.TemplateArguments.Count;
          for (int i = 0; i < templateArgCount; i++) {
            args.Add(originalInstanceMethod.TemplateArguments[i]);
          }
          args.Add(virtcallConstraint);
          instMethod = instMethod.GetTemplateInstance(instWrapperType, args);
        }
        else {
          instMethod = instMethod.GetTemplateInstance(instWrapperType, originalInstanceMethod.TemplateArguments);
        }
      }
      return instMethod;
    }
Exemplo n.º 38
0
        public override TypeNode VisitTypeReference(TypeNode type)
        { //TODO: break up this method
            if (type == null) return null;
            TypeNodeList pars = this.pars;
            TypeNodeList args = this.args;
            switch (type.NodeType)
            {
                case NodeType.ArrayType:
                    ArrayType arrType = (ArrayType)type;
                    TypeNode elemType = this.VisitTypeReference(arrType.ElementType);
                    if (elemType == arrType.ElementType || elemType == null) return arrType;
                    if (arrType.IsSzArray()) return elemType.GetArrayType(1);
                    return elemType.GetArrayType(arrType.Rank, arrType.Sizes, arrType.LowerBounds);

                case NodeType.DelegateNode:
                    {
                        FunctionType ftype = type as FunctionType;
                        if (ftype == null) goto default;
                        TypeNode referringType = ftype.DeclaringType == null ? this.CurrentType : this.VisitTypeReference(ftype.DeclaringType);
                        return FunctionType.For(this.VisitTypeReference(ftype.ReturnType), this.VisitParameterList(ftype.Parameters), referringType);
                    }

                case NodeType.Pointer:
                    Pointer pType = (Pointer)type;
                    elemType = this.VisitTypeReference(pType.ElementType);
                    if (elemType == pType.ElementType || elemType == null) return pType;
                    return elemType.GetPointerType();
                case NodeType.Reference:
                    Reference rType = (Reference)type;
                    elemType = this.VisitTypeReference(rType.ElementType);
                    if (elemType == rType.ElementType || elemType == null) return rType;
                    return elemType.GetReferenceType();

                case NodeType.ArrayTypeExpression:
                    ArrayTypeExpression aExpr = (ArrayTypeExpression)type;
                    aExpr.ElementType = this.VisitTypeReference(aExpr.ElementType);
                    return aExpr;
                case NodeType.BoxedTypeExpression:
                    BoxedTypeExpression bExpr = (BoxedTypeExpression)type;
                    bExpr.ElementType = this.VisitTypeReference(bExpr.ElementType);
                    return bExpr;
                case NodeType.ClassExpression:
                    {
                        ClassExpression cExpr = (ClassExpression)type;
                        cExpr.Expression = this.VisitTypeExpression(cExpr.Expression);
                        Literal lit = cExpr.Expression as Literal; //Could happen if the expression is a template parameter
                        if (lit != null) return lit.Value as TypeNode;
                        cExpr.TemplateArguments = this.VisitTypeReferenceList(cExpr.TemplateArguments);
                        return cExpr;
                    }

                case NodeType.ClassParameter:
                case NodeType.TypeParameter:
                    int key = type.UniqueKey;
                    for (int i = 0, n = pars == null ? 0 : pars.Count, m = args == null ? 0 : args.Count; i < n && i < m; i++)
                    {
                        //^ assert pars != null && args != null;
                        TypeNode tp = pars[i];
                        if (tp == null) continue;
                        if (tp.UniqueKey == key) return args[i];
                        if (tp.Name.UniqueIdKey == type.Name.UniqueIdKey && (tp is ClassParameter && type is TypeParameter))
                        {
                            //This shouldn't really happen, but in practice it does. Hack past it.
                            return args[i];
                        }
                    }
                    return type;

                case NodeType.FlexArrayTypeExpression:
                    FlexArrayTypeExpression flExpr = (FlexArrayTypeExpression)type;
                    flExpr.ElementType = this.VisitTypeReference(flExpr.ElementType);
                    return flExpr;
                case NodeType.FunctionTypeExpression:
                    FunctionTypeExpression ftExpr = (FunctionTypeExpression)type;
                    ftExpr.Parameters = this.VisitParameterList(ftExpr.Parameters);
                    ftExpr.ReturnType = this.VisitTypeReference(ftExpr.ReturnType);
                    return ftExpr;
                case NodeType.InvariantTypeExpression:
                    InvariantTypeExpression invExpr = (InvariantTypeExpression)type;
                    invExpr.ElementType = this.VisitTypeReference(invExpr.ElementType);
                    return invExpr;

                case NodeType.InterfaceExpression:
                    InterfaceExpression iExpr = (InterfaceExpression)type;
                    if (iExpr.Expression == null) goto default;
                    iExpr.Expression = this.VisitTypeExpression(iExpr.Expression);
                    iExpr.TemplateArguments = this.VisitTypeReferenceList(iExpr.TemplateArguments);
                    return iExpr;

                case NodeType.NonEmptyStreamTypeExpression:
                    NonEmptyStreamTypeExpression neExpr = (NonEmptyStreamTypeExpression)type;
                    neExpr.ElementType = this.VisitTypeReference(neExpr.ElementType);
                    return neExpr;
                case NodeType.NonNullTypeExpression:
                    NonNullTypeExpression nnExpr = (NonNullTypeExpression)type;
                    nnExpr.ElementType = this.VisitTypeReference(nnExpr.ElementType);
                    return nnExpr;
                case NodeType.NonNullableTypeExpression:
                    NonNullableTypeExpression nbExpr = (NonNullableTypeExpression)type;
                    nbExpr.ElementType = this.VisitTypeReference(nbExpr.ElementType);
                    return nbExpr;
                case NodeType.NullableTypeExpression:
                    NullableTypeExpression nuExpr = (NullableTypeExpression)type;
                    nuExpr.ElementType = this.VisitTypeReference(nuExpr.ElementType);
                    return nuExpr;

                case NodeType.OptionalModifier:
                    {
                        TypeModifier modType = (TypeModifier)type;
                        TypeNode modifiedType = this.VisitTypeReference(modType.ModifiedType);
                        TypeNode modifierType = this.VisitTypeReference(modType.Modifier);
                        if (modifiedType == null || modifierType == null) { return type; }

                        return OptionalModifier.For(modifierType, modifiedType);
                    }
                case NodeType.RequiredModifier:
                    {
                        TypeModifier modType = (TypeModifier)type;
                        TypeNode modifiedType = this.VisitTypeReference(modType.ModifiedType);
                        TypeNode modifierType = this.VisitTypeReference(modType.Modifier);
                        if (modifiedType == null || modifierType == null) { Debug.Fail(""); return type; }
                        return RequiredModifier.For(modifierType, modifiedType);
                    }

                case NodeType.OptionalModifierTypeExpression:
                    OptionalModifierTypeExpression optmodType = (OptionalModifierTypeExpression)type;
                    optmodType.ModifiedType = this.VisitTypeReference(optmodType.ModifiedType);
                    optmodType.Modifier = this.VisitTypeReference(optmodType.Modifier);
                    return optmodType;
                case NodeType.RequiredModifierTypeExpression:
                    RequiredModifierTypeExpression reqmodType = (RequiredModifierTypeExpression)type;
                    reqmodType.ModifiedType = this.VisitTypeReference(reqmodType.ModifiedType);
                    reqmodType.Modifier = this.VisitTypeReference(reqmodType.Modifier);
                    return reqmodType;
                case NodeType.PointerTypeExpression:
                    PointerTypeExpression pExpr = (PointerTypeExpression)type;
                    pExpr.ElementType = this.VisitTypeReference(pExpr.ElementType);
                    return pExpr;
                case NodeType.ReferenceTypeExpression:
                    ReferenceTypeExpression rExpr = (ReferenceTypeExpression)type;
                    rExpr.ElementType = this.VisitTypeReference(rExpr.ElementType);
                    return rExpr;
                case NodeType.StreamTypeExpression:
                    StreamTypeExpression sExpr = (StreamTypeExpression)type;
                    sExpr.ElementType = this.VisitTypeReference(sExpr.ElementType);
                    return sExpr;
                case NodeType.TupleTypeExpression:
                    TupleTypeExpression tuExpr = (TupleTypeExpression)type;
                    tuExpr.Domains = this.VisitFieldList(tuExpr.Domains);
                    return tuExpr;
                case NodeType.TypeExpression:
                    {
                        TypeExpression tExpr = (TypeExpression)type;
                        tExpr.Expression = this.VisitTypeExpression(tExpr.Expression);
                        if (tExpr.Expression is Literal) return type;
                        tExpr.TemplateArguments = this.VisitTypeReferenceList(tExpr.TemplateArguments);
                        return tExpr;
                    }
                case NodeType.TypeIntersectionExpression:
                    TypeIntersectionExpression tiExpr = (TypeIntersectionExpression)type;
                    tiExpr.Types = this.VisitTypeReferenceList(tiExpr.Types);
                    return tiExpr;
                case NodeType.TypeUnionExpression:
                    TypeUnionExpression tyuExpr = (TypeUnionExpression)type;
                    tyuExpr.Types = this.VisitTypeReferenceList(tyuExpr.Types);
                    return tyuExpr;

                default:
                    TypeNode declaringType = this.VisitTypeReference(type.DeclaringType);
                    if (declaringType != null)
                    {
                        Identifier tname = type.Name;
                        if (type.Template != null && type.IsGeneric) tname = type.Template.Name;
                        TypeNode nt = declaringType.GetNestedType(tname);
                        if (nt != null)
                        {
                            TypeNodeList arguments = type.TemplateArguments;
                            type = nt;
                            if (TargetPlatform.UseGenerics)
                            {
                                if (arguments != null && arguments.Count > 0 && nt.ConsolidatedTemplateParameters != null && nt.ConsolidatedTemplateParameters.Count > 0)
                                    type = nt.GetTemplateInstance(this.TargetModule, this.CurrentType, declaringType, arguments);
                            }
                        }
                    }

                    if(type.Template != null && (type.ConsolidatedTemplateParameters == null || type.ConsolidatedTemplateParameters.Count == 0))
                    {
                        if(!type.IsNotFullySpecialized && (!type.IsNormalized ||
                         (this.CurrentType != null && type.DeclaringModule == this.CurrentType.DeclaringModule)))
                        {
                            return type;
                        }

                        // Type is a template instance, but some of its arguments were themselves parameters.
                        // See if any of these parameters are to be specialized by this specializer.
                        bool mustSpecializeFurther = false;
                        TypeNodeList targs = type.TemplateArguments;
                        int numArgs = targs == null ? 0 : targs.Count;

                        if(targs != null)
                        {
                            targs = new TypeNodeList(targs);

                            for(int i = 0; i < numArgs; i++)
                            {
                                TypeNode targ = targs[i];
                                ITypeParameter tparg = targ as ITypeParameter;

                                if(tparg != null)
                                {
                                    for(int j = 0, np = pars == null ? 0 : pars.Count, m = args == null ? 0 : args.Count; j < np && j < m; j++)
                                    {
                                        //^ assert pars != null && args != null;
                                        if(TargetPlatform.UseGenerics)
                                        {
                                            ITypeParameter par = pars[j] as ITypeParameter;

                                            if(par == null)
                                                continue;

                                            if(tparg == par || (tparg.ParameterListIndex == par.ParameterListIndex && tparg.DeclaringMember == par.DeclaringMember))
                                            {
                                                targ = this.args[j];
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            if(targ == pars[j])
                                            {
                                                targ = this.args[j];
                                                break;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    if(targ != type)
                                        targ = this.VisitTypeReference(targ);

                                    if(targ == type)
                                        continue;
                                }

                                mustSpecializeFurther |= targs[i] != targ;
                                targs[i] = targ;
                            }
                        }

                        if(targs == null || !mustSpecializeFurther)
                            return type;

                        return type.Template.GetTemplateInstance(this.TargetModule, this.CurrentType, declaringType, targs);
                    }

                    TypeNodeList tPars = type.TemplateParameters;
                    if (tPars == null || tPars.Count == 0) return type; //Not a parameterized type. No need to get an instance.
                    TypeNodeList tArgs = new TypeNodeList();
                    for (int i = 0, n = tPars.Count; i < n; i++)
                    {
                        TypeNode tPar = tPars[i];
                        tArgs.Add(tPar); //Leave parameter in place if there is no match
                        if (tPar == null || tPar.Name == null) continue;
                        int idKey = tPar.Name.UniqueIdKey;
                        for (int j = 0, m = pars == null ? 0 : pars.Count, k = args == null ? 0 : args.Count; j < m && j < k; j++)
                        {
                            //^ assert pars != null && args != null;
                            TypeNode par = pars[j];
                            if (par == null || par.Name == null) continue;
                            if (par.Name.UniqueIdKey == idKey)
                            {
                                tArgs[i] = args[j];
                                break;
                            }
                        }
                    }
                    return type.GetTemplateInstance(this.TargetModule, this.CurrentType, this.VisitTypeReference(type.DeclaringType), tArgs);
            }
        }
Exemplo n.º 39
0
    private static Specializer TypeParameterSpecialization(TypeNode genericType, TypeNode atInstanceType)
    {
      // F:
      Contract.Requires(genericType != null);
      Contract.Requires(atInstanceType != null);

      TypeNodeList formals = new TypeNodeList();
      TypeNodeList actuals = new TypeNodeList();

      var wrapperTypeParams = genericType.ConsolidatedTemplateParameters;
      var instanceTypeParams = atInstanceType.ConsolidatedTemplateArguments;
      if (wrapperTypeParams != null && wrapperTypeParams.Count > 0) {
        for (int i = 0; i < wrapperTypeParams.Count; i++) {
          formals.Add(wrapperTypeParams[i]);
          actuals.Add(instanceTypeParams[i]);
        }
      }

#if false // method specs
      if (includeMethodSpec) {
        var wrapperMethodParams = wrapperMethod.TemplateParameters;
        var instanceMethodParams = originalInstanceMethod.TemplateArguments;
        if (wrapperMethodParams != null && wrapperMethodParams.Count > 0) {
          for (int i = 0; i < wrapperMethodParams.Count; i++) {
            formals.Add(wrapperMethodParams[i]);
            actuals.Add(instanceMethodParams[i]);
          }
        }
      }
#endif 
      if (formals.Count > 0) {
        return new Specializer(genericType.DeclaringModule, formals, actuals);
      }
      return null;
    }