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

Side by Side Diff: frog/leg/emitter.dart

Issue 9666006: Support for "a is Function". (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 months 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
« no previous file with comments | « frog/leg/compiler.dart ('k') | frog/leg/enqueue.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 18 matching lines...) Expand all
29 function tmp() {}; 29 function tmp() {};
30 tmp.prototype = parent.prototype; 30 tmp.prototype = parent.prototype;
31 child.prototype = new tmp(); 31 child.prototype = new tmp();
32 child.prototype.constructor = child; 32 child.prototype.constructor = child;
33 } 33 }
34 }'''; 34 }''';
35 35
36 bool addedInheritFunction = false; 36 bool addedInheritFunction = false;
37 final Namer namer; 37 final Namer namer;
38 final NativeEmitter nativeEmitter; 38 final NativeEmitter nativeEmitter;
39 Set<ClassElement> generatedClasses;
39 40
40 CodeEmitterTask(Compiler compiler) 41 CodeEmitterTask(Compiler compiler)
41 : namer = compiler.namer, 42 : namer = compiler.namer,
42 nativeEmitter = new NativeEmitter(compiler), 43 nativeEmitter = new NativeEmitter(compiler),
44 generatedClasses = new Set<ClassElement>(),
43 super(compiler); 45 super(compiler);
44 46
45 String get name() => 'CodeEmitter'; 47 String get name() => 'CodeEmitter';
46 48
47 String get inheritsName() => '${namer.ISOLATE}.\$inherits'; 49 String get inheritsName() => '${namer.ISOLATE}.\$inherits';
48 50
49 String get objectClassName() { 51 String get objectClassName() {
50 ClassElement objectClass = 52 ClassElement objectClass =
51 compiler.coreLibrary.find(const SourceString('Object')); 53 compiler.coreLibrary.find(const SourceString('Object'));
52 return namer.isolatePropertyAccess(objectClass); 54 return namer.isolatePropertyAccess(objectClass);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 generateFieldInit(element); 249 generateFieldInit(element);
248 } 250 }
249 for (Element element in classElement.backendMembers) { 251 for (Element element in classElement.backendMembers) {
250 generateFieldInit(element); 252 generateFieldInit(element);
251 } 253 }
252 254
253 classElement = classElement.superclass; 255 classElement = classElement.superclass;
254 } while(classElement !== null); 256 } while(classElement !== null);
255 } 257 }
256 258
257 void generateClass(ClassElement classElement, 259 void emitInherits(ClassElement cls, StringBuffer buffer) {
258 StringBuffer buffer, 260 ClassElement superclass = cls.superclass;
259 Set<ClassElement> seenClasses) {
260 if (seenClasses.contains(classElement)) return;
261 seenClasses.add(classElement);
262 ClassElement superclass = classElement.superclass;
263 if (superclass !== null) { 261 if (superclass !== null) {
264 generateClass(classElement.superclass, buffer, seenClasses); 262 addInheritFunctionIfNecessary(buffer);
263 String className = namer.isolatePropertyAccess(cls);
264 String superName = namer.isolatePropertyAccess(superclass);
265 buffer.add('${inheritsName}($className, $superName);\n');
265 } 266 }
267 }
268
269 void ensureGenerated(ClassElement classElement, StringBuffer buffer) {
270 if (classElement == null) return;
271 if (generatedClasses.contains(classElement)) return;
272 generatedClasses.add(classElement);
273 generateClass(classElement, buffer);
274 }
275
276 void generateClass(ClassElement classElement, StringBuffer buffer) {
277 ensureGenerated(classElement.superclass, buffer);
266 278
267 if (classElement.isNative()) { 279 if (classElement.isNative()) {
268 nativeEmitter.generateNativeClass(classElement, buffer); 280 nativeEmitter.generateNativeClass(classElement, buffer);
269 return; 281 return;
270 } 282 }
271 283
272 String className = namer.isolatePropertyAccess(classElement); 284 String className = namer.isolatePropertyAccess(classElement);
273 buffer.add('$className = function ${classElement.name.slowToString()}('); 285 buffer.add('$className = function ${classElement.name.slowToString()}(');
274 StringBuffer bodyBuffer = new StringBuffer(); 286 StringBuffer bodyBuffer = new StringBuffer();
275 // If the class is never instantiated we still need to set it up for 287 // If the class is never instantiated we still need to set it up for
276 // inheritance purposes, but we can leave its JavaScript constructor empty. 288 // inheritance purposes, but we can leave its JavaScript constructor empty.
277 if (compiler.universe.instantiatedClasses.contains(classElement)) { 289 if (compiler.universe.instantiatedClasses.contains(classElement)) {
278 generateFieldInits(classElement, buffer, bodyBuffer); 290 generateFieldInits(classElement, buffer, bodyBuffer);
279 } 291 }
280 buffer.add(') {\n'); 292 buffer.add(') {\n');
281 buffer.add(bodyBuffer); 293 buffer.add(bodyBuffer);
282 buffer.add('};\n'); 294 buffer.add('};\n');
283 if (superclass !== null) { 295
284 addInheritFunctionIfNecessary(buffer); 296 emitInherits(classElement, buffer);
285 String superName = namer.isolatePropertyAccess(superclass);
286 buffer.add('${inheritsName}($className, $superName);\n');
287 }
288 297
289 String attachTo(String name) => '$className.prototype.$name'; 298 String attachTo(String name) => '$className.prototype.$name';
290 for (Element member in classElement.members) { 299 for (Element member in classElement.members) {
291 if (member.isInstanceMember()) { 300 if (member.isInstanceMember()) {
292 addInstanceMember(member, attachTo, buffer); 301 addInstanceMember(member, attachTo, buffer);
293 } 302 }
294 } 303 }
295 for (Element member in classElement.backendMembers) { 304 for (Element member in classElement.backendMembers) {
296 if (member.isInstanceMember()) { 305 if (member.isInstanceMember()) {
297 addInstanceMember(member, attachTo, buffer); 306 addInstanceMember(member, attachTo, buffer);
298 } 307 }
299 } 308 }
300 generateTypeTests(classElement, (Element other) { 309 generateTypeTests(classElement, (Element other) {
301 buffer.add('${attachTo(namer.operatorIs(other))} = true;\n'); 310 buffer.add('${attachTo(namer.operatorIs(other))} = true;\n');
302 }); 311 });
303 312
304 if (superclass === null && compiler.enabledNoSuchMethod) { 313 if (classElement === compiler.objectClass && compiler.enabledNoSuchMethod) {
305 // Emit the noSuchMethods on the Object prototype now, so that 314 // Emit the noSuchMethods on the Object prototype now, so that
306 // the code in the dynamicMethod can find them. Note that the 315 // the code in the dynamicMethod can find them. Note that the
307 // code in dynamicMethod is invoked before analyzing the full JS 316 // code in dynamicMethod is invoked before analyzing the full JS
308 // script. 317 // script.
309 emitNoSuchMethodCalls(buffer); 318 emitNoSuchMethodCalls(buffer);
310 } 319 }
311 } 320 }
312 321
313 void generateTypeTests(ClassElement cls, 322 void generateTypeTests(ClassElement cls,
314 void generateTypeTest(ClassElement element)) { 323 void generateTypeTest(ClassElement element)) {
315 if (compiler.universe.isChecks.contains(cls)) { 324 if (compiler.universe.isChecks.contains(cls)) {
316 generateTypeTest(cls); 325 generateTypeTest(cls);
317 } 326 }
318 generateInterfacesIsTests(cls, generateTypeTest); 327 generateInterfacesIsTests(cls, generateTypeTest);
319 } 328 }
320 329
321 void generateInterfacesIsTests(ClassElement cls, 330 void generateInterfacesIsTests(ClassElement cls,
322 void generateTypeTest(ClassElement element)) { 331 void generateTypeTest(ClassElement element)) {
323 for (Type interfaceType in cls.interfaces) { 332 for (Type interfaceType in cls.interfaces) {
324 Element element = interfaceType.element; 333 Element element = interfaceType.element;
325 if (compiler.universe.isChecks.contains(element)) { 334 if (compiler.universe.isChecks.contains(element)) {
326 generateTypeTest(element); 335 generateTypeTest(element);
327 } 336 }
328 generateInterfacesIsTests(element, generateTypeTest); 337 generateInterfacesIsTests(element, generateTypeTest);
329 } 338 }
330 } 339 }
331 340
332 void emitClasses(StringBuffer buffer) { 341 void emitClasses(StringBuffer buffer) {
333 Set seenClasses = new Set<ClassElement>();
334 for (ClassElement element in compiler.universe.instantiatedClasses) { 342 for (ClassElement element in compiler.universe.instantiatedClasses) {
335 generateClass(element, buffer, seenClasses); 343 ensureGenerated(element, buffer);
336 } 344 }
337 } 345 }
338 346
339 void emitStaticFunctionsWithNamer(StringBuffer buffer, 347 void emitStaticFunctionsWithNamer(StringBuffer buffer,
340 Map<Element, String> generatedCode, 348 Map<Element, String> generatedCode,
341 String functionNamer(Element element)) { 349 String functionNamer(Element element)) {
342 generatedCode.forEach((Element element, String codeBlock) { 350 generatedCode.forEach((Element element, String codeBlock) {
343 if (!element.isInstanceMember()) { 351 if (!element.isInstanceMember()) {
344 buffer.add('${functionNamer(element)} = '); 352 buffer.add('${functionNamer(element)} = ');
345 buffer.add(codeBlock); 353 buffer.add(codeBlock);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 FunctionElement member) { 389 FunctionElement member) {
382 // For every method that has the same name as a property-get we create a 390 // For every method that has the same name as a property-get we create a
383 // getter that returns a bound closure. Say we have a class 'A' with method 391 // getter that returns a bound closure. Say we have a class 'A' with method
384 // 'foo' and somewhere in the code there is a dynamic property get of 392 // 'foo' and somewhere in the code there is a dynamic property get of
385 // 'foo'. Then we generate the following code (in pseudo Dart): 393 // 'foo'. Then we generate the following code (in pseudo Dart):
386 // 394 //
387 // class A { 395 // class A {
388 // foo(x, y, z) { ... } // Original function. 396 // foo(x, y, z) { ... } // Original function.
389 // get foo() { return new BoundClosure499(this); } 397 // get foo() { return new BoundClosure499(this); }
390 // } 398 // }
391 // class BoundClosure499 { 399 // class BoundClosure499 extends Closure {
392 // var self; 400 // var self;
393 // BoundClosure499(this.self); 401 // BoundClosure499(this.self);
394 // $call3(x, y, z) { return self.foo(x, y, z); } 402 // $call3(x, y, z) { return self.foo(x, y, z); }
395 // } 403 // }
396 404
397 // TODO(floitsch): share the closure classes with other classes 405 // TODO(floitsch): share the closure classes with other classes
398 // if they share methods with the same signature. 406 // if they share methods with the same signature.
399 407
400 // The closure class. 408 // The closure class.
401 SourceString name = const SourceString("BoundClosure"); 409 SourceString name = const SourceString("BoundClosure");
402 CompilationUnitElement compilationUnit = member.getCompilationUnit(); 410 ClassElement closureClassElement =
403 ClassElement closureClassElement = new ClassElement(name, compilationUnit); 411 new ClosureClassElement(compiler, member.getCompilationUnit());
404 String isolateAccess = namer.isolatePropertyAccess(closureClassElement); 412 String isolateAccess = namer.isolatePropertyAccess(closureClassElement);
413 ensureGenerated(closureClassElement.superclass, buffer);
405 414
406 // Define the constructor with a name so that Object.toString can 415 // Define the constructor with a name so that Object.toString can
407 // find the class name of the closure class. 416 // find the class name of the closure class.
408 buffer.add("$isolateAccess = function $name(self) "); 417 buffer.add("$isolateAccess = function $name(self) ");
409 buffer.add("{ this.self = self; };\n"); 418 buffer.add("{ this.self = self; };\n");
410 419 emitInherits(closureClassElement, buffer);
411 // Make the closure class extend Object.
412 addInheritFunctionIfNecessary(buffer);
413 ClassElement objectClass =
414 compiler.coreLibrary.find(const SourceString('Object'));
415 String superName = namer.isolatePropertyAccess(objectClass);
416 buffer.add('${inheritsName}($isolateAccess, $superName);\n');
417 420
418 String prototype = "$isolateAccess.prototype"; 421 String prototype = "$isolateAccess.prototype";
419 422
420 // Now add the methods on the closure class. The instance method does not 423 // Now add the methods on the closure class. The instance method does not
421 // have the correct name. Since [addParameterStubs] use the name to create 424 // have the correct name. Since [addParameterStubs] use the name to create
422 // its stubs we simply create a fake element with the correct name. 425 // its stubs we simply create a fake element with the correct name.
423 // Note: the callElement will not have any enclosingElement. 426 // Note: the callElement will not have any enclosingElement.
424 FunctionElement callElement = 427 FunctionElement callElement =
425 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); 428 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
426 429
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 emitStaticFinalFieldInitializations(buffer); 617 emitStaticFinalFieldInitializations(buffer);
615 nativeEmitter.emitDynamicDispatchMetadata(buffer); 618 nativeEmitter.emitDynamicDispatchMetadata(buffer);
616 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); 619 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n');
617 Element main = compiler.mainApp.find(Compiler.MAIN); 620 Element main = compiler.mainApp.find(Compiler.MAIN);
618 buffer.add('${namer.isolateAccess(main)}();\n'); 621 buffer.add('${namer.isolateAccess(main)}();\n');
619 compiler.assembledCode = buffer.toString(); 622 compiler.assembledCode = buffer.toString();
620 }); 623 });
621 return compiler.assembledCode; 624 return compiler.assembledCode;
622 } 625 }
623 } 626 }
OLDNEW
« no previous file with comments | « frog/leg/compiler.dart ('k') | frog/leg/enqueue.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698