Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 /** | 5 /** |
| 6 * Top level generator object for writing code and keeping track of | 6 * Top level generator object for writing code and keeping track of |
| 7 * dependencies. | 7 * dependencies. |
| 8 * | 8 * |
| 9 * Should have two compilation models, but only one implemented so far. | 9 * Should have two compilation models, but only one implemented so far. |
| 10 * | 10 * |
| 11 * 1. Do a top-level resolution of all types and their members. | 11 * 1. Do a top-level resolution of all types and their members. |
| 12 * 2. Start from main and walk the call-graph compiling members as needed. | 12 * 2. Start from main and walk the call-graph compiling members as needed. |
| 13 * 2a. That includes compiling overriding methods and calling methods by | 13 * 2a. That includes compiling overriding methods and calling methods by |
| 14 * selector when invoked on var. | 14 * selector when invoked on var. |
| 15 * 3. Spit out all required code. | 15 * 3. Spit out all required code. |
| 16 */ | 16 */ |
| 17 class WorldGenerator { | 17 class WorldGenerator { |
| 18 MethodMember main; | 18 MethodMember main; |
| 19 CodeWriter writer; | 19 CodeWriter writer; |
| 20 CodeWriter _mixins; | |
|
jimhug
2011/12/14 19:00:57
<smile>
| |
| 20 | 21 |
| 21 /** | 22 /** |
| 22 * Whether the app has any static fields used. Note this could still be true | 23 * Whether the app has any static fields used. Note this could still be true |
| 23 * and [globals] be empty if no static field has a default initialization. | 24 * and [globals] be empty if no static field has a default initialization. |
| 24 */ | 25 */ |
| 25 bool hasStatics = false; | 26 bool hasStatics = false; |
| 26 | 27 |
| 27 /** Global const and static field initializations. */ | 28 /** Global const and static field initializations. */ |
| 28 Map<String, GlobalValue> globals; | 29 Map<String, GlobalValue> globals; |
| 29 CoreJs corejs; | 30 CoreJs corejs; |
| 30 bool _inheritsGenerated = false; | 31 bool _inheritsGenerated = false; |
| 31 | 32 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 53 new Arguments(null, [main._get(metaGen, main.definition, null)])); | 54 new Arguments(null, [main._get(metaGen, main.definition, null)])); |
| 54 } | 55 } |
| 55 | 56 |
| 56 writeTypes(world.coreimpl); | 57 writeTypes(world.coreimpl); |
| 57 writeTypes(world.corelib); | 58 writeTypes(world.corelib); |
| 58 | 59 |
| 59 // Write the main library. This will cause all libraries to be written in | 60 // Write the main library. This will cause all libraries to be written in |
| 60 // the topographic sort order. | 61 // the topographic sort order. |
| 61 writeTypes(main.declaringType.library); | 62 writeTypes(main.declaringType.library); |
| 62 | 63 |
| 64 // Write out any inherited concrete members. | |
| 65 if (_mixins != null) writer.write(_mixins.text); | |
| 66 | |
| 63 writeGlobals(); | 67 writeGlobals(); |
| 64 writer.writeln('${mainCall.code};'); | 68 writer.writeln('${mainCall.code};'); |
| 65 } | 69 } |
| 66 | 70 |
| 67 GlobalValue globalForStaticField(FieldMember field, Value fieldValue, | 71 GlobalValue globalForStaticField(FieldMember field, Value fieldValue, |
| 68 List<Value> dependencies) { | 72 List<Value> dependencies) { |
| 69 hasStatics = true; | 73 hasStatics = true; |
| 70 var fullname = "${field.declaringType.jsname}.${field.jsname}"; | 74 var fullname = "${field.declaringType.jsname}.${field.jsname}"; |
| 71 if (!globals.containsKey(fullname)) { | 75 if (!globals.containsKey(fullname)) { |
| 72 globals[fullname] = new GlobalValue.fromStatic( | 76 globals[fullname] = new GlobalValue.fromStatic( |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 | 198 |
| 195 for (var c in type.constructors.getValues()) { | 199 for (var c in type.constructors.getValues()) { |
| 196 if (c.generator != null && c != standardConstructor) { | 200 if (c.generator != null && c != standardConstructor) { |
| 197 c.generator.writeDefinition(writer, null); | 201 c.generator.writeDefinition(writer, null); |
| 198 } | 202 } |
| 199 } | 203 } |
| 200 } | 204 } |
| 201 | 205 |
| 202 if (!type.isTop) { | 206 if (!type.isTop) { |
| 203 if (type is ConcreteType) { | 207 if (type is ConcreteType) { |
| 208 ConcreteType c = type; | |
| 204 _ensureInheritsHelper(); | 209 _ensureInheritsHelper(); |
| 205 writer.writeln( | 210 writer.writeln('\$inherits(${c.jsname}, ${c.genericType.jsname});'); |
| 206 '\$inherits(${type.jsname}, ${type.genericType.jsname});'); | 211 |
| 212 // Mixin members from concrete specializations of base types too. | |
| 213 // TODO(jmesserly): emit this sooner instead of at the end. | |
| 214 // But it needs to come after we've emitted both types. | |
| 215 // TODO(jmesserly): HACK: using _parent instead of parent so we don't | |
| 216 // try to inherit things that we didn't actually use. | |
| 217 for (var p = c._parent; p is ConcreteType; p = p._parent) { | |
| 218 _ensureInheritMembersHelper(); | |
| 219 _mixins.writeln('\$inheritsMembers(${c.jsname}, ${p.jsname});'); | |
| 220 } | |
| 207 } else if (!type.isNativeType) { | 221 } else if (!type.isNativeType) { |
| 208 if (type.parent != null && !type.parent.isObject) { | 222 if (type.parent != null && !type.parent.isObject) { |
| 209 _ensureInheritsHelper(); | 223 _ensureInheritsHelper(); |
| 210 writer.writeln('\$inherits(${type.jsname}, ${type.parent.jsname});'); | 224 writer.writeln('\$inherits(${type.jsname}, ${type.parent.jsname});'); |
| 211 } | 225 } |
| 212 } | 226 } |
| 213 } | 227 } |
| 214 | 228 |
| 215 // Concrete types (like List<String>) will have this already defined on | 229 // Concrete types (like List<String>) will have this already defined on |
| 216 // their prototype from the generic type (like List) | 230 // their prototype from the generic type (like List) |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 child.prototype.__proto__ = parent.prototype; | 294 child.prototype.__proto__ = parent.prototype; |
| 281 } else { | 295 } else { |
| 282 function tmp() {}; | 296 function tmp() {}; |
| 283 tmp.prototype = parent.prototype; | 297 tmp.prototype = parent.prototype; |
| 284 child.prototype = new tmp(); | 298 child.prototype = new tmp(); |
| 285 child.prototype.constructor = child; | 299 child.prototype.constructor = child; |
| 286 } | 300 } |
| 287 }"""); | 301 }"""); |
| 288 } | 302 } |
| 289 | 303 |
| 304 /** | |
| 305 * Generates the $inheritsMembers function when it's first used. | |
| 306 * This is used to mix in specialized generic members from the base class. | |
| 307 */ | |
| 308 _ensureInheritMembersHelper() { | |
| 309 if (_mixins != null) return; | |
| 310 _mixins = new CodeWriter(); | |
| 311 _mixins.comment('// ********** Generic Type Inheritance **************'); | |
| 312 _mixins.writeln(@""" | |
| 313 /** Implements extends for generic types. */ | |
| 314 function $inheritsMembers(child, parent) { | |
| 315 child = child.prototype; | |
| 316 parent = parent.prototype; | |
| 317 Object.getOwnPropertyNames(parent).forEach(function(name) { | |
| 318 if (typeof(child[name]) == 'undefined') child[name] = parent[name]; | |
| 319 }); | |
| 320 }"""); | |
|
Siggi Cherem (dart-lang)
2011/11/18 20:09:58
should this code be in corejs.dart?
Jennifer Messerly
2011/11/18 21:30:07
Similar to _ensureInherits, it can't be, because w
| |
| 321 } | |
| 322 | |
| 290 _writeDynamicStubs(Type type) { | 323 _writeDynamicStubs(Type type) { |
| 291 if (type.varStubs != null) { | 324 if (type.varStubs != null) { |
| 292 for (var stub in orderValuesByKeys(type.varStubs)) { | 325 for (var stub in orderValuesByKeys(type.varStubs)) { |
| 293 stub.generate(writer); | 326 stub.generate(writer); |
| 294 } | 327 } |
| 295 } | 328 } |
| 296 } | 329 } |
| 297 | 330 |
| 298 _writeStaticField(FieldMember field) { | 331 _writeStaticField(FieldMember field) { |
| 299 // Final static fields must be constants which will be folded and inlined. | 332 // Final static fields must be constants which will be folded and inlined. |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 var optional = "['" + Strings.join(optNames, "', '") + "']"; | 843 var optional = "['" + Strings.join(optNames, "', '") + "']"; |
| 811 defWriter.writeln('${start}${meth.jsname}.\$optional = $optional'); | 844 defWriter.writeln('${start}${meth.jsname}.\$optional = $optional'); |
| 812 } | 845 } |
| 813 } | 846 } |
| 814 } | 847 } |
| 815 } | 848 } |
| 816 | 849 |
| 817 writeBody() { | 850 writeBody() { |
| 818 var initializers = null; | 851 var initializers = null; |
| 819 var initializedFields = null; // to check that final fields are initialized | 852 var initializedFields = null; // to check that final fields are initialized |
| 853 var allMembers = null; | |
| 820 if (method.isConstructor) { | 854 if (method.isConstructor) { |
| 821 initializers = []; | 855 initializers = []; |
| 822 initializedFields = new Set(); | 856 initializedFields = new Set(); |
| 823 for (var f in world.gen._orderValues(method.declaringType.getAllMembers()) ) { | 857 allMembers = world.gen._orderValues(method.declaringType.getAllMembers()); |
| 824 if (f is FieldMember && !f.isStatic) { | 858 for (var f in allMembers) { |
| 859 if (f.isField && !f.isStatic) { | |
| 825 var cv = f.computeValue(); | 860 var cv = f.computeValue(); |
| 826 if (cv != null) { | 861 if (cv != null) { |
| 827 initializers.add('this.${f.jsname} = ${cv.code}'); | 862 initializers.add('this.${f.jsname} = ${cv.code}'); |
| 828 initializedFields.add(f.name); | 863 initializedFields.add(f.name); |
| 829 } | 864 } |
| 830 } | 865 } |
| 831 } | 866 } |
| 832 } | 867 } |
| 833 | 868 |
| 834 // Collects parameters for writing signature in the future. | 869 // Collects parameters for writing signature in the future. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 939 world.error( | 974 world.error( |
| 940 'no initialization allowed on redirecting constructors', | 975 'no initialization allowed on redirecting constructors', |
| 941 init.span); | 976 init.span); |
| 942 } | 977 } |
| 943 initializedFields = null; | 978 initializedFields = null; |
| 944 } | 979 } |
| 945 } | 980 } |
| 946 | 981 |
| 947 // check that initialization was correct | 982 // check that initialization was correct |
| 948 if (initializedFields != null) { | 983 if (initializedFields != null) { |
| 949 for (var name in method.declaringType.members.getKeys()) { | 984 for (var member in allMembers) { |
| 950 var member = method.declaringType.members[name]; | 985 if (member.isField && member.isFinal && !member.isStatic |
| 951 if (member is FieldMember && member.isFinal && !member.isStatic | 986 && !initializedFields.contains(member.name)) { |
| 952 && !initializedFields.contains(name)) { | 987 world.error('Field "${member.name}" is final and was not initialized', |
| 953 world.error('Field "${name}" is final and was not initialized', | |
| 954 method.definition.span); | 988 method.definition.span); |
| 955 } | 989 } |
| 956 } | 990 } |
| 957 } | 991 } |
| 958 | 992 |
| 959 visitStatementsInBlock(body); | 993 visitStatementsInBlock(body); |
| 960 } | 994 } |
| 961 | 995 |
| 962 /** | 996 /** |
| 963 * Calls another constructor (super, super.name, this, this.name). Returns | 997 * Calls another constructor (super, super.name, this, this.name). Returns |
| (...skipping 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2317 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); | 2351 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); |
| 2318 } | 2352 } |
| 2319 for (int i = bareCount; i < length; i++) { | 2353 for (int i = bareCount; i < length; i++) { |
| 2320 var name = getName(i); | 2354 var name = getName(i); |
| 2321 if (name == null) name = '\$$i'; | 2355 if (name == null) name = '\$$i'; |
| 2322 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); | 2356 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); |
| 2323 } | 2357 } |
| 2324 return new Arguments(nodes, result); | 2358 return new Arguments(nodes, result); |
| 2325 } | 2359 } |
| 2326 } | 2360 } |
| OLD | NEW |