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

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

Issue 9689045: Library privacy. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address review comments 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
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,
11 FunctionElement other) 11 FunctionElement other)
12 : super.from(name, other, null); 12 : super.from(name, other, other.enclosingElement);
13 13
14 isInstanceMember() => true; 14 isInstanceMember() => true;
15 } 15 }
16 16
17 /** 17 /**
18 * Generates the code for all used classes in the program. Static fields (even 18 * Generates the code for all used classes in the program. Static fields (even
19 * in classes) are ignored, since they can be treated as non-class elements. 19 * in classes) are ignored, since they can be treated as non-class elements.
20 * 20 *
21 * The code for the containing (used) methods must exist in the [:universe:]. 21 * The code for the containing (used) methods must exist in the [:universe:].
22 */ 22 */
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 FunctionParameters parameters = member.computeParameters(compiler); 70 FunctionParameters parameters = member.computeParameters(compiler);
71 int positionalArgumentCount = selector.positionalArgumentCount; 71 int positionalArgumentCount = selector.positionalArgumentCount;
72 if (positionalArgumentCount == parameters.parameterCount) { 72 if (positionalArgumentCount == parameters.parameterCount) {
73 assert(selector.namedArgumentCount == 0); 73 assert(selector.namedArgumentCount == 0);
74 return; 74 return;
75 } 75 }
76 ConstantHandler handler = compiler.constantHandler; 76 ConstantHandler handler = compiler.constantHandler;
77 List<SourceString> names = selector.getOrderedNamedArguments(); 77 List<SourceString> names = selector.getOrderedNamedArguments();
78 78
79 String invocationName = 79 String invocationName =
80 namer.instanceMethodInvocationName(member.name, selector); 80 namer.instanceMethodInvocationName(member.getLibrary(), member.name,
81 selector);
81 buffer.add('${attachTo(invocationName)} = function('); 82 buffer.add('${attachTo(invocationName)} = function(');
82 83
83 // The parameters that this stub takes. 84 // The parameters that this stub takes.
84 List<String> parametersBuffer = new List<String>(selector.argumentCount); 85 List<String> parametersBuffer = new List<String>(selector.argumentCount);
85 // The arguments that will be passed to the real method. 86 // The arguments that will be passed to the real method.
86 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); 87 List<String> argumentsBuffer = new List<String>(parameters.parameterCount);
87 88
88 // We fill the lists depending on the selector. For example, 89 // We fill the lists depending on the selector. For example,
89 // take method foo: 90 // take method foo:
90 // foo(a, b, [c, d]); 91 // foo(a, b, [c, d]);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 FunctionElement function = member; 202 FunctionElement function = member;
202 FunctionParameters parameters = function.computeParameters(compiler); 203 FunctionParameters parameters = function.computeParameters(compiler);
203 if (!parameters.optionalParameters.isEmpty()) { 204 if (!parameters.optionalParameters.isEmpty()) {
204 addParameterStubs(member, attachTo, buffer, isNative: isNative); 205 addParameterStubs(member, attachTo, buffer, isNative: isNative);
205 } 206 }
206 } else if (member.kind === ElementKind.FIELD) { 207 } else if (member.kind === ElementKind.FIELD) {
207 // TODO(ngeoffray): Have another class generate the code for the 208 // TODO(ngeoffray): Have another class generate the code for the
208 // fields. 209 // fields.
209 if ((member.modifiers === null || !member.modifiers.isFinal()) && 210 if ((member.modifiers === null || !member.modifiers.isFinal()) &&
210 compiler.universe.invokedSetters.contains(member.name)) { 211 compiler.universe.invokedSetters.contains(member.name)) {
211 String setterName = namer.setterName(member.name); 212 String setterName = namer.setterName(member.getLibrary(), member.name);
212 String name = 213 String name =
213 isNative ? member.name.slowToString() : namer.getName(member); 214 isNative ? member.name.slowToString() : namer.getName(member);
214 buffer.add('${attachTo(setterName)} = function(v){\n'); 215 buffer.add('${attachTo(setterName)} = function(v){\n');
215 buffer.add(' this.$name = v;\n};\n'); 216 buffer.add(' this.$name = v;\n};\n');
216 } 217 }
217 if (compiler.universe.invokedGetters.contains(member.name)) { 218 if (compiler.universe.invokedGetters.contains(member.name)) {
218 String getterName = namer.getterName(member.name); 219 String getterName = namer.getterName(member.getLibrary(), member.name);
219 String name = 220 String name =
220 isNative ? member.name.slowToString() : namer.getName(member); 221 isNative ? member.name.slowToString() : namer.getName(member);
221 buffer.add('${attachTo(getterName)} = function(){\n'); 222 buffer.add('${attachTo(getterName)} = function(){\n');
222 buffer.add(' return this.$name;\n};\n'); 223 buffer.add(' return this.$name;\n};\n');
223 } 224 }
224 } else { 225 } else {
225 compiler.internalError('unexpected kind: "${member.kind}"', 226 compiler.internalError('unexpected kind: "${member.kind}"',
226 element: member); 227 element: member);
227 } 228 }
228 emitExtraAccessors(member, attachTo, buffer); 229 emitExtraAccessors(member, attachTo, buffer);
229 } 230 }
230 231
231 bool generateFieldInits(ClassElement classElement, 232 bool generateFieldInits(ClassElement classElement,
232 StringBuffer argumentsBuffer, 233 StringBuffer argumentsBuffer,
233 StringBuffer bodyBuffer) { 234 StringBuffer bodyBuffer) {
234 bool isFirst = true; 235 bool isFirst = true;
235 do { 236 do {
236 // TODO(floitsch): make sure there are no name clashes. 237 // TODO(floitsch): make sure there are no name clashes.
237 String className = namer.getName(classElement); 238 String className = namer.getName(classElement);
238 239
239 void generateFieldInit(Element member) { 240 void generateFieldInit(Element member) {
240 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { 241 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
241 if (!isFirst) argumentsBuffer.add(', '); 242 if (!isFirst) argumentsBuffer.add(', ');
242 isFirst = false; 243 isFirst = false;
243 String memberName = namer.instanceFieldName(member.name); 244 String memberName = namer.instanceFieldName(member.getLibrary(),
245 member.name);
244 argumentsBuffer.add('${className}_$memberName'); 246 argumentsBuffer.add('${className}_$memberName');
245 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n'); 247 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n');
246 } 248 }
247 } 249 }
248 250
249 for (Element element in classElement.members) { 251 for (Element element in classElement.members) {
250 generateFieldInit(element); 252 generateFieldInit(element);
251 } 253 }
252 for (Element element in classElement.backendMembers) { 254 for (Element element in classElement.backendMembers) {
253 generateFieldInit(element); 255 generateFieldInit(element);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 for (FunctionElement element in functionsNeedingGetter) { 374 for (FunctionElement element in functionsNeedingGetter) {
373 // The static function does not have the correct name. Since 375 // The static function does not have the correct name. Since
374 // [addParameterStubs] use the name to create its stubs we simply 376 // [addParameterStubs] use the name to create its stubs we simply
375 // create a fake element with the correct name. 377 // create a fake element with the correct name.
376 // Note: the callElement will not have any enclosingElement. 378 // Note: the callElement will not have any enclosingElement.
377 FunctionElement callElement = 379 FunctionElement callElement =
378 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); 380 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element);
379 String staticName = namer.isolatePropertyAccess(element); 381 String staticName = namer.isolatePropertyAccess(element);
380 int parameterCount = element.parameterCount(compiler); 382 int parameterCount = element.parameterCount(compiler);
381 String invocationName = 383 String invocationName =
382 namer.instanceMethodName(callElement.name, parameterCount); 384 namer.instanceMethodName(element.getLibrary(), callElement.name,
385 parameterCount);
383 buffer.add("$staticName.$invocationName = $staticName;\n"); 386 buffer.add("$staticName.$invocationName = $staticName;\n");
384 addParameterStubs(callElement, (name) => '$staticName.$name', buffer); 387 addParameterStubs(callElement, (name) => '$staticName.$name', buffer);
385 } 388 }
386 } 389 }
387 390
388 void emitDynamicFunctionGetter(StringBuffer buffer, 391 void emitDynamicFunctionGetter(StringBuffer buffer,
389 String attachTo(String invocationName), 392 String attachTo(String invocationName),
390 FunctionElement member) { 393 FunctionElement member) {
391 // For every method that has the same name as a property-get we create a 394 // For every method that has the same name as a property-get we create a
392 // getter that returns a bound closure. Say we have a class 'A' with method 395 // getter that returns a bound closure. Say we have a class 'A' with method
(...skipping 30 matching lines...) Expand all
423 426
424 // Now add the methods on the closure class. The instance method does not 427 // Now add the methods on the closure class. The instance method does not
425 // have the correct name. Since [addParameterStubs] use the name to create 428 // have the correct name. Since [addParameterStubs] use the name to create
426 // its stubs we simply create a fake element with the correct name. 429 // its stubs we simply create a fake element with the correct name.
427 // Note: the callElement will not have any enclosingElement. 430 // Note: the callElement will not have any enclosingElement.
428 FunctionElement callElement = 431 FunctionElement callElement =
429 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member); 432 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, member);
430 433
431 int parameterCount = member.parameterCount(compiler); 434 int parameterCount = member.parameterCount(compiler);
432 String invocationName = 435 String invocationName =
433 namer.instanceMethodName(callElement.name, parameterCount); 436 namer.instanceMethodName(member.getLibrary(),
434 String targetName = namer.instanceMethodName(member.name, parameterCount); 437 callElement.name, parameterCount);
438 String targetName = namer.instanceMethodName(member.getLibrary(),
439 member.name, parameterCount);
435 List<String> arguments = new List<String>(parameterCount); 440 List<String> arguments = new List<String>(parameterCount);
436 for (int i = 0; i < parameterCount; i++) { 441 for (int i = 0; i < parameterCount; i++) {
437 arguments[i] = "arg$i"; 442 arguments[i] = "arg$i";
438 } 443 }
439 String joinedArgs = Strings.join(arguments, ", "); 444 String joinedArgs = Strings.join(arguments, ", ");
440 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n"); 445 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n");
441 buffer.add(" return this.self.$targetName($joinedArgs);\n"); 446 buffer.add(" return this.self.$targetName($joinedArgs);\n");
442 buffer.add("};\n"); 447 buffer.add("};\n");
443 addParameterStubs(callElement, 448 addParameterStubs(callElement,
444 (invocationName) => '$prototype.$invocationName', 449 (invocationName) => '$prototype.$invocationName',
445 buffer); 450 buffer);
446 451
447 // And finally the getter. 452 // And finally the getter.
448 String getterName = namer.getterName(member.name); 453 String getterName = namer.getterName(member.getLibrary(), member.name);
449 String closureClass = namer.isolateAccess(closureClassElement); 454 String closureClass = namer.isolateAccess(closureClassElement);
450 buffer.add("${attachTo(getterName)} = function() {\n"); 455 buffer.add("${attachTo(getterName)} = function() {\n");
451 buffer.add(" return new $closureClass(this);\n"); 456 buffer.add(" return new $closureClass(this);\n");
452 buffer.add("};\n"); 457 buffer.add("};\n");
453 } 458 }
454 459
455 void emitCallStubForGetter(StringBuffer buffer, 460 void emitCallStubForGetter(StringBuffer buffer,
456 String attachTo(String name), 461 String attachTo(String name),
457 Element member, 462 Element member,
458 Set<Selector> selectors) { 463 Set<Selector> selectors) {
459 String getter; 464 String getter;
460 if (member.kind == ElementKind.GETTER) { 465 if (member.kind == ElementKind.GETTER) {
461 getter = "this.${namer.getterName(member.name)}()"; 466 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()";
462 } else { 467 } else {
463 getter = "this.${namer.instanceFieldName(member.name)}"; 468 getter =
469 "this.${namer.instanceFieldName(member.getLibrary(), member.name)}";
464 } 470 }
465 for (Selector selector in selectors) { 471 for (Selector selector in selectors) {
466 String invocationName = 472 String invocationName =
467 namer.instanceMethodInvocationName(member.name, selector); 473 namer.instanceMethodInvocationName(member.getLibrary(), member.name,
474 selector);
468 SourceString callName = Namer.CLOSURE_INVOCATION_NAME; 475 SourceString callName = Namer.CLOSURE_INVOCATION_NAME;
469 String closureCallName = 476 String closureCallName =
470 namer.instanceMethodInvocationName(callName, selector); 477 namer.instanceMethodInvocationName(member.getLibrary(), callName,
478 selector);
471 List<String> arguments = <String>[]; 479 List<String> arguments = <String>[];
472 for (int i = 0; i < selector.argumentCount; i++) { 480 for (int i = 0; i < selector.argumentCount; i++) {
473 arguments.add("arg$i"); 481 arguments.add("arg$i");
474 } 482 }
475 String joined = Strings.join(arguments, ", "); 483 String joined = Strings.join(arguments, ", ");
476 buffer.add("${attachTo(invocationName)} = function($joined) {\n"); 484 buffer.add("${attachTo(invocationName)} = function($joined) {\n");
477 buffer.add(" return $getter.$closureCallName($joined);\n"); 485 buffer.add(" return $getter.$closureCallName($joined);\n");
478 buffer.add("};\n"); 486 buffer.add("};\n");
479 } 487 }
480 } 488 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 562
555 void emitNoSuchMethodCalls(StringBuffer buffer) { 563 void emitNoSuchMethodCalls(StringBuffer buffer) {
556 // Do not generate no such method calls if there is no class. 564 // Do not generate no such method calls if there is no class.
557 if (compiler.universe.instantiatedClasses.isEmpty()) return; 565 if (compiler.universe.instantiatedClasses.isEmpty()) return;
558 566
559 ClassElement objectClass = 567 ClassElement objectClass =
560 compiler.coreLibrary.find(const SourceString('Object')); 568 compiler.coreLibrary.find(const SourceString('Object'));
561 String className = namer.isolatePropertyAccess(objectClass); 569 String className = namer.isolatePropertyAccess(objectClass);
562 String prototype = '$className.prototype'; 570 String prototype = '$className.prototype';
563 String noSuchMethodName = 571 String noSuchMethodName =
564 namer.instanceMethodName(Compiler.NO_SUCH_METHOD, 2); 572 namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2);
573 Collection<LibraryElement> libraries =
574 compiler.universe.libraries.getValues();
ngeoffray 2012/03/18 11:49:59 missing 2 spaces.
ahe 2012/03/18 21:15:55 Done.
565 575
566 void generateMethod(String methodName, String jsName, Selector selector) { 576 void generateMethod(String methodName, String jsName, Selector selector) {
567 buffer.add('$prototype.$jsName = function'); 577 buffer.add('$prototype.$jsName = function');
568 StringBuffer args = new StringBuffer(); 578 StringBuffer args = new StringBuffer();
569 for (int i = 0; i < selector.argumentCount; i++) { 579 for (int i = 0; i < selector.argumentCount; i++) {
570 if (i != 0) args.add(', '); 580 if (i != 0) args.add(', ');
571 args.add('arg$i'); 581 args.add('arg$i');
572 } 582 }
573 // We need to check if the object has a noSuchMethod. If not, it 583 // We need to check if the object has a noSuchMethod. If not, it
574 // means the object is a native object, and we can just call our 584 // means the object is a native object, and we can just call our
575 // generic noSuchMethod. Note that when calling this method, the 585 // generic noSuchMethod. Note that when calling this method, the
576 // 'this' object is not a Dart object. 586 // 'this' object is not a Dart object.
577 buffer.add(' ($args) {\n'); 587 buffer.add(' ($args) {\n');
578 buffer.add(' return this.$noSuchMethodName\n'); 588 buffer.add(' return this.$noSuchMethodName\n');
579 buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n"); 589 buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n");
580 buffer.add(" : $objectClassName.prototype.$noSuchMethodName.call("); 590 buffer.add(" : $objectClassName.prototype.$noSuchMethodName.call(");
581 buffer.add("this, '$methodName', [$args])\n"); 591 buffer.add("this, '$methodName', [$args])\n");
582 buffer.add('}\n'); 592 buffer.add('}\n');
583 } 593 }
584 594
585 compiler.universe.invokedNames.forEach((SourceString methodName, 595 compiler.universe.invokedNames.forEach((SourceString methodName,
586 Set<Selector> selectors) { 596 Set<Selector> selectors) {
587 if (objectClass.lookupLocalMember(methodName) === null 597 if (objectClass.lookupLocalMember(methodName) === null
588 && methodName != Namer.OPERATOR_EQUALS) { 598 && methodName != Namer.OPERATOR_EQUALS) {
589 for (Selector selector in selectors) { 599 for (Selector selector in selectors) {
590 String jsName = 600 if (methodName.isPrivate()) {
591 namer.instanceMethodInvocationName(methodName, selector); 601 for (LibraryElement lib in libraries) {
592 generateMethod(methodName.slowToString(), jsName, selector); 602 String jsName =
603 namer.instanceMethodInvocationName(lib, methodName, selector);
604 generateMethod(methodName.slowToString(), jsName, selector);
605 }
606 } else {
607 String jsName =
608 namer.instanceMethodInvocationName(null, methodName, selector);
609 generateMethod(methodName.slowToString(), jsName, selector);
610 }
593 } 611 }
594 } 612 }
595 }); 613 });
596 614
597 compiler.universe.invokedGetters.forEach((SourceString getterName) { 615 compiler.universe.invokedGetters.forEach((SourceString getterName) {
598 String jsName = namer.getterName(getterName); 616 if (getterName.isPrivate()) {
599 generateMethod('get ${getterName.slowToString()}', jsName, 617 for (LibraryElement lib in libraries) {
600 Selector.GETTER); 618 String jsName = namer.getterName(lib, getterName);
619 generateMethod('get ${getterName.slowToString()}', jsName,
620 Selector.GETTER);
621 }
622 } else {
623 String jsName = namer.getterName(null, getterName);
624 generateMethod('get ${getterName.slowToString()}', jsName,
625 Selector.GETTER);
626 }
601 }); 627 });
602 628
603 compiler.universe.invokedSetters.forEach((SourceString setterName) { 629 compiler.universe.invokedSetters.forEach((SourceString setterName) {
604 String jsName = namer.setterName(setterName); 630 if (setterName.isPrivate()) {
605 generateMethod('set ${setterName.slowToString()}', jsName, 631 for (LibraryElement lib in libraries) {
606 Selector.SETTER); 632 String jsName = namer.setterName(lib, setterName);
633 generateMethod('set ${setterName.slowToString()}', jsName,
634 Selector.SETTER);
635 }
636 } else {
637 String jsName = namer.setterName(null, setterName);
638 generateMethod('set ${setterName.slowToString()}', jsName,
639 Selector.SETTER);
640 }
607 }); 641 });
608 } 642 }
609 643
610 String buildIsolateSetup(Element appMain, Element isolateMain) { 644 String buildIsolateSetup(Element appMain, Element isolateMain) {
611 String mainAccess = "${namer.isolateAccess(appMain)}"; 645 String mainAccess = "${namer.isolateAccess(appMain)}";
612 String currentIsolate = "${namer.CURRENT_ISOLATE}"; 646 String currentIsolate = "${namer.CURRENT_ISOLATE}";
613 String mainEnsureGetter = ''; 647 String mainEnsureGetter = '';
614 // Since we pass the closurized version of the main method to 648 // Since we pass the closurized version of the main method to
615 // the isolate method, we must make sure that it exists. 649 // the isolate method, we must make sure that it exists.
616 if (!compiler.universe.staticFunctionsNeedingGetter.contains(appMain)) { 650 if (!compiler.universe.staticFunctionsNeedingGetter.contains(appMain)) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE); 692 compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE);
659 buffer.add(buildIsolateSetup(main, isolateMain)); 693 buffer.add(buildIsolateSetup(main, isolateMain));
660 } else { 694 } else {
661 buffer.add('${namer.isolateAccess(main)}();\n'); 695 buffer.add('${namer.isolateAccess(main)}();\n');
662 } 696 }
663 compiler.assembledCode = buffer.toString(); 697 compiler.assembledCode = buffer.toString();
664 }); 698 });
665 return compiler.assembledCode; 699 return compiler.assembledCode;
666 } 700 }
667 } 701 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698