1 /** 2 * Provides a visitor class visiting all AST nodes present in the compiler. 3 * 4 * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/visitor.d, _visitor.d) 8 * Documentation: https://dlang.org/phobos/dmd_visitor.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/visitor.d 10 */ 11 12 module dmd.visitor; 13 14 import dmd.astcodegen; 15 import dmd.astenums; 16 import dmd.parsetimevisitor; 17 import dmd.tokens; 18 import dmd.transitivevisitor; 19 import dmd.expression; 20 import dmd.root.rootobject; 21 22 /** 23 * Classic Visitor class which implements visit methods for all the AST 24 * nodes present in the compiler. The visit methods for AST nodes 25 * created at parse time are inherited while the visiting methods 26 * for AST nodes created at semantic time are implemented. 27 */ 28 extern (C++) class Visitor : ParseTimeVisitor!ASTCodegen 29 { 30 alias visit = ParseTimeVisitor!ASTCodegen.visit; 31 public: 32 void visit(ASTCodegen.ErrorStatement s) { visit(cast(ASTCodegen.Statement)s); } 33 void visit(ASTCodegen.PeelStatement s) { visit(cast(ASTCodegen.Statement)s); } 34 void visit(ASTCodegen.UnrolledLoopStatement s) { visit(cast(ASTCodegen.Statement)s); } 35 void visit(ASTCodegen.SwitchErrorStatement s) { visit(cast(ASTCodegen.Statement)s); } 36 void visit(ASTCodegen.DebugStatement s) { visit(cast(ASTCodegen.Statement)s); } 37 void visit(ASTCodegen.DtorExpStatement s) { visit(cast(ASTCodegen.ExpStatement)s); } 38 void visit(ASTCodegen.ForwardingStatement s) { visit(cast(ASTCodegen.Statement)s); } 39 void visit(ASTCodegen.OverloadSet s) { visit(cast(ASTCodegen.Dsymbol)s); } 40 void visit(ASTCodegen.LabelDsymbol s) { visit(cast(ASTCodegen.Dsymbol)s); } 41 void visit(ASTCodegen.WithScopeSymbol s) { visit(cast(ASTCodegen.ScopeDsymbol)s); } 42 void visit(ASTCodegen.ArrayScopeSymbol s) { visit(cast(ASTCodegen.ScopeDsymbol)s); } 43 void visit(ASTCodegen.OverDeclaration s) { visit(cast(ASTCodegen.Declaration)s); } 44 void visit(ASTCodegen.SymbolDeclaration s) { visit(cast(ASTCodegen.Declaration)s); } 45 void visit(ASTCodegen.ForwardingAttribDeclaration s) { visit(cast(ASTCodegen.AttribDeclaration)s); } 46 void visit(ASTCodegen.ThisDeclaration s) { visit(cast(ASTCodegen.VarDeclaration)s); } 47 void visit(ASTCodegen.TypeInfoDeclaration s) { visit(cast(ASTCodegen.VarDeclaration)s); } 48 void visit(ASTCodegen.TypeInfoStructDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 49 void visit(ASTCodegen.TypeInfoClassDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 50 void visit(ASTCodegen.TypeInfoInterfaceDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 51 void visit(ASTCodegen.TypeInfoPointerDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 52 void visit(ASTCodegen.TypeInfoArrayDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 53 void visit(ASTCodegen.TypeInfoStaticArrayDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 54 void visit(ASTCodegen.TypeInfoAssociativeArrayDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 55 void visit(ASTCodegen.TypeInfoEnumDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 56 void visit(ASTCodegen.TypeInfoFunctionDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 57 void visit(ASTCodegen.TypeInfoDelegateDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 58 void visit(ASTCodegen.TypeInfoTupleDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 59 void visit(ASTCodegen.TypeInfoConstDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 60 void visit(ASTCodegen.TypeInfoInvariantDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 61 void visit(ASTCodegen.TypeInfoSharedDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 62 void visit(ASTCodegen.TypeInfoWildDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 63 void visit(ASTCodegen.TypeInfoVectorDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); } 64 void visit(ASTCodegen.FuncAliasDeclaration s) { visit(cast(ASTCodegen.FuncDeclaration)s); } 65 void visit(ASTCodegen.ErrorInitializer i) { visit(cast(ASTCodegen.Initializer)i); } 66 void visit(ASTCodegen.ErrorExp e) { visit(cast(ASTCodegen.Expression)e); } 67 void visit(ASTCodegen.ComplexExp e) { visit(cast(ASTCodegen.Expression)e); } 68 void visit(ASTCodegen.StructLiteralExp e) { visit(cast(ASTCodegen.Expression)e); } 69 void visit(ASTCodegen.CompoundLiteralExp e) { visit(cast(ASTCodegen.Expression)e); } 70 void visit(ASTCodegen.ObjcClassReferenceExp e) { visit(cast(ASTCodegen.Expression)e); } 71 void visit(ASTCodegen.SymOffExp e) { visit(cast(ASTCodegen.SymbolExp)e); } 72 void visit(ASTCodegen.OverExp e) { visit(cast(ASTCodegen.Expression)e); } 73 void visit(ASTCodegen.HaltExp e) { visit(cast(ASTCodegen.Expression)e); } 74 void visit(ASTCodegen.DotTemplateExp e) { visit(cast(ASTCodegen.UnaExp)e); } 75 void visit(ASTCodegen.DotVarExp e) { visit(cast(ASTCodegen.UnaExp)e); } 76 void visit(ASTCodegen.DelegateExp e) { visit(cast(ASTCodegen.UnaExp)e); } 77 void visit(ASTCodegen.DotTypeExp e) { visit(cast(ASTCodegen.UnaExp)e); } 78 void visit(ASTCodegen.VectorExp e) { visit(cast(ASTCodegen.UnaExp)e); } 79 void visit(ASTCodegen.VectorArrayExp e) { visit(cast(ASTCodegen.UnaExp)e); } 80 void visit(ASTCodegen.SliceExp e) { visit(cast(ASTCodegen.UnaExp)e); } 81 void visit(ASTCodegen.ArrayLengthExp e) { visit(cast(ASTCodegen.UnaExp)e); } 82 void visit(ASTCodegen.DelegatePtrExp e) { visit(cast(ASTCodegen.UnaExp)e); } 83 void visit(ASTCodegen.DelegateFuncptrExp e) { visit(cast(ASTCodegen.UnaExp)e); } 84 void visit(ASTCodegen.DotExp e) { visit(cast(ASTCodegen.BinExp)e); } 85 void visit(ASTCodegen.IndexExp e) { visit(cast(ASTCodegen.BinExp)e); } 86 void visit(ASTCodegen.ConstructExp e) { visit(cast(ASTCodegen.AssignExp)e); } 87 void visit(ASTCodegen.BlitExp e) { visit(cast(ASTCodegen.AssignExp)e); } 88 void visit(ASTCodegen.RemoveExp e) { visit(cast(ASTCodegen.BinExp)e); } 89 void visit(ASTCodegen.ClassReferenceExp e) { visit(cast(ASTCodegen.Expression)e); } 90 void visit(ASTCodegen.VoidInitExp e) { visit(cast(ASTCodegen.Expression)e); } 91 void visit(ASTCodegen.ThrownExceptionExp e) { visit(cast(ASTCodegen.Expression)e); } 92 } 93 94 /** 95 * The PermissiveVisitor overrides the root AST nodes with 96 * empty visiting methods. 97 */ 98 extern (C++) class SemanticTimePermissiveVisitor : Visitor 99 { 100 alias visit = Visitor.visit; 101 102 override void visit(ASTCodegen.Dsymbol){} 103 override void visit(ASTCodegen.Parameter){} 104 override void visit(ASTCodegen.Statement){} 105 override void visit(ASTCodegen.Type){} 106 override void visit(ASTCodegen.Expression){} 107 override void visit(ASTCodegen.TemplateParameter){} 108 override void visit(ASTCodegen.Condition){} 109 override void visit(ASTCodegen.Initializer){} 110 } 111 112 /** 113 * The TransitiveVisitor implements the AST traversal logic for all AST nodes. 114 */ 115 extern (C++) class SemanticTimeTransitiveVisitor : SemanticTimePermissiveVisitor 116 { 117 alias visit = SemanticTimePermissiveVisitor.visit; 118 119 mixin ParseVisitMethods!ASTCodegen __methods; 120 alias visit = __methods.visit; 121 122 override void visit(ASTCodegen.PeelStatement s) 123 { 124 if (s.s) 125 s.s.accept(this); 126 } 127 128 override void visit(ASTCodegen.UnrolledLoopStatement s) 129 { 130 foreach(sx; *s.statements) 131 { 132 if (sx) 133 sx.accept(this); 134 } 135 } 136 137 override void visit(ASTCodegen.DebugStatement s) 138 { 139 if (s.statement) 140 s.statement.accept(this); 141 } 142 143 override void visit(ASTCodegen.ForwardingStatement s) 144 { 145 if (s.statement) 146 s.statement.accept(this); 147 } 148 149 override void visit(ASTCodegen.StructLiteralExp e) 150 { 151 // CTFE can generate struct literals that contain an AddrExp pointing to themselves, 152 // need to avoid infinite recursion. 153 if (!(e.stageflags & stageToCBuffer)) 154 { 155 int old = e.stageflags; 156 e.stageflags |= stageToCBuffer; 157 foreach (el; *e.elements) 158 if (el) 159 el.accept(this); 160 e.stageflags = old; 161 } 162 } 163 164 override void visit(ASTCodegen.CompoundLiteralExp e) 165 { 166 if (e.initializer) 167 e.initializer.accept(this); 168 } 169 170 override void visit(ASTCodegen.DotTemplateExp e) 171 { 172 e.e1.accept(this); 173 } 174 175 override void visit(ASTCodegen.DotVarExp e) 176 { 177 e.e1.accept(this); 178 } 179 180 override void visit(ASTCodegen.DelegateExp e) 181 { 182 if (!e.func.isNested() || e.func.needThis()) 183 e.e1.accept(this); 184 } 185 186 override void visit(ASTCodegen.DotTypeExp e) 187 { 188 e.e1.accept(this); 189 } 190 191 override void visit(ASTCodegen.VectorExp e) 192 { 193 visitType(e.to); 194 e.e1.accept(this); 195 } 196 197 override void visit(ASTCodegen.VectorArrayExp e) 198 { 199 e.e1.accept(this); 200 } 201 202 override void visit(ASTCodegen.SliceExp e) 203 { 204 e.e1.accept(this); 205 if (e.upr) 206 e.upr.accept(this); 207 if (e.lwr) 208 e.lwr.accept(this); 209 } 210 211 override void visit(ASTCodegen.ArrayLengthExp e) 212 { 213 e.e1.accept(this); 214 } 215 216 override void visit(ASTCodegen.DelegatePtrExp e) 217 { 218 e.e1.accept(this); 219 } 220 221 override void visit(ASTCodegen.DelegateFuncptrExp e) 222 { 223 e.e1.accept(this); 224 } 225 226 override void visit(ASTCodegen.DotExp e) 227 { 228 e.e1.accept(this); 229 e.e2.accept(this); 230 } 231 232 override void visit(ASTCodegen.IndexExp e) 233 { 234 e.e1.accept(this); 235 e.e2.accept(this); 236 } 237 238 override void visit(ASTCodegen.RemoveExp e) 239 { 240 e.e1.accept(this); 241 e.e2.accept(this); 242 } 243 } 244 245 extern (C++) class StoppableVisitor : Visitor 246 { 247 alias visit = Visitor.visit; 248 public: 249 bool stop; 250 this()251 final extern (D) this() 252 { 253 } 254 } 255