Beispiel #1
0
        public void IsExpressionAlias()
        {
            var ctxt = ResolutionTests.CreateCtxt("A", @"module A;
static if(is(const(int)* U == const(U)*))
U var;

U derp;
");

            IExpression  x;
            AbstractType t;
            DSymbol      ds;

            x = DParser.ParseExpression("var");
            (x as IdentifierExpression).Location = new CodeLocation(2, 3);
            t  = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            ds = t as DSymbol;

            Assert.That(t, Is.TypeOf(typeof(MemberSymbol)));
            Assert.That(ds.Base, Is.TypeOf(typeof(TemplateParameterSymbol)));
            ds = ds.Base as DSymbol;
            Assert.That(ds.Base, Is.TypeOf(typeof(PrimitiveType)));
            Assert.That((ds.Base as PrimitiveType).Modifier, Is.EqualTo(0));

            ctxt.CurrentContext.DeducedTemplateParameters.Clear();

            var dv = ctxt.ParseCache[0]["A"]["derp"].First() as DVariable;

            t = TypeDeclarationResolver.HandleNodeMatch(dv, ctxt);
            Assert.That(t, Is.TypeOf(typeof(MemberSymbol)));
            Assert.That((t as MemberSymbol).Base, Is.Null);
        }
Beispiel #2
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);
        }
Beispiel #3
0
        public void BasicResolution()
        {
            var          ctxt = ResolutionTests.CreateCtxt("modA", @"module modA;
void writeln(T...)(T t) {}
int[] foo(string a) {}
int foo(int a) {}

string globStr;
int globI;
");
            IExpression  x;
            AbstractType t;

            x = DParser.ParseExpression("globStr.foo()");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(ArrayType)));

            x = DParser.ParseExpression("globI.foo()");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(PrimitiveType)));

            x = DParser.ParseExpression("globStr.writeln()");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(PrimitiveType)));
            Assert.That((t as PrimitiveType).TypeToken, Is.EqualTo(DTokens.Void));
        }
        protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar)
        {
            ed   = Editor;
            ctxt = ResolutionContext.Create(Editor, false);

            AbstractType t = null;

            CodeCompletion.DoTimeoutableCompletionTask(CompletionDataGenerator, ctxt, () =>
            {
                ctxt.Push(Editor);
                if (AccessExpression is IExpression)
                {
                    t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt);
                }
                else if (AccessExpression is ITypeDeclaration)
                {
                    t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt);
                }
            });

            if (t == null)             //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope
            {
                return;
            }

            t.Accept(this);
        }
Beispiel #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dm"></param>
        /// <param name="args"></param>
        /// <param name="baseValueProvider">Required for evaluating missing default parameters.</param>
        public static bool AssignCallArgumentsToIC <T>(MemberSymbol mr, T[] args, AbstractSymbolValueProvider baseValueProvider,
                                                       out Dictionary <DVariable, T> targetArgs, ResolutionContext ctxt = null) where T : class, ISemantic
        {
            var dm   = mr.Definition as DMethod;
            int para = 0;

            ISemantic firstArg;

            if (TypeResolution.UFCSResolver.IsUfcsResult(mr, out firstArg))
            {
                para++;
            }

            targetArgs = new Dictionary <DVariable, T>();
            var argsRemaining = args != null ? args.Length : 0;
            int argu          = 0;

            for (; para < dm.Parameters.Count; para++)
            {
                var par = dm.Parameters[para] as DVariable;

                if (par.Type is VarArgDecl && argsRemaining > 0)
                {
                    var va_args = new T[argsRemaining];
                    args.CopyTo(va_args, argu);
                    argsRemaining = 0;
                    //TODO: Assign a value tuple to par
                    if (++para < dm.Parameters.Count)
                    {
                        return(false);
                    }
                }

                if (argsRemaining > 0)
                {
                    targetArgs[par] = args[argu++];
                    argsRemaining--;
                }
                else if (par.Initializer != null)
                {
                    if (typeof(T) == typeof(AbstractType))
                    {
                        targetArgs[par] = ExpressionTypeEvaluation.EvaluateType(par.Initializer, ctxt) as T;
                    }
                    else if (typeof(T) == typeof(ISymbolValue))
                    {
                        targetArgs[par] = Evaluation.EvaluateValue(par.Initializer, baseValueProvider) as T;
                    }
                }
                else
                {
                    return(false);
                }
            }

            return(argsRemaining == 0);
        }
