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

Side by Side Diff: pkg/compiler/lib/src/universe/call_structure.dart

Issue 2630743002: Remove use of FunctionSignature et al from call_structure.dart (Closed)
Patch Set: Created 3 years, 11 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 dart2js.call_structure; 5 library dart2js.call_structure;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/names.dart' show Names; 8 import '../common/names.dart' show Names;
9 import '../elements/elements.dart'; 9 import '../elements/types.dart' show FunctionType;
10 import '../tree/tree.dart';
11 import '../util/util.dart'; 10 import '../util/util.dart';
12 import 'selector.dart' show Selector; 11 import 'selector.dart' show Selector;
13 12
14 /// The structure of the arguments at a call-site. 13 /// The structure of the arguments at a call-site.
15 // TODO(johnniwinther): Should these be cached? 14 // TODO(johnniwinther): Should these be cached?
16 // TODO(johnniwinther): Should isGetter/isSetter be part of the call structure 15 // TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
17 // instead of the selector? 16 // instead of the selector?
18 class CallStructure { 17 class CallStructure {
19 static const CallStructure NO_ARGS = const CallStructure.unnamed(0); 18 static const CallStructure NO_ARGS = const CallStructure.unnamed(0);
20 static const CallStructure ONE_ARG = const CallStructure.unnamed(1); 19 static const CallStructure ONE_ARG = const CallStructure.unnamed(1);
(...skipping 11 matching lines...) Expand all
32 31
33 const CallStructure.unnamed(this.argumentCount); 32 const CallStructure.unnamed(this.argumentCount);
34 33
35 factory CallStructure(int argumentCount, [List<String> namedArguments]) { 34 factory CallStructure(int argumentCount, [List<String> namedArguments]) {
36 if (namedArguments == null || namedArguments.isEmpty) { 35 if (namedArguments == null || namedArguments.isEmpty) {
37 return new CallStructure.unnamed(argumentCount); 36 return new CallStructure.unnamed(argumentCount);
38 } 37 }
39 return new NamedCallStructure(argumentCount, namedArguments); 38 return new NamedCallStructure(argumentCount, namedArguments);
40 } 39 }
41 40
42 /// Creates the [CallStructure] corresponding to calling [signature] as
43 /// declared, that is, all named arguments are in the order of declaration.
44 factory CallStructure.fromSignature(FunctionSignature signature) {
45 List<String> namedParameters;
46 if (signature.optionalParametersAreNamed) {
47 namedParameters =
48 signature.optionalParameters.map((e) => e.name).toList();
49 }
50 return new CallStructure(signature.parameterCount, namedParameters);
51 }
52
53 /// `true` if this call has named arguments. 41 /// `true` if this call has named arguments.
54 bool get isNamed => false; 42 bool get isNamed => false;
55 43
56 /// `true` if this call has no named arguments. 44 /// `true` if this call has no named arguments.
57 bool get isUnnamed => true; 45 bool get isUnnamed => true;
58 46
59 /// The names of the named arguments in call-site order. 47 /// The names of the named arguments in call-site order.
60 List<String> get namedArguments => const <String>[]; 48 List<String> get namedArguments => const <String>[];
61 49
62 /// The names of the named arguments in canonicalized order. 50 /// The names of the named arguments in canonicalized order.
(...skipping 17 matching lines...) Expand all
80 int get hashCode { 68 int get hashCode {
81 return Hashing.listHash(namedArguments, 69 return Hashing.listHash(namedArguments,
82 Hashing.objectHash(argumentCount, namedArguments.length)); 70 Hashing.objectHash(argumentCount, namedArguments.length));
83 } 71 }
84 72
85 bool operator ==(other) { 73 bool operator ==(other) {
86 if (other is! CallStructure) return false; 74 if (other is! CallStructure) return false;
87 return match(other); 75 return match(other);
88 } 76 }
89 77
90 bool signatureApplies(FunctionSignature parameters) { 78 bool signatureApplies(FunctionType type) {
91 if (argumentCount > parameters.parameterCount) return false; 79 int requiredParameterCount = type.parameterTypes.length;
92 int requiredParameterCount = parameters.requiredParameterCount; 80 int optionalParameterCount =
93 int optionalParameterCount = parameters.optionalParameterCount; 81 type.optionalParameterTypes.length + type.namedParameters.length;
82 int parameterCount = requiredParameterCount + optionalParameterCount;
83 if (argumentCount > parameterCount) return false;
94 if (positionalArgumentCount < requiredParameterCount) return false; 84 if (positionalArgumentCount < requiredParameterCount) return false;
95 85
96 if (!parameters.optionalParametersAreNamed) { 86 if (type.namedParameters.isEmpty) {
97 // We have already checked that the number of arguments are 87 // We have already checked that the number of arguments are
98 // not greater than the number of parameters. Therefore the 88 // not greater than the number of parameters. Therefore the
99 // number of positional arguments are not greater than the 89 // number of positional arguments are not greater than the
100 // number of parameters. 90 // number of parameters.
101 assert(positionalArgumentCount <= parameters.parameterCount); 91 assert(positionalArgumentCount <= parameterCount);
102 return namedArguments.isEmpty; 92 return namedArguments.isEmpty;
103 } else { 93 } else {
104 if (positionalArgumentCount > requiredParameterCount) return false; 94 if (positionalArgumentCount > requiredParameterCount) return false;
105 assert(positionalArgumentCount == requiredParameterCount); 95 assert(positionalArgumentCount == requiredParameterCount);
106 if (namedArgumentCount > optionalParameterCount) return false; 96 if (namedArgumentCount > optionalParameterCount) return false;
107 Set<String> nameSet = new Set<String>(); 97
108 parameters.optionalParameters.forEach((Element element) { 98 int nameIndex = 0;
109 nameSet.add(element.name); 99 List<String> namedParameters = type.namedParameters;
110 }); 100 OUTER:
111 for (String name in namedArguments) { 101 for (String name in getOrderedNamedArguments()) {
112 if (!nameSet.contains(name)) return false; 102 while (nameIndex < namedParameters.length) {
113 // TODO(5213): By removing from the set we are checking 103 if (name == namedParameters[nameIndex]) {
Siggi Cherem (dart-lang) 2017/01/13 17:11:07 Can we get here anymore with the duplicated names,
Johnni Winther 2017/01/18 11:02:51 We still create both function signatures/types and
114 // that we are not passing the name twice. We should have this 104 continue OUTER;
Siggi Cherem (dart-lang) 2017/01/13 17:11:07 I find the logic with `continue` a bit hard to fol
Johnni Winther 2017/01/18 11:02:51 Done.
115 // check in the resolver also. 105 }
116 nameSet.remove(name); 106 nameIndex++;
107 }
108 return false;
117 } 109 }
118 return true; 110 return true;
119 } 111 }
120 } 112 }
121 113
122 /**
123 * Returns a `List` with the evaluated arguments in the normalized order.
124 *
125 * [compileDefaultValue] is a function that returns a compiled constant
126 * of an optional argument that is not in [compiledArguments].
127 *
128 * Precondition: `this.applies(element, world)`.
129 *
130 * Invariant: [element] must be the implementation element.
131 */
132 /*<T>*/ List/*<T>*/ makeArgumentsList(
133 Link<Node> arguments,
134 FunctionElement element,
135 /*T*/ compileArgument(Node argument),
136 /*T*/ compileDefaultValue(ParameterElement element)) {
137 assert(invariant(element, element.isImplementation));
138 List/*<T>*/ result = new List();
139
140 FunctionSignature parameters = element.functionSignature;
141 parameters.forEachRequiredParameter((ParameterElement element) {
142 result.add(compileArgument(arguments.head));
143 arguments = arguments.tail;
144 });
145
146 if (!parameters.optionalParametersAreNamed) {
147 parameters.forEachOptionalParameter((ParameterElement element) {
148 if (!arguments.isEmpty) {
149 result.add(compileArgument(arguments.head));
150 arguments = arguments.tail;
151 } else {
152 result.add(compileDefaultValue(element));
153 }
154 });
155 } else {
156 // Visit named arguments and add them into a temporary list.
157 List compiledNamedArguments = [];
158 for (; !arguments.isEmpty; arguments = arguments.tail) {
159 NamedArgument namedArgument = arguments.head;
160 compiledNamedArguments.add(compileArgument(namedArgument.expression));
161 }
162 // Iterate over the optional parameters of the signature, and try to
163 // find them in [compiledNamedArguments]. If found, we use the
164 // value in the temporary list, otherwise the default value.
165 parameters.orderedOptionalParameters.forEach((ParameterElement element) {
166 int foundIndex = namedArguments.indexOf(element.name);
167 if (foundIndex != -1) {
168 result.add(compiledNamedArguments[foundIndex]);
169 } else {
170 result.add(compileDefaultValue(element));
171 }
172 });
173 }
174 return result;
175 }
176
177 /**
178 * Fills [list] with the arguments in the order expected by
179 * [callee], and where [caller] is a synthesized element
180 *
181 * [compileArgument] is a function that returns a compiled version
182 * of a parameter of [callee].
183 *
184 * [compileConstant] is a function that returns a compiled constant
185 * of an optional argument that is not in the parameters of [callee].
186 *
187 * Returns [:true:] if the signature of the [caller] matches the
188 * signature of the [callee], [:false:] otherwise.
189 */
190 static/*<T>*/ bool addForwardingElementArgumentsToList(
191 ConstructorElement caller,
192 List/*<T>*/ list,
193 ConstructorElement callee,
194 /*T*/ compileArgument(ParameterElement element),
195 /*T*/ compileConstant(ParameterElement element)) {
196 assert(invariant(caller, !callee.isMalformed,
197 message: "Cannot compute arguments to malformed constructor: "
198 "$caller calling $callee."));
199
200 FunctionSignature signature = caller.functionSignature;
201 Map<Node, ParameterElement> mapping = <Node, ParameterElement>{};
202
203 // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
204 // that we can call [addArgumentsToList].
205 Link<Node> computeCallNodesFromParameters() {
206 LinkBuilder<Node> builder = new LinkBuilder<Node>();
207 signature.forEachRequiredParameter((ParameterElement element) {
208 Node node = element.node;
209 mapping[node] = element;
210 builder.addLast(node);
211 });
212 if (signature.optionalParametersAreNamed) {
213 signature.forEachOptionalParameter((ParameterElement element) {
214 mapping[element.initializer] = element;
215 builder.addLast(new NamedArgument(null, null, element.initializer));
216 });
217 } else {
218 signature.forEachOptionalParameter((ParameterElement element) {
219 Node node = element.node;
220 mapping[node] = element;
221 builder.addLast(node);
222 });
223 }
224 return builder.toLink();
225 }
226
227 /*T*/ internalCompileArgument(Node node) {
228 return compileArgument(mapping[node]);
229 }
230
231 Link<Node> nodes = computeCallNodesFromParameters();
232
233 // Synthesize a structure for the call.
234 // TODO(ngeoffray): Should the resolver do it instead?
235 CallStructure callStructure = new CallStructure.fromSignature(signature);
236 if (!callStructure.signatureApplies(signature)) {
237 return false;
238 }
239 list.addAll(callStructure.makeArgumentsList(
240 nodes, callee, internalCompileArgument, compileConstant));
241
242 return true;
243 }
244
245 static bool sameNames(List<String> first, List<String> second) { 114 static bool sameNames(List<String> first, List<String> second) {
246 for (int i = 0; i < first.length; i++) { 115 for (int i = 0; i < first.length; i++) {
247 if (first[i] != second[i]) return false; 116 if (first[i] != second[i]) return false;
248 } 117 }
249 return true; 118 return true;
250 } 119 }
251 } 120 }
252 121
253 /// 122 ///
254 class NamedCallStructure extends CallStructure { 123 class NamedCallStructure extends CallStructure {
(...skipping 26 matching lines...) Expand all
281 return first.compareTo(second); 150 return first.compareTo(second);
282 }); 151 });
283 return _orderedNamedArguments; 152 return _orderedNamedArguments;
284 } 153 }
285 154
286 @override 155 @override
287 String structureToString() { 156 String structureToString() {
288 return 'arity=$argumentCount, named=[${namedArguments.join(', ')}]'; 157 return 'arity=$argumentCount, named=[${namedArguments.join(', ')}]';
289 } 158 }
290 } 159 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698