Пример #1
0
        ISemantic E(ArrayLiteralExpression arr)
        {
            if (eval)
            {
                var elements = new List <ISymbolValue>(arr.Elements.Count);

                //ISSUE: Type-check each item to distinguish not matching items
                foreach (var e in arr.Elements)
                {
                    elements.Add(E(e) as ISymbolValue);
                }

                if (elements.Count == 0)
                {
                    EvalError(arr, "Array literal must contain at least one element.");
                    return(null);
                }

                return(new ArrayValue(new ArrayType(elements[0].RepresentedType, arr), elements.ToArray()));
            }

            if (arr.Elements != null && arr.Elements.Count > 0)
            {
                // Simply resolve the first element's type and take it as the array's value type
                var valueType = AbstractType.Get(E(arr.Elements[0]));

                return(new ArrayType(valueType, arr));
            }

            ctxt.LogError(arr, "Array literal must contain at least one element.");
            return(null);
        }
Пример #2
0
        public AbstractType TryDeduce(DSymbol ds, IEnumerable <ISemantic> templateArguments, ref INode returnedNode)
        {
            var cls = ds as ClassType;

            if (cls == null || templateArguments == null)
            {
                return(null);
            }

            var en = templateArguments.GetEnumerator();

            if (!en.MoveNext())
            {
                return(null);
            }

            returnedNode = cls.Definition;
            var baseClass = DResolver.StripMemberSymbols(AbstractType.Get(en.Current)) as TemplateIntermediateType;

            if (baseClass == null)
            {
                return(ds);
            }

            return(new ClassType(cls.Definition, ds.DeclarationOrExpressionBase, baseClass as ClassType, baseClass is InterfaceType ? new[] { baseClass as InterfaceType } : null, ds.DeducedTypes));
        }
Пример #3
0
        ISemantic E(CastExpression ce)
        {
            AbstractType castedType = null;

            if (ce.Type != null)
            {
                var castedTypes = TypeDeclarationResolver.Resolve(ce.Type, ctxt);

                ctxt.CheckForSingleResult(castedTypes, ce.Type);

                if (castedTypes != null && castedTypes.Length != 0)
                {
                    castedType = castedTypes[0];
                }
            }
            else
            {
                castedType = AbstractType.Get(E(ce.UnaryExpression));

                if (castedType != null && ce.CastParamTokens != null && ce.CastParamTokens.Length > 0)
                {
                    //TODO: Wrap resolved type with member function attributes
                }
            }

            return(castedType);
        }
        bool HandleDecl(TemplateTypeParameter p, IdentifierDeclaration id, ISemantic r)
        {
            // Bottom-level reached
            if (id.InnerDeclaration == null && Contains(id.IdHash) && !id.ModuleScoped)
            {
                // Associate template param with r
                return(Set((p != null && id.IdHash == p.NameHash) ? p : null, r, id.IdHash));
            }

            var deducee = DResolver.StripMemberSymbols(AbstractType.Get(r)) as DSymbol;

            if (id.InnerDeclaration != null && deducee != null && deducee.Definition.NameHash == id.IdHash)
            {
                var physicalParentType = TypeDeclarationResolver.HandleNodeMatch(deducee.Definition.Parent, ctxt, null, id.InnerDeclaration);
                if (HandleDecl(p, id.InnerDeclaration, physicalParentType))
                {
                    if (Contains(id.IdHash))
                    {
                        Set((p != null && id.IdHash == p.NameHash) ? p : null, deducee, id.IdHash);
                    }
                    return(true);
                }
            }

            /*
             * If not stand-alone identifier or is not required as template param, resolve the id and compare it against r
             */
            var _r = TypeDeclarationResolver.ResolveSingle(id, ctxt);

            return(_r != null && (EnforceTypeEqualityWhenDeducing ?
                                  ResultComparer.IsEqual(r, _r) :
                                  ResultComparer.IsImplicitlyConvertible(r, _r)));
        }
Пример #5
0
        public static DNode GetResultMember(ISemantic res, bool keepAliases = false)
        {
            var t = AbstractType.Get(res);

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

            if (keepAliases)
            {
                var aliasTag = t.Tag as TypeResolution.TypeDeclarationResolver.AliasTag;
                if (aliasTag != null &&
                    (!(aliasTag.aliasDefinition is ImportSymbolAlias) ||                     // Only if the import symbol alias definition was selected, go to its base
                     (aliasTag.typeBase != null && aliasTag.aliasDefinition.NameLocation != aliasTag.typeBase.Location)))
                {
                    return(aliasTag.aliasDefinition);
                }
            }

            if (t is DSymbol)
            {
                return(((DSymbol)res).Definition);
            }

            return(null);
        }
Пример #6
0
        ISemantic E(AssocArrayExpression aa)
        {
            if (eval)
            {
                var elements = new List <KeyValuePair <ISymbolValue, ISymbolValue> >();

                foreach (var e in aa.Elements)
                {
                    var keyVal = E(e.Key) as ISymbolValue;
                    var valVal = E(e.Value) as ISymbolValue;

                    elements.Add(new KeyValuePair <ISymbolValue, ISymbolValue>(keyVal, valVal));
                }

                return(new AssociativeArrayValue(new AssocArrayType(elements[0].Value.RepresentedType, elements[0].Key.RepresentedType, aa), elements));
            }

            if (aa.Elements != null && aa.Elements.Count > 0)
            {
                var firstElement      = aa.Elements[0].Key;
                var firstElementValue = aa.Elements[0].Value;

                var keyType   = AbstractType.Get(E(firstElement));
                var valueType = AbstractType.Get(E(firstElementValue));

                return(new AssocArrayType(valueType, keyType, aa));
            }

            return(null);
        }
        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);
        }
