bool IterateThrough(DClassLike cls, MemberFilter VisibleMembers, ref bool breakOnNextScope) { var curWatchedClass = cls; // MyClass > BaseA > BaseB > Object while (curWatchedClass != null) { if (curWatchedClass.TemplateParameters != null && (breakOnNextScope = HandleItems(curWatchedClass.TemplateParameterNodes as IEnumerable <INode>)) && breakImmediately) { return(true); } var ch = PrefilterSubnodes(curWatchedClass); if (ch != null) { foreach (var m in ch) { var dm2 = m as DNode; var dm3 = m as DMethod; // Only show normal & delegate methods if (!CanAddMemberOfType(VisibleMembers, m) || dm2 == null || (dm3 != null && !(dm3.SpecialType == DMethod.MethodType.Normal || dm3.SpecialType == DMethod.MethodType.Delegate))) { continue; } // Add static and non-private members of all base classes; // Add everything if we're still handling the currently scoped class if ((curWatchedClass == cls || dm2.IsStatic || (!(m is DVariable) || ((DVariable)dm2).IsConst) || !dm2.ContainsAttribute(DTokens.Private)) && (breakOnNextScope = HandleItem(m)) && breakImmediately) { return(true); } } } // 3) if (cls.ClassType == DTokens.Class) { var tr = DResolver.ResolveBaseClasses(new ClassType(curWatchedClass, curWatchedClass, null), ctxt, true); if (tr.Base is TemplateIntermediateType) { curWatchedClass = ((TemplateIntermediateType)tr.Base).Definition; } else { break; } } else { break; } } return(false); }
protected override bool HandleItem(INode n) { // Find all class+interface definitions var dc = n as DClassLike; if (dc == null || dc.BaseClasses == null || dc.BaseClasses.Count < 0 || alreadyResolvedClasses.Contains(dc)) { return(false); } // resolve immediate base classes/interfaces; Rely on dc being either a class or an interface, nothing else. var t = DResolver.ResolveBaseClasses(dc.ClassType == DTokens.Class ? (UserDefinedType) new ClassType(dc, null, null) : new InterfaceType(dc, null), ctxt) as TemplateIntermediateType; alreadyResolvedClasses.Add(dc); // Look for classes/interfaces that match dc (check all dcs to have better performance on ambiguous lastresults), var bt = DResolver.StripMemberSymbols(t.Base) as TemplateIntermediateType; while (bt != null) { var def = bt.Definition; if (def == typeNodeToFind) { if (!results.Contains(t)) { results.Add(t); } } if (!alreadyResolvedClasses.Contains(def)) { alreadyResolvedClasses.Add(def); } bt = DResolver.StripMemberSymbols(bt.Base) as TemplateIntermediateType; } return(false); }
ISemantic E(TokenExpression x) { switch (x.Token) { // References current class scope case DTokens.This: if (eval && resolveConstOnly) { EvalError(new NoConstException(x)); return(null); } var classDef = ctxt.ScopedBlock; while (!(classDef is DClassLike) && classDef != null) { classDef = classDef.Parent as IBlockNode; } if (classDef is DClassLike) { return(TypeDeclarationResolver.HandleNodeMatch(classDef, ctxt, null, x)); } /* * TODO: Return an object reference to the 'this' object. */ break; case DTokens.Super: // References super type of currently scoped class declaration if (eval && resolveConstOnly) { EvalError(new NoConstException(x)); return(null); } classDef = ctxt.ScopedBlock; while (!(classDef is DClassLike) && classDef != null) { classDef = classDef.Parent as IBlockNode; } if (classDef != null) { var tr = DResolver.ResolveBaseClasses(new ClassType(classDef as DClassLike, null, null), ctxt, true); if (tr.Base != null) { // Important: Overwrite type decl base with 'super' token tr.Base.DeclarationOrExpressionBase = x; return(tr.Base); } } /* * TODO: Return an object reference to 'this', wheras the type is the superior type. */ break; case DTokens.Null: if (eval && resolveConstOnly) { EvalError(new NoConstException(x)); return(null); } if (eval) { //TODO } return(null); case DTokens.Dollar: if (!eval) { return(new PrimitiveType(DTokens.Int)); } // It's only allowed if the evaluation stack contains an array value if (ValueProvider.CurrentArrayLength != -1) { return(new PrimitiveValue(DTokens.Int, ValueProvider.CurrentArrayLength, x)); } else { EvalError(x, "Dollar not allowed here!"); return(null); } case DTokens.True: if (!eval) { return(new PrimitiveType(DTokens.Bool)); } return(new PrimitiveValue(DTokens.Bool, 1, x)); case DTokens.False: if (!eval) { return(new PrimitiveType(DTokens.Bool)); } return(new PrimitiveValue(DTokens.Bool, 0, x)); case DTokens.__FILE__: if (!eval) { return(GetStringType()); } return(new ArrayValue(GetStringType(), (ctxt.ScopedBlock.NodeRoot as DModule).FileName)); case DTokens.__LINE__: if (!eval) { return(new PrimitiveType(DTokens.Int)); } return(new PrimitiveValue(DTokens.Int, x.Location.Line, x)); case DTokens.__MODULE__: if (!eval) { return(GetStringType()); } return(new ArrayValue(GetStringType(), (ctxt.ScopedBlock.NodeRoot as DModule).ModuleName)); case DTokens.__FUNCTION__: //TODO case DTokens.__PRETTY_FUNCTION__: if (!eval) { return(GetStringType()); } var dm = ctxt.ScopedStatement.ParentNode as DMethod; return(new ArrayValue(GetStringType(), dm == null ? "<not inside function>" : dm.ToString(false, true))); } return(null); }
/// <summary> /// Item1 - True, if isExpression returns true /// Item2 - If Item1 is true, it contains the type of the alias that is defined in the isExpression /// </summary> private Tuple <bool, AbstractType> evalIsExpression_EvalSpecToken(IsExpression isExpression, AbstractType typeToCheck, bool DoAliasHandling = false) { bool r = false; AbstractType res = null; switch (isExpression.TypeSpecializationToken) { /* * To handle semantic tokens like "return" or "super" it's just needed to * look into the current resolver context - * then, we'll be able to gather either the parent method or the currently scoped class definition. */ case DTokens.Struct: case DTokens.Union: case DTokens.Class: case DTokens.Interface: if (r = typeToCheck is UserDefinedType && ((TemplateIntermediateType)typeToCheck).Definition.ClassType == isExpression.TypeSpecializationToken) { res = typeToCheck; } break; case DTokens.Enum: if (!(typeToCheck is EnumType)) { break; } { var tr = (UserDefinedType)typeToCheck; r = true; res = tr.Base; } break; case DTokens.Function: case DTokens.Delegate: if (typeToCheck is DelegateType) { var isFun = false; var dgr = (DelegateType)typeToCheck; if (!dgr.IsFunctionLiteral) { r = isExpression.TypeSpecializationToken == ( (isFun = ((DelegateDeclaration)dgr.DeclarationOrExpressionBase).IsFunction) ? DTokens.Function : DTokens.Delegate); } // Must be a delegate otherwise else { isFun = !(r = isExpression.TypeSpecializationToken == DTokens.Delegate); } if (r) { //TODO if (isFun) { // TypeTuple of the function parameter types. For C- and D-style variadic functions, only the non-variadic parameters are included. // For typesafe variadic functions, the ... is ignored. } else { // the function type of the delegate } } } else // Normal functions are also accepted as delegates { r = isExpression.TypeSpecializationToken == DTokens.Delegate && typeToCheck is MemberSymbol && ((DSymbol)typeToCheck).Definition is DMethod; //TODO: Alias handling, same as couple of lines above } break; case DTokens.Super: //TODO: Test this var dc = DResolver.SearchClassLikeAt(ctxt.ScopedBlock, isExpression.Location) as DClassLike; if (dc != null) { var udt = DResolver.ResolveBaseClasses(new ClassType(dc, dc, null), ctxt, true) as ClassType; if (r = udt.Base != null && ResultComparer.IsEqual(typeToCheck, udt.Base)) { var l = new List <AbstractType>(); if (udt.Base != null) { l.Add(udt.Base); } if (udt.BaseInterfaces != null && udt.BaseInterfaces.Length != 0) { l.AddRange(udt.BaseInterfaces); } res = new DTuple(isExpression, l); } } break; case DTokens.Const: case DTokens.Immutable: case DTokens.InOut: // TODO? case DTokens.Shared: if (r = typeToCheck.Modifier == isExpression.TypeSpecializationToken) { res = typeToCheck; } break; case DTokens.Return: // TODO: Test IStatement _u = null; var dm = DResolver.SearchBlockAt(ctxt.ScopedBlock, isExpression.Location, out _u) as DMethod; if (dm != null) { var retType_ = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt); if (r = retType_ != null && ResultComparer.IsEqual(typeToCheck, retType_)) { res = retType_; } } break; } return(new Tuple <bool, AbstractType>(r, res)); }
/// <summary> /// Scans through the node. Also checks if n is a DClassLike or an other kind of type node and checks their specific child and/or base class nodes. /// </summary> /// <param name="parseCache">Needed when trying to search base classes</param> public static INode[] ScanNodeForIdentifier(IBlockNode curScope, string name, ResolverContextStack ctxt) { if (__stack > 40) { return(null); } __stack++; var matches = new List <INode>(); // Watch for anonymous enums var children = curScope[string.Empty]; if (children != null) { foreach (var n in children) { if (n is DEnum) { var de = (DEnum)n; var enumChildren = de[name]; if (enumChildren != null) { matches.AddRange(enumChildren); } } } } // Scan for normal members called 'name' if ((children = curScope[name]) != null) { matches.AddRange(children); } // If our current Level node is a class-like, also attempt to search in its baseclass! if (curScope is DClassLike) { var dc = (DClassLike)curScope; if (dc.ClassType == DTokens.Class) { var tr = DResolver.ResolveBaseClasses(new ClassType(dc, dc, null), ctxt, true); var tit = tr.Base as TemplateIntermediateType; if (tit != null && tit.Definition != dc) { // Search for items called name in the base class(es) var r = ScanNodeForIdentifier(tit.Definition, name, ctxt); if (r != null) { matches.AddRange(r); } } } else if (dc.ClassType == DTokens.Interface) { var tr = DResolver.ResolveBaseClasses(new InterfaceType(dc, dc), ctxt) as InterfaceType; if (tr != null && tr.BaseInterfaces != null && tr.BaseInterfaces.Length != 0) { foreach (var I in tr.BaseInterfaces) { if (I.Definition == dc) { break; } // Search for items called name in the base class(es) var r = ScanNodeForIdentifier(I.Definition, name, ctxt); if (r != null) { matches.AddRange(r); } } } } } // Check parameters var dn = curScope as DNode; if (dn != null) { var dm = dn as DMethod; if (dm != null && dm.Parameters != null && dm.Parameters.Count != 0) { foreach (var ch in ((DMethod)curScope).Parameters) { if (name == ch.Name) { matches.Add(ch); } } } // and template parameters if (dn.TemplateParameters != null) { foreach (var ch in dn.TemplateParameters) { if (name == ch.Name) { matches.Add(new TemplateParameterNode(ch) { Parent = curScope }); } } } } __stack--; return(matches.Count > 0 ? matches.ToArray() : null); }
protected bool DeepScanClass(UserDefinedType udt, MemberFilter vis, bool resolveBaseClassIfRequired = true) { bool isBase = false; bool scopeIsInInheritanceHierarchy = udt != null && ctxt.ScopedBlockIsInNodeHierarchy(udt.Definition); bool takeStaticChildrenOnly = ctxt.ScopedBlock is DMethod && (ctxt.ScopedBlock as DMethod).IsStatic; // Check if the scoped node's parent is the current class if (takeStaticChildrenOnly) { takeStaticChildrenOnly = false; var sc = udt.Definition as IBlockNode; while (sc != null) { if (ctxt.ScopedBlock.Parent == sc) { takeStaticChildrenOnly = true; break; } sc = sc.Parent as IBlockNode; } } List <InterfaceType> interfaces = null; while (udt != null) { if (scanChildren(udt.Definition as DBlockNode, vis, false, isBase, false, takeStaticChildrenOnly, scopeIsInInheritanceHierarchy)) { return(true); } if (udt is TemplateIntermediateType) { var tit = udt as TemplateIntermediateType; var type = (tit.Definition as DClassLike).ClassType; if ((type == DTokens.Struct || type == DTokens.Class || type == DTokens.Template) && HandleAliasThisDeclarations(tit, vis)) { return(true); } if (tit.BaseInterfaces != null) { if (interfaces == null) { interfaces = new List <InterfaceType> (); } foreach (var I in tit.BaseInterfaces) { if (!interfaces.Contains(I)) { interfaces.Add(I); } } } if (resolveBaseClassIfRequired && udt.Base == null && type == DTokens.Class) { udt = DResolver.ResolveBaseClasses(udt, ctxt); } udt = udt.Base as UserDefinedType; isBase = true; } else { break; } } if (interfaces != null) { foreach (var I in interfaces) { if (scanChildren(I.Definition, vis, false, true, false, takeStaticChildrenOnly, scopeIsInInheritanceHierarchy)) { return(true); } } } return(false); }