| 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 |