OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
3 # for details. All rights reserved. Use of this source code is governed by a | |
4 # BSD-style license that can be found in the LICENSE file. | |
5 | |
6 '''Generates the many subtypes of Node as well as a NodeVisitor into | |
7 tree.g.dart.''' | |
8 | |
9 from codegen import CodeWriter | |
10 | |
11 class Node: | |
12 def __init__(self, name, properties=None): | |
13 if properties is None: | |
14 self.properties = [] | |
15 else: | |
16 self.properties = [p.strip().split() for p in properties.split(',')] | |
17 self.kind = self.__class__.__name__ | |
18 | |
19 self.name = name | |
20 if self.name.endswith('!'): | |
21 self.name = self.name[:-1] | |
22 self.fullname = self.name | |
23 else: | |
24 self.fullname = self.name + self.kind | |
25 | |
26 def write(self, cw): | |
27 cw.enterBlock('class %s extends %s {' % (self.fullname, self.kind)) | |
28 | |
29 for typ, name in self.properties: | |
30 cw.writeln('%s %s;', typ, name) | |
31 | |
32 args = ['this.%s' % name for typ, name in self.properties] | |
33 args.append('SourceSpan span') | |
34 | |
35 cw.writeln('') | |
36 | |
37 cw.writeln('%s(%s): super(span) {}', self.fullname, ', '.join(args)); | |
38 | |
39 cw.writeln('') | |
40 | |
41 cw.writeln('visit(TreeVisitor visitor) => visitor.visit%s(this);' | |
42 % self.fullname) | |
43 | |
44 cw.exitBlock('}') | |
45 | |
46 def writeVisitInterfaceMethod(self, cw): | |
47 cw.writeln('visit%s(%s node);', self.fullname, self.fullname) | |
48 | |
49 def writePrettyPrintMethod(self, cw): | |
50 cw.enterBlock('void visit%s(%s node) {' % (self.fullname, self.fullname)) | |
51 if oneLineProperties(self.properties): | |
52 cw.writeln( | |
53 'output.heading(%r + output.toValue(node.%s) + ")", node.span);' % | |
54 (self.fullname + '(', self.properties[0][1])) | |
55 else: | |
56 cw.writeln('output.heading(%r, node.span);' % self.fullname) | |
57 for typ, name in self.properties: | |
58 if isNodeType(typ): | |
59 cw.writeln('output.writeNode(%r, node.%s);', name, name) | |
60 elif isListType(typ): | |
61 innerType = typ[len('List<'):-1] | |
62 if isNodeType(innerType): | |
63 cw.writeln('output.writeNodeList(%r, node.%s);', name, name) | |
64 else: | |
65 cw.writeln('output.writeList(%r, node.%s);', name, name) | |
66 else: | |
67 cw.writeln('output.writeValue(%r, node.%s);', name, name) | |
68 cw.exitBlock('}') | |
69 | |
70 def oneLineProperties(properties): | |
71 if len(properties) != 1: return False | |
72 | |
73 propType = properties[0][0] | |
74 | |
75 if propType == 'Identifier': return True | |
76 if isNodeType(propType): return False | |
77 if isListType(propType): return False | |
78 | |
79 return True | |
80 | |
81 def isNodeType(typ): | |
82 return (typ.endswith('Expression') or typ.endswith('Statement') or | |
83 typ.endswith('Node') or typ.endswith('TypeReference') or | |
84 typ.endswith('Identifier') or typ.endswith('Definition')) | |
85 | |
86 def isListType(typ): | |
87 return typ.startswith('List<') | |
88 | |
89 class Expression(Node): pass | |
90 | |
91 class Statement(Node): pass | |
92 | |
93 class Definition(Node): pass | |
94 | |
95 class TypeReference(Node): pass | |
96 | |
97 nodes = [ | |
98 Definition('Directive', 'Identifier name, List<ArgumentNode> arguments'), | |
99 | |
100 Definition('Type', | |
101 'bool isClass, Identifier name, List<ParameterType> typeParameters, '+ | |
102 'List<TypeReference> extendsTypes, List<TypeReference> implementsTypes, '+ | |
103 'NativeType nativeType, DefaultTypeReference defaultType, '+ | |
104 'List<Statement> body'), | |
105 | |
106 Definition('FunctionType', | |
107 'FunctionDefinition func, List<ParameterType> typeParameters'), | |
108 | |
109 Definition('Variable', | |
110 'List<Token> modifiers, TypeReference type, List<Identifier> names,' + | |
111 'List<Expression> values'), | |
112 | |
113 Definition('Function', | |
114 'List<Token> modifiers, TypeReference returnType, Identifier name,' + | |
115 'List<FormalNode> formals, List<Expression> initializers, ' + | |
116 'String nativeBody, Statement body'), | |
117 | |
118 Statement('Return', 'Expression value'), | |
119 Statement('Throw', 'Expression value'), | |
120 Statement('Assert', 'Expression test'), | |
121 | |
122 Statement('Break', 'Identifier label'), | |
123 Statement('Continue', 'Identifier label'), | |
124 | |
125 Statement('If', | |
126 'Expression test, Statement trueBranch, Statement falseBranch'), | |
127 Statement('While', 'Expression test, Statement body'), | |
128 Statement('Do', 'Statement body, Expression test'), | |
129 Statement('For', | |
130 'Statement init, Expression test, List<Expression> step, Statement body'), | |
131 Statement('ForIn', | |
132 'DeclaredIdentifier item, Expression list, Statement body'), | |
133 | |
134 Statement('Try', | |
135 'Statement body, List<CatchNode> catches, Statement finallyBlock'), | |
136 Statement('Switch', 'Expression test, List<CaseNode> cases'), | |
137 | |
138 Statement('Block', 'List<Statement> body'), | |
139 | |
140 Statement('Labeled', 'Identifier name, Statement body'), | |
141 Statement('Expression', 'Expression body'), | |
142 Statement('Empty'), | |
143 Statement('Diet'), | |
144 | |
145 Expression('Lambda', 'FunctionDefinition func'), | |
146 Expression('Call', 'Expression target, List<ArgumentNode> arguments'), | |
147 | |
148 # These three desugar into Call, but that is handled in gen, not parser. | |
149 Expression('Index', 'Expression target, Expression index'), | |
150 Expression('Binary', 'Token op, Expression x, Expression y'), | |
151 Expression('Unary', 'Token op, Expression self'), | |
152 | |
153 Expression('Postfix', 'Expression body, Token op'), | |
154 | |
155 Expression('New', | |
156 'bool isConst, TypeReference type, Identifier name,' + | |
157 'List<ArgumentNode> arguments'), | |
158 | |
159 Expression('List', | |
160 'bool isConst, TypeReference itemType, List<Expression> values'), | |
161 Expression('Map', | |
162 'bool isConst, TypeReference keyType, TypeReference valueType,' + | |
163 'List<Expression> items'), | |
164 | |
165 Expression('Conditional', | |
166 'Expression test, Expression trueBranch, Expression falseBranch'), | |
167 | |
168 Expression('Is', 'bool isTrue, Expression x, TypeReference type'), | |
169 Expression('Paren', 'Expression body'), | |
170 Expression('Await', 'Expression body'), | |
171 | |
172 Expression('Dot', 'Expression self, Identifier name'), | |
173 Expression('Var', 'Identifier name'), | |
174 | |
175 Expression('This'), | |
176 Expression('Super'), | |
177 | |
178 Expression('Literal', 'Value value'), | |
179 | |
180 Expression('StringInterp', 'List<Expression> pieces'), | |
181 | |
182 # TODO(jimhug): Split into Simple and Qualified names | |
183 TypeReference('Simple', 'Type type'), | |
184 TypeReference('Name', | |
185 'bool isFinal, Identifier name, List<Identifier> names'), | |
186 | |
187 TypeReference('Generic', | |
188 'TypeReference baseType, List<TypeReference> typeArguments, int depth'), | |
189 TypeReference('Function', | |
190 'bool isFinal, FunctionDefinition func'), | |
191 # TODO(jimhug): This shouldn't be a subtype of TypeReference. | |
192 TypeReference('Default', 'bool oldFactory, NameTypeReference baseType, '+ | |
193 'List<ParameterType> typeParameters'), | |
194 | |
195 Node('Argument', 'Identifier label, Expression value'), | |
196 Node('Formal', | |
197 'bool isThis, bool isRest, TypeReference type, Identifier name,'+ | |
198 'Expression value'), | |
199 | |
200 Node('Catch', | |
201 'DeclaredIdentifier exception, DeclaredIdentifier trace, Statement body'), | |
202 Node('Case', | |
203 'Identifier label, List<Expression> cases, List<Statement> statements'), | |
204 | |
205 # Don't want to add Node to these names, use ! as convention to say so. | |
206 Node('TypeParameter!', 'Identifier name, TypeReference extendsType'), | |
207 | |
208 # TODO(jimhug): Consider removing this node and just using String. | |
209 Node('Identifier!', 'String name'), | |
210 | |
211 # Pseudo Expression for cover grammar approach | |
212 Expression('DeclaredIdentifier!', | |
213 'TypeReference type, Identifier name, bool isFinal'), | |
214 ] | |
215 | |
216 def main(): | |
217 cw = CodeWriter(__file__) | |
218 | |
219 for node in nodes: | |
220 node.write(cw) | |
221 cw.writeln() | |
222 | |
223 cw.writeln() | |
224 cw.enterBlock('interface TreeVisitor {') | |
225 for node in nodes: | |
226 node.writeVisitInterfaceMethod(cw) | |
227 cw.writeln() | |
228 | |
229 cw.exitBlock('}') | |
230 | |
231 cw.writeln() | |
232 cw.enterBlock('class TreePrinter implements TreeVisitor {') | |
233 | |
234 cw.writeln('var output;') | |
235 cw.writeln('TreePrinter(this.output) { output.printer = this; }') | |
236 for node in nodes: | |
237 node.writePrettyPrintMethod(cw) | |
238 cw.writeln() | |
239 cw.exitBlock('}') | |
240 | |
241 cw.writeToFile('tree') | |
242 | |
243 if __name__ == '__main__': main() | |
OLD | NEW |