コード例 #1
0
ファイル: Resolver.cs プロジェクト: rainers/D_Parser
 public override void Visit(PostfixExpression_MethodCall x)
 {
     base.Visit(x);
     if (IdNearCaret == x.PostfixForeExpression)
     {
         IdNearCaret = x;
     }
 }
コード例 #2
0
        public AbstractType Visit(PostfixExpression_MethodCall call)
        {
            List <ISemantic> callArgs;
            ISymbolValue     delegValue;

            AbstractType[]             baseExpression;
            TemplateInstanceExpression tix;

            GetRawCallOverloads(ctxt, call.PostfixForeExpression, out baseExpression, out tix);

            return(Evaluation.EvalMethodCall(baseExpression, null, tix, ctxt, call, out callArgs, out delegValue, !ctxt.Options.HasFlag(ResolutionOptions.ReturnMethodReferencesOnly)));
        }
コード例 #3
0
        public void Visit(PostfixExpression_MethodCall call)
        {
            res.IsMethodArguments = true;

            res.MethodIdentifier       = call.PostfixForeExpression;
            res.ResolvedTypesOrMethods = ExpressionTypeEvaluation.GetUnfilteredMethodOverloads(call.PostfixForeExpression, ctxt, call);

            if (call.Arguments != null)
            {
                res.CurrentlyTypedArgumentIndex = call.ArgumentCount;
            }
        }
コード例 #4
0
 public override void Visit(PostfixExpression_MethodCall x)
 {
     if (triggerChar == '(' && x.ArgumentCount > 0 && IsIncompleteExpression(x.Arguments[x.ArgumentCount - 1]))
     {
         halt = true;
         explicitlyNoCompletion = true;
     }
     else
     {
         base.Visit(x);
     }
 }
コード例 #5
0
        public AbstractType Visit(PostfixExpression_MethodCall call)
        {
            List <ISemantic> callArgs;
            ISymbolValue     delegValue;

            AbstractType[]             baseExpression;
            TemplateInstanceExpression tix;

            GetRawCallOverloads(ctxt, call, out baseExpression, out tix);

            var argTypeFilteredOverloads = Evaluation.EvalMethodCall(baseExpression, null, tix, ctxt, call, out callArgs, out delegValue, !ctxt.Options.HasFlag(ResolutionOptions.ReturnMethodReferencesOnly));

            // Check if one overload remains and return that one.
            ctxt.CheckForSingleResult(argTypeFilteredOverloads, call);
            return(argTypeFilteredOverloads != null && argTypeFilteredOverloads.Count != 0 ? argTypeFilteredOverloads[0] : null);
        }
コード例 #6
0
        public ISymbolValue Visit(PostfixExpression_MethodCall call)
        {
            var returnBaseTypeOnly = !this.returnBaseTypeOnly.HasValue ?
                                     !ctxt.Options.HasFlag(ResolutionOptions.ReturnMethodReferencesOnly) :
                                     this.returnBaseTypeOnly.Value;

            this.returnBaseTypeOnly = null;

            List <ISemantic> callArguments;
            ISymbolValue     delegValue;

            // Deduce template parameters later on
            AbstractType[]             baseExpression;
            ISymbolValue               baseValue;
            TemplateInstanceExpression tix;

            GetRawCallOverloads(ctxt, call, out baseExpression, out baseValue, out tix);

            var argTypeFilteredOverloads = EvalMethodCall(baseExpression, baseValue, tix, ctxt, call, out callArguments, out delegValue, returnBaseTypeOnly, ValueProvider);

            if (delegValue != null)
            {
                return(delegValue);
            }
            if (argTypeFilteredOverloads == null)
            {
                return(null);
            }

            // Convert ISemantic[] to ISymbolValue[]
            var args = new List <ISymbolValue>(callArguments != null ? callArguments.Count : 0);

            if (callArguments != null)
            {
                foreach (var a in callArguments)
                {
                    args.Add(a as ISymbolValue);
                }
            }

            // Execute/Evaluate the variable contents etc.
            return(TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads, call.PostfixForeExpression, true, args.ToArray()));
        }
