Exemplo n.º 1
0
        static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt)
        {
            if (ept.Definition.Initializer == null &&
                ept.Definition.Type == null)
            {
                ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!");
                return(null);
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept);

            // Get actual overloads
            AbstractType deducedType = null;
            var          def         = ept.Definition;

            deducedType = new MemberSymbol(def, def.Type != null ?
                                           TypeDeclarationResolver.ResolveSingle(def.Type, ctxt) :
                                           ExpressionTypeEvaluation.EvaluateType(def.Initializer, ctxt), null, ept.DeducedTypes); //ept; //ExpressionTypeEvaluation.EvaluateType (ept.Definition.Initializer, ctxt);

            deducedType.Tag = ept.Tag;                                                                                            // Currently requried for proper UFCS resolution - sustain ept's Tag

            // Undo context-related changes
            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept);

            return(deducedType);
        }
Exemplo n.º 2
0
        void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null)
        {
            if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null)
            {
                var pop = ctxt.ScopedBlock != dm;
                if (pop)
                {
                    ctxt.PushNewScope(dm);
                }

                var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters [0].Type, ctxt);
                if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt))
                {
                    var res = alreadyResolvedMethod ?? new MemberSymbol(dm, null, sr);
                    res.Tag = new UfcsTag {
                        firstArgument = firstArgument
                    };
                    matches.Add(res);
                }

                if (pop)
                {
                    ctxt.Pop();
                }
            }
        }
Exemplo n.º 3
0
 void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null)
 {
     if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null)
     {
         var loc = dm.Body != null ? dm.Body.Location : dm.Location;
         using (alreadyResolvedMethod != null ? ctxt.Push(alreadyResolvedMethod, loc) : ctxt.Push(dm, loc))
         {
             var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters[0].Type, ctxt);
             if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt))
             {
                 var res = alreadyResolvedMethod ?? TypeDeclarationResolver.HandleNodeMatch(dm, ctxt, typeBase: sr);
                 res.Tag = new UfcsTag {
                     firstArgument = firstArgument
                 };
                 matches.Add(res);
             }
         }
     }
 }
Exemplo n.º 4
0
        public static AbstractType ResolveType(IEditorData editor, ResolutionContext ctxt = null)
        {
            var o = GetScopedCodeObject(editor);

            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor, false);
            }

            AbstractType ret = null;

            CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () =>
            {
                ctxt.Push(editor);

                var optionBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly;

                if (o is IExpression)
                {
                    ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false);
                }
                else if (o is ITypeDeclaration)
                {
                    ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt);
                }
                else if (o is INode)
                {
                    ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt);
                }

                ctxt.CurrentContext.ContextDependentOptions = optionBackup;
            });

            return(ret);
        }
