Mercurial > projects > dil
annotate trunk/src/dil/ast/Visitor.d @ 754:c7a5499faa77
Improved DDoc related code.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Wed, 13 Feb 2008 17:10:55 +0100 |
parents | ca7607226caa |
children | e4b60543c5e8 |
rev | line source |
---|---|
635 | 1 /++ |
2 Author: Aziz Köksal | |
3 License: GPL3 | |
4 +/ | |
5 module dil.ast.Visitor; | |
6 | |
7 import dil.ast.Node; | |
8 import dil.ast.Declarations, | |
9 dil.ast.Expressions, | |
10 dil.ast.Statements, | |
11 dil.ast.Types, | |
12 dil.ast.Parameters; | |
13 | |
14 /++ | |
649
3ebe76ad680e
Using SemanticPass1 in main.d do start semantic analysis.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
648
diff
changeset
|
15 Generate visit methods. |
635 | 16 E.g.: |
649
3ebe76ad680e
Using SemanticPass1 in main.d do start semantic analysis.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
648
diff
changeset
|
17 Declaration visit(ClassDeclaration){return null;}; |
3ebe76ad680e
Using SemanticPass1 in main.d do start semantic analysis.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
648
diff
changeset
|
18 Expression visit(CommaExpression){return null;}; |
635 | 19 +/ |
649
3ebe76ad680e
Using SemanticPass1 in main.d do start semantic analysis.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
648
diff
changeset
|
20 char[] generateVisitMethods() |
635 | 21 { |
22 char[] text; | |
23 foreach (className; classNames) | |
667
1ac758cd952a
Fixed a few things in DefaultVisitor.d and Pass1.d
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
655
diff
changeset
|
24 text ~= "returnType!(\""~className~"\") visit("~className~" node){return node;}\n"; |
635 | 25 return text; |
26 } | |
27 // pragma(msg, generateAbstractVisitMethods()); | |
28 | |
29 /// Gets the appropriate return type for the provided class. | |
30 template returnType(char[] className) | |
31 { | |
32 static if (is(typeof(mixin(className)) : Declaration)) | |
33 alias Declaration returnType; | |
34 else | |
35 static if (is(typeof(mixin(className)) : Statement)) | |
36 alias Statement returnType; | |
37 else | |
38 static if (is(typeof(mixin(className)) : Expression)) | |
39 alias Expression returnType; | |
40 else | |
41 static if (is(typeof(mixin(className)) : TypeNode)) | |
42 alias TypeNode returnType; | |
43 else | |
44 alias Node returnType; | |
45 } | |
46 | |
47 /++ | |
731
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
48 Generate functions which do the second dispatch.$(BR) |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
49 E.g.:$(BR) |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
50 $(D_CODE |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
51 Expression visitCommaExpression(Visitor visitor, CommaExpression c) |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
52 { visitor.visit(c); }) |
635 | 53 |
731
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
54 The equivalent in the traditional visitor pattern would be:$(BR) |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
55 $(D_CODE |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
56 class CommaExpression : Expression |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
57 { |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
58 void accept(Visitor visitor) |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
59 { visitor.visit(this); } |
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
60 }) |
635 | 61 +/ |
62 char[] generateDispatchFunctions() | |
63 { | |
64 char[] text; | |
65 foreach (className; classNames) | |
66 text ~= "returnType!(\""~className~"\") visit"~className~"(Visitor visitor, "~className~" c)\n" | |
67 "{ return visitor.visit(c); }\n"; | |
68 return text; | |
69 } | |
70 // pragma(msg, generateDispatchFunctions()); | |
71 | |
72 /++ | |
73 The vtable holds a list of function pointers to the dispatch functions. | |
74 +/ | |
75 char[] generateVTable() | |
76 { | |
77 char[] text = "["; | |
78 foreach (className; classNames) | |
79 text ~= "cast(void*)&visit"~className~",\n"; | |
80 return text[0..$-2]~"]"; // slice away last ",\n" | |
81 } | |
82 // pragma(msg, generateVTable()); | |
83 | |
731
ca7607226caa
Added new module cmd.DDoc.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
667
diff
changeset
|
84 /// The visitor pattern. |
635 | 85 abstract class Visitor |
86 { | |
649
3ebe76ad680e
Using SemanticPass1 in main.d do start semantic analysis.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
648
diff
changeset
|
87 mixin(generateVisitMethods()); |
635 | 88 |
89 static | |
90 mixin(generateDispatchFunctions()); | |
91 | |
92 /// The dispatch table. | |
93 static const void*[] dispatch_vtable = mixin(generateVTable()); | |
94 static assert(dispatch_vtable.length == classNames.length, "vtable length doesn't match number of classes"); | |
95 | |
96 // Returns the dispatch function for n. | |
754
c7a5499faa77
Improved DDoc related code.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
731
diff
changeset
|
97 final T function(Visitor,T) getDispatchFunction(T)(T n) |
635 | 98 { |
99 return cast(T function(Visitor,T))dispatch_vtable[n.kind]; | |
100 } | |
101 | |
648
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
102 Declaration visit(Declaration n) |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
103 { return visitD(n); } |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
104 Statement visit(Statement n) |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
105 { return visitS(n); } |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
106 Expression visit(Expression n) |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
107 { return visitE(n); } |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
108 TypeNode visit(TypeNode n) |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
109 { return visitT(n); } |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
110 Node visit(Node n) |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
111 { return visitN(n); } |
4ae7b13aaac8
Moved some semantic() methods to SemanticPass1.
Aziz K?ksal <aziz.koeksal@gmail.com>
parents:
641
diff
changeset
|
112 |
635 | 113 Declaration visitD(Declaration n) |
114 { | |
115 // Do first dispatch. Second dispatch is done in the called function. | |
116 return getDispatchFunction(n)(this, n); | |
117 } | |
118 | |
119 Statement visitS(Statement n) | |
120 { | |
121 return getDispatchFunction(n)(this, n); | |
122 } | |
123 | |
124 Expression visitE(Expression n) | |
125 { | |
126 return getDispatchFunction(n)(this, n); | |
127 } | |
128 | |
129 TypeNode visitT(TypeNode n) | |
130 { | |
131 return getDispatchFunction(n)(this, n); | |
132 } | |
133 | |
134 Node visitN(Node n) | |
135 { | |
136 return getDispatchFunction(n)(this, n); | |
137 } | |
138 } |