コード例 #7
0
        void GetRawCallOverloads(ResolutionContext ctxt, PostfixExpression_MethodCall call,
                                 out AbstractType[] baseExpression,
                                 out TemplateInstanceExpression tix)
        {
            tix = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                baseExpression = Evaluation.EvalPostfixAccessExpression(this, ctxt, pac, null, false, false);
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                {
                    baseExpression = ExpressionTypeEvaluation.GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                }
                else
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                    {
                        baseExpression = ExpressionTypeEvaluation.GetOverloads(tix = (TemplateInstanceExpression)call.PostfixForeExpression, ctxt, null, false);
                    }
                    else if (call.PostfixForeExpression is IdentifierExpression)
                    {
                        baseExpression = ExpressionTypeEvaluation.GetOverloads(call.PostfixForeExpression as IdentifierExpression, ctxt, deduceParameters: false);
                    }
                    else
                    {
                        baseExpression = new[] { call.PostfixForeExpression != null?AbstractType.Get(call.PostfixForeExpression.Accept(this)) : null }
                    };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
コード例 #8
0
ファイル: Parser_Impl.cs プロジェクト: gavin-norman/Mono-D
        IExpression PostfixExpression(IBlockNode Scope = null)
        {
            var curLastParsedObj = LastParsedObject;

            // PostfixExpression
            IExpression leftExpr = PrimaryExpression(Scope);

            if(curLastParsedObj==LastParsedObject)
                LastParsedObject = leftExpr;

            while (!IsEOF)
            {
                if (laKind == Dot)
                {
                    Step();

                    var e = new PostfixExpression_Access {
                        PostfixForeExpression=leftExpr
                    };
                    LastParsedObject = e;

                    leftExpr = e;

                    if (laKind == New)
                        e.AccessExpression = NewExpression(Scope);
                    else if (IsTemplateInstance)
                        e.AccessExpression = TemplateInstance();
                    else if (Expect(Identifier))
                        e.AccessExpression = new IdentifierExpression(t.Value) { Location=t.Location, EndLocation=t.EndLocation };

                    e.EndLocation = t.EndLocation;
                }
                else if (laKind == Increment || laKind == Decrement)
                {
                    Step();
                    var e = t.Kind == Increment ? (PostfixExpression)new PostfixExpression_Increment() : new PostfixExpression_Decrement();
                    LastParsedObject = e;
                    e.EndLocation = t.EndLocation;
                    e.PostfixForeExpression = leftExpr;
                    leftExpr = e;
                }

                // Function call
                else if (laKind == OpenParenthesis)
                {
                    Step();
                    var ae = new PostfixExpression_MethodCall();
                    LastParsedObject = ae;
                    ae.PostfixForeExpression = leftExpr;
                    leftExpr = ae;

                    if (laKind != CloseParenthesis)
                        ae.Arguments = ArgumentList(Scope).ToArray();
                    Step();
                    ae.EndLocation = t.EndLocation;
                }

                // IndexExpression | SliceExpression
                else if (laKind == OpenSquareBracket)
                {
                    Step();

                    if (laKind != CloseSquareBracket)
                    {
                        var firstEx = AssignExpression(Scope);
                        // [ AssignExpression .. AssignExpression ]
                        if (laKind == DoubleDot)
                        {
                            Step();

                            leftExpr = new PostfixExpression_Slice()
                            {
                                FromExpression = firstEx,
                                PostfixForeExpression = leftExpr,
                                ToExpression = AssignExpression(Scope)
                            };
                            LastParsedObject = leftExpr;
                        }
                        // [ ArgumentList ]
                        else if (laKind == CloseSquareBracket || laKind == (Comma))
                        {
                            var args = new List<IExpression>();
                            args.Add(firstEx);
                            if (laKind == Comma)
                            {
                                Step();
                                args.AddRange(ArgumentList(Scope));
                            }

                            leftExpr = new PostfixExpression_Index()
                            {
                                PostfixForeExpression = leftExpr,
                                Arguments = args.ToArray()
                            };
                            LastParsedObject = leftExpr;
                        }
                    }
                    else // Empty array literal = SliceExpression
                    {
                        leftExpr = new PostfixExpression_Slice()
                        {
                            PostfixForeExpression=leftExpr
                        };
                        LastParsedObject = leftExpr;
                    }

                    Expect(CloseSquareBracket);
                    if(leftExpr is PostfixExpression)
                        ((PostfixExpression)leftExpr).EndLocation = t.EndLocation;
                }
                else break;
            }

            return leftExpr;
        }
コード例 #9
0
		public void Visit(PostfixExpression_MethodCall call)
		{
			res.IsMethodArguments = true;

			res.MethodIdentifier = call.PostfixForeExpression;
			res.ResolvedTypesOrMethods = ExpressionTypeEvaluation.GetUnfilteredMethodOverloads(call.PostfixForeExpression, ctxt, call);

			if (call.Arguments != null)
				res.CurrentlyTypedArgumentIndex = call.ArgumentCount;
		}
コード例 #10
0
ファイル: Parser_Impl.cs プロジェクト: rainers/D_Parser
        IExpression PostfixExpression(IBlockNode Scope = null)
        {
            IExpression leftExpr = null;

            /*
             * Despite the following syntax is an explicit UnaryExpression (see http://dlang.org/expression.html#UnaryExpression),
             * stuff like (MyType).init[] is actually allowed - so it's obviously a PostfixExpression! (Nov 13 2013)
             */

            // ( Type ) . Identifier
            if (laKind == OpenParenthesis)
            {
                Lexer.StartPeek();
                OverPeekBrackets(OpenParenthesis, false);
                var dotToken = Lexer.CurrentPeekToken;

                if (Lexer.CurrentPeekToken.Kind == DTokens.Dot &&
                    (Peek().Kind == DTokens.Identifier || Lexer.CurrentPeekToken.Kind == EOF))
                {
                    var wkParsing = AllowWeakTypeParsing;
                    AllowWeakTypeParsing = true;
                    Lexer.PushLookAheadBackup();
                    Step();
                    var startLoc = t.Location;

                    var td = Type();

                    AllowWeakTypeParsing = wkParsing;

                    /*
                     * (a. -- expression: (a.myProp + 2) / b;
                     * (int. -- must be expression anyway
                     * (const).asdf -- definitely unary expression ("type")
                     * (const). -- also treat it as type accessor
                     */
                    if (td != null &&
                        laKind == CloseParenthesis && Lexer.CurrentPeekToken == dotToken) // Also take it as a type declaration if there's nothing following (see Expression Resolving)
                    {
                        Step();  // Skip to )
                        if (laKind == DTokens.Dot)
                        {
                            Step();  // Skip to .
                            if ((laKind == DTokens.Identifier && Peek(1).Kind != Not && Peek(1).Kind != OpenParenthesis) || IsEOF)
                            {
                                Lexer.PopLookAheadBackup();
                                Step();  // Skip to identifier

                                leftExpr = new UnaryExpression_Type()
                                {
                                    Type = td,
                                    AccessIdentifier = t.Value,
                                    Location = startLoc,
                                    EndLocation = t.EndLocation
                                };
                            }
                            else
                                Lexer.RestoreLookAheadBackup();
                        }
                        else
                            Lexer.RestoreLookAheadBackup();
                    }
                    else
                        Lexer.RestoreLookAheadBackup();
                }
            }

            // PostfixExpression
            if(leftExpr == null)
                leftExpr = PrimaryExpression(Scope);

            while (!IsEOF)
            {
                switch (laKind)
                {
                    case Dot:
                        Step();

                        var pea = new PostfixExpression_Access {
                            PostfixForeExpression = leftExpr
                        };

                        leftExpr = pea;

                        if (laKind == New)
                            pea.AccessExpression = PostfixExpression(Scope);
                        else if (IsTemplateInstance)
                            pea.AccessExpression = TemplateInstance(Scope);
                        else if (Expect(Identifier))
                            pea.AccessExpression = new IdentifierExpression(t.Value) {
                                Location = t.Location,
                                EndLocation = t.EndLocation
                            };
                        else if (IsEOF)
                            pea.AccessExpression = new TokenExpression(DTokens.Incomplete);

                        pea.EndLocation = t.EndLocation;
                        break;
                    case Increment:
                    case Decrement:
                        Step();
                        var peid = t.Kind == Increment ? (PostfixExpression)new PostfixExpression_Increment() : new PostfixExpression_Decrement();
                        peid.EndLocation = t.EndLocation;
                        peid.PostfixForeExpression = leftExpr;
                        leftExpr = peid;
                        break;
                    // Function call
                    case OpenParenthesis:
                        Step();
                        var pemc = new PostfixExpression_MethodCall();
                        pemc.PostfixForeExpression = leftExpr;
                        leftExpr = pemc;

                        if (laKind == CloseParenthesis)
                            Step();
                        else
                        {
                            pemc.Arguments = ArgumentList(Scope).ToArray();
                            Expect(CloseParenthesis);
                        }

                        if(IsEOF)
                            pemc.EndLocation = CodeLocation.Empty;
                        else
                            pemc.EndLocation = t.EndLocation;
                        break;
                    // IndexExpression | SliceExpression
                    case OpenSquareBracket:
                        Step();

                        if (laKind != CloseSquareBracket)
                        {
                            var firstEx = AssignExpression(Scope);
                            // [ AssignExpression .. AssignExpression ]
                            if (laKind == DoubleDot)
                            {
                                Step();

                                leftExpr = new PostfixExpression_Slice()
                                {
                                    FromExpression = firstEx,
                                    PostfixForeExpression = leftExpr,
                                    ToExpression = AssignExpression(Scope)
                                };
                            }
                            // [ ArgumentList ]
                            else if (laKind == CloseSquareBracket || laKind == (Comma))
                            {
                                var args = new List<IExpression>();
                                args.Add(firstEx);
                                if (laKind == Comma)
                                {
                                    Step();
                                    args.AddRange(ArgumentList(Scope));
                                }

                                leftExpr = new PostfixExpression_Index()
                                {
                                    PostfixForeExpression = leftExpr,
                                    Arguments = args.ToArray()
                                };
                            }
                        }
                        else // Empty array literal = SliceExpression
                        {
                            leftExpr = new PostfixExpression_Slice()
                            {
                                PostfixForeExpression=leftExpr
                            };
                        }

                        Expect(CloseSquareBracket);
                        if(leftExpr is PostfixExpression)
                            ((PostfixExpression)leftExpr).EndLocation = t.EndLocation;
                        break;
                    default:
                        return leftExpr;
                }
            }

            return leftExpr;
        }
コード例 #11
0
ファイル: ParamInsightVisitor.cs プロジェクト: Orvid/D_Parser
 public override void Visit(PostfixExpression_MethodCall x)
 {
     CallExpressionStack.Push(x);
     base.Visit(x);
     CallExpressionStack.Pop();
 }
コード例 #12
0
        ISemantic E(PostfixExpression_MethodCall call, bool returnBaseTypeOnly = true)
        {
            // Deduce template parameters later on
            AbstractType[]             baseExpression;
            ISymbolValue               baseValue;
            TemplateInstanceExpression tix;

            GetRawCallOverloads(call, out baseExpression, out baseValue, out tix);

            var methodOverloads = new List <AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true;             //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable <AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression);
            var nextResults = new List <AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (eval)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else
                                {
                                    EvalError(call, "Variable must be a delegate, not anything else", mr);
                                    return(null);
                                }
                            }
                            else
                            {
                                var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt));

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    //TODO: Ensure that there's no further overload - inform the user elsewise

                                    if (returnBaseTypeOnly)
                                    {
                                        return(bt);
                                    }
                                    else
                                    {
                                        return(new MemberSymbol(mr.Definition, bt, mr.DeclarationOrExpressionBase));
                                    }
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var dg = (DelegateType)b;

                        /*
                         * int a = delegate(x) { return x*2; } (12); // a is 24 after execution
                         * auto dg=delegate(x) {return x*3;};
                         * int b = dg(4);
                         */

                        if (dg.IsFunctionLiteral)
                        {
                            methodOverloads.Add(dg);
                        }
                        else
                        {
                            // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method.
                            if (eval)
                            {
                                EvalError(call, "TODO", dg);
                                return(null);
                            }
                            //TODO
                            //if(returnBaseTypeOnly)
                            //TODO: Check for multiple definitions. Also, make a parameter-argument check to inform the user about wrong arguments.
                            return(dg);
                        }
                    }
                    else if (b is ClassType || b is StructType)
                    {
                        var tit = (TemplateIntermediateType)b;

                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = tit.Definition;

                        if (classDef == null)
                        {
                            continue;
                        }

                        foreach (var i in GetOpCalls(tit, requireStaticItems))
                        {
                            methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);
                        }

                        /*
                         * Every struct can contain a default ctor:
                         *
                         * struct S { int a; bool b; }
                         *
                         * auto s = S(1,true); -- ok
                         * auto s2= new S(2,false); -- error, no constructor found!
                         */
                        if (b is StructType && methodOverloads.Count == 0)
                        {
                            //TODO: Deduce parameters
                            return(b);
                        }
                    }

                    /*
                     * If the overload is a template, it quite exclusively means that we'll handle a method that is the only
                     * child inside a template + that is named as the template.
                     */
                    else if (b is TemplateType)
                    {
                        methodOverloads.Add(b);
                    }
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
            {
                return(null);
            }

            // Get all arguments' types
            var  callArguments   = new List <ISemantic>();
            bool hasNonFinalArgs = false;

            if (call.Arguments != null)
            {
                foreach (var arg in call.Arguments)
                {
                    callArguments.Add(E(arg));
                }
            }

            #region If explicit template type args were given, try to associate them with each overload
            if (tix != null)
            {
                var args             = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasNonFinalArgs);
                var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt, hasNonFinalArgs);
                methodOverloads.Clear();
                if (deducedOverloads != null)
                {
                    methodOverloads.AddRange(deducedOverloads);
                }
            }
            #endregion

            #region Filter by parameter-argument comparison
            var  argTypeFilteredOverloads   = new List <AbstractType>();
            bool hasHandledUfcsResultBefore = false;

            foreach (var ov in methodOverloads)
            {
                if (ov is MemberSymbol)
                {
                    var ms = ov as MemberSymbol;
                    var dm = ms.Definition as DMethod;

                    if (dm != null)
                    {
                        // In the case of an ufcs, insert the first argument into the CallArguments list
                        if (ms.IsUFCSResult && !hasHandledUfcsResultBefore)
                        {
                            callArguments.Insert(0, eval ? baseValue as ISemantic : ((MemberSymbol)baseExpression[0]).FirstArgument);
                            hasHandledUfcsResultBefore = true;
                        }
                        else if (!ms.IsUFCSResult && hasHandledUfcsResultBefore)                         // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again
                        {
                            callArguments.RemoveAt(0);
                            hasHandledUfcsResultBefore = false;
                        }

                        var deducedTypeDict = new DeducedTypeDictionary(ms);
                        if (dm.TemplateParameters != null)
                        {
                            foreach (var tpar in dm.TemplateParameters)
                            {
                                if (!deducedTypeDict.ContainsKey(tpar.NameHash))
                                {
                                    deducedTypeDict[tpar.NameHash] = null;
                                }
                            }
                        }
                        var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt);

                        int  currentArg = 0;
                        bool add        = true;
                        if (callArguments.Count > 0 || dm.Parameters.Count > 0)
                        {
                            for (int i = 0; i < dm.Parameters.Count; i++)
                            {
                                var paramType = dm.Parameters[i].Type;

                                // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way..
                                if (paramType is IdentifierDeclaration &&
                                    TryHandleMethodArgumentTuple(ref add, callArguments, dm, deducedTypeDict, i, ref currentArg))
                                {
                                    continue;
                                }
                                else if (currentArg < callArguments.Count)
                                {
                                    if (!templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++]))
                                    {
                                        add = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    // If there are more parameters than arguments given, check if the param has default values
                                    if (!(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer == null)
                                    {
                                        add = false;
                                        break;
                                    }
                                    // Assume that all further method parameters do have default values - and don't check further parameters
                                    break;
                                }
                            }
                        }

                        // If type params were unassigned, try to take the defaults
                        if (add && dm.TemplateParameters != null)
                        {
                            foreach (var tpar in dm.TemplateParameters)
                            {
                                if (deducedTypeDict[tpar.NameHash] == null)
                                {
                                    add = templateParamDeduction.Handle(tpar, null);
                                    if (!add)
                                    {
                                        if (hasNonFinalArgs)
                                        {
                                            deducedTypeDict[tpar.NameHash] = new TemplateParameterSymbol(tpar, null);
                                            add = true;
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        if (add && (deducedTypeDict.AllParamatersSatisfied || hasNonFinalArgs))
                        {
                            ms.DeducedTypes = deducedTypeDict.ToReadonly();
                            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);

                            var bt = ms.Base ?? TypeDeclarationResolver.GetMethodReturnType(dm, ctxt);

                            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);

                            if (eval || !returnBaseTypeOnly)
                            {
                                argTypeFilteredOverloads.Add(ms.Base == null ? new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) : ms);
                            }
                            else
                            {
                                argTypeFilteredOverloads.Add(bt);
                            }
                        }
                    }
                }
                else if (ov is DelegateType)
                {
                    var dg = (DelegateType)ov;
                    var bt = TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                    //TODO: Param-Arg check

                    if (!eval || returnBaseTypeOnly)
                    {
                        argTypeFilteredOverloads.Add(bt);
                    }
                    else
                    {
                        argTypeFilteredOverloads.Add(new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters));
                    }
                }
            }
            #endregion

            if (eval)
            {
                // Convert ISemantic[] to ISymbolValue[]
                var args = new List <ISymbolValue>(callArguments.Count);

                foreach (var a in callArguments)
                {
                    args.Add(a as ISymbolValue);
                }

                // Execute/Evaluate the variable contents etc.
                return(TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads.ToArray(), call.PostfixForeExpression, true, args.ToArray()));
            }
            else
            {
                // Check if one overload remains and return that one.
                ctxt.CheckForSingleResult(argTypeFilteredOverloads.ToArray(), call);
                return(argTypeFilteredOverloads.Count != 0 ? argTypeFilteredOverloads[0] : null);
            }
        }
