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

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

Issue 11016027: Patch cleanup. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 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 * This library contains the infrastructure to parse and integrate patch files. 6 * This library contains the infrastructure to parse and integrate patch files.
7 * 7 *
8 * Three types of elements can be patched: [LibraryElement], [ClassElement], 8 * Three types of elements can be patched: [LibraryElement], [ClassElement],
9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded
10 * together with the corresponding origin library. Which libraries that are 10 * together with the corresponding origin library. Which libraries that are
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 Function idGenerator = compiler.getNextFreeClassId; 159 Function idGenerator = compiler.getNextFreeClassId;
160 PatchListener patchListener = 160 PatchListener patchListener =
161 new PatchElementListener(compiler, 161 new PatchElementListener(compiler,
162 compilationUnit, 162 compilationUnit,
163 idGenerator, 163 idGenerator,
164 imports); 164 imports);
165 new PatchParser(patchListener).parseUnit(tokens); 165 new PatchParser(patchListener).parseUnit(tokens);
166 }); 166 });
167 } 167 }
168 168
169 tree.ClassNode parsePatchClassNode(PartialClassElement element) { 169 void parsePatchClassNode(PartialClassElement element) {
170 // Parse [PartialClassElement] using a "patch"-aware parser instead 170 // Parse [PartialClassElement] using a "patch"-aware parser instead
171 // of calling its [parseNode] method. 171 // of calling its [parseNode] method.
172 if (element.cachedNode != null) return element.cachedNode; 172 if (element.cachedNode != null) return;
173 173
174 return measure(() => compiler.withCurrentElement(element, () { 174 return measure(() => compiler.withCurrentElement(element, () {
175 PatchMemberListener listener = new PatchMemberListener(compiler, element); 175 PatchMemberListener listener = new PatchMemberListener(compiler, element);
176 Parser parser = new PatchClassElementParser(listener); 176 Parser parser = new PatchClassElementParser(listener);
177 Token token = parser.parseTopLevelDeclaration(element.beginToken); 177 Token token = parser.parseTopLevelDeclaration(element.beginToken);
178 assert(token === element.endToken.next); 178 assert(token === element.endToken.next);
179 element.cachedNode = listener.popNode(); 179 element.cachedNode = listener.popNode();
180 assert(listener.nodes.isEmpty()); 180 assert(listener.nodes.isEmpty());
181 return element.cachedNode; 181
182 Link<Element> patches = element.localMembers;
183 applyContainerPatch(element.origin, patches);
182 })); 184 }));
183 } 185 }
186
187 void applyContainerPatch(ScopeContainerElement original,
188 Link<Element> patches) {
189 while (!patches.isEmpty()) {
190 Element patchElement = patches.head;
191 Element originalElement = original.localLookup(patchElement.name);
192 if (patchElement.isAccessor() && originalElement !== null) {
193 if (originalElement.kind !== ElementKind.ABSTRACT_FIELD) {
194 compiler.internalError(
195 "Cannot patch non-getter/setter with getter/setter",
196 element: originalElement);
197 }
198 AbstractFieldElement originalField = originalElement;
199 if (patchElement.isGetter()) {
200 originalElement = originalField.getter;
201 } else {
202 originalElement = originalField.setter;
203 }
204 }
205 if (originalElement === null) {
206 if (isPatchElement(patchElement)) {
207 compiler.internalError("Cannot patch non-existing member '"
208 "${patchElement.name.slowToString()}'.");
209 }
210 } else {
211 patchMember(originalElement, patchElement);
212 }
213 patches = patches.tail;
214 }
215 }
216
217 bool isPatchElement(Element element) {
218 // TODO(lrn): More checks needed if we introduce metadata for real.
219 // In that case, it must have the identifier "native" as metadata.
220 for (Link link = element.metadata; !link.isEmpty(); link = link.tail) {
221 if (link.head is PatchMetadataAnnotation) return true;
222 }
223 return false;
224 }
225
226 void patchMember(Element originalElement, Element patchElement) {
227 // The original library has an element with the same name as the patch
228 // library element.
229 // In this case, the patch library element must be a function marked as
230 // "patch" and it must have the same signature as the function it patches.
231 if (!isPatchElement(patchElement)) {
232 compiler.internalError("Cannot overwrite existing '"
233 "${originalElement.name.slowToString()}' with non-patch.");
234 }
235 if (originalElement is! FunctionElement) {
236 // TODO(lrn): Handle class declarations too.
237 compiler.internalError("Can only patch functions", element: originalElemen t);
238 }
239 FunctionElement original = originalElement;
240 if (!original.modifiers.isExternal()) {
241 compiler.internalError("Can only patch external functions.", element: orig inal);
242 }
243 if (patchElement is! FunctionElement ||
244 !patchSignatureMatches(original, patchElement)) {
245 compiler.internalError("Can only patch functions with matching signatures" ,
246 element: original);
247 }
248 applyFunctionPatch(original, patchElement);
249 }
250
251 bool patchSignatureMatches(FunctionElement original, FunctionElement patch) {
252 // TODO(lrn): Check that patches actually match the signature of
253 // the function it's patching.
254 return true;
255 }
256
257 void applyFunctionPatch(FunctionElement element,
258 FunctionElement patchElement) {
259 if (element.isPatched) {
260 compiler.internalError("Trying to patch a function more than once.",
261 element: element);
262 }
263 if (element.cachedNode !== null) {
264 compiler.internalError("Trying to patch an already compiled function.",
265 element: element);
266 }
267 // Don't just assign the patch field. This also updates the cachedNode.
268 element.setPatch(patchElement);
269 patchElement.origin = element;
270 }
184 } 271 }
185 272
186 /** 273 /**
187 * Extension of the [Listener] interface to handle the extra "patch" pseudo- 274 * Extension of the [Listener] interface to handle the extra "patch" pseudo-
188 * keyword in patch files. 275 * keyword in patch files.
189 * Patch files shouldn't have a type named "patch". 276 * Patch files shouldn't have a type named "patch".
190 */ 277 */
191 abstract class PatchListener extends Listener { 278 abstract class PatchListener extends Listener {
192 void beginPatch(Token patch); 279 void beginPatch(Token patch);
193 void endPatch(Token patch); 280 void endPatch(Token patch);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 super.addMember(element); 489 super.addMember(element);
403 } 490 }
404 } 491 }
405 492
406 // TODO(ahe): Get rid of this class. 493 // TODO(ahe): Get rid of this class.
407 class PatchMetadataAnnotation extends MetadataAnnotation { 494 class PatchMetadataAnnotation extends MetadataAnnotation {
408 final leg.Constant value = null; 495 final leg.Constant value = null;
409 496
410 PatchMetadataAnnotation() : super(STATE_DONE); 497 PatchMetadataAnnotation() : super(STATE_DONE);
411 } 498 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/scanner/class_element_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698