OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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.expressions; | 5 library dart2js.constants.expressions; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../constants/constant_system.dart'; | 8 import '../constants/constant_system.dart'; |
9 import '../core_types.dart'; | 9 import '../core_types.dart'; |
10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 int _hashCode; | 66 int _hashCode; |
67 | 67 |
68 ConstantExpressionKind get kind; | 68 ConstantExpressionKind get kind; |
69 | 69 |
70 // TODO(johnniwinther): Unify precedence handled between constants, front-end | 70 // TODO(johnniwinther): Unify precedence handled between constants, front-end |
71 // and back-end. | 71 // and back-end. |
72 int get precedence => 16; | 72 int get precedence => 16; |
73 | 73 |
74 accept(ConstantExpressionVisitor visitor, [context]); | 74 accept(ConstantExpressionVisitor visitor, [context]); |
75 | 75 |
| 76 /// `true` if this is an erroneous constant expression. |
| 77 bool get isErroneous => false; |
| 78 |
76 /// Substitute free variables using arguments. | 79 /// Substitute free variables using arguments. |
77 ConstantExpression apply(NormalizedArguments arguments) => this; | 80 ConstantExpression apply(NormalizedArguments arguments) => this; |
78 | 81 |
79 /// Compute the [ConstantValue] for this expression using the [environment] | 82 /// Compute the [ConstantValue] for this expression using the [environment] |
80 /// and the [constantSystem]. | 83 /// and the [constantSystem]. |
81 ConstantValue evaluate(Environment environment, | 84 ConstantValue evaluate(Environment environment, |
82 ConstantSystem constantSystem); | 85 ConstantSystem constantSystem); |
83 | 86 |
84 /// Returns the type of this constant expression, if it is independent of the | 87 /// Returns the type of this constant expression, if it is independent of the |
85 /// environment values. | 88 /// environment values. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 ConstantSystem constantSystem) { | 133 ConstantSystem constantSystem) { |
131 // TODO(johnniwinther): Use non-constant values for errors. | 134 // TODO(johnniwinther): Use non-constant values for errors. |
132 return new NonConstantValue(); | 135 return new NonConstantValue(); |
133 } | 136 } |
134 | 137 |
135 @override | 138 @override |
136 int _computeHashCode() => 13; | 139 int _computeHashCode() => 13; |
137 | 140 |
138 @override | 141 @override |
139 bool _equals(ErroneousConstantExpression other) => true; | 142 bool _equals(ErroneousConstantExpression other) => true; |
| 143 |
| 144 @override |
| 145 bool get isErroneous => true; |
140 } | 146 } |
141 | 147 |
142 // TODO(johnniwinther): Avoid the need for this class. | 148 // TODO(johnniwinther): Avoid the need for this class. |
143 class SyntheticConstantExpression extends ConstantExpression { | 149 class SyntheticConstantExpression extends ConstantExpression { |
144 final SyntheticConstantValue value; | 150 final SyntheticConstantValue value; |
145 | 151 |
146 SyntheticConstantExpression(this.value); | 152 SyntheticConstantExpression(this.value); |
147 | 153 |
148 @override | 154 @override |
149 ConstantValue evaluate(Environment environment, | 155 ConstantValue evaluate(Environment environment, |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 386 |
381 ConstantExpressionKind get kind => ConstantExpressionKind.MAP; | 387 ConstantExpressionKind get kind => ConstantExpressionKind.MAP; |
382 | 388 |
383 accept(ConstantExpressionVisitor visitor, [context]) { | 389 accept(ConstantExpressionVisitor visitor, [context]) { |
384 return visitor.visitMap(this, context); | 390 return visitor.visitMap(this, context); |
385 } | 391 } |
386 | 392 |
387 @override | 393 @override |
388 ConstantValue evaluate(Environment environment, | 394 ConstantValue evaluate(Environment environment, |
389 ConstantSystem constantSystem) { | 395 ConstantSystem constantSystem) { |
390 return constantSystem.createMap(environment.compiler, | 396 /*return constantSystem.createMap(environment.compiler, |
391 type, | 397 type, |
392 keys.map((k) => k.evaluate(environment, constantSystem)).toList(), | 398 keys.map((k) => k.evaluate(environment, constantSystem)).toList(), |
393 values.map((v) => v.evaluate(environment, constantSystem)).toList()); | 399 values.map((v) => v.evaluate(environment, constantSystem)).toList());*/ |
| 400 Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{}; |
| 401 |
| 402 for (int i = 0; i < keys.length; i++) { |
| 403 ConstantValue key = keys[i].evaluate(environment, constantSystem); |
| 404 if (!key.isConstant) { |
| 405 return new NonConstantValue(); |
| 406 } |
| 407 ConstantValue value = values[i].evaluate(environment, constantSystem); |
| 408 if (!value.isConstant) { |
| 409 return new NonConstantValue(); |
| 410 } |
| 411 if (map.containsKey(key)) { |
| 412 environment.reportWarning(keys[i], MessageKind.EQUAL_MAP_ENTRY_KEY, {}); |
| 413 } |
| 414 map[key] = value; |
| 415 } |
| 416 return constantSystem.createMap( |
| 417 environment.compiler, type, map.keys.toList(), map.values.toList()); |
394 } | 418 } |
395 | 419 |
396 ConstantExpression apply(NormalizedArguments arguments) { | 420 ConstantExpression apply(NormalizedArguments arguments) { |
397 return new MapConstantExpression( | 421 return new MapConstantExpression( |
398 type, | 422 type, |
399 keys.map((k) => k.apply(arguments)).toList(), | 423 keys.map((k) => k.apply(arguments)).toList(), |
400 values.map((v) => v.apply(arguments)).toList()); | 424 values.map((v) => v.apply(arguments)).toList()); |
401 } | 425 } |
402 | 426 |
403 @override | 427 @override |
(...skipping 27 matching lines...) Expand all Loading... |
431 final CallStructure callStructure; | 455 final CallStructure callStructure; |
432 final List<ConstantExpression> arguments; | 456 final List<ConstantExpression> arguments; |
433 | 457 |
434 ConstructedConstantExpression( | 458 ConstructedConstantExpression( |
435 this.type, | 459 this.type, |
436 this.target, | 460 this.target, |
437 this.callStructure, | 461 this.callStructure, |
438 this.arguments) { | 462 this.arguments) { |
439 assert(type.element == target.enclosingClass); | 463 assert(type.element == target.enclosingClass); |
440 assert(!arguments.contains(null)); | 464 assert(!arguments.contains(null)); |
| 465 assert(invariant(NO_LOCATION_SPANNABLE, target.isConst, |
| 466 message: "Referenced constructor $target is not constant.")); |
441 } | 467 } |
442 | 468 |
443 ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED; | 469 ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED; |
444 | 470 |
445 accept(ConstantExpressionVisitor visitor, [context]) { | 471 accept(ConstantExpressionVisitor visitor, [context]) { |
446 return visitor.visitConstructed(this, context); | 472 return visitor.visitConstructed(this, context); |
447 } | 473 } |
448 | 474 |
449 Map<FieldElement, ConstantExpression> computeInstanceFields() { | 475 Map<FieldElement, ConstantExpression> computeInstanceFields() { |
| 476 assert(invariant(target, target.constantConstructor != null, |
| 477 message: "Constant constructor has not been computed for $target.")); |
450 return target.constantConstructor.computeInstanceFields( | 478 return target.constantConstructor.computeInstanceFields( |
451 arguments, callStructure); | 479 arguments, callStructure); |
452 } | 480 } |
453 | 481 |
454 InterfaceType computeInstanceType() { | 482 InterfaceType computeInstanceType() { |
455 return target.constantConstructor.computeInstanceType(type); | 483 return target.constantConstructor.computeInstanceType(type); |
456 } | 484 } |
457 | 485 |
458 ConstructedConstantExpression apply(NormalizedArguments arguments) { | 486 ConstructedConstantExpression apply(NormalizedArguments arguments) { |
459 return new ConstructedConstantExpression( | 487 return new ConstructedConstantExpression( |
460 type, target, callStructure, | 488 type, target, callStructure, |
461 this.arguments.map((a) => a.apply(arguments)).toList()); | 489 this.arguments.map((a) => a.apply(arguments)).toList()); |
462 } | 490 } |
463 | 491 |
464 @override | 492 @override |
465 ConstantValue evaluate(Environment environment, | 493 ConstantValue evaluate(Environment environment, |
466 ConstantSystem constantSystem) { | 494 ConstantSystem constantSystem) { |
467 Map<FieldElement, ConstantValue> fieldValues = | 495 return environment.evaluateConstructor(target, () { |
468 <FieldElement, ConstantValue>{}; | 496 Map<FieldElement, ConstantExpression> fieldMap = |
469 computeInstanceFields().forEach( | 497 computeInstanceFields(); |
470 (FieldElement field, ConstantExpression constant) { | 498 if (fieldMap == null) { |
471 fieldValues[field] = constant.evaluate(environment, constantSystem); | 499 // An erroneous constant constructor was encountered in the super-chain. |
| 500 return new NonConstantValue(); |
| 501 } |
| 502 bool isValidAsConstant = true; |
| 503 Map<FieldElement, ConstantValue> fieldValues = |
| 504 <FieldElement, ConstantValue>{}; |
| 505 fieldMap.forEach((FieldElement field, ConstantExpression constant) { |
| 506 ConstantValue value = constant.evaluate(environment, constantSystem); |
| 507 assert(invariant(CURRENT_ELEMENT_SPANNABLE, value != null, |
| 508 message: "No value computed for ${constant.getText()}.")); |
| 509 if (value.isConstant) { |
| 510 fieldValues[field] = value; |
| 511 } else { |
| 512 isValidAsConstant = false; |
| 513 } |
| 514 }); |
| 515 if (isValidAsConstant) { |
| 516 return new ConstructedConstantValue(computeInstanceType(), fieldValues); |
| 517 } else { |
| 518 return new NonConstantValue(); |
| 519 } |
472 }); | 520 }); |
473 return new ConstructedConstantValue(computeInstanceType(), fieldValues); | |
474 } | 521 } |
475 | 522 |
476 @override | 523 @override |
477 int _computeHashCode() { | 524 int _computeHashCode() { |
478 int hashCode = | 525 int hashCode = |
479 13 * type.hashCode + | 526 13 * type.hashCode + |
480 17 * target.hashCode + | 527 17 * target.hashCode + |
481 19 * callStructure.hashCode; | 528 19 * callStructure.hashCode; |
482 for (ConstantExpression value in arguments) { | 529 for (ConstantExpression value in arguments) { |
483 hashCode ^= 23 * value.hashCode; | 530 hashCode ^= 23 * value.hashCode; |
(...skipping 26 matching lines...) Expand all Loading... |
510 } | 557 } |
511 | 558 |
512 ConstantExpression apply(NormalizedArguments arguments) { | 559 ConstantExpression apply(NormalizedArguments arguments) { |
513 return new ConcatenateConstantExpression( | 560 return new ConcatenateConstantExpression( |
514 expressions.map((a) => a.apply(arguments)).toList()); | 561 expressions.map((a) => a.apply(arguments)).toList()); |
515 } | 562 } |
516 | 563 |
517 @override | 564 @override |
518 ConstantValue evaluate(Environment environment, | 565 ConstantValue evaluate(Environment environment, |
519 ConstantSystem constantSystem) { | 566 ConstantSystem constantSystem) { |
| 567 bool isValidAsConstant = true; |
520 DartString accumulator; | 568 DartString accumulator; |
521 for (ConstantExpression expression in expressions) { | 569 for (ConstantExpression expression in expressions) { |
522 ConstantValue value = expression.evaluate(environment, constantSystem); | 570 ConstantValue value = expression.evaluate(environment, constantSystem); |
523 DartString valueString; | 571 DartString valueString; |
524 if (value.isNum || value.isBool) { | 572 if (!value.isConstant) { |
| 573 isValidAsConstant = false; |
| 574 continue; |
| 575 } else if (value.isNum || value.isBool) { |
525 PrimitiveConstantValue primitive = value; | 576 PrimitiveConstantValue primitive = value; |
526 valueString = | 577 valueString = |
527 new DartString.literal(primitive.primitiveValue.toString()); | 578 new DartString.literal(primitive.primitiveValue.toString()); |
528 } else if (value.isString) { | 579 } else if (value.isString) { |
529 PrimitiveConstantValue primitive = value; | 580 PrimitiveConstantValue primitive = value; |
530 valueString = primitive.primitiveValue; | 581 valueString = primitive.primitiveValue; |
531 } else { | 582 } else { |
532 // TODO(johnniwinther): Specialize message to indicated that the problem | 583 // TODO(johnniwinther): Specialize message to indicated that the problem |
533 // is not constness but the types of the const expressions. | 584 // is not constness but the types of the const expressions. |
534 return new NonConstantValue(); | 585 environment.reportError( |
| 586 expression, |
| 587 MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE, |
| 588 {'constant': expression, |
| 589 'type': value.getType(environment.coreTypes)}); |
| 590 isValidAsConstant = false; |
| 591 continue; |
535 } | 592 } |
536 if (accumulator == null) { | 593 if (accumulator == null) { |
537 accumulator = valueString; | 594 accumulator = valueString; |
538 } else { | 595 } else { |
539 accumulator = new DartString.concat(accumulator, valueString); | 596 accumulator = new DartString.concat(accumulator, valueString); |
540 } | 597 } |
541 } | 598 } |
542 return constantSystem.createString(accumulator); | 599 if (isValidAsConstant) { |
| 600 return constantSystem.createString(accumulator); |
| 601 } |
| 602 return new NonConstantValue(); |
543 } | 603 } |
544 | 604 |
545 @override | 605 @override |
546 int _computeHashCode() { | 606 int _computeHashCode() { |
547 int hashCode = 17 * expressions.length; | 607 int hashCode = 17 * expressions.length; |
548 for (ConstantExpression value in expressions) { | 608 for (ConstantExpression value in expressions) { |
549 hashCode ^= 19 * value.hashCode; | 609 hashCode ^= 19 * value.hashCode; |
550 } | 610 } |
551 return hashCode; | 611 return hashCode; |
552 } | 612 } |
(...skipping 27 matching lines...) Expand all Loading... |
580 int _computeHashCode() => 13 * name.hashCode; | 640 int _computeHashCode() => 13 * name.hashCode; |
581 | 641 |
582 @override | 642 @override |
583 bool _equals(SymbolConstantExpression other) { | 643 bool _equals(SymbolConstantExpression other) { |
584 return name == other.name; | 644 return name == other.name; |
585 } | 645 } |
586 | 646 |
587 @override | 647 @override |
588 ConstantValue evaluate(Environment environment, | 648 ConstantValue evaluate(Environment environment, |
589 ConstantSystem constantSystem) { | 649 ConstantSystem constantSystem) { |
590 // TODO(johnniwinther): Implement this. | 650 return constantSystem.createSymbol(environment.compiler, name); |
591 throw new UnsupportedError('SymbolConstantExpression.evaluate'); | |
592 } | 651 } |
593 | 652 |
594 @override | 653 @override |
595 DartType getKnownType(CoreTypes coreTypes) => coreTypes.symbolType; | 654 DartType getKnownType(CoreTypes coreTypes) => coreTypes.symbolType; |
596 } | 655 } |
597 | 656 |
598 /// Type literal. | 657 /// Type literal. |
599 class TypeConstantExpression extends ConstantExpression { | 658 class TypeConstantExpression extends ConstantExpression { |
600 /// Either [DynamicType] or a raw [GenericType]. | 659 /// Either [DynamicType] or a raw [GenericType]. |
601 final DartType type; | 660 final DartType type; |
(...skipping 23 matching lines...) Expand all Loading... |
625 } | 684 } |
626 | 685 |
627 @override | 686 @override |
628 DartType getKnownType(CoreTypes coreTypes) => coreTypes.typeType; | 687 DartType getKnownType(CoreTypes coreTypes) => coreTypes.typeType; |
629 } | 688 } |
630 | 689 |
631 /// Reference to a constant local, top-level, or static variable. | 690 /// Reference to a constant local, top-level, or static variable. |
632 class VariableConstantExpression extends ConstantExpression { | 691 class VariableConstantExpression extends ConstantExpression { |
633 final VariableElement element; | 692 final VariableElement element; |
634 | 693 |
635 VariableConstantExpression(this.element); | 694 VariableConstantExpression(this.element) { |
| 695 /*assert(invariant(NO_LOCATION_SPANNABLE, element.isConst, |
| 696 message: "Referenced variable $element is not constant."));*/ |
| 697 } |
636 | 698 |
637 ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE; | 699 ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE; |
638 | 700 |
639 accept(ConstantExpressionVisitor visitor, [context]) { | 701 accept(ConstantExpressionVisitor visitor, [context]) { |
640 return visitor.visitVariable(this, context); | 702 return visitor.visitVariable(this, context); |
641 } | 703 } |
642 | 704 |
643 @override | 705 @override |
644 ConstantValue evaluate(Environment environment, | 706 ConstantValue evaluate(Environment environment, |
645 ConstantSystem constantSystem) { | 707 ConstantSystem constantSystem) { |
646 return element.constant.evaluate(environment, constantSystem); | 708 return environment.evaluateVariable(element, () { |
| 709 return element.constant.evaluate(environment, constantSystem); |
| 710 }); |
647 } | 711 } |
648 | 712 |
649 @override | 713 @override |
650 int _computeHashCode() => 13 * element.hashCode; | 714 int _computeHashCode() => 13 * element.hashCode; |
651 | 715 |
652 @override | 716 @override |
653 bool _equals(VariableConstantExpression other) { | 717 bool _equals(VariableConstantExpression other) { |
654 return element == other.element; | 718 return element == other.element; |
655 } | 719 } |
656 } | 720 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 | 761 |
698 ConstantExpressionKind get kind => ConstantExpressionKind.BINARY; | 762 ConstantExpressionKind get kind => ConstantExpressionKind.BINARY; |
699 | 763 |
700 accept(ConstantExpressionVisitor visitor, [context]) { | 764 accept(ConstantExpressionVisitor visitor, [context]) { |
701 return visitor.visitBinary(this, context); | 765 return visitor.visitBinary(this, context); |
702 } | 766 } |
703 | 767 |
704 @override | 768 @override |
705 ConstantValue evaluate(Environment environment, | 769 ConstantValue evaluate(Environment environment, |
706 ConstantSystem constantSystem) { | 770 ConstantSystem constantSystem) { |
707 return constantSystem.lookupBinary(operator).fold( | 771 ConstantValue leftValue = left.evaluate(environment, constantSystem); |
708 left.evaluate(environment, constantSystem), | 772 ConstantValue rightValue = right.evaluate(environment, constantSystem); |
709 right.evaluate(environment, constantSystem)); | 773 if (!leftValue.isConstant || |
| 774 !rightValue.isConstant) { |
| 775 return new NonConstantValue(); |
| 776 } |
| 777 ConstantExpressionChecker checker = |
| 778 new ConstantExpressionChecker(environment); |
| 779 bool isValid = checker.checkBinaryExpression( |
| 780 this, |
| 781 checker.createInfo(left, leftValue), |
| 782 operator, |
| 783 checker.createInfo(right, rightValue)); |
| 784 |
| 785 BinaryOperation operation = constantSystem.lookupBinary(operator); |
| 786 assert(invariant(NO_LOCATION_SPANNABLE, operation != null, |
| 787 message: "No binary operation for $operator.")); |
| 788 ConstantValue value = operation.fold(leftValue, rightValue); |
| 789 if (value != null) { |
| 790 return value; |
| 791 } |
| 792 assert(!isValid); |
| 793 return new NonConstantValue(); |
710 } | 794 } |
711 | 795 |
712 ConstantExpression apply(NormalizedArguments arguments) { | 796 ConstantExpression apply(NormalizedArguments arguments) { |
713 return new BinaryConstantExpression( | 797 return new BinaryConstantExpression( |
714 left.apply(arguments), | 798 left.apply(arguments), |
715 operator, | 799 operator, |
716 right.apply(arguments)); | 800 right.apply(arguments)); |
717 } | 801 } |
718 | 802 |
719 DartType getKnownType(CoreTypes coreTypes) { | 803 DartType getKnownType(CoreTypes coreTypes) { |
720 DartType knownLeftType = left.getKnownType(coreTypes); | 804 DartType knownLeftType = left.getKnownType(coreTypes); |
721 DartType knownRightType = right.getKnownType(coreTypes); | 805 DartType knownRightType = right.getKnownType(coreTypes); |
722 switch (operator.kind) { | 806 switch (operator.kind) { |
723 case BinaryOperatorKind.EQ: | 807 case BinaryOperatorKind.EQ: |
724 case BinaryOperatorKind.NOT_EQ: | 808 case BinaryOperatorKind.NOT_EQ: |
725 case BinaryOperatorKind.LOGICAL_AND: | 809 case BinaryOperatorKind.LOGICAL_AND: |
726 case BinaryOperatorKind.LOGICAL_OR: | 810 case BinaryOperatorKind.LOGICAL_OR: |
727 case BinaryOperatorKind.GT: | 811 case BinaryOperatorKind.GT: |
728 case BinaryOperatorKind.LT: | 812 case BinaryOperatorKind.LT: |
729 case BinaryOperatorKind.GTEQ: | 813 case BinaryOperatorKind.GTEQ: |
730 case BinaryOperatorKind.LTEQ: | 814 case BinaryOperatorKind.LTEQ: |
731 return coreTypes.boolType; | 815 return coreTypes.boolType; |
732 case BinaryOperatorKind.ADD: | 816 case BinaryOperatorKind.ADD: |
733 if (knownLeftType == coreTypes.stringType) { | 817 if (knownLeftType == coreTypes.stringType && |
734 assert(knownRightType == coreTypes.stringType); | 818 knownRightType == coreTypes.stringType) { |
735 return coreTypes.stringType; | 819 return coreTypes.stringType; |
736 } else if (knownLeftType == coreTypes.intType && | 820 } else if (knownLeftType == coreTypes.intType && |
737 knownRightType == coreTypes.intType) { | 821 knownRightType == coreTypes.intType) { |
738 return coreTypes.intType; | 822 return coreTypes.intType; |
| 823 } else if ((knownLeftType == coreTypes.intType || |
| 824 knownLeftType == coreTypes.doubleType) && |
| 825 (knownRightType == coreTypes.intType || |
| 826 knownRightType == coreTypes.doubleType)) { |
| 827 return coreTypes.doubleType; |
739 } | 828 } |
740 assert(knownLeftType == coreTypes.doubleType || | 829 return null; |
741 knownRightType == coreTypes.doubleType); | |
742 return coreTypes.doubleType; | |
743 case BinaryOperatorKind.SUB: | 830 case BinaryOperatorKind.SUB: |
744 case BinaryOperatorKind.MUL: | 831 case BinaryOperatorKind.MUL: |
745 case BinaryOperatorKind.MOD: | 832 case BinaryOperatorKind.MOD: |
746 if (knownLeftType == coreTypes.intType && | 833 if (knownLeftType == coreTypes.intType && |
747 knownRightType == coreTypes.intType) { | 834 knownRightType == coreTypes.intType) { |
748 return coreTypes.intType; | 835 return coreTypes.intType; |
| 836 } else if ((knownLeftType == coreTypes.intType || |
| 837 knownLeftType == coreTypes.doubleType) && |
| 838 (knownRightType == coreTypes.intType || |
| 839 knownRightType == coreTypes.doubleType)) { |
| 840 return coreTypes.doubleType; |
749 } | 841 } |
750 assert(knownLeftType == coreTypes.doubleType || | 842 return null; |
751 knownRightType == coreTypes.doubleType); | |
752 return coreTypes.doubleType; | |
753 case BinaryOperatorKind.DIV: | 843 case BinaryOperatorKind.DIV: |
754 return coreTypes.doubleType; | 844 return coreTypes.doubleType; |
755 case BinaryOperatorKind.IDIV: | 845 case BinaryOperatorKind.IDIV: |
756 return coreTypes.intType; | 846 return coreTypes.intType; |
757 case BinaryOperatorKind.AND: | 847 case BinaryOperatorKind.AND: |
758 case BinaryOperatorKind.OR: | 848 case BinaryOperatorKind.OR: |
759 case BinaryOperatorKind.XOR: | 849 case BinaryOperatorKind.XOR: |
760 case BinaryOperatorKind.SHR: | 850 case BinaryOperatorKind.SHR: |
761 case BinaryOperatorKind.SHL: | 851 case BinaryOperatorKind.SHL: |
762 return coreTypes.intType; | 852 return coreTypes.intType; |
763 case BinaryOperatorKind.IF_NULL: | 853 case BinaryOperatorKind.IF_NULL: |
764 case BinaryOperatorKind.INDEX: | 854 case BinaryOperatorKind.INDEX: |
765 throw new UnsupportedError( | 855 throw new UnsupportedError( |
766 'Unexpected constant binary operator: $operator'); | 856 'Unexpected constant binary operator: $operator'); |
767 } | 857 } |
768 } | 858 } |
769 | 859 |
770 | |
771 int get precedence => PRECEDENCE_MAP[operator.kind]; | 860 int get precedence => PRECEDENCE_MAP[operator.kind]; |
772 | 861 |
773 @override | 862 @override |
774 int _computeHashCode() { | 863 int _computeHashCode() { |
775 return 13 * operator.hashCode + | 864 return 13 * operator.hashCode + |
776 17 * left.hashCode + | 865 17 * left.hashCode + |
777 19 * right.hashCode; | 866 19 * right.hashCode; |
778 } | 867 } |
779 | 868 |
780 @override | 869 @override |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 | 905 |
817 ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL; | 906 ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL; |
818 | 907 |
819 accept(ConstantExpressionVisitor visitor, [context]) { | 908 accept(ConstantExpressionVisitor visitor, [context]) { |
820 return visitor.visitIdentical(this, context); | 909 return visitor.visitIdentical(this, context); |
821 } | 910 } |
822 | 911 |
823 @override | 912 @override |
824 ConstantValue evaluate(Environment environment, | 913 ConstantValue evaluate(Environment environment, |
825 ConstantSystem constantSystem) { | 914 ConstantSystem constantSystem) { |
826 return constantSystem.identity.fold( | 915 ConstantValue leftValue = left.evaluate(environment, constantSystem); |
827 left.evaluate(environment, constantSystem), | 916 ConstantValue rightValue = right.evaluate(environment, constantSystem); |
828 right.evaluate(environment, constantSystem)); | 917 if (leftValue.isConstant && rightValue.isConstant) { |
| 918 return constantSystem.identity.fold(leftValue, rightValue); |
| 919 } |
| 920 return new NonConstantValue(); |
829 } | 921 } |
830 | 922 |
831 ConstantExpression apply(NormalizedArguments arguments) { | 923 ConstantExpression apply(NormalizedArguments arguments) { |
832 return new IdenticalConstantExpression( | 924 return new IdenticalConstantExpression( |
833 left.apply(arguments), | 925 left.apply(arguments), |
834 right.apply(arguments)); | 926 right.apply(arguments)); |
835 } | 927 } |
836 | 928 |
837 int get precedence => 15; | 929 int get precedence => 15; |
838 | 930 |
(...skipping 24 matching lines...) Expand all Loading... |
863 | 955 |
864 ConstantExpressionKind get kind => ConstantExpressionKind.UNARY; | 956 ConstantExpressionKind get kind => ConstantExpressionKind.UNARY; |
865 | 957 |
866 accept(ConstantExpressionVisitor visitor, [context]) { | 958 accept(ConstantExpressionVisitor visitor, [context]) { |
867 return visitor.visitUnary(this, context); | 959 return visitor.visitUnary(this, context); |
868 } | 960 } |
869 | 961 |
870 @override | 962 @override |
871 ConstantValue evaluate(Environment environment, | 963 ConstantValue evaluate(Environment environment, |
872 ConstantSystem constantSystem) { | 964 ConstantSystem constantSystem) { |
873 return constantSystem.lookupUnary(operator).fold( | 965 ConstantValue expressionValue = |
874 expression.evaluate(environment, constantSystem)); | 966 expression.evaluate(environment, constantSystem); |
| 967 ConstantExpressionChecker checker = |
| 968 new ConstantExpressionChecker(environment); |
| 969 bool isValidAsConstant = checker.checkUnary( |
| 970 operator, checker.createInfo(expression, expressionValue)); |
| 971 if (isValidAsConstant) { |
| 972 return constantSystem.lookupUnary(operator).fold(expressionValue); |
| 973 } |
| 974 return new NonConstantValue(); |
875 } | 975 } |
876 | 976 |
877 ConstantExpression apply(NormalizedArguments arguments) { | 977 ConstantExpression apply(NormalizedArguments arguments) { |
878 return new UnaryConstantExpression( | 978 return new UnaryConstantExpression( |
879 operator, | 979 operator, |
880 expression.apply(arguments)); | 980 expression.apply(arguments)); |
881 } | 981 } |
882 | 982 |
883 int get precedence => PRECEDENCE_MAP[operator.kind]; | 983 int get precedence => PRECEDENCE_MAP[operator.kind]; |
884 | 984 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 | 1091 |
992 @override | 1092 @override |
993 ConstantValue evaluate(Environment environment, | 1093 ConstantValue evaluate(Environment environment, |
994 ConstantSystem constantSystem) { | 1094 ConstantSystem constantSystem) { |
995 ConstantValue conditionValue = | 1095 ConstantValue conditionValue = |
996 condition.evaluate(environment, constantSystem); | 1096 condition.evaluate(environment, constantSystem); |
997 ConstantValue trueValue = | 1097 ConstantValue trueValue = |
998 trueExp.evaluate(environment, constantSystem); | 1098 trueExp.evaluate(environment, constantSystem); |
999 ConstantValue falseValue = | 1099 ConstantValue falseValue = |
1000 falseExp.evaluate(environment, constantSystem); | 1100 falseExp.evaluate(environment, constantSystem); |
1001 if (conditionValue.isTrue) { | 1101 ConstantExpressionChecker checker = |
| 1102 new ConstantExpressionChecker(environment); |
| 1103 bool isValidAsConstant = checker.checkConditional( |
| 1104 checker.createInfo(condition, conditionValue)); |
| 1105 if (!isValidAsConstant) { |
| 1106 return new NonConstantValue(); |
| 1107 } else if (conditionValue.isTrue) { |
1002 return trueValue; | 1108 return trueValue; |
1003 } else if (conditionValue.isFalse) { | 1109 } else { |
| 1110 assert(conditionValue.isFalse); |
1004 return falseValue; | 1111 return falseValue; |
1005 } else { | |
1006 return new NonConstantValue(); | |
1007 } | 1112 } |
1008 } | 1113 } |
1009 | 1114 |
1010 @override | 1115 @override |
1011 DartType getKnownType(CoreTypes coreTypes) { | 1116 DartType getKnownType(CoreTypes coreTypes) { |
1012 DartType trueType = trueExp.getKnownType(coreTypes); | 1117 DartType trueType = trueExp.getKnownType(coreTypes); |
1013 DartType falseType = falseExp.getKnownType(coreTypes); | 1118 DartType falseType = falseExp.getKnownType(coreTypes); |
1014 if (trueType == falseType) { | 1119 if (trueType == falseType) { |
1015 return trueType; | 1120 return trueType; |
1016 } | 1121 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 ConstantSystem constantSystem) { | 1226 ConstantSystem constantSystem) { |
1122 ConstantValue nameConstantValue = | 1227 ConstantValue nameConstantValue = |
1123 name.evaluate(environment, constantSystem); | 1228 name.evaluate(environment, constantSystem); |
1124 ConstantValue defaultConstantValue; | 1229 ConstantValue defaultConstantValue; |
1125 if (defaultValue != null) { | 1230 if (defaultValue != null) { |
1126 defaultConstantValue = | 1231 defaultConstantValue = |
1127 defaultValue.evaluate(environment, constantSystem); | 1232 defaultValue.evaluate(environment, constantSystem); |
1128 } else { | 1233 } else { |
1129 defaultConstantValue = constantSystem.createBool(false); | 1234 defaultConstantValue = constantSystem.createBool(false); |
1130 } | 1235 } |
1131 if (!nameConstantValue.isString) { | 1236 ConstantExpressionChecker checker = |
| 1237 new ConstantExpressionChecker(environment); |
| 1238 bool isValidAsConstant = checker.checkBoolFromEnvironment( |
| 1239 checker.createInfo(name, nameConstantValue), |
| 1240 checker.createInfo(defaultValue, defaultConstantValue)); |
| 1241 if (!isValidAsConstant) { |
1132 return new NonConstantValue(); | 1242 return new NonConstantValue(); |
1133 } | 1243 } |
1134 StringConstantValue nameStringConstantValue = nameConstantValue; | 1244 StringConstantValue nameStringConstantValue = nameConstantValue; |
1135 String text = environment.readFromEnvironment( | 1245 String text = environment.readFromEnvironment( |
1136 nameStringConstantValue.primitiveValue.slowToString()); | 1246 nameStringConstantValue.primitiveValue.slowToString()); |
1137 if (text == 'true') { | 1247 if (text == 'true') { |
1138 return constantSystem.createBool(true); | 1248 return constantSystem.createBool(true); |
1139 } else if (text == 'false') { | 1249 } else if (text == 'false') { |
1140 return constantSystem.createBool(false); | 1250 return constantSystem.createBool(false); |
1141 } else { | 1251 } else { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 ConstantSystem constantSystem) { | 1285 ConstantSystem constantSystem) { |
1176 ConstantValue nameConstantValue = | 1286 ConstantValue nameConstantValue = |
1177 name.evaluate(environment, constantSystem); | 1287 name.evaluate(environment, constantSystem); |
1178 ConstantValue defaultConstantValue; | 1288 ConstantValue defaultConstantValue; |
1179 if (defaultValue != null) { | 1289 if (defaultValue != null) { |
1180 defaultConstantValue = | 1290 defaultConstantValue = |
1181 defaultValue.evaluate(environment, constantSystem); | 1291 defaultValue.evaluate(environment, constantSystem); |
1182 } else { | 1292 } else { |
1183 defaultConstantValue = constantSystem.createNull(); | 1293 defaultConstantValue = constantSystem.createNull(); |
1184 } | 1294 } |
1185 if (!nameConstantValue.isString) { | 1295 ConstantExpressionChecker checker = |
| 1296 new ConstantExpressionChecker(environment); |
| 1297 bool isValidAsConstant = checker.checkIntFromEnvironment( |
| 1298 checker.createInfo(name, nameConstantValue), |
| 1299 checker.createInfo(defaultValue, defaultConstantValue)); |
| 1300 if (!isValidAsConstant) { |
1186 return new NonConstantValue(); | 1301 return new NonConstantValue(); |
1187 } | 1302 } |
1188 StringConstantValue nameStringConstantValue = nameConstantValue; | 1303 StringConstantValue nameStringConstantValue = nameConstantValue; |
1189 String text = environment.readFromEnvironment( | 1304 String text = environment.readFromEnvironment( |
1190 nameStringConstantValue.primitiveValue.slowToString()); | 1305 nameStringConstantValue.primitiveValue.slowToString()); |
1191 int value; | 1306 int value; |
1192 if (text != null) { | 1307 if (text != null) { |
1193 value = int.parse(text, onError: (_) => null); | 1308 value = int.parse(text, onError: (_) => null); |
1194 } | 1309 } |
1195 if (value == null) { | 1310 if (value == null) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 ConstantSystem constantSystem) { | 1346 ConstantSystem constantSystem) { |
1232 ConstantValue nameConstantValue = | 1347 ConstantValue nameConstantValue = |
1233 name.evaluate(environment, constantSystem); | 1348 name.evaluate(environment, constantSystem); |
1234 ConstantValue defaultConstantValue; | 1349 ConstantValue defaultConstantValue; |
1235 if (defaultValue != null) { | 1350 if (defaultValue != null) { |
1236 defaultConstantValue = | 1351 defaultConstantValue = |
1237 defaultValue.evaluate(environment, constantSystem); | 1352 defaultValue.evaluate(environment, constantSystem); |
1238 } else { | 1353 } else { |
1239 defaultConstantValue = constantSystem.createNull(); | 1354 defaultConstantValue = constantSystem.createNull(); |
1240 } | 1355 } |
1241 if (!nameConstantValue.isString) { | 1356 ConstantExpressionChecker checker = |
| 1357 new ConstantExpressionChecker(environment); |
| 1358 bool isValidAsConstant = checker.checkStringFromEnvironment( |
| 1359 checker.createInfo(name, nameConstantValue), |
| 1360 checker.createInfo(defaultValue, defaultConstantValue)); |
| 1361 if (!isValidAsConstant) { |
1242 return new NonConstantValue(); | 1362 return new NonConstantValue(); |
1243 } | 1363 } |
1244 StringConstantValue nameStringConstantValue = nameConstantValue; | 1364 StringConstantValue nameStringConstantValue = nameConstantValue; |
1245 String text = environment.readFromEnvironment( | 1365 String text = environment.readFromEnvironment( |
1246 nameStringConstantValue.primitiveValue.slowToString()); | 1366 nameStringConstantValue.primitiveValue.slowToString()); |
1247 if (text == null) { | 1367 if (text == null) { |
1248 return defaultConstantValue; | 1368 return defaultConstantValue; |
1249 } else { | 1369 } else { |
1250 return constantSystem.createString(new DartString.literal(text)); | 1370 return constantSystem.createString(new DartString.literal(text)); |
1251 } | 1371 } |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 sb.write('const String.fromEnvironment('); | 1718 sb.write('const String.fromEnvironment('); |
1599 visit(exp.name); | 1719 visit(exp.name); |
1600 if (exp.defaultValue != null) { | 1720 if (exp.defaultValue != null) { |
1601 sb.write(', defaultValue: '); | 1721 sb.write(', defaultValue: '); |
1602 visit(exp.defaultValue); | 1722 visit(exp.defaultValue); |
1603 } | 1723 } |
1604 sb.write(')'); | 1724 sb.write(')'); |
1605 } | 1725 } |
1606 | 1726 |
1607 String toString() => sb.toString(); | 1727 String toString() => sb.toString(); |
1608 } | 1728 } |
OLD | NEW |