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

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

Issue 25478009: Handle compile-time constness for conditionals and type literal calls. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments Created 7 years, 2 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 | « no previous file | sdk/lib/_internal/compiler/implementation/js_backend/backend.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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 part of dart2js; 5 part of dart2js;
6 6
7 /** 7 /**
8 * The [ConstantHandler] keeps track of compile-time constants, 8 * The [ConstantHandler] keeps track of compile-time constants,
9 * initializations of global and static fields, and default values of 9 * initializations of global and static fields, and default values of
10 * optional parameters. 10 * optional parameters.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 /** 84 /**
85 * Returns the a compile-time constant if the variable could be compiled 85 * Returns the a compile-time constant if the variable could be compiled
86 * eagerly. If the variable needs to be initialized lazily returns `null`. 86 * eagerly. If the variable needs to be initialized lazily returns `null`.
87 * If the variable is `const` but cannot be compiled eagerly reports an 87 * If the variable is `const` but cannot be compiled eagerly reports an
88 * error. 88 * error.
89 */ 89 */
90 Constant compileVariableWithDefinitions(VariableElement element, 90 Constant compileVariableWithDefinitions(VariableElement element,
91 TreeElements definitions, 91 TreeElements definitions,
92 {bool isConst: false}) { 92 {bool isConst: false}) {
93 return measure(() { 93 return measure(() {
94 // Initializers for parameters must be const.
95 isConst = isConst || element.modifiers.isConst()
96 || !Elements.isStaticOrTopLevel(element);
97 if (!isConst && lazyStatics.contains(element)) return null; 94 if (!isConst && lazyStatics.contains(element)) return null;
98 95
99 Node node = element.parseNode(compiler); 96 Node node = element.parseNode(compiler);
100 if (pendingVariables.contains(element)) { 97 if (pendingVariables.contains(element)) {
101 if (isConst) { 98 if (isConst) {
102 compiler.reportFatalError( 99 compiler.reportFatalError(
103 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); 100 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
104 } else { 101 } else {
105 lazyStatics.add(element); 102 lazyStatics.add(element);
106 return null; 103 return null;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 pendingVariables.remove(element); 141 pendingVariables.remove(element);
145 return value; 142 return value;
146 }); 143 });
147 } 144 }
148 145
149 Constant compileNodeWithDefinitions(Node node, 146 Constant compileNodeWithDefinitions(Node node,
150 TreeElements definitions, 147 TreeElements definitions,
151 {bool isConst: false}) { 148 {bool isConst: false}) {
152 return measure(() { 149 return measure(() {
153 assert(node != null); 150 assert(node != null);
151 Constant constant = definitions.getConstant(node);
152 if (constant != null) {
153 return constant;
154 }
154 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( 155 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
155 this, definitions, compiler, isConst: isConst); 156 this, definitions, compiler, isConst: isConst);
156 return evaluator.evaluate(node); 157 constant = evaluator.evaluate(node);
158 if (constant != null) {
159 definitions.setConstant(node, constant);
160 }
161 return constant;
157 }); 162 });
158 } 163 }
159 164
160 /** 165 /**
161 * Returns an [Iterable] of static non final fields that need to be 166 * Returns an [Iterable] of static non final fields that need to be
162 * initialized. The fields list must be evaluated in order since they might 167 * initialized. The fields list must be evaluated in order since they might
163 * depend on each other. 168 * depend on each other.
164 */ 169 */
165 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { 170 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() {
166 return initialVariableValues.keys.where((element) { 171 return initialVariableValues.keys.where((element) {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 List<Constant> createArguments(_) { 395 List<Constant> createArguments(_) {
391 return [constantSystem.createString( 396 return [constantSystem.createString(
392 new DartString.literal(node.slowNameString), node)]; 397 new DartString.literal(node.slowNameString), node)];
393 } 398 }
394 return makeConstructedConstant( 399 return makeConstructedConstant(
395 node, type, compiler.symbolConstructor, createArguments); 400 node, type, compiler.symbolConstructor, createArguments);
396 } 401 }
397 402
398 Constant makeTypeConstant(Element element) { 403 Constant makeTypeConstant(Element element) {
399 DartType elementType = element.computeType(compiler).asRaw(); 404 DartType elementType = element.computeType(compiler).asRaw();
400 compiler.backend.registerTypeLiteral(
401 element, compiler.enqueuer.codegen, elements);
402 DartType constantType = 405 DartType constantType =
403 compiler.backend.typeImplementation.computeType(compiler); 406 compiler.backend.typeImplementation.computeType(compiler);
404 return new TypeConstant(elementType, constantType); 407 return new TypeConstant(elementType, constantType);
405 } 408 }
406 409
407 // TODO(floitsch): provide better error-messages. 410 // TODO(floitsch): provide better error-messages.
408 Constant visitSend(Send send) { 411 Constant visitSend(Send send) {
409 Element element = elements[send]; 412 Element element = elements[send];
410 if (send.isPropertyAccess) { 413 if (send.isPropertyAccess) {
411 if (Elements.isStaticOrTopLevelFunction(element)) { 414 if (Elements.isStaticOrTopLevelFunction(element)) {
412 return new FunctionConstant(element); 415 return new FunctionConstant(element);
413 } else if (Elements.isStaticOrTopLevelField(element)) { 416 } else if (Elements.isStaticOrTopLevelField(element)) {
414 Constant result; 417 Constant result;
415 if (element.modifiers.isConst()) { 418 if (element.modifiers.isConst()) {
416 result = handler.compileConstant(element); 419 result = handler.compileConstant(element);
417 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { 420 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) {
418 result = handler.compileVariable(element); 421 result = handler.compileVariable(element);
419 } 422 }
420 if (result != null) return result; 423 if (result != null) return result;
421 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { 424 } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
425 assert(elements.isTypeLiteral(send));
422 return makeTypeConstant(element); 426 return makeTypeConstant(element);
423 } else if (send.receiver != null) { 427 } else if (send.receiver != null) {
424 // Fall through to error handling. 428 // Fall through to error handling.
425 } else if (!Elements.isUnresolved(element) 429 } else if (!Elements.isUnresolved(element)
426 && element.isVariable() 430 && element.isVariable()
427 && element.modifiers.isConst()) { 431 && element.modifiers.isConst()) {
428 Constant result = handler.compileConstant(element); 432 Constant result = handler.compileConstant(element);
429 if (result != null) return result; 433 if (result != null) return result;
430 } 434 }
431 return signalNotCompileTimeConstant(send); 435 return signalNotCompileTimeConstant(send);
432 } else if (send.isCall) { 436 } else if (send.isCall) {
433 if (identical(element, compiler.identicalFunction) 437 if (identical(element, compiler.identicalFunction)
434 && send.argumentCount() == 2) { 438 && send.argumentCount() == 2) {
435 Constant left = evaluate(send.argumentsNode.nodes.head); 439 Constant left = evaluate(send.argumentsNode.nodes.head);
436 Constant right = evaluate(send.argumentsNode.nodes.tail.head); 440 Constant right = evaluate(send.argumentsNode.nodes.tail.head);
437 Constant result = constantSystem.identity.fold(left, right); 441 Constant result = constantSystem.identity.fold(left, right);
438 if (result != null) return result; 442 if (result != null) return result;
439 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { 443 } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
440 return makeTypeConstant(element); 444 // The node itself is not a constant but we register the selector (the
445 // identifier that refers to the class/typedef) as a constant.
446 Constant typeConstant = makeTypeConstant(element);
447 elements.setConstant(send.selector, typeConstant);
441 } 448 }
442 return signalNotCompileTimeConstant(send); 449 return signalNotCompileTimeConstant(send);
443 } else if (send.isPrefix) { 450 } else if (send.isPrefix) {
444 assert(send.isOperator); 451 assert(send.isOperator);
445 Constant receiverConstant = evaluate(send.receiver); 452 Constant receiverConstant = evaluate(send.receiver);
446 if (receiverConstant == null) return null; 453 if (receiverConstant == null) return null;
447 Operator op = send.selector; 454 Operator op = send.selector;
448 Constant folded; 455 Constant folded;
449 switch (op.source.stringValue) { 456 switch (op.source.stringValue) {
450 case "!": 457 case "!":
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 folded = areIdentical.negate(); 555 folded = areIdentical.negate();
549 } 556 }
550 break; 557 break;
551 } 558 }
552 if (folded == null) return signalNotCompileTimeConstant(send); 559 if (folded == null) return signalNotCompileTimeConstant(send);
553 return folded; 560 return folded;
554 } 561 }
555 return signalNotCompileTimeConstant(send); 562 return signalNotCompileTimeConstant(send);
556 } 563 }
557 564
565 Constant visitConditional(Conditional node) {
566 Constant condition = evaluate(node.condition);
567 if (condition == null) {
568 return null;
569 } else if (!condition.isBool()) {
570 DartType conditionType = condition.computeType(compiler);
571 if (isEvaluatingConstant) {
572 compiler.reportFatalError(
573 node.condition, MessageKind.NOT_ASSIGNABLE.error,
574 {'fromType': conditionType, 'toType': compiler.boolClass.rawType});
575 }
576 return null;
577 }
578 Constant thenExpression = evaluate(node.thenExpression);
579 Constant elseExpression = evaluate(node.elseExpression);
580 BoolConstant boolCondition = condition;
581 return boolCondition.value ? thenExpression : elseExpression;
582 }
583
558 Constant visitSendSet(SendSet node) { 584 Constant visitSendSet(SendSet node) {
559 return signalNotCompileTimeConstant(node); 585 return signalNotCompileTimeConstant(node);
560 } 586 }
561 587
562 /** 588 /**
563 * Returns the list of constants that are passed to the static function. 589 * Returns the list of constants that are passed to the static function.
564 * 590 *
565 * Invariant: [target] must be an implementation element. 591 * Invariant: [target] must be an implementation element.
566 */ 592 */
567 List<Constant> evaluateArgumentsToConstructor(Node node, 593 List<Constant> evaluateArgumentsToConstructor(Node node,
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 if (fieldValue == null) { 878 if (fieldValue == null) {
853 // Use the default value. 879 // Use the default value.
854 fieldValue = handler.compileConstant(field); 880 fieldValue = handler.compileConstant(field);
855 } 881 }
856 jsNewArguments.add(fieldValue); 882 jsNewArguments.add(fieldValue);
857 }, 883 },
858 includeSuperAndInjectedMembers: true); 884 includeSuperAndInjectedMembers: true);
859 return jsNewArguments; 885 return jsNewArguments;
860 } 886 }
861 } 887 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/js_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698