Пример #8
0
        /// <summary>
        /// Returns false if the item has already been set before and if the already set item is not equal to 'r'.
        /// Inserts 'r' into the target dictionary and returns true otherwise.
        /// </summary>
        bool Set(TemplateParameter p, ISemantic r, int nameHash)
        {
            if (p == null)
            {
                if (nameHash != 0 && TargetDictionary.ExpectedParameters != null)
                {
                    foreach (var tpar in TargetDictionary.ExpectedParameters)
                    {
                        if (tpar.NameHash == nameHash)
                        {
                            p = tpar;
                            break;
                        }
                    }
                }
            }

            if (p == null)
            {
                ctxt.LogError(null, "no fitting template parameter found!");
                return(false);
            }

            // void call(T)(T t) {}
            // call(myA) -- T is *not* myA but A, so only assign myA's type to T.
            if (p is TemplateTypeParameter)
            {
                var newR = Resolver.TypeResolution.DResolver.StripMemberSymbols(AbstractType.Get(r));
                if (newR != null)
                {
                    r = newR;
                }
            }

            TemplateParameterSymbol rl;

            if (!TargetDictionary.TryGetValue(p, out rl) || rl == null)
            {
                TargetDictionary[p] = new TemplateParameterSymbol(p, r);
                return(true);
            }
            else
            {
                if (ResultComparer.IsEqual(rl.Base, r))
                {
                    TargetDictionary[p] = new TemplateParameterSymbol(p, r);
                    return(true);
                }
                else if (rl == null)
                {
                    TargetDictionary[p] = new TemplateParameterSymbol(p, r);
                }

                // Error: Ambiguous assignment

                return(false);
            }
        }
Пример #9
0
 public TemplateParameterSymbol(ITemplateParameter tp,
                                ISemantic representedTypeOrValue,
                                ISyntaxRegion originalParameterIdentifier = null,
                                DNode parentNode = null)
     : base(new TemplateParameterNode(tp) { Parent = parentNode },
            AbstractType.Get(representedTypeOrValue), originalParameterIdentifier ?? tp)
 {
     this.Parameter      = tp;
     this.ParameterValue = representedTypeOrValue as ISymbolValue;
 }
Пример #10
0
        /// <summary>
        /// Since most expressions should return a single type only, it's not needed to use this function unless you might
        /// want to pay attention on (illegal) multiple overloads.
        /// </summary>
        public static AbstractType[] EvaluateTypes(IExpression x, ResolverContextStack ctxt)
        {
            var t = new Evaluation(ctxt).E(x);

            if (t is InternalOverloadValue)
            {
                return(((InternalOverloadValue)t).Overloads);
            }

            return(new[] { AbstractType.Get(t) });
        }
Пример #11
0
        ISemantic E(NewExpression nex)
        {
            // http://www.d-programming-language.org/expression.html#NewExpression
            ISemantic[] possibleTypes = null;

            if (nex.Type is IdentifierDeclaration)
            {
                possibleTypes = TypeDeclarationResolver.Resolve((IdentifierDeclaration)nex.Type, ctxt, filterForTemplateArgs: false);
            }
            else
            {
                possibleTypes = TypeDeclarationResolver.Resolve(nex.Type, ctxt);
            }

            var ctors = new Dictionary <DMethod, TemplateIntermediateType>();

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

            foreach (var t in possibleTypes)
            {
                var ct = DResolver.StripAliasSymbol(t as AbstractType) as TemplateIntermediateType;
                if (ct != null &&
                    !ct.Definition.ContainsAttribute(DTokens.Abstract))
                {
                    foreach (var ctor in GetConstructors(ct))
                    {
                        ctors.Add(ctor, ct);
                    }
                }
            }

            MemberSymbol finalCtor = null;

            var kvArray = ctors.ToArray();

            /*
             * TODO: Determine argument types and filter out ctor overloads.
             */

            if (kvArray.Length != 0)
            {
                finalCtor = new MemberSymbol(kvArray[0].Key, kvArray[0].Value, nex);
            }
            else if (possibleTypes.Length != 0)
            {
                return(AbstractType.Get(possibleTypes[0]));
            }

            return(finalCtor);
        }
Пример #12
0
        ISemantic E(UnaryExpression_And x)
        {
            var ptrBase = E(x.UnaryExpression);

            if (eval)
            {
                // Create a new pointer
                //
            }

            // &i -- makes an int* out of an int
            return(new PointerType(AbstractType.Get(ptrBase), x));
        }
Пример #13
0
        public static AbstractType EvaluateType(IExpression x, ResolutionContext ctxt)
        {
            var       ev = new Evaluation(ctxt);
            ISemantic t  = null;

            if (!Debugger.IsAttached)
            {
                try { t = ev.E(x); }
                catch { }
            }
            else
            {
                t = ev.E(x);
            }

            return(AbstractType.Get(t));
        }
Пример #14
0
        public static AbstractType Resolve(ArrayDecl ad, ResolutionContext ctxt)
        {
            var valueTypes = Resolve(ad.ValueType, ctxt);

            ctxt.CheckForSingleResult(valueTypes, ad);

            AbstractType valueType        = null;
            AbstractType keyType          = null;
            int          fixedArrayLength = -1;

            if (valueTypes != null && valueTypes.Length != 0)
            {
                valueType = valueTypes[0];
            }

            ISymbolValue val;

            keyType = ResolveKey(ad, out fixedArrayLength, out val, ctxt);

            if (keyType == null || (keyType is PrimitiveType &&
                                    ((PrimitiveType)keyType).TypeToken == DTokens.Int))
            {
                if (fixedArrayLength >= 0)
                {
                    // D Magic: One might access tuple items directly in the pseudo array declaration - so stuff like Tup[0] i; becomes e.g. int i;
                    var dtup = DResolver.StripMemberSymbols(valueType) as DTuple;
                    if (dtup == null)
                    {
                        return(new ArrayType(valueType, fixedArrayLength, ad));
                    }

                    if (dtup.Items != null && fixedArrayLength < dtup.Items.Length)
                    {
                        return(AbstractType.Get(dtup.Items [fixedArrayLength]));
                    }
                    else
                    {
                        ctxt.LogError(ad, "TypeTuple only consists of " + (dtup.Items != null ? dtup.Items.Length : 0) + " items. Can't access item at index " + fixedArrayLength);
                        return(null);
                    }
                }
                return(new ArrayType(valueType, ad));
            }

            return(new AssocArrayType(valueType, keyType, ad));
        }
