예제 #1
0
        public static AbstractType[] GetOverloads(IdentifierExpression id, ResolutionContext ctxt, IEnumerable <AbstractType> resultBases = null, bool deduceParameters = true)
        {
            AbstractType[] res;
            if (resultBases == null)
            {
                res = TypeDeclarationResolver.ResolveIdentifier(id.ValueStringHash, ctxt, id, id.ModuleScoped);
            }
            else
            {
                res = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id.ValueStringHash, resultBases, ctxt, id);
            }

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

            var f = DResolver.FilterOutByResultPriority(ctxt, res);

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

            return((ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0 && deduceParameters?
                   TemplateInstanceHandler.DeduceParamsAndFilterOverloads(f, null, false, ctxt) :
                       f.ToArray());
        }
예제 #2
0
파일: DType.cs 프로젝트: Orvid/D_Parser
 public TemplateParameterSymbol(TemplateParameter tpn, ISemantic typeOrValue, ISyntaxRegion paramIdentifier = null)
     : base(tpn != null ? tpn.Representation : null, AbstractType.Get(typeOrValue), paramIdentifier)
 {
     IsKnowinglyUndetermined = TemplateInstanceHandler.IsNonFinalArgument(typeOrValue);
     this.Parameter          = tpn;
     this.ParameterValue     = typeOrValue as ISymbolValue;
 }
        public bool HandleDecl(TemplateTypeParameter p, ITypeDeclaration td, ISemantic rr)
        {
            if (td is IdentifierDeclaration)
            {
                return(HandleDecl(p, (IdentifierDeclaration)td, rr));
            }

            if (TemplateInstanceHandler.IsNonFinalArgument(rr))
            {
                foreach (var tp in this.TargetDictionary.Keys.ToList())
                {
                    if (TargetDictionary[tp] == null)
                    {
                        TargetDictionary[tp] = new TemplateParameterSymbol(tp, null);
                    }
                }

                return(true);
            }

            //HACK Ensure that no information gets lost by using this function
            // -- getting a value but requiring an abstract type and just extract it from the value - is this correct behaviour?
            var at = AbstractType.Get(rr);

            if (td is ArrayDecl)
            {
                return(HandleDecl(p, (ArrayDecl)td, DResolver.StripMemberSymbols(at) as AssocArrayType));
            }
            else if (td is DTokenDeclaration)
            {
                return(HandleDecl((DTokenDeclaration)td, at));
            }
            else if (td is DelegateDeclaration)
            {
                return(HandleDecl(p, (DelegateDeclaration)td, DResolver.StripMemberSymbols(at) as DelegateType));
            }
            else if (td is PointerDecl)
            {
                return(HandleDecl(p, (PointerDecl)td, DResolver.StripMemberSymbols(at) as PointerType));
            }
            else if (td is MemberFunctionAttributeDecl)
            {
                return(HandleDecl(p, (MemberFunctionAttributeDecl)td, at));
            }
            else if (td is TypeOfDeclaration)
            {
                return(HandleDecl((TypeOfDeclaration)td, at));
            }
            else if (td is VectorDeclaration)
            {
                return(HandleDecl((VectorDeclaration)td, at));
            }
            else if (td is TemplateInstanceExpression)
            {
                return(HandleDecl(p, (TemplateInstanceExpression)td, at));
            }

            return(false);
        }
예제 #4
0
        public static bool TryGetImplicitProperty(TemplateType template, ResolverContextStack ctxt, out AbstractType[] matchingChild)
        {
            // Check if there are only children that are named as the parent template.
            // That's the requirement for the special treatment.
            matchingChild = null;
            if (!ContainsEquallyNamedChildrenOnly(template.Definition))
            {
                return(false);
            }

            // Prepare a new context
            bool pop = !ctxt.NodeIsInCurrentScopeHierarchy(template.Definition);

            if (pop)
            {
                ctxt.PushNewScope(template.Definition);
            }

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

            // Get actual overloads,
            var overloads = template.Definition[template.Name];

            // resolve them
            var resolvedOverloads = TypeDeclarationResolver.HandleNodeMatches(overloads, ctxt, null, template.DeclarationOrExpressionBase);

            // and deduce their parameters whereas this time, the parent's parameter are given already, in the case it's e.g.
            // needed as return type or in a declaration condition:

            // Furthermore, pass all the arguments that have been passed to the super template, to the child,
            // so these arguments may be used again for some inner parameters.
            var args = new List <ISemantic>(template.DeducedTypes.Count);

            foreach (var kv in template.DeducedTypes)
            {
                args.Add((ISemantic)kv.Value.ParameterValue ?? kv.Value.Base);
            }

            matchingChild = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(resolvedOverloads, args, true, ctxt);

            // Undo context-related changes
            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(template);
            }

            return(matchingChild != null && matchingChild.Length == 1 && matchingChild[0] != null);
        }
