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

Side by Side Diff: lib/compiler/implementation/compiler.dart

Issue 10696147: Patch methods in classes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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 | « corelib/unified/math/random.dart ('k') | lib/compiler/implementation/lib/math.dartp » ('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 /** 6 /**
7 * If true, print a warning for each method that was resolved, but not 7 * If true, print a warning for each method that was resolved, but not
8 * compiled. 8 * compiled.
9 */ 9 */
10 final bool REPORT_EXCESS_RESOLUTION = false; 10 final bool REPORT_EXCESS_RESOLUTION = false;
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 LibraryElement patchLibrary = 514 LibraryElement patchLibrary =
515 patchParser.loadPatchLibrary(patchUri); 515 patchParser.loadPatchLibrary(patchUri);
516 // We allow foreign functions in patched libraries. 516 // We allow foreign functions in patched libraries.
517 addForeignFunctions(library); // Is safe even if already added. 517 addForeignFunctions(library); // Is safe even if already added.
518 applyLibraryPatch(library, patchLibrary); 518 applyLibraryPatch(library, patchLibrary);
519 } 519 }
520 } 520 }
521 521
522 void applyLibraryPatch(LibraryElement original, LibraryElement patch) { 522 void applyLibraryPatch(LibraryElement original, LibraryElement patch) {
523 Link<Element> patches = patch.topLevelElements; 523 Link<Element> patches = patch.topLevelElements;
524 applyContainerPatch(original, patches, original.findLocal);
524 525
525 // Copy/patch top-level elements. 526 // Copy imports from patch to original library.
527 Map<String, LibraryElement> delayedPatches = <LibraryElement>{};
528 Uri patchBase = patch.script.uri;
529 for (ScriptTag tag in patch.tags.reverse()) {
530 if (tag.isImport()) {
531 StringNode argument = tag.argument;
532 Uri resolved = patchBase.resolve(argument.dartString.slowToString());
533 LibraryElement importedLibrary =
534 scanner.loadLibrary(resolved, argument);
535 scanner.importLibrary(original, importedLibrary, tag, patch);
536 if (resolved.scheme == "dart") {
537 delayedPatches[resolved.path] = importedLibrary;
538 }
539 }
540 }
541
542 // Mark library as already patched.
543 original.patch = patch;
544
545 // We patch imported libraries after marking the current library as
546 // patched, to avoid problems with cyclic dependencies.
547 delayedPatches.forEach((String path, LibraryElement importedLibrary) {
548 patchDartLibrary(importedLibrary, path);
549 });
550 }
551
552 void applyContainerPatch(ContainerElement original, Link<Element> patches,
553 Element lookup(SourceString name)) {
526 while (!patches.isEmpty()) { 554 while (!patches.isEmpty()) {
527 Element patchElement = patches.head; 555 Element patchElement = patches.head;
528 Element originalElement = original.elements[patchElement.name]; 556 Element originalElement = lookup(patchElement.name);
529 // Getters and setters are kept inside a synthetic field. 557 // Getters and setters are kept inside a synthetic field.
530 if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { 558 if (patchElement.kind === ElementKind.ABSTRACT_FIELD) {
531 if (originalElement !== null && 559 if (originalElement !== null &&
532 originalElement.kind !== ElementKind.ABSTRACT_FIELD) { 560 originalElement.kind !== ElementKind.ABSTRACT_FIELD) {
533 internalError("Cannot patch non-getter/setter with getter/setter", 561 internalError("Cannot patch non-getter/setter with getter/setter",
534 element: originalElement); 562 element: originalElement);
535 } 563 }
536 AbstractFieldElement patchField = patchElement; 564 AbstractFieldElement patchField = patchElement;
537 AbstractFieldElement originalField = originalElement; 565 AbstractFieldElement originalField = originalElement;
538 if (patchField.getter !== null) { 566 if (patchField.getter !== null) {
539 if (originalField === null || originalField.getter === null) { 567 if (originalField === null || originalField.getter === null) {
540 original.addGetterOrSetter(clonePatch(patchField.getter)); 568 original.addGetterOrSetter(clonePatch(patchField.getter));
541 } else { 569 } else {
542 patchMember(originalField.getter, patchField.getter); 570 patchMember(originalField.getter, patchField.getter);
543 } 571 }
544 } 572 }
545 if (patchField.setter !== null) { 573 if (patchField.setter !== null) {
546 if (originalField === null || originalField.setter === null) { 574 if (originalField === null || originalField.setter === null) {
547 original.addGetterOrSetter(clonePatch(patchField.setter)); 575 original.addGetterOrSetter(clonePatch(patchField.setter));
548 } else { 576 } else {
549 patchMember(originalField.setter, patchField.setter); 577 patchMember(originalField.setter, patchField.setter);
550 } 578 }
551 } 579 }
552 } else if (originalElement === null) { 580 } else if (originalElement === null) {
581 if (isPatchElement(patchElement)) {
582 /// WHAT IS WRONG HERE? Why isn't _RANDOM in the library?
floitsch 2012/07/10 17:53:45 remove?
Lasse Reichstein Nielsen 2012/07/11 07:45:22 Absolutely. Just a comment to myself, so I could r
583 internalError("Cannot patch non-existing member '"
584 "${patchElement.name.slowToString()}'.");
585 }
553 original.addMember(clonePatch(patchElement)); 586 original.addMember(clonePatch(patchElement));
554 } else { 587 } else {
555 patchMember(originalElement, patchElement); 588 patchMember(originalElement, patchElement);
556 } 589 }
557 patches = patches.tail; 590 patches = patches.tail;
558 } 591 }
559
560 // Copy imports.
561 Map<String, LibraryElement> delayedPatches = <LibraryElement>{};
562 Uri patchBase = patch.script.uri;
563 for (ScriptTag tag in patch.tags.reverse()) {
564 if (tag.isImport()) {
565 StringNode argument = tag.argument;
566 Uri resolved = patchBase.resolve(argument.dartString.slowToString());
567 LibraryElement importedLibrary =
568 scanner.loadLibrary(resolved, argument);
569 scanner.importLibrary(original, importedLibrary, tag, patch);
570 if (resolved.scheme == "dart") {
571 delayedPatches[resolved.path] = importedLibrary;
572 }
573 }
574 }
575
576 // Mark library as already patched.
577 original.patch = patch;
578
579 // We patch imported libraries after marking the current library as
580 // patched, to avoid problems with cyclic dependencies.
581 delayedPatches.forEach((String path, LibraryElement importedLibrary) {
582 patchDartLibrary(importedLibrary, path);
583 });
584 } 592 }
585 593
586 bool isPatchElement(Element element) { 594 bool isPatchElement(Element element) {
587 // TODO(lrn): More checks needed if we introduce metadata for real. 595 // TODO(lrn): More checks needed if we introduce metadata for real.
588 // In that case, it must have the identifier "native" as metadata. 596 // In that case, it must have the identifier "native" as metadata.
589 return !element.metadata.isEmpty(); 597 return !element.metadata.isEmpty();
590 } 598 }
591 599
592 Element clonePatch(Element patchElement) { 600 Element clonePatch(Element patchElement) {
593 // The original library does not have an element with the same name 601 // The original library does not have an element with the same name
594 // as the patch library element. 602 // as the patch library element.
595 // In this case, the patch library element must not be marked as "patch", 603 // In this case, the patch library element must not be marked as "patch",
596 // and its name must make it private. 604 // and its name must make it private.
597 if (isPatchElement(patchElement)) {
598 internalError("Cannot patch non-existing member '"
599 "${patchElement.name.slowToString()}'.");
600
601 }
602 if (!patchElement.name.isPrivate()) { 605 if (!patchElement.name.isPrivate()) {
603 internalError("Cannot add non-private member '" 606 internalError("Cannot add non-private member '"
604 "${patchElement.name.slowToString()}' from patch."); 607 "${patchElement.name.slowToString()}' from patch.");
605 } 608 }
606 // TODO(lrn): Create a copy of patchElement that isn't added to anything, 609 // TODO(lrn): Create a copy of patchElement that isn't added to any
607 // but which takes its source from patchElement. 610 // object/library yet, but which takes its source from patchElement.
608 throw "Adding members from patch is unsupported"; 611 throw "Adding members from patch is unsupported";
609 } 612 }
610 613
611 void patchMember(Element originalElement, 614 void patchMember(Element originalElement, Element patchElement) {
612 Element patchElement) {
613 // The original library has an element with the same name as the patch 615 // The original library has an element with the same name as the patch
614 // library element. 616 // library element.
615 // In this case, the patch library element must be a function marked as 617 // In this case, the patch library element must be a function marked as
616 // "patch" and it must have the same signature as the function it patches. 618 // "patch" and it must have the same signature as the function it patches.
617 if (!isPatchElement(patchElement)) { 619 if (!isPatchElement(patchElement)) {
618 internalError("Cannot overwrite existing '" 620 internalError("Cannot overwrite existing '"
619 "${originalElement.name.slowToString()}' with non-patch."); 621 "${originalElement.name.slowToString()}' with non-patch.");
620 } 622 }
623 if (originalElement is PartialClassElement) {
624 // Only happens when patching a library. Dart does not, yet, have nested
625 // classes.
626 if (patchElement is! PartialClassElement) {
627 internalError("Trying to patch class with non-class",
628 element:originalElement);
629 }
630 applyClassPatch(originalElement, patchElement);
631 return;
632 }
621 if (originalElement is! FunctionElement) { 633 if (originalElement is! FunctionElement) {
622 // TODO(lrn): Handle class declarations too. 634 // TODO(lrn): Handle class declarations too.
623 internalError("Can only patch functions", element: originalElement); 635 internalError("Can only patch functions", element: originalElement);
624 } 636 }
625 // TODO(lrn): Abort if the original isn't marked external, when 637 FunctionElement original = originalElement;
626 // that is added to the language. 638 if (!original.modifiers.isExternal()) {
639 internalError("Can only patch external functions.", element: original);
640 }
627 if (patchElement is! FunctionElement || 641 if (patchElement is! FunctionElement ||
628 !patchSignatureMatches(originalElement, patchElement)) { 642 !patchSignatureMatches(original, patchElement)) {
629 internalError("Can only patch functions with matching signatures", 643 internalError("Can only patch functions with matching signatures",
630 element: originalElement); 644 element: original);
631 } 645 }
632 applyFunctionPatch(originalElement, patchElement); 646 applyFunctionPatch(original, patchElement);
633 } 647 }
634 648
635 bool patchSignatureMatches(FunctionElement original, FunctionElement patch) { 649 bool patchSignatureMatches(FunctionElement original, FunctionElement patch) {
636 // TODO(lrn): Check that patches actually match the signature of 650 // TODO(lrn): Check that patches actually match the signature of
637 // the function it's patching. 651 // the function it's patching.
638 return true; 652 return true;
639 } 653 }
640 654
641 void applyFunctionPatch(FunctionElement element, 655 void applyFunctionPatch(FunctionElement element,
642 FunctionElement patchElement) { 656 FunctionElement patchElement) {
643 // Don't just assign the patch field. This also updates the cachedNode.
644 if (element.isPatched) { 657 if (element.isPatched) {
645 internalError("Trying to patch a function more than once.", 658 internalError("Trying to patch a function more than once.",
646 element: element); 659 element: element);
647 } 660 }
648 if (element.cachedNode !== null) { 661 if (element.cachedNode !== null) {
649 internalError("Trying to patch an already compiled function.", 662 internalError("Trying to patch an already compiled function.",
650 element: element); 663 element: element);
651 } 664 }
665 // Don't just assign the patch field. This also updates the cachedNode.
652 element.setPatch(patchElement); 666 element.setPatch(patchElement);
653 } 667 }
654 668
669 void applyClassPatch(PartialClassElement original,
670 PartialClassElement patch) {
671 // Eagerly parse the class so we can patch it.
672 // TODO(lrn): Perhaps find a way to delay parsing until the class is needed,
673 // i.e., until [parseNode] is called on [original].
floitsch 2012/07/10 17:53:45 Does parsing a class go into the methods? If not,
Lasse Reichstein Nielsen 2012/07/11 07:45:22 It doesn't. We first diet-parse the structure of
674 ClassNode node = original.parseNode(this);
675 // Parse patch class with "patch" parser.
676 ClassNode patchNode = patchParser.parsePatchClassNode(patch);
677 Link<Element> patches = patch.members;
678 Element lookupMemberOrConstructor(SourceString name) {
679 Element result = original.lookupLocalMember(name);
680 if (result !== null) return result;
681 return original.lookupConstructor(name);
682 }
683 applyContainerPatch(original, patches, lookupMemberOrConstructor);
684 }
685
655 /** 686 /**
656 * Get an [Uri] pointing to a patch for the dart: library with 687 * Get an [Uri] pointing to a patch for the dart: library with
657 * the given path. Returns null if there is no patch. 688 * the given path. Returns null if there is no patch.
658 */ 689 */
659 abstract Uri resolvePatchUri(String dartLibraryPath); 690 abstract Uri resolvePatchUri(String dartLibraryPath);
660 691
661 /** Define the JS helper functions in the given library. */ 692 /** Define the JS helper functions in the given library. */
662 void addForeignFunctions(LibraryElement library) { 693 void addForeignFunctions(LibraryElement library) {
663 library.define(new ForeignElement( 694 library.define(new ForeignElement(
664 const SourceString('JS'), library), this); 695 const SourceString('JS'), library), this);
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 f(int beginOffset, int endOffset)) { 1074 f(int beginOffset, int endOffset)) {
1044 final beginOffset = begin.charOffset; 1075 final beginOffset = begin.charOffset;
1045 final endOffset = end.charOffset + end.slowCharCount; 1076 final endOffset = end.charOffset + end.slowCharCount;
1046 1077
1047 // [begin] and [end] might be the same for the same empty token. This 1078 // [begin] and [end] might be the same for the same empty token. This
1048 // happens for instance when scanning '$$'. 1079 // happens for instance when scanning '$$'.
1049 assert(endOffset >= beginOffset); 1080 assert(endOffset >= beginOffset);
1050 return f(beginOffset, endOffset); 1081 return f(beginOffset, endOffset);
1051 } 1082 }
1052 } 1083 }
OLDNEW
« no previous file with comments | « corelib/unified/math/random.dart ('k') | lib/compiler/implementation/lib/math.dartp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698