comparison trunk/src/dil/ast/Visitor.d @ 769:5e3ef1b2011c

Added and improved documentation.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 17 Feb 2008 02:21:55 +0100
parents e4b60543c5e8
children cf2ad5df025c
comparison
equal deleted inserted replaced
768:d84349a60f5c 769:5e3ef1b2011c
9 dil.ast.Expressions, 9 dil.ast.Expressions,
10 dil.ast.Statements, 10 dil.ast.Statements,
11 dil.ast.Types, 11 dil.ast.Types,
12 dil.ast.Parameters; 12 dil.ast.Parameters;
13 13
14 /++ 14 /// Generate visit methods.
15 Generate visit methods. 15 ///
16 E.g.: 16 /// E.g.:
17 Declaration visit(ClassDeclaration){return null;}; 17 /// ---
18 Expression visit(CommaExpression){return null;}; 18 /// Declaration visit(ClassDeclaration){return null;};
19 +/ 19 /// Expression visit(CommaExpression){return null;};
20 /// ---
20 char[] generateVisitMethods() 21 char[] generateVisitMethods()
21 { 22 {
22 char[] text; 23 char[] text;
23 foreach (className; classNames) 24 foreach (className; classNames)
24 text ~= "returnType!(\""~className~"\") visit("~className~" node){return node;}\n"; 25 text ~= "returnType!(\""~className~"\") visit("~className~" node){return node;}\n";
42 alias TypeNode returnType; 43 alias TypeNode returnType;
43 else 44 else
44 alias Node returnType; 45 alias Node returnType;
45 } 46 }
46 47
47 /++ 48 /// Generate functions which do the second dispatch.
48 Generate functions which do the second dispatch.$(BR) 49 ///
49 E.g.:$(BR) 50 /// E.g.:
50 $(D_CODE 51 /// ---
51 Expression visitCommaExpression(Visitor visitor, CommaExpression c) 52 /// Expression visitCommaExpression(Visitor visitor, CommaExpression c)
52 { visitor.visit(c); }) 53 /// { visitor.visit(c); /* Second dispatch. */ }
53 54 /// ---
54 The equivalent in the traditional visitor pattern would be:$(BR) 55 /// The equivalent in the traditional visitor pattern would be:
55 $(D_CODE 56 /// ---
56 class CommaExpression : Expression 57 /// class CommaExpression : Expression
57 { 58 /// {
58 void accept(Visitor visitor) 59 /// void accept(Visitor visitor)
59 { visitor.visit(this); } 60 /// { visitor.visit(this); }
60 }) 61 /// }
61 +/ 62 /// ---
62 char[] generateDispatchFunctions() 63 char[] generateDispatchFunctions()
63 { 64 {
64 char[] text; 65 char[] text;
65 foreach (className; classNames) 66 foreach (className; classNames)
66 text ~= "returnType!(\""~className~"\") visit"~className~"(Visitor visitor, "~className~" c)\n" 67 text ~= "returnType!(\""~className~"\") visit"~className~"(Visitor visitor, "~className~" c)\n"
68 return text; 69 return text;
69 } 70 }
70 // pragma(msg, generateDispatchFunctions()); 71 // pragma(msg, generateDispatchFunctions());
71 72
72 /++ 73 /++
73 The vtable holds a list of function pointers to the dispatch functions. 74 Generates an array of function pointers.
75
76 ---
77 [
78 cast(void*)&visitCommaExpression,
79 // etc.
80 ]
81 ---
74 +/ 82 +/
75 char[] generateVTable() 83 char[] generateVTable()
76 { 84 {
77 char[] text = "["; 85 char[] text = "[";
78 foreach (className; classNames) 86 foreach (className; classNames)
79 text ~= "cast(void*)&visit"~className~",\n"; 87 text ~= "cast(void*)&visit"~className~",\n";
80 return text[0..$-2]~"]"; // slice away last ",\n" 88 return text[0..$-2]~"]"; // slice away last ",\n"
81 } 89 }
82 // pragma(msg, generateVTable()); 90 // pragma(msg, generateVTable());
83 91
84 /// The visitor pattern. 92 /// Implements a variation of the visitor pattern.
93 ///
94 /// Inherited by classes that need to traverse a D syntax tree
95 /// and do computations, transformations and other things on it.
85 abstract class Visitor 96 abstract class Visitor
86 { 97 {
87 mixin(generateVisitMethods()); 98 mixin(generateVisitMethods());
88 99
89 static 100 static
90 mixin(generateDispatchFunctions()); 101 mixin(generateDispatchFunctions());
91 102
92 /// The dispatch table. 103 /// The table holding function pointers to the second dispatch functions.
93 static const void*[] dispatch_vtable = mixin(generateVTable()); 104 static const void*[] dispatch_vtable = mixin(generateVTable());
94 static assert(dispatch_vtable.length == classNames.length, "vtable length doesn't match number of classes"); 105 static assert(dispatch_vtable.length == classNames.length, "vtable length doesn't match number of classes");
95 106
96 // Returns the dispatch function for n. 107 /// Looks up the second dispatch function for n and returns that.
97 Node function(Visitor, Node) getDispatchFunction()(Node n) 108 Node function(Visitor, Node) getDispatchFunction()(Node n)
98 { 109 {
99 return cast(Node function(Visitor, Node))dispatch_vtable[n.kind]; 110 return cast(Node function(Visitor, Node))dispatch_vtable[n.kind];
100 } 111 }
101 112
113 /// The main and first dispatch function.
102 Node dispatch(Node n) 114 Node dispatch(Node n)
103 { // Do first dispatch. Second dispatch is done in the called function. 115 { // Second dispatch is done in the called function.
104 return getDispatchFunction(n)(this, n); 116 return getDispatchFunction(n)(this, n);
105 } 117 }
106 118
107 final: 119 final:
108 Declaration visit(Declaration n) 120 Declaration visit(Declaration n)