1 /** 2 * Provides a visitor class visiting all AST nodes present in the compiler. 3 * 4 * Copyright: Copyright (C) 1999-2023 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 void visit(ASTCodegen.LoweredAssignExp e) { visit(cast(ASTCodegen.AssignExp)e); } 93 } 94 95 /** 96 * The PermissiveVisitor overrides the root AST nodes with 97 * empty visiting methods. 98 */ 99 extern (C++) class SemanticTimePermissiveVisitor : Visitor 100 { 101 alias visit = Visitor.visit; 102 103 override void visit(ASTCodegen.Dsymbol){} 104 override void visit(ASTCodegen.Parameter){} 105 override void visit(ASTCodegen.Statement){} 106 override void visit(ASTCodegen.Type){} 107 override void visit(ASTCodegen.Expression){} 108 override void visit(ASTCodegen.TemplateParameter){} 109 override void visit(ASTCodegen.Condition){} 110 override void visit(ASTCodegen.Initializer){} 111 } 112 113 /** 114 * The TransitiveVisitor implements the AST traversal logic for all AST nodes. 115 */ 116 extern (C++) class SemanticTimeTransitiveVisitor : SemanticTimePermissiveVisitor 117 { 118 alias visit = SemanticTimePermissiveVisitor.visit; 119 120 mixin ParseVisitMethods!ASTCodegen __methods; 121 alias visit = __methods.visit; 122 123 override void visit(ASTCodegen.PeelStatement s) 124 { 125 if (s.s) 126 s.s.accept(this); 127 } 128 129 override void visit(ASTCodegen.UnrolledLoopStatement s) 130 { 131 foreach(sx; *s.statements) 132 { 133 if (sx) 134 sx.accept(this); 135 } 136 } 137 138 override void visit(ASTCodegen.DebugStatement s) 139 { 140 if (s.statement) 141 s.statement.accept(this); 142 } 143 144 override void visit(ASTCodegen.ForwardingStatement s) 145 { 146 if (s.statement) 147 s.statement.accept(this); 148 } 149 150 override void visit(ASTCodegen.StructLiteralExp e) 151 { 152 // CTFE can generate struct literals that contain an AddrExp pointing to themselves, 153 // need to avoid infinite recursion. 154 if (!(e.stageflags & stageToCBuffer)) 155 { 156 const old = e.stageflags; 157 e.stageflags |= stageToCBuffer; 158 foreach (el; *e.elements) 159 if (el) 160 el.accept(this); 161 e.stageflags = old; 162 } 163 } 164 165 override void visit(ASTCodegen.CompoundLiteralExp e) 166 { 167 if (e.initializer) 168 e.initializer.accept(this); 169 } 170 171 override void visit(ASTCodegen.DotTemplateExp e) 172 { 173 e.e1.accept(this); 174 } 175 176 override void visit(ASTCodegen.DotVarExp e) 177 { 178 e.e1.accept(this); 179 } 180 181 override void visit(ASTCodegen.DelegateExp e) 182 { 183 if (!e.func.isNested() || e.func.needThis()) 184 e.e1.accept(this); 185 } 186 187 override void visit(ASTCodegen.DotTypeExp e) 188 { 189 e.e1.accept(this); 190 } 191 192 override void visit(ASTCodegen.VectorExp e) 193 { 194 visitType(e.to); 195 e.e1.accept(this); 196 } 197 198 override void visit(ASTCodegen.VectorArrayExp e) 199 { 200 e.e1.accept(this); 201 } 202 203 override void visit(ASTCodegen.SliceExp e) 204 { 205 e.e1.accept(this); 206 if (e.upr) 207 e.upr.accept(this); 208 if (e.lwr) 209 e.lwr.accept(this); 210 } 211 212 override void visit(ASTCodegen.ArrayLengthExp e) 213 { 214 e.e1.accept(this); 215 } 216 217 override void visit(ASTCodegen.DelegatePtrExp e) 218 { 219 e.e1.accept(this); 220 } 221 222 override void visit(ASTCodegen.DelegateFuncptrExp e) 223 { 224 e.e1.accept(this); 225 } 226 227 override void visit(ASTCodegen.DotExp e) 228 { 229 e.e1.accept(this); 230 e.e2.accept(this); 231 } 232 233 override void visit(ASTCodegen.IndexExp e) 234 { 235 e.e1.accept(this); 236 e.e2.accept(this); 237 } 238 239 override void visit(ASTCodegen.RemoveExp e) 240 { 241 e.e1.accept(this); 242 e.e2.accept(this); 243 } 244 245 override void visit(ASTCodegen.LoweredAssignExp e) 246 { 247 e.lowering.accept(this); 248 visit(cast(AssignExp)e); 249 } 250 } 251 252 extern (C++) class StoppableVisitor : Visitor 253 { 254 alias visit = Visitor.visit; 255 public: 256 bool stop; 257 258 final extern (D) this() scope 259 { 260 } 261 }