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); }
/// <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); }
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 }
//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 } } } } } }
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; }
/// <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; }
/// <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); }