コード例 #13
0
        void GetRawCallOverloads(PostfixExpression_MethodCall call,
                                 out AbstractType[] baseExpression,
                                 out ISymbolValue baseValue,
                                 out TemplateInstanceExpression tix)
        {
            baseExpression = null;
            baseValue      = null;
            tix            = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = E(pac, null, false, false);

                if (vs != null && vs.Length != 0)
                {
                    if (vs[0] is ISymbolValue)
                    {
                        baseValue      = (ISymbolValue)vs[0];
                        baseExpression = new[] { baseValue.RepresentedType };
                    }
                    else if (vs[0] is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)vs[0]).Overloads;
                    }
                    else
                    {
                        baseExpression = TypeDeclarationResolver.Convert(vs);
                    }
                }
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                {
                    baseExpression = GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                }
                else if (eval)
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                    {
                        baseValue = E(tix = call.PostfixForeExpression as TemplateInstanceExpression, false) as ISymbolValue;
                    }
                    else if (call.PostfixForeExpression is IdentifierExpression)
                    {
                        baseValue = E((IdentifierExpression)call.PostfixForeExpression, false) as ISymbolValue;
                    }
                    else
                    {
                        baseValue = E(call.PostfixForeExpression) as ISymbolValue;
                    }

                    if (baseValue is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    }
                    else if (baseValue != null)
                    {
                        baseExpression = new[] { baseValue.RepresentedType }
                    }
                    ;
                    else
                    {
                        baseExpression = null;
                    }
                }
                else
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                    {
                        baseExpression = GetOverloads(tix = (TemplateInstanceExpression)call.PostfixForeExpression, null, false);
                    }
                    else if (call.PostfixForeExpression is IdentifierExpression)
                    {
                        baseExpression = GetOverloads((IdentifierExpression)call.PostfixForeExpression, false);
                    }
                    else
                    {
                        baseExpression = new[] { AbstractType.Get(E(call.PostfixForeExpression)) }
                    };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