Exemplo n.º 5
0
        public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
        {
            keyVal           = null;
            fixedArrayLength = -1;
            AbstractType keyType = null;

            if (ad.KeyExpression != null)
            {
                //TODO: Template instance expressions?
                var id_x = ad.KeyExpression as IdentifierExpression;
                if (id_x != null && id_x.IsIdentifier)
                {
                    var id = new IdentifierDeclaration((string)id_x.Value)
                    {
                        Location    = id_x.Location,
                        EndLocation = id_x.EndLocation
                    };

                    keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

                    if (keyType != null)
                    {
                        var tt = DResolver.StripAliasSymbol(keyType) as MemberSymbol;

                        if (tt == null ||
                            !(tt.Definition is DVariable) ||
                            ((DVariable)tt.Definition).Initializer == null)
                        {
                            return(keyType);
                        }
                    }
                }

                try
                {
                    keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

                    if (keyVal != null)
                    {
                        // Take the value's type as array key type
                        keyType = keyVal.RepresentedType;

                        // It should be mostly a number only that points out how large the final array should be
                        var pv = Evaluation.GetVariableContents(keyVal, new StandardValueProvider(ctxt)) as PrimitiveValue;
                        if (pv != null)
                        {
                            fixedArrayLength = System.Convert.ToInt32(pv.Value);

                            if (fixedArrayLength < 0)
                            {
                                ctxt.LogError(ad, "Invalid array size: Length value must be greater than 0");
                            }
                        }
                        //TODO Is there any other type of value allowed?
                    }
                }
                catch { }
            }
            else
            {
                var t = Resolve(ad.KeyType, ctxt);
                ctxt.CheckForSingleResult(t, ad.KeyType);

                if (t != null && t.Length != 0)
                {
                    return(t[0]);
                }
            }

            return(keyType);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static TemplateIntermediateType ResolveClassOrInterface(DClassLike dc, ResolutionContext ctxt, ISyntaxRegion instanceDeclaration, bool ResolveFirstBaseIdOnly = false, IEnumerable <TemplateParameterSymbol> extraDeducedTemplateParams = null)
        {
            if (parsedClassInstanceDecls == null)
            {
                parsedClassInstanceDecls = new List <ISyntaxRegion> ();
            }

            switch (dc.ClassType)
            {
            case DTokens.Class:
            case DTokens.Interface:
                break;

            default:
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(null);
            }

            bool isClass = dc.ClassType == DTokens.Class;

            if (bcStack > 6 || (instanceDeclaration != null && parsedClassInstanceDecls.Contains(instanceDeclaration)))
            {
                return(isClass ? new ClassType(dc, instanceDeclaration, null) as TemplateIntermediateType : new InterfaceType(dc, instanceDeclaration));
            }

            if (instanceDeclaration != null)
            {
                parsedClassInstanceDecls.Add(instanceDeclaration);
            }
            bcStack++;

            var deducedTypes = new DeducedTypeDictionary(dc);
            var tix          = instanceDeclaration as TemplateInstanceExpression;

            if (tix != null && (ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0)
            {
                // Pop a context frame as we still need to resolve the template instance expression args in the place where the expression occurs, not the instantiated class' location
                var backup = ctxt.Pop();
                if (ctxt.CurrentContext == null)
                {
                    ctxt.Push(backup);
                }

                var givenTemplateArguments = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);

                if (ctxt.CurrentContext != backup)
                {
                    foreach (var kv in ctxt.CurrentContext.DeducedTemplateParameters)
                    {
                        backup.DeducedTemplateParameters [kv.Key] = kv.Value;
                        deducedTypes [kv.Key] = kv.Value;
                    }
                    ctxt.Push(backup);
                }

                if (!TemplateInstanceHandler.DeduceParams(givenTemplateArguments, false, ctxt, null, dc, deducedTypes))
                {
                    parsedClassInstanceDecls.Remove(instanceDeclaration);
                    bcStack--;
                    return(null);
                }
            }

            if (extraDeducedTemplateParams != null)
            {
                foreach (var tps in extraDeducedTemplateParams)
                {
                    deducedTypes[tps.Parameter] = tps;
                }
            }


            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                parsedClassInstanceDecls.Remove(instanceDeclaration);
                bcStack--;

                // The Object class has no further base class;
                // Normal class instances have the object as base class;
                // Interfaces must not have any default base class/interface
                return(isClass ? new ClassType(dc, instanceDeclaration, dc.NameHash != ObjectNameHash ? ctxt.ParseCache.ObjectClassResult : null, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) :
                       new InterfaceType(dc, instanceDeclaration, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) as TemplateIntermediateType);
            }


            #region Base class & interface resolution
            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();

            var back = ctxt.ScopedBlock;
            using (ctxt.Push(dc.Parent))
            {
                var pop = back != ctxt.ScopedBlock;

                foreach (var kv in deducedTypes)
                {
                    ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
                }

                try
                {
                    for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
                    {
                        var type = dc.BaseClasses[i];

                        // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                        if (type is IdentifierDeclaration &&
                            (type as IdentifierDeclaration).IdHash == ObjectNameHash)
                        {
                            if (baseClass != null)
                            {
                                ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                                continue;
                            }
                            else if (i != 0)
                            {
                                ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                                continue;
                            }

                            baseClass = ctxt.ParseCache.ObjectClassResult;
                            continue;
                        }

                        if (type == null || (type is IdentifierDeclaration && (type as IdentifierDeclaration).IdHash == dc.NameHash) || dc.NodeRoot == dc)
                        {
                            ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                            continue;
                        }

                        var r = DResolver.StripMemberSymbols(TypeDeclarationResolver.ResolveSingle(type, ctxt));

                        if (r is ClassType || r is TemplateType)
                        {
                            if (!isClass)
                            {
                                ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                            }
                            else if (i == 0)
                            {
                                baseClass = r as TemplateIntermediateType;
                            }
                            else
                            {
                                ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ? "class" : "template") + " name must preceed base interfaces"));
                            }
                        }
                        else if (r is InterfaceType)
                        {
                            interfaces.Add(r as InterfaceType);

                            if (isClass && dc.NameHash != ObjectNameHash && baseClass == null)
                            {
                                baseClass = ctxt.ParseCache.ObjectClassResult;
                            }
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                            continue;
                        }
                    }
                }
                finally
                {
                    bcStack--;
                    parsedClassInstanceDecls.Remove(instanceDeclaration);
                }

                if (!pop)
                {
                    foreach (var kv in deducedTypes)                     // May be backup old tps?
                    {
                        ctxt.CurrentContext.DeducedTemplateParameters.Remove(kv.Key);
                    }
                }
            }
            #endregion

            if (isClass)
            {
                return(new ClassType(dc, instanceDeclaration, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
            }

            return(new InterfaceType(dc, instanceDeclaration, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
        }
Exemplo n.º 7
0
        public static AbstractType ResolveTypeLoosely(IEditorData editor, out NodeResolutionAttempt resolutionAttempt, ResolutionContext ctxt = null)
        {
            var o = GetScopedCodeObject(editor);

            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor, false);
            }

            AbstractType          ret        = null;
            NodeResolutionAttempt resAttempt = NodeResolutionAttempt.Normal;

            CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () =>
            {
                ctxt.Push(editor);

                var optionBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly | ResolutionOptions.DontResolveAliases;

                if (o is IExpression)
                {
                    ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false);
                }
                else if (o is ITypeDeclaration)
                {
                    ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt);
                }
                else if (o is INode)
                {
                    ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt, null, o);
                }
                else
                {
                    ret = null;
                }

                if (ret == null)
                {
                    resAttempt = NodeResolutionAttempt.NoParameterOrTemplateDeduction;

                    if (o is PostfixExpression_MethodCall)
                    {
                        o = (o as PostfixExpression_MethodCall).PostfixForeExpression;
                    }

                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.NoTemplateParameterDeduction | ResolutionOptions.DontResolveAliases;

                    if (o is IdentifierExpression)
                    {
                        ret = AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(o as IdentifierExpression, ctxt, deduceParameters: false), o);
                    }
                    else if (o is ITypeDeclaration)
                    {
                        ret = TypeDeclarationResolver.ResolveSingle(o as ITypeDeclaration, ctxt);
                    }
                    else if (o is IExpression)
                    {
                        ret = ExpressionTypeEvaluation.EvaluateType(o as IExpression, ctxt, false);
                    }
                }

                if (ret == null)
                {
                    resAttempt    = NodeResolutionAttempt.RawSymbolLookup;
                    var overloads = TypeDeclarationResolver.HandleNodeMatches(LookupIdRawly(editor, o as ISyntaxRegion), ctxt, null, o);
                    ret           = AmbiguousType.Get(overloads, o);
                }

                ctxt.CurrentContext.ContextDependentOptions = optionBackup;
            });

            resolutionAttempt = resAttempt;

            if (ret != null)
            {
                ret.DeclarationOrExpressionBase = o;
            }

            return(ret);
        }
