1 /** 2 * Development utility for printing AST nodes by their internal name, instead of as D source code. 3 * 4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved 5 * Authors: Stefan Koch 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/asttypename.d, _asttypename.d) 8 * Documentation: https://dlang.org/phobos/dmd_asttypename.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/asttypename.d 10 */ 11 12 module dmd.asttypename; 13 14 import dmd.ast_node; 15 import dmd.attrib; 16 import dmd.aliasthis; 17 import dmd.aggregate; 18 import dmd.cond; 19 import dmd.ctfeexpr; 20 import dmd.dclass; 21 import dmd.declaration; 22 import dmd.denum; 23 import dmd.dimport; 24 import dmd.declaration; 25 import dmd.dstruct; 26 import dmd.dsymbol; 27 import dmd.dtemplate; 28 import dmd.dversion; 29 import dmd.expression; 30 import dmd.func; 31 import dmd.denum; 32 import dmd.dimport; 33 import dmd.dmodule; 34 import dmd.mtype; 35 import dmd.identifier; 36 import dmd.init; 37 import dmd.root.complex; 38 import dmd.rootobject; 39 import dmd.statement; 40 import dmd.staticassert; 41 import dmd.nspace; 42 import dmd.visitor; 43 44 /// Returns: the typename of the dynamic ast-node-type 45 /// (this is a development tool, do not use in actual code) 46 string astTypeName(RootObject node) 47 { 48 final switch (node.dyncast()) 49 { 50 case DYNCAST.object: 51 return "RootObject"; 52 case DYNCAST.identifier: 53 return "Identifier"; 54 case DYNCAST.tuple: 55 return "Tuple"; 56 57 case DYNCAST.expression: 58 return astTypeName(cast(Expression) node); 59 case DYNCAST.dsymbol: 60 return astTypeName(cast(Dsymbol) node); 61 case DYNCAST.type: 62 return astTypeName(cast(Type) node); 63 case DYNCAST.parameter: 64 return astTypeName(cast(Parameter) node); 65 case DYNCAST.statement: 66 return astTypeName(cast(Statement) node); 67 case DYNCAST.condition: 68 return astTypeName(cast(Condition) node); 69 case DYNCAST.templateparameter: 70 return astTypeName(cast(TemplateParameter) node); 71 case DYNCAST.initializer: 72 return astTypeName(cast(Initializer) node); 73 } 74 } 75 76 extern(D) enum mixin_string = 77 ({ 78 string astTypeNameFunctions; 79 string visitOverloads; 80 81 foreach (ov; __traits(getOverloads, Visitor, "visit")) 82 { 83 static if (is(typeof(ov) P == function)) 84 { 85 static if (is(P[0] S == super) && is(S[0] == ASTNode)) 86 { 87 astTypeNameFunctions ~= ` 88 string astTypeName(` ~ P[0].stringof ~ ` node) 89 { 90 scope tsv = new AstTypeNameVisitor; 91 node.accept(tsv); 92 return tsv.typeName; 93 } 94 `; 95 } 96 97 visitOverloads ~= ` 98 override void visit (` ~ P[0].stringof ~ ` _) 99 { 100 typeName = "` ~ P[0].stringof ~ `"; 101 } 102 `; 103 } 104 } 105 106 return astTypeNameFunctions ~ ` 107 private extern(C++) final class AstTypeNameVisitor : Visitor 108 { 109 alias visit = Visitor.visit; 110 public : 111 string typeName; 112 ` ~ visitOverloads ~ "}"; 113 }()); 114 115 // pragma(msg, mixin_string); 116 mixin(mixin_string); 117 /// 118 unittest 119 { 120 import dmd.location; 121 Expression e = new TypeidExp(Loc.initial, null); 122 Tuple t = new Tuple(); 123 TemplateTypeParameter tp = new TemplateTypeParameter(Loc.initial, null, null, null); 124 assert(e.astTypeName == "TypeidExp"); 125 assert(t.astTypeName == "Tuple"); 126 assert(tp.astTypeName == "TemplateTypeParameter"); 127 }