コード例 #14
0
        ISemantic E(PostfixExpression_MethodCall call, bool returnBaseTypeOnly=true)
        {
            // Deduce template parameters later on
            AbstractType[] baseExpression = null;
            ISymbolValue baseValue = null;
            TemplateInstanceExpression tix = null;
            bool isUFCSFunction = false;

            GetRawCallOverloads(call, out baseExpression, out baseValue, out tix, out isUFCSFunction);

            var methodOverloads = new List<AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true; //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable<AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression);
            var nextResults = new List<AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (eval)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else
                                    throw new EvaluationException(call, "Variable must be a delegate, not anything else", mr);
                            }
                            else
                            {
                                var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt));

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    //TODO: Ensure that there's no further overload - inform the user elsewise

                                    if (returnBaseTypeOnly)
                                        return bt;
                                    else
                                        return new MemberSymbol(mr.Definition, bt, mr.DeclarationOrExpressionBase);
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var dg = (DelegateType)b;

                        /*
                         * int a = delegate(x) { return x*2; } (12); // a is 24 after execution
                         * auto dg=delegate(x) {return x*3;};
                         * int b = dg(4);
                         */

                        if (dg.IsFunctionLiteral)
                            methodOverloads.Add(dg);
                        else
                        {
                            // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method.
                            if (eval)
                                throw new EvaluationException(call, "TODO", dg);
                            //TODO
                            //if(returnBaseTypeOnly)
                            //TODO: Check for multiple definitions. Also, make a parameter-argument check to inform the user about wrong arguments.
                            return dg;
                        }
                    }
                    else if (b is ClassType)
                    {
                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = ((ClassType)b).Definition;

                        if (classDef == null)
                            continue;

                        foreach (var i in classDef)
                            if (i.Name == "opCall" && i is DMethod && (!requireStaticItems || (i as DNode).IsStatic))
                                methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);
                    }
                    /*
                     * Every struct can contain a default ctor:
                     *
                     * struct S { int a; bool b; }
                     *
                     * auto s = S(1,true); -- ok
                     * auto s2= new S(2,false); -- error, no constructor found!
                     */
                    else if (b is StructType && methodOverloads.Count == 0)
                    {
                        //TODO: Deduce parameters
                        return b;
                    }
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
                return null;

            // Get all arguments' types
            var callArguments = new List<ISemantic>();

            // If it's sure that we got a ufcs call here, add the base expression's type as first argument type
            if (isUFCSFunction)
                callArguments.Add(eval ? (ISemantic)baseValue : baseExpression[0]);

            if (call.Arguments != null)
                foreach (var arg in call.Arguments)
                    callArguments.Add(E(arg));

            #region Deduce template parameters and filter out unmatching overloads
            // First add optionally given template params
            // http://dlang.org/template.html#function-templates
            var tplParamDeductionArguments = tix == null ?
                new List<ISemantic>() :
                TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);

            // Then add the arguments[' member types]
            foreach (var arg in callArguments)
                if (arg is VariableValue)
                    tplParamDeductionArguments.Add(ValueProvider[((VariableValue)arg).Variable]);
                else if(arg is AbstractType)
                    tplParamDeductionArguments.Add(DResolver.StripMemberSymbols((AbstractType)arg));
                else
                    tplParamDeductionArguments.Add(arg);

            var templateParamFilteredOverloads= TemplateInstanceHandler.EvalAndFilterOverloads(
                methodOverloads,
                tplParamDeductionArguments.Count > 0 ? tplParamDeductionArguments.ToArray() : null,
                true, ctxt);
            #endregion

            #region Filter by parameter-argument comparison
            var argTypeFilteredOverloads = new List<AbstractType>();

            if (templateParamFilteredOverloads != null)
                foreach (var ov in templateParamFilteredOverloads)
                {
                    if (ov is MemberSymbol)
                    {
                        var ms = (MemberSymbol)ov;
                        var dm = ms.Definition as DMethod;
                        bool add = false;

                        if (dm != null)
                        {
                            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);

                            add = false;

                            if (callArguments.Count == 0 && dm.Parameters.Count == 0)
                                add=true;
                            else
                                for (int i=0; i< dm.Parameters.Count; i++)
                                {
                                    var paramType = TypeDeclarationResolver.ResolveSingle(dm.Parameters[i].Type, ctxt);

                                    // TODO: Expression tuples & variable argument lengths
                                    if (i >= callArguments.Count ||
                                        !ResultComparer.IsImplicitlyConvertible(callArguments[i], paramType, ctxt))
                                        continue;

                                    add = true;
                                }

                            if (add)
                            {
                                var bt=TypeDeclarationResolver.GetMethodReturnType(dm, ctxt);

                                if (returnBaseTypeOnly)
                                    argTypeFilteredOverloads.Add(bt);
                                else
                                    argTypeFilteredOverloads.Add(new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes));
                            }

                            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);
                        }
                    }
                    else if(ov is DelegateType)
                    {
                        var dg = (DelegateType)ov;
                        var bt = TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                        //TODO: Param-Arg check
                        if (returnBaseTypeOnly)
                            argTypeFilteredOverloads.Add(bt);
                        else
                            argTypeFilteredOverloads.Add(new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters));
                    }
                }
            #endregion

            if (eval)
            {
                // Convert ISemantic[] to ISymbolValue[]
                var args = new List<ISymbolValue>(callArguments.Count);

                foreach (var a in callArguments)
                    args.Add(a as ISymbolValue);

                // Execute/Evaluate the variable contents etc.
                return TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads.ToArray(), call.PostfixForeExpression, true, args.ToArray());
            }
            else
            {
                // Check if one overload remains and return that one.
                ctxt.CheckForSingleResult(argTypeFilteredOverloads.ToArray(), call);
                return argTypeFilteredOverloads != null && argTypeFilteredOverloads.Count != 0 ?
                    argTypeFilteredOverloads[0] : null;
            }
        }
