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

Side by Side Diff: pkg/compiler/lib/src/constants/evaluation.dart

Issue 1559233002: WIP: Compute constant expressions in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 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.constants.evaluation; 5 library dart2js.constants.evaluation;
6 6
7 import '../compiler.dart' show 7 import '../compiler.dart' show
8 Compiler; 8 Compiler;
9 import '../core_types.dart';
10 import '../dart_types.dart';
11 import '../diagnostics/messages.dart' show
12 MessageKind;
13 import '../elements/elements.dart' show
14 ConstructorElement,
15 VariableElement;
16 import '../resolution/operators.dart';
9 import '../universe/call_structure.dart' show 17 import '../universe/call_structure.dart' show
10 CallStructure; 18 CallStructure;
11 import 'expressions.dart'; 19 import 'expressions.dart';
20 import 'values.dart';
12 21
13 /// Environment used for evaluating constant expressions. 22 /// Environment used for evaluating constant expressions.
14 abstract class Environment { 23 abstract class Environment {
15 // TODO(johnniwinther): Replace this with [CoreTypes] and maybe [Backend]. 24 // TODO(johnniwinther): Replace this with [CoreTypes] and maybe [Backend].
16 Compiler get compiler; 25 Compiler get compiler;
17 26
27 /// The core types in the evaluation environment.
28 CoreTypes get coreTypes;
29
18 /// Read environments string passed in using the '-Dname=value' option. 30 /// Read environments string passed in using the '-Dname=value' option.
19 String readFromEnvironment(String name); 31 String readFromEnvironment(String name);
32
33 void reportWarning(ConstantExpression expression,
34 MessageKind kind,
35 Map arguments);
36
37 void reportError(ConstantExpression expression,
38 MessageKind kind,
39 Map arguments);
40
41 ConstantValue evaluateConstructor(
42 ConstructorElement constructor,
43 ConstantValue evaluate());
44
45 ConstantValue evaluateVariable(
46 VariableElement variable,
47 ConstantValue evaluate());
20 } 48 }
21 49
22 /// The normalized arguments passed to a const constructor computed from the 50 /// The normalized arguments passed to a const constructor computed from the
23 /// actual [arguments] and the [defaultValues] of the called construrctor. 51 /// actual [arguments] and the [defaultValues] of the called construrctor.
24 class NormalizedArguments { 52 class NormalizedArguments {
25 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues; 53 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues;
26 final CallStructure callStructure; 54 final CallStructure callStructure;
27 final List<ConstantExpression> arguments; 55 final List<ConstantExpression> arguments;
28 56
29 NormalizedArguments(this.defaultValues, this.callStructure, this.arguments); 57 NormalizedArguments(this.defaultValues, this.callStructure, this.arguments);
(...skipping 10 matching lines...) Expand all
40 68
41 /// Returns the normalized [index]th positional argument. 69 /// Returns the normalized [index]th positional argument.
42 ConstantExpression getPositionalArgument(int index) { 70 ConstantExpression getPositionalArgument(int index) {
43 if (index >= callStructure.positionalArgumentCount) { 71 if (index >= callStructure.positionalArgumentCount) {
44 // The positional argument is not provided. 72 // The positional argument is not provided.
45 return defaultValues[index]; 73 return defaultValues[index];
46 } 74 }
47 return arguments[index]; 75 return arguments[index];
48 } 76 }
49 } 77 }
78
79 abstract class ConstantTypeChecker<T> {
80 CoreTypes get coreTypes;
81 bool get isRequired;
82 bool get allowUnknown;
83
84 void reportError(T position, MessageKind messageKind, Map arguments);
85
86 bool isBool(DartType type, {bool allowUnknown}) {
87 if (allowUnknown == null) allowUnknown = this.allowUnknown;
88 return
89 type == coreTypes.boolType ||
90 (type == null && allowUnknown);
91 }
92
93 bool isBoolOrNull(DartType type, {bool allowUnknown}) {
94 if (allowUnknown == null) allowUnknown = this.allowUnknown;
95 return
96 type == coreTypes.boolType ||
97 type == coreTypes.nullType ||
98 (type == null && allowUnknown);
99 }
100
101 bool isInt(DartType type, {bool allowUnknown}) {
102 if (allowUnknown == null) allowUnknown = this.allowUnknown;
103 return
104 type == coreTypes.intType ||
105 (type == null && allowUnknown);
106 }
107
108 bool isIntOrNull(DartType type, {bool allowUnknown}) {
109 if (allowUnknown == null) allowUnknown = this.allowUnknown;
110 return
111 type == coreTypes.intType ||
112 type == coreTypes.nullType ||
113 (type == null && allowUnknown);
114 }
115
116 bool isNum(DartType type, {bool allowUnknown}) {
117 if (allowUnknown == null) allowUnknown = this.allowUnknown;
118 return
119 type == coreTypes.intType ||
120 type == coreTypes.doubleType ||
121 (type == null && allowUnknown);
122 }
123
124 bool isString(DartType type, {bool allowUnknown}) {
125 if (allowUnknown == null) allowUnknown = this.allowUnknown;
126 return
127 type == coreTypes.stringType ||
128 (type == null && allowUnknown);
129 }
130
131 bool isStringOrNull(DartType type, {bool allowUnknown}) {
132 if (allowUnknown == null) allowUnknown = this.allowUnknown;
133 return
134 type == coreTypes.stringType ||
135 type == coreTypes.nullType ||
136 (type == null && allowUnknown);
137 }
138
139 bool isPrimitive(DartType type, {bool allowUnknown}) {
140 if (allowUnknown == null) allowUnknown = this.allowUnknown;
141 return
142 type == coreTypes.intType ||
143 type == coreTypes.doubleType ||
144 type == coreTypes.stringType ||
145 type == coreTypes.boolType ||
146 type == coreTypes.nullType ||
147 (type == null && allowUnknown);
148 }
149
150 bool isNonNullPrimitive(DartType type, {bool allowUnknown}) {
151 if (allowUnknown == null) allowUnknown = this.allowUnknown;
152 return
153 type == coreTypes.boolType ||
154 type == coreTypes.intType ||
155 type == coreTypes.doubleType ||
156 type == coreTypes.stringType ||
157 (type == null && allowUnknown);
158 }
159
160 bool checkBinaryExpression(
161 T position,
162 ConstantTypeInfo<T> left,
163 BinaryOperator operator,
164 ConstantTypeInfo<T> right) {
165 bool isValid = true;
166 switch (operator.kind) {
167 case BinaryOperatorKind.EQ:
168 case BinaryOperatorKind.NOT_EQ:
169 if (!isPrimitive(left.type)) {
170 if (isRequired) {
171 reportError(
172 left.position,
173 MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE,
174 {'constant': left.constant,
175 'type': left.type,
176 'operator': operator});
177 }
178 isValid = false;
179 }
180 if (!isPrimitive(right.type)) {
181 if (isRequired) {
182 reportError(
183 right.position,
184 MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE,
185 {'constant': right.constant,
186 'type': right.type,
187 'operator': operator});
188 }
189 isValid = false;
190 }
191 break;
192 case BinaryOperatorKind.ADD:
193 if (isString(left.type, allowUnknown: false)) {
194 if (!isString(right.type)) {
195 if (isRequired) {
196 reportError(
197 right.position,
198 MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE,
199 {'constant': right.constant,
200 'type': right.type});
201 }
202 isValid = false;
203 }
204 } else if (isNum(left.type, allowUnknown: false)) {
205 if (!isNum(right.type)) {
206 if (isRequired) {
207 reportError(
208 right.position,
209 MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE,
210 {'constant': right.constant,
211 'type': right.type});
212 }
213 isValid = false;
214 }
215 } else if (isString(right.type, allowUnknown: false)) {
216 if (!isString(left.type)) {
217 if (isRequired) {
218 reportError(
219 left.position,
220 MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE,
221 {'constant': left.constant,
222 'type': left.type});
223 }
224 isValid = false;
225 }
226 } else if (isNum(right.type, allowUnknown: false)) {
227 if (!isNum(left.type)) {
228 if (isRequired) {
229 reportError(
230 left.position,
231 MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE,
232 {'constant': left.constant,
233 'type': left.type});
234 }
235 isValid = false;
236 }
237 } else if (allowUnknown && (left.type == null || right.type == null)) {
238 // Assume valid on unknown types.
239 } else {
240 if (isRequired) {
241 assert(left.type != null);
242 assert(right.type != null);
243 reportError(
244 position,
245 MessageKind.INVALID_CONSTANT_ADD_TYPES,
246 {'leftConstant': left.constant,
247 'leftType': left.type,
248 'rightConstant': right.constant,
249 'rightType': right.type});
250 }
251 isValid = false;
252 }
253 break;
254 case BinaryOperatorKind.SUB:
255 case BinaryOperatorKind.MUL:
256 case BinaryOperatorKind.DIV:
257 case BinaryOperatorKind.IDIV:
258 case BinaryOperatorKind.MOD:
259 case BinaryOperatorKind.GTEQ:
260 case BinaryOperatorKind.GT:
261 case BinaryOperatorKind.LTEQ:
262 case BinaryOperatorKind.LT:
263 if (!isNum(left.type)) {
264 if (isRequired) {
265 reportError(
266 left.position,
267 MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE,
268 {'constant': left.constant,
269 'type': left.type,
270 'operator': operator});
271 }
272 isValid = false;
273 }
274 if (!isNum(right.type)) {
275 if (isRequired) {
276 reportError(
277 right.position,
278 MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE,
279 {'constant': right.constant,
280 'type': right.type,
281 'operator': operator});
282 }
283 isValid = false;
284 }
285 break;
286 case BinaryOperatorKind.SHL:
287 case BinaryOperatorKind.SHR:
288 case BinaryOperatorKind.AND:
289 case BinaryOperatorKind.OR:
290 case BinaryOperatorKind.XOR:
291 if (!isInt(left.type)) {
292 if (isRequired) {
293 reportError(
294 left.position,
295 MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE,
296 {'constant': left.constant,
297 'type': left.type,
298 'operator': operator});
299 }
300 isValid = false;
301 }
302 if (!isInt(right.type)) {
303 if (isRequired) {
304 reportError(
305 right.position,
306 MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE,
307 {'constant': right.constant,
308 'type': right.type,
309 'operator': operator});
310 }
311 isValid = false;
312 }
313 break;
314 case BinaryOperatorKind.LOGICAL_AND:
315 if (!isBool(left.type)) {
316 if (isRequired) {
317 reportError(
318 left.position,
319 MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE,
320 {'constant': left.constant,
321 'type': left.type,
322 'operator': operator});
323 }
324 isValid = false;
325 }
326 if (!isBool(right.type)) {
327 if (isRequired) {
328 reportError(
329 right.position,
330 MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE,
331 {'constant': right.constant,
332 'type': right.type,
333 'operator': operator});
334 }
335 isValid = false;
336 }
337 break;
338 case BinaryOperatorKind.LOGICAL_OR:
339 if (!isBool(left.type)) {
340 if (isRequired) {
341 reportError(
342 left.position,
343 MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE,
344 {'constant': left.constant,
345 'type': left.type,
346 'operator': operator});
347 }
348 isValid = false;
349 }
350 if (!isBool(right.type)) {
351 if (isRequired) {
352 reportError(
353 right.position,
354 MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE,
355 {'constant': right.constant,
356 'type': right.type,
357 'operator': operator});
358 }
359 isValid = false;
360 }
361 break;
362 case BinaryOperatorKind.INDEX:
363 if (isRequired) {
364 reportError(position, MessageKind.INVALID_CONSTANT_INDEX, {});
365 }
366 isValid = false;
367 break;
368 case BinaryOperatorKind.IF_NULL:
369 if (isRequired) {
370 reportError(position, MessageKind.INVALID_CONSTANT_IF_NULL, {});
371 }
372 isValid = false;
373 break;
374 }
375 return isValid;
376 }
377
378 bool checkFromEnvironment(ConstantTypeInfo<T> name) {
379 bool isValidAsConstant = true;
380 if (!isString(name.type)) {
381 if (isRequired) {
382 reportError(
383 name.position,
384 MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE,
385 {'constant': name.constant,
386 'type': name.type});
387 }
388 isValidAsConstant = false;
389 }
390 return isValidAsConstant;
391 }
392
393 bool checkBoolFromEnvironment(
394 ConstantTypeInfo<T> name,
395 ConstantTypeInfo<T> defaultValue) {
396 bool isValidAsConstant = checkFromEnvironment(name);
397 if (defaultValue != null) {
398 if (!isBoolOrNull(defaultValue.type)) {
399 if (isRequired) {
400 reportError(
401 defaultValue.position,
402 MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE,
403 {'constant': defaultValue.constant,
404 'type': defaultValue.type});
405 }
406 isValidAsConstant = false;
407 }
408 }
409 return isValidAsConstant;
410 }
411
412 bool checkIntFromEnvironment(
413 ConstantTypeInfo<T> name,
414 ConstantTypeInfo<T> defaultValue) {
415 bool isValidAsConstant = checkFromEnvironment(name);
416 if (defaultValue != null) {
417 if (!isIntOrNull(defaultValue.type)) {
418 if (isRequired) {
419 reportError(
420 defaultValue.position,
421 MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE,
422 {'constant': defaultValue.constant,
423 'type': defaultValue.type});
424 }
425 isValidAsConstant = false;
426 }
427 }
428 return isValidAsConstant;
429 }
430
431 bool checkStringFromEnvironment(
432 ConstantTypeInfo<T> name,
433 ConstantTypeInfo<T> defaultValue) {
434 bool isValidAsConstant = checkFromEnvironment(name);
435 if (defaultValue != null) {
436 if (!isStringOrNull(defaultValue.type)) {
437 if (isRequired) {
438 reportError(
439 defaultValue.position,
440 MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE,
441 {'constant': defaultValue.constant,
442 'type': defaultValue.type});
443 }
444 isValidAsConstant = false;
445 }
446 }
447 return isValidAsConstant;
448 }
449
450 bool checkConcatenate(ConstantTypeInfo<T> part) {
451 bool isValidAsConstant = true;
452 if (!isNonNullPrimitive(part.type)) {
453 if (isRequired) {
454 reportError(
455 part.position,
456 MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
457 {'constant': part.constant,
458 'type': part.type});
459 }
460 isValidAsConstant = false;
461 }
462 return isValidAsConstant;
463 }
464
465 bool checkConditional(ConstantTypeInfo<T> condition) {
466 bool isValidAsConstant = true;
467 if (!isBool(condition.type)) {
468 reportError(
469 condition.position,
470 MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE,
471 {'constant': condition.constant,
472 'type': condition.type});
473 isValidAsConstant = false;
474 }
475 return isValidAsConstant;
476 }
477
478
479 bool checkUnary(
480 UnaryOperator operator,
481 ConstantTypeInfo<T> expression) {
482 bool isValid = true;
483 switch (operator.kind) {
484 case UnaryOperatorKind.NOT:
485 if (!isBool(expression.type)) {
486 if (isRequired) {
487 reportError(
488 expression.position,
489 MessageKind.INVALID_CONSTANT_NOT_TYPE,
490 {'constant': expression.constant,
491 'type': expression.type,
492 'operator': operator});
493 }
494 isValid = false;
495 }
496 break;
497 case UnaryOperatorKind.NEGATE:
498 if (!isNum(expression.type)) {
499 if (isRequired) {
500 reportError(
501 expression.position,
502 MessageKind.INVALID_CONSTANT_NEGATE_TYPE,
503 {'constant': expression.constant,
504 'type': expression.type,
505 'operator': operator});
506 }
507 isValid = false;
508 }
509 break;
510 case UnaryOperatorKind.COMPLEMENT:
511 if (!isInt(expression.type)) {
512 if (isRequired) {
513 reportError(
514 expression.position,
515 MessageKind.INVALID_CONSTANT_COMPLEMENT_TYPE,
516 {'constant': expression.constant,
517 'type': expression.type,
518 'operator': operator});
519 }
520 isValid = false;
521 }
522 break;
523 }
524 return isValid;
525 }
526 }
527
528 abstract class ConstantTypeInfo<T> {
529 T get position;
530 ConstantExpression get constant;
531 DartType get type;
532 }
533
534 class ConstantExpressionChecker
535 extends ConstantTypeChecker<ConstantExpression> {
536 final Environment environment;
537
538 ConstantExpressionChecker(this.environment);
539
540 @override
541 bool get allowUnknown => false;
542
543 @override
544 CoreTypes get coreTypes => environment.coreTypes;
545
546 @override
547 bool get isRequired => true;
548
549 @override
550 void reportError(ConstantExpression position,
551 MessageKind messageKind,
552 Map arguments) {
553 environment.reportError(position, messageKind, arguments);
554 }
555
556 ConstantValueTypeInfo createInfo(ConstantExpression expression,
557 ConstantValue value) {
558 if (expression == null) return null;
559 return new ConstantValueTypeInfo(expression, value.getType(coreTypes));
560 }
561 }
562
563 class ConstantValueTypeInfo implements ConstantTypeInfo<ConstantExpression> {
564 final ConstantExpression constant;
565 final DartType type;
566
567 ConstantValueTypeInfo(this.constant, this.type);
568
569 ConstantExpression get position => constant;
570 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/constants/constructors.dart ('k') | pkg/compiler/lib/src/constants/expressions.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698