Beispiel #6
0
        public void IsExpressionAlias_InMethod()
        {
            var          ctxt = ResolutionTests.CreateCtxt("A", @"module A;
void main(){
pre;

static if(is(const(int)* U == const(U)*))
{
U var;
}

post;
}
");
            IExpression  x;
            AbstractType t;
            DSymbol      ds;

            var main = ctxt.ParseCache[0]["A"]["main"].First() as DMethod;

            ctxt.PushNewScope(main, main.Body.SubStatements.First());
            t = TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration("U")
            {
                Location = main.Body.SubStatements.First().Location
            }, ctxt);

            Assert.That(t, Is.Null);

            ctxt.Pop();
            ctxt.PushNewScope(main, main.Body.SubStatements.ElementAt(2));
            t = TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration("U")
            {
                Location = main.Body.SubStatements.ElementAt(2).Location
            }, ctxt);

            Assert.That(t, Is.Null);
            ctxt.Pop();

            x = DParser.ParseExpression("var");

            IStatement stmt;

            DResolver.SearchBlockAt(main, (x as IdentifierExpression).Location = new CodeLocation(3, 7), out stmt);

            ctxt.PushNewScope(main, stmt);
            t  = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            ds = t as DSymbol;

            Assert.That(t, Is.TypeOf(typeof(MemberSymbol)));
            Assert.That(ds.Base, Is.TypeOf(typeof(TemplateParameterSymbol)));
            ds = ds.Base as DSymbol;
            Assert.That(ds.Base, Is.TypeOf(typeof(PrimitiveType)));
            Assert.That((ds.Base as PrimitiveType).Modifier, Is.EqualTo(0));
        }
Beispiel #7
0
 public override void Visit(TemplateInstanceExpression id)
 {
     if (id.TemplateIdHash == searchHash)
     {
         ctxt.CurrentContext.Set(id.Location);
         if (TryAdd(ExpressionTypeEvaluation.EvaluateType(id, ctxt, false), id))
         {
             return;
         }
     }
 }
Beispiel #8
0
 public override void Visit(IdentifierExpression id)
 {
     if (id.IsIdentifier && id.ValueStringHash == searchHash)
     {
         ctxt.CurrentContext.Set(id.Location);
         if (TryAdd(ExpressionTypeEvaluation.EvaluateType(id, ctxt, false), id))
         {
             return;
         }
     }
 }
Beispiel #9
0
        public override void Visit(PostfixExpression_Access acc)
        {
            var resolvedSymbol = TryPopPFAStack();

            if ((acc.AccessExpression is IdentifierExpression &&
                 (acc.AccessExpression as IdentifierExpression).ValueStringHash != searchHash) ||
                (acc.AccessExpression is TemplateInstanceExpression &&
                 ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash))
            {
                acc.PostfixForeExpression.Accept(this);
                return;
            }
            else if (acc.AccessExpression is NewExpression)
            {
                var nex = acc.AccessExpression as NewExpression;

                if ((nex.Type is IdentifierDeclaration &&
                     ((IdentifierDeclaration)nex.Type).IdHash != searchHash) ||
                    (nex.Type is TemplateInstanceExpression &&
                     ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash))
                {
                    acc.PostfixForeExpression.Accept(this);
                    return;
                }
                // Are there other types to test for?
            }
            else
            {
                // Are there other types to test for?
            }

            var s = resolvedSymbol ?? ExpressionTypeEvaluation.EvaluateType(acc, ctxt) as DerivedDataType;

            if (s is DSymbol)
            {
                if (((DSymbol)s).Definition == symbol)
                {
                    l.Add(acc.AccessExpression);
                }
            }
            else if (s == null || !(s.Base is DSymbol))
            {
                acc.PostfixForeExpression.Accept(this);
                return;
            }

            // Scan down for other possible symbols
            if (s.Base is DSymbol)
            {
                postfixForeExprAccessStack.Push(s.Base as DSymbol);
            }
            acc.PostfixForeExpression.Accept(this);
        }
