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

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

Issue 9873021: Move frog/leg to lib/compiler/implementation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: 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
« no previous file with comments | « frog/leg/diagnostic_listener.dart ('k') | frog/leg/emitter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #library('elements');
6
7 #import('../tree/tree.dart');
8 #import('../scanner/scannerlib.dart');
9 #import('../leg.dart'); // TODO(karlklose): we only need type.
10 #import('../util/util.dart');
11
12 class ElementCategory {
13 /**
14 * Represents things that we don't expect to find when looking in a
15 * scope.
16 */
17 static final int NONE = 0;
18
19 /** Field, parameter, or variable. */
20 static final int VARIABLE = 1;
21
22 /** Function, method, or foreign function. */
23 static final int FUNCTION = 2;
24
25 static final int CLASS = 4;
26
27 static final int PREFIX = 8;
28
29 /** Constructor or factory. */
30 static final int FACTORY = 16;
31
32 static final int ALIAS = 32;
33
34 static final int SUPER = 64;
35
36 /** Type variable */
37 static final int TYPE_VARIABLE = 128;
38
39 static final int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE;
40
41 static final int IS_EXTENDABLE = CLASS | ALIAS;
42 }
43
44 class ElementKind {
45 final String id;
46 final int category;
47
48 const ElementKind(String this.id, this.category);
49
50 static final ElementKind VARIABLE =
51 const ElementKind('variable', ElementCategory.VARIABLE);
52 static final ElementKind PARAMETER =
53 const ElementKind('parameter', ElementCategory.VARIABLE);
54 // Parameters in constructors that directly initialize fields. For example:
55 // [:A(this.field):].
56 static final ElementKind FIELD_PARAMETER =
57 const ElementKind('field_parameter', ElementCategory.VARIABLE);
58 static final ElementKind FUNCTION =
59 const ElementKind('function', ElementCategory.FUNCTION);
60 static final ElementKind CLASS =
61 const ElementKind('class', ElementCategory.CLASS);
62 static final ElementKind FOREIGN =
63 const ElementKind('foreign', ElementCategory.FUNCTION);
64 static final ElementKind GENERATIVE_CONSTRUCTOR =
65 const ElementKind('generative_constructor', ElementCategory.FACTORY);
66 static final ElementKind FIELD =
67 const ElementKind('field', ElementCategory.VARIABLE);
68 static final ElementKind VARIABLE_LIST =
69 const ElementKind('variable_list', ElementCategory.NONE);
70 static final ElementKind FIELD_LIST =
71 const ElementKind('field_list', ElementCategory.NONE);
72 static final ElementKind GENERATIVE_CONSTRUCTOR_BODY =
73 const ElementKind('generative_constructor_body', ElementCategory.NONE);
74 static final ElementKind COMPILATION_UNIT =
75 const ElementKind('compilation_unit', ElementCategory.NONE);
76 static final ElementKind GETTER =
77 const ElementKind('getter', ElementCategory.NONE);
78 static final ElementKind SETTER =
79 const ElementKind('setter', ElementCategory.NONE);
80 static final ElementKind TYPE_VARIABLE =
81 const ElementKind('type_variable', ElementCategory.TYPE_VARIABLE);
82 static final ElementKind ABSTRACT_FIELD =
83 const ElementKind('abstract_field', ElementCategory.VARIABLE);
84 static final ElementKind LIBRARY =
85 const ElementKind('library', ElementCategory.NONE);
86 static final ElementKind PREFIX =
87 const ElementKind('prefix', ElementCategory.PREFIX);
88 static final ElementKind TYPEDEF =
89 const ElementKind('typedef', ElementCategory.ALIAS);
90
91 static final ElementKind STATEMENT =
92 const ElementKind('statement', ElementCategory.NONE);
93 static final ElementKind LABEL =
94 const ElementKind('label', ElementCategory.NONE);
95
96 toString() => id;
97 }
98
99 class Element implements Hashable {
100 final SourceString name;
101 final ElementKind kind;
102 final Element enclosingElement;
103 Modifiers get modifiers() => null;
104
105 Node parseNode(DiagnosticListener listener) {
106 listener.cancel("Internal Error: $this.parseNode", token: position());
107 }
108
109 Type computeType(Compiler compiler) {
110 compiler.internalError("$this.computeType.", token: position());
111 }
112
113 bool isFunction() => kind === ElementKind.FUNCTION;
114 bool isMember() =>
115 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS;
116 bool isInstanceMember() => false;
117 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory();
118 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR;
119 bool isCompilationUnit() {
120 return kind === ElementKind.COMPILATION_UNIT ||
121 kind === ElementKind.LIBRARY;
122 }
123 bool isClass() => kind === ElementKind.CLASS;
124 bool isVariable() => kind === ElementKind.VARIABLE;
125 bool isParameter() => kind === ElementKind.PARAMETER;
126 bool isStatement() => kind === ElementKind.STATEMENT;
127 bool isTypedef() => kind === ElementKind.TYPEDEF;
128 bool isTypeVariable() => kind === ElementKind.TYPE_VARIABLE;
129 bool isGetter() => kind === ElementKind.GETTER;
130 bool isSetter() => kind === ElementKind.SETTER;
131 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0;
132 bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0;
133
134 bool isAssignable() {
135 if (modifiers != null && modifiers.isFinal()) return false;
136 if (isFunction() || isGenerativeConstructor()) return false;
137 return true;
138 }
139
140 Token position() => null;
141
142 Token findMyName(Token token) {
143 for (Token t = token; t !== EOF_TOKEN; t = t.next) {
144 if (t.value == name) return t;
145 }
146 return token;
147 }
148
149 Element(this.name, this.kind, this.enclosingElement) {
150 assert(getLibrary() !== null);
151 }
152
153 // TODO(kasperl): This is a very bad hash code for the element and
154 // there's no reason why two elements with the same name should have
155 // the same hash code. Replace this with a simple id in the element?
156 int hashCode() => name.hashCode();
157
158 CompilationUnitElement getCompilationUnit() {
159 Element element = this;
160 while (element !== null && !element.isCompilationUnit()) {
161 element = element.enclosingElement;
162 }
163 return element;
164 }
165
166 LibraryElement getLibrary() {
167 Element element = this;
168 while (element.kind !== ElementKind.LIBRARY) {
169 element = element.enclosingElement;
170 }
171 return element;
172 }
173
174 ClassElement getEnclosingClass() {
175 for (Element e = this; e !== null; e = e.enclosingElement) {
176 if (e.kind === ElementKind.CLASS) return e;
177 }
178 return null;
179 }
180
181 toString() => '$kind(${name.slowToString()})';
182
183 bool _isNative = false;
184 void setNative() => _isNative = true;
185 bool isNative() => _isNative;
186 }
187
188 class ContainerElement extends Element {
189 ContainerElement(name, kind, enclosingElement) :
190 super(name, kind, enclosingElement);
191
192 abstract void addMember(Element element, DiagnosticListener listener);
193
194 void addGetterOrSetter(Element element,
195 Element existing,
196 DiagnosticListener listener) {
197 void reportError(Element other) {
198 listener.cancel('duplicate definition of ${element.name.slowToString()}',
199 element: element);
200 listener.cancel('existing definition', element: other);
201 }
202
203 if (existing != null) {
204 if (existing.kind !== ElementKind.ABSTRACT_FIELD) {
205 reportError(existing);
206 } else {
207 AbstractFieldElement field = existing;
208 if (element.kind == ElementKind.GETTER) {
209 if (field.getter != null && field.getter != element) {
210 reportError(field.getter);
211 }
212 field.getter = element;
213 } else {
214 if (field.setter != null && field.setter != element) {
215 reportError(field.setter);
216 }
217 field.setter = element;
218 }
219 }
220 } else {
221 AbstractFieldElement field = new AbstractFieldElement(element.name, this);
222 addMember(field, listener);
223 if (element.kind == ElementKind.GETTER) {
224 field.getter = element;
225 } else {
226 field.setter = element;
227 }
228 }
229 }
230 }
231
232 class CompilationUnitElement extends ContainerElement {
233 final Script script;
234 Link<Element> topLevelElements = const EmptyLink<Element>();
235
236 CompilationUnitElement(Script script, Element enclosing)
237 : this.script = script,
238 super(new SourceString(script.name),
239 ElementKind.COMPILATION_UNIT,
240 enclosing);
241
242 CompilationUnitElement.library(Script script)
243 : this.script = script,
244 super(new SourceString(script.name), ElementKind.LIBRARY, null);
245
246 void addMember(Element element, DiagnosticListener listener) {
247 LibraryElement library = enclosingElement;
248 library.addMember(element, listener);
249 topLevelElements = topLevelElements.prepend(element);
250 }
251
252 void define(Element element, DiagnosticListener listener) {
253 LibraryElement library = enclosingElement;
254 library.define(element, listener);
255 }
256
257 void addTag(ScriptTag tag, DiagnosticListener listener) {
258 listener.cancel("script tags not allowed here", node: tag);
259 }
260 }
261
262 class LibraryElement extends CompilationUnitElement {
263 // TODO(ahe): Library element should not be a subclass of
264 // CompilationUnitElement.
265
266 Link<CompilationUnitElement> compilationUnits =
267 const EmptyLink<CompilationUnitElement>();
268 Link<ScriptTag> tags = const EmptyLink<ScriptTag>();
269 ScriptTag libraryTag;
270 Map<SourceString, Element> elements;
271 bool canUseNative = false;
272
273 LibraryElement(Script script)
274 : elements = new Map<SourceString, Element>(),
275 super.library(script);
276
277 void addCompilationUnit(CompilationUnitElement element) {
278 compilationUnits = compilationUnits.prepend(element);
279 }
280
281 void addTag(ScriptTag tag, DiagnosticListener listener) {
282 tags = tags.prepend(tag);
283 }
284
285 void addMember(Element element, DiagnosticListener listener) {
286 topLevelElements = topLevelElements.prepend(element);
287 define(element, listener);
288 }
289
290 void define(Element element, DiagnosticListener listener) {
291 if (element.kind == ElementKind.GETTER
292 || element.kind == ElementKind.SETTER) {
293 addGetterOrSetter(element, elements[element.name], listener);
294 } else {
295 Element existing = elements.putIfAbsent(element.name, () => element);
296 if (existing !== element) {
297 listener.cancel('duplicate definition', token: element.position());
298 listener.cancel('existing definition', token: existing.position());
299 }
300 }
301 }
302
303 Element find(SourceString elementName) {
304 return elements[elementName];
305 }
306
307 void forEachExport(f(Element element)) {
308 elements.forEach((SourceString _, Element e) {
309 if (this === e.getLibrary()
310 && e.kind !== ElementKind.PREFIX
311 && e.kind !== ElementKind.FOREIGN) {
312 if (!e.name.isPrivate()) f(e);
313 }
314 });
315 }
316
317 bool hasLibraryName() => libraryTag !== null;
318 }
319
320 class PrefixElement extends Element {
321 Map<SourceString, Element> imported;
322 Token firstPosition;
323
324 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition)
325 : imported = new Map<SourceString, Element>(),
326 super(prefix, ElementKind.PREFIX, enclosing);
327
328 lookupLocalMember(SourceString memberName) => imported[memberName];
329
330 Type computeType(Compiler compiler) => compiler.types.dynamicType;
331
332 Token position() => firstPosition;
333 }
334
335 class TypedefElement extends Element {
336 Token token;
337 TypedefElement(SourceString name, Element enclosing, this.token)
338 : super(name, ElementKind.TYPEDEF, enclosing);
339
340 position() => findMyName(token);
341 }
342
343 class VariableElement extends Element {
344 final VariableListElement variables;
345 Expression cachedNode; // The send or the identifier in the variables list.
346
347 Modifiers get modifiers() => variables.modifiers;
348
349 VariableElement(SourceString name,
350 VariableListElement this.variables,
351 ElementKind kind,
352 Element enclosing,
353 [Node node])
354 : super(name, kind, enclosing), cachedNode = node;
355
356 Node parseNode(DiagnosticListener listener) {
357 if (cachedNode !== null) return cachedNode;
358 VariableDefinitions definitions = variables.parseNode(listener);
359 for (Link<Node> link = definitions.definitions.nodes;
360 !link.isEmpty(); link = link.tail) {
361 Expression initializedIdentifier = link.head;
362 Identifier identifier = initializedIdentifier.asIdentifier();
363 if (identifier === null) {
364 identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
365 }
366 if (name === identifier.source) {
367 cachedNode = initializedIdentifier;
368 return cachedNode;
369 }
370 }
371 listener.cancel('internal error: could not find $name', node: variables);
372 }
373
374 Type computeType(Compiler compiler) {
375 return variables.computeType(compiler);
376 }
377
378 Type get type() => variables.type;
379
380 bool isInstanceMember() {
381 return isMember() && !modifiers.isStatic();
382 }
383
384 // Note: cachedNode.getBeginToken() will not be correct in all
385 // cases, for example, for function typed parameters.
386 Token position() => findMyName(variables.position());
387 }
388
389 /**
390 * Parameters in constructors that directly initialize fields. For example:
391 * [:A(this.field):].
392 */
393 class FieldParameterElement extends VariableElement {
394 VariableElement fieldElement;
395
396 FieldParameterElement(SourceString name,
397 this.fieldElement,
398 VariableListElement variables,
399 Element enclosing,
400 Node node)
401 : super(name, variables, ElementKind.FIELD_PARAMETER, enclosing, node);
402 }
403
404 // This element represents a list of variable or field declaration.
405 // It contains the node, and the type. A [VariableElement] always
406 // references its [VariableListElement]. It forwards its
407 // [computeType] and [parseNode] methods to this element.
408 class VariableListElement extends Element {
409 VariableDefinitions cachedNode;
410 Type type;
411 final Modifiers modifiers;
412
413 VariableListElement(ElementKind kind,
414 Modifiers this.modifiers,
415 Element enclosing)
416 : super(null, kind, enclosing);
417
418 VariableListElement.node(VariableDefinitions node,
419 ElementKind kind,
420 Element enclosing)
421 : super(null, kind, enclosing),
422 this.cachedNode = node,
423 this.modifiers = node.modifiers;
424
425 VariableDefinitions parseNode(DiagnosticListener listener) {
426 return cachedNode;
427 }
428
429 Type computeType(Compiler compiler) {
430 if (type != null) return type;
431 type = getType(parseNode(compiler).type, compiler, getLibrary());
432 return type;
433 }
434
435 Token position() => cachedNode.getBeginToken();
436 }
437
438 class ForeignElement extends Element {
439 ForeignElement(SourceString name, ContainerElement enclosingElement)
440 : super(name, ElementKind.FOREIGN, enclosingElement);
441
442 Type computeType(Compiler compiler) {
443 return compiler.types.dynamicType;
444 }
445
446 parseNode(DiagnosticListener listener) {
447 throw "internal error: ForeignElement has no node";
448 }
449 }
450
451 class AbstractFieldElement extends Element {
452 FunctionElement getter;
453 FunctionElement setter;
454 Modifiers modifiers;
455
456 AbstractFieldElement(SourceString name, Element enclosing)
457 : super(name, ElementKind.ABSTRACT_FIELD, enclosing),
458 modifiers = new Modifiers.empty();
459
460 Type computeType(Compiler compiler) {
461 throw "internal error: AbstractFieldElement has no type";
462 }
463
464 Node parseNode(DiagnosticListener listener) {
465 throw "internal error: AbstractFieldElement has no node";
466 }
467
468 position() {
469 // The getter and setter may be defined in two different
470 // compilation units. However, we know that one of them is
471 // non-null and defined in the same compilation unit as the
472 // abstract element.
473 //
474 // We need to make sure that the position returned is relative to
475 // the compilation unit of the abstract element.
476 if (getter !== null && getter.enclosingElement === enclosingElement) {
477 return getter.position();
478 } else if (setter != null) {
479 // TODO(ahe): checking for null should not be necessary.
480 return setter.position();
481 }
482 }
483 }
484
485 /** DEPRECATED. */
486 Type getType(TypeAnnotation typeAnnotation,
487 Compiler compiler,
488 LibraryElement library) {
489 // TODO(karlklose,ngeoffray): This method should be removed and the
490 // information should be computed by the resolver.
491
492 if (typeAnnotation == null || typeAnnotation.typeName == null) {
493 return compiler.types.dynamicType;
494 }
495 Identifier identifier = typeAnnotation.typeName.asIdentifier();
496 if (identifier === null) {
497 compiler.reportWarning(typeAnnotation.typeName,
498 'library prefixes not handled');
499 return compiler.types.dynamicType;
500 }
501 SourceString name = identifier.source;
502 Element element = library.find(name);
503 if (element !== null) {
504 if (element.isTypedef()) {
505 // TODO(ngeoffray): This is a hack to help us get support for the
506 // DOM library.
507 // TODO(ngeoffray): The list of types for the argument is wrong.
508 return new FunctionType(compiler.types.dynamicType,
509 const EmptyLink<Type>(),
510 element);
511 }
512 if (element.isClass()) {
513 // TODO(karlklose): substitute type parameters.
514 return element.computeType(compiler);
515 }
516 }
517 Type type = compiler.types.lookup(name);
518 if (type === null) {
519 type = compiler.types.dynamicType;
520 }
521 return type;
522 }
523
524 class FunctionParameters {
525 Link<Element> requiredParameters;
526 Link<Element> optionalParameters;
527 int requiredParameterCount;
528 int optionalParameterCount;
529 FunctionParameters(this.requiredParameters,
530 this.optionalParameters,
531 this.requiredParameterCount,
532 this.optionalParameterCount);
533
534 void forEachParameter(void function(Element parameter)) {
535 for (Link<Element> link = requiredParameters;
536 !link.isEmpty();
537 link = link.tail) {
538 function(link.head);
539 }
540 for (Link<Element> link = optionalParameters;
541 !link.isEmpty();
542 link = link.tail) {
543 function(link.head);
544 }
545 }
546
547 int get parameterCount() => requiredParameterCount + optionalParameterCount;
548 }
549
550 class FunctionElement extends Element {
551 FunctionExpression cachedNode;
552 Type type;
553 final Modifiers modifiers;
554
555 FunctionParameters functionParameters;
556
557 /**
558 * If this is an interface constructor, [defaultImplementation] will
559 * changed by the resolver to point to the default
560 * implementation. Otherwise, [:defaultImplementation === this:].
561 */
562 FunctionElement defaultImplementation;
563
564 FunctionElement(SourceString name,
565 ElementKind kind,
566 Modifiers modifiers,
567 Element enclosing)
568 : this.tooMuchOverloading(name, null, kind, modifiers, enclosing, null);
569
570 FunctionElement.node(SourceString name,
571 FunctionExpression node,
572 ElementKind kind,
573 Modifiers modifiers,
574 Element enclosing)
575 : this.tooMuchOverloading(name, node, kind, modifiers, enclosing, null);
576
577 FunctionElement.from(SourceString name,
578 FunctionElement other,
579 Element enclosing)
580 : this.tooMuchOverloading(name, other.cachedNode, other.kind,
581 other.modifiers, enclosing,
582 other.functionParameters);
583
584 FunctionElement.tooMuchOverloading(SourceString name,
585 FunctionExpression this.cachedNode,
586 ElementKind kind,
587 Modifiers this.modifiers,
588 Element enclosing,
589 FunctionParameters this.functionParameters)
590 : super(name, kind, enclosing)
591 {
592 defaultImplementation = this;
593 }
594
595 bool isInstanceMember() {
596 return isMember()
597 && kind != ElementKind.GENERATIVE_CONSTRUCTOR
598 && !modifiers.isFactory()
599 && !modifiers.isStatic();
600 }
601
602 FunctionParameters computeParameters(Compiler compiler) {
603 if (functionParameters !== null) return functionParameters;
604 functionParameters = compiler.resolveSignature(this);
605 return functionParameters;
606 }
607
608 int requiredParameterCount(Compiler compiler) {
609 return computeParameters(compiler).requiredParameterCount;
610 }
611
612 int optionalParameterCount(Compiler compiler) {
613 return computeParameters(compiler).optionalParameterCount;
614 }
615
616 int parameterCount(Compiler compiler) {
617 return computeParameters(compiler).parameterCount;
618 }
619
620 FunctionType computeType(Compiler compiler) {
621 if (type != null) return type;
622 FunctionParameters parameters = computeParameters(compiler);
623 Types types = compiler.types;
624 FunctionExpression node =
625 compiler.parser.measure(() => parseNode(compiler));
626 Type returnType = getType(node.returnType, compiler, getLibrary());
627 if (returnType === null) returnType = types.dynamicType;
628
629 LinkBuilder<Type> parameterTypes = new LinkBuilder<Type>();
630 for (Link<Element> link = parameters.requiredParameters;
631 !link.isEmpty();
632 link = link.tail) {
633 parameterTypes.addLast(link.head.computeType(compiler));
634 }
635 type = new FunctionType(returnType, parameterTypes.toLink(), this);
636 return type;
637 }
638
639 Node parseNode(DiagnosticListener listener) => cachedNode;
640
641 Token position() => cachedNode.getBeginToken();
642 }
643
644 class ConstructorBodyElement extends FunctionElement {
645 FunctionElement constructor;
646
647 ConstructorBodyElement(FunctionElement constructor)
648 : this.constructor = constructor,
649 super(constructor.name,
650 ElementKind.GENERATIVE_CONSTRUCTOR_BODY,
651 null,
652 constructor.enclosingElement) {
653 functionParameters = constructor.functionParameters;
654 }
655
656 bool isInstanceMember() => true;
657
658 FunctionType computeType(Compiler compiler) { unreachable(); }
659
660 Node parseNode(DiagnosticListener listener) {
661 if (cachedNode !== null) return cachedNode;
662 cachedNode = constructor.parseNode(listener);
663 assert(cachedNode !== null);
664 return cachedNode;
665 }
666
667 Token position() => constructor.position();
668 }
669
670 class SynthesizedConstructorElement extends FunctionElement {
671 SynthesizedConstructorElement(Element enclosing)
672 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
673 null, enclosing);
674
675 Token position() => enclosingElement.position();
676 }
677
678 class ClassElement extends ContainerElement {
679 Type type;
680 Type supertype;
681 Type defaultClass;
682 Link<Element> members = const EmptyLink<Element>();
683 Map<SourceString, Element> localMembers;
684 Map<SourceString, Element> constructors;
685 Link<Type> interfaces = const EmptyLink<Type>();
686 Map<SourceString, TypeVariableElement> typeParameters;
687 bool isResolved = false;
688 bool isBeingResolved = false;
689 // backendMembers are members that have been added by the backend to simplify
690 // compilation. They don't have any user-side counter-part.
691 Link<Element> backendMembers = const EmptyLink<Element>();
692
693 Link<Type> allSupertypes;
694
695 ClassElement(SourceString name, CompilationUnitElement enclosing)
696 : localMembers = new Map<SourceString, Element>(),
697 constructors = new Map<SourceString, Element>(),
698 typeParameters = new Map<SourceString, TypeVariableElement>(),
699 super(name, ElementKind.CLASS, enclosing);
700
701 void addMember(Element element, DiagnosticListener listener) {
702 members = members.prepend(element);
703 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
704 element.modifiers.isFactory()) {
705 constructors[element.name] = element;
706 } else if (element.kind == ElementKind.GETTER
707 || element.kind == ElementKind.SETTER) {
708 addGetterOrSetter(element, localMembers[element.name], listener);
709 } else {
710 localMembers[element.name] = element;
711 }
712 }
713
714 Type computeType(compiler) {
715 if (type === null) {
716 type = new SimpleType(name, this);
717 }
718 return type;
719 }
720
721 ClassElement ensureResolved(Compiler compiler) {
722 if (!isResolved && !isBeingResolved) {
723 isBeingResolved = true;
724 compiler.resolveType(this);
725 isBeingResolved = false;
726 isResolved = true;
727 }
728 return this;
729 }
730
731 Element lookupTypeParameter(SourceString parameterName) {
732 Element result = typeParameters[parameterName];
733 return result;
734 }
735
736 Element lookupLocalMember(SourceString memberName) {
737 return localMembers[memberName];
738 }
739
740 Element lookupSuperMember(SourceString memberName) {
741 for (ClassElement s = superclass; s != null; s = s.superclass) {
742 Element e = s.lookupLocalMember(memberName);
743 if (e !== null) {
744 if (!memberName.isPrivate() || getLibrary() === e.getLibrary()) {
745 return e;
746 }
747 }
748 }
749 return null;
750 }
751
752 Element lookupConstructor(SourceString className,
753 [SourceString constructorName =
754 const SourceString(''),
755 Element noMatch(Element)]) {
756 // TODO(karlklose): have a map from class names to a map of constructors
757 // instead of creating the name here?
758 SourceString normalizedName;
759 if (constructorName !== const SourceString('')) {
760 normalizedName = Elements.constructConstructorName(className,
761 constructorName);
762 } else {
763 normalizedName = className;
764 }
765 Element result = constructors[normalizedName];
766 if (result === null && noMatch !== null) {
767 result = noMatch(lookupLocalMember(constructorName));
768 }
769 return result;
770 }
771
772 /**
773 * Returns the super class, if any.
774 *
775 * The returned element may not be resolved yet.
776 */
777 ClassElement get superclass() {
778 assert(isResolved);
779 return supertype === null ? null : supertype.element;
780 }
781
782 bool isInterface() => false;
783 bool isNative() => nativeName != null;
784 SourceString nativeName;
785 }
786
787 class Elements {
788 static bool isLocal(Element element) {
789 return ((element !== null)
790 && !element.isInstanceMember()
791 && !isStaticOrTopLevelField(element)
792 && !isStaticOrTopLevelFunction(element)
793 && (element.kind === ElementKind.VARIABLE ||
794 element.kind === ElementKind.PARAMETER ||
795 element.kind === ElementKind.FUNCTION));
796 }
797
798 static bool isInstanceField(Element element) {
799 return (element !== null)
800 && element.isInstanceMember()
801 && (element.kind === ElementKind.FIELD
802 || element.kind === ElementKind.GETTER
803 || element.kind === ElementKind.SETTER);
804 }
805
806 static bool isStaticOrTopLevel(Element element) {
807 return (element != null)
808 && !element.isInstanceMember()
809 && element.enclosingElement !== null
810 && (element.enclosingElement.kind == ElementKind.CLASS ||
811 element.enclosingElement.kind == ElementKind.COMPILATION_UNIT ||
812 element.enclosingElement.kind == ElementKind.LIBRARY);
813 }
814
815 static bool isStaticOrTopLevelField(Element element) {
816 return isStaticOrTopLevel(element)
817 && (element.kind === ElementKind.FIELD
818 || element.kind === ElementKind.GETTER
819 || element.kind === ElementKind.SETTER);
820 }
821
822 static bool isStaticOrTopLevelFunction(Element element) {
823 return isStaticOrTopLevel(element)
824 && (element.kind === ElementKind.FUNCTION);
825 }
826
827 static bool isInstanceMethod(Element element) {
828 return (element != null)
829 && element.isInstanceMember()
830 && (element.kind === ElementKind.FUNCTION);
831 }
832
833 static bool isInstanceSend(Send send, TreeElements elements) {
834 Element element = elements[send];
835 if (element === null) return !isClosureSend(send, elements);
836 return isInstanceMethod(element) || isInstanceField(element);
837 }
838
839 static bool isClosureSend(Send send, TreeElements elements) {
840 if (send.isPropertyAccess) return false;
841 if (send.receiver !== null) return false;
842 Element element = elements[send];
843 // (o)() or foo()().
844 if (element === null && send.selector.asIdentifier() === null) return true;
845 if (element === null) return false;
846 // foo() with foo a local or a parameter.
847 return isLocal(element);
848 }
849
850 static SourceString constructConstructorName(SourceString receiver,
851 SourceString selector) {
852 String r = receiver.slowToString();
853 String s = selector.slowToString();
854 return new SourceString('$r\$$s');
855 }
856
857 static SourceString constructOperatorName(SourceString receiver,
858 SourceString selector,
859 [bool isPrefix = false]) {
860 String str = selector.stringValue;
861 if (str === '==' || str === '!=') return Namer.OPERATOR_EQUALS;
862
863 if (str === '~') str = 'not';
864 else if (str === 'negate' || (str === '-' && isPrefix)) str = 'negate';
865 else if (str === '[]') str = 'index';
866 else if (str === '[]=') str = 'indexSet';
867 else if (str === '*' || str === '*=') str = 'mul';
868 else if (str === '/' || str === '/=') str = 'div';
869 else if (str === '%' || str === '%=') str = 'mod';
870 else if (str === '~/' || str === '~/=') str = 'tdiv';
871 else if (str === '+' || str === '+=') str = 'add';
872 else if (str === '-' || str === '-=') str = 'sub';
873 else if (str === '<<' || str === '<<=') str = 'shl';
874 else if (str === '>>' || str === '>>=') str = 'shr';
875 else if (str === '>=') str = 'ge';
876 else if (str === '>') str = 'gt';
877 else if (str === '<=') str = 'le';
878 else if (str === '<') str = 'lt';
879 else if (str === '&' || str === '&=') str = 'and';
880 else if (str === '^' || str === '^=') str = 'xor';
881 else if (str === '|' || str === '|=') str = 'or';
882 else {
883 throw new Exception('Unhandled selector: ${selector.slowToString()}');
884 }
885 return new SourceString('$receiver\$$str');
886 }
887
888 static bool isStringSupertype(Element element, Compiler compiler) {
889 LibraryElement coreLibrary = compiler.coreLibrary;
890 return (element == coreLibrary.find(const SourceString('Comparable')))
891 || (element == coreLibrary.find(const SourceString('Hashable')))
892 || (element == coreLibrary.find(const SourceString('Pattern')));
893 }
894
895 static bool isListSupertype(Element element, Compiler compiler) {
896 LibraryElement coreLibrary = compiler.coreLibrary;
897 return (element == coreLibrary.find(const SourceString('Collection')))
898 || (element == coreLibrary.find(const SourceString('Iterable')));
899 }
900 }
901
902
903 class LabelElement extends Element {
904 final Identifier label;
905 final String labelName;
906 final TargetElement target;
907 bool isBreakTarget = false;
908 bool isContinueTarget = false;
909 LabelElement(Identifier label, this.labelName, this.target,
910 Element enclosingElement)
911 : this.label = label,
912 super(label.source, ElementKind.LABEL, enclosingElement);
913
914 void setBreakTarget() {
915 isBreakTarget = true;
916 target.isBreakTarget = true;
917 }
918 void setContinueTarget() {
919 isContinueTarget = true;
920 target.isContinueTarget = true;
921 }
922
923 bool get isTarget() => isBreakTarget || isContinueTarget;
924 Node parseNode(DiagnosticListener l) => label;
925
926 Token position() => label.token;
927 String toString() => "${labelName}:";
928 }
929
930 // Represents a reference to a statement, either a label or the
931 // default target of a break or continue.
932 class TargetElement extends Element {
933 // TODO(lrn): StatementElement is not just referencing statements anymore.
934 final Node statement;
935 final int nestingLevel;
936 Link<LabelElement> labels = const EmptyLink<LabelElement>();
937 bool isBreakTarget = false;
938 bool isContinueTarget = false;
939
940 TargetElement(this.statement, this.nestingLevel, Element enclosingElement)
941 : super(const SourceString(""), ElementKind.STATEMENT, enclosingElement);
942 bool get isTarget() => isBreakTarget || isContinueTarget;
943
944 LabelElement addLabel(Identifier label, String labelName) {
945 LabelElement result = new LabelElement(label, labelName, this,
946 enclosingElement);
947 labels = labels.prepend(result);
948 return result;
949 }
950
951 Node parseNode(DiagnosticListener l) => statement;
952
953 bool get isSwitch() => statement is SwitchStatement;
954
955 Token position() => statement.getBeginToken();
956 String toString() => statement.toString();
957 }
958
959 class TypeVariableElement extends Element {
960 final Node node;
961 Type bound;
962 Type type;
963 TypeVariableElement(name, Element enclosing, this.node, this.type,
964 [this.bound])
965 : super(name, ElementKind.TYPE_VARIABLE, enclosing);
966 Type computeType(compiler) => type;
967 Node parseNode(compiler) => node;
968 toString() => "${enclosingElement.toString()}.${name.slowToString()}";
969 }
OLDNEW
« no previous file with comments | « frog/leg/diagnostic_listener.dart ('k') | frog/leg/emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698