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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « corelib/unified/math/random.dart ('k') | lib/compiler/implementation/lib/math.dartp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/compiler.dart
diff --git a/lib/compiler/implementation/compiler.dart b/lib/compiler/implementation/compiler.dart
index 4c078eb2884bb28109d19d276b27e8ea7ca8d82b..94560faea0d8c1a89e862e53551b4225fad0b5dd 100644
--- a/lib/compiler/implementation/compiler.dart
+++ b/lib/compiler/implementation/compiler.dart
@@ -521,11 +521,39 @@ class Compiler implements DiagnosticListener {
void applyLibraryPatch(LibraryElement original, LibraryElement patch) {
Link<Element> patches = patch.topLevelElements;
+ applyContainerPatch(original, patches, original.findLocal);
- // Copy/patch top-level elements.
+ // Copy imports from patch to original library.
+ Map<String, LibraryElement> delayedPatches = <LibraryElement>{};
+ Uri patchBase = patch.script.uri;
+ for (ScriptTag tag in patch.tags.reverse()) {
+ if (tag.isImport()) {
+ StringNode argument = tag.argument;
+ Uri resolved = patchBase.resolve(argument.dartString.slowToString());
+ LibraryElement importedLibrary =
+ scanner.loadLibrary(resolved, argument);
+ scanner.importLibrary(original, importedLibrary, tag, patch);
+ if (resolved.scheme == "dart") {
+ delayedPatches[resolved.path] = importedLibrary;
+ }
+ }
+ }
+
+ // Mark library as already patched.
+ original.patch = patch;
+
+ // We patch imported libraries after marking the current library as
+ // patched, to avoid problems with cyclic dependencies.
+ delayedPatches.forEach((String path, LibraryElement importedLibrary) {
+ patchDartLibrary(importedLibrary, path);
+ });
+ }
+
+ void applyContainerPatch(ContainerElement original, Link<Element> patches,
+ Element lookup(SourceString name)) {
while (!patches.isEmpty()) {
Element patchElement = patches.head;
- Element originalElement = original.elements[patchElement.name];
+ Element originalElement = lookup(patchElement.name);
// Getters and setters are kept inside a synthetic field.
if (patchElement.kind === ElementKind.ABSTRACT_FIELD) {
if (originalElement !== null &&
@@ -550,37 +578,17 @@ class Compiler implements DiagnosticListener {
}
}
} else if (originalElement === null) {
+ if (isPatchElement(patchElement)) {
+ /// 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
+ internalError("Cannot patch non-existing member '"
+ "${patchElement.name.slowToString()}'.");
+ }
original.addMember(clonePatch(patchElement));
} else {
patchMember(originalElement, patchElement);
}
patches = patches.tail;
}
-
- // Copy imports.
- Map<String, LibraryElement> delayedPatches = <LibraryElement>{};
- Uri patchBase = patch.script.uri;
- for (ScriptTag tag in patch.tags.reverse()) {
- if (tag.isImport()) {
- StringNode argument = tag.argument;
- Uri resolved = patchBase.resolve(argument.dartString.slowToString());
- LibraryElement importedLibrary =
- scanner.loadLibrary(resolved, argument);
- scanner.importLibrary(original, importedLibrary, tag, patch);
- if (resolved.scheme == "dart") {
- delayedPatches[resolved.path] = importedLibrary;
- }
- }
- }
-
- // Mark library as already patched.
- original.patch = patch;
-
- // We patch imported libraries after marking the current library as
- // patched, to avoid problems with cyclic dependencies.
- delayedPatches.forEach((String path, LibraryElement importedLibrary) {
- patchDartLibrary(importedLibrary, path);
- });
}
bool isPatchElement(Element element) {
@@ -594,22 +602,16 @@ class Compiler implements DiagnosticListener {
// as the patch library element.
// In this case, the patch library element must not be marked as "patch",
// and its name must make it private.
- if (isPatchElement(patchElement)) {
- internalError("Cannot patch non-existing member '"
- "${patchElement.name.slowToString()}'.");
-
- }
if (!patchElement.name.isPrivate()) {
internalError("Cannot add non-private member '"
"${patchElement.name.slowToString()}' from patch.");
}
- // TODO(lrn): Create a copy of patchElement that isn't added to anything,
- // but which takes its source from patchElement.
+ // TODO(lrn): Create a copy of patchElement that isn't added to any
+ // object/library yet, but which takes its source from patchElement.
throw "Adding members from patch is unsupported";
}
- void patchMember(Element originalElement,
- Element patchElement) {
+ void patchMember(Element originalElement, Element patchElement) {
// The original library has an element with the same name as the patch
// library element.
// In this case, the patch library element must be a function marked as
@@ -618,18 +620,30 @@ class Compiler implements DiagnosticListener {
internalError("Cannot overwrite existing '"
"${originalElement.name.slowToString()}' with non-patch.");
}
+ if (originalElement is PartialClassElement) {
+ // Only happens when patching a library. Dart does not, yet, have nested
+ // classes.
+ if (patchElement is! PartialClassElement) {
+ internalError("Trying to patch class with non-class",
+ element:originalElement);
+ }
+ applyClassPatch(originalElement, patchElement);
+ return;
+ }
if (originalElement is! FunctionElement) {
// TODO(lrn): Handle class declarations too.
internalError("Can only patch functions", element: originalElement);
}
- // TODO(lrn): Abort if the original isn't marked external, when
- // that is added to the language.
+ FunctionElement original = originalElement;
+ if (!original.modifiers.isExternal()) {
+ internalError("Can only patch external functions.", element: original);
+ }
if (patchElement is! FunctionElement ||
- !patchSignatureMatches(originalElement, patchElement)) {
+ !patchSignatureMatches(original, patchElement)) {
internalError("Can only patch functions with matching signatures",
- element: originalElement);
+ element: original);
}
- applyFunctionPatch(originalElement, patchElement);
+ applyFunctionPatch(original, patchElement);
}
bool patchSignatureMatches(FunctionElement original, FunctionElement patch) {
@@ -640,7 +654,6 @@ class Compiler implements DiagnosticListener {
void applyFunctionPatch(FunctionElement element,
FunctionElement patchElement) {
- // Don't just assign the patch field. This also updates the cachedNode.
if (element.isPatched) {
internalError("Trying to patch a function more than once.",
element: element);
@@ -649,9 +662,27 @@ class Compiler implements DiagnosticListener {
internalError("Trying to patch an already compiled function.",
element: element);
}
+ // Don't just assign the patch field. This also updates the cachedNode.
element.setPatch(patchElement);
}
+ void applyClassPatch(PartialClassElement original,
+ PartialClassElement patch) {
+ // Eagerly parse the class so we can patch it.
+ // TODO(lrn): Perhaps find a way to delay parsing until the class is needed,
+ // 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
+ ClassNode node = original.parseNode(this);
+ // Parse patch class with "patch" parser.
+ ClassNode patchNode = patchParser.parsePatchClassNode(patch);
+ Link<Element> patches = patch.members;
+ Element lookupMemberOrConstructor(SourceString name) {
+ Element result = original.lookupLocalMember(name);
+ if (result !== null) return result;
+ return original.lookupConstructor(name);
+ }
+ applyContainerPatch(original, patches, lookupMemberOrConstructor);
+ }
+
/**
* Get an [Uri] pointing to a patch for the dart: library with
* the given path. Returns null if there is no patch.
« 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