Пример #15
0
        bool HandleDecl(TemplateTypeParameter p, ITypeDeclaration td, ISemantic rr)
        {
            if (td is IdentifierDeclaration)
            {
                return(HandleDecl(p, (IdentifierDeclaration)td, rr));
            }

            //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, at as AssocArrayType));
            }
            else if (td is DTokenDeclaration)
            {
                return(HandleDecl((DTokenDeclaration)td, at));
            }
            else if (td is DelegateDeclaration)
            {
                return(HandleDecl(p, (DelegateDeclaration)td, at as DelegateType));
            }
            else if (td is PointerDecl)
            {
                return(HandleDecl(p, (PointerDecl)td, 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);
        }
Пример #16
0
        /// <summary>
        /// Since most expressions should return a single type only, it's not needed to use this function unless you might
        /// want to pay attention on (illegal) multiple overloads.
        /// </summary>
        public static AbstractType[] EvaluateTypes(IExpression x, ResolutionContext ctxt)
        {
            var       ev = new Evaluation(ctxt);
            ISemantic t  = null;

            if (!Debugger.IsAttached)
            {
                try { t = ev.E(x); }
                catch { }
            }
            else
            {
                t = ev.E(x);
            }

            if (t is InternalOverloadValue)
            {
                return(((InternalOverloadValue)t).Overloads);
            }

            return(t == null ? null : new[] { AbstractType.Get(t) });
        }
        /// <summary>
        /// Returns all constructors from the given class or struct.
        /// If no explicit constructor given, an artificial implicit constructor method stub will be created.
        /// </summary>
        public static IEnumerable <DMethod> GetConstructors(TemplateIntermediateType ct)
        {
            bool foundExplicitCtor = false;

            // Simply get all constructors that have the ctor id assigned. Makin' it faster ;)
            var ch = ct.Definition[DMethod.ConstructorIdentifier];

            if (ch != null)
            {
                foreach (var m in ch)
                {
                    // Not to forget: 'this' aliases are also possible - so keep checking for m being a genuine ctor
                    var dm = m as DMethod;
                    if (m != null && dm.SpecialType == DMethod.MethodType.Constructor)
                    {
                        yield return(dm);

                        foundExplicitCtor = true;
                    }
                }
            }

            if (!foundExplicitCtor)
            {
                yield return new DMethod(DMethod.MethodType.Constructor)
                       {
                           Name = DMethod.ConstructorIdentifier, Parent = ct.Definition, Description = "Default constructor for " + ct.Name
                       }
            }
            ;
        }

        ISemantic E(CastExpression ce)
        {
            AbstractType castedType = null;

            if (ce.Type != null)
            {
                var castedTypes = TypeDeclarationResolver.Resolve(ce.Type, ctxt);

                ctxt.CheckForSingleResult(castedTypes, ce.Type);

                if (castedTypes != null && castedTypes.Length != 0)
                {
                    castedType = castedTypes[0];
                }
            }
            else
            {
                castedType = AbstractType.Get(E(ce.UnaryExpression));

                if (castedType != null && ce.CastParamTokens != null && ce.CastParamTokens.Length > 0)
                {
                    //TODO: Wrap resolved type with member function attributes
                }
            }

            return(castedType);
        }

        ISemantic E(UnaryExpression_Cat x)         // a = ~b;
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Increment x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Decrement x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Add x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Sub x)
        {
            var v = E(x.UnaryExpression);

            if (eval)
            {
                if (v is AbstractType)
                {
                    v = DResolver.StripMemberSymbols((AbstractType)v);
                }

                if (v is PrimitiveValue)
                {
                    var pv = (PrimitiveValue)v;

                    return(new PrimitiveValue(pv.BaseTypeToken, -pv.Value, x, -pv.ImaginaryPart));
                }
            }

            return(v);
        }

        ISemantic E(UnaryExpression_Not x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Mul x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_And x)
        {
            var ptrBase = E(x.UnaryExpression);

            if (eval)
            {
                // Create a new pointer
                //
            }

            // &i -- makes an int* out of an int
            return(new PointerType(AbstractType.Get(ptrBase), x));
        }

        ISemantic E(DeleteExpression x)
        {
            if (eval)
            {
                // Reset the content of the variable
            }

            return(null);
        }

        ISemantic E(UnaryExpression_Type x)
        {
            var uat = x as UnaryExpression_Type;

            if (uat.Type == null)
            {
                return(null);
            }

            var types = TypeDeclarationResolver.Resolve(uat.Type, ctxt);

            ctxt.CheckForSingleResult(types, uat.Type);

            if (types != null && types.Length != 0)
            {
                var id = new IdentifierDeclaration(uat.AccessIdentifier)
                {
                    EndLocation = uat.EndLocation
                };

                // First off, try to resolve static properties
                var statProp = StaticPropertyResolver.TryResolveStaticProperties(types[0], uat.AccessIdentifier, ctxt, eval, id);

                if (statProp != null)
                {
                    return(statProp);
                }

                // If it's not the case, try the conservative way
                var res = TypeDeclarationResolver.Resolve(id, ctxt, types);

                ctxt.CheckForSingleResult(res, x);

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

            return(null);
        }
    }