Exemplo n.º 8
0
        public static List <ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolutionContext ctxt)
        {
            // Resolve given argument expressions
            var templateArguments = new List <ISemantic>();

            if (tix != null && tix.Arguments != null)
            {
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.ResolveSingle(tde.Declaration, ctxt);

                        // Might be a simple symbol without any applied template arguments that is then passed to an template alias parameter
                        if (res == null && tde.Declaration is IdentifierDeclaration)
                        {
                            res = TypeDeclarationResolver.ResolveSingle(tde.Declaration as IdentifierDeclaration, ctxt, null, false);
                        }

                        var amb = res as AmbiguousType;
                        if (amb != null)
                        {
                            // Error
                            res = amb.Overloads[0];
                        }

                        var mr = res as MemberSymbol;
                        if (mr != null && mr.Definition is DVariable)
                        {
                            var dv = (DVariable)mr.Definition;

                            if (dv.IsAlias || dv.Initializer == null)
                            {
                                templateArguments.Add(mr);
                                continue;
                            }

                            ISemantic eval = null;

                            try
                            {
                                eval = new StandardValueProvider(ctxt)[dv];
                            }
                            catch (System.Exception ee)                            // Should be a non-const-expression error here only
                            {
                                ctxt.LogError(dv.Initializer, ee.Message);
                            }

                            templateArguments.Add(eval ?? (ISemantic)mr);
                        }
                        else
                        {
                            templateArguments.Add(res);
                        }
                    }
                    else
                    {
                        ISemantic v = Evaluation.EvaluateValue(arg, ctxt, true);
                        if (v is VariableValue)
                        {
                            var vv = v as VariableValue;
                            if (vv.Variable.IsConst && vv.Variable.Initializer != null)
                            {
                                v = Evaluation.EvaluateValue(vv, new StandardValueProvider(ctxt));
                            }
                        }

                        v = DResolver.StripValueTypeWrappers(v);
                        templateArguments.Add(v);
                    }
                }
            }

            return(templateArguments);
        }