Beispiel #10
0
        public void EponymousTemplates()
        {
            var          ctxt = ResolutionTests.CreateDefCtxt(@"module B;
alias Tuple(T...) = T;
alias Tup = Tuple!(int, float, string);

enum isIntOrFloat(F) = is(F == int) || is(F == float);
");
            IExpression  x;
            ISymbolValue v;
            AbstractType t;

            x = DParser.ParseExpression("isIntOrFloat!(Tup[0])");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m));

            DToken tk;
            var    td = DParser.ParseBasicType("Tuple!(int, float, string)", out tk);

            //t = TypeDeclarationResolver.ResolveSingle (td, ctxt);
            //Assert.That (t, Is.TypeOf(typeof(MemberSymbol)));
            //Assert.That ((t as MemberSymbol).Base, Is.TypeOf(typeof(DTuple)));

            x = DParser.ParseExpression("Tup[0]");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(PrimitiveType)));

            x = DParser.ParseExpression("Tup[1]");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(PrimitiveType)));

            x = DParser.ParseExpression("Tup[2]");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(ArrayType)));


            x = DParser.ParseExpression("isIntOrFloat!int");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m));

            x = DParser.ParseExpression("isIntOrFloat!float");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m));

            x = DParser.ParseExpression("isIntOrFloat!string");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That((v as PrimitiveValue).Value, Is.EqualTo(0m));
        }
        bool HandleDecl(VectorDeclaration v, AbstractType r)
        {
            if (r.DeclarationOrExpressionBase is VectorDeclaration)
            {
                var v_res = ExpressionTypeEvaluation.EvaluateType(v.Id, ctxt);
                var r_res = ExpressionTypeEvaluation.EvaluateType(((VectorDeclaration)r.DeclarationOrExpressionBase).Id, ctxt);

                if (v_res == null || r_res == null)
                {
                    return(false);
                }
                else
                {
                    return(ResultComparer.IsImplicitlyConvertible(r_res, v_res));
                }
            }
            return(false);
        }
Beispiel #12
0
            public AbstractType Visit(DVariable variable)
            {
                AbstractType bt;

                if (CanResolveBase(variable))
                {
                    var bts = TypeDeclarationResolver.Resolve(variable.Type, ctxt);

                    if (bts != null && bts.Length != 0)
                    {
                        bt = bts[0];
                    }

                    // For auto variables, use the initializer to get its type
                    else if (variable.Initializer != null)
                    {
                        bt = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(variable.Initializer, ctxt));
                    }
                    else
                    {
                        bt = null;
                    }

                    // Check if inside an foreach statement header
                    if (bt == null && ctxt.ScopedStatement != null)
                    {
                        bt = GetForeachIteratorType(variable);
                    }

                    if (bt == null)
                    {
                        ctxt.CheckForSingleResult(bts, variable.Type as ISyntaxRegion ?? variable.Initializer);
                    }
                }
                else
                {
                    bt = null;
                }

                // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
                return(variable.IsAlias ?
                       new AliasedType(variable, bt, typeBase) :
                       new MemberSymbol(variable, bt, typeBase));
            }
Beispiel #13
0
        public override void Visit(TemplateInstanceExpression tix)
        {
            var resolvedSymbol = TryPopPFAStack();

            if (tix.TemplateIdHash == searchHash)
            {
                if (resolvedSymbol == null)
                {
                    resolvedSymbol = ExpressionTypeEvaluation.EvaluateType(tix, ctxt) as DSymbol;
                }

                if (resolvedSymbol != null && resolvedSymbol.Definition == symbol)
                {
                    l.Add(tix);
                    return;
                }
            }
            base.Visit(tix);
        }
Beispiel #14
0
        public override void Visit(IdentifierExpression id)
        {
            var resolvedSymbol = TryPopPFAStack();

            if (id.IsIdentifier && id.ValueStringHash == searchHash)
            {
                if (resolvedSymbol == null)
                {
                    resolvedSymbol = ExpressionTypeEvaluation.EvaluateType(id, ctxt) as DSymbol;
                }

                if (resolvedSymbol != null && resolvedSymbol.Definition == symbol)
                {
                    l.Add(id);
                    return;
                }
            }
            base.Visit(id);
        }
Beispiel #15
0
        public static AbstractType Resolve(TypeOfDeclaration typeOf, ResolutionContext ctxt)
        {
            // typeof(return)
            if (typeOf.Expression is TokenExpression && (typeOf.Expression as TokenExpression).Token == DTokens.Return)
            {
                var m = HandleNodeMatch(ctxt.ScopedBlock, ctxt, null, typeOf);
                if (m != null)
                {
                    return(m);
                }
            }
            // typeOf(myInt)  =>  int
            else if (typeOf.Expression != null)
            {
                var wantedTypes = ExpressionTypeEvaluation.EvaluateType(typeOf.Expression, ctxt);
                return(DResolver.StripMemberSymbols(wantedTypes));
            }

            return(null);
        }
