public static void AddArrayProperties(ISemantic rr, ICompletionDataGenerator cdg, ArrayDecl ArrayDecl = null)
        {
            CreateArtificialProperties(ArrayProps, cdg, ArrayDecl);

            cdg.Add(new DVariable
            {
                Name = "ptr",
                Description = "Returns pointer to the array",
                Type = new PointerDecl(ArrayDecl == null ? new DTokenDeclaration(DTokens.Void) : ArrayDecl.ValueType)
            });
        }
        public virtual void Visit(ArrayDecl td)
        {
            VisitInner(td);

            if (td.KeyType != null)
            {
                td.KeyType.Accept(this);
            }

            if (td.KeyExpression != null)
            {
                td.KeyExpression.Accept(this);
            }

            // ValueType == InnerDeclaration
        }
        public ObjectValue Resolve(ulong offset, string symbolname, string typename, string val, DEW.DebugScopedSymbol parentsymbol)
        {
            DModule module;
            int codeLine;
            INode variableNode = null;

            // Search currently scoped module
            string file = "";
            uint line = 0;
            Engine.Symbols.GetLineByOffset(Engine.CurrentInstructionOffset, out file, out line);
            codeLine = (int)line;

            if (string.IsNullOrWhiteSpace(file))
                return null;

            AbstractDProject dproj = null;
            module = GetFileSyntaxTree(file, out dproj);

            // If syntax tree built, search the variable location
            if (module != null)
            {
                var ed = Resolver.DResolverWrapper.CreateEditorData(IdeApp.Workbench.ActiveDocument);
                var ctxt = ResolutionContext.Create(ed, false);

                CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () =>
                    {
                        ctxt.Push(module, new CodeLocation(0, codeLine));

                        AbstractType[] res;
                        if (parentsymbol != null)
                        {
                            var parentres = ResolveParentSymbol(parentsymbol, ctxt);
                            res = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(symbolname, parentres, ctxt, null);
                        }
                        else
                        {
                            res = TypeDeclarationResolver.ResolveIdentifier(symbolname, ctxt, null);
                        }

                        if (res != null && res.Length > 0 && res[0] is DSymbol)
                        {
                            variableNode = (res[0] as DSymbol).Definition;
                        }
                    });
            }

            // Set type string
            string _typeString = typename;
            if (variableNode != null)
            {
                var t = variableNode.Type;
                if (t != null)
                    _typeString = t.ToString();
            }

            // Set value string
            string _valueString = val;

            ObjectValueFlags flags = ObjectValueFlags.Variable;

            if (variableNode != null)
            {
                ITypeDeclaration curValueType = variableNode.Type;
                if (curValueType != null)
                {
                    if (!IsBasicType(curValueType))
                    {
                        if (_typeString == "string") //TODO: Replace this by searching the alias definition in the cache
                            curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Char) };
                        else if (_typeString == "wstring")
                            curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Wchar) };
                        else if (_typeString == "dstring")
                            curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Dchar) };

                        if (IsArray(curValueType))
                        {
                            flags = ObjectValueFlags.Array;

                            var clampDecl = curValueType as ArrayDecl;
                            var valueType = clampDecl.InnerDeclaration;

                            if (valueType is DTokenDeclaration)
                            {
                                bool IsString = false;
                                uint elsz = 0;
                                var realType = DetermineArrayType((valueType as DTokenDeclaration).Token, out elsz, out IsString);

                                var arr = Engine.Symbols.ReadArray(offset, realType, elsz);

                                if (arr != null)
                                    _valueString = BuildArrayContentString(arr, IsString);

                            }
                        }
                        else
                        {
                            flags = ObjectValueFlags.Object;
                        }
                    }
                }
            }

            return ObjectValue.CreatePrimitive(ObjectValueSource, new ObjectPath(symbolname), _typeString, new EvaluationResult(_valueString), flags);
        }
        bool HandleDecl(TemplateTypeParameter parameterRef,ArrayDecl arrayDeclToCheckAgainst, AssocArrayType argumentArrayType)
        {
            if (argumentArrayType == null)
                return false;

            // Handle key type
            if((arrayDeclToCheckAgainst.KeyType != null || arrayDeclToCheckAgainst.KeyExpression!=null) && argumentArrayType.KeyType == null)
                return false;
            bool result = false;

            if (arrayDeclToCheckAgainst.KeyExpression != null)
            {
                // Remove all surrounding parentheses from the expression
                var x_param = arrayDeclToCheckAgainst.KeyExpression;

                while(x_param is SurroundingParenthesesExpression)
                    x_param = ((SurroundingParenthesesExpression)x_param).Expression;

                var ad_Argument = argumentArrayType.DeclarationOrExpressionBase as ArrayDecl;

                /*
                 * This might be critical:
                 * the [n] part in class myClass(T:char[n], int n) {}
                 * will be seen as an identifier expression, not as an identifier declaration.
                 * So in the case the parameter expression is an identifier,
                 * test if it's part of the parameter list
                 */
                var id = x_param as IdentifierExpression;
                if(id!=null && id.IsIdentifier && Contains(id.ValueStringHash))
                {
                    // If an expression (the usual case) has been passed as argument, evaluate its value, otherwise is its type already resolved.
                    ISemantic finalArg = null;

                    if (ad_Argument != null && ad_Argument.KeyExpression != null)
                    {
                        ISymbolValue val = null;
                        int len = -1;
                        finalArg = TypeDeclarationResolver.ResolveKey(ad_Argument, out len, out val, ctxt);
                        if (val != null)
                            finalArg = val;
                    }
                    else
                        finalArg = argumentArrayType.KeyType;

                    //TODO: Do a type convertability check between the param type and the given argument's type.
                    // The affected parameter must also be a value parameter then, if an expression was given.

                    // and handle it as if it was an identifier declaration..
                    result = Set(parameterRef, finalArg, id.ValueStringHash);
                }
                else if (ad_Argument != null && ad_Argument.KeyExpression != null)
                {
                    // Just test for equality of the argument and parameter expression, e.g. if both param and arg are 123, the result will be true.
                    result = SymbolValueComparer.IsEqual(arrayDeclToCheckAgainst.KeyExpression, ad_Argument.KeyExpression, new StandardValueProvider(ctxt));
                }
            }
            else if (arrayDeclToCheckAgainst.KeyType != null)
            {
                // If the array we're passing to the decl check that is static (i.e. has a constant number as key 'type'),
                // pass that number instead of type 'int' to the check.
                var at = argumentArrayType as ArrayType;
                if (argumentArrayType != null && at != null && at.IsStaticArray)
                    result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType,
                        new PrimitiveValue(D_Parser.Parser.DTokens.Int, (decimal)at.FixedLength, null));
                else
                    result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType);
            }

            // Handle inner type
            return result && HandleDecl(parameterRef,arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base);
        }
        public static void AddAssocArrayProperties(ISemantic rr, ICompletionDataGenerator cdg, ArrayDecl ad)
        {
            var ll = new List<INode>();

            /*ll.Add(new DVariable()
            {
                Name = "sizeof",
                Description = "Returns the size of the reference to the associative array; it is typically 8.",
                Type = new IdentifierDeclaration("size_t"),
                Initializer = new IdentifierExpression(8, LiteralFormat.Scalar)
            });*/

            ll.Add(new DVariable() {
                Name="length",
                Description="Returns number of values in the associative array. Unlike for dynamic arrays, it is read-only.",
                Type = new IdentifierDeclaration("size_t"),
                Initializer= ad!=null? ad.KeyExpression : null
            });

            if (ad != null)
            {
                ll.Add(new DVariable()
                {
                    Name = "keys",
                    Description = "Returns dynamic array, the elements of which are the keys in the associative array.",
                    Type = new ArrayDecl() { ValueType = ad.KeyType }
                });

                ll.Add(new DVariable()
                {
                    Name = "values",
                    Description = "Returns dynamic array, the elements of which are the values in the associative array.",
                    Type = new ArrayDecl() { ValueType = ad.ValueType }
                });

                ll.Add(new DVariable()
                {
                    Name = "rehash",
                    Description = "Reorganizes the associative array in place so that lookups are more efficient. rehash is effective when, for example, the program is done loading up a symbol table and now needs fast lookups in it. Returns a reference to the reorganized array.",
                    Type = ad
                });

                ll.Add(new DVariable()
                {
                    Name = "byKey",
                    Description = "Returns a delegate suitable for use as an Aggregate to a ForeachStatement which will iterate over the keys of the associative array.",
                    Type = new DelegateDeclaration() { ReturnType = new ArrayDecl() { ValueType = ad.KeyType } }
                });

                ll.Add(new DVariable()
                {
                    Name = "byValue",
                    Description = "Returns a delegate suitable for use as an Aggregate to a ForeachStatement which will iterate over the values of the associative array.",
                    Type = new DelegateDeclaration() { ReturnType = new ArrayDecl() { ValueType = ad.ValueType } }
                });

                ll.Add(new DMethod()
                {
                    Name = "get",
                    Description = "Looks up key; if it exists returns corresponding value else evaluates and returns defaultValue.",
                    Type = ad.ValueType,
                    Parameters = new List<INode> {
                        new DVariable(){
                            Name="key",
                            Type=ad.KeyType
                        },
                        new DVariable(){
                            Name="defaultValue",
                            Type=ad.ValueType,
                            Attributes=new List<DAttribute>{ new DAttribute(DTokens.Lazy)}
                        }
                    }
                });
            }

            foreach (var prop in ll)
                cdg.Add(prop);
        }
