| 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 |