OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class NativeEmitter { | 5 class NativeEmitter { |
6 | 6 |
7 Compiler compiler; | 7 Compiler compiler; |
8 StringBuffer buffer; | 8 StringBuffer buffer; |
9 | 9 |
10 // Classes that participate in dynamic dispatch. These are the | 10 // Classes that participate in dynamic dispatch. These are the |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 Set<ClassElement> seen = new Set<ClassElement>(); | 199 Set<ClassElement> seen = new Set<ClassElement>(); |
200 List<ClassElement> classes = <ClassElement>[]; | 200 List<ClassElement> classes = <ClassElement>[]; |
201 void visit(ClassElement cls) { | 201 void visit(ClassElement cls) { |
202 if (seen.contains(cls)) return; | 202 if (seen.contains(cls)) return; |
203 seen.add(cls); | 203 seen.add(cls); |
204 for (final ClassElement subclass in getDirectSubclasses(cls)) { | 204 for (final ClassElement subclass in getDirectSubclasses(cls)) { |
205 visit(subclass); | 205 visit(subclass); |
206 } | 206 } |
207 classes.add(cls); | 207 classes.add(cls); |
208 } | 208 } |
209 for (final ClassElement cls in classesWithDynamicDispatch) { | 209 for (final ClassElement classElement in classesWithDynamicDispatch) { |
210 visit(cls); | 210 visit(classElement); |
211 } | 211 } |
212 | 212 |
213 Collection<ClassElement> dispatchClasses = classes.filter( | 213 Collection<ClassElement> dispatchClasses = classes.filter( |
214 (cls) => !getDirectSubclasses(cls).isEmpty() && | 214 (cls) => !getDirectSubclasses(cls).isEmpty() && |
215 classesWithDynamicDispatch.contains(cls)); | 215 classesWithDynamicDispatch.contains(cls)); |
216 | 216 |
217 buffer.add('// ${classes.length} classes\n'); | 217 buffer.add('// ${classes.length} classes\n'); |
218 Collection<ClassElement> classesThatHaveSubclasses = classes.filter( | 218 Collection<ClassElement> classesThatHaveSubclasses = classes.filter( |
219 (ClassElement t) => !getDirectSubclasses(t).isEmpty()); | 219 (ClassElement t) => !getDirectSubclasses(t).isEmpty()); |
220 buffer.add('// ${classesThatHaveSubclasses.length} !leaf\n'); | 220 buffer.add('// ${classesThatHaveSubclasses.length} !leaf\n'); |
(...skipping 11 matching lines...) Expand all Loading... |
232 // the test, replacing dozens of HTMLxxxElement classes with the regexp | 232 // the test, replacing dozens of HTMLxxxElement classes with the regexp |
233 // /HTML.*Element/. | 233 // /HTML.*Element/. |
234 | 234 |
235 // Temporary variables for common substrings. | 235 // Temporary variables for common substrings. |
236 List<String> varNames = <String>[]; | 236 List<String> varNames = <String>[]; |
237 // var -> expression | 237 // var -> expression |
238 Map<String, String> varDefns = <String>{}; | 238 Map<String, String> varDefns = <String>{}; |
239 // tag -> expression (a string or a variable) | 239 // tag -> expression (a string or a variable) |
240 Map<ClassElement, String> tagDefns = new Map<ClassElement, String>(); | 240 Map<ClassElement, String> tagDefns = new Map<ClassElement, String>(); |
241 | 241 |
242 String makeExpression(ClassElement cls) { | 242 String makeExpression(ClassElement classElement) { |
243 // Expression fragments for this set of cls keys. | 243 // Expression fragments for this set of cls keys. |
244 List<String> expressions = <String>[]; | 244 List<String> expressions = <String>[]; |
245 // TODO: Remove if cls is abstract. | 245 // TODO: Remove if cls is abstract. |
246 List<String> subtags = [toNativeName(cls)]; | 246 List<String> subtags = [toNativeName(classElement)]; |
247 void walk(ClassElement cls) { | 247 void walk(ClassElement cls) { |
248 for (final ClassElement subclass in getDirectSubclasses(cls)) { | 248 for (final ClassElement subclass in getDirectSubclasses(cls)) { |
249 ClassElement tag = subclass; | 249 ClassElement tag = subclass; |
250 String existing = tagDefns[tag]; | 250 String existing = tagDefns[tag]; |
251 if (existing == null) { | 251 if (existing == null) { |
252 subtags.add(toNativeName(tag)); | 252 subtags.add(toNativeName(tag)); |
253 walk(subclass); | 253 walk(subclass); |
254 } else { | 254 } else { |
255 if (varDefns.containsKey(existing)) { | 255 if (varDefns.containsKey(existing)) { |
256 expressions.add(existing); | 256 expressions.add(existing); |
257 } else { | 257 } else { |
258 String varName = 'v${varNames.length}/*${tag}*/'; | 258 String varName = 'v${varNames.length}/*${tag}*/'; |
259 varNames.add(varName); | 259 varNames.add(varName); |
260 varDefns[varName] = existing; | 260 varDefns[varName] = existing; |
261 tagDefns[tag] = varName; | 261 tagDefns[tag] = varName; |
262 expressions.add(varName); | 262 expressions.add(varName); |
263 } | 263 } |
264 } | 264 } |
265 } | 265 } |
266 } | 266 } |
267 walk(cls); | 267 walk(classElement); |
268 String constantPart = "'${Strings.join(subtags, '|')}'"; | 268 String constantPart = "'${Strings.join(subtags, '|')}'"; |
269 if (constantPart != "''") expressions.add(constantPart); | 269 if (constantPart != "''") expressions.add(constantPart); |
270 String expression; | 270 String expression; |
271 if (expressions.length == 1) { | 271 if (expressions.length == 1) { |
272 expression = expressions[0]; | 272 expression = expressions[0]; |
273 } else { | 273 } else { |
274 expression = "[${Strings.join(expressions, ',')}].join('|')"; | 274 expression = "[${Strings.join(expressions, ',')}].join('|')"; |
275 } | 275 } |
276 return expression; | 276 return expression; |
277 } | 277 } |
278 | 278 |
279 for (final ClassElement cls in dispatchClasses) { | 279 for (final ClassElement classElement in dispatchClasses) { |
280 tagDefns[cls] = makeExpression(cls); | 280 tagDefns[classElement] = makeExpression(classElement); |
281 } | 281 } |
282 | 282 |
283 // Write out a thunk that builds the metadata. | 283 // Write out a thunk that builds the metadata. |
284 | 284 |
285 if (!tagDefns.isEmpty()) { | 285 if (!tagDefns.isEmpty()) { |
286 buffer.add('(function(){\n'); | 286 buffer.add('(function(){\n'); |
287 | 287 |
288 for (final String varName in varNames) { | 288 for (final String varName in varNames) { |
289 buffer.add(' var ${varName} = ${varDefns[varName]};\n'); | 289 buffer.add(' var ${varName} = ${varDefns[varName]};\n'); |
290 } | 290 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 String toStringName = compiler.namer.instanceMethodName( | 354 String toStringName = compiler.namer.instanceMethodName( |
355 null, const SourceString('toString'), 0); | 355 null, const SourceString('toString'), 0); |
356 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); | 356 objectProperties.add("$defPropName(Object.prototype, '$toStringName', "); |
357 objectProperties.add( | 357 objectProperties.add( |
358 'function() { return $toStringHelperName(this); });\n'); | 358 'function() { return $toStringHelperName(this); });\n'); |
359 | 359 |
360 // Finally, emit the code in the main buffer. | 360 // Finally, emit the code in the main buffer. |
361 targetBuffer.add('(function() {\n$objectProperties$buffer\n})();\n'); | 361 targetBuffer.add('(function() {\n$objectProperties$buffer\n})();\n'); |
362 } | 362 } |
363 } | 363 } |
OLD | NEW |