Пример #18
0
        public AbstractType TryDeduce(DSymbol ds, IEnumerable <ISemantic> templateArguments, ref INode n)
        {
            TemplateTypeParameter tp;
            var t = ds as TemplateType;

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

            var orig        = ds.Definition;
            var tupleStruct = new DClassLike(DTokens.Struct)
            {
                NameHash     = ds.NameHash,
                Parent       = orig.Parent,
                Location     = orig.Location,
                EndLocation  = orig.EndLocation,
                NameLocation = orig.NameLocation
            };

            var ded = new Templates.DeducedTypeDictionary(tupleStruct);

            if (templateArguments != null)
            {
                var typeList = new List <AbstractType>();

                var en = templateArguments.GetEnumerator();
                if (en.MoveNext())
                {
                    var next = en.Current;
                    int i    = 0;
                    for (; ; i++)
                    {
                        var fieldType = AbstractType.Get(next);

                        if (fieldType == null)
                        {
                            break;
                        }

                        fieldType.NonStaticAccess = true;

                        typeList.Add(fieldType);

                        if (!en.MoveNext())
                        {
                            break;
                        }

                        next = en.Current;

                        if (next is ArrayValue && (next as ArrayValue).IsString)
                        {
                            var name = (next as ArrayValue).StringValue;
                            var templateParamName = "_" + i.ToString();
                            tp      = new TemplateTypeParameter(templateParamName, CodeLocation.Empty, tupleStruct);
                            ded[tp] = new TemplateParameterSymbol(tp, fieldType);

                            tupleStruct.Add(new DVariable {
                                Name = name, Type = new IdentifierDeclaration(templateParamName)
                            });

                            if (!en.MoveNext())
                            {
                                break;
                            }

                            next = en.Current;
                        }
                    }
                }

                var tupleName = "Types";
                tp      = new TemplateTypeParameter(tupleName, CodeLocation.Empty, tupleStruct);
                ded[tp] = new TemplateParameterSymbol(tp, new DTuple(null, typeList));

                tupleStruct.Add(new DVariable {
                    NameHash = DVariable.AliasThisIdentifierHash, IsAlias = true, IsAliasThis = true, Type = new IdentifierDeclaration(tupleName)
                });
            }

            n = tupleStruct;
            return(new StructType(tupleStruct, ds.DeclarationOrExpressionBase, ded.Count != 0 ? ded.Values : null));

            //TODO: Ensure renaming and other AST-based things run properly
        }
Пример #19
0
 public static AbstractType EvaluateType(IExpression x, ResolverContextStack ctxt)
 {
     return(AbstractType.Get(new Evaluation(ctxt).E(x)));
 }
Пример #20
0
        public AbstractType TryDeduce(DSymbol ds, IEnumerable <ISemantic> templateArguments, ref INode n)
        {
            TemplateTypeParameter tp;
            var t = ds as TemplateType;

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

            var orig        = ds.Definition;
            var tupleStruct = new DClassLike(DTokens.Struct)
            {
                NameHash     = ds.NameHash,
                Parent       = orig.Parent,
                Location     = orig.Location,
                EndLocation  = orig.EndLocation,
                NameLocation = orig.NameLocation
            };

            var ded = new Templates.DeducedTypeDictionary(tupleStruct);

            var sb = new StringBuilder();

            if (templateArguments != null)
            {
                var en = templateArguments.GetEnumerator();
                if (en.MoveNext())
                {
                    var next = en.Current;
                    int i    = 0;
                    for (; ; i++)
                    {
                        var fieldType = AbstractType.Get(next);

                        if (fieldType == null)
                        {
                            break;
                        }

                        fieldType.NonStaticAccess = true;

                        if (!en.MoveNext())
                        {
                            break;
                        }

                        next = en.Current;

                        if (next is ArrayValue && (next as ArrayValue).IsString)
                        {
                            var name = (next as ArrayValue).StringValue;
                            if (!string.IsNullOrWhiteSpace(name))
                            {
                                var templateParamName = "_" + i.ToString();
                                tp      = new TemplateTypeParameter(templateParamName, CodeLocation.Empty, tupleStruct);
                                ded[tp] = new TemplateParameterSymbol(tp, fieldType);

                                // getter
                                sb.Append("@property @safe ").Append(templateParamName).Append(' ').Append(name).AppendLine("() pure nothrow const {}");
                                // setter
                                sb.Append("@property @safe void ").Append(name).AppendLine("(").Append(templateParamName).AppendLine(" v) pure nothrow {}");
                                // constants
                                sb.Append("enum ").Append(templateParamName).Append(" ").Append(name).Append("_min = cast(").Append(templateParamName).AppendLine(") 0;");
                                sb.Append("enum ").Append(templateParamName).Append(" ").Append(name).Append("_max = cast(").Append(templateParamName).AppendLine(") 0;");
                            }
                            if (!en.MoveNext())
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }

                        if (!en.MoveNext())                         // Skip offset
                        {
                            break;
                        }

                        next = en.Current;
                    }
                }

                tupleStruct.Add(new DVariable {
                    NameHash   = tupleStruct.NameHash,
                    Attributes = new List <DAttribute> {
                        new Modifier(DTokens.Enum)
                    },
                    Initializer = new IdentifierExpression(sb.ToString(), LiteralFormat.StringLiteral, LiteralSubformat.Utf8)
                });
            }

            n = tupleStruct;
            return(new TemplateType(tupleStruct, ds.DeclarationOrExpressionBase, ded.Count != 0 ? ded.Values : null));
        }
