| 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 // TODO(asgerf): Include metadata. | 5 // TODO(asgerf): Include metadata. |
| 6 // TODO(asgerf): Include cascade operator. | 6 // TODO(asgerf): Include cascade operator. |
| 7 library dart_printer; | 7 library dart_printer; |
| 8 | 8 |
| 9 import '../dart2jslib.dart' as dart2js; | 9 import '../dart2jslib.dart' as dart2js; |
| 10 import '../tree/tree.dart' as tree; | 10 import '../tree/tree.dart' as tree; |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 | 467 |
| 468 UnaryOperator(this.operatorName, this.operand) { | 468 UnaryOperator(this.operatorName, this.operand) { |
| 469 assert(isUnaryOperator(operatorName)); | 469 assert(isUnaryOperator(operatorName)); |
| 470 } | 470 } |
| 471 } | 471 } |
| 472 | 472 |
| 473 /// Expression of form `e1 + e2`, `e1 - e2`, etc. | 473 /// Expression of form `e1 + e2`, `e1 - e2`, etc. |
| 474 /// This node also represents application of the logical operators && and ||. | 474 /// This node also represents application of the logical operators && and ||. |
| 475 class BinaryOperator extends Expression { | 475 class BinaryOperator extends Expression { |
| 476 final Receiver left; | 476 final Receiver left; |
| 477 final String operatorName; | 477 final String operator; |
| 478 final Expression right; | 478 final Expression right; |
| 479 | 479 |
| 480 BinaryOperator(this.left, this.operatorName, this.right) { | 480 BinaryOperator(this.left, this.operator, this.right) { |
| 481 assert(isBinaryOperator(operatorName)); | 481 assert(isBinaryOperator(operator)); |
| 482 } | 482 } |
| 483 } | 483 } |
| 484 | 484 |
| 485 /// Expression of form `e is T` or `e is! T` or `e as T`. | 485 /// Expression of form `e is T` or `e is! T` or `e as T`. |
| 486 class TypeOperator extends Expression { | 486 class TypeOperator extends Expression { |
| 487 final Expression expression; | 487 final Expression expression; |
| 488 final String operatorName; | 488 final String operator; |
| 489 final TypeAnnotation type; | 489 final TypeAnnotation type; |
| 490 | 490 |
| 491 TypeOperator(this.expression, this.operatorName, this.type) { | 491 TypeOperator(this.expression, this.operator, this.type) { |
| 492 assert(operatorName == 'is' | 492 assert(operator == 'is' |
| 493 || operatorName == 'as' | 493 || operator == 'as' |
| 494 || operatorName == 'is!'); | 494 || operator == 'is!'); |
| 495 } | 495 } |
| 496 } | 496 } |
| 497 | 497 |
| 498 class Increment extends Expression { | 498 class Increment extends Expression { |
| 499 final Expression expression; | 499 final Expression expression; |
| 500 final String operatorName; | 500 final String operator; |
| 501 final bool isPrefix; | 501 final bool isPrefix; |
| 502 | 502 |
| 503 Increment(this.expression, this.operatorName, this.isPrefix) { | 503 Increment(this.expression, this.operator, this.isPrefix) { |
| 504 assert(operatorName == '++' || operatorName == '--'); | 504 assert(operator == '++' || operator == '--'); |
| 505 assert(expression.assignable); | 505 assert(expression.assignable); |
| 506 } | 506 } |
| 507 | 507 |
| 508 Increment.prefix(Expression expression, String operator) | 508 Increment.prefix(Expression expression, String operator) |
| 509 : this(expression, operator, true); | 509 : this(expression, operator, true); |
| 510 | 510 |
| 511 Increment.postfix(Expression expression, String operator) | 511 Increment.postfix(Expression expression, String operator) |
| 512 : this(expression, operator, false); | 512 : this(expression, operator, false); |
| 513 } | 513 } |
| 514 | 514 |
| 515 class Assignment extends Expression { | 515 class Assignment extends Expression { |
| 516 static final _operators = | 516 static final _operators = |
| 517 new Set.from(['=', '|=', '^=', '&=', '<<=', '>>=', | 517 new Set.from(['=', '|=', '^=', '&=', '<<=', '>>=', |
| 518 '+=', '-=', '*=', '/=', '%=', '~/=']); | 518 '+=', '-=', '*=', '/=', '%=', '~/=']); |
| 519 | 519 |
| 520 final Expression left; | 520 final Expression left; |
| 521 final String operatorName; | 521 final String operator; |
| 522 final Expression right; | 522 final Expression right; |
| 523 | 523 |
| 524 Assignment(this.left, this.operatorName, this.right) { | 524 Assignment(this.left, this.operator, this.right) { |
| 525 assert(_operators.contains(operatorName)); | 525 assert(_operators.contains(operator)); |
| 526 assert(left.assignable); | 526 assert(left.assignable); |
| 527 } | 527 } |
| 528 } | 528 } |
| 529 | 529 |
| 530 class Throw extends Expression { | 530 class Throw extends Expression { |
| 531 final Expression expression; | 531 final Expression expression; |
| 532 | 532 |
| 533 Throw(this.expression); | 533 Throw(this.expression); |
| 534 } | 534 } |
| 535 | 535 |
| 536 class This extends Expression { | 536 class This extends Expression { |
| 537 static final This _instance = new This._create(); | 537 static final This _instance = new This._create(); |
| 538 | 538 |
| 539 factory This() => _instance; | 539 factory This() => _instance; |
| 540 This._create(); | 540 This._create(); |
| 541 } | 541 } |
| 542 | 542 |
| 543 // UNPARSER | 543 // UNPARSER |
| 544 | 544 |
| 545 bool isUnaryOperator(String op) { | 545 bool isUnaryOperator(String op) { |
| 546 return op == '!' || op == '-' || op == '~'; | 546 return op == '!' || op == '-' || op == '~'; |
| 547 } | 547 } |
| 548 bool isBinaryOperator(String op) { | 548 bool isBinaryOperator(String op) { |
| 549 return BINARY_PRECEDENCE.containsKey(op); | 549 return BINARY_PRECEDENCE.containsKey(op); |
| 550 } | 550 } |
| 551 /// True if the given operator can be converted to a compound assignment. |
| 552 bool isCompoundableOperator(String op) { |
| 553 switch (BINARY_PRECEDENCE[op]) { |
| 554 case BITWISE_OR: |
| 555 case BITWISE_XOR: |
| 556 case BITWISE_AND: |
| 557 case SHIFT: |
| 558 case ADDITIVE: |
| 559 case MULTIPLICATIVE: |
| 560 return true; |
| 561 default: |
| 562 return false; |
| 563 } |
| 564 } |
| 551 | 565 |
| 552 | 566 |
| 553 // Precedence levels | 567 // Precedence levels |
| 554 const int EXPRESSION = 1; | 568 const int EXPRESSION = 1; |
| 555 const int CONDITIONAL = 2; | 569 const int CONDITIONAL = 2; |
| 556 const int LOGICAL_OR = 3; | 570 const int LOGICAL_OR = 3; |
| 557 const int LOGICAL_AND = 4; | 571 const int LOGICAL_AND = 4; |
| 558 const int EQUALITY = 6; | 572 const int EQUALITY = 6; |
| 559 const int RELATIONAL = 7; | 573 const int RELATIONAL = 7; |
| 560 const int BITWISE_OR = 8; | 574 const int BITWISE_OR = 8; |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 } | 845 } |
| 832 } else if (e is LiteralSymbol) { | 846 } else if (e is LiteralSymbol) { |
| 833 write('#'); | 847 write('#'); |
| 834 write(e.id); // TODO(asgerf): Do we need to escape something here? | 848 write(e.id); // TODO(asgerf): Do we need to escape something here? |
| 835 } else if (e is StringConcat) { | 849 } else if (e is StringConcat) { |
| 836 writeStringLiteral(e); | 850 writeStringLiteral(e); |
| 837 } else if (e is UnaryOperator) { | 851 } else if (e is UnaryOperator) { |
| 838 Receiver operand = e.operand; | 852 Receiver operand = e.operand; |
| 839 // !(x == y) ==> x != y. | 853 // !(x == y) ==> x != y. |
| 840 if (e.operatorName == '!' && | 854 if (e.operatorName == '!' && |
| 841 operand is BinaryOperator && operand.operatorName == '==') { | 855 operand is BinaryOperator && operand.operator == '==') { |
| 842 withPrecedence(EQUALITY, () { | 856 withPrecedence(EQUALITY, () { |
| 843 writeExp(operand.left, RELATIONAL); | 857 writeExp(operand.left, RELATIONAL); |
| 844 writeOperator('!='); | 858 writeOperator('!='); |
| 845 writeExp(operand.right, RELATIONAL); | 859 writeExp(operand.right, RELATIONAL); |
| 846 }); | 860 }); |
| 847 } | 861 } |
| 848 // !(x is T) ==> x is!T | 862 // !(x is T) ==> x is!T |
| 849 else if (e.operatorName == '!' && | 863 else if (e.operatorName == '!' && |
| 850 operand is TypeOperator && operand.operatorName == 'is') { | 864 operand is TypeOperator && operand.operator == 'is') { |
| 851 withPrecedence(RELATIONAL, () { | 865 withPrecedence(RELATIONAL, () { |
| 852 writeExp(operand.expression, BITWISE_OR, beginStmt: beginStmt); | 866 writeExp(operand.expression, BITWISE_OR, beginStmt: beginStmt); |
| 853 write(' is!'); // TODO(asgerf): Minimize use of whitespace. | 867 write(' is!'); // TODO(asgerf): Minimize use of whitespace. |
| 854 writeType(operand.type); | 868 writeType(operand.type); |
| 855 }); | 869 }); |
| 856 } | 870 } |
| 857 else { | 871 else { |
| 858 withPrecedence(UNARY, () { | 872 withPrecedence(UNARY, () { |
| 859 writeOperator(e.operatorName); | 873 writeOperator(e.operatorName); |
| 860 writeExp(e.operand, UNARY); | 874 writeExp(e.operand, UNARY); |
| 861 }); | 875 }); |
| 862 } | 876 } |
| 863 } else if (e is BinaryOperator) { | 877 } else if (e is BinaryOperator) { |
| 864 int precedence = BINARY_PRECEDENCE[e.operatorName]; | 878 int precedence = BINARY_PRECEDENCE[e.operator]; |
| 865 withPrecedence(precedence, () { | 879 withPrecedence(precedence, () { |
| 866 // All binary operators are left-associative or non-associative. | 880 // All binary operators are left-associative or non-associative. |
| 867 // For each operand, we use either the same precedence level as | 881 // For each operand, we use either the same precedence level as |
| 868 // the current operator, or one higher. | 882 // the current operator, or one higher. |
| 869 int deltaLeft = isAssociativeBinaryOperator(precedence) ? 0 : 1; | 883 int deltaLeft = isAssociativeBinaryOperator(precedence) ? 0 : 1; |
| 870 writeExp(e.left, precedence + deltaLeft, beginStmt: beginStmt); | 884 writeExp(e.left, precedence + deltaLeft, beginStmt: beginStmt); |
| 871 writeOperator(e.operatorName); | 885 writeOperator(e.operator); |
| 872 writeExp(e.right, precedence + 1); | 886 writeExp(e.right, precedence + 1); |
| 873 }); | 887 }); |
| 874 } else if (e is TypeOperator) { | 888 } else if (e is TypeOperator) { |
| 875 withPrecedence(RELATIONAL, () { | 889 withPrecedence(RELATIONAL, () { |
| 876 writeExp(e.expression, BITWISE_OR, beginStmt: beginStmt); | 890 writeExp(e.expression, BITWISE_OR, beginStmt: beginStmt); |
| 877 write(' '); | 891 write(' '); |
| 878 write(e.operatorName); | 892 write(e.operator); |
| 879 write(' '); | 893 write(' '); |
| 880 writeType(e.type); | 894 writeType(e.type); |
| 881 }); | 895 }); |
| 882 } else if (e is Assignment) { | 896 } else if (e is Assignment) { |
| 883 withPrecedence(EXPRESSION, () { | 897 withPrecedence(EXPRESSION, () { |
| 884 writeExp(e.left, PRIMARY, beginStmt: beginStmt); | 898 writeExp(e.left, PRIMARY, beginStmt: beginStmt); |
| 885 writeOperator(e.operatorName); | 899 writeOperator(e.operator); |
| 886 writeExp(e.right, EXPRESSION); | 900 writeExp(e.right, EXPRESSION); |
| 887 }); | 901 }); |
| 888 } else if (e is FieldExpression) { | 902 } else if (e is FieldExpression) { |
| 889 withPrecedence(PRIMARY, () { | 903 withPrecedence(PRIMARY, () { |
| 890 writeExp(e.object, PRIMARY, beginStmt: beginStmt); | 904 writeExp(e.object, PRIMARY, beginStmt: beginStmt); |
| 891 write('.'); | 905 write('.'); |
| 892 write(e.fieldName); | 906 write(e.fieldName); |
| 893 }); | 907 }); |
| 894 } else if (e is IndexExpression) { | 908 } else if (e is IndexExpression) { |
| 895 withPrecedence(CALLEE, () { | 909 withPrecedence(CALLEE, () { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 write('.'); | 947 write('.'); |
| 934 write(e.methodName); | 948 write(e.methodName); |
| 935 write('('); | 949 write('('); |
| 936 writeEach(',', e.arguments, writeArgument); | 950 writeEach(',', e.arguments, writeArgument); |
| 937 write(')'); | 951 write(')'); |
| 938 }); | 952 }); |
| 939 } else if (e is Increment) { | 953 } else if (e is Increment) { |
| 940 int precedence = e.isPrefix ? UNARY : POSTFIX_INCREMENT; | 954 int precedence = e.isPrefix ? UNARY : POSTFIX_INCREMENT; |
| 941 withPrecedence(precedence, () { | 955 withPrecedence(precedence, () { |
| 942 if (e.isPrefix) { | 956 if (e.isPrefix) { |
| 943 write(e.operatorName); | 957 write(e.operator); |
| 944 writeExp(e.expression, PRIMARY); | 958 writeExp(e.expression, PRIMARY); |
| 945 } else { | 959 } else { |
| 946 writeExp(e.expression, PRIMARY, beginStmt: beginStmt); | 960 writeExp(e.expression, PRIMARY, beginStmt: beginStmt); |
| 947 write(e.operatorName); | 961 write(e.operator); |
| 948 } | 962 } |
| 949 }); | 963 }); |
| 950 } else if (e is Throw) { | 964 } else if (e is Throw) { |
| 951 withPrecedence(EXPRESSION, () { | 965 withPrecedence(EXPRESSION, () { |
| 952 write('throw '); | 966 write('throw '); |
| 953 writeExp(e.expression, EXPRESSION); | 967 writeExp(e.expression, EXPRESSION); |
| 954 }); | 968 }); |
| 955 } else if (e is This) { | 969 } else if (e is This) { |
| 956 write('this'); | 970 write('this'); |
| 957 } else { | 971 } else { |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1476 final StringChunk previous; | 1490 final StringChunk previous; |
| 1477 final tree.StringQuoting quoting; | 1491 final tree.StringQuoting quoting; |
| 1478 num cost; | 1492 num cost; |
| 1479 | 1493 |
| 1480 OpenStringChunk(this.previous, this.quoting, this.cost); | 1494 OpenStringChunk(this.previous, this.quoting, this.cost); |
| 1481 | 1495 |
| 1482 StringChunk end(int endIndex) { | 1496 StringChunk end(int endIndex) { |
| 1483 return new StringChunk(previous, quoting, endIndex); | 1497 return new StringChunk(previous, quoting, endIndex); |
| 1484 } | 1498 } |
| 1485 } | 1499 } |
| OLD | NEW |