コード例 #15
0
        void GetRawCallOverloads(ResolutionContext ctxt, PostfixExpression_MethodCall call,
                                 out AbstractType[] baseExpression,
                                 out ISymbolValue baseValue,
                                 out TemplateInstanceExpression tix)
        {
            baseValue = null;
            tix       = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = EvalPostfixAccessExpression(this, ctxt, pac, null, false, false);

                baseExpression = TypeDeclarationResolver.Convert(vs);
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                {
                    baseExpression = ExpressionTypeEvaluation.GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                }
                else
                {
                    var fore = call.PostfixForeExpression;
                    if (fore is TemplateInstanceExpression)
                    {
                        ImplicitlyExecute = false;
                        tix = call.PostfixForeExpression as TemplateInstanceExpression;
                    }
                    else if (fore is IdentifierExpression)
                    {
                        ImplicitlyExecute = false;
                    }

                    if (call.PostfixForeExpression != null)
                    {
                        baseValue = call.PostfixForeExpression.Accept(this) as ISymbolValue;
                    }

                    if (baseValue is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    }
                    else if (baseValue != null)
                    {
                        baseExpression = new[] { baseValue.RepresentedType }
                    }
                    ;
                    else
                    {
                        baseExpression = null;
                    }
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
コード例 #16
0
ファイル: Parser_Impl.cs プロジェクト: DinrusGroup/D_Parser
		IExpression PrimaryExpression(IBlockNode Scope=null)
		{
			bool isModuleScoped = laKind == Dot;
			if (isModuleScoped)
			{
				Step();
				if (IsEOF)
				{
					var dot = new TokenExpression(Dot) { Location = t.Location, EndLocation = t.EndLocation };
					return new PostfixExpression_Access{ PostfixForeExpression = dot, AccessExpression = new TokenExpression(DTokens.Incomplete) };
				}
			}

			// TemplateInstance
			if (IsTemplateInstance)
			{
				var tix = TemplateInstance(Scope);
				if (tix != null)
					tix.ModuleScoped = isModuleScoped;
				return tix;
			}

			if (IsLambaExpression())
				return LambaExpression(Scope);

			CodeLocation startLoc;
			switch (laKind)
			{
				// ArrayLiteral | AssocArrayLiteral
				case OpenSquareBracket:
					return ArrayLiteral(Scope);
				case New:
					return NewExpression(Scope);
				case Typeof:
					return new TypeDeclarationExpression(TypeOf(Scope));
				case __traits:
					return TraitsExpression(Scope);
				// Dollar (== Array length expression)
				case Dollar:
					Step();
					return new TokenExpression(t.Kind)
					{
						Location = t.Location,
						EndLocation = t.EndLocation
					};
				case Identifier:
					Step();
					return new IdentifierExpression(t.Value)
					{
						Location = t.Location,
						EndLocation = t.EndLocation,
						ModuleScoped = isModuleScoped
					};
				// SpecialTokens (this,super,null,true,false,$) // $ has been handled before
				case This:
				case Super:
				case Null:
				case True:
				case False:
					Step();
					return new TokenExpression(t.Kind)
					{
						Location = t.Location,
						EndLocation = t.EndLocation
					};
				case OpenParenthesis:
					if (IsFunctionLiteral())
						goto case Function;
					// ( Expression )
					Step();
					var ret = new SurroundingParenthesesExpression() {Location=t.Location };

					ret.Expression = Expression();

					Expect(CloseParenthesis);
					ret.EndLocation = t.EndLocation;
					return ret;
				case Literal:
					Step();
					startLoc = t.Location;

					// Concatenate multiple string literals here
					if (t.LiteralFormat == LiteralFormat.StringLiteral || t.LiteralFormat == LiteralFormat.VerbatimStringLiteral)
					{
						var sb = new StringBuilder(t.RawCodeRepresentation ?? t.Value);
						while (la.LiteralFormat == LiteralFormat.StringLiteral || la.LiteralFormat == LiteralFormat.VerbatimStringLiteral)
						{
							Step();
							sb.Append(t.RawCodeRepresentation ?? t.Value);
						}
						return new IdentifierExpression(sb.ToString(), t.LiteralFormat, t.Subformat) { Location = startLoc, EndLocation = t.EndLocation };
					}
					//else if (t.LiteralFormat == LiteralFormat.CharLiteral)return new IdentifierExpression(t.LiteralValue) { LiteralFormat=t.LiteralFormat,Location = startLoc, EndLocation = t.EndLocation };
					return new IdentifierExpression(t.LiteralValue, t.LiteralFormat, t.Subformat, t.RawCodeRepresentation) { Location = startLoc, EndLocation = t.EndLocation };
				// FunctionLiteral
				case Delegate:
				case Function:
				case OpenCurlyBrace:
					var fl = new FunctionLiteral() { Location=la.Location};
					fl.AnonymousMethod.Location = la.Location;

					if (laKind == Delegate || laKind == Function)
					{
						Step();
						fl.LiteralToken = t.Kind;
					}

					// file.d:1248
					/*
						listdir (".", delegate bool (DirEntry * de)
						{
							auto s = std.string.format("%s : c %s, w %s, a %s", de.name,
									toUTCString (de.creationTime),
									toUTCString (de.lastWriteTime),
									toUTCString (de.lastAccessTime));
							return true;
						}
						);
					*/
					if (laKind != OpenCurlyBrace) // foo( 1, {bar();} ); -> is a legal delegate
					{
						if (!IsFunctionAttribute && Lexer.CurrentPeekToken.Kind == OpenParenthesis)
							fl.AnonymousMethod.Type = BasicType(Scope);
						else if (laKind != OpenParenthesis && laKind != OpenCurlyBrace)
							fl.AnonymousMethod.Type = Type(Scope);

						if (laKind == OpenParenthesis)
							Parameters(fl.AnonymousMethod);

						FunctionAttributes(fl.AnonymousMethod);
					}

					FunctionBody(fl.AnonymousMethod);

					if(IsEOF)
						fl.AnonymousMethod.EndLocation = CodeLocation.Empty;

					fl.EndLocation = fl.AnonymousMethod.EndLocation;

					if (Scope != null && !AllowWeakTypeParsing) // HACK -- not only on AllowWeakTypeParsing! But apparently, this stuff may be parsed twice, so force-skip results of the first attempt although this is a rather stupid solution
						Scope.Add(fl.AnonymousMethod);

					return fl;
				// AssertExpression
				case Assert:
					Step();
					startLoc = t.Location;
					Expect(OpenParenthesis);
					var ce = new AssertExpression() { Location=startLoc};

					var exprs = new List<IExpression>();
					var assertedExpr = AssignExpression(Scope);
					if(assertedExpr!=null)
						exprs.Add(assertedExpr);

					if (laKind == (Comma))
					{
						Step();
						assertedExpr = AssignExpression(Scope);
						if (assertedExpr != null)
							exprs.Add(assertedExpr);
					}
					ce.AssignExpressions = exprs.ToArray();
					Expect(CloseParenthesis);
					ce.EndLocation = t.EndLocation;
					return ce;
				// MixinExpression
				case Mixin:
					Step();
					var me = new MixinExpression() { Location=t.Location};
					if (Expect(OpenParenthesis))
					{
						me.AssignExpression = AssignExpression(Scope);
						Expect(CloseParenthesis);
					}
					me.EndLocation = t.EndLocation;
					return me;
				// ImportExpression
				case Import:
					Step();
					var ie = new ImportExpression() { Location=t.Location};
					Expect(OpenParenthesis);

                    ie.AssignExpression = AssignExpression(Scope);

					Expect(CloseParenthesis);
					ie.EndLocation = t.EndLocation;
					return ie;
				// TypeidExpression
				case Typeid:
					Step();
					var tide = new TypeidExpression() { Location=t.Location};
					Expect(OpenParenthesis);

					if (IsAssignExpression())
						tide.Expression = AssignExpression(Scope);
					else
					{
						Lexer.PushLookAheadBackup();
						AllowWeakTypeParsing = true;
						tide.Type = Type(Scope);
						AllowWeakTypeParsing = false;

						if (tide.Type == null || laKind != CloseParenthesis)
						{
							Lexer.RestoreLookAheadBackup();
							tide.Expression = AssignExpression(Scope);
						}
						else
							Lexer.PopLookAheadBackup();
					}

					Expect (CloseParenthesis);

					tide.EndLocation = t.EndLocation;
					return tide;
				// IsExpression
				case Is:
					Step ();
					var ise = new IsExpression () { Location = t.Location };
					Expect (OpenParenthesis);

					if (laKind == DTokens.This && Lexer.CurrentPeekToken.Kind != DTokens.Dot) {
						Step ();
						ise.TestedType = new DTokenDeclaration (DTokens.This) { Location = t.Location, EndLocation = t.EndLocation };
					} else
						ise.TestedType = Type (Scope);

					if (ise.TestedType == null)
						SynErr(laKind, "In an IsExpression, either a type or an expression is required!");

					if (ise.TestedType != null)
					{
						if (laKind == Identifier && (Lexer.CurrentPeekToken.Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Equal
						    || Lexer.CurrentPeekToken.Kind == Colon))
						{
							Step();
							Strings.Add(strVal);
							ise.TypeAliasIdentifierHash = strVal.GetHashCode();
							ise.TypeAliasIdLocation = t.Location;
						}
						else if (IsEOF)
							ise.TypeAliasIdentifierHash = DTokens.IncompleteIdHash;
					}

					if (laKind == Colon || laKind == Equal)
					{
						Step();
						ise.EqualityTest = t.Kind == Equal;
					}
					else if (laKind == CloseParenthesis)
					{
						Step();
						ise.EndLocation = t.EndLocation;
						return ise;
					}

					/*
					TypeSpecialization:
						Type
							struct
							union
							class
							interface
							enum
							function
							delegate
							super
						const
						immutable
						inout
						shared
							return
					*/

					bool specialTest = false;
					if (ise.EqualityTest)
					{
						switch (laKind)
						{
							case Typedef: // typedef is possible although it's not yet documented in the syntax docs
							case Enum:
							case Delegate:
							case Function:
							case Super:
							case Return:
								specialTest = true;
								break;
							case Const:
							case Immutable:
							case InOut:
							case Shared:
								specialTest = Peek(1).Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Comma;
								break;
							default:
								specialTest = IsClassLike(laKind);
								break;
						}
					}
					if (specialTest)
					{
						Step();
						ise.TypeSpecializationToken = t.Kind;
					}
					else if (IsEOF)
						ise.TypeSpecializationToken = DTokens.Incomplete;
					else
						ise.TypeSpecialization = Type(Scope);

					// TemplateParameterList
					if (laKind == Comma)
					{
						var tempParam = new List<TemplateParameter>();
						do
						{
							Step();
							tempParam.Add(TemplateParameter(Scope as DNode));
						}
						while (laKind == Comma);
						ise.TemplateParameterList = tempParam.ToArray();
					}

					Expect(CloseParenthesis);
					ise.EndLocation = t.EndLocation;
					return ise;
				default:
					if (DTokens.IsMetaIdentifier(laKind))
						goto case Dollar;
					else if (IsBasicType())
					{
						startLoc = la.Location;

						var bt=BasicType(Scope);

						switch (laKind)
						{
							case DTokens.Dot: // BasicType . Identifier
								Step();
								// Things like incomplete 'float.' expressions shall be parseable, too
								if (Expect(Identifier) || IsEOF)
									return new PostfixExpression_Access()
									{
										PostfixForeExpression = new TypeDeclarationExpression(bt),
										AccessExpression = IsEOF ? new TokenExpression(Incomplete) as IExpression : new IdentifierExpression(t.Value) { Location = t.Location, EndLocation = t.EndLocation },
										EndLocation = t.EndLocation
									};
								break;
							case DTokens.OpenParenthesis:
								Step();

								var callExp = new PostfixExpression_MethodCall { PostfixForeExpression = new TypeDeclarationExpression(bt) };
								callExp.Arguments = ArgumentList(Scope).ToArray();

								Expect(DTokens.CloseParenthesis);
								return callExp;
							default:
								if (bt is TypeOfDeclaration || bt is MemberFunctionAttributeDecl)
									return new TypeDeclarationExpression(bt);
								break;
						}

						return null;
					}

					SynErr(Identifier);
					if(laKind != CloseCurlyBrace)
						Step();

					if (IsEOF)
						return new TokenExpression (DTokens.Incomplete) { Location = t.Location, EndLocation = t.Location };

					// Don't know why, in rare situations, t tends to be null..
					if (t == null)
						return null;
					return new TokenExpression() { Location = t.Location, EndLocation = t.EndLocation };
			}
		}
コード例 #17
0
 public override void Visit(PostfixExpression_MethodCall x)
 {
     CallExpressionStack.Push (x);
     base.Visit (x);
     CallExpressionStack.Pop ();
 }
コード例 #18
0
ファイル: ResolutionTests.cs プロジェクト: EnergonV/D_Parser
        public void opDispatch()
        {
            var ctxt = CreateCtxt ("A", @"module A;
            class S {
            int* opDispatch(string s)(int i){ }
            int opDispatch(string s)(){ }
            }

            struct S2 {
              T opDispatch(string s, T)(T i){ return i; }
            }

            struct S3 {
              static int opDispatch(string s)(){ }
            }

            struct D {
              template opDispatch(string s) {
            enum int opDispatch = 8;
              }
            }

            S s;
            S2 s2;
            S3 s3;

            void main() {
              S2 loc;
            x;
            }");
            AbstractType t;
            DSymbol ds;
            IExpression x;
            ITypeDeclaration td;
            ISymbolValue v;

            var main = ctxt.ParseCache [0] ["A"] ["main"].First () as DMethod;
            var stmt_x = main.Body.SubStatements.ElementAt (1);

            x = new PostfixExpression_MethodCall{
                Arguments = new[]{ new IdentifierExpression(123m, LiteralFormat.Scalar) },
                PostfixForeExpression = new PostfixExpression_Access{
                    AccessExpression = new IdentifierExpression("bar"),
                    PostfixForeExpression = new IdentifierExpression("loc") { Location = stmt_x.Location }
                }
            };
            ctxt.PushNewScope (main, stmt_x);

            ds = Evaluation.EvaluateType (x, ctxt) as DSymbol;
            Assert.That (ds, Is.TypeOf(typeof(TemplateParameterSymbol)));
            Assert.That (ds.Base, Is.TypeOf(typeof(PrimitiveType)));

            ctxt.Pop ();

            x = DParser.ParseExpression ("s2.bar(s)");
            ds = Evaluation.EvaluateType (x, ctxt) as DSymbol;
            Assert.That (ds, Is.TypeOf (typeof(TemplateParameterSymbol)));
            Assert.That (ds.Base, Is.TypeOf(typeof(ClassType)));

            x = DParser.ParseExpression ("s.foo(123)");
            t = Evaluation.EvaluateType (x, ctxt);
            Assert.That (t, Is.TypeOf(typeof(PointerType)));

            x = DParser.ParseExpression ("s.foo");
            ds = Evaluation.EvaluateType (x, ctxt) as DSymbol;
            Assert.That (ds, Is.TypeOf(typeof(MemberSymbol)));
            Assert.That (ds.Base, Is.TypeOf(typeof(PrimitiveType)));

            x = DParser.ParseExpression ("D.foo");
            ds = Evaluation.EvaluateType (x, ctxt) as DSymbol;
            Assert.That (ds, Is.TypeOf(typeof(MemberSymbol)));
            Assert.That (ds.Base, Is.TypeOf(typeof(PrimitiveType)));

            v = Evaluation.EvaluateValue (x, ctxt);
            Assert.That (v, Is.TypeOf(typeof(PrimitiveValue)));
            Assert.That ((v as PrimitiveValue).Value, Is.EqualTo(8m));

            td = DParser.ParseBasicType("D.foo");
            ds = TypeDeclarationResolver.ResolveSingle (td, ctxt) as DSymbol;
            Assert.That (ds, Is.TypeOf(typeof(MemberSymbol)));
            Assert.That (ds.Base , Is.TypeOf(typeof(PrimitiveType)));
        }
コード例 #19
0
		public override void Visit(PostfixExpression_MethodCall x)
		{
			if (triggerChar == '(' && x.ArgumentCount > 0 && IsIncompleteExpression(x.Arguments[x.ArgumentCount - 1]))
			{
				halt = true;
				explicitlyNoCompletion = true;
			}
			else
				base.Visit(x);
		}
コード例 #20
0
        public static AbstractType EvalMethodCall(AbstractType[] baseExpression, ISymbolValue baseValue, TemplateInstanceExpression tix,
                                                  ResolutionContext ctxt,
                                                  PostfixExpression_MethodCall call, out List <ISemantic> callArguments, out ISymbolValue delegateValue,
                                                  bool returnBaseTypeOnly, AbstractSymbolValueProvider ValueProvider = null)
        {
            //TODO: Refactor this crap!

            delegateValue = null;
            callArguments = null;

            var methodOverloads = new List <AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true;             //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable <AbstractType> scanResults = baseExpression;
            var nextResults = new List <AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is AmbiguousType)
                    {
                        nextResults.AddRange((b as AmbiguousType).Overloads);
                    }
                    else if (b is TemplateParameterSymbol)
                    {
                        nextResults.Add((b as TemplateParameterSymbol).Base);
                    }
                    else if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (ValueProvider != null)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else
                                {
                                    ValueProvider.LogError(call, "Variable must be a delegate, not anything else");
                                    return(null);
                                }
                            }
                            else
                            {
                                var bt = mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt);

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    var ret = HandleCallDelegateType(ValueProvider, bt as DelegateType, methodOverloads, returnBaseTypeOnly);
                                    if (ret is ISymbolValue)
                                    {
                                        delegateValue = ret as ISymbolValue;
                                        return(null);
                                    }
                                    else if (ret is AbstractType)
                                    {
                                        return(ret as AbstractType);
                                    }
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var ret = HandleCallDelegateType(ValueProvider, b as DelegateType, methodOverloads, returnBaseTypeOnly);
                        if (ret is ISymbolValue)
                        {
                            delegateValue = ret as ISymbolValue;
                            return(null);
                        }
                        else if (ret is AbstractType)
                        {
                            return(ret as AbstractType);
                        }
                    }
                    else if (b is ClassType || b is StructType)
                    {
                        var tit = (TemplateIntermediateType)b;

                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = tit.Definition;

                        if (classDef == null)
                        {
                            continue;
                        }

                        foreach (var i in ExpressionTypeEvaluation.GetOpCalls(tit, requireStaticItems))
                        {
                            methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);
                        }

                        /*
                         * Every struct can contain a default ctor:
                         *
                         * struct S { int a; bool b; }
                         *
                         * auto s = S(1,true); -- ok
                         * auto s2= new S(2,false); -- error, no constructor found!
                         */
                        if (b is StructType && methodOverloads.Count == 0)
                        {
                            //TODO: Deduce parameters
                            return(b);
                        }
                    }

                    /*
                     * If the overload is a template, it quite exclusively means that we'll handle a method that is the only
                     * child inside a template + that is named as the template.
                     */
                    else if (b is TemplateType)
                    {
                        methodOverloads.Add(b);
                    }
                    else if (b is PrimitiveType)                     // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal.
                    {
                        methodOverloads.Add(b);
                    }
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
            {
                return(null);
            }

            // Get all arguments' types
            callArguments = new List <ISemantic>();

            if (call.Arguments != null)
            {
                if (ValueProvider != null)
                {
                    foreach (var arg in call.Arguments)
                    {
                        callArguments.Add(arg != null ? Evaluation.EvaluateValue(arg, ValueProvider) : null);
                    }
                }
                else
                {
                    foreach (var arg in call.Arguments)
                    {
                        callArguments.Add(arg != null ? ExpressionTypeEvaluation.EvaluateType(arg, ctxt) : null);
                    }
                }
            }

            #region If explicit template type args were given, try to associate them with each overload
            if (tix != null)
            {
                var args             = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);
                var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt);
                methodOverloads.Clear();
                if (deducedOverloads != null)
                {
                    methodOverloads.AddRange(deducedOverloads);
                }
            }
            #endregion

            #region Filter by parameter-argument comparison
            var          argTypeFilteredOverloads   = new List <AbstractType>();
            bool         hasHandledUfcsResultBefore = false;
            AbstractType untemplatedMethodResult    = null;

            foreach (var ov in methodOverloads)
            {
                if (ov is MemberSymbol)
                {
                    HandleDMethodOverload(ctxt, ValueProvider != null, baseValue, callArguments, returnBaseTypeOnly, argTypeFilteredOverloads, ref hasHandledUfcsResultBefore,
                                          ov as MemberSymbol, ref untemplatedMethodResult);
                }
                else if (ov is DelegateType)
                {
                    var dg = ov as DelegateType;
                    var bt = dg.Base ?? TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                    //TODO: Param-Arg check

                    if (returnBaseTypeOnly)
                    {
                        argTypeFilteredOverloads.Add(bt);
                    }
                    else
                    {
                        if (dg.Base == null)
                        {
                            if (dg.IsFunctionLiteral)
                            {
                                dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters);
                            }
                            else
                            {
                                dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as DelegateDeclaration, dg.Parameters);
                            }
                        }
                        argTypeFilteredOverloads.Add(new DelegateCallSymbol(dg, call));
                    }
                }
                else if (ov is PrimitiveType)                 // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal.
                {
                    if (ValueProvider != null)
                    {
                        if (callArguments == null || callArguments.Count != 1)
                        {
                            ValueProvider.LogError(call, "Uniform construction syntax expects exactly one argument");
                        }
                        else
                        {
                            var pv = callArguments[0] as PrimitiveValue;
                            if (pv == null)
                            {
                                ValueProvider.LogError(call, "Uniform construction syntax expects one built-in scalar value as first argument");
                            }
                            else
                            {
                                delegateValue = new PrimitiveValue(pv.Value, ov as PrimitiveType, pv.ImaginaryPart);
                            }
                        }
                    }

                    argTypeFilteredOverloads.Add(ov);
                }
            }

            // Prefer untemplated methods over templated ones
            if (untemplatedMethodResult != null)
            {
                return(untemplatedMethodResult);
            }
            #endregion

            return(AmbiguousType.Get(argTypeFilteredOverloads, tix));
        }