示例#6
0
        /// <summary>
        /// Note:
        /// http://www.digitalmars.com/d/2.0/declaration.html#DeclaratorSuffix
        /// The definition of a sequence of declarator suffixes is buggy here! Theoretically template parameters can be declared without a surrounding ( and )!
        /// Also, more than one parameter sequences are possible!
        /// 
        /// TemplateParameterList[opt] Parameters MemberFunctionAttributes[opt]
        /// </summary>
        void DeclaratorSuffixes(DNode dn)
        {
            FunctionAttributes(ref dn.Attributes);

            while (laKind == (OpenSquareBracket))
            {
                Step();
                var ad = new ArrayDecl() { Location=t.Location,InnerDeclaration = dn.Type };

                if (laKind != (CloseSquareBracket))
                {
                    ad.ClampsEmpty = false;
                    ITypeDeclaration keyType=null;
                    Lexer.PushLookAheadBackup();
                    if (!IsAssignExpression())
                    {
                        var weakType = AllowWeakTypeParsing;
                        AllowWeakTypeParsing = true;

                        keyType= ad.KeyType = Type();

                        AllowWeakTypeParsing = weakType;
                    }
                    if (keyType == null || laKind != CloseSquareBracket)
                    {
                        Lexer.RestoreLookAheadBackup();
                        keyType = ad.KeyType = null;
                        ad.KeyExpression = AssignExpression();
                    }
                    else
                        Lexer.PopLookAheadBackup();
                }
                Expect(CloseSquareBracket);
                ad.EndLocation = t.EndLocation;
                dn.Type = ad;
            }

            if (laKind == (OpenParenthesis))
            {
                if (IsTemplateParameterList())
                {
                    TemplateParameterList(dn);
                }
                var dm = dn as DMethod;
                if(dm != null)
                    dm.Parameters = Parameters(dm);
            }

            FunctionAttributes(ref dn.Attributes);
        }