Beispiel #16
0
        public void AliasedTypeTuple()
        {
            var          ctxt = ResolutionTests.CreateDefCtxt(@"module A;
template Tuple(T...) { alias Tuple = T; }
alias Tup = Tuple!(int, float, string);

template isIntOrFloat(T)
{
    static if (is(T == int) || is(T == float))
        enum isIntOrFloat = true;
    else
        enum isIntOrFloat = false;
}
");
            IExpression  x;
            ISymbolValue v;
            AbstractType t;

            x = DParser.ParseExpression("Tup[2]");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(ArrayType)));

            x = DParser.ParseExpression("isIntOrFloat!(Tup[2])");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That((v as PrimitiveValue).Value, Is.EqualTo(0m));

            x = DParser.ParseExpression("Tup[0]");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(PrimitiveType)));

            x = DParser.ParseExpression("Tup[1]");
            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(PrimitiveType)));

            x = DParser.ParseExpression("isIntOrFloat!(Tup[0])");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m));
        }
        protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar)
        {
            ed   = Editor;
            ctxt = ResolutionContext.Create(Editor.ParseCache, new ConditionalCompilationFlags(Editor), ScopedBlock, ScopedStatement);
            ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly;

            AbstractType t;

            if (AccessExpression is IExpression)
            {
                t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt);
            }
            else if (AccessExpression is ITypeDeclaration)
            {
                t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt);
            }
            else
            {
                return;
            }

            t = DResolver.StripAliasSymbol(t);

            if (t == null)             //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope
            {
                return;
            }

            isVariableInstance = false;

            if (t.DeclarationOrExpressionBase is ITypeDeclaration)
            {
                isVariableInstance |= (t.DeclarationOrExpressionBase as ITypeDeclaration).ExpressesVariableAccess;
            }

            t.Accept(this);
        }
Beispiel #18
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);
        }
Beispiel #19
0
            /// <summary>
            /// string[] s;
            ///
            /// foreach(i;s)
            /// {
            ///		// i is of type 'string'
            ///		writeln(i);
            /// }
            /// </summary>
            public AbstractType GetForeachIteratorType(DVariable i)
            {
                var r       = new List <AbstractType>();
                var curStmt = ctxt.ScopedStatement;

                bool init = true;

                // Walk up statement hierarchy -- note that foreach loops can be nested
                while (curStmt != null)
                {
                    if (init)
                    {
                        init = false;
                    }
                    else
                    {
                        curStmt = curStmt.Parent;
                    }

                    if (curStmt is ForeachStatement)
                    {
                        var fe = (ForeachStatement)curStmt;

                        if (fe.ForeachTypeList == null)
                        {
                            continue;
                        }

                        // If the searched variable is declared in the header
                        int iteratorIndex = -1;

                        for (int j = 0; j < fe.ForeachTypeList.Length; j++)
                        {
                            if (fe.ForeachTypeList[j] == i)
                            {
                                iteratorIndex = j;
                                break;
                            }
                        }

                        if (iteratorIndex == -1)
                        {
                            continue;
                        }

                        bool keyIsSearched = iteratorIndex == 0 && fe.ForeachTypeList.Length > 1;


                        // foreach(var k, var v; 0 .. 9)
                        if (keyIsSearched && fe.IsRangeStatement)
                        {
                            // -- it's static type int, of course(?)
                            return(new PrimitiveType(DTokens.Int));
                        }

                        var aggregateType = ExpressionTypeEvaluation.EvaluateType(fe.Aggregate, ctxt);

                        aggregateType = DResolver.StripMemberSymbols(aggregateType);

                        if (aggregateType == null)
                        {
                            return(null);
                        }

                        // The most common way to do a foreach
                        if (aggregateType is AssocArrayType)
                        {
                            var ar = (AssocArrayType)aggregateType;

                            return(keyIsSearched ? ar.KeyType : ar.ValueType);
                        }
                        else if (aggregateType is UserDefinedType)
                        {
                            var tr = (UserDefinedType)aggregateType;

                            if (keyIsSearched || !(tr.Definition is IBlockNode))
                            {
                                continue;
                            }

                            bool foundIterPropertyMatch = false;
                            #region Foreach over Structs and Classes with Ranges

                            // Enlist all 'back'/'front' members
                            var t_l = new List <AbstractType>();

                            foreach (var n in (IBlockNode)tr.Definition)
                            {
                                if (fe.IsReverse ? n.Name == "back" : n.Name == "front")
                                {
                                    t_l.Add(HandleNodeMatch(n, ctxt));
                                }
                            }

                            // Remove aliases
                            var iterPropertyTypes = DResolver.StripAliasSymbols(t_l);

                            foreach (var iterPropType in iterPropertyTypes)
                            {
                                if (iterPropType is MemberSymbol)
                                {
                                    foundIterPropertyMatch = true;

                                    var itp = (MemberSymbol)iterPropType;

                                    // Only take non-parameterized methods
                                    if (itp.Definition is DMethod && ((DMethod)itp.Definition).Parameters.Count != 0)
                                    {
                                        continue;
                                    }

                                    // Handle its base type [return type] as iterator type
                                    if (itp.Base != null)
                                    {
                                        r.Add(itp.Base);
                                    }

                                    foundIterPropertyMatch = true;
                                }
                            }

                            if (foundIterPropertyMatch)
                            {
                                continue;
                            }
                            #endregion

                            #region Foreach over Structs and Classes with opApply
                            t_l.Clear();
                            r.Clear();

                            foreach (var n in (IBlockNode)tr.Definition)
                            {
                                if (n is DMethod &&
                                    (fe.IsReverse ? n.Name == "opApplyReverse" : n.Name == "opApply"))
                                {
                                    t_l.Add(HandleNodeMatch(n, ctxt));
                                }
                            }

                            iterPropertyTypes = DResolver.StripAliasSymbols(t_l);

                            foreach (var iterPropertyType in iterPropertyTypes)
                            {
                                if (iterPropertyType is MemberSymbol)
                                {
                                    var mr = (MemberSymbol)iterPropertyType;
                                    var dm = mr.Definition as DMethod;

                                    if (dm == null || dm.Parameters.Count != 1)
                                    {
                                        continue;
                                    }

                                    var dg = dm.Parameters[0].Type as DelegateDeclaration;

                                    if (dg == null || dg.Parameters.Count != fe.ForeachTypeList.Length)
                                    {
                                        continue;
                                    }

                                    var paramType = Resolve(dg.Parameters[iteratorIndex].Type, ctxt);

                                    if (paramType != null && paramType.Length > 0)
                                    {
                                        r.Add(paramType[0]);
                                    }
                                }
                            }
                            #endregion
                        }

                        if (r.Count > 1)
                        {
                            ctxt.LogError(new ResolutionError(curStmt, "Ambigous iterator type"));
                        }

                        return(r.Count != 0 ? r[0] : null);
                    }
                }

                return(null);
            }
