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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/elements/modelx.dart

Issue 14168003: Implement implicit constructors in mixin applications. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 8 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library elements.modelx; 5 library elements.modelx;
6 6
7 import 'dart:uri'; 7 import 'dart:uri';
8 import 'dart:collection' show LinkedHashMap; 8 import 'dart:collection' show LinkedHashMap;
9 9
10 import 'elements.dart'; 10 import 'elements.dart';
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 125
126 /** 126 /**
127 * Is [:true:] if this element introduces the entity of this element. 127 * Is [:true:] if this element introduces the entity of this element.
128 * 128 *
129 * See [:patch_parser.dart:] for a description of the terminology. 129 * See [:patch_parser.dart:] for a description of the terminology.
130 */ 130 */
131 bool get isDeclaration => !isPatch; 131 bool get isDeclaration => !isPatch;
132 132
133 bool get isSynthesized => false; 133 bool get isSynthesized => false;
134 134
135 bool get isForwardingConstructor => false;
136
135 /** 137 /**
136 * Returns the element which defines the implementation for the entity of this 138 * Returns the element which defines the implementation for the entity of this
137 * element. 139 * element.
138 * 140 *
139 * See [:patch_parser.dart:] for a description of the terminology. 141 * See [:patch_parser.dart:] for a description of the terminology.
140 */ 142 */
141 Element get implementation => isPatched ? patch : this; 143 Element get implementation => isPatched ? patch : this;
142 144
143 /** 145 /**
144 * Returns the element which introduces the entity of this element. 146 * Returns the element which introduces the entity of this element.
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 void setFixedBackendName(String name) { 265 void setFixedBackendName(String name) {
264 _fixedBackendName = name; 266 _fixedBackendName = name;
265 } 267 }
266 268
267 FunctionElement asFunctionElement() => null; 269 FunctionElement asFunctionElement() => null;
268 270
269 static bool isInvalid(Element e) => e == null || e.isErroneous(); 271 static bool isInvalid(Element e) => e == null || e.isErroneous();
270 272
271 bool isAbstract(Compiler compiler) => modifiers.isAbstract(); 273 bool isAbstract(Compiler compiler) => modifiers.isAbstract();
272 bool isForeign(Compiler compiler) => getLibrary() == compiler.foreignLibrary; 274 bool isForeign(Compiler compiler) => getLibrary() == compiler.foreignLibrary;
275
276 FunctionElement get targetConstructor => null;
273 } 277 }
274 278
275 /** 279 /**
276 * Represents an unresolvable or duplicated element. 280 * Represents an unresolvable or duplicated element.
277 * 281 *
278 * An [ErroneousElement] is used instead of [null] to provide additional 282 * An [ErroneousElement] is used instead of [null] to provide additional
279 * information about the error that caused the element to be unresolvable 283 * information about the error that caused the element to be unresolvable
280 * or otherwise invalid. 284 * or otherwise invalid.
281 * 285 *
282 * Accessing any field or calling any method defined on [ErroneousElement] 286 * Accessing any field or calling any method defined on [ErroneousElement]
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 Node parseNode(DiagnosticListener listener) { 1260 Node parseNode(DiagnosticListener listener) {
1257 if (cachedNode != null) return cachedNode; 1261 if (cachedNode != null) return cachedNode;
1258 cachedNode = constructor.parseNode(listener); 1262 cachedNode = constructor.parseNode(listener);
1259 assert(cachedNode != null); 1263 assert(cachedNode != null);
1260 return cachedNode; 1264 return cachedNode;
1261 } 1265 }
1262 1266
1263 Token position() => constructor.position(); 1267 Token position() => constructor.position();
1264 } 1268 }
1265 1269
1270 /**
1271 * A constructor that is not defined in the source code but rather implied by
1272 * the language semantics.
1273 *
1274 * This class is used to represent default constructors and forwarding
1275 * constructors for mixin applications.
1276 */
1266 class SynthesizedConstructorElementX extends FunctionElementX { 1277 class SynthesizedConstructorElementX extends FunctionElementX {
1278 /// The target constructor if this synthetic constructor is a forwarding
1279 /// constructor in a mixin application.
1280 final FunctionElement target;
1281
1267 SynthesizedConstructorElementX(Element enclosing) 1282 SynthesizedConstructorElementX(Element enclosing)
1268 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, 1283 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
1269 Modifiers.EMPTY, enclosing); 1284 Modifiers.EMPTY, enclosing),
1285 target = null;
1270 1286
1271 SynthesizedConstructorElementX.forDefault(Element enclosing, 1287 SynthesizedConstructorElementX.forDefault(Element enclosing,
1272 Compiler compiler) 1288 Compiler compiler)
1273 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, 1289 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
1274 Modifiers.EMPTY, enclosing) { 1290 Modifiers.EMPTY, enclosing),
1291 target = null {
1292 // TODO(karlklose): get rid of the fake AST.
1275 type = new FunctionType(this, 1293 type = new FunctionType(this,
1276 compiler.types.voidType, 1294 compiler.types.voidType,
1277 const Link<DartType>(), 1295 const Link<DartType>(),
1278 const Link<DartType>(), 1296 const Link<DartType>(),
1279 const Link<SourceString>(), 1297 const Link<SourceString>(),
1280 const Link<DartType>()); 1298 const Link<DartType>());
1281 cachedNode = new FunctionExpression( 1299 cachedNode = new FunctionExpression(
1282 new Identifier(enclosing.position()), 1300 new Identifier(enclosing.position()),
1283 new NodeList.empty(), 1301 new NodeList.empty(),
1284 new Block(new NodeList.empty()), 1302 new Block(new NodeList.empty()),
1285 null, Modifiers.EMPTY, null, null); 1303 null, Modifiers.EMPTY, null, null);
1286 } 1304 }
1287 1305
1306 /**
1307 * Create synthetic constructor that directly forwards to a constructor in the
1308 * super class of a mixin application.
1309 *
1310 * In a mixin application `Base with M`, any constructor defined in `Base` is
1311 * available as if they were a constructor defined in the mixin application
1312 * with the same formal parameters that calls the constructor in the super
1313 * class via a `super` initializer (see Ch. 9.1 in the specification).
1314 */
1315 SynthesizedConstructorElementX.forwarding(SourceString name, this.target,
1316 Element enclosing)
1317 : super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
1318 enclosing);
1319
1320 Token position() => enclosingElement.position();
1321
1288 bool get isSynthesized => true; 1322 bool get isSynthesized => true;
1289 1323
1290 Token position() => enclosingElement.position(); 1324 bool get isForwardingConstructor => target != null;
1325
1326 FunctionElement get targetConstructor => target;
1327
1328 FunctionSignature computeSignature(compiler) {
1329 if (target != null) {
1330 return target.computeSignature(compiler);
1331 } else {
1332 assert(cachedNode != null);
1333 return super.computeSignature(compiler);
1334 }
1335 }
1336
1337 get declaration => this;
1338 get implementation => this;
1339 get defaultImplementation => this;
1291 } 1340 }
1292 1341
1293 class VoidElementX extends ElementX { 1342 class VoidElementX extends ElementX {
1294 VoidElementX(Element enclosing) 1343 VoidElementX(Element enclosing)
1295 : super(const SourceString('void'), ElementKind.VOID, enclosing); 1344 : super(const SourceString('void'), ElementKind.VOID, enclosing);
1296 DartType computeType(compiler) => compiler.types.voidType; 1345 DartType computeType(compiler) => compiler.types.voidType;
1297 Node parseNode(_) { 1346 Node parseNode(_) {
1298 throw 'internal error: parseNode on void'; 1347 throw 'internal error: parseNode on void';
1299 } 1348 }
1300 bool impliesType() => true; 1349 bool impliesType() => true;
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1832 return super.toString(); 1881 return super.toString();
1833 } 1882 }
1834 } 1883 }
1835 } 1884 }
1836 1885
1837 class MixinApplicationElementX extends BaseClassElementX 1886 class MixinApplicationElementX extends BaseClassElementX
1838 implements MixinApplicationElement { 1887 implements MixinApplicationElement {
1839 final Node node; 1888 final Node node;
1840 final Modifiers modifiers; 1889 final Modifiers modifiers;
1841 1890
1842 FunctionElement constructor; 1891 Link<FunctionElement> constructors = new Link<FunctionElement>();
1892
1843 ClassElement mixin; 1893 ClassElement mixin;
1844 1894
1845 // TODO(kasperl): The analyzer complains when I don't have these two 1895 // TODO(kasperl): The analyzer complains when I don't have these two
1846 // fields. This is pretty weird. I cannot replace them with getters. 1896 // fields. This is pretty weird. I cannot replace them with getters.
1847 final ClassElement patch = null; 1897 final ClassElement patch = null;
1848 final ClassElement origin = null; 1898 final ClassElement origin = null;
1849 1899
1850 MixinApplicationElementX(SourceString name, Element enclosing, int id, 1900 MixinApplicationElementX(SourceString name, Element enclosing, int id,
1851 this.node, this.modifiers) 1901 this.node, this.modifiers)
1852 : super(name, enclosing, id, STATE_NOT_STARTED); 1902 : super(name, enclosing, id, STATE_NOT_STARTED);
1853 1903
1854 bool get isMixinApplication => true; 1904 bool get isMixinApplication => true;
1855 bool get hasConstructor => constructor != null; 1905 bool get hasConstructor => !constructors.isEmpty;
1856 bool get hasLocalScopeMembers => false; 1906 bool get hasLocalScopeMembers => constructors.isEmpty;
kasperl 2013/04/25 12:13:12 So it has local scope members when there are no co
karlklose 2013/05/03 09:35:45 Done.
1857 1907
1858 Token position() => node.getBeginToken(); 1908 Token position() => node.getBeginToken();
1859 1909
1860 Node parseNode(DiagnosticListener listener) => node; 1910 Node parseNode(DiagnosticListener listener) => node;
1861 1911
1862 Element localLookup(SourceString name) { 1912 Element localLookup(SourceString name) {
1863 if (this.name == name) return constructor; 1913 for (Link<Element> link = constructors;
kasperl 2013/04/25 12:13:12 Maybe add a lookup constructor for this and call i
karlklose 2013/05/03 09:35:45 Done.
1914 !link.isEmpty;
1915 link = link.tail) {
1916 if (link.head.name == name) return link.head;
1917 }
1864 if (mixin == null) return null; 1918 if (mixin == null) return null;
1865 Element mixedInElement = mixin.localLookup(name); 1919 Element mixedInElement = mixin.localLookup(name);
1866 if (mixedInElement == null) return null; 1920 if (mixedInElement == null) return null;
1867 return mixedInElement.isInstanceMember() ? mixedInElement : null; 1921 return mixedInElement.isInstanceMember() ? mixedInElement : null;
1868 } 1922 }
1869 1923
1870 void forEachLocalMember(void f(Element member)) { 1924 void forEachLocalMember(void f(Element member)) {
1871 if (mixin != null) mixin.forEachLocalMember((Element mixedInElement) { 1925 if (mixin != null) mixin.forEachLocalMember((Element mixedInElement) {
1872 if (mixedInElement.isInstanceMember()) f(mixedInElement); 1926 if (mixedInElement.isInstanceMember()) f(mixedInElement);
1873 }); 1927 });
1874 } 1928 }
1875 1929
1876 void addMember(Element element, DiagnosticListener listener) { 1930 void addMember(Element element, DiagnosticListener listener) {
1877 throw new UnsupportedError("cannot add member to $this"); 1931 throw new UnsupportedError("cannot add member to $this");
1878 } 1932 }
1879 1933
1880 void addToScope(Element element, DiagnosticListener listener) { 1934 void addToScope(Element element, DiagnosticListener listener) {
1881 throw new UnsupportedError("cannot add to scope of $this"); 1935 if (!element.isConstructor()) {
kasperl 2013/04/25 12:13:12 Why not keep this as is and always throw?
karlklose 2013/05/03 09:35:45 Done.
1936 listener.internalError('can only add constructors to mixin application '
1937 'scope, but got $element', element: this);
1938 }
1939 constructors = constructors.prepend(element);
1882 } 1940 }
1883 1941
1884 void setDefaultConstructor(FunctionElement constructor, Compiler compiler) { 1942 void setDefaultConstructor(FunctionElement constructor, Compiler compiler) {
1885 assert(!hasConstructor); 1943 assert(!hasConstructor);
1886 this.constructor = constructor; 1944 addToScope(constructor, compiler);
1887 } 1945 }
1888 1946
kasperl 2013/04/25 12:13:12 I'd add a new method for adding a constructor and
karlklose 2013/05/03 09:35:45 Done.
1889 Link<DartType> computeTypeParameters(Compiler compiler) { 1947 Link<DartType> computeTypeParameters(Compiler compiler) {
1890 NamedMixinApplication named = node.asNamedMixinApplication(); 1948 NamedMixinApplication named = node.asNamedMixinApplication();
1891 if (named == null) return const Link<DartType>(); 1949 if (named == null) return const Link<DartType>();
1892 return TypeDeclarationElementX.createTypeVariables( 1950 return TypeDeclarationElementX.createTypeVariables(
1893 this, named.typeParameters); 1951 this, named.typeParameters);
1894 } 1952 }
1895 } 1953 }
1896 1954
1897 class LabelElementX extends ElementX implements LabelElement { 1955 class LabelElementX extends ElementX implements LabelElement {
1898 1956
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 2076
2019 MetadataAnnotation ensureResolved(Compiler compiler) { 2077 MetadataAnnotation ensureResolved(Compiler compiler) {
2020 if (resolutionState == STATE_NOT_STARTED) { 2078 if (resolutionState == STATE_NOT_STARTED) {
2021 compiler.resolver.resolveMetadataAnnotation(this); 2079 compiler.resolver.resolveMetadataAnnotation(this);
2022 } 2080 }
2023 return this; 2081 return this;
2024 } 2082 }
2025 2083
2026 String toString() => 'MetadataAnnotation($value, $resolutionState)'; 2084 String toString() => 'MetadataAnnotation($value, $resolutionState)';
2027 } 2085 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698