示例#7
0
        ITypeDeclaration BasicType2()
        {
            // *
            if (laKind == (Times))
            {
                Step();
                return new PointerDecl() { Location=t.Location, EndLocation=t.EndLocation };
            }

            // [ ... ]
            else if (laKind == (OpenSquareBracket))
            {
                var startLoc = la.Location;
                Step();
                // [ ]
                if (laKind == (CloseSquareBracket))
                {
                    Step();
                    return new ArrayDecl() { Location=startLoc, EndLocation=t.EndLocation };
                }

                ITypeDeclaration cd = null;

                // [ Type ]
                Lexer.PushLookAheadBackup();
                bool weaktype = AllowWeakTypeParsing;
                AllowWeakTypeParsing = true;

                var keyType = Type();

                AllowWeakTypeParsing = weaktype;

                if (keyType != null && laKind == CloseSquareBracket && !(keyType is IdentifierDeclaration))
                {
                    //HACK: Both new int[size_t] as well as new int[someConstNumber] are legal. So better treat them as expressions.
                    cd = new ArrayDecl() { KeyType = keyType, ClampsEmpty = false, Location = startLoc };
                    Lexer.PopLookAheadBackup();
                }
                else
                {
                    Lexer.RestoreLookAheadBackup();

                    var fromExpression = AssignExpression();

                    // [ AssignExpression .. AssignExpression ]
                    if (laKind == DoubleDot)
                    {
                        Step();
                        cd = new ArrayDecl() {
                            Location=startLoc,
                            ClampsEmpty=false,
                            KeyType=null,
                            KeyExpression= new PostfixExpression_Slice() {
                                FromExpression=fromExpression,
                                ToExpression=AssignExpression()}};
                    }
                    else
                        cd = new ArrayDecl() { KeyType=null, KeyExpression=fromExpression,ClampsEmpty=false,Location=startLoc };
                }

                if ((AllowWeakTypeParsing && laKind != CloseSquareBracket) || IsEOF)
                    return null;

                Expect(CloseSquareBracket);
                if(cd!=null)
                    cd.EndLocation = t.EndLocation;
                return cd;
            }

            // delegate | function
            else if (laKind == (Delegate) || laKind == (Function))
            {
                Step();
                var dd = new DelegateDeclaration() { Location=t.Location};
                dd.IsFunction = t.Kind == Function;

                if (AllowWeakTypeParsing && laKind != OpenParenthesis)
                    return null;

                dd.Parameters = Parameters(null);

                var attributes = new List<DAttribute>();
                FunctionAttributes(ref attributes);
                dd.Modifiers= attributes.Count > 0 ? attributes.ToArray() : null;

                dd.EndLocation = t.EndLocation;
                return dd;
            }
            else
                SynErr(Identifier);
            return null;
        }
        public virtual void Visit(ArrayDecl td)
        {
            VisitInner(td);

            if (td.KeyType != null)
                td.KeyType.Accept(this);

            if (td.KeyExpression != null)
                td.KeyExpression.Accept(this);

            // ValueType == InnerDeclaration
        }
