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]; ISymbolValue val; keyType = ResolveKey(ad, out fixedArrayLength, out val, ctxt); 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)); }
private DSDomain ArrayDeclTransfer(ArrayDecl arrayDecl, DSDomain domain) { var ident = new Identifier(arrayDecl.Name, VarType.Array, arrayDecl.Id); var newDomain = CopyDomain(domain); newDomain[ident] = DSSign.Zero.Singleton().ToHashSet(); return(newDomain); }
public override IAstNode VisitArrayDecl(MicroCParser.ArrayDeclContext context) { var label = ++_label; var name = context.IDENT().GetText(); var size = int.Parse(context.NUMBER().GetText()); var id = _symbolTable.InsertSymbol(name, VarType.Array, size); var arrayDecl = new ArrayDecl(name, size); arrayDecl.Label = label; arrayDecl.Id = id; return(arrayDecl); }
private IADomain ArrayDeclTransfer(ArrayDecl arrayDecl, IADomain domain) { var newDomain = CopyDomain(domain); if (domain.IsBottom()) { return(newDomain); } var ident = new Identifier(arrayDecl.Name, VarType.Array, arrayDecl.Id); newDomain[ident] = new Interval(new ExtendedZ(0), new ExtendedZ(0)).ToIntervalK(_program); return(newDomain); }
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)); }
public ITypeDeclaration VisitArrayAccessSymbol(ArrayAccessSymbol t) { var ad = new ArrayDecl { ValueType = AcceptType(t.Base) }; if (t.DeclarationOrExpressionBase is IExpression) { ad.KeyExpression = t.DeclarationOrExpressionBase as IExpression; } else { ad.KeyType = t.DeclarationOrExpressionBase as ITypeDeclaration; } return(ad); }
protected override ILattice <IADomain> TransferFunctions(int label) { var block = GetBlock(label); var domain = _analysisCircle[label].GetDomain(); var newDomain = block switch { IntDecl intDecl => IntDeclTransfer(intDecl, domain), ArrayDecl arrayDecl => ArrayDeclTransfer(arrayDecl, domain), RecordDecl recordDecl => RecDeclTransfer(recordDecl, domain), AssignStmt assignStmt => AssignTransfer(assignStmt, domain), RecAssignStmt recAssignStmt => RecAssignTransfer(recAssignStmt, domain), IfStmt ifStmt => IdTransfer(ifStmt, domain), IfElseStmt ifElseStmt => IdTransfer(ifElseStmt, domain), WhileStmt whileStmt => IdTransfer(whileStmt, domain), WriteStmt writeStmt => IdTransfer(writeStmt, domain), ReadStmt readStmt => ReadTransfer(readStmt, domain), _ => Bottom().GetDomain(), }; return(new IALattice(newDomain)); }
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); }
/// <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 }; LastParsedObject = ad; ad.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; var lpo = LastParsedObject; if (AllowWeakTypeParsing && laKind != OpenParenthesis) return null; dd.Parameters = Parameters(null); if (!IsEOF) LastParsedObject = lpo; 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; }
//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 } } } } } }
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; 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 { result = false; } if (!result) { return(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(D_Parser.Parser.DTokens.Int, (decimal)at.FixedLength, null)); } else { result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType); } if (!result) { return(false); } } // Handle inner type return(HandleDecl(parameterRef, arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base)); }
public ulong Visit(ArrayDecl arrayDecl) { return(1001551); }
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, () => { var loc = new CodeLocation(0, codeLine); ctxt.Push(DResolver.SearchBlockAt(module, loc), loc); 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(DSharp.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 AddArrayProperties(ResolveResult 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 static void AddAssocArrayProperties(ResolveResult 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") * });*/ 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); } }
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 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 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); }