1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity very high)
4 module dil.ast.DefaultVisitor;
5 
6 import dil.ast.Visitor,
7        dil.ast.Node,
8        dil.ast.Declarations,
9        dil.ast.Expressions,
10        dil.ast.Statements,
11        dil.ast.Types,
12        dil.ast.Parameters;
13 import common;
14 
15 /// Provides a visit() method which calls Visitor.visitN() on subnodes.
16 mixin template visitDefault(N, Ret = returnType!(N))
17 {
18   override Ret visit(N n)
19   {
20     foreach (i, T; N.CTTI_Types)
21     {
22       auto member = __traits(getMember, n, N.CTTI_Members[i]);
23       static if (is(T : Node)) // A Node?
24       {
25         if (!N.CTTI_MayBeNull[i] || member !is null)
26           visitN(member);
27       }
28       else
29       static if (is(T : E[], E : Node)) // A Node array?
30       {
31         foreach (x; member)
32           if (!N.CTTI_MayBeNull[i] || x !is null)
33             visitN(x);
34       }
35     }
36     static if (!is(Ret : void))
37       return n;
38   }
39 }
40 
41 /// Generates the default visit methods.
42 ///
43 /// E.g.:
44 /// ---
45 /// mixin visitDefault!(ClassDecl);
46 /// mixin visitDefault!(InterfaceDecl);
47 /// ---
48 char[] generateDefaultVisitMethods()
49 {
50   char[] code;
51   foreach (className; NodeClassNames)
52     code ~= "mixin visitDefault!(" ~ className ~ ");\n";
53   return code;
54 }
55 //pragma(msg, generateDefaultVisitMethods());
56 
57 /// Same as above but returns void.
58 char[] generateDefaultVisitMethods2()
59 {
60   char[] code;
61   foreach (className; NodeClassNames)
62     code ~= "mixin visitDefault!(" ~ className ~ ", void);\n";
63   return code;
64 }
65 
66 
67 /// This class provides default methods for
68 /// traversing nodes and their subnodes.
69 class DefaultVisitor : Visitor
70 {
71   // Comment out if too many errors are shown.
72   mixin(generateDefaultVisitMethods());
73 }
74 
75 /// This class provides default methods for
76 /// traversing nodes and their subnodes.
77 class DefaultVisitor2 : Visitor2
78 {
79   // Comment out if too many errors are shown.
80   mixin(generateDefaultVisitMethods2());
81 }