Пример #21
0
        /// <summary>
        /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b).
        /// if <param name="EvalAndFilterOverloads"></param> is false.
        /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned
        /// which stores the return value of the property function b that is executed without arguments.
        /// Also handles UFCS - so if filtering is wanted, the function becom
        /// </summary>
        ISemantic[] E(PostfixExpression_Access acc,
                      ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true)
        {
            if (acc == null)
            {
                return(null);
            }

            var baseExpression = resultBase ?? E(acc.PostfixForeExpression);

            if (acc.AccessExpression is NewExpression)
            {
                /*
                 * This can be both a normal new-Expression as well as an anonymous class declaration!
                 */
                //TODO!
                return(null);
            }


            AbstractType[] overloads;
            var            optBackup = ctxt.CurrentContext.ContextDependentOptions;

            if (acc.AccessExpression is TemplateInstanceExpression)
            {
                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                var tix = (TemplateInstanceExpression)acc.AccessExpression;
                // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments!
                overloads = GetOverloads(tix, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }

            else if (acc.AccessExpression is IdentifierExpression)
            {
                var id = acc.AccessExpression as IdentifierExpression;

                if (eval && EvalAndFilterOverloads && resultBase != null)
                {
                    var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, resultBase, id.ValueStringHash);
                    if (staticPropResult != null)
                    {
                        return new[] { staticPropResult }
                    }
                    ;
                }

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id.ValueStringHash, new[] { AbstractType.Get(baseExpression) }, ctxt, acc.AccessExpression);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }
            else
            {
                if (eval)
                {
                    EvalError(acc, "Invalid access expression");
                    return(null);
                }
                ctxt.LogError(acc, "Invalid post-dot expression");
                return(null);
            }

            /*
             * Try to get ufcs functions at first!
             *
             * void foo(int i) {}
             *
             * class A
             * {
             *	void foo(int i, int a) {}
             *
             *	void bar(){
             *		123.foo(23); // Not allowed!
             *		// Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels,
             *		// it would return the local foo() only, not the global one..which would be an error then!
             *  }
             *
             * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones?
             * }
             */
            if (overloads == null || EvalAndFilterOverloads)
            {
                var oo = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[];

                if (oo != null)
                {
                    int overloadsLength = overloads == null ? 0 : overloads.Length;
                    var newArr          = new AbstractType[overloadsLength + oo.Length];
                    if (overloadsLength != 0)
                    {
                        overloads.CopyTo(newArr, 0);
                    }
                    oo.CopyTo(newArr, overloadsLength);
                    overloads = newArr;
                }
            }

            // If evaluation active and the access expression is stand-alone, return a single item only.
            if (EvalAndFilterOverloads && eval)
            {
                return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) }
            }
            ;

            return(overloads);
        }

        ISemantic E(PostfixExpression_Index x, ISemantic foreExpression)
        {
            if (eval)
            {
                //TODO: Access pointer arrays(?)

                if (foreExpression is ArrayValue)                 // ArrayValue must be checked first due to inheritance!
                {
                    var av = foreExpression as ArrayValue;

                    // Make $ operand available
                    var arrLen_Backup = ValueProvider.CurrentArrayLength;
                    ValueProvider.CurrentArrayLength = av.Elements.Length;

                    var n = E(x.Arguments[0]) as PrimitiveValue;

                    ValueProvider.CurrentArrayLength = arrLen_Backup;

                    if (n == null)
                    {
                        EvalError(x.Arguments[0], "Returned no value");
                        return(null);
                    }

                    int i = 0;
                    try{
                        i = Convert.ToInt32(n.Value);
                    }
                    catch
                    {
                        EvalError(x.Arguments[0], "Index expression must be of type int");
                        return(null);
                    }

                    if (i < 0 || i > av.Elements.Length)
                    {
                        EvalError(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);
                        return(null);
                    }

                    return(av.Elements[i]);
                }
                else if (foreExpression is AssociativeArrayValue)
                {
                    var aa = (AssociativeArrayValue)foreExpression;

                    var key = E(x.Arguments[0]);

                    if (key == null)
                    {
                        EvalError(x.Arguments[0], "Returned no value");
                        return(null);
                    }

                    ISymbolValue val = null;

                    foreach (var kv in aa.Elements)
                    {
                        if (kv.Key.Equals(key))
                        {
                            return(kv.Value);
                        }
                    }

                    EvalError(x, "Could not find key '" + val + "'");
                    return(null);
                }

                EvalError(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);

                return(null);
            }
            else
            {
                foreExpression = DResolver.StripMemberSymbols(AbstractType.Get(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

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

                /*
                 * int* a = new int[10];
                 *
                 * a[0] = 12;
                 */
                else if (foreExpression is PointerType)
                {
                    return((foreExpression as PointerType).Base);
                }
                //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 = EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue;

                        if (idx == null || !DTokens.BasicTypes_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 ||
                                 (int)idx.Value < 0)
                        {
                            ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length);
                        }
                        else
                        {
                            return(tt.Items[(int)idx.Value]);
                        }
                    }
                }

                ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression"));
            }

            return(null);
        }

        ISemantic E(PostfixExpression_Slice x, ISemantic foreExpression)
        {
            if (!eval)
            {
                return(foreExpression);                // Still of the array's type.
            }
            if (!(foreExpression is ArrayValue))
            {
                EvalError(x.PostfixForeExpression, "Must be an array");
                return(null);
            }

            var ar = (ArrayValue)foreExpression;
            var sl = (PostfixExpression_Slice)x;

            // If the [ ] form is used, the slice is of the entire array.
            if (sl.FromExpression == null && sl.ToExpression == null)
            {
                return(foreExpression);
            }

            // Make $ operand available
            var arrLen_Backup = ValueProvider.CurrentArrayLength;

            ValueProvider.CurrentArrayLength = ar.Elements.Length;

            var bound_lower = E(sl.FromExpression) as PrimitiveValue;
            var bound_upper = E(sl.ToExpression) as PrimitiveValue;

            ValueProvider.CurrentArrayLength = arrLen_Backup;

            if (bound_lower == null || bound_upper == null)
            {
                EvalError(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type");
                return(null);
            }

            int lower = -1, upper = -1;

            try
            {
                lower = Convert.ToInt32(bound_lower.Value);
                upper = Convert.ToInt32(bound_upper.Value);
            }
            catch { EvalError(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type");
                    return(null); }

            if (lower < 0)
            {
                EvalError(sl.FromExpression, "Lower boundary must be greater than 0"); return(null);
            }
            if (lower >= ar.Elements.Length)
            {
                EvalError(sl.FromExpression, "Lower boundary must be smaller than " + ar.Elements.Length); return(null);
            }
            if (upper < lower)
            {
                EvalError(sl.ToExpression, "Upper boundary must be greater than " + lower); return(null);
            }
            if (upper >= ar.Elements.Length)
            {
                EvalError(sl.ToExpression, "Upper boundary must be smaller than " + ar.Elements.Length); return(null);
            }


            var rawArraySlice = new ISymbolValue[upper - lower];
            int j             = 0;

            for (int i = lower; i < upper; i++)
            {
                rawArraySlice[j++] = ar.Elements[i];
            }

            return(new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice));
        }

        ISemantic E(PostfixExpression_Increment x, ISemantic foreExpression)
        {
            // myInt++ is still of type 'int'
            if (!eval)
            {
                return(foreExpression);
            }

            if (resolveConstOnly)
            {
                EvalError(new NoConstException(x));
            }
            // Must be implemented anyway regarding ctfe
            return(null);
        }

        ISemantic E(PostfixExpression_Decrement x, ISemantic foreExpression)
        {
            if (!eval)
            {
                return(foreExpression);
            }

            if (resolveConstOnly)
            {
                EvalError(new NoConstException(x));
            }
            // Must be implemented anyway regarding ctfe
            return(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((IdentifierExpression)call.PostfixForeExpression, false);
                    }
                    else
                    {
                        baseExpression = new[] { AbstractType.Get(E(call.PostfixForeExpression)) }
                    };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
        bool Handle(TemplateAliasParameter p, ISemantic arg)
        {
            #region Handle parameter defaults
            if (arg == null)
            {
                if (p.DefaultExpression != null)
                {
                    var eval = Evaluation.EvaluateValue(p.DefaultExpression, ctxt);

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

                    return(Set(p, eval, 0));
                }
                else if (p.DefaultType != null)
                {
                    var res = TypeDeclarationResolver.Resolve(p.DefaultType, ctxt);

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

                    bool ret = false;
                    foreach (var r in res)
                    {
                        if (!Set(p, r, 0))
                        {
                            ret = true;
                        }
                    }

                    if (ret)
                    {
                        return(false);
                    }
                }
                return(false);
            }
            #endregion

            #region Given argument must be a symbol - so no built-in type but a reference to a node or an expression
            var t = AbstractType.Get(arg);

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

            if (!(t is DSymbol))
            {
                while (t != null)
                {
                    if (t is PrimitiveType)                     // arg must not base on a primitive type.
                    {
                        return(false);
                    }

                    if (t is DerivedDataType)
                    {
                        t = ((DerivedDataType)t).Base;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            #endregion

            #region Specialization check
            if (p.SpecializationExpression != null)
            {
                // LANGUAGE ISSUE: Can't do anything here - dmd won't let you use MyClass!(2) though you have class MyClass(alias X:2)
                return(false);
            }
            else if (p.SpecializationType != null)
            {
                // ditto
                return(false);
            }
            #endregion

            return(Set(p, arg, 0));
        }
Пример #24
0
 public TemplateParameterSymbol(TemplateParameterNode tpn, ISemantic typeOrValue, ISyntaxRegion paramIdentifier = null)
     : base(tpn, AbstractType.Get(typeOrValue), paramIdentifier)
 {
     this.Parameter      = tpn.TemplateParameter;
     this.ParameterValue = typeOrValue as ISymbolValue;
 }
        internal static bool TryHandleMethodArgumentTuple(ResolutionContext ctxt, ref bool add,
                                                          List <ISemantic> callArguments,
                                                          DMethod dm,
                                                          DeducedTypeDictionary deducedTypeDict, int currentParameter, ref int currentArg)
        {
            // .. so only check if it's an identifer & if the id represents a tuple parameter
            var id                 = dm.Parameters[currentParameter].Type as IdentifierDeclaration;
            var curNode            = dm as DNode;
            TemplateParameter tpar = null;

            while (curNode != null && !curNode.TryGetTemplateParameter(id.IdHash, out tpar))
            {
                curNode = curNode.Parent as DNode;
            }

            if (!(tpar is TemplateTupleParameter))
            {
                return(false);
            }

            int lastArgumentToTake = -1;

            /*
             * Note: an expression tuple parameter can occur also somewhere in between the parameter list!
             * void write(A...)(bool b, A a, double d) {}
             *
             * can be matched by
             * write(true, 1.2) as well as
             * write(true, "asdf", 1.2) as well as
             * write(true, 123, true, 'c', [3,4,5], 3.4) !
             */

            TemplateParameterSymbol tps;
            DTuple tuple = null;

            if (deducedTypeDict.TryGetValue(tpar, out tps) && tps != null)
            {
                if (tps.Base is DTuple)
                {
                    tuple = tps.Base as DTuple;
                    lastArgumentToTake = currentParameter + (tuple.Items == null ? 0 : (tuple.Items.Length - 1));
                }
                else
                {
                    // Error: Type param must be tuple!
                }
            }
            // - Get the (amount of) arguments that shall be put into the tuple
            else if (currentParameter == dm.Parameters.Count - 1)
            {
                // The usual case: A tuple of a variable length is put at the end of a parameter list..
                // take all arguments from i until the end of the argument list..
                // ; Also accept empty tuples
                lastArgumentToTake = callArguments.Count - 1;
            }
            else
            {
                // Get the type of the next expected parameter
                var nextExpectedParameter = DResolver.StripMemberSymbols(TypeDeclarationResolver.ResolveSingle(dm.Parameters[currentParameter + 1].Type, ctxt));

                // Look for the first argument whose type is equal to the next parameter's type..
                for (int k = currentArg; k < callArguments.Count; k++)
                {
                    if (ResultComparer.IsEqual(AbstractType.Get(callArguments[k]), nextExpectedParameter))
                    {
                        // .. and assume the tuple to go from i to the previous argument..
                        lastArgumentToTake = k - 1;
                        break;
                    }
                }
            }

            int argCountToHandle = lastArgumentToTake - currentArg + 1;

            if (tuple != null)
            {
                // - If there's been set an explicit type tuple, compare all arguments' types with those in the tuple
                if (tuple.Items != null)
                {
                    foreach (ISemantic item in tuple.Items)
                    {
                        if (currentArg >= callArguments.Count || !ResultComparer.IsImplicitlyConvertible(callArguments[currentArg++], AbstractType.Get(item), ctxt))
                        {
                            add = false;
                            return(true);
                        }
                    }
                }
            }
            else
            {
                // - If there was no explicit initialization, put all arguments' types into a type tuple
                var argsToTake = new ISemantic[argCountToHandle];
                callArguments.CopyTo(currentArg, argsToTake, 0, argsToTake.Length);
                currentArg += argsToTake.Length;
                var tt = new DTuple(null, argsToTake);
                tps = new TemplateParameterSymbol(tpar, tt);

                //   and set the actual template tuple parameter deduction
                deducedTypeDict[tpar] = tps;
            }
            add = true;
            return(true);
        }
Пример #26
0
        /// <summary>
        /// Used for searching further identifier list parts.
        ///
        /// a.b -- nextIdentifier would be 'b' whereas <param name="resultBases">resultBases</param> contained the resolution result for 'a'
        /// </summary>
        public static AbstractType[] ResolveFurtherTypeIdentifier(string nextIdentifier,
                                                                  IEnumerable <AbstractType> resultBases,
                                                                  ResolverContextStack ctxt,
                                                                  object typeIdObject = null)
        {
            if ((resultBases = DResolver.StripAliasSymbols(resultBases)) == null)
            {
                return(null);
            }

            var r = new List <AbstractType>();

            var nextResults = new List <AbstractType>();

            foreach (var b in resultBases)
            {
                IEnumerable <AbstractType> scanResults = new[] { b };

                do
                {
                    foreach (var scanResult in scanResults)
                    {
                        // First filter out all alias and member results..so that there will be only (Static-)Type or Module results left..
                        if (scanResult is MemberSymbol)
                        {
                            var mr = (MemberSymbol)scanResult;

                            if (mr.Base != null)
                            {
                                nextResults.Add(mr.Base);
                            }
                        }

                        else if (scanResult is UserDefinedType)
                        {
                            var udt         = (UserDefinedType)scanResult;
                            var bn          = udt.Definition as IBlockNode;
                            var nodeMatches = NameScan.ScanNodeForIdentifier(bn, nextIdentifier, ctxt);

                            ctxt.PushNewScope(bn);
                            ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt);

                            var results = HandleNodeMatches(nodeMatches, ctxt, b, typeIdObject);

                            if (results != null)
                            {
                                foreach (var res in results)
                                {
                                    r.Add(AbstractType.Get(res));
                                }
                            }

                            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
                            ctxt.Pop();
                        }
                        else if (scanResult is PackageSymbol)
                        {
                            var pack = ((PackageSymbol)scanResult).Package;

                            IAbstractSyntaxTree accessedModule = null;
                            if (pack.Modules.TryGetValue(nextIdentifier, out accessedModule))
                            {
                                r.Add(new ModuleSymbol(accessedModule as DModule, typeIdObject as ISyntaxRegion, (PackageSymbol)scanResult));
                            }
                            else if (pack.Packages.TryGetValue(nextIdentifier, out pack))
                            {
                                r.Add(new PackageSymbol(pack, typeIdObject as ISyntaxRegion));
                            }
                        }
                        else if (scanResult is ModuleSymbol)
                        {
                            var modRes = (ModuleSymbol)scanResult;

                            var matches = NameScan.ScanNodeForIdentifier(modRes.Definition, nextIdentifier, ctxt);

                            var results = HandleNodeMatches(matches, ctxt, b, typeIdObject);

                            if (results != null)
                            {
                                foreach (var res in results)
                                {
                                    r.Add(AbstractType.Get(res));
                                }
                            }
                        }
                    }

                    scanResults = DResolver.FilterOutByResultPriority(ctxt, nextResults);
                    nextResults = new List <AbstractType>();
                }while (scanResults != null);
            }

            return(r.Count == 0 ? null : r.ToArray());
        }
        /// <summary>
        /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b).
        /// if <param name="EvalAndFilterOverloads"></param> is false.
        /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned
        /// which stores the return value of the property function b that is executed without arguments.
        /// Also handles UFCS - so if filtering is wanted, the function becom
        /// </summary>
        public static R[] EvalPostfixAccessExpression <R>(ExpressionVisitor <R> vis, ResolutionContext ctxt, PostfixExpression_Access acc,
                                                          ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true, AbstractSymbolValueProvider ValueProvider = null)
            where R : class, ISemantic
        {
            if (acc == null)
            {
                return(null);
            }

            var baseExpression = resultBase ?? (acc.PostfixForeExpression != null ? acc.PostfixForeExpression.Accept(vis) as ISemantic : null);

            if (acc.AccessExpression is NewExpression)
            {
                /*
                 * This can be both a normal new-Expression as well as an anonymous class declaration!
                 */
                //TODO!
                return(null);
            }


            AbstractType[] overloads;
            var            optBackup = ctxt.CurrentContext.ContextDependentOptions;

            if (acc.AccessExpression is TemplateInstanceExpression)
            {
                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                var tix = (TemplateInstanceExpression)acc.AccessExpression;
                // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments!
                overloads = ExpressionTypeEvaluation.GetOverloads(tix, ctxt, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }

            else if (acc.AccessExpression is IdentifierExpression)
            {
                var id = acc.AccessExpression as IdentifierExpression;

                if (ValueProvider != null && EvalAndFilterOverloads && baseExpression != null)
                {
                    var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, baseExpression, id.ValueStringHash);
                    if (staticPropResult != null)
                    {
                        return new[] { (R)staticPropResult }
                    }
                    ;
                }

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                overloads = ExpressionTypeEvaluation.GetOverloads(id, ctxt, AmbiguousType.TryDissolve(AbstractType.Get(baseExpression)), EvalAndFilterOverloads);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }
            else
            {            /*
                          *     if (eval){
                          *             EvalError(acc, "Invalid access expression");
                          *             return null;
                          *     }*/
                ctxt.LogError(acc, "Invalid post-dot expression");
                return(null);
            }

            // If evaluation active and the access expression is stand-alone, return a single item only.
            if (EvalAndFilterOverloads && ValueProvider != null)
            {
                return new[] { (R) new Evaluation(ValueProvider).TryDoCTFEOrGetValueRefs(AmbiguousType.Get(overloads, acc.AccessExpression), acc.AccessExpression) }
            }
            ;

            return(overloads as R[]);
        }

        ISymbolValue EvalForeExpression(PostfixExpression ex)
        {
            return(ex.PostfixForeExpression != null?ex.PostfixForeExpression.Accept(this) : null);
        }
Пример #28
0
        /// <summary>
        /// Tries to resolve a static property's name.
        /// Returns a result describing the theoretical member (".init"-%gt;MemberResult; ".typeof"-&gt;TypeResult etc).
        /// Returns null if nothing was found.
        /// </summary>
        /// <param name="InitialResult"></param>
        /// <returns></returns>
        public static MemberSymbol TryResolveStaticProperties(
            ISemantic InitialResult,
            string propertyIdentifier,
            ResolverContextStack ctxt          = null,
            bool Evaluate                      = false,
            IdentifierDeclaration idContainter = null)
        {
            // If a pointer'ed type is given, take its base type
            if (InitialResult is PointerType)
            {
                InitialResult = ((PointerType)InitialResult).Base;
            }

            if (InitialResult == null || InitialResult is ModuleSymbol)
            {
                return(null);
            }

            INode relatedNode = null;

            if (InitialResult is DSymbol)
            {
                relatedNode = ((DSymbol)InitialResult).Definition;
            }

            #region init
            if (propertyIdentifier == "init")
            {
                var prop_Init = new DVariable
                {
                    Name        = "init",
                    Description = "Initializer"
                };

                if (relatedNode != null)
                {
                    if (!(relatedNode is DVariable))
                    {
                        prop_Init.Parent = relatedNode.Parent;
                        prop_Init.Type   = new IdentifierDeclaration(relatedNode.Name);
                    }
                    else
                    {
                        prop_Init.Parent      = relatedNode;
                        prop_Init.Initializer = (relatedNode as DVariable).Initializer;
                        prop_Init.Type        = relatedNode.Type;
                    }
                }

                return(new MemberSymbol(prop_Init, DResolver.StripAliasSymbol(AbstractType.Get(InitialResult)), idContainter));
            }
            #endregion

            #region sizeof
            if (propertyIdentifier == "sizeof")
            {
                return(new MemberSymbol(new DVariable
                {
                    Name = "sizeof",
                    Type = new DTokenDeclaration(DTokens.Int),
                    Initializer = new IdentifierExpression(4),
                    Description = "Size in bytes (equivalent to C's sizeof(type))"
                }, new PrimitiveType(DTokens.Int), idContainter));
            }
            #endregion

            #region alignof
            if (propertyIdentifier == "alignof")
            {
                return(new MemberSymbol(new DVariable
                {
                    Name = "alignof",
                    Type = new DTokenDeclaration(DTokens.Int),
                    Description = "Alignment size"
                }, new PrimitiveType(DTokens.Int), idContainter));
            }
            #endregion

            #region mangleof
            if (propertyIdentifier == "mangleof")
            {
                return(new MemberSymbol(new DVariable
                {
                    Name = "mangleof",
                    Type = new IdentifierDeclaration("string"),
                    Description = "String representing the ‘mangled’ representation of the type"
                }, getStringType(ctxt), idContainter));
            }
            #endregion

            #region stringof
            if (propertyIdentifier == "stringof")
            {
                return(new MemberSymbol(new DVariable
                {
                    Name = "stringof",
                    Type = new IdentifierDeclaration("string"),
                    Description = "String representing the source representation of the type"
                }, getStringType(ctxt), idContainter));
            }
            #endregion

            #region classinfo
            else if (propertyIdentifier == "classinfo")
            {
                var tr = DResolver.StripMemberSymbols(AbstractType.Get(InitialResult)) as TemplateIntermediateType;

                if (tr is ClassType || tr is InterfaceType)
                {
                    var ci = new IdentifierDeclaration("TypeInfo_Class")
                    {
                        InnerDeclaration        = new IdentifierDeclaration("object"),
                        ExpressesVariableAccess = true,
                    };

                    var ti = TypeDeclarationResolver.Resolve(ci, ctxt);

                    ctxt.CheckForSingleResult(ti, ci);

                    return(new MemberSymbol(new DVariable {
                        Name = "classinfo", Type = ci
                    }, ti != null && ti.Length != 0?ti[0]:null, idContainter));
                }
            }
            #endregion

            //TODO: Resolve the types of type-specific properties (floats, ints, arrays, assocarrays etc.)

            return(null);
        }