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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 11411215: Generate parameter stubs using ASTs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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) 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 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 } 82 }
83 83
84 js.Expression constantReference(Constant value) { 84 js.Expression constantReference(Constant value) {
85 return constantEmitter.reference(value); 85 return constantEmitter.reference(value);
86 } 86 }
87 87
88 js.Expression constantInitializerExpression(Constant value) { 88 js.Expression constantInitializerExpression(Constant value) {
89 return constantEmitter.initializationExpression(value); 89 return constantEmitter.initializationExpression(value);
90 } 90 }
91 91
92 // Deprecated. Remove after last use is converted to JS ASTs.
93 void writeConstantToBuffer(Constant value, CodeBuffer buffer) {
94 buffer.add(js.prettyPrint(constantReference(value), compiler));
95 }
96
97 String get name => 'CodeEmitter'; 92 String get name => 'CodeEmitter';
98 93
99 String get defineClassName 94 String get defineClassName
100 => '${namer.ISOLATE}.\$defineClass'; 95 => '${namer.ISOLATE}.\$defineClass';
101 String get finishClassesName 96 String get finishClassesName
102 => '${namer.ISOLATE}.\$finishClasses'; 97 => '${namer.ISOLATE}.\$finishClasses';
103 String get finishIsolateConstructorName 98 String get finishIsolateConstructorName
104 => '${namer.ISOLATE}.\$finishIsolateConstructor'; 99 => '${namer.ISOLATE}.\$finishIsolateConstructor';
105 String get pendingClassesName 100 String get pendingClassesName
106 => '${namer.ISOLATE}.\$pendingClasses'; 101 => '${namer.ISOLATE}.\$pendingClasses';
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 return; 414 return;
420 } 415 }
421 ConstantHandler handler = compiler.constantHandler; 416 ConstantHandler handler = compiler.constantHandler;
422 List<SourceString> names = selector.getOrderedNamedArguments(); 417 List<SourceString> names = selector.getOrderedNamedArguments();
423 418
424 String invocationName = 419 String invocationName =
425 namer.instanceMethodInvocationName(member.getLibrary(), member.name, 420 namer.instanceMethodInvocationName(member.getLibrary(), member.name,
426 selector); 421 selector);
427 if (alreadyGenerated.contains(invocationName)) return; 422 if (alreadyGenerated.contains(invocationName)) return;
428 alreadyGenerated.add(invocationName); 423 alreadyGenerated.add(invocationName);
429 CodeBuffer buffer = new CodeBuffer();
430 buffer.add('function(');
431 424
432 JavaScriptBackend backend = compiler.backend; 425 JavaScriptBackend backend = compiler.backend;
433 bool isInterceptorClass = 426 bool isInterceptorClass =
434 backend.isInterceptorClass(member.getEnclosingClass()); 427 backend.isInterceptorClass(member.getEnclosingClass());
435 428
436 // If the method is in an interceptor class, we need to also pass 429 // If the method is in an interceptor class, we need to also pass
437 // the actual receiver. 430 // the actual receiver.
438 int extraArgumentCount = isInterceptorClass ? 1 : 0; 431 int extraArgumentCount = isInterceptorClass ? 1 : 0;
439 // Use '$receiver' to avoid clashes with other parameter names. Using 432 // Use '$receiver' to avoid clashes with other parameter names. Using
440 // '$receiver' works because [JsNames.getValid] used for getting parameter 433 // '$receiver' works because [JsNames.getValid] used for getting parameter
441 // names never returns a name beginning with a single '$'. 434 // names never returns a name beginning with a single '$'.
442 String receiverArgumentName = r'$receiver'; 435 String receiverArgumentName = r'$receiver';
443 436
444 // The parameters that this stub takes. 437 // The parameters that this stub takes.
445 List<String> parametersBuffer = 438 List<js.Parameter> parametersBuffer =
446 new List<String>(selector.argumentCount + extraArgumentCount); 439 new List<js.Parameter>(selector.argumentCount + extraArgumentCount);
447 // The arguments that will be passed to the real method. 440 // The arguments that will be passed to the real method.
448 List<String> argumentsBuffer = 441 List<js.Expression> argumentsBuffer =
449 new List<String>(parameters.parameterCount + extraArgumentCount); 442 new List<js.Expression>(parameters.parameterCount + extraArgumentCount);
450 443
451 int count = 0; 444 int count = 0;
452 if (isInterceptorClass) { 445 if (isInterceptorClass) {
453 count++; 446 count++;
454 parametersBuffer[0] = receiverArgumentName; 447 parametersBuffer[0] = new js.Parameter(receiverArgumentName);
455 argumentsBuffer[0] = receiverArgumentName; 448 argumentsBuffer[0] = new js.VariableUse(receiverArgumentName);
456 } 449 }
457 450
458 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; 451 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1;
459 TreeElements elements = 452 TreeElements elements =
460 compiler.enqueuer.resolution.getCachedElements(member); 453 compiler.enqueuer.resolution.getCachedElements(member);
461 454
462 parameters.orderedForEachParameter((Element element) { 455 parameters.orderedForEachParameter((Element element) {
463 String jsName = JsNames.getValid(element.name.slowToString()); 456 String jsName = JsNames.getValid(element.name.slowToString());
464 assert(jsName != receiverArgumentName); 457 assert(jsName != receiverArgumentName);
465 if (count < positionalArgumentCount + extraArgumentCount) { 458 if (count < positionalArgumentCount + extraArgumentCount) {
466 parametersBuffer[count] = jsName; 459 parametersBuffer[count] = new js.Parameter(jsName);
467 argumentsBuffer[count] = jsName; 460 argumentsBuffer[count] = new js.VariableUse(jsName);
468 } else { 461 } else {
469 int index = names.indexOf(element.name); 462 int index = names.indexOf(element.name);
470 if (index != -1) { 463 if (index != -1) {
471 indexOfLastOptionalArgumentInParameters = count; 464 indexOfLastOptionalArgumentInParameters = count;
472 // The order of the named arguments is not the same as the 465 // The order of the named arguments is not the same as the
473 // one in the real method (which is in Dart source order). 466 // one in the real method (which is in Dart source order).
474 argumentsBuffer[count] = jsName; 467 argumentsBuffer[count] = new js.VariableUse(jsName);
475 parametersBuffer[selector.positionalArgumentCount + index] = jsName; 468 parametersBuffer[selector.positionalArgumentCount + index] =
469 new js.Parameter(jsName);
476 // Note that [elements] may be null for a synthetized [member]. 470 // Note that [elements] may be null for a synthetized [member].
floitsch 2012/11/29 16:49:05 synthesized
sra1 2012/11/29 20:39:10 Done.
477 } else if (elements != null && elements.isParameterChecked(element)) { 471 } else if (elements != null && elements.isParameterChecked(element)) {
478 CodeBuffer argumentBuffer = new CodeBuffer(); 472 argumentsBuffer[count] = constantReference(SentinelConstant.SENTINEL);
479 writeConstantToBuffer(SentinelConstant.SENTINEL, argumentBuffer);
480 argumentsBuffer[count] = argumentBuffer.toString();
481 } else { 473 } else {
482 Constant value = handler.initialVariableValues[element]; 474 Constant value = handler.initialVariableValues[element];
483 if (value == null) { 475 if (value == null) {
484 argumentsBuffer[count] = NullConstant.JsNull; 476 argumentsBuffer[count] = constantReference(new NullConstant());
485 } else { 477 } else {
486 if (!value.isNull()) { 478 if (!value.isNull()) {
487 // If the value is the null constant, we should not pass it 479 // If the value is the null constant, we should not pass it
488 // down to the native method. 480 // down to the native method.
489 indexOfLastOptionalArgumentInParameters = count; 481 indexOfLastOptionalArgumentInParameters = count;
490 } 482 }
491 CodeBuffer argumentBuffer = new CodeBuffer(); 483 argumentsBuffer[count] = constantReference(value);
492 writeConstantToBuffer(value, argumentBuffer);
493 argumentsBuffer[count] = argumentBuffer.toString();
494 } 484 }
495 } 485 }
496 } 486 }
497 count++; 487 count++;
498 }); 488 });
499 String parametersString = Strings.join(parametersBuffer, ",");
500 buffer.add('$parametersString) {\n');
501 489
490 List<js.Statement> body;
502 if (member.isNative()) { 491 if (member.isNative()) {
503 nativeEmitter.generateParameterStub( 492 body = nativeEmitter.generateParameterStub(
504 member, invocationName, parametersString, argumentsBuffer, 493 member, invocationName, parametersBuffer, argumentsBuffer,
505 indexOfLastOptionalArgumentInParameters, buffer); 494 indexOfLastOptionalArgumentInParameters);
506 } else { 495 } else {
507 String arguments = Strings.join(argumentsBuffer, ","); 496 body = <js.Statement>[
508 buffer.add(' return this.${namer.getName(member)}($arguments)'); 497 new js.Return(
498 new js.VariableUse('this')
499 .dot(namer.getName(member))
500 .callOn(argumentsBuffer))];
509 } 501 }
510 buffer.add('\n}'); 502
503 js.Fun function = new js.Fun(parametersBuffer, new js.Block(body));
504
505 CodeBuffer buffer = new CodeBuffer();
506 buffer.add(js.prettyPrint(function, compiler));
511 defineInstanceMember(invocationName, buffer); 507 defineInstanceMember(invocationName, buffer);
512 } 508 }
513 509
514 void addParameterStubs(FunctionElement member, 510 void addParameterStubs(FunctionElement member,
515 DefineMemberFunction defineInstanceMember) { 511 DefineMemberFunction defineInstanceMember) {
516 // We fill the lists depending on the selector. For example, 512 // We fill the lists depending on the selector. For example,
517 // take method foo: 513 // take method foo:
518 // foo(a, b, {c, d}); 514 // foo(a, b, {c, d});
519 // 515 //
520 // We may have multiple ways of calling foo: 516 // We may have multiple ways of calling foo:
(...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after
1818 const String HOOKS_API_USAGE = """ 1814 const String HOOKS_API_USAGE = """
1819 // Generated by dart2js, the Dart to JavaScript compiler. 1815 // Generated by dart2js, the Dart to JavaScript compiler.
1820 // The code supports the following hooks: 1816 // The code supports the following hooks:
1821 // dartPrint(message) - if this function is defined it is called 1817 // dartPrint(message) - if this function is defined it is called
1822 // instead of the Dart [print] method. 1818 // instead of the Dart [print] method.
1823 // dartMainRunner(main) - if this function is defined, the Dart [main] 1819 // dartMainRunner(main) - if this function is defined, the Dart [main]
1824 // method will not be invoked directly. 1820 // method will not be invoked directly.
1825 // Instead, a closure that will invoke [main] is 1821 // Instead, a closure that will invoke [main] is
1826 // passed to [dartMainRunner]. 1822 // passed to [dartMainRunner].
1827 """; 1823 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698