AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolverContextStack ctxt) { AbstractType pfType = null; if (acc.PostfixForeExpression is PostfixExpression_Access) { pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt); } else { pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt)); if (acc.PostfixForeExpression is IdentifierExpression || acc.PostfixForeExpression is TemplateInstanceExpression || acc.PostfixForeExpression is PostfixExpression_Access) { HandleResult(acc.PostfixForeExpression, pfType); } } bool ufcs = false; var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, out ufcs, pfType); ctxt.CheckForSingleResult(accessedMembers, acc); if (accessedMembers != null && accessedMembers.Length != 0) { HandleResult(acc, accessedMembers[0]); return(accessedMembers[0]); } return(null); }
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)); }
public static AbstractType ResolveSingle(IdentifierDeclaration id, ResolverContextStack ctxt, AbstractType[] resultBases = null, bool filterForTemplateArgs = true) { var r = Resolve(id, ctxt, resultBases, filterForTemplateArgs); ctxt.CheckForSingleResult(r, id); return(r != null && r.Length != 0 ? r[0] : null); }
public static AbstractType getStringType(ResolverContextStack ctxt) { var str = new IdentifierDeclaration("string"); var sType = TypeDeclarationResolver.Resolve(str, ctxt); ctxt.CheckForSingleResult(sType, str); return sType != null && sType.Length != 0 ? sType[0] : null; }
public static AbstractType ResolveSingle(string id, ResolverContextStack ctxt, object idObject, bool ModuleScope = false) { var r = ResolveIdentifier(id, ctxt, idObject, ModuleScope); ctxt.CheckForSingleResult(r, idObject as ISyntaxRegion); return(r != null && r.Length != 0 ? r[0] : null); }
public static AbstractType getStringType(ResolverContextStack ctxt) { var str = new IdentifierDeclaration("string"); var sType = TypeDeclarationResolver.Resolve(str, ctxt); ctxt.CheckForSingleResult(sType, str); return(sType != null && sType.Length != 0 ? sType[0] : null); }
public static List <ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolverContextStack ctxt) { // Resolve given argument expressions var templateArguments = new List <ISemantic>(); if (tix != null && tix.Arguments != null) { foreach (var arg in tix.Arguments) { if (arg is TypeDeclarationExpression) { var tde = (TypeDeclarationExpression)arg; var res = TypeDeclarationResolver.Resolve(tde.Declaration, ctxt); if (ctxt.CheckForSingleResult(res, tde.Declaration) || res != null) { var mr = res[0] as MemberSymbol; if (mr != null && mr.Definition is DVariable) { var dv = (DVariable)mr.Definition; if (dv.IsAlias || dv.Initializer == null) { templateArguments.Add(mr); continue; } ISemantic eval = null; try { eval = new StandardValueProvider(ctxt)[dv]; } catch (System.Exception ee) // Should be a non-const-expression error here only { ctxt.LogError(dv.Initializer, ee.Message); } templateArguments.Add(eval == null ? (ISemantic)mr : eval); } else { templateArguments.Add(res[0]); } } } else { templateArguments.Add(Evaluation.EvaluateValue(arg, ctxt)); } } } return(templateArguments); }
public static DelegateType Resolve(DelegateDeclaration dg, ResolverContextStack ctxt) { var returnTypes = Resolve(dg.ReturnType, ctxt); ctxt.CheckForSingleResult(returnTypes, dg.ReturnType); if (returnTypes != null && returnTypes.Length != 0) { return(new DelegateType(returnTypes[0], dg)); // Parameter types will be resolved later on } return(null); }
public static PointerType Resolve(PointerDecl pd, ResolverContextStack ctxt) { var ptrBaseTypes = Resolve(pd.InnerDeclaration, ctxt); ctxt.CheckForSingleResult(ptrBaseTypes, pd); if (ptrBaseTypes == null || ptrBaseTypes.Length == 0) { return(null); } return(new PointerType(ptrBaseTypes[0], pd)); }
public static AbstractType Resolve(MemberFunctionAttributeDecl attrDecl, ResolverContextStack ctxt) { if (attrDecl != null) { var ret = Resolve(attrDecl.InnerType, ctxt); ctxt.CheckForSingleResult(ret, attrDecl.InnerType); if (ret != null && ret.Length != 0 && ret[0] != null) { ret[0].Modifier = attrDecl.Modifier; return(ret[0]); } } return(null); }
public static AbstractType GetMethodReturnType(DelegateType dg, ResolverContextStack ctxt) { if (dg == null || ctxt == null) { return(null); } if (dg.IsFunctionLiteral) { return(GetMethodReturnType(((FunctionLiteral)dg.DeclarationOrExpressionBase).AnonymousMethod, ctxt)); } else { var rt = ((DelegateDeclaration)dg.DeclarationOrExpressionBase).ReturnType; var r = Resolve(rt, ctxt); ctxt.CheckForSingleResult(r, rt); return(r[0]); } }
/// <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 MemberSymbol TryResolveStaticProperties( ISemantic InitialResult, string propertyIdentifier, ResolverContextStack ctxt = null, bool Evaluate = false, IdentifierDeclaration idContainter = null) { // If a pointer'ed type is given, take its base type if (InitialResult is PointerType) InitialResult = ((PointerType)InitialResult).Base; if (InitialResult == null || InitialResult is ModuleSymbol) return null; INode relatedNode = null; if (InitialResult is DSymbol) relatedNode = ((DSymbol)InitialResult).Definition; #region init if (propertyIdentifier == "init") { var prop_Init = new DVariable { Name = "init", Description = "Initializer" }; if (relatedNode != null) { if (!(relatedNode is DVariable)) { prop_Init.Parent = relatedNode.Parent; prop_Init.Type = new IdentifierDeclaration(relatedNode.Name); } else { prop_Init.Parent = relatedNode; prop_Init.Initializer = (relatedNode as DVariable).Initializer; prop_Init.Type = relatedNode.Type; } } return new MemberSymbol(prop_Init, DResolver.StripAliasSymbol(AbstractType.Get(InitialResult)), idContainter); } #endregion #region sizeof if (propertyIdentifier == "sizeof") return new MemberSymbol(new DVariable { Name = "sizeof", Type = new DTokenDeclaration(DTokens.Int), Initializer = new IdentifierExpression(4), Description = "Size in bytes (equivalent to C's sizeof(type))" }, new PrimitiveType(DTokens.Int), idContainter); #endregion #region alignof if (propertyIdentifier == "alignof") return new MemberSymbol(new DVariable { Name = "alignof", Type = new DTokenDeclaration(DTokens.Int), Description = "Alignment size" }, new PrimitiveType(DTokens.Int),idContainter); #endregion #region mangleof if (propertyIdentifier == "mangleof") return new MemberSymbol(new DVariable { Name = "mangleof", Type = new IdentifierDeclaration("string"), Description = "String representing the ‘mangled’ representation of the type" }, getStringType(ctxt) , idContainter); #endregion #region stringof if (propertyIdentifier == "stringof") return new MemberSymbol(new DVariable { Name = "stringof", Type = new IdentifierDeclaration("string"), Description = "String representing the source representation of the type" }, getStringType(ctxt), idContainter); #endregion #region classinfo else if (propertyIdentifier == "classinfo") { var tr = DResolver.StripMemberSymbols(AbstractType.Get(InitialResult)) as TemplateIntermediateType; if (tr is ClassType || tr is InterfaceType) { var ci=new IdentifierDeclaration("TypeInfo_Class") { InnerDeclaration = new IdentifierDeclaration("object"), ExpressesVariableAccess = true, }; var ti = TypeDeclarationResolver.Resolve(ci, ctxt); ctxt.CheckForSingleResult(ti, ci); return new MemberSymbol(new DVariable { Name = "classinfo", Type = ci }, ti!=null && ti.Length!=0?ti[0]:null, idContainter); } } #endregion //TODO: Resolve the types of type-specific properties (floats, ints, arrays, assocarrays etc.) return null; }
public static AbstractType GetMethodReturnType(DelegateType dg, ResolverContextStack ctxt) { if (dg == null || ctxt == null) return null; if (dg.IsFunctionLiteral) return GetMethodReturnType(((FunctionLiteral)dg.DeclarationOrExpressionBase).AnonymousMethod, ctxt); else { var rt=((DelegateDeclaration)dg.DeclarationOrExpressionBase).ReturnType; var r = Resolve(rt, ctxt); ctxt.CheckForSingleResult(r,rt); return r[0]; } }
public static AbstractType GetMethodReturnType(DMethod method, ResolverContextStack ctxt) { if (ctxt!=null && ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseTypes)) return null; /* * 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 */ if (method.Type != null) { var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt); if (ctxt.CheckForSingleResult(returnType, method.Type)) return returnType[0]; } else if (method.Body != null) { ReturnStatement returnStmt = null; var list = new List<IStatement> { method.Body }; var list2 = new List<IStatement>(); bool foundMatch = false; while (!foundMatch && list.Count > 0) { foreach (var stmt in list) { if (stmt is ReturnStatement) { returnStmt = stmt as ReturnStatement; if (!(returnStmt.ReturnExpression is TokenExpression) || (returnStmt.ReturnExpression as TokenExpression).Token != DTokens.Null) { foundMatch = true; break; } } if (stmt is StatementContainingStatement) list2.AddRange((stmt as StatementContainingStatement).SubStatements); } list = list2; list2 = new List<IStatement>(); } if (returnStmt != null && returnStmt.ReturnExpression != null) { ctxt.PushNewScope(method); var t= Evaluation.EvaluateType(returnStmt.ReturnExpression, ctxt); ctxt.Pop(); return t; } } return null; }
public static AbstractType GetMethodReturnType(DMethod method, ResolverContextStack ctxt) { if (ctxt != null && ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseTypes)) { return(null); } /* * 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 */ bool pushMethodScope = ctxt.ScopedBlock != method; if (method.Type != null) { if (pushMethodScope) { ctxt.PushNewScope(method); } //FIXME: Is it legal to explicitly return a nested type? var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt); if (pushMethodScope) { ctxt.Pop(); } if (ctxt.CheckForSingleResult(returnType, method.Type)) { return(returnType[0]); } } else if (method.Body != null) { ReturnStatement returnStmt = null; var list = new List <IStatement> { method.Body }; var list2 = new List <IStatement>(); bool foundMatch = false; while (!foundMatch && list.Count > 0) { foreach (var stmt in list) { if (stmt is ReturnStatement) { returnStmt = stmt as ReturnStatement; if (!(returnStmt.ReturnExpression is TokenExpression) || (returnStmt.ReturnExpression as TokenExpression).Token != DTokens.Null) { foundMatch = true; break; } } if (stmt is StatementContainingStatement) { list2.AddRange((stmt as StatementContainingStatement).SubStatements); } } list = list2; list2 = new List <IStatement>(); } if (returnStmt != null && returnStmt.ReturnExpression != null) { if (pushMethodScope) { var dedTypes = ctxt.CurrentContext.DeducedTemplateParameters; ctxt.PushNewScope(method); ctxt.CurrentContext.ScopedStatement = returnStmt; if (dedTypes.Count != 0) { foreach (var kv in dedTypes) { ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value; } } } var t = Evaluation.EvaluateType(returnStmt.ReturnExpression, ctxt); if (pushMethodScope) { ctxt.Pop(); } return(t); } } return(null); }
public static AbstractType ResolveSingle(ITypeDeclaration declaration, ResolverContextStack ctxt) { if (declaration is IdentifierDeclaration) return ResolveSingle(declaration as IdentifierDeclaration, ctxt); else if (declaration is TemplateInstanceExpression) { var a = Evaluation.GetOverloads(declaration as TemplateInstanceExpression, ctxt); ctxt.CheckForSingleResult(a, declaration); return a != null && a.Length != 0 ? a[0] : null; } AbstractType t = null; if (declaration is DTokenDeclaration) t = Resolve(declaration as DTokenDeclaration); else if (declaration is TypeOfDeclaration) t = Resolve(declaration as TypeOfDeclaration, ctxt); else if (declaration is MemberFunctionAttributeDecl) t = Resolve(declaration as MemberFunctionAttributeDecl, ctxt); else if (declaration is ArrayDecl) t = Resolve(declaration as ArrayDecl, ctxt); else if (declaration is PointerDecl) t = Resolve(declaration as PointerDecl, ctxt); else if (declaration is DelegateDeclaration) t = Resolve(declaration as DelegateDeclaration, ctxt); //TODO: VarArgDeclaration else if (declaration is ITemplateParameterDeclaration) { var tpd = declaration as ITemplateParameterDeclaration; var templateParameter = tpd.TemplateParameter; //TODO: Is this correct handling? while (templateParameter is TemplateThisParameter) templateParameter = (templateParameter as TemplateThisParameter).FollowParameter; if (tpd.TemplateParameter is TemplateValueParameter) { // Return a member result -- it's a static variable } else { // Return a type result? } } return t; }
/// <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> public static AbstractType HandleNodeMatch( INode m, ResolverContextStack ctxt, AbstractType resultBase = null, object typeBase = null) { stackNum_HandleNodeMatch++; /* * Pushing a new scope is only required if current scope cannot be found in the handled node's hierarchy. */ bool popAfterwards = !ctxt.NodeIsInCurrentScopeHierarchy(m); if (popAfterwards) { ctxt.PushNewScope(m is IBlockNode ? (IBlockNode)m : m.Parent as IBlockNode); } //HACK: Really dirty stack overflow prevention via manually counting call depth var canResolveBaseGenerally = stackNum_HandleNodeMatch < 6; var DoResolveBaseType = canResolveBaseGenerally && !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses) && (m.Type == null || m.Type.ToString(false) != m.Name); AbstractType ret = null; // To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context if (canResolveBaseGenerally && resultBase is DSymbol) { ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase); } // Only import symbol aliases are allowed to search in the parse cache if (m is ImportSymbolAlias) { var isa = (ImportSymbolAlias)m; if (isa.IsModuleAlias ? isa.Type != null : isa.Type.InnerDeclaration != null) { var mods = new List <DModule>(); var td = isa.IsModuleAlias ? isa.Type : isa.Type.InnerDeclaration; foreach (var mod in ctxt.ParseCache.LookupModuleName(td.ToString())) { mods.Add(mod as DModule); } if (mods.Count == 0) { ctxt.LogError(new NothingFoundError(isa.Type)); } else if (mods.Count > 1) { var m__ = new List <ISemantic>(); foreach (var mod in mods) { m__.Add(new ModuleSymbol(mod, isa.Type)); } ctxt.LogError(new AmbiguityError(isa.Type, m__)); } var bt = mods.Count != 0 ? (AbstractType) new ModuleSymbol(mods[0], td) : null; //TODO: Is this correct behaviour? if (!isa.IsModuleAlias) { var furtherId = ResolveFurtherTypeIdentifier(isa.Type.ToString(false), new[] { bt }, ctxt, isa.Type); ctxt.CheckForSingleResult(furtherId, isa.Type); if (furtherId != null && furtherId.Length != 0) { bt = furtherId[0]; } else { bt = null; } } ret = new AliasedType(isa, bt, isa.Type); } } else if (m is DVariable) { var v = (DVariable)m; AbstractType bt = null; if (DoResolveBaseType) { var bts = TypeDeclarationResolver.Resolve(v.Type, ctxt); if (bts != null && bts.Length != 0 && ctxt.CheckForSingleResult(bts, v.Type)) { bt = bts[0]; } // For auto variables, use the initializer to get its type else if (v.Initializer != null) { bt = ExpressionSemantics.Evaluation.EvaluateType(v.Initializer, ctxt); } // Check if inside an foreach statement header if (bt == null && ctxt.ScopedStatement != null) { bt = GetForeachIteratorType(v, ctxt); } } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type ret = v.IsAlias ? (DSymbol) new AliasedType(v, bt, typeBase as ISyntaxRegion) : new MemberSymbol(v, bt, typeBase as ISyntaxRegion); } else if (m is DMethod) { ret = new MemberSymbol((DNode)m, DoResolveBaseType ? GetMethodReturnType((DMethod)m, ctxt) : null , typeBase as ISyntaxRegion); } else if (m is DClassLike) { UserDefinedType udt = null; var dc = (DClassLike)m; var invisibleTypeParams = new Dictionary <string, TemplateParameterSymbol>(); /* * Add 'superior' template parameters to the current symbol because the parameters * might be re-used in the nested class. */ var tStk = new Stack <ResolverContext>(); do { var curCtxt = ctxt.Pop(); tStk.Push(curCtxt); foreach (var kv in curCtxt.DeducedTemplateParameters) { if (!dc.ContainsTemplateParameter(kv.Key) && !invisibleTypeParams.ContainsKey(kv.Key)) { invisibleTypeParams.Add(kv.Key, kv.Value); } } } while (ctxt.PrevContextIsInSameHierarchy); while (tStk.Count != 0) { ctxt.Push(tStk.Pop()); } switch (dc.ClassType) { case DTokens.Struct: ret = new StructType(dc, typeBase as ISyntaxRegion, invisibleTypeParams); break; case DTokens.Union: ret = new UnionType(dc, typeBase as ISyntaxRegion, invisibleTypeParams); break; case DTokens.Class: udt = new ClassType(dc, typeBase as ISyntaxRegion, null, null, invisibleTypeParams); break; case DTokens.Interface: udt = new InterfaceType(dc, typeBase as ISyntaxRegion, null, invisibleTypeParams); break; case DTokens.Template: ret = new TemplateType(dc, typeBase as ISyntaxRegion, invisibleTypeParams); break; default: ctxt.LogError(new ResolutionError(m, "Unknown type (" + DTokens.GetTokenString(dc.ClassType) + ")")); break; } if (dc.ClassType == DTokens.Class || dc.ClassType == DTokens.Interface) { if (canResolveBaseGenerally && !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses)) { ret = DResolver.ResolveBaseClasses(udt, ctxt); } else { ret = udt; } } } else if (m is IAbstractSyntaxTree) { var mod = (IAbstractSyntaxTree)m; if (typeBase != null && typeBase.ToString() != mod.ModuleName) { var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).First(); if (pack != null) { ret = new PackageSymbol(pack, typeBase as ISyntaxRegion); } } else { ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion); } } else if (m is DEnum) { ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion); } else if (m is TemplateParameterNode) { //ResolveResult[] templateParameterType = null; //TODO: Resolve the specialization type //var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt); ret = new TemplateParameterSymbol((TemplateParameterNode)m, null, typeBase as ISyntaxRegion); } if (canResolveBaseGenerally && resultBase is DSymbol) { ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase); } if (popAfterwards) { ctxt.Pop(); } stackNum_HandleNodeMatch--; return(ret); }
public static AbstractType Resolve(MemberFunctionAttributeDecl attrDecl, ResolverContextStack ctxt) { if (attrDecl != null) { var ret = Resolve(attrDecl.InnerType, ctxt); ctxt.CheckForSingleResult(ret, attrDecl.InnerType); if (ret != null && ret.Length != 0 && ret[0] != null) { ret[0].Modifier = attrDecl.Modifier; return ret[0]; } } return null; }
/// <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> public static AbstractType HandleNodeMatch( INode m, ResolverContextStack ctxt, AbstractType resultBase = null, object typeBase = null) { stackNum_HandleNodeMatch++; bool popAfterwards = m.Parent != ctxt.ScopedBlock && m.Parent is IBlockNode; if (popAfterwards) ctxt.PushNewScope((IBlockNode)m.Parent); //HACK: Really dirty stack overflow prevention via manually counting call depth var canResolveBaseGenerally = stackNum_HandleNodeMatch < 6; var DoResolveBaseType = canResolveBaseGenerally && !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses) && (m.Type == null || m.Type.ToString(false) != m.Name); AbstractType ret = null; // To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context if (canResolveBaseGenerally && resultBase is DSymbol) ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase); // Only import symbol aliases are allowed to search in the parse cache if (m is ImportSymbolAlias) { var isa = (ImportSymbolAlias)m; if (isa.IsModuleAlias ? isa.Type != null : isa.Type.InnerDeclaration != null) { var mods = new List<DModule>(); var td=isa.IsModuleAlias ? isa.Type : isa.Type.InnerDeclaration; foreach (var mod in ctxt.ParseCache.LookupModuleName(td.ToString())) mods.Add(mod as DModule); if(mods.Count == 0) ctxt.LogError(new NothingFoundError(isa.Type)); else if(mods.Count > 1) { var m__=new List<ISemantic>(); foreach(var mod in mods) m__.Add(new ModuleSymbol(mod, isa.Type)); ctxt.LogError(new AmbiguityError(isa.Type,m__)); } var bt=mods.Count != 0 ? (AbstractType)new ModuleSymbol(mods[0], td) : null; //TODO: Is this correct behaviour? if (!isa.IsModuleAlias){ var furtherId = ResolveFurtherTypeIdentifier(isa.Type.ToString(false), new[]{ bt }, ctxt, isa.Type); ctxt.CheckForSingleResult(furtherId, isa.Type); if (furtherId != null && furtherId.Length != 0) bt = furtherId[0]; else bt = null; } ret = new AliasedType(isa, bt, isa.Type); } } else if (m is DVariable) { var v = (DVariable)m; AbstractType bt = null; if (DoResolveBaseType) { var bts = TypeDeclarationResolver.Resolve(v.Type, ctxt); if (bts != null && bts.Length != 0 && ctxt.CheckForSingleResult(bts, v.Type)) bt = bts[0]; // For auto variables, use the initializer to get its type else if (v.Initializer != null) bt = ExpressionSemantics.Evaluation.EvaluateType(v.Initializer, ctxt); // Check if inside an foreach statement header if (bt == null && ctxt.ScopedStatement != null) bt = GetForeachIteratorType(v, ctxt); } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type ret=v.IsAlias ? (DSymbol)new AliasedType(v, bt, typeBase as ISyntaxRegion) : new MemberSymbol(v, bt, typeBase as ISyntaxRegion); } else if (m is DMethod) { ret = new MemberSymbol((DNode)m, DoResolveBaseType ? GetMethodReturnType((DMethod)m, ctxt) : null , typeBase as ISyntaxRegion); } else if (m is DClassLike) { UserDefinedType udt = null; var dc=(DClassLike)m; switch (dc.ClassType) { case DTokens.Struct: udt = new StructType(dc, typeBase as ISyntaxRegion); break; case DTokens.Union: udt = new UnionType(dc, typeBase as ISyntaxRegion); break; case DTokens.Class: udt = new ClassType(dc, typeBase as ISyntaxRegion, null); break; case DTokens.Template: udt = new TemplateType(dc, typeBase as ISyntaxRegion); break; case DTokens.Interface: udt = new InterfaceType(dc, typeBase as ISyntaxRegion); break; default: ctxt.LogError(new ResolutionError(m, "Unknown type ("+DTokens.GetTokenString(dc.ClassType)+")")); break; } if (canResolveBaseGenerally && !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses)) ret = DResolver.ResolveBaseClasses(udt, ctxt); else ret = udt; } else if (m is IAbstractSyntaxTree) { var mod = (IAbstractSyntaxTree)m; if (typeBase != null && typeBase.ToString() != mod.ModuleName) { var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).First(); if (pack != null) ret = new PackageSymbol(pack, typeBase as ISyntaxRegion); } else ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion); } else if (m is DEnum) ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion); else if (m is TemplateParameterNode) { var tmp = ((TemplateParameterNode)m).TemplateParameter; //ResolveResult[] templateParameterType = null; //TODO: Resolve the specialization type //var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt); ret = new MemberSymbol((DNode)m, null, typeBase as ISyntaxRegion); } if (canResolveBaseGenerally && resultBase is DSymbol) ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase); if (popAfterwards) ctxt.Pop(); stackNum_HandleNodeMatch--; return ret; }
AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolverContextStack ctxt) { AbstractType pfType = null; if (acc.PostfixForeExpression is PostfixExpression_Access) pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt); else { pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt)); if (acc.PostfixForeExpression is IdentifierExpression || acc.PostfixForeExpression is TemplateInstanceExpression || acc.PostfixForeExpression is PostfixExpression_Access) HandleResult(acc.PostfixForeExpression, pfType); } bool ufcs=false; var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, out ufcs, pfType); ctxt.CheckForSingleResult(accessedMembers, acc); if (accessedMembers != null && accessedMembers.Length != 0) { HandleResult(acc, accessedMembers[0]); return accessedMembers[0]; } return null; }
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); }
public static PointerType Resolve(PointerDecl pd, ResolverContextStack ctxt) { var ptrBaseTypes = Resolve(pd.InnerDeclaration, ctxt); ctxt.CheckForSingleResult(ptrBaseTypes, pd); if (ptrBaseTypes == null || ptrBaseTypes.Length == 0) return null; return new PointerType(ptrBaseTypes[0], pd); }
public static DelegateType Resolve(DelegateDeclaration dg, ResolverContextStack ctxt) { var returnTypes = Resolve(dg.ReturnType, ctxt); ctxt.CheckForSingleResult(returnTypes, dg.ReturnType); if (returnTypes != null && returnTypes.Length != 0) return new DelegateType(returnTypes[0], dg); // Parameter types will be resolved later on return null; }
public static AbstractType ResolveSingle(string id, ResolverContextStack ctxt, object idObject, bool ModuleScope = false) { var r = ResolveIdentifier(id, ctxt, idObject, ModuleScope); ctxt.CheckForSingleResult(r, idObject as ISyntaxRegion); return r != null && r.Length != 0 ? r[0] : null; }
/// <summary> /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces. /// Also usable for enums. /// /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved. /// Will clone 'tr', whereas the new object will contain the base class. /// </summary> public static UserDefinedType ResolveBaseClasses(UserDefinedType tr, ResolverContextStack ctxt, bool ResolveFirstBaseIdOnly = false) { if (bcStack > 8) { bcStack--; return(tr); } if (tr is EnumType) { var et = tr as EnumType; AbstractType bt = null; if (et.Definition.Type == null) { bt = new PrimitiveType(DTokens.Int); } else { if (tr.Definition.Parent is IBlockNode) { ctxt.PushNewScope((IBlockNode)tr.Definition.Parent); } var bts = TypeDeclarationResolver.Resolve(et.Definition.Type, ctxt); if (tr.Definition.Parent is IBlockNode) { ctxt.Pop(); } ctxt.CheckForSingleResult(bts, et.Definition.Type); if (bts != null && bts.Length != 0) { bt = bts[0]; } } return(new EnumType(et.Definition, bt, et.DeclarationOrExpressionBase)); } var dc = tr.Definition as DClassLike; // Return immediately if searching base classes of the Object class if (dc == null || ((dc.BaseClasses == null || dc.BaseClasses.Count < 1) && dc.Name == "Object")) { return(tr); } // If no base class(es) specified, and if it's no interface that is handled, return the global Object reference // -- and do not throw any error message, it's ok if (dc.BaseClasses == null || dc.BaseClasses.Count < 1) { if (tr is ClassType) // Only Classes can inherit from non-interfaces { return(new ClassType(dc, tr.DeclarationOrExpressionBase, ctxt.ParseCache.ObjectClassResult)); } return(tr); } #region Base class & interface resolution TemplateIntermediateType baseClass = null; var interfaces = new List <InterfaceType>(); if (!(tr is ClassType || tr is InterfaceType)) { if (dc.BaseClasses.Count != 0) { ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces"); } return(tr); } for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++) { var type = dc.BaseClasses[i]; // If there's an explicit 'Object' inheritance, also return the pre-resolved object class if (type is IdentifierDeclaration && ((IdentifierDeclaration)type).Id == "Object") { if (baseClass != null) { ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes")); continue; } else if (i != 0) { ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces")); continue; } baseClass = ctxt.ParseCache.ObjectClassResult; continue; } if (type == null || type.ToString(false) == dc.Name || dc.NodeRoot == dc) { ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself")); continue; } ctxt.PushNewScope(dc.Parent as IBlockNode); bcStack++; var res = TypeDeclarationResolver.Resolve(type, ctxt); ctxt.CheckForSingleResult(res, type); if (res != null && res.Length != 0) { var r = res[0]; if (r is ClassType || r is TemplateType) { if (tr is InterfaceType) { ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces")); } else if (i == 0) { baseClass = (TemplateIntermediateType)r; } else { ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ? "class" : "template") + " name must preceed base interfaces")); } } else if (r is InterfaceType) { interfaces.Add((InterfaceType)r); } else { ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface")); continue; } } bcStack--; ctxt.Pop(); } #endregion if (baseClass == null && interfaces.Count == 0) { return(tr); } if (tr is ClassType) { return(new ClassType(dc, tr.DeclarationOrExpressionBase, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes)); } else if (tr is InterfaceType) { return(new InterfaceType(dc, tr.DeclarationOrExpressionBase, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes)); } // Method should end here return(tr); }
public static AbstractType ResolveSingle(ITypeDeclaration declaration, ResolverContextStack ctxt) { if (declaration is IdentifierDeclaration) { return(ResolveSingle(declaration as IdentifierDeclaration, ctxt)); } else if (declaration is TemplateInstanceExpression) { var a = Evaluation.GetOverloads(declaration as TemplateInstanceExpression, ctxt); ctxt.CheckForSingleResult(a, declaration); return(a != null && a.Length != 0 ? a[0] : null); } AbstractType t = null; if (declaration is DTokenDeclaration) { t = Resolve(declaration as DTokenDeclaration); } else if (declaration is TypeOfDeclaration) { t = Resolve(declaration as TypeOfDeclaration, ctxt); } else if (declaration is MemberFunctionAttributeDecl) { t = Resolve(declaration as MemberFunctionAttributeDecl, ctxt); } else if (declaration is ArrayDecl) { t = Resolve(declaration as ArrayDecl, ctxt); } else if (declaration is PointerDecl) { t = Resolve(declaration as PointerDecl, ctxt); } else if (declaration is DelegateDeclaration) { t = Resolve(declaration as DelegateDeclaration, ctxt); } //TODO: VarArgDeclaration else if (declaration is ITemplateParameterDeclaration) { var tpd = declaration as ITemplateParameterDeclaration; var templateParameter = tpd.TemplateParameter; //TODO: Is this correct handling? while (templateParameter is TemplateThisParameter) { templateParameter = (templateParameter as TemplateThisParameter).FollowParameter; } if (tpd.TemplateParameter is TemplateValueParameter) { // Return a member result -- it's a static variable } else { // Return a type result? } } return(t); }
/// <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 MemberSymbol TryResolveStaticProperties( ISemantic InitialResult, string propertyIdentifier, ResolverContextStack ctxt = null, bool Evaluate = false, IdentifierDeclaration idContainter = null) { // If a pointer'ed type is given, take its base type if (InitialResult is PointerType) { InitialResult = ((PointerType)InitialResult).Base; } if (InitialResult == null || InitialResult is ModuleSymbol) { return(null); } INode relatedNode = null; if (InitialResult is DSymbol) { relatedNode = ((DSymbol)InitialResult).Definition; } #region init if (propertyIdentifier == "init") { var prop_Init = new DVariable { Name = "init", Description = "Initializer" }; if (relatedNode != null) { if (!(relatedNode is DVariable)) { prop_Init.Parent = relatedNode.Parent; prop_Init.Type = new IdentifierDeclaration(relatedNode.Name); } else { prop_Init.Parent = relatedNode; prop_Init.Initializer = (relatedNode as DVariable).Initializer; prop_Init.Type = relatedNode.Type; } } return(new MemberSymbol(prop_Init, DResolver.StripAliasSymbol(AbstractType.Get(InitialResult)), idContainter)); } #endregion #region sizeof if (propertyIdentifier == "sizeof") { return(new MemberSymbol(new DVariable { Name = "sizeof", Type = new DTokenDeclaration(DTokens.Int), Initializer = new IdentifierExpression(4), Description = "Size in bytes (equivalent to C's sizeof(type))" }, new PrimitiveType(DTokens.Int), idContainter)); } #endregion #region alignof if (propertyIdentifier == "alignof") { return(new MemberSymbol(new DVariable { Name = "alignof", Type = new DTokenDeclaration(DTokens.Int), Description = "Alignment size" }, new PrimitiveType(DTokens.Int), idContainter)); } #endregion #region mangleof if (propertyIdentifier == "mangleof") { return(new MemberSymbol(new DVariable { Name = "mangleof", Type = new IdentifierDeclaration("string"), Description = "String representing the ‘mangled’ representation of the type" }, getStringType(ctxt), idContainter)); } #endregion #region stringof if (propertyIdentifier == "stringof") { return(new MemberSymbol(new DVariable { Name = "stringof", Type = new IdentifierDeclaration("string"), Description = "String representing the source representation of the type" }, getStringType(ctxt), idContainter)); } #endregion #region classinfo else if (propertyIdentifier == "classinfo") { var tr = DResolver.StripMemberSymbols(AbstractType.Get(InitialResult)) as TemplateIntermediateType; if (tr is ClassType || tr is InterfaceType) { var ci = new IdentifierDeclaration("TypeInfo_Class") { InnerDeclaration = new IdentifierDeclaration("object"), ExpressesVariableAccess = true, }; var ti = TypeDeclarationResolver.Resolve(ci, ctxt); ctxt.CheckForSingleResult(ti, ci); return(new MemberSymbol(new DVariable { Name = "classinfo", Type = ci }, ti != null && ti.Length != 0?ti[0]:null, idContainter)); } } #endregion //TODO: Resolve the types of type-specific properties (floats, ints, arrays, assocarrays etc.) return(null); }
public static AbstractType ResolveSingle(IdentifierDeclaration id, ResolverContextStack ctxt, AbstractType[] resultBases = null, bool filterForTemplateArgs = true) { var r = Resolve(id, ctxt, resultBases, filterForTemplateArgs); ctxt.CheckForSingleResult(r, id); return r != null && r.Length != 0 ? r[0] : null; }
public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolverContextStack ctxt) { keyVal = null; fixedArrayLength = 0; 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 List<ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolverContextStack ctxt) { // Resolve given argument expressions var templateArguments = new List<ISemantic>(); if (tix != null && tix.Arguments!=null) foreach (var arg in tix.Arguments) { if (arg is TypeDeclarationExpression) { var tde = (TypeDeclarationExpression)arg; var res = TypeDeclarationResolver.Resolve(tde.Declaration, ctxt); if (ctxt.CheckForSingleResult(res, tde.Declaration) || res != null) { var mr = res[0] as MemberSymbol; if (mr != null && mr.Definition is DVariable) { var dv = (DVariable)mr.Definition; if (dv.IsAlias || dv.Initializer == null) { templateArguments.Add(mr); continue; } ISemantic eval = null; try { eval = new StandardValueProvider(ctxt)[dv]; } catch(System.Exception ee) // Should be a non-const-expression error here only { ctxt.LogError(dv.Initializer, ee.Message); } templateArguments.Add(eval==null ? (ISemantic)mr : eval); } else templateArguments.Add(res[0]); } } else templateArguments.Add(Evaluation.EvaluateValue(arg, ctxt)); } return templateArguments; }