示例#9
0
            //INode typeNode;
            //IEnumerable<IAbstractSyntaxTree> moduleCache;
            public DDebugSymbolWrapper(DebugScopedSymbol sym, DDebugSupport support)
                : base(sym)
            {
                this.supp = support;
                try
                {
                    /*var ci=CoreManager.DebugManagement.Engine.Symbols.GetPointerTarget(sym.Offset);
                    object mo = null;
                    IntPtr moPtr = new IntPtr();
                    var raw = CoreManager.DebugManagement.Engine.Memory.ReadVirtual(ci, 4);
                    Marshal.StructureToPtr(raw, moPtr, false);
                    mo = Marshal.PtrToStructure(moPtr, typeof(DObject));*/
                }
                catch { }

                // Search currently scoped module
                string file = "";
                uint line = 0;
                CoreManager.DebugManagement.Engine.Symbols.GetLineByOffset(CoreManager.DebugManagement.Engine.CurrentInstructionOffset,out file,out line);
                codeLine = (int)line;

                if (string.IsNullOrWhiteSpace(file))
                    return;

                // If file name found, get syntax tree, as far as possible
                DProject ownerPrj=null;
                module = DLanguageBinding.GetFileSyntaxTree(file,out ownerPrj);

                // If syntax tree built, search the variable location
                if (module != null)
                {
                    IStatement stmt = null;
                    var block = DResolver.SearchBlockAt(module, new CodeLocation(0, codeLine),out stmt);

                    var ctxt=ResolutionContext.Create(null, null, block);

                    var res = TypeDeclarationResolver.ResolveIdentifier(Symbol.Name,ctxt, null);

                    if (res!=null && res.Length > 0 && res[0] is DSymbol)
                    {
                        variableNode = ((DSymbol)res[0]).Definition;
                        //moduleCache = DCodeCompletionSupport.Instance.EnumAvailableModules(ownerPrj);
                    }
                }

                // Set type string
                _typeString= base.TypeString;
                if (variableNode != null)
                {
                    var t = variableNode.Type;
                    if (t != null)
                        _typeString= t.ToString();
                }

                // Set value string
                if (_typeString.StartsWith("class "))
                {
                    _valueString = base.ValueString;

                    //CodeInjection.WriteObjectVariable(supp.hProcess, supp.varAddr, (uint)sym.Offset);

                    //_valueString = CodeInjection.EvaluateObjectString(supp.hProcess, supp.toStringFunc, supp.varAddr, (uint)sym.Offset);
                    /*
                    var th = CodeInjection.BeginExecuteMethod(supp.hProcess, supp.toStringFunc);

                    CoreManager.DebugManagement.Engine.Execute("~2 g");
                    CoreManager.DebugManagement.Engine.WaitForEvent();

                    CodeInjection.WaitForExecutionEnd(th);
                    */
                    //_valueString = CodeInjection.ReadDString(supp.hProcess, supp.varAddr);
                }
                else
                {
                    _valueString=base.ValueString;

                    if (variableNode != null)
                    {
                        ITypeDeclaration curValueType = variableNode.Type;
                        if (curValueType != null)
                        {
                            if (!IsBasicType(curValueType))
                            {
                                if (TypeString == "string") //TODO: Replace this by searching the alias definition in the cache
                                    curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Char) };
                                else if (TypeString == "wstring")
                                    curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Wchar) };
                                else if (TypeString == "dstring")
                                    curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Dchar) };

                                if (IsArray(curValueType))
                                {
                                    var clampDecl = curValueType as ArrayDecl;
                                    var valueType = clampDecl.InnerDeclaration;

                                    if (valueType is DTokenDeclaration)
                                    {
                                        bool IsString = false;
                                        uint elsz = 0;
                                        var realType = DetermineArrayType((valueType as DTokenDeclaration).Token, out elsz, out IsString);

                                        var arr = CoreManager.DebugManagement.Engine.Symbols.ReadArray(sym.Offset, realType, elsz);

                                        if (arr != null) _valueString = BuildArrayContentString(arr, IsString);
                                    }
                                }

                                else
                                {
                                    //TODO: call an object's toString method somehow to obtain its representing string manually
                                }
                            }
                        }
                    }
                }
            }