예제 #5
0
        public static AbstractType[] GetOverloads(IdentifierExpression id, ResolutionContext ctxt, bool deduceParameters = true)
        {
            var raw = TypeDeclarationResolver.ResolveIdentifier(id.ValueStringHash, ctxt, id, id.ModuleScoped);
            var f   = DResolver.FilterOutByResultPriority(ctxt, raw);

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

            return((ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0 && deduceParameters?
                   TemplateInstanceHandler.DeduceParamsAndFilterOverloads(f, null, false, ctxt) :
                       f.ToArray());
        }
예제 #6
0
        public static AbstractType[] GetOverloads(TemplateInstanceExpression tix, ResolverContextStack ctxt, IEnumerable <AbstractType> resultBases = null, bool deduceParameters = true)
        {
            AbstractType[] res = null;
            if (resultBases == null)
            {
                res = TypeDeclarationResolver.ResolveIdentifier(tix.TemplateIdentifier.Id, ctxt, tix, tix.TemplateIdentifier.ModuleScoped);
            }
            else
            {
                res = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(tix.TemplateIdentifier.Id, resultBases, ctxt, tix);
            }

            return(!ctxt.Options.HasFlag(ResolutionOptions.NoTemplateParameterDeduction) && deduceParameters?
                   TemplateInstanceHandler.DeduceParamsAndFilterOverloads(res, tix, ctxt) : res);
        }
예제 #7
0
        public AbstractType Visit(PostfixExpression_Slice x)
        {
            var foreExpression = EvalForeExpression(x);

            // myArray[0]; myArray[0..5];
            if (foreExpression is MemberSymbol)
            {
                foreExpression = DResolver.StripMemberSymbols(foreExpression);
            }

            var udt = foreExpression as UserDefinedType;

            if (udt == null)
            {
                return(foreExpression);
            }

            AbstractType[] sliceArgs;
            if (x.FromExpression == null && x.ToExpression == null)
            {
                sliceArgs = null;
            }
            else
            {
                sliceArgs = new AbstractType[2];
                if (x.FromExpression != null)
                {
                    sliceArgs[0] = x.FromExpression.Accept(this);
                }
                if (x.ToExpression != null)
                {
                    sliceArgs[1] = x.ToExpression.Accept(this);
                }
            }

            ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt);

            var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(OpSliceIdHash, AmbiguousType.TryDissolve(foreExpression), ctxt, x, false);

            overloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(overloads, sliceArgs, true, ctxt);

            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
            return(TryPretendMethodExecution(AmbiguousType.Get(overloads, x), x, sliceArgs) ?? foreExpression);
        }
예제 #8
0
        public static AbstractType[] GetOverloads(TemplateInstanceExpression tix, ResolutionContext ctxt, IEnumerable <AbstractType> resultBases = null, bool deduceParameters = true)
        {
            if (resultBases == null && tix.InnerDeclaration != null)
            {
                resultBases = TypeDeclarationResolver.Resolve(tix.InnerDeclaration, ctxt);
            }

            AbstractType[] res;
            if (resultBases == null)
            {
                res = TypeDeclarationResolver.ResolveIdentifier(tix.TemplateIdHash, ctxt, tix, tix.ModuleScopedIdentifier);
            }
            else
            {
                res = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(tix.TemplateIdHash, resultBases, ctxt, tix);
            }

            return((ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0 && deduceParameters?
                   TemplateInstanceHandler.DeduceParamsAndFilterOverloads(res, tix, ctxt) : res);
        }
        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));
        }