Beispiel #20
0
        public static AbstractType GetMethodReturnType(DMethod method, ResolutionContext ctxt)
        {
            if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) == ResolutionOptions.DontResolveBaseTypes)
            {
                return(null);
            }

            /*
             * If a method's type equals null, assume that it's an 'auto' function..
             * 1) Search for a return statement
             * 2) Resolve the returned expression
             * 3) Use that one as the method's type
             */
            bool pushMethodScope = ctxt.ScopedBlock != method;

            if (method.Type != null)
            {
                if (pushMethodScope)
                {
                    ctxt.PushNewScope(method);
                }

                //FIXME: Is it legal to explicitly return a nested type?
                var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt);

                if (pushMethodScope)
                {
                    ctxt.Pop();
                }

                ctxt.CheckForSingleResult(returnType, method.Type);
                if (returnType != null && returnType.Length > 0)
                {
                    return(returnType[0]);
                }
            }
            else if (method.Body != null)
            {
                ReturnStatement returnStmt = null;
                var             list       = new List <IStatement> {
                    method.Body
                };
                var list2 = new List <IStatement>();

                bool foundMatch = false;
                while (!foundMatch && list.Count > 0)
                {
                    foreach (var stmt in list)
                    {
                        if (stmt is ReturnStatement)
                        {
                            returnStmt = stmt as ReturnStatement;

                            var te = returnStmt.ReturnExpression as TokenExpression;
                            if (te == null || te.Token != DTokens.Null)
                            {
                                foundMatch = true;
                                break;
                            }
                        }

                        var statementContainingStatement = stmt as StatementContainingStatement;
                        if (statementContainingStatement != null)
                        {
                            list2.AddRange(statementContainingStatement.SubStatements);
                        }
                    }

                    list  = list2;
                    list2 = new List <IStatement>();
                }

                if (returnStmt != null && returnStmt.ReturnExpression != null)
                {
                    if (pushMethodScope)
                    {
                        var dedTypes = ctxt.CurrentContext.DeducedTemplateParameters;
                        ctxt.PushNewScope(method, returnStmt);

                        if (dedTypes.Count != 0)
                        {
                            foreach (var kv in dedTypes)
                            {
                                ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
                            }
                        }
                    }

                    var t = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(returnStmt.ReturnExpression, ctxt));

                    if (pushMethodScope)
                    {
                        ctxt.Pop();
                    }

                    return(t);
                }

                return(new PrimitiveType(DTokens.Void));
            }

            return(null);
        }
