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 |