示例#10
0
        ITypeDeclaration BasicType2()
        {
            // *
            if (laKind == (Times))
            {
                Step();
                return new PointerDecl() { Location=t.Location, EndLocation=t.EndLocation };
            }

            // [ ... ]
            else if (laKind == (OpenSquareBracket))
            {
                var startLoc = la.Location;
                Step();
                // [ ]
                if (laKind == (CloseSquareBracket))
                {
                    Step();
                    return new ArrayDecl() { Location=startLoc, EndLocation=t.EndLocation };
                }

                ITypeDeclaration cd = null;

                // [ Type ]
                if (!IsAssignExpression())
                {
                    var la_backup = la;
                    bool weaktype = AllowWeakTypeParsing;
                    AllowWeakTypeParsing = true;
                    var keyType = Type();
                    AllowWeakTypeParsing = weaktype;

                    if (keyType != null && laKind == CloseSquareBracket)
                        cd = new ArrayDecl() { KeyType = keyType, Location=startLoc };
                    else
                        la = la_backup;
                }

                if(cd==null)
                {
                    var fromExpression = AssignExpression();

                    // [ AssignExpression .. AssignExpression ]
                    if (laKind == DoubleDot)
                    {
                        Step();
                        cd = new ArrayDecl() {
                            Location=startLoc
                            ,KeyExpression= new PostfixExpression_Slice() {
                                FromExpression=fromExpression,
                                ToExpression=AssignExpression()}};
                    }
                    else
                        cd = new ArrayDecl() { KeyExpression=fromExpression,Location=startLoc };
                }

                if (AllowWeakTypeParsing && laKind != CloseSquareBracket)
                    return null;

                Expect(CloseSquareBracket);
                if(cd!=null)
                    cd.EndLocation = t.EndLocation;
                return cd;
            }

            // delegate | function
            else if (laKind == (Delegate) || laKind == (Function))
            {
                Step();
                ITypeDeclaration td = null;
                var dd = new DelegateDeclaration() { Location=t.Location};
                dd.IsFunction = t.Kind == Function;

                dd.Parameters = Parameters(null);
                td = dd;
                //TODO: add attributes to declaration
                while (FunctionAttribute[laKind])
                {
                    Step();
                    td = new DTokenDeclaration(t.Kind, td) { Location=t.Location, EndLocation=t.EndLocation };
                }
                td.EndLocation = t.EndLocation;
                return td;
            }
            else
                SynErr(Identifier);
            return null;
        }