Beispiel #21
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);
        }
        bool HandleDecl(TemplateTypeParameter parameter, TemplateInstanceExpression tix, AbstractType r)
        {
            /*
             * TODO: Scan down r for having at least one templateinstanceexpression as declaration base.
             * If a tix was found, check if the definition of the respective result base level
             * and the un-aliased identifier of the 'tix' parameter match.
             * Attention: if the alias represents an undeduced type (i.e. a type bundle of equally named type nodes),
             * it is only important that the definition is inside this bundle.
             * Therefore, it's needed to manually resolve the identifier, and look out for aliases or such unprecise aliases..confusing as s**t!
             *
             * If the param tix id is part of the template param list, the behaviour is currently undefined! - so instantly return false, I'll leave it as TODO/FIXME
             */
            var paramTix_TemplateMatchPossibilities       = ResolveTemplateInstanceId(tix);
            TemplateIntermediateType tixBasedArgumentType = null;
            var r_ = r as DSymbol;

            while (r_ != null)
            {
                if (r_.DeclarationOrExpressionBase is TemplateInstanceExpression)
                {
                    var tit = r_ as TemplateIntermediateType;
                    if (tit != null && CheckForTixIdentifierEquality(paramTix_TemplateMatchPossibilities, tit.Definition))
                    {
                        tixBasedArgumentType = tit;
                        break;
                    }
                }

                r_ = r_.Base as DSymbol;
            }

            /*
             * This part is very tricky:
             * I still dunno what is allowed over here--
             *
             * class Foo(T:Bar!E[],E) {}
             * ...
             * Foo!(Bar!string[]) f; -- E will be 'string' then
             *
             * class DerivateBar : Bar!string[] {} -- new Foo!DerivateBar() is also allowed, but now DerivateBar
             *		obviously is not a template instance expression - it's a normal identifier only.
             */
            if (tixBasedArgumentType != null)
            {
                var argEnum_given = ((TemplateInstanceExpression)tixBasedArgumentType.DeclarationOrExpressionBase).Arguments.GetEnumerator();

                foreach (var p in tix.Arguments)
                {
                    if (!argEnum_given.MoveNext() || argEnum_given.Current == null)
                    {
                        return(false);
                    }

                    // Convert p to type declaration
                    var param_Expected = ConvertToTypeDeclarationRoughly(p);

                    if (param_Expected == null)
                    {
                        return(false);
                    }

                    var result_Given = ExpressionTypeEvaluation.EvaluateType(argEnum_given.Current as IExpression, ctxt);

                    if (result_Given == null || !HandleDecl(parameter, param_Expected, result_Given))
                    {
                        return(false);
                    }
                }

                // Too many params passed..
                if (argEnum_given.MoveNext())
                {
                    return(false);
                }

                return(true);
            }

            return(false);
        }