コード例 #21
0
        ISemantic E(PostfixExpression_MethodCall call, bool returnBaseTypeOnly=true)
        {
            // Deduce template parameters later on
            AbstractType[] baseExpression;
            ISymbolValue baseValue;
            TemplateInstanceExpression tix;

            GetRawCallOverloads(call, out baseExpression, out baseValue, out tix);

            var methodOverloads = new List<AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true; //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable<AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression);
            var nextResults = new List<AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (eval)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else{
                                    EvalError(call, "Variable must be a delegate, not anything else", mr);
                                    return null;
                                }
                            }
                            else
                            {
                                var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt));

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    //TODO: Ensure that there's no further overload - inform the user elsewise

                                    if (returnBaseTypeOnly)
                                        return bt;
                                    else
                                        return new MemberSymbol(mr.Definition, bt, mr.DeclarationOrExpressionBase);
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var dg = (DelegateType)b;

                        /*
                         * int a = delegate(x) { return x*2; } (12); // a is 24 after execution
                         * auto dg=delegate(x) {return x*3;};
                         * int b = dg(4);
                         */

                        if (dg.IsFunctionLiteral)
                            methodOverloads.Add(dg);
                        else
                        {
                            // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method.
                            if (eval) {
                                EvalError(call, "TODO", dg);
                                return null;
                            }
                            //TODO
                            //if(returnBaseTypeOnly)
                            //TODO: Check for multiple definitions. Also, make a parameter-argument check to inform the user about wrong arguments.
                            return dg;
                        }
                    }
                    else if (b is ClassType || b is StructType)
                    {
                        var tit = (TemplateIntermediateType)b;
                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = tit.Definition;

                        if (classDef == null)
                            continue;

                        foreach (var i in GetOpCalls(tit, requireStaticItems))
                                methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);

                        /*
                         * Every struct can contain a default ctor:
                         *
                         * struct S { int a; bool b; }
                         *
                         * auto s = S(1,true); -- ok
                         * auto s2= new S(2,false); -- error, no constructor found!
                         */
                        if (b is StructType && methodOverloads.Count == 0)
                        {
                            //TODO: Deduce parameters
                            return b;
                        }
                    }

                    /*
                     * If the overload is a template, it quite exclusively means that we'll handle a method that is the only
                     * child inside a template + that is named as the template.
                     */
                    else if (b is TemplateType)
                        methodOverloads.Add(b);
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
                return null;

            // Get all arguments' types
            var callArguments = new List<ISemantic>();
            bool hasNonFinalArgs = false;

            if (call.Arguments != null)
                foreach (var arg in call.Arguments)
                    callArguments.Add(E(arg));

            #region If explicit template type args were given, try to associate them with each overload
            if (tix != null)
            {
                var args = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasNonFinalArgs);
                var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt, hasNonFinalArgs);
                methodOverloads.Clear();
                if(deducedOverloads != null)
                    methodOverloads.AddRange(deducedOverloads);
            }
            #endregion

            #region Filter by parameter-argument comparison
            var argTypeFilteredOverloads = new List<AbstractType>();
            bool hasHandledUfcsResultBefore = false;

            foreach (var ov in methodOverloads)
            {
                if (ov is MemberSymbol)
                {
                    var ms = ov as MemberSymbol;
                    var dm = ms.Definition as DMethod;

                    if (dm != null)
                    {
                        // In the case of an ufcs, insert the first argument into the CallArguments list
                        if (ms.IsUFCSResult && !hasHandledUfcsResultBefore)
                        {
                            callArguments.Insert(0, eval ? baseValue as ISemantic : ((MemberSymbol)baseExpression[0]).FirstArgument);
                            hasHandledUfcsResultBefore = true;
                        }
                        else if (!ms.IsUFCSResult && hasHandledUfcsResultBefore) // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again
                        {
                            callArguments.RemoveAt(0);
                            hasHandledUfcsResultBefore = false;
                        }

                        var deducedTypeDict = new DeducedTypeDictionary(ms);
                        var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt);

                        if(dm.Parameters.Count == 0 && callArguments.Count > 0)
                            continue;

                        int currentArg = 0;
                        bool add = true;
                        if (dm.Parameters.Count > 0 || callArguments.Count > 0)
                            for (int i=0; i< dm.Parameters.Count; i++)
                            {
                                var paramType = dm.Parameters[i].Type;

                                // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way..
                                if (paramType is IdentifierDeclaration &&
                                    TryHandleMethodArgumentTuple(ref add, callArguments, dm, deducedTypeDict, i, ref currentArg))
                                    continue;
                                else if (currentArg < callArguments.Count)
                                {
                                    if (!templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++]))
                                    {
                                        add = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    // If there are more parameters than arguments given, check if the param has default values
                                    if (!(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer == null)
                                    {
                                        add = false;
                                        break;
                                    }
                                    // Assume that all further method parameters do have default values - and don't check further parameters
                                    break;
                                }
                            }

                        // If type params were unassigned, try to take the defaults
                        if (add && dm.TemplateParameters != null)
                        {
                            foreach (var tpar in dm.TemplateParameters)
                            {
                                if (deducedTypeDict[tpar.NameHash] == null)
                                {
                                    add = templateParamDeduction.Handle(tpar, null);
                                    if (!add)
                                    {
                                        if (hasNonFinalArgs)
                                        {
                                            deducedTypeDict[tpar] = new TemplateParameterSymbol(tpar, null);
                                            add = true;
                                        }
                                        else
                                            break;
                                    }
                                }
                            }
                        }

                        if (add && (deducedTypeDict.AllParamatersSatisfied || hasNonFinalArgs))
                        {
                            ms.DeducedTypes = deducedTypeDict.ToReadonly();
                            var pop = ctxt.ScopedBlock != dm;
                            if(pop)
                                ctxt.PushNewScope(dm);
                            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);

                            var bt=ms.Base ?? TypeDeclarationResolver.GetMethodReturnType(dm, ctxt);

                            if(pop)
                                ctxt.Pop();
                            else
                                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);

                            if(eval || !returnBaseTypeOnly)
                                argTypeFilteredOverloads.Add(ms.Base == null ? new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) : ms);
                            else
                                argTypeFilteredOverloads.Add(bt);
                        }
                    }
                }
                else if(ov is DelegateType)
                {
                    var dg = (DelegateType)ov;
                    var bt = TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                    //TODO: Param-Arg check

                    if (!eval || returnBaseTypeOnly)
                        argTypeFilteredOverloads.Add(bt);
                    else
                        argTypeFilteredOverloads.Add(new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters));
                }
            }
            #endregion

            if (eval)
            {
                // Convert ISemantic[] to ISymbolValue[]
                var args = new List<ISymbolValue>(callArguments.Count);

                foreach (var a in callArguments)
                    args.Add(a as ISymbolValue);

                // Execute/Evaluate the variable contents etc.
                return TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads.ToArray(), call.PostfixForeExpression, true, args.ToArray());
            }
            else
            {
                // Check if one overload remains and return that one.
                ctxt.CheckForSingleResult(argTypeFilteredOverloads.ToArray(), call);
                return argTypeFilteredOverloads.Count != 0 ? argTypeFilteredOverloads[0] : null;
            }
        }