示例#11
0
        /// <summary>
        /// Note:
        /// http://www.digitalmars.com/d/2.0/declaration.html#DeclaratorSuffix
        /// The definition of a sequence of declarator suffixes is buggy here! Theoretically template parameters can be declared without a surrounding ( and )!
        /// Also, more than one parameter sequences are possible!
        /// 
        /// TemplateParameterList[opt] Parameters MemberFunctionAttributes[opt]
        /// </summary>
        ITypeDeclaration DeclaratorSuffixes(out ITemplateParameter[] TemplateParameters, out List<INode> _Parameters, List<DAttribute> _Attributes)
        {
            DAttribute attr = null;
            ITypeDeclaration td = null;
            TemplateParameters = null;
            _Parameters = null;

            while (MemberFunctionAttribute[laKind])
            {
                _Attributes.Add(attr=new DAttribute(laKind, la.Value));
                LastParsedObject = attr;
                Step();
            }

            while (laKind == (OpenSquareBracket))
            {
                Step();
                var ad = new ArrayDecl() { Location=t.Location };
                LastParsedObject = ad;
                ad.InnerDeclaration = td;
                if (laKind != (CloseSquareBracket))
                {
                    ad.ClampsEmpty = false;
                    ITypeDeclaration keyType=null;
                    var la_backup = la;
                    if (!IsAssignExpression())
                    {

                        var weakType = AllowWeakTypeParsing;
                        AllowWeakTypeParsing = true;

                        keyType= ad.KeyType = Type();

                        AllowWeakTypeParsing = weakType;
                    }
                    if (keyType == null || laKind != CloseSquareBracket)
                    {
                        keyType = ad.KeyType = null;
                        la = la_backup;
                        ad.KeyExpression = AssignExpression();
                    }
                }
                Expect(CloseSquareBracket);
                ad.EndLocation = t.EndLocation;
                td = ad;
            }

            if (laKind == (OpenParenthesis))
            {
                if (IsTemplateParameterList())
                {
                    TemplateParameters = TemplateParameterList();
                }
                _Parameters = Parameters(null);

                while (StorageClass[laKind] || laKind==PropertyAttribute)
                {
                    _Attributes.Add(attr=new DAttribute(laKind, la.Value));
                    LastParsedObject = attr;
                    Step();
                }
            }

            while (MemberFunctionAttribute[laKind])
            {
                _Attributes.Add(attr=new DAttribute(laKind,la.Value));
                LastParsedObject = attr;
                Step();
            }
            return td;
        }
