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

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

Issue 9415005: Support implicitly bound closures (aka. tear-off closures). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 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
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 * Generates the code for all used classes in the program. Static fields (even 6 * Generates the code for all used classes in the program. Static fields (even
7 * in classes) are ignored, since they can be treated as non-class elements. 7 * in classes) are ignored, since they can be treated as non-class elements.
8 * 8 *
9 * The code for the containing (used) methods must exist in the [:universe:]. 9 * The code for the containing (used) methods must exist in the [:universe:].
10 */ 10 */
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 null); 283 null);
284 String staticName = namer.isolatePropertyAccess(element); 284 String staticName = namer.isolatePropertyAccess(element);
285 int parameterCount = element.parameterCount(compiler); 285 int parameterCount = element.parameterCount(compiler);
286 String invocationName = 286 String invocationName =
287 namer.instanceMethodName(callElement.name, parameterCount); 287 namer.instanceMethodName(callElement.name, parameterCount);
288 buffer.add("$staticName.$invocationName = $staticName;\n"); 288 buffer.add("$staticName.$invocationName = $staticName;\n");
289 addParameterStubs(callElement, staticName, buffer); 289 addParameterStubs(callElement, staticName, buffer);
290 } 290 }
291 } 291 }
292 292
293 void emitDynamicFunctionGetter(StringBuffer buffer,
294 ClassElement enclosingClass,
295 FunctionElement member) {
296 // For every method that has the same name as a property-get we create a
297 // getter that returns a bound closure. Say we have a class 'A' with method
298 // 'foo' and somewhere in the code there is a dynamic property get of
299 // 'foo'. Then we generate the following code (in pseudo Dart):
300 //
301 // class A {
302 // foo(x, y, z) { ... } // Original function.
303 // foo$get() { return new BoundClosure499(this); }
ngeoffray 2012/02/16 12:38:46 foo$get -> get foo ?
floitsch 2012/02/16 13:43:07 Done.
304 // }
305 // class BoundClosure499 {
306 // var self;
307 // BoundClosure499(this.self);
308 // $call3(x, y, z) { return self.foo(x, y, z); }
309 // }
310
311 // TODO(floitsch): share the closure classes with other classes
312 // if they share methods with the same signature.
313
314 // The closure class.
315 SourceString name = const SourceString("BoundClosure");
316 CompilationUnitElement compilationUnit = member.getCompilationUnit();
317 ClassElement closureClassElement = new ClassElement(name, compilationUnit);
318 String isolateAccess = namer.isolatePropertyAccess(closureClassElement);
319 buffer.add("$isolateAccess = function(self) { this.self = self; };\n");
320 String prototype = "$isolateAccess.prototype";
321
322 // Now add the methods on the closure class. The instance method does not
323 // have the correct name. Since [addParameterStubs] use the name to create
324 // its stubs we simply create a fake element with the correct name.
325 // Note: the callElement will not have the correct modifiers (in case
326 // of static functions) and will not have any enclosingElement.
327 FunctionElement callElement =
328 new FunctionElement.from(Namer.CLOSURE_INVOCATION_NAME, member, null);
329
330 int parameterCount = member.parameterCount(compiler);
331 String invocationName =
332 namer.instanceMethodName(callElement.name, parameterCount);
333 String targetName = namer.instanceMethodName(member.name, parameterCount);
334 List<String> arguments = new List<String>(parameterCount);
335 for (int i = 0; i < parameterCount; i++) {
336 arguments[i] = "arg$i";
337 }
338 String joinedArgs = Strings.join(arguments, ", ");
339 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n");
340 buffer.add(" return this.self.$targetName($joinedArgs);\n");
341 buffer.add("};\n");
342 addParameterStubs(callElement, prototype, buffer);
343
344 // And finally the getter.
345 String enclosingClassAccess = namer.isolatePropertyAccess(enclosingClass);
346 String enclosingClassPrototype = "$enclosingClassAccess.prototype";
347 String getterName = namer.getterName(member.name);
348 String closureClass = namer.isolateAccess(closureClassElement);
349 buffer.add("$enclosingClassPrototype.$getterName = function() {\n");
350 buffer.add(" return new $closureClass(this);\n");
351 buffer.add("};\n");
352 }
353
354 void emitDynamicFunctionGetters(StringBuffer buffer) {
355 for (ClassElement classElement in compiler.universe.instantiatedClasses) {
356 for (ClassElement currentClass = classElement;
357 currentClass !== null;
358 currentClass = currentClass.superclass) {
359 // TODO(floitsch): we don't need to deal with members that have been
360 // overwritten by subclasses.
361 for (Element member in currentClass.members) {
362 if (!member.isInstanceMember()) continue;
363 if (member.kind == ElementKind.FUNCTION) {
364 if (compiler.universe.invokedGetters.contains(member.name)) {
365 emitDynamicFunctionGetter(buffer, currentClass, member);
366 }
367 }
368 }
369 }
370 }
371 }
372
293 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) { 373 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) {
294 // Adds initializations inside the Isolate constructor. 374 // Adds initializations inside the Isolate constructor.
295 // Example: 375 // Example:
296 // function Isolate() { 376 // function Isolate() {
297 // this.staticNonFinal = Isolate.prototype.someVal; 377 // this.staticNonFinal = Isolate.prototype.someVal;
298 // ... 378 // ...
299 // } 379 // }
300 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; 380 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler;
301 List<VariableElement> staticNonFinalFields = 381 List<VariableElement> staticNonFinalFields =
302 constants.getStaticNonFinalFieldsForEmission(); 382 constants.getStaticNonFinalFieldsForEmission();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 String assembleProgram() { 455 String assembleProgram() {
376 measure(() { 456 measure(() {
377 StringBuffer buffer = new StringBuffer(); 457 StringBuffer buffer = new StringBuffer();
378 buffer.add('function ${namer.ISOLATE}() {'); 458 buffer.add('function ${namer.ISOLATE}() {');
379 emitStaticNonFinalFieldInitializations(buffer); 459 emitStaticNonFinalFieldInitializations(buffer);
380 buffer.add('}\n\n'); 460 buffer.add('}\n\n');
381 emitClasses(buffer); 461 emitClasses(buffer);
382 emitNoSuchMethodCalls(buffer); 462 emitNoSuchMethodCalls(buffer);
383 emitStaticFunctions(buffer); 463 emitStaticFunctions(buffer);
384 emitStaticFunctionGetters(buffer); 464 emitStaticFunctionGetters(buffer);
465 emitDynamicFunctionGetters(buffer);
385 emitStaticFinalFieldInitializations(buffer); 466 emitStaticFinalFieldInitializations(buffer);
386 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); 467 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n');
387 Element main = compiler.mainApp.find(Compiler.MAIN); 468 Element main = compiler.mainApp.find(Compiler.MAIN);
388 buffer.add('${namer.isolateAccess(main)}();\n'); 469 buffer.add('${namer.isolateAccess(main)}();\n');
389 compiler.assembledCode = buffer.toString(); 470 compiler.assembledCode = buffer.toString();
390 }); 471 });
391 return compiler.assembledCode; 472 return compiler.assembledCode;
392 } 473 }
393 } 474 }
OLDNEW
« no previous file with comments | « frog/leg/compiler.dart ('k') | frog/leg/namer.dart » ('j') | frog/leg/namer.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698