コード例 #22
0
        void GetRawCallOverloads(PostfixExpression_MethodCall call, 
			out AbstractType[] baseExpression, 
			out ISymbolValue baseValue, 
			out TemplateInstanceExpression tix)
        {
            baseExpression = null;
            baseValue = null;
            tix = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = E(pac, null, false, false);

                if (vs != null && vs.Length != 0)
                {
                    if (vs[0] is ISymbolValue)
                    {
                        baseValue = (ISymbolValue)vs[0];
                        baseExpression = new[] { baseValue.RepresentedType };
                    }
                    else if (vs[0] is InternalOverloadValue)
                        baseExpression = ((InternalOverloadValue)vs[0]).Overloads;
                    else
                        baseExpression = TypeDeclarationResolver.Convert(vs);
                }
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                    baseExpression = GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                else if (eval)
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                        baseValue = E(tix = call.PostfixForeExpression as TemplateInstanceExpression, false) as ISymbolValue;
                    else if (call.PostfixForeExpression is IdentifierExpression)
                        baseValue = E((IdentifierExpression)call.PostfixForeExpression, false) as ISymbolValue;
                    else
                        baseValue = E(call.PostfixForeExpression) as ISymbolValue;

                    if (baseValue is InternalOverloadValue)
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    else if (baseValue != null)
                        baseExpression = new[] { baseValue.RepresentedType };
                    else baseExpression = null;
                }
                else
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                        baseExpression = GetOverloads(tix = (TemplateInstanceExpression)call.PostfixForeExpression, null, false);
                    else if (call.PostfixForeExpression is IdentifierExpression)
                        baseExpression = GetOverloads(call.PostfixForeExpression as IdentifierExpression, deduceParameters:false);
                    else
                        baseExpression = new[] { AbstractType.Get(E(call.PostfixForeExpression)) };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