示例#12
0
        /// <summary>
        /// Note:
        /// http://www.digitalmars.com/d/2.0/declaration.html#DeclaratorSuffix
        /// The definition of a sequence of declarator suffixes is buggy here! Theoretically template parameters can be declared without a surrounding ( and )!
        /// Also, more than one parameter sequences are possible!
        /// 
        /// TemplateParameterList[opt] Parameters MemberFunctionAttributes[opt]
        /// </summary>
        ITypeDeclaration DeclaratorSuffixes(out ITemplateParameter[] TemplateParameters, out List<INode> _Parameters, List<DAttribute> _Attributes)
        {
            ITypeDeclaration td = null;
            TemplateParameters = null;
            _Parameters = null;

            while (MemberFunctionAttribute[laKind])
            {
                _Attributes.Add(new DAttribute(laKind, la.Value));
                Step();
            }

            while (laKind == (OpenSquareBracket))
            {
                Step();
                var ad = new ArrayDecl() { Location=t.Location };
                LastParsedObject = ad;
                ad.InnerDeclaration = td;
                if (laKind != (CloseSquareBracket))
                {
                    ITypeDeclaration keyType=null;
                    if (!IsAssignExpression())
                    {
                        AllowWeakTypeParsing = true;
                        keyType= ad.KeyType = Type();
                        AllowWeakTypeParsing = false;
                    }
                    if (keyType==null)
                        ad.KeyExpression = AssignExpression();
                }
                Expect(CloseSquareBracket);
                ad.EndLocation = t.EndLocation;
                td = ad;
            }

            if (laKind == (OpenParenthesis))
            {
                if (IsTemplateParameterList())
                {
                    TemplateParameters = TemplateParameterList();
                }
                _Parameters = Parameters(null);

                //TODO: MemberFunctionAttributes -- add them to the declaration
                while (StorageClass[laKind] || laKind==PropertyAttribute)
                {
                    Step();
                }
            }

            while (MemberFunctionAttribute[laKind])
            {
                _Attributes.Add(new DAttribute(laKind,la.Value));
                Step();
            }
            return td;
        }
		bool HandleDecl(TemplateTypeParameter parameterRef,ArrayDecl arrayDeclToCheckAgainst, AssocArrayType argumentArrayType)
		{
			if (argumentArrayType == null)
				return false;

			// Handle key type
			var at = argumentArrayType as ArrayType;
			if((arrayDeclToCheckAgainst.ClampsEmpty == (at == null)) &&
				(at == null || !at.IsStaticArray || arrayDeclToCheckAgainst.KeyExpression == null))
				return false;
			
			bool result = true;

			if (arrayDeclToCheckAgainst.KeyExpression != null)
			{
				var x_param = arrayDeclToCheckAgainst.KeyExpression;

				while(x_param is SurroundingParenthesesExpression)
					x_param = ((SurroundingParenthesesExpression)x_param).Expression;
				
				/*
				 * This might be critical:
				 * the [n] part in class myClass(T:char[n], int n) {}
				 * will be seen as an identifier expression, not as an identifier declaration.
				 * So in the case the parameter expression is an identifier,
				 * test if it's part of the parameter list
				 */
				var id = x_param as IdentifierExpression;
				if (id != null && id.IsIdentifier && Contains (id.ValueStringHash)) { // Match int[5] into T[n],n - after deduction, n will be 5
					
					// If an expression (the usual case) has been passed as argument, evaluate its value, otherwise is its type already resolved.
					var finalArg = argumentArrayType is ArrayType ? (ISemantic)new PrimitiveValue ((argumentArrayType as ArrayType).FixedLength) : argumentArrayType.KeyType;

					//TODO: Do a type convertability check between the param type and the given argument's type.
					// The affected parameter must also be a value parameter then, if an expression was given.

					// and handle it as if it was an identifier declaration..
					result = Set (parameterRef, finalArg, id.ValueStringHash); 
				} else if (argumentArrayType is ArrayType) { // Match int[5] into T[5]
					// Just test for equality of the argument and parameter expression, e.g. if both param and arg are 123, the result will be true.
					result = SymbolValueComparer.IsEqual (Evaluation.EvaluateValue (arrayDeclToCheckAgainst.KeyExpression, ctxt), new PrimitiveValue ((argumentArrayType as ArrayType).FixedLength));
				} else
					result = false;
			}
			else if (arrayDeclToCheckAgainst.KeyType != null)
			{
				// If the array we're passing to the decl check that is static (i.e. has a constant number as key 'type'),
				// pass that number instead of type 'int' to the check.
				if (argumentArrayType != null && at != null && at.IsStaticArray)
					result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType,
						new PrimitiveValue(at.FixedLength)); 
				else
					result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType);
			}

			// Handle inner type
			return result && HandleDecl(parameterRef,arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base);
		}
        public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
        {
            keyVal = null;
            fixedArrayLength = -1;
            AbstractType keyType = null;

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

                    keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

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

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

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

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

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

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

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

            return keyType;
        }
        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 (fixedArrayLength < dtup.Items.Length)
                        return AbstractType.Get(dtup.Items [fixedArrayLength]);
                    else {
                        ctxt.LogError (ad, "TypeTuple only consists of " + dtup.Items.Length + " items. Can't access item at index " + fixedArrayLength);
                        return null;
                    }
                }
                return new ArrayType (valueType, ad);
            }

            return new AssocArrayType(valueType, keyType, ad);
        }
        public static AssocArrayType Resolve(ArrayDecl ad, ResolverContextStack 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)
                return null;
            valueType = valueTypes[0];

            if (ad.KeyExpression != null)
            {
                var keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

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

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

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

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

            if (keyType== null || (keyType is PrimitiveType && ((PrimitiveType)keyType).TypeToken == DTokens.Int))
                return fixedArrayLength == -1 ?
                    new ArrayType(valueType, ad) :
                    new ArrayType(valueType, fixedArrayLength, ad);

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