예제 #10
0
        public AbstractType Visit(PostfixExpression_Index x)
        {
            var foreExpression = EvalForeExpression(x);

            // myArray[0]; myArray[0..5];
            // opIndex/opSlice ?
            if (foreExpression is MemberSymbol)
            {
                foreExpression = DResolver.StripMemberSymbols(foreExpression);
            }

            var udt = foreExpression as UserDefinedType;

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

                var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(OpIndexIdHash, AmbiguousType.TryDissolve(foreExpression), ctxt, x, false);
                if (overloads != null && overloads.Length > 0)
                {
                    var indexArgs = x.Arguments != null ? new AbstractType[x.Arguments.Length] : null;
                    for (int i = 0; i < indexArgs.Length; i++)
                    {
                        if (x.Arguments[i] != null)
                        {
                            indexArgs[i] = x.Arguments[i].Accept(this);
                        }
                    }

                    overloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(overloads, indexArgs, true, ctxt);
                    ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
                    return(TryPretendMethodExecution(AmbiguousType.Get(overloads, x), x, indexArgs));
                }
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);

                if (foreExpression is TemplateIntermediateType)
                {                //TODO: Proper resolution of alias this declarations
                    var tit = foreExpression as TemplateIntermediateType;
                    var ch  = tit.Definition[DVariable.AliasThisIdentifierHash];
                    if (ch != null)
                    {
                        foreach (DVariable aliasThis in ch)
                        {
                            foreExpression = TypeDeclarationResolver.HandleNodeMatch(aliasThis, ctxt, foreExpression);
                            if (foreExpression != null)
                            {
                                break;                                 // HACK: Just omit other alias this' to have a quick run-through
                            }
                        }
                    }

                    if (foreExpression == null)
                    {
                        return(tit);
                    }
                }
            }

            foreExpression = DResolver.StripMemberSymbols(foreExpression);

            if (foreExpression is AssocArrayType)
            {
                var ar = foreExpression as AssocArrayType;

                /*
                 * myType_Array[0] -- returns TypeResult myType
                 * return the value type of a given array result
                 */
                //TODO: Handle opIndex overloads
                if (ar.ValueType != null)
                {
                    ar.ValueType.NonStaticAccess = true;
                }

                return(new ArrayAccessSymbol(x, ar.ValueType));
            }

            /*
             * int* a = new int[10];
             *
             * a[0] = 12;
             */
            else if (foreExpression is PointerType)
            {
                var b = (foreExpression as PointerType).Base;
                if (b != null)
                {
                    b.NonStaticAccess = true;
                }
                return(b);
            }
            //return new ArrayAccessSymbol(x,((PointerType)foreExpression).Base);

            else if (foreExpression is DTuple)
            {
                var tt = foreExpression as DTuple;

                if (x.Arguments != null && x.Arguments.Length != 0)
                {
                    var idx = Evaluation.EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue;

                    if (tt.Items == null)
                    {
                        ctxt.LogError(tt.DeclarationOrExpressionBase, "No items in Type tuple");
                    }
                    else if (idx == null || !DTokens.IsBasicType_Integral(idx.BaseTypeToken))
                    {
                        ctxt.LogError(x.Arguments[0], "Index expression must evaluate to integer value");
                    }
                    else if (idx.Value > (decimal)Int32.MaxValue ||
                             (int)idx.Value >= tt.Items.Length || idx.Value < 0m)
                    {
                        ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length);
                    }
                    else
                    {
                        return(AbstractType.Get(tt.Items[(int)idx.Value]));
                    }
                }
            }

            ctxt.LogError(x, "No matching base type for indexing operation");
            return(null);
        }
예제 #11
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);
            }
        }
예제 #12
0
        /// <summary>
        /// Checks given results for type equality
        /// </summary>
        public static bool IsEqual(ISemantic r1, ISemantic r2)
        {
            if (r1 == r2)
            {
                return(true);
            }

            if (r1 is TemplateParameterSymbol)
            {
                var tps1 = r1 as TemplateParameterSymbol;
                var tps2 = r2 as TemplateParameterSymbol;
                if (tps2 != null && tps1.Parameter == tps2.Parameter)
                {
                    return((tps1.Base == null && tps2.Base == null) || IsEqual(tps1.Base, tps2.Base));
                }

                if (TemplateInstanceHandler.IsNonFinalArgument(r2))
                {
                    return(true);
                }
                r1 = tps1.Base;
            }
            if (r2 is TemplateParameterSymbol)
            {
                r2 = ((TemplateParameterSymbol)r2).Base;
            }

            if (r1 is ISymbolValue && r2 is ISymbolValue)
            {
                return(SymbolValueComparer.IsEqual((ISymbolValue)r1, (ISymbolValue)r2));
            }

            else if (r1 is TemplateIntermediateType && r2 is TemplateIntermediateType)
            {
                var tr1 = (TemplateIntermediateType)r1;
                var tr2 = (TemplateIntermediateType)r2;

                if (tr1.Definition != tr2.Definition)
                {
                    return(false);
                }

                //TODO: Compare deduced types
                return(true);
            }
            else if (r1 is PrimitiveType && r2 is PrimitiveType)
            {
                return(((PrimitiveType)r1).TypeToken == ((PrimitiveType)r2).TypeToken);
            }
            else if (r1 is ArrayType && r2 is ArrayType)
            {
                var ar1 = (ArrayType)r1;
                var ar2 = (ArrayType)r2;

                if (!IsEqual(ar1.KeyType, ar2.KeyType))
                {
                    return(false);
                }

                return(IsEqual(ar1.Base, ar2.Base));
            }
            else if (r1 is DelegateType && r2 is DelegateType)
            {
                var dg1 = r1 as DelegateType;
                var dg2 = r2 as DelegateType;

                if (dg1.IsFunctionLiteral != dg2.IsFunctionLiteral ||
                    !IsEqual(dg1.ReturnType, dg2.ReturnType))
                {
                    return(false);
                }

                if (dg1.Parameters == null || dg1.Parameters.Length == 0)
                {
                    return(dg2.Parameters == null || dg2.Parameters.Length == 0);
                }
                else if (dg2.Parameters == null)
                {
                    return(dg1.Parameters == null || dg1.Parameters.Length == 0);
                }
                else if (dg1.Parameters.Length == dg2.Parameters.Length)
                {
                    for (int i = dg1.Parameters.Length - 1; i != 0; i--)
                    {
                        if (!IsEqual(dg1.Parameters[i], dg2.Parameters[i]))
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            }

            //TODO: Handle other types

            return(false);
        }
예제 #13
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);
            }
        }