public static string GetResolveResultString(ResolveResult rr) { if (rr is MemberResult) return DNode.GetNodePath((rr as MemberResult).ResolvedMember, true); if (rr is TypeResult) return DNode.GetNodePath((rr as TypeResult).ResolvedTypeDefinition, true); if (rr is StaticTypeResult) return (rr as StaticTypeResult).TypeDeclarationBase.ToString(); if (rr is ModuleResult) { var mrr = rr as ModuleResult; var parts = mrr.ResolvedModule.ModuleName.Split('.'); var ret = ""; for (int i = 0; i < mrr.AlreadyTypedModuleNameParts; i++) ret += parts[i] + '.'; return ret.TrimEnd('.'); } return null; }
public static ResolveResult[] HandleNodeMatches(IEnumerable<INode> matches, ResolverContext ctxt, IBlockNode currentlyScopedNode = null, ResolveResult resultBase = null, ITypeDeclaration TypeDeclaration = null) { var rl = new List<ResolveResult>(); if (matches != null) foreach (var m in matches) { if (m == null) continue; var res = HandleNodeMatch(m, ctxt, currentlyScopedNode, resultBase, typeBase: TypeDeclaration); if (res != null) rl.Add(res); } return rl.ToArray(); }
/// <summary> /// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken). /// A class' base class will be searched. /// etc.. /// </summary> /// <returns></returns> public static ResolveResult HandleNodeMatch( INode m, ResolverContext ctxt, IBlockNode currentlyScopedNode = null, ResolveResult resultBase = null, ITypeDeclaration typeBase = null) { if (currentlyScopedNode == null) currentlyScopedNode = ctxt.ScopedBlock; stackNum_HandleNodeMatch++; //HACK: Really dirty stack overflow prevention via manually counting call depth var DoResolveBaseType = stackNum_HandleNodeMatch > 5 ? false : ctxt.ResolveBaseTypes; // Prevent infinite recursion if the type accidently equals the node's name if (m.Type != null && m.Type.ToString(false) == m.Name) DoResolveBaseType = false; if (m is DVariable) { var v = m as DVariable; var memberbaseTypes = DoResolveBaseType ? ResolveType(v.Type, ctxt, currentlyScopedNode) : null; // For auto variables, use the initializer to get its type if (memberbaseTypes == null && DoResolveBaseType && v.ContainsAttribute(DTokens.Auto) && v.Initializer != null) { var init = v.Initializer; memberbaseTypes = ResolveType(init.ExpressionTypeRepresentation, ctxt, currentlyScopedNode); } // Resolve aliases if wished if (ctxt.ResolveAliases && memberbaseTypes != null) { /* * To ensure that absolutely all kinds of alias definitions became resolved (includes aliased alias definitions!), * loop through the resolution process again, after at least one aliased type has been found. */ while (memberbaseTypes.Length > 0) { bool hadAliasResolution = false; var memberBaseTypes_Override = new List<ResolveResult>(); foreach (var type in memberbaseTypes) { var mr = type as MemberResult; if (mr != null && mr.ResolvedMember is DVariable) { var dv = mr.ResolvedMember as DVariable; // Note: Normally, a variable's base type mustn't be an other variable but an alias defintion... if (dv.IsAlias) { var newRes = ResolveType(dv.Type, ctxt, currentlyScopedNode); if (newRes != null) memberBaseTypes_Override.AddRange(newRes); hadAliasResolution = true; continue; } } // If no alias found, re-add it to our override list again memberBaseTypes_Override.Add(type); } memberbaseTypes = memberBaseTypes_Override.ToArray(); if (!hadAliasResolution) break; } } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type stackNum_HandleNodeMatch--; return new MemberResult() { ResolvedMember = m, MemberBaseTypes = memberbaseTypes, ResultBase = resultBase, TypeDeclarationBase = typeBase }; } else if (m is DMethod) { var method = m as DMethod; var methodType = method.Type; /* * If a method's type equals null, assume that it's an 'auto' function.. * 1) Search for a return statement * 2) Resolve the returned expression * 3) Use that one as the method's type */ //TODO: What about handling 'null'-returns? if (methodType == null && method.Body != null) { ReturnStatement returnStmt = null; var list = new List<IStatement> { method.Body }; var list2 = new List<IStatement>(); while (returnStmt == null && list.Count > 0) { foreach (var stmt in list) { if (stmt is ReturnStatement) { returnStmt = stmt as ReturnStatement; break; } if (stmt is StatementContainingStatement) list2.AddRange((stmt as StatementContainingStatement).SubStatements); } list = list2; list2 = new List<IStatement>(); } if (returnStmt != null && returnStmt.ReturnExpression != null) { currentlyScopedNode = method; methodType = returnStmt.ReturnExpression.ExpressionTypeRepresentation; } } var ret = new MemberResult() { ResolvedMember = m, MemberBaseTypes = DoResolveBaseType ? ResolveType(methodType, ctxt, currentlyScopedNode) : null, ResultBase = resultBase, TypeDeclarationBase = typeBase }; stackNum_HandleNodeMatch--; return ret; } else if (m is DClassLike) { var Class = m as DClassLike; var bc = DoResolveBaseType ? ResolveBaseClass(Class, ctxt) : null; stackNum_HandleNodeMatch--; return new TypeResult() { ResolvedTypeDefinition = Class, BaseClass = bc, ResultBase = resultBase, TypeDeclarationBase = typeBase }; } else if (m is IAbstractSyntaxTree) { stackNum_HandleNodeMatch--; return new ModuleResult() { ResolvedModule = m as IAbstractSyntaxTree, AlreadyTypedModuleNameParts = 1, ResultBase = resultBase, TypeDeclarationBase = typeBase }; } else if (m is DEnum) { stackNum_HandleNodeMatch--; return new TypeResult() { ResolvedTypeDefinition = m as IBlockNode, ResultBase = resultBase, TypeDeclarationBase = typeBase }; } else if (m is TemplateParameterNode) { stackNum_HandleNodeMatch--; return new MemberResult() { ResolvedMember = m, TypeDeclarationBase = typeBase, ResultBase = resultBase }; } stackNum_HandleNodeMatch--; // This never should happen.. return null; }
/// <summary> /// /// </summary> /// <param name="TypeDeclarationString"></param> /// <param name="NodeMatches"></param> /// <param name="ScopedType">If null, ScopedBlock variable will be assumed</param> /// <returns></returns> public bool TryGetAlreadyResolvedType(string TypeDeclarationString, out ResolveResult[] NodeMatches, object ScopedType = null) { if (ScopedType == null) ScopedType = ScopedBlock; Dictionary<string, ResolveResult[]> subDict = null; if (ScopedType!=null && !ResolvedTypes.TryGetValue(ScopedType, out subDict)) { NodeMatches = null; return false; } if(subDict!=null) return subDict.TryGetValue(TypeDeclarationString, out NodeMatches); NodeMatches = null; return false; }
public void TryAddResults(string TypeDeclarationString, ResolveResult[] NodeMatches, IBlockNode ScopedType = null) { if (ScopedType == null) ScopedType = ScopedBlock; Dictionary<string, ResolveResult[]> subDict = null; if (!ResolvedTypes.TryGetValue(ScopedType, out subDict)) ResolvedTypes.Add(ScopedType, subDict = new Dictionary<string, ResolveResult[]>()); if (!subDict.ContainsKey(TypeDeclarationString)) subDict.Add(TypeDeclarationString, NodeMatches); }
/// <summary> /// Tries to resolve a static property's name. /// Returns a result describing the theoretical member (".init"-%gt;MemberResult; ".typeof"->TypeResult etc). /// Returns null if nothing was found. /// </summary> /// <param name="InitialResult"></param> /// <returns></returns> public static ResolveResult TryResolveStaticProperties(ResolveResult InitialResult, IdentifierDeclaration Identifier, ResolverContext ctxt = null) { if (InitialResult == null || Identifier == null || InitialResult is ModuleResult) { return null; } var propertyName = Identifier.Value as string; if (propertyName == null) return null; INode relatedNode = null; if (InitialResult is MemberResult) relatedNode = (InitialResult as MemberResult).ResolvedMember; else if (InitialResult is TypeResult) relatedNode = (InitialResult as TypeResult).ResolvedTypeDefinition; #region init if (propertyName == "init") { var prop_Init = new DVariable { Name = "init", Description = "Initializer" }; if (relatedNode != null) { if (!(relatedNode is DVariable)) { prop_Init.Parent = relatedNode.Parent; prop_Init.Type = new IdentifierDeclaration(relatedNode.Name); } else { prop_Init.Parent = relatedNode; prop_Init.Initializer = (relatedNode as DVariable).Initializer; prop_Init.Type = relatedNode.Type; } } return new MemberResult { ResultBase = InitialResult, MemberBaseTypes = new[] { InitialResult }, TypeDeclarationBase = Identifier, ResolvedMember = prop_Init }; } #endregion #region sizeof if (propertyName == "sizeof") return new MemberResult { ResultBase = InitialResult, TypeDeclarationBase = Identifier, ResolvedMember = new DVariable { Name = "sizeof", Type = new DTokenDeclaration(DTokens.Int), Initializer = new IdentifierExpression(4), Description = "Size in bytes (equivalent to C's sizeof(type))" } }; #endregion #region alignof if (propertyName == "alignof") return new MemberResult { ResultBase = InitialResult, TypeDeclarationBase = Identifier, ResolvedMember = new DVariable { Name = "alignof", Type = new DTokenDeclaration(DTokens.Int), Description = "Alignment size" } }; #endregion #region mangleof if (propertyName == "mangleof") return new MemberResult { ResultBase = InitialResult, TypeDeclarationBase = Identifier, ResolvedMember = new DVariable { Name = "mangleof", Type = new IdentifierDeclaration("string"), Description = "String representing the ‘mangled’ representation of the type" }, MemberBaseTypes = ResolveType(new IdentifierDeclaration("string"), ctxt) }; #endregion #region stringof if (propertyName == "stringof") return new MemberResult { ResultBase = InitialResult, TypeDeclarationBase = Identifier, ResolvedMember = new DVariable { Name = "stringof", Type = new IdentifierDeclaration("string"), Description = "String representing the source representation of the type" }, MemberBaseTypes = ResolveType(new IdentifierDeclaration("string"), ctxt) }; #endregion bool isArray = false, isAssocArray = false, isInt = false, isFloat = false; #region See AbsractCompletionSupport.StaticPropertyAddition if (InitialResult is StaticTypeResult) { var srr = InitialResult as StaticTypeResult; var type = srr.TypeDeclarationBase; // on things like immutable(char), pass by the surrounding attribute.. while (type is MemberFunctionAttributeDecl) type = (type as MemberFunctionAttributeDecl).InnerType; if (type is ArrayDecl) { var ad = type as ArrayDecl; // Normal array if (ad.KeyType is DTokenDeclaration && DTokens.BasicTypes_Integral[(ad.KeyType as DTokenDeclaration).Token]) isArray = true; // Associative array else isAssocArray = true; } else if (!(type is PointerDecl)) { int TypeToken = srr.BaseTypeToken; if (TypeToken <= 0 && type is DTokenDeclaration) TypeToken = (type as DTokenDeclaration).Token; if (TypeToken > 0) { // Determine whether float by the var's base type isInt = DTokens.BasicTypes_Integral[srr.BaseTypeToken]; isFloat = DTokens.BasicTypes_FloatingPoint[srr.BaseTypeToken]; } } } else if (InitialResult is ExpressionResult) { var err = InitialResult as ExpressionResult; var expr = err.Expression; // 'Skip' surrounding parentheses while (expr is SurroundingParenthesesExpression) expr = (expr as SurroundingParenthesesExpression).Expression; var idExpr = expr as IdentifierExpression; if (idExpr != null) { // Char literals, Integrals types & Floats if ((idExpr.Format & LiteralFormat.Scalar) == LiteralFormat.Scalar || idExpr.Format == LiteralFormat.CharLiteral) { // Floats also imply integral properties isInt = true; isFloat = (idExpr.Format & LiteralFormat.FloatingPoint) == LiteralFormat.FloatingPoint; } // String literals else if (idExpr.Format == LiteralFormat.StringLiteral || idExpr.Format == LiteralFormat.VerbatimStringLiteral) { isArray = true; } } // Pointer conversions (e.g. (myInt*).sizeof) } #endregion //TODO: Resolve static [assoc] array props if (isArray || isAssocArray) { } return null; }