コード例 #23
0
        ISemantic E(PostfixExpression_MethodCall call, bool returnBaseTypeOnly = true)
        {
            // Deduce template parameters later on
            AbstractType[]             baseExpression = null;
            ISymbolValue               baseValue      = null;
            TemplateInstanceExpression tix            = null;
            bool isUFCSFunction = false;

            GetRawCallOverloads(call, out baseExpression, out baseValue, out tix, out isUFCSFunction);

            var methodOverloads = new List <AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true;             //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable <AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression);
            var nextResults = new List <AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (eval)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else
                                {
                                    throw new EvaluationException(call, "Variable must be a delegate, not anything else", mr);
                                }
                            }
                            else
                            {
                                var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt));

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    //TODO: Ensure that there's no further overload - inform the user elsewise

                                    if (returnBaseTypeOnly)
                                    {
                                        return(bt);
                                    }
                                    else
                                    {
                                        return(new MemberSymbol(mr.Definition, bt, mr.DeclarationOrExpressionBase));
                                    }
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var dg = (DelegateType)b;

                        /*
                         * int a = delegate(x) { return x*2; } (12); // a is 24 after execution
                         * auto dg=delegate(x) {return x*3;};
                         * int b = dg(4);
                         */

                        if (dg.IsFunctionLiteral)
                        {
                            methodOverloads.Add(dg);
                        }
                        else
                        {
                            // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method.
                            if (eval)
                            {
                                throw new EvaluationException(call, "TODO", dg);
                            }
                            //TODO
                            //if(returnBaseTypeOnly)
                            //TODO: Check for multiple definitions. Also, make a parameter-argument check to inform the user about wrong arguments.
                            return(dg);
                        }
                    }
                    else if (b is ClassType)
                    {
                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = ((ClassType)b).Definition;

                        if (classDef == null)
                        {
                            continue;
                        }

                        foreach (var i in classDef)
                        {
                            if (i.Name == "opCall" && i is DMethod && (!requireStaticItems || (i as DNode).IsStatic))
                            {
                                methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);
                            }
                        }
                    }

                    /*
                     * Every struct can contain a default ctor:
                     *
                     * struct S { int a; bool b; }
                     *
                     * auto s = S(1,true); -- ok
                     * auto s2= new S(2,false); -- error, no constructor found!
                     */
                    else if (b is StructType && methodOverloads.Count == 0)
                    {
                        //TODO: Deduce parameters
                        return(b);
                    }

                    /*
                     * If the overload is a template, it quite exclusively means that we'll handle a method that is the only
                     * child inside a template + that is named as the template.
                     */
                    else if (b is TemplateType &&
                             ImplicitTemplateProperties.ContainsEquallyNamedChildrenOnly(((TemplateType)b).Definition))
                    {
                        methodOverloads.Add(b);
                    }
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
            {
                return(null);
            }

            // Get all arguments' types
            var callArguments = new List <ISemantic>();

            // If it's sure that we got a ufcs call here, add the base expression's type as first argument type
            if (isUFCSFunction)
            {
                callArguments.Add(eval ? (ISemantic)baseValue : ((MemberSymbol)baseExpression[0]).Base);
            }

            if (call.Arguments != null)
            {
                foreach (var arg in call.Arguments)
                {
                    callArguments.Add(E(arg));
                }
            }

            #region Deduce template parameters and filter out unmatching overloads
            // First add optionally given template params
            // http://dlang.org/template.html#function-templates
            var tplParamDeductionArguments = tix == null ?
                                             new List <ISemantic>() :
                                             TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);

            // Then add the arguments[' member types]
            foreach (var arg in callArguments)
            {
                if (arg is VariableValue)
                {
                    tplParamDeductionArguments.Add(ValueProvider[((VariableValue)arg).Variable]);
                }
                else if (arg is AbstractType)
                {
                    tplParamDeductionArguments.Add(DResolver.StripMemberSymbols((AbstractType)arg));
                }
                else
                {
                    tplParamDeductionArguments.Add(arg);
                }
            }

            var templateParamFilteredOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(
                methodOverloads,
                tplParamDeductionArguments.Count > 0 ? tplParamDeductionArguments.ToArray() : null,
                true, ctxt);
            #endregion

            #region Filter by parameter-argument comparison
            var argTypeFilteredOverloads = new List <AbstractType>();

            if (templateParamFilteredOverloads != null)
            {
                foreach (var ov in templateParamFilteredOverloads)
                {
                    if (ov is MemberSymbol)
                    {
                        var  ms  = (MemberSymbol)ov;
                        var  dm  = ms.Definition as DMethod;
                        bool add = false;

                        if (dm != null)
                        {
                            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);

                            add = false;

                            if (callArguments.Count == 0 && dm.Parameters.Count == 0)
                            {
                                add = true;
                            }
                            else
                            {
                                for (int i = 0; i < dm.Parameters.Count; i++)
                                {
                                    var paramType = TypeDeclarationResolver.ResolveSingle(dm.Parameters[i].Type, ctxt);

                                    // TODO: Expression tuples & variable argument lengths
                                    if (i >= callArguments.Count ||
                                        !ResultComparer.IsImplicitlyConvertible(callArguments[i], paramType, ctxt))
                                    {
                                        continue;
                                    }

                                    add = true;
                                }
                            }

                            if (add)
                            {
                                var bt = ms.Base ?? TypeDeclarationResolver.GetMethodReturnType(dm, ctxt);

                                if (returnBaseTypeOnly)
                                {
                                    argTypeFilteredOverloads.Add(bt);
                                }
                                else
                                {
                                    argTypeFilteredOverloads.Add(ms.Base == null ? new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) : ms);
                                }
                            }

                            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);
                        }
                    }
                    else if (ov is DelegateType)
                    {
                        var dg = (DelegateType)ov;
                        var bt = TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                        //TODO: Param-Arg check
                        if (returnBaseTypeOnly)
                        {
                            argTypeFilteredOverloads.Add(bt);
                        }
                        else
                        {
                            argTypeFilteredOverloads.Add(new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters));
                        }
                    }
                }
            }
            #endregion

            if (eval)
            {
                // Convert ISemantic[] to ISymbolValue[]
                var args = new List <ISymbolValue>(callArguments.Count);

                foreach (var a in callArguments)
                {
                    args.Add(a as ISymbolValue);
                }

                // Execute/Evaluate the variable contents etc.
                return(TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads.ToArray(), call.PostfixForeExpression, true, args.ToArray()));
            }
            else
            {
                // Check if one overload remains and return that one.
                ctxt.CheckForSingleResult(argTypeFilteredOverloads.ToArray(), call);
                return(argTypeFilteredOverloads != null && argTypeFilteredOverloads.Count != 0 ?
                       argTypeFilteredOverloads[0] : null);
            }
        }