Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: frog/gen.dart

Issue 8746005: Fix a bunch of issues with 'hidden' DOM types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: removed dead code Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 *
(...skipping 10 matching lines...) Expand all
21 21
22 /** 22 /**
23 * 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
24 * 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.
25 */ 25 */
26 bool hasStatics = false; 26 bool hasStatics = false;
27 27
28 /** Global const and static field initializations. */ 28 /** Global const and static field initializations. */
29 Map<String, GlobalValue> globals; 29 Map<String, GlobalValue> globals;
30 CoreJs corejs; 30 CoreJs corejs;
31 bool _inheritsGenerated = false;
32 31
33 WorldGenerator(this.main, this.writer): globals = {}, corejs = new CoreJs(); 32 WorldGenerator(this.main, this.writer)
33 : globals = {}, corejs = new CoreJs();
34 34
35 run() { 35 run() {
36 var metaGen = new MethodGenerator(main, null); 36 var metaGen = new MethodGenerator(main, null);
37 var mainTarget = new Value.type(main.declaringType, main.span); 37 var mainTarget = new Value.type(main.declaringType, main.span);
38 var mainCall = main.invoke(metaGen, null, mainTarget, Arguments.EMPTY); 38 var mainCall = main.invoke(metaGen, null, mainTarget, Arguments.EMPTY);
39 main.declaringType.markUsed(); 39 main.declaringType.markUsed();
40 40
41 if (options.compileAll) { 41 if (options.compileAll) {
42 markLibraryUsed(world.corelib); 42 markLibraryUsed(world.corelib);
43 markLibraryUsed(main.declaringType.library); 43 markLibraryUsed(main.declaringType.library);
(...skipping 25 matching lines...) Expand all
69 } 69 }
70 70
71 writeTypes(world.coreimpl); 71 writeTypes(world.coreimpl);
72 writeTypes(world.corelib); 72 writeTypes(world.corelib);
73 73
74 // Write the main library. This will cause all libraries to be written in 74 // Write the main library. This will cause all libraries to be written in
75 // the topographic sort order. 75 // the topographic sort order.
76 writeTypes(main.declaringType.library); 76 writeTypes(main.declaringType.library);
77 77
78 // Write out any inherited concrete members. 78 // Write out any inherited concrete members.
79 // TODO(jmesserly): this won't need to come last once we are sorting types
80 // correctly.
79 if (_mixins != null) writer.write(_mixins.text); 81 if (_mixins != null) writer.write(_mixins.text);
80 82
81 writeGlobals(); 83 writeGlobals();
82 writer.writeln('${mainCall.code};'); 84 writer.writeln('${mainCall.code};');
83 } 85 }
84 86
85 void markLibraryUsed(Library l) { 87 void markLibraryUsed(Library l) {
86 if (l.isMarked) return; 88 if (l.isMarked) return;
87 l.isMarked = true; 89 l.isMarked = true;
88 90
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 corejs.generate(writer); 155 corejs.generate(writer);
154 } 156 }
155 for (var file in lib.natives) { 157 for (var file in lib.natives) {
156 var filename = basename(file.filename); 158 var filename = basename(file.filename);
157 writer.comment('// ********** Natives $filename **************'); 159 writer.comment('// ********** Natives $filename **************');
158 writer.writeln(file.text); 160 writer.writeln(file.text);
159 } 161 }
160 lib.topType.markUsed(); // TODO(jimhug): EGREGIOUS HACK 162 lib.topType.markUsed(); // TODO(jimhug): EGREGIOUS HACK
161 163
162 for (var type in _orderValues(lib.types)) { 164 for (var type in _orderValues(lib.types)) {
163 if (type.isUsed && type.isClass) { 165 // TODO(jmesserly): we can't accurately track if DOM types are
166 // created or not, so we need to prepare to handle them.
167 if ((type.isUsed || type.isHiddenNativeType) && type.isClass) {
164 writeType(type); 168 writeType(type);
165 169
166 if (type.isGeneric) { 170 if (type.isGeneric) {
167 for (var ct in _orderValues(type._concreteTypes)) { 171 for (var ct in _orderValues(type._concreteTypes)) {
168 writeType(ct); 172 writeType(ct);
169 } 173 }
170 } 174 }
171 } 175 } else if (type.isFunction && type.varStubs.length > 0) {
172 if (type.isFunction && type.varStubs != null) { 176 // Emit stubs on "Function" or hidden types if needed
173 // Emit stubs on "Function" if needed
174 writer.comment('// ********** Code for ${type.jsname} **************'); 177 writer.comment('// ********** Code for ${type.jsname} **************');
175 _writeDynamicStubs(type); 178 _writeDynamicStubs(type);
176 } 179 }
177 // Type check functions for builtin JS types 180 // Type check functions for builtin JS types
178 if (type.typeCheckCode != null) { 181 if (type.typeCheckCode != null) {
179 writer.writeln(type.typeCheckCode); 182 writer.writeln(type.typeCheckCode);
180 } 183 }
181 } 184 }
182 } 185 }
183 186
184 genMethod(Member meth, [MethodGenerator enclosingMethod=null]) { 187 genMethod(Member meth, [MethodGenerator enclosingMethod=null]) {
185 if (!meth.isGenerated && !meth.isAbstract && meth.definition != null) { 188 if (!meth.isGenerated && !meth.isAbstract && meth.definition != null) {
186 new MethodGenerator(meth, enclosingMethod).run(); 189 new MethodGenerator(meth, enclosingMethod).run();
187 } 190 }
188 } 191 }
189 192
193 String _prototypeOf(Type type, String name) {
194 if (type.isHiddenNativeType) {
195 corejs.ensureDynamicProto();
196 return '\$dynamic("$name").${type.jsname}';
197 } else {
198 return '${type.jsname}.prototype.$name';
199 }
200 }
201
190 _maybeIsTest(Type onType, Type checkType) { 202 _maybeIsTest(Type onType, Type checkType) {
191 if (!checkType.isTested) return; 203 bool isSubtype = onType.isSubtypeOf(checkType);
192 204 if (checkType.isTested) {
193 var value = 'false'; 205 // TODO(jmesserly): cache these functions? they just return true or false.
194 if (onType.isSubtypeOf(checkType)) { 206 writer.writeln(_prototypeOf(onType, 'is\$${checkType.jsname}')
195 value = 'function(){return this;}'; 207 + ' = function(){return $isSubtype};');
196 } 208 }
197 209
198 writer.writeln('${onType.jsname}.prototype.is\$${checkType.jsname} = ' 210 if (checkType.isChecked) {
199 + '$value;'); 211 String body = 'return this';
212 String checkName = 'assert\$${checkType.jsname}';
213 if (!isSubtype) {
214 // Get the code to throw a TypeError.
215 // TODO(jmesserly): it'd be nice not to duplicate this code, and instead
216 // be able to refer to the JS function.
217 body = world.objectType.varStubs[checkName].body;
218 }
219 writer.writeln(_prototypeOf(onType, checkName) + ' = function(){$body};');
220 }
200 } 221 }
201 222
202 writeType(Type type) { 223 writeType(Type type) {
203 // TODO(jimhug): Workaround for problems with reified generic Array. 224 // TODO(jimhug): Workaround for problems with reified generic Array.
204 if (type.name != null && type is ConcreteType && 225 if (type.name != null && type is ConcreteType &&
205 type.library == world.coreimpl && 226 type.library == world.coreimpl &&
206 type.name.startsWith('ListFactory')) { 227 type.name.startsWith('ListFactory')) {
207 writer.writeln('${type.jsname} = ${type.genericType.jsname};'); 228 writer.writeln('${type.jsname} = ${type.genericType.jsname};');
208 return; 229 return;
209 } 230 }
(...skipping 30 matching lines...) Expand all
240 for (var c in type.constructors.getValues()) { 261 for (var c in type.constructors.getValues()) {
241 if (c.generator != null && c != standardConstructor) { 262 if (c.generator != null && c != standardConstructor) {
242 c.generator.writeDefinition(writer, null); 263 c.generator.writeDefinition(writer, null);
243 } 264 }
244 } 265 }
245 } 266 }
246 267
247 if (!type.isTop) { 268 if (!type.isTop) {
248 if (type is ConcreteType) { 269 if (type is ConcreteType) {
249 ConcreteType c = type; 270 ConcreteType c = type;
250 _ensureInheritsHelper(); 271 corejs.ensureInheritsHelper();
251 writer.writeln('\$inherits(${c.jsname}, ${c.genericType.jsname});'); 272 writer.writeln('\$inherits(${c.jsname}, ${c.genericType.jsname});');
252 273
253 // Mixin members from concrete specializations of base types too. 274 // Mixin members from concrete specializations of base types too.
254 // TODO(jmesserly): emit this sooner instead of at the end. 275 // TODO(jmesserly): emit this sooner instead of at the end.
255 // But it needs to come after we've emitted both types. 276 // But it needs to come after we've emitted both types.
256 // TODO(jmesserly): HACK: using _parent instead of parent so we don't 277 // TODO(jmesserly): HACK: using _parent instead of parent so we don't
257 // try to inherit things that we didn't actually use. 278 // try to inherit things that we didn't actually use.
258 for (var p = c._parent; p is ConcreteType; p = p._parent) { 279 for (var p = c._parent; p is ConcreteType; p = p._parent) {
259 _ensureInheritMembersHelper(); 280 _ensureInheritMembersHelper();
260 _mixins.writeln('\$inheritsMembers(${c.jsname}, ${p.jsname});'); 281 _mixins.writeln('\$inheritsMembers(${c.jsname}, ${p.jsname});');
261 } 282 }
262 } else if (!type.isNative) { 283 } else if (!type.isNative) {
263 if (type.parent != null && !type.parent.isObject) { 284 if (type.parent != null && !type.parent.isObject) {
264 _ensureInheritsHelper(); 285 corejs.ensureInheritsHelper();
265 writer.writeln('\$inherits(${type.jsname}, ${type.parent.jsname});'); 286 writer.writeln('\$inherits(${type.jsname}, ${type.parent.jsname});');
266 } 287 }
267 } 288 }
268 } 289 }
269 290
270 // Concrete types (like List<String>) will have this already defined on 291 // Concrete types (like List<String>) will have this already defined on
271 // their prototype from the generic type (like List) 292 // their prototype from the generic type (like List)
272 if (type is! ConcreteType) { 293 if (type is! ConcreteType) {
273 _maybeIsTest(type, type); 294 _maybeIsTest(type, type);
274 } 295 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 334
314 if (member.isMethod) { 335 if (member.isMethod) {
315 _writeMethod(member); 336 _writeMethod(member);
316 } 337 }
317 } 338 }
318 339
319 _writeDynamicStubs(type); 340 _writeDynamicStubs(type);
320 } 341 }
321 342
322 /** 343 /**
323 * Generates the $inherits function when it's first used. Unlike some of the
324 * other helpers in [CoreJS], we don't notice that we need this one until
325 * we're generating types.
326 */
327 _ensureInheritsHelper() {
328 if (_inheritsGenerated) return;
329
330 _inheritsGenerated = true;
331 writer.writeln(@"""
332 /** Implements extends for Dart classes on JavaScript prototypes. */
333 function $inherits(child, parent) {
334 if (child.prototype.__proto__) {
335 child.prototype.__proto__ = parent.prototype;
336 } else {
337 function tmp() {};
338 tmp.prototype = parent.prototype;
339 child.prototype = new tmp();
340 child.prototype.constructor = child;
341 }
342 }""");
343 }
344
345 /**
346 * Generates the $inheritsMembers function when it's first used. 344 * Generates the $inheritsMembers function when it's first used.
347 * This is used to mix in specialized generic members from the base class. 345 * This is used to mix in specialized generic members from the base class.
348 */ 346 */
349 _ensureInheritMembersHelper() { 347 _ensureInheritMembersHelper() {
350 if (_mixins != null) return; 348 if (_mixins != null) return;
351 _mixins = new CodeWriter(); 349 _mixins = new CodeWriter();
352 _mixins.comment('// ********** Generic Type Inheritance **************'); 350 _mixins.comment('// ********** Generic Type Inheritance **************');
353 _mixins.writeln(@""" 351 _mixins.writeln(@"""
354 /** Implements extends for generic types. */ 352 /** Implements extends for generic types. */
355 function $inheritsMembers(child, parent) { 353 function $inheritsMembers(child, parent) {
356 child = child.prototype; 354 child = child.prototype;
357 parent = parent.prototype; 355 parent = parent.prototype;
358 Object.getOwnPropertyNames(parent).forEach(function(name) { 356 Object.getOwnPropertyNames(parent).forEach(function(name) {
359 if (typeof(child[name]) == 'undefined') child[name] = parent[name]; 357 if (typeof(child[name]) == 'undefined') child[name] = parent[name];
360 }); 358 });
361 }"""); 359 }""");
362 } 360 }
363 361
364 _writeDynamicStubs(Type type) { 362 _writeDynamicStubs(Type type) {
365 if (type.varStubs != null) { 363 for (var stub in orderValuesByKeys(type.varStubs)) {
366 for (var stub in orderValuesByKeys(type.varStubs)) { 364 stub.generate(writer);
367 stub.generate(writer);
368 }
369 } 365 }
370 } 366 }
371 367
372 _writeStaticField(FieldMember field) { 368 _writeStaticField(FieldMember field) {
373 // Final static fields must be constants which will be folded and inlined. 369 // Final static fields must be constants which will be folded and inlined.
374 if (field.isFinal) return; 370 if (field.isFinal) return;
375 371
376 var fullname = "${field.declaringType.jsname}.${field.jsname}"; 372 var fullname = "${field.declaringType.jsname}.${field.jsname}";
377 if (globals.containsKey(fullname)) { 373 if (globals.containsKey(fullname)) {
378 var value = globals[fullname]; 374 var value = globals[fullname];
379 if (field.declaringType.isTop && !field.isNative) { 375 if (field.declaringType.isTop && !field.isNative) {
380 writer.writeln('\$globals.${field.jsname} = ${value.exp.code};'); 376 writer.writeln('\$globals.${field.jsname} = ${value.exp.code};');
381 } else { 377 } else {
382 writer.writeln('\$globals.${field.declaringType.jsname}_${field.jsname}' 378 writer.writeln('\$globals.${field.declaringType.jsname}_${field.jsname}'
383 + ' = ${value.exp.code};'); 379 + ' = ${value.exp.code};');
384 } 380 }
385 } 381 }
386 // No need to write code for a static class field with no initial value. 382 // No need to write code for a static class field with no initial value.
387 } 383 }
388 384
389 _writeField(FieldMember field) { 385 _writeField(FieldMember field) {
390 // Generate declarations for static top-level fields with no value. 386 // Generate declarations for static top-level fields with no value.
391 if (field.declaringType.isTop && !field.isNative && field.value == null) { 387 if (field.declaringType.isTop && !field.isNative && field.value == null) {
392 writer.writeln('var ${field.jsname};'); 388 writer.writeln('var ${field.jsname};');
393 } 389 }
394 390
395 // generate code for instance fields 391 // generate code for instance fields
396 if (field._providePropertySyntax) { 392 if (field._providePropertySyntax) {
397 writer.writeln( 393 writer.writeln(_prototypeOf(field.declaringType, 'get\$${field.jsname}')
398 '${field.declaringType.jsname}.prototype.get\$${field.jsname} = ' + 394 + ' = function() { return this.${field.jsname}; };');
399 'function() { return this.${field.jsname}; };');
400 if (!field.isFinal) { 395 if (!field.isFinal) {
401 writer.writeln( 396 writer.writeln(_prototypeOf(field.declaringType, 'set\$${field.jsname}')
402 '${field.declaringType.jsname}.prototype.set\$${field.jsname} = ' + 397 + ' = function(value) { return this.${field.jsname} = value; };');
403 'function(value) { return this.${field.jsname} = value; };');
404 } 398 }
405 } 399 }
406 400
407 // TODO(jimhug): Currently choose not to initialize fields on objects, but 401 // TODO(jimhug): Currently choose not to initialize fields on objects, but
408 // instead to rely on uninitialized === null in our generated code. 402 // instead to rely on uninitialized === null in our generated code.
409 // Investigate the perf pros and cons of this. 403 // Investigate the perf pros and cons of this.
410 } 404 }
411 405
412 _writeProperty(PropertyMember property) { 406 _writeProperty(PropertyMember property) {
413 if (property.getter != null) _writeMethod(property.getter); 407 if (property.getter != null) _writeMethod(property.getter);
414 if (property.setter != null) _writeMethod(property.setter); 408 if (property.setter != null) _writeMethod(property.setter);
415 409
410 // TODO(jmesserly): make sure we don't do this on hidden native types!
416 if (property._provideFieldSyntax) { 411 if (property._provideFieldSyntax) {
417 writer.enterBlock('Object.defineProperty(' + 412 writer.enterBlock('Object.defineProperty(' +
418 '${property.declaringType.jsname}.prototype, "${property.jsname}", {'); 413 '${property.declaringType.jsname}.prototype, "${property.jsname}", {');
419 if (property.getter != null) { 414 if (property.getter != null) {
420 writer.write( 415 writer.write(
421 'get: ${property.declaringType.jsname}.prototype.${property.getter.jsn ame}'); 416 'get: ${property.declaringType.jsname}.prototype.${property.getter.jsn ame}');
422 // The shenanigan below is to make IE happy -- IE 9 doesn't like a 417 // The shenanigan below is to make IE happy -- IE 9 doesn't like a
423 // trailing comma on the last element in a list. 418 // trailing comma on the last element in a list.
424 writer.writeln(property.setter == null ? '' : ','); 419 writer.writeln(property.setter == null ? '' : ',');
425 } 420 }
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 initializedFields.add(f.name); 983 initializedFields.add(f.name);
989 writer.writeln('this.${f.jsname} = ${visitValue(init.y).code};'); 984 writer.writeln('this.${f.jsname} = ${visitValue(init.y).code};');
990 } else { 985 } else {
991 world.error('invalid initializer', init.span); 986 world.error('invalid initializer', init.span);
992 } 987 }
993 } 988 }
994 } 989 }
995 writer.comment('// Initializers done'); 990 writer.comment('// Initializers done');
996 } 991 }
997 992
998 if (method.isConstructor && initializerCall == null) { 993 if (method.isConstructor && initializerCall == null && !method.isNative) {
999 var parentType = method.declaringType.parent; 994 var parentType = method.declaringType.parent;
1000 if (parentType != null && !parentType.isObject) { 995 if (parentType != null && !parentType.isObject) {
1001 // TODO(jmesserly): we could omit this if all supertypes are using 996 // TODO(jmesserly): we could omit this if all supertypes are using
1002 // default constructors. 997 // default constructors.
1003 initializerCall = new CallExpression( 998 initializerCall = new CallExpression(
1004 new SuperExpression(method.span), [], method.span); 999 new SuperExpression(method.span), [], method.span);
1005 } 1000 }
1006 } 1001 }
1007 1002
1008 if (initializerCall != null) { 1003 if (initializerCall != null) {
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 } 1285 }
1291 } 1286 }
1292 return true; 1287 return true;
1293 } 1288 }
1294 1289
1295 bool visitAssertStatement(AssertStatement node) { 1290 bool visitAssertStatement(AssertStatement node) {
1296 // be sure to walk test for static checking even is asserts disabled 1291 // be sure to walk test for static checking even is asserts disabled
1297 var test = visitValue(node.test); // TODO(jimhug): check bool or callable. 1292 var test = visitValue(node.test); // TODO(jimhug): check bool or callable.
1298 if (options.enableAsserts) { 1293 if (options.enableAsserts) {
1299 var err = world.corelib.types['AssertError']; 1294 var err = world.corelib.types['AssertError'];
1300 world.gen.genMethod(err.getConstructor('')); 1295 world.gen.genMethod(err.getConstructor('_internal'));
1301 world.gen.genMethod(err.members['toString']); 1296 world.gen.genMethod(err.members['toString']);
1302 var span = node.test.span; 1297 var span = node.test.span;
1303 1298
1304 // TODO(jmesserly): do we need to include path/line/column here? 1299 // TODO(jmesserly): do we need to include path/line/column here?
1305 // It should be captured in the stack trace. 1300 // It should be captured in the stack trace.
1306 var line = span.file.getLine(span.start); 1301 var line = span.file.getLine(span.start);
1307 var column = span.file.getColumn(line, span.start); 1302 var column = span.file.getColumn(line, span.start);
1308 writer.writeln('\$assert(${test.code}, "${_escapeString(span.text)}",' + 1303 writer.writeln('\$assert(${test.code}, "${_escapeString(span.text)}",' +
1309 ' "${basename(span.file.filename)}", ${line + 1}, ${column + 1});'); 1304 ' "${basename(span.file.filename)}", ${line + 1}, ${column + 1});');
1310 world.gen.corejs.useAssert = true; 1305 world.gen.corejs.useAssert = true;
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2428 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false)); 2423 result.add(new Value(world.varType, '\$$i', null, /*needsTemp:*/false));
2429 } 2424 }
2430 for (int i = bareCount; i < length; i++) { 2425 for (int i = bareCount; i < length; i++) {
2431 var name = getName(i); 2426 var name = getName(i);
2432 if (name == null) name = '\$$i'; 2427 if (name == null) name = '\$$i';
2433 result.add(new Value(world.varType, name, null, /*needsTemp:*/false)); 2428 result.add(new Value(world.varType, name, null, /*needsTemp:*/false));
2434 } 2429 }
2435 return new Arguments(nodes, result); 2430 return new Arguments(nodes, result);
2436 } 2431 }
2437 } 2432 }
OLDNEW
« no previous file with comments | « frog/frogsh ('k') | frog/lib/corelib.dart » ('j') | frog/lib/corelib.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698