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