Beispiel #23
0
        public void ParsePerformance1()
        {
            //var pc = ParsePhobos(false);
            var pcl = ResolutionTests.CreateCache(@"module modA;

import std.stdio, std.array;

class lol{
	
	static int Object;
	
	int inc(int i, int k)
	{
		
		return i+k;	
	}

	void derp() {}
	
	const void lolBar(this T)() {
		
		auto l=123.inc!int();
		lol.Object;
		writeln(typeid(T));
		
		Object=1;
	}
}

void main()
{
	immutable(char)[] arr;
	destroy(arr);
	for(int i=0;i<10;i++)
		writeln(i);
	return;
	
	auto st=new STest();
	auto tt = new ModClass!int();
	writeln(st.a);
	
	static assert(st.a==34);
	
	int i = delegate int() { return 123; }();	
	//int j= 234++;
	writeln(i);
	writeln(di,123,123);

	lol o = new lol();
	o.derp();
}

");
            //pcl.Add(pc);

            var sw   = new Stopwatch();
            var main = pcl[0]["modA"]["main"].First() as DMethod;

            Assert.AreEqual(0, (pcl[0]["modA"] as DModule).ParseErrors.Count);
            var s    = main.Body.SubStatements.Last() as IExpressionContainingStatement;
            var ctxt = ResolutionContext.Create(pcl, null, main, s.Location);
            //ctxt.ContextIndependentOptions |= ResolutionOptions.StopAfterFirstOverloads | ResolutionOptions.DontResolveBaseClasses | ResolutionOptions.DontResolveBaseTypes;
            var x = s.SubExpressions[0];

            //pc.UfcsCache.Update(pcl);
            sw.Restart();

            var t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);

            sw.Stop();
            Trace.WriteLine("Took " + sw.Elapsed.TotalMilliseconds + "ms to resolve " + x);
        }
        void HandleIndexSliceExpression(PostfixExpression x)
        {
            res.IsMethodArguments = true;
            res.ParsedExpression  = x;

            var overloads = new List <AbstractType>();

            if (x.PostfixForeExpression == null)
            {
                return;
            }

            var b     = ExpressionTypeEvaluation.EvaluateType(x.PostfixForeExpression, ctxt);
            var bases = AmbiguousType.TryDissolve(b);

            var ov = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(ExpressionTypeEvaluation.OpSliceIdHash, bases, ctxt, x, false);

            if (ov != null)
            {
                overloads.AddRange(ov);
            }

            ov = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(ExpressionTypeEvaluation.OpIndexIdHash, bases, ctxt, x, false);
            if (ov != null)
            {
                overloads.AddRange(ov);
            }

            if (overloads.Count == 0)
            {
                b = DResolver.StripMemberSymbols(b);
                var toTypeDecl = new DTypeToTypeDeclVisitor();
                var aa         = b as AssocArrayType;
                if (aa != null)
                {
                    var retType = aa.ValueType != null?aa.ValueType.Accept(toTypeDecl) : null;

                    var dm = new DMethod {
                        Name = "opIndex",
                        Type = retType
                    };
                    dm.Parameters.Add(new DVariable {
                        Name = "index",
                        Type = aa.KeyType != null ? aa.KeyType.Accept(toTypeDecl) : null
                    });
                    overloads.Add(new MemberSymbol(dm, aa.ValueType, x));

                    if ((aa is ArrayType) && !(aa as ArrayType).IsStaticArray)
                    {
                        dm = new DMethod
                        {
                            Name = "opSlice",
                            Type = retType
                        };
                        overloads.Add(new MemberSymbol(dm, aa.ValueType, x));
                    }
                }
                else if (b is PointerType)
                {
                    b = (b as PointerType).Base;
                    var dm = new DMethod
                    {
                        Name = "opIndex",
                        Type = b != null?b.Accept(toTypeDecl) : null
                    };
                    dm.Parameters.Add(new DVariable
                    {
                        Name = "index",
                        Type = new IdentifierDeclaration("size_t")
                    });
                    overloads.Add(new MemberSymbol(dm, b, x));
                }
            }

            res.ResolvedTypesOrMethods = overloads.ToArray();
        }
