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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/resolution/signatures.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
(Empty)
1 // Copyright (c) 2014, 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 part of resolution;
6
7 /**
8 * [SignatureResolver] resolves function signatures.
9 */
10 class SignatureResolver extends MappingVisitor<FormalElementX> {
11 final ResolverVisitor resolver;
12 final FunctionTypedElement enclosingElement;
13 final Scope scope;
14 final MessageKind defaultValuesError;
15 final bool createRealParameters;
16 Link<Element> optionalParameters = const Link<Element>();
17 int optionalParameterCount = 0;
18 bool isOptionalParameter = false;
19 bool optionalParametersAreNamed = false;
20 VariableDefinitions currentDefinitions;
21
22 SignatureResolver(Compiler compiler,
23 FunctionTypedElement enclosingElement,
24 ResolutionRegistry registry,
25 {this.defaultValuesError,
26 this.createRealParameters})
27 : this.enclosingElement = enclosingElement,
28 this.scope = enclosingElement.buildScope(),
29 this.resolver =
30 new ResolverVisitor(compiler, enclosingElement, registry),
31 super(compiler, registry);
32
33 bool get defaultValuesAllowed => defaultValuesError == null;
34
35 visitNodeList(NodeList node) {
36 // This must be a list of optional arguments.
37 String value = node.beginToken.stringValue;
38 if ((!identical(value, '[')) && (!identical(value, '{'))) {
39 internalError(node, "expected optional parameters");
40 }
41 optionalParametersAreNamed = (identical(value, '{'));
42 isOptionalParameter = true;
43 LinkBuilder<Element> elements = analyzeNodes(node.nodes);
44 optionalParameterCount = elements.length;
45 optionalParameters = elements.toLink();
46 }
47
48 FormalElementX visitVariableDefinitions(VariableDefinitions node) {
49 Link<Node> definitions = node.definitions.nodes;
50 if (definitions.isEmpty) {
51 internalError(node, 'no parameter definition');
52 return null;
53 }
54 if (!definitions.tail.isEmpty) {
55 internalError(definitions.tail.head, 'extra definition');
56 return null;
57 }
58 Node definition = definitions.head;
59 if (definition is NodeList) {
60 internalError(node, 'optional parameters are not implemented');
61 }
62 if (node.modifiers.isConst) {
63 compiler.reportError(node, MessageKind.FORMAL_DECLARED_CONST);
64 }
65 if (node.modifiers.isStatic) {
66 compiler.reportError(node, MessageKind.FORMAL_DECLARED_STATIC);
67 }
68
69 if (currentDefinitions != null) {
70 internalError(node, 'function type parameters not supported');
71 }
72 currentDefinitions = node;
73 FormalElementX element = definition.accept(this);
74 if (currentDefinitions.metadata != null) {
75 element.metadata = compiler.resolver.resolveMetadata(element, node);
76 }
77 currentDefinitions = null;
78 return element;
79 }
80
81 void validateName(Identifier node) {
82 String name = node.source;
83 if (isOptionalParameter &&
84 optionalParametersAreNamed &&
85 isPrivateName(node.source)) {
86 compiler.reportError(node, MessageKind.PRIVATE_NAMED_PARAMETER);
87 }
88 }
89
90 void computeParameterType(FormalElementX element,
91 [VariableElement fieldElement]) {
92 void computeFunctionType(FunctionExpression functionExpression) {
93 FunctionSignature functionSignature = SignatureResolver.analyze(
94 compiler, functionExpression.parameters,
95 functionExpression.returnType, element, registry,
96 defaultValuesError: MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT);
97 element.functionSignatureCache = functionSignature;
98 element.typeCache = functionSignature.type;
99 }
100
101 if (currentDefinitions.type != null) {
102 element.typeCache = resolveTypeAnnotation(currentDefinitions.type);
103 } else {
104 // Is node.definitions exactly one FunctionExpression?
105 Link<Node> link = currentDefinitions.definitions.nodes;
106 assert(invariant(currentDefinitions, !link.isEmpty));
107 assert(invariant(currentDefinitions, link.tail.isEmpty));
108 if (link.head.asFunctionExpression() != null) {
109 // Inline function typed parameter, like `void m(int f(String s))`.
110 computeFunctionType(link.head);
111 } else if (link.head.asSend() != null &&
112 link.head.asSend().selector.asFunctionExpression() != null) {
113 // Inline function typed initializing formal or
114 // parameter with default value, like `C(int this.f(String s))` or
115 // `void m([int f(String s) = null])`.
116 computeFunctionType(link.head.asSend().selector.asFunctionExpression());
117 } else {
118 assert(invariant(currentDefinitions,
119 link.head.asIdentifier() != null || link.head.asSend() != null));
120 if (fieldElement != null) {
121 element.typeCache = fieldElement.computeType(compiler);
122 } else {
123 element.typeCache = const DynamicType();
124 }
125 }
126 }
127 }
128
129 Element visitIdentifier(Identifier node) {
130 return createParameter(node, null);
131 }
132
133 Identifier getParameterName(Send node) {
134 var identifier = node.selector.asIdentifier();
135 if (identifier != null) {
136 // Normal parameter: [:Type name:].
137 return identifier;
138 } else {
139 // Function type parameter: [:void name(DartType arg):].
140 var functionExpression = node.selector.asFunctionExpression();
141 if (functionExpression != null &&
142 functionExpression.name.asIdentifier() != null) {
143 return functionExpression.name.asIdentifier();
144 } else {
145 internalError(node,
146 'internal error: unimplemented receiver on parameter send');
147 return null;
148 }
149 }
150 }
151
152 // The only valid [Send] can be in constructors and must be of the form
153 // [:this.x:] (where [:x:] represents an instance field).
154 InitializingFormalElementX visitSend(Send node) {
155 return createFieldParameter(node, null);
156 }
157
158 FormalElementX createParameter(Identifier name, Expression initializer) {
159 validateName(name);
160 FormalElementX parameter;
161 if (createRealParameters) {
162 parameter = new LocalParameterElementX(
163 enclosingElement, currentDefinitions, name, initializer);
164 } else {
165 parameter = new FormalElementX(
166 ElementKind.PARAMETER, enclosingElement, currentDefinitions, name);
167 }
168 computeParameterType(parameter);
169 return parameter;
170 }
171
172 InitializingFormalElementX createFieldParameter(Send node,
173 Expression initializer) {
174 InitializingFormalElementX element;
175 if (node.receiver.asIdentifier() == null ||
176 !node.receiver.asIdentifier().isThis()) {
177 error(node, MessageKind.INVALID_PARAMETER);
178 } else if (!identical(enclosingElement.kind,
179 ElementKind.GENERATIVE_CONSTRUCTOR)) {
180 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED);
181 } else {
182 Identifier name = getParameterName(node);
183 validateName(name);
184 Element fieldElement =
185 enclosingElement.enclosingClass.lookupLocalMember(name.source);
186 if (fieldElement == null ||
187 !identical(fieldElement.kind, ElementKind.FIELD)) {
188 error(node, MessageKind.NOT_A_FIELD, {'fieldName': name});
189 } else if (!fieldElement.isInstanceMember) {
190 error(node, MessageKind.NOT_INSTANCE_FIELD, {'fieldName': name});
191 }
192 element = new InitializingFormalElementX(enclosingElement,
193 currentDefinitions, name, initializer, fieldElement);
194 computeParameterType(element, fieldElement);
195 }
196 return element;
197 }
198
199 /// A [SendSet] node is an optional parameter with a default value.
200 Element visitSendSet(SendSet node) {
201 FormalElementX element;
202 if (node.receiver != null) {
203 element = createFieldParameter(node, node.arguments.first);
204 } else if (node.selector.asIdentifier() != null ||
205 node.selector.asFunctionExpression() != null) {
206 element = createParameter(getParameterName(node), node.arguments.first);
207 }
208 Node defaultValue = node.arguments.head;
209 if (!defaultValuesAllowed) {
210 compiler.reportError(defaultValue, defaultValuesError);
211 }
212 return element;
213 }
214
215 Element visitFunctionExpression(FunctionExpression node) {
216 // This is a function typed parameter.
217 Modifiers modifiers = currentDefinitions.modifiers;
218 if (modifiers.isFinal) {
219 compiler.reportError(modifiers,
220 MessageKind.FINAL_FUNCTION_TYPE_PARAMETER);
221 }
222 if (modifiers.isVar) {
223 compiler.reportError(modifiers, MessageKind.VAR_FUNCTION_TYPE_PARAMETER);
224 }
225
226 return createParameter(node.name, null);
227 }
228
229 LinkBuilder<Element> analyzeNodes(Link<Node> link) {
230 LinkBuilder<Element> elements = new LinkBuilder<Element>();
231 for (; !link.isEmpty; link = link.tail) {
232 Element element = link.head.accept(this);
233 if (element != null) {
234 elements.addLast(element);
235 } else {
236 // If parameter is null, the current node should be the last,
237 // and a list of optional named parameters.
238 if (!link.tail.isEmpty || (link.head is !NodeList)) {
239 internalError(link.head, "expected optional parameters");
240 }
241 }
242 }
243 return elements;
244 }
245
246 /**
247 * Resolves formal parameters and return type of a [FunctionExpression]
248 * to a [FunctionSignature].
249 *
250 * If [createRealParameters] is `true`, the parameters will be
251 * real parameters implementing the [ParameterElement] interface. Otherwise,
252 * the parameters will only implement [FormalElement].
253 */
254 static FunctionSignature analyze(Compiler compiler,
255 NodeList formalParameters,
256 Node returnNode,
257 FunctionTypedElement element,
258 ResolutionRegistry registry,
259 {MessageKind defaultValuesError,
260 bool createRealParameters: false}) {
261 SignatureResolver visitor = new SignatureResolver(compiler, element,
262 registry, defaultValuesError: defaultValuesError,
263 createRealParameters: createRealParameters);
264 Link<Element> parameters = const Link<Element>();
265 int requiredParameterCount = 0;
266 if (formalParameters == null) {
267 if (!element.isGetter) {
268 if (element.isErroneous) {
269 // If the element is erroneous, an error should already have been
270 // reported. In the case of parse errors, it is possible that there
271 // are formal parameters, but something else in the method failed to
272 // parse. So we suppress the message about missing formals.
273 assert(invariant(element, compiler.compilationFailed));
274 } else {
275 compiler.reportError(element, MessageKind.MISSING_FORMALS);
276 }
277 }
278 } else {
279 if (element.isGetter) {
280 if (!identical(formalParameters.endToken.next.stringValue,
281 // TODO(ahe): Remove the check for native keyword.
282 'native')) {
283 compiler.reportError(formalParameters,
284 MessageKind.EXTRA_FORMALS);
285 }
286 }
287 LinkBuilder<Element> parametersBuilder =
288 visitor.analyzeNodes(formalParameters.nodes);
289 requiredParameterCount = parametersBuilder.length;
290 parameters = parametersBuilder.toLink();
291 }
292 DartType returnType;
293 if (element.isFactoryConstructor) {
294 returnType = element.enclosingClass.thisType;
295 // Because there is no type annotation for the return type of
296 // this element, we explicitly add one.
297 if (compiler.enableTypeAssertions) {
298 registry.registerIsCheck(returnType);
299 }
300 } else {
301 returnType = visitor.resolveReturnType(returnNode);
302 }
303
304 if (element.isSetter && (requiredParameterCount != 1 ||
305 visitor.optionalParameterCount != 0)) {
306 // If there are no formal parameters, we already reported an error above.
307 if (formalParameters != null) {
308 compiler.reportError(formalParameters,
309 MessageKind.ILLEGAL_SETTER_FORMALS);
310 }
311 }
312 LinkBuilder<DartType> parameterTypes = new LinkBuilder<DartType>();
313 for (FormalElement parameter in parameters) {
314 parameterTypes.addLast(parameter.type);
315 }
316 List<DartType> optionalParameterTypes = const <DartType>[];
317 List<String> namedParameters = const <String>[];
318 List<DartType> namedParameterTypes = const <DartType>[];
319 List<Element> orderedOptionalParameters =
320 visitor.optionalParameters.toList();
321 if (visitor.optionalParametersAreNamed) {
322 // TODO(karlklose); replace when [visitor.optinalParameters] is a [List].
323 orderedOptionalParameters.sort((Element a, Element b) {
324 return a.name.compareTo(b.name);
325 });
326 LinkBuilder<String> namedParametersBuilder = new LinkBuilder<String>();
327 LinkBuilder<DartType> namedParameterTypesBuilder =
328 new LinkBuilder<DartType>();
329 for (FormalElement parameter in orderedOptionalParameters) {
330 namedParametersBuilder.addLast(parameter.name);
331 namedParameterTypesBuilder.addLast(parameter.type);
332 }
333 namedParameters = namedParametersBuilder.toLink().toList(growable: false);
334 namedParameterTypes = namedParameterTypesBuilder.toLink()
335 .toList(growable: false);
336 } else {
337 // TODO(karlklose); replace when [visitor.optinalParameters] is a [List].
338 LinkBuilder<DartType> optionalParameterTypesBuilder =
339 new LinkBuilder<DartType>();
340 for (FormalElement parameter in visitor.optionalParameters) {
341 optionalParameterTypesBuilder.addLast(parameter.type);
342 }
343 optionalParameterTypes = optionalParameterTypesBuilder.toLink()
344 .toList(growable: false);
345 }
346 FunctionType type = new FunctionType(
347 element.declaration,
348 returnType,
349 parameterTypes.toLink().toList(growable: false),
350 optionalParameterTypes,
351 namedParameters,
352 namedParameterTypes);
353 return new FunctionSignatureX(parameters,
354 visitor.optionalParameters,
355 requiredParameterCount,
356 visitor.optionalParameterCount,
357 visitor.optionalParametersAreNamed,
358 orderedOptionalParameters,
359 type);
360 }
361
362 DartType resolveTypeAnnotation(TypeAnnotation annotation) {
363 DartType type = resolveReturnType(annotation);
364 if (type.isVoid) {
365 compiler.reportError(annotation, MessageKind.VOID_NOT_ALLOWED);
366 }
367 return type;
368 }
369
370 DartType resolveReturnType(TypeAnnotation annotation) {
371 if (annotation == null) return const DynamicType();
372 DartType result = resolver.resolveTypeAnnotation(annotation);
373 if (result == null) {
374 return const DynamicType();
375 }
376 return result;
377 }
378 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698