Beispiel #25
0
        public void Traits()
        {
            var pcl  = ResolutionTests.CreateCache(@"module A;
int i;
string s;

abstract class C { int foo(); }
class NC { int foo(); }

C c;
int[] dynArr;
int[5] statArr;
auto assocArr = ['c' : 23, 'b' : 84];

struct S {
  void bar() { }
  void bar(int i) {}
  void bar(string s) {}
  static int statInt;
}

class D {
	void bar() { }
	abstract void absBar();
	static void statFoo() {}
	final void finBar() {};
	private int privInt;
	package int packInt;
}

class E : D{
	final override void absBar()
	{
		
	}
	
	final void bar() {}
}

interface I {
  void bar();
}

template Tmpl(){
	void bar();
}
", @"module std.someStd;");
            var ctxt = ResolutionTests.CreateDefCtxt(pcl, pcl[0]["A"], null);

            BoolTrait(ctxt, "isArithmetic, int");
            BoolTrait(ctxt, "isArithmetic, i, i+1, int");
            BoolTrait(ctxt, "isArithmetic", false);
            BoolTrait(ctxt, "isArithmetic, int*", false);
            BoolTrait(ctxt, "isArithmetic, s, 123", false);
            BoolTrait(ctxt, "isArithmetic, 123, s", false);

            BoolTrait(ctxt, "isAbstractClass, C, c");
            BoolTrait(ctxt, "isAbstractClass, C");
            BoolTrait(ctxt, "isAbstractClass, int", false);
            BoolTrait(ctxt, "isAbstractClass, NC", false);
            BoolTrait(ctxt, "isAbstractClass", false);

            BoolTrait(ctxt, "isAssociativeArray, assocArr");
            BoolTrait(ctxt, "isAssociativeArray, dynArr", false);
            BoolTrait(ctxt, "isStaticArray, statArr");
            BoolTrait(ctxt, "isStaticArray, dynArr", false);

            BoolTrait(ctxt, "isVirtualMethod, D.bar");
            BoolTrait(ctxt, "isVirtualMethod, D.absBar");
            BoolTrait(ctxt, "isVirtualMethod, I.bar");
            BoolTrait(ctxt, "isVirtualMethod, Tmpl!().bar");
            //BoolTrait(ctxt, "isVirtualMethod, E.bar");
            //BoolTrait(ctxt, "isVirtualMethod, E.absBar");
            BoolTrait(ctxt, "isVirtualMethod, S.bar", false);
            BoolTrait(ctxt, "isVirtualMethod, D.statFoo", false);
            BoolTrait(ctxt, "isVirtualMethod, D.finBar", false);

            BoolTrait(ctxt, "isVirtualFunction, D.bar");
            BoolTrait(ctxt, "isVirtualFunction, D.absBar");
            BoolTrait(ctxt, "isVirtualFunction, I.bar");
            BoolTrait(ctxt, "isVirtualFunction, Tmpl!().bar");
            //BoolTrait(ctxt, "isVirtualFunction, E.bar");
            //BoolTrait(ctxt, "isVirtualFunction, E.absBar");
            BoolTrait(ctxt, "isVirtualFunction, S.bar", false);
            BoolTrait(ctxt, "isVirtualFunction, D.statFoo", false);
            BoolTrait(ctxt, "isVirtualFunction, D.finBar");

            BoolTrait(ctxt, "hasMember, C, \"foo\"");
            BoolTrait(ctxt, "hasMember, c, \"foo\"");
            BoolTrait(ctxt, "hasMember, C, \"noFoo\"", false);
            BoolTrait(ctxt, "hasMember, int, \"sizeof\"");

            var x = DParser.ParseExpression(@"__traits(identifier, C.aso.derp)");
            var v = Evaluation.EvaluateValue(x, ctxt);

            Assert.That(v, Is.TypeOf(typeof(ArrayValue)));
            var av = v as ArrayValue;

            Assert.That(av.IsString, Is.True);
            Assert.That(av.StringValue, Is.EqualTo("C.aso.derp"));

            x = DParser.ParseExpression("__traits(getMember, c, \"foo\")");
            var t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);

            Assert.That(t, Is.TypeOf(typeof(MemberSymbol)));



            x = DParser.ParseExpression("__traits(getOverloads, S, \"bar\")");
            v = Evaluation.EvaluateValue(x, ctxt);
            Assert.That(v, Is.TypeOf(typeof(TypeValue)));
            Assert.That((v as TypeValue).RepresentedType, Is.TypeOf(typeof(DTuple)));

            t = ExpressionTypeEvaluation.EvaluateType(x, ctxt);
            Assert.That(t, Is.TypeOf(typeof(DTuple)));


            x = DParser.ParseExpression("__traits(getProtection, D.privInt)");
            v = Evaluation.EvaluateValue(x, ctxt);

            Assert.That(v, Is.TypeOf(typeof(ArrayValue)));
            av = v as ArrayValue;
            Assert.That(av.IsString, Is.True);
            Assert.That(av.StringValue, Is.EqualTo("private"));

            x = DParser.ParseExpression("__traits(getProtection, D)");
            v = Evaluation.EvaluateValue(x, ctxt);

            Assert.That(v, Is.TypeOf(typeof(ArrayValue)));
            av = v as ArrayValue;
            Assert.That(av.IsString, Is.True);
            Assert.That(av.StringValue, Is.EqualTo("public"));

            x = DParser.ParseExpression("__traits(getProtection, D.packInt)");
            v = Evaluation.EvaluateValue(x, ctxt);

            Assert.That(v, Is.TypeOf(typeof(ArrayValue)));
            av = v as ArrayValue;
            Assert.That(av.IsString, Is.True);
            Assert.That(av.StringValue, Is.EqualTo("package"));

            BoolTrait(ctxt, "isSame, int, int");
            BoolTrait(ctxt, "isSame, int, double", false);
            BoolTrait(ctxt, "isSame, C, D", false);
            BoolTrait(ctxt, "isSame, D, D");

            BoolTrait(ctxt, "compiles", false);
            BoolTrait(ctxt, "compiles, asd.herp", false);
            BoolTrait(ctxt, "compiles, i");
            BoolTrait(ctxt, "compiles, i + 1");
            //BoolTrait(ctxt, "compiles, &i + 1", false); //TODO: Check if both operand types match..is this still efficient?
            BoolTrait(ctxt, "compiles, typeof(1)");
            BoolTrait(ctxt, "compiles, S.nonExistingItem", false);             //TODO: Make the resolver not resolve non-static items implicitly (i.e. without explicit resolution option)
            BoolTrait(ctxt, "compiles, S.statInt");
            BoolTrait(ctxt, "compiles, 1,2,3,int,long,std");
            BoolTrait(ctxt, "compiles, 1,2,3,int,long,3[1]", false);
            BoolTrait(ctxt, "compiles, 3[1]", false);
            BoolTrait(ctxt, "compiles, immutable(S44)(3, &i)", false);
        }