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

Side by Side Diff: pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 backend_ast_nodes; 5 library backend_ast_nodes;
6 6
7 import '../constants/values.dart' as values; 7 import '../constants/values.dart' as values;
8 import '../dart_types.dart' as types; 8 import '../dart_types.dart' as types;
9 import '../elements/elements.dart' as elements; 9 import '../elements/elements.dart' as elements;
10 import '../tree/tree.dart' as tree; 10 import '../tree/tree.dart' as tree;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 final String name; 61 final String name;
62 final List<TypeAnnotation> typeArguments; 62 final List<TypeAnnotation> typeArguments;
63 63
64 types.DartType dartType; 64 types.DartType dartType;
65 65
66 TypeAnnotation(this.name, [this.typeArguments = const <TypeAnnotation>[]]); 66 TypeAnnotation(this.name, [this.typeArguments = const <TypeAnnotation>[]]);
67 } 67 }
68 68
69 // STATEMENTS 69 // STATEMENTS
70 70
71
72 class Block extends Statement { 71 class Block extends Statement {
73 final List<Statement> statements; 72 final List<Statement> statements;
74 73
75 Block(this.statements); 74 Block(this.statements);
76 } 75 }
77 76
78 class Break extends Statement { 77 class Break extends Statement {
79 final String label; 78 final String label;
80 79
81 Break([this.label]); 80 Break([this.label]);
(...skipping 19 matching lines...) Expand all
101 } 100 }
102 101
103 class For extends Statement { 102 class For extends Statement {
104 final Node initializer; 103 final Node initializer;
105 final Expression condition; 104 final Expression condition;
106 final List<Expression> updates; 105 final List<Expression> updates;
107 final Statement body; 106 final Statement body;
108 107
109 /// Initializer must be [VariableDeclarations] or [Expression] or null. 108 /// Initializer must be [VariableDeclarations] or [Expression] or null.
110 For(this.initializer, this.condition, this.updates, this.body) { 109 For(this.initializer, this.condition, this.updates, this.body) {
111 assert(initializer == null 110 assert(initializer == null ||
112 || initializer is VariableDeclarations 111 initializer is VariableDeclarations ||
113 || initializer is Expression); 112 initializer is Expression);
114 } 113 }
115 } 114 }
116 115
117 class ForIn extends Statement { 116 class ForIn extends Statement {
118 final Node leftHandValue; 117 final Node leftHandValue;
119 final Expression expression; 118 final Expression expression;
120 final Statement body; 119 final Statement body;
121 120
122 /// [leftHandValue] must be [Identifier] or [VariableDeclarations] with 121 /// [leftHandValue] must be [Identifier] or [VariableDeclarations] with
123 /// exactly one definition, and that variable definition must have no 122 /// exactly one definition, and that variable definition must have no
124 /// initializer. 123 /// initializer.
125 ForIn(Node leftHandValue, this.expression, this.body) 124 ForIn(Node leftHandValue, this.expression, this.body)
126 : this.leftHandValue = leftHandValue { 125 : this.leftHandValue = leftHandValue {
127 assert(leftHandValue is Identifier 126 assert(leftHandValue is Identifier ||
128 || (leftHandValue is VariableDeclarations 127 (leftHandValue is VariableDeclarations &&
129 && leftHandValue.declarations.length == 1 128 leftHandValue.declarations.length == 1 &&
130 && leftHandValue.declarations[0].initializer == null)); 129 leftHandValue.declarations[0].initializer == null));
131 } 130 }
132 } 131 }
133 132
134 class While extends Statement { 133 class While extends Statement {
135 final Expression condition; 134 final Expression condition;
136 final Statement body; 135 final Statement body;
137 136
138 While(this.condition, this.body); 137 While(this.condition, this.body);
139 } 138 }
140 139
(...skipping 12 matching lines...) Expand all
153 If(this.condition, this.thenStatement, [this.elseStatement]); 152 If(this.condition, this.thenStatement, [this.elseStatement]);
154 } 153 }
155 154
156 class LabeledStatement extends Statement { 155 class LabeledStatement extends Statement {
157 final String label; 156 final String label;
158 final Statement statement; 157 final Statement statement;
159 158
160 LabeledStatement(this.label, this.statement); 159 LabeledStatement(this.label, this.statement);
161 } 160 }
162 161
163 class Rethrow extends Statement { 162 class Rethrow extends Statement {}
164 }
165 163
166 class Return extends Statement { 164 class Return extends Statement {
167 final Expression expression; 165 final Expression expression;
168 166
169 Return([this.expression]); 167 Return([this.expression]);
170 } 168 }
171 169
172 class Switch extends Statement { 170 class Switch extends Statement {
173 final Expression expression; 171 final Expression expression;
174 final List<SwitchCase> cases; 172 final List<SwitchCase> cases;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 } 220 }
223 } 221 }
224 222
225 class VariableDeclarations extends Statement { 223 class VariableDeclarations extends Statement {
226 final TypeAnnotation type; 224 final TypeAnnotation type;
227 final bool isFinal; 225 final bool isFinal;
228 final bool isConst; 226 final bool isConst;
229 final List<VariableDeclaration> declarations; 227 final List<VariableDeclaration> declarations;
230 228
231 VariableDeclarations(this.declarations, 229 VariableDeclarations(this.declarations,
232 { this.type, 230 {this.type, this.isFinal: false, this.isConst: false}) {
233 this.isFinal: false,
234 this.isConst: false }) {
235 // Cannot be both final and const. 231 // Cannot be both final and const.
236 assert(!isFinal || !isConst); 232 assert(!isFinal || !isConst);
237 } 233 }
238 } 234 }
239 235
240 class VariableDeclaration extends Node { 236 class VariableDeclaration extends Node {
241 final String name; 237 final String name;
242 final Expression initializer; 238 final Expression initializer;
243 239
244 elements.Element element; 240 elements.Element element;
245 241
246 VariableDeclaration(this.name, [this.initializer]); 242 VariableDeclaration(this.name, [this.initializer]);
247 } 243 }
248 244
249
250 class FunctionDeclaration extends Statement { 245 class FunctionDeclaration extends Statement {
251 final FunctionExpression function; 246 final FunctionExpression function;
252 247
253 TypeAnnotation get returnType => function.returnType; 248 TypeAnnotation get returnType => function.returnType;
254 Parameters get parameters => function.parameters; 249 Parameters get parameters => function.parameters;
255 String get name => function.name; 250 String get name => function.name;
256 Statement get body => function.body; 251 Statement get body => function.body;
257 252
258 FunctionDeclaration(this.function); 253 FunctionDeclaration(this.function);
259 } 254 }
260 255
261 class Parameters extends Node { 256 class Parameters extends Node {
262 final List<Parameter> requiredParameters; 257 final List<Parameter> requiredParameters;
263 final List<Parameter> optionalParameters; 258 final List<Parameter> optionalParameters;
264 final bool hasNamedParameters; 259 final bool hasNamedParameters;
265 260
266 Parameters(this.requiredParameters, 261 Parameters(this.requiredParameters,
267 [ this.optionalParameters, 262 [this.optionalParameters, this.hasNamedParameters = false]);
268 this.hasNamedParameters = false ]);
269 263
270 Parameters.named(this.requiredParameters, this.optionalParameters) 264 Parameters.named(this.requiredParameters, this.optionalParameters)
271 : hasNamedParameters = true; 265 : hasNamedParameters = true;
272 266
273 Parameters.positional(this.requiredParameters, this.optionalParameters) 267 Parameters.positional(this.requiredParameters, this.optionalParameters)
274 : hasNamedParameters = false; 268 : hasNamedParameters = false;
275 269
276 bool get hasOptionalParameters => 270 bool get hasOptionalParameters =>
277 optionalParameters != null && optionalParameters.length > 0; 271 optionalParameters != null && optionalParameters.length > 0;
278 } 272 }
279 273
280 class Parameter extends Node { 274 class Parameter extends Node {
281 final String name; 275 final String name;
282 276
283 /// Type of parameter, or return type of function parameter. 277 /// Type of parameter, or return type of function parameter.
284 final TypeAnnotation type; 278 final TypeAnnotation type;
285 279
286 Expression defaultValue; 280 Expression defaultValue;
287 281
288 /// Parameters to function parameter. Null for non-function parameters. 282 /// Parameters to function parameter. Null for non-function parameters.
289 final Parameters parameters; 283 final Parameters parameters;
290 284
291 elements.FormalElement element; 285 elements.FormalElement element;
292 286
293 Parameter(this.name, {this.type, this.defaultValue}) 287 Parameter(this.name, {this.type, this.defaultValue}) : parameters = null;
294 : parameters = null;
295 288
296 Parameter.function(this.name, 289 Parameter.function(this.name, TypeAnnotation returnType, this.parameters,
297 TypeAnnotation returnType, 290 [this.defaultValue])
298 this.parameters, 291 : type = returnType {
299 [ this.defaultValue ]) : type = returnType {
300 assert(parameters != null); 292 assert(parameters != null);
301 } 293 }
302 294
303 /// True if this is a function parameter. 295 /// True if this is a function parameter.
304 bool get isFunction => parameters != null; 296 bool get isFunction => parameters != null;
305 } 297 }
306 298
307 // EXPRESSIONS 299 // EXPRESSIONS
308 300
309 abstract class Initializer extends Expression {} 301 abstract class Initializer extends Expression {}
(...skipping 15 matching lines...) Expand all
325 class FunctionExpression extends Expression implements RootNode { 317 class FunctionExpression extends Expression implements RootNode {
326 final TypeAnnotation returnType; 318 final TypeAnnotation returnType;
327 String name; 319 String name;
328 final Parameters parameters; 320 final Parameters parameters;
329 final Statement body; 321 final Statement body;
330 final bool isGetter; 322 final bool isGetter;
331 final bool isSetter; 323 final bool isSetter;
332 324
333 elements.FunctionElement element; 325 elements.FunctionElement element;
334 326
335 FunctionExpression(this.parameters, 327 FunctionExpression(this.parameters, this.body,
336 this.body, 328 {this.name,
337 { this.name, 329 this.returnType,
338 this.returnType, 330 this.isGetter: false,
339 this.isGetter: false, 331 this.isSetter: false}) {
340 this.isSetter: false }) {
341 // Function must have a name if it has a return type 332 // Function must have a name if it has a return type
342 assert(returnType == null || name != null); 333 assert(returnType == null || name != null);
343 } 334 }
344 } 335 }
345 336
346 class ConstructorDefinition extends FunctionExpression { 337 class ConstructorDefinition extends FunctionExpression {
347 final List<Initializer> initializers; 338 final List<Initializer> initializers;
348 final bool isConst; 339 final bool isConst;
349 340
350 ConstructorDefinition(Parameters parameters, Statement body, 341 ConstructorDefinition(Parameters parameters, Statement body,
351 this.initializers, String name, this.isConst) 342 this.initializers, String name, this.isConst)
352 : super(parameters, body, name: name); 343 : super(parameters, body, name: name);
353 } 344 }
354 345
355 class Conditional extends Expression { 346 class Conditional extends Expression {
356 final Expression condition; 347 final Expression condition;
357 final Expression thenExpression; 348 final Expression thenExpression;
358 final Expression elseExpression; 349 final Expression elseExpression;
359 350
360 Conditional(this.condition, this.thenExpression, this.elseExpression); 351 Conditional(this.condition, this.thenExpression, this.elseExpression);
361 } 352 }
(...skipping 20 matching lines...) Expand all
382 final values.PrimitiveConstantValue value; 373 final values.PrimitiveConstantValue value;
383 374
384 Literal(this.value); 375 Literal(this.value);
385 } 376 }
386 377
387 class LiteralList extends Expression { 378 class LiteralList extends Expression {
388 final bool isConst; 379 final bool isConst;
389 final TypeAnnotation typeArgument; 380 final TypeAnnotation typeArgument;
390 final List<Expression> values; 381 final List<Expression> values;
391 382
392 LiteralList(this.values, { this.typeArgument, this.isConst: false }); 383 LiteralList(this.values, {this.typeArgument, this.isConst: false});
393 } 384 }
394 385
395 class LiteralMap extends Expression { 386 class LiteralMap extends Expression {
396 final bool isConst; 387 final bool isConst;
397 final List<TypeAnnotation> typeArguments; 388 final List<TypeAnnotation> typeArguments;
398 final List<LiteralMapEntry> entries; 389 final List<LiteralMapEntry> entries;
399 390
400 LiteralMap(this.entries, { this.typeArguments, this.isConst: false }) { 391 LiteralMap(this.entries, {this.typeArguments, this.isConst: false}) {
401 assert(this.typeArguments == null 392 assert(this.typeArguments == null ||
402 || this.typeArguments.length == 0 393 this.typeArguments.length == 0 ||
403 || this.typeArguments.length == 2); 394 this.typeArguments.length == 2);
404 } 395 }
405 } 396 }
406 397
407 class LiteralMapEntry extends Node { 398 class LiteralMapEntry extends Node {
408 final Expression key; 399 final Expression key;
409 final Expression value; 400 final Expression value;
410 401
411 LiteralMapEntry(this.key, this.value); 402 LiteralMapEntry(this.key, this.value);
412 } 403 }
413 404
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 /// or `const T.f(..)`. 488 /// or `const T.f(..)`.
498 class CallNew extends Expression { 489 class CallNew extends Expression {
499 final bool isConst; 490 final bool isConst;
500 final TypeAnnotation type; 491 final TypeAnnotation type;
501 final String constructorName; 492 final String constructorName;
502 final List<Argument> arguments; 493 final List<Argument> arguments;
503 494
504 elements.FunctionElement constructor; 495 elements.FunctionElement constructor;
505 types.DartType dartType; 496 types.DartType dartType;
506 497
507 CallNew(this.type, 498 CallNew(this.type, this.arguments,
508 this.arguments, 499 {this.constructorName, this.isConst: false});
509 { this.constructorName,
510 this.isConst: false });
511 } 500 }
512 501
513 /// Expression of form `T.f(..)`. 502 /// Expression of form `T.f(..)`.
514 class CallStatic extends Expression { 503 class CallStatic extends Expression {
515 final String className; 504 final String className;
516 final String methodName; 505 final String methodName;
517 final List<Argument> arguments; 506 final List<Argument> arguments;
518 507
519 elements.Element element; 508 elements.Element element;
520 509
(...skipping 22 matching lines...) Expand all
543 } 532 }
544 } 533 }
545 534
546 /// Expression of form `e is T` or `e is! T` or `e as T`. 535 /// Expression of form `e is T` or `e is! T` or `e as T`.
547 class TypeOperator extends Expression { 536 class TypeOperator extends Expression {
548 final Expression expression; 537 final Expression expression;
549 final String operator; 538 final String operator;
550 final TypeAnnotation type; 539 final TypeAnnotation type;
551 540
552 TypeOperator(this.expression, this.operator, this.type) { 541 TypeOperator(this.expression, this.operator, this.type) {
553 assert(operator == 'is' 542 assert(operator == 'is' || operator == 'as' || operator == 'is!');
554 || operator == 'as'
555 || operator == 'is!');
556 } 543 }
557 } 544 }
558 545
559 class Increment extends Expression { 546 class Increment extends Expression {
560 final Expression expression; 547 final Expression expression;
561 final String operator; 548 final String operator;
562 final bool isPrefix; 549 final bool isPrefix;
563 550
564 Increment(this.expression, this.operator, this.isPrefix) { 551 Increment(this.expression, this.operator, this.isPrefix) {
565 assert(operator == '++' || operator == '--'); 552 assert(operator == '++' || operator == '--');
566 assert(expression.assignable); 553 assert(expression.assignable);
567 } 554 }
568 555
569 Increment.prefix(Expression expression, String operator) 556 Increment.prefix(Expression expression, String operator)
570 : this(expression, operator, true); 557 : this(expression, operator, true);
571 558
572 Increment.postfix(Expression expression, String operator) 559 Increment.postfix(Expression expression, String operator)
573 : this(expression, operator, false); 560 : this(expression, operator, false);
574 } 561 }
575 562
576 class Assignment extends Expression { 563 class Assignment extends Expression {
577 static final _operators = 564 static final _operators = new Set.from([
578 new Set.from(['=', '|=', '^=', '&=', '<<=', '>>=', 565 '=',
579 '+=', '-=', '*=', '/=', '%=', '~/=']); 566 '|=',
567 '^=',
568 '&=',
569 '<<=',
570 '>>=',
571 '+=',
572 '-=',
573 '*=',
574 '/=',
575 '%=',
576 '~/='
577 ]);
580 578
581 final Expression left; 579 final Expression left;
582 final String operator; 580 final String operator;
583 final Expression right; 581 final Expression right;
584 582
585 Assignment(this.left, this.operator, this.right) { 583 Assignment(this.left, this.operator, this.right) {
586 assert(_operators.contains(operator)); 584 assert(_operators.contains(operator));
587 assert(left.assignable); 585 assert(left.assignable);
588 } 586 }
589 } 587 }
590 588
591 class Throw extends Expression { 589 class Throw extends Expression {
592 final Expression expression; 590 final Expression expression;
593 591
594 Throw(this.expression); 592 Throw(this.expression);
595 } 593 }
596 594
597 class This extends Expression { 595 class This extends Expression {
598 static final This _instance = new This._create(); 596 static final This _instance = new This._create();
599 597
600 factory This() => _instance; 598 factory This() => _instance;
601 This._create(); 599 This._create();
602 } 600 }
603 601
604 // UNPARSER 602 // UNPARSER
605 603
606 bool isUnaryOperator(String op) { 604 bool isUnaryOperator(String op) {
607 return op == '!' || op == '-' || op == '~'; 605 return op == '!' || op == '-' || op == '~';
608 } 606 }
607
609 bool isBinaryOperator(String op) { 608 bool isBinaryOperator(String op) {
610 return BINARY_PRECEDENCE.containsKey(op); 609 return BINARY_PRECEDENCE.containsKey(op);
611 } 610 }
611
612 /// True if the given operator can be converted to a compound assignment. 612 /// True if the given operator can be converted to a compound assignment.
613 bool isCompoundableOperator(String op) { 613 bool isCompoundableOperator(String op) {
614 switch (BINARY_PRECEDENCE[op]) { 614 switch (BINARY_PRECEDENCE[op]) {
615 case BITWISE_OR: 615 case BITWISE_OR:
616 case BITWISE_XOR: 616 case BITWISE_XOR:
617 case BITWISE_AND: 617 case BITWISE_AND:
618 case SHIFT: 618 case SHIFT:
619 case ADDITIVE: 619 case ADDITIVE:
620 case MULTIPLICATIVE: 620 case MULTIPLICATIVE:
621 return true; 621 return true;
622 default: 622 default:
623 return false; 623 return false;
624 } 624 }
625 } 625 }
626 626
627
628 // Precedence levels 627 // Precedence levels
629 const int EXPRESSION = 1; 628 const int EXPRESSION = 1;
630 const int CONDITIONAL = 2; 629 const int CONDITIONAL = 2;
631 const int LOGICAL_OR = 3; 630 const int LOGICAL_OR = 3;
632 const int LOGICAL_AND = 4; 631 const int LOGICAL_AND = 4;
633 const int EQUALITY = 6; 632 const int EQUALITY = 6;
634 const int RELATIONAL = 7; 633 const int RELATIONAL = 7;
635 const int BITWISE_OR = 8; 634 const int BITWISE_OR = 8;
636 const int BITWISE_XOR = 9; 635 const int BITWISE_XOR = 9;
637 const int BITWISE_AND = 10; 636 const int BITWISE_AND = 10;
638 const int SHIFT = 11; 637 const int SHIFT = 11;
639 const int ADDITIVE = 12; 638 const int ADDITIVE = 12;
640 const int MULTIPLICATIVE = 13; 639 const int MULTIPLICATIVE = 13;
641 const int UNARY = 14; 640 const int UNARY = 14;
642 const int POSTFIX_INCREMENT = 15; 641 const int POSTFIX_INCREMENT = 15;
643 const int TYPE_LITERAL = 19; 642 const int TYPE_LITERAL = 19;
644 const int PRIMARY = 20; 643 const int PRIMARY = 20;
645 644
646 /// Precedence level required for the callee in a [FunctionCall]. 645 /// Precedence level required for the callee in a [FunctionCall].
647 const int CALLEE = 21; 646 const int CALLEE = 21;
648 647
649 const Map<String,int> BINARY_PRECEDENCE = const { 648 const Map<String, int> BINARY_PRECEDENCE = const {
650 '&&': LOGICAL_AND, 649 '&&': LOGICAL_AND,
651 '||': LOGICAL_OR, 650 '||': LOGICAL_OR,
652
653 '==': EQUALITY, 651 '==': EQUALITY,
654 '!=': EQUALITY, 652 '!=': EQUALITY,
655
656 '>': RELATIONAL, 653 '>': RELATIONAL,
657 '>=': RELATIONAL, 654 '>=': RELATIONAL,
658 '<': RELATIONAL, 655 '<': RELATIONAL,
659 '<=': RELATIONAL, 656 '<=': RELATIONAL,
660
661 '|': BITWISE_OR, 657 '|': BITWISE_OR,
662 '^': BITWISE_XOR, 658 '^': BITWISE_XOR,
663 '&': BITWISE_AND, 659 '&': BITWISE_AND,
664
665 '>>': SHIFT, 660 '>>': SHIFT,
666 '<<': SHIFT, 661 '<<': SHIFT,
667
668 '+': ADDITIVE, 662 '+': ADDITIVE,
669 '-': ADDITIVE, 663 '-': ADDITIVE,
670
671 '*': MULTIPLICATIVE, 664 '*': MULTIPLICATIVE,
672 '%': MULTIPLICATIVE, 665 '%': MULTIPLICATIVE,
673 '/': MULTIPLICATIVE, 666 '/': MULTIPLICATIVE,
674 '~/': MULTIPLICATIVE, 667 '~/': MULTIPLICATIVE,
675 }; 668 };
676 669
677 /// Return true if binary operators with the given precedence level are 670 /// Return true if binary operators with the given precedence level are
678 /// (left) associative. False if they are non-associative. 671 /// (left) associative. False if they are non-associative.
679 bool isAssociativeBinaryOperator(int precedence) { 672 bool isAssociativeBinaryOperator(int precedence) {
680 return precedence != EQUALITY && precedence != RELATIONAL; 673 return precedence != EQUALITY && precedence != RELATIONAL;
681 } 674 }
682 675
683 /// True if [x] is a letter, digit, or underscore. 676 /// True if [x] is a letter, digit, or underscore.
684 /// Such characters may not follow a shorthand string interpolation. 677 /// Such characters may not follow a shorthand string interpolation.
685 bool isIdentifierPartNoDollar(dynamic x) { 678 bool isIdentifierPartNoDollar(dynamic x) {
686 if (x is! int) { 679 if (x is! int) {
687 return false; 680 return false;
688 } 681 }
689 return (characters.$0 <= x && x <= characters.$9) || 682 return (characters.$0 <= x && x <= characters.$9) ||
690 (characters.$A <= x && x <= characters.$Z) || 683 (characters.$A <= x && x <= characters.$Z) ||
691 (characters.$a <= x && x <= characters.$z) || 684 (characters.$a <= x && x <= characters.$z) ||
692 (x == characters.$_); 685 (x == characters.$_);
693 } 686 }
694 687
695 /// The unparser will apply the following syntactic rewritings: 688 /// The unparser will apply the following syntactic rewritings:
696 /// Use short-hand function returns: 689 /// Use short-hand function returns:
697 /// foo(){return E} ==> foo() => E; 690 /// foo(){return E} ==> foo() => E;
698 /// Remove empty else branch: 691 /// Remove empty else branch:
699 /// if (E) S else ; ==> if (E) S 692 /// if (E) S else ; ==> if (E) S
700 /// Flatten nested blocks: 693 /// Flatten nested blocks:
701 /// {S; {S; S}; S} ==> {S; S; S; S} 694 /// {S; {S; S}; S} ==> {S; S; S; S}
702 /// Remove empty statements from block: 695 /// Remove empty statements from block:
(...skipping 17 matching lines...) Expand all
720 /// 713 ///
721 /// The following transformations might be applied here in the future: 714 /// The following transformations might be applied here in the future:
722 /// Use implicit dynamic types: 715 /// Use implicit dynamic types:
723 /// dynamic x = E ==> var x = E 716 /// dynamic x = E ==> var x = E
724 /// <dynamic>[] ==> [] 717 /// <dynamic>[] ==> []
725 class Unparser { 718 class Unparser {
726 StringSink output; 719 StringSink output;
727 720
728 Unparser(this.output); 721 Unparser(this.output);
729 722
730
731 void write(String s) { 723 void write(String s) {
732 output.write(s); 724 output.write(s);
733 } 725 }
734 726
735 /// Outputs each element from [items] separated by [separator]. 727 /// Outputs each element from [items] separated by [separator].
736 /// The actual printing must be performed by the [callback]. 728 /// The actual printing must be performed by the [callback].
737 void writeEach(String separator, Iterable items, void callback(any)) { 729 void writeEach(String separator, Iterable items, void callback(any)) {
738 bool first = true; 730 bool first = true;
739 for (var x in items) { 731 for (var x in items) {
740 if (first) { 732 if (first) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 771
780 /// Prints the expression [e]. 772 /// Prints the expression [e].
781 void writeExpression(Expression e) { 773 void writeExpression(Expression e) {
782 writeExp(e, EXPRESSION); 774 writeExp(e, EXPRESSION);
783 } 775 }
784 776
785 /// Prints [e] as an expression with precedence of at least [minPrecedence], 777 /// Prints [e] as an expression with precedence of at least [minPrecedence],
786 /// using parentheses if necessary to raise the precedence level. 778 /// using parentheses if necessary to raise the precedence level.
787 /// Abusing terminology slightly, the function accepts a [Receiver] which 779 /// Abusing terminology slightly, the function accepts a [Receiver] which
788 /// may also be the [SuperReceiver] object. 780 /// may also be the [SuperReceiver] object.
789 void writeExp(Receiver e, int minPrecedence, {beginStmt:false}) { 781 void writeExp(Receiver e, int minPrecedence, {beginStmt: false}) {
790 void withPrecedence(int actual, void action()) { 782 void withPrecedence(int actual, void action()) {
791 if (actual < minPrecedence) { 783 if (actual < minPrecedence) {
792 write("("); 784 write("(");
793 beginStmt = false; 785 beginStmt = false;
794 action(); 786 action();
795 write(")"); 787 write(")");
796 } else { 788 } else {
797 action(); 789 action();
798 } 790 }
799 } 791 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 write(' ? '); 827 write(' ? ');
836 writeExp(e.thenExpression, EXPRESSION); 828 writeExp(e.thenExpression, EXPRESSION);
837 write(' : '); 829 write(' : ');
838 writeExp(e.elseExpression, EXPRESSION); 830 writeExp(e.elseExpression, EXPRESSION);
839 }); 831 });
840 } else if (e is Identifier) { 832 } else if (e is Identifier) {
841 write(e.name); 833 write(e.name);
842 } else if (e is Literal) { 834 } else if (e is Literal) {
843 if (e.value.isString) { 835 if (e.value.isString) {
844 writeStringLiteral(e); 836 writeStringLiteral(e);
845 } 837 } else if (e.value.isDouble) {
846 else if (e.value.isDouble) {
847 double v = e.value.primitiveValue; 838 double v = e.value.primitiveValue;
848 if (v == double.INFINITY) { 839 if (v == double.INFINITY) {
849 withPrecedence(MULTIPLICATIVE, () { 840 withPrecedence(MULTIPLICATIVE, () {
850 write('1/0.0'); 841 write('1/0.0');
851 }); 842 });
852 } else if (v == double.NEGATIVE_INFINITY) { 843 } else if (v == double.NEGATIVE_INFINITY) {
853 withPrecedence(MULTIPLICATIVE, () { 844 withPrecedence(MULTIPLICATIVE, () {
854 write('-1/0.0'); 845 write('-1/0.0');
855 }); 846 });
856 } else if (v.isNaN) { 847 } else if (v.isNaN) {
(...skipping 11 matching lines...) Expand all
868 write(' const '); 859 write(' const ');
869 } 860 }
870 if (e.typeArgument != null) { 861 if (e.typeArgument != null) {
871 write('<'); 862 write('<');
872 writeType(e.typeArgument); 863 writeType(e.typeArgument);
873 write('>'); 864 write('>');
874 } 865 }
875 write('['); 866 write('[');
876 writeEach(',', e.values, writeExpression); 867 writeEach(',', e.values, writeExpression);
877 write(']'); 868 write(']');
878 } 869 } else if (e is LiteralMap) {
879 else if (e is LiteralMap) {
880 // The curly brace can be mistaken for a block statement if we 870 // The curly brace can be mistaken for a block statement if we
881 // are at the beginning of a statement. 871 // are at the beginning of a statement.
882 bool needParen = beginStmt; 872 bool needParen = beginStmt;
883 if (e.isConst) { 873 if (e.isConst) {
884 write(' const '); 874 write(' const ');
885 needParen = false; 875 needParen = false;
886 } 876 }
887 if (e.typeArguments.length > 0) { 877 if (e.typeArguments.length > 0) {
888 write('<'); 878 write('<');
889 writeEach(',', e.typeArguments, writeType); 879 writeEach(',', e.typeArguments, writeType);
(...skipping 23 matching lines...) Expand all
913 } else if (e is ReifyTypeVar) { 903 } else if (e is ReifyTypeVar) {
914 withPrecedence(PRIMARY, () { 904 withPrecedence(PRIMARY, () {
915 write(e.name); 905 write(e.name);
916 }); 906 });
917 } else if (e is StringConcat) { 907 } else if (e is StringConcat) {
918 writeStringLiteral(e); 908 writeStringLiteral(e);
919 } else if (e is UnaryOperator) { 909 } else if (e is UnaryOperator) {
920 Receiver operand = e.operand; 910 Receiver operand = e.operand;
921 // !(x == y) ==> x != y. 911 // !(x == y) ==> x != y.
922 if (e.operatorName == '!' && 912 if (e.operatorName == '!' &&
923 operand is BinaryOperator && operand.operator == '==') { 913 operand is BinaryOperator &&
914 operand.operator == '==') {
924 withPrecedence(EQUALITY, () { 915 withPrecedence(EQUALITY, () {
925 writeExp(operand.left, RELATIONAL); 916 writeExp(operand.left, RELATIONAL);
926 writeOperator('!='); 917 writeOperator('!=');
927 writeExp(operand.right, RELATIONAL); 918 writeExp(operand.right, RELATIONAL);
928 }); 919 });
929 } 920 }
930 // !(x is T) ==> x is!T 921 // !(x is T) ==> x is!T
931 else if (e.operatorName == '!' && 922 else if (e.operatorName == '!' &&
932 operand is TypeOperator && operand.operator == 'is') { 923 operand is TypeOperator &&
924 operand.operator == 'is') {
933 withPrecedence(RELATIONAL, () { 925 withPrecedence(RELATIONAL, () {
934 writeExp(operand.expression, BITWISE_OR, beginStmt: beginStmt); 926 writeExp(operand.expression, BITWISE_OR, beginStmt: beginStmt);
935 write(' is!'); 927 write(' is!');
936 writeType(operand.type); 928 writeType(operand.type);
937 }); 929 });
938 } 930 } else {
939 else {
940 withPrecedence(UNARY, () { 931 withPrecedence(UNARY, () {
941 writeOperator(e.operatorName); 932 writeOperator(e.operatorName);
942 writeExp(e.operand, UNARY); 933 writeExp(e.operand, UNARY);
943 }); 934 });
944 } 935 }
945 } else if (e is BinaryOperator) { 936 } else if (e is BinaryOperator) {
946 int precedence = BINARY_PRECEDENCE[e.operator]; 937 int precedence = BINARY_PRECEDENCE[e.operator];
947 withPrecedence(precedence, () { 938 withPrecedence(precedence, () {
948 // All binary operators are left-associative or non-associative. 939 // All binary operators are left-associative or non-associative.
949 // For each operand, we use either the same precedence level as 940 // For each operand, we use either the same precedence level as
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 } else if (stmt is Continue) { 1084 } else if (stmt is Continue) {
1094 write('continue'); 1085 write('continue');
1095 if (stmt.label != null) { 1086 if (stmt.label != null) {
1096 write(' '); 1087 write(' ');
1097 write(stmt.label); 1088 write(stmt.label);
1098 } 1089 }
1099 write(';'); 1090 write(';');
1100 } else if (stmt is EmptyStatement) { 1091 } else if (stmt is EmptyStatement) {
1101 write(';'); 1092 write(';');
1102 } else if (stmt is ExpressionStatement) { 1093 } else if (stmt is ExpressionStatement) {
1103 writeExp(stmt.expression, EXPRESSION, beginStmt:true); 1094 writeExp(stmt.expression, EXPRESSION, beginStmt: true);
1104 write(';'); 1095 write(';');
1105 } else if (stmt is For) { 1096 } else if (stmt is For) {
1106 write('for('); 1097 write('for(');
1107 Node init = stmt.initializer; 1098 Node init = stmt.initializer;
1108 if (init is Expression) { 1099 if (init is Expression) {
1109 writeExp(init, EXPRESSION); 1100 writeExp(init, EXPRESSION);
1110 } else if (init is VariableDeclarations) { 1101 } else if (init is VariableDeclarations) {
1111 writeVariableDefinitions(init); 1102 writeVariableDefinitions(init);
1112 } 1103 }
1113 write(';'); 1104 write(';');
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 } 1230 }
1240 } else { 1231 } else {
1241 throw "Unexpected statement: $stmt"; 1232 throw "Unexpected statement: $stmt";
1242 } 1233 }
1243 } 1234 }
1244 1235
1245 /// Writes a variable definition statement without the trailing semicolon 1236 /// Writes a variable definition statement without the trailing semicolon
1246 void writeVariableDefinitions(VariableDeclarations vds) { 1237 void writeVariableDefinitions(VariableDeclarations vds) {
1247 if (vds.isConst) 1238 if (vds.isConst)
1248 write('const '); 1239 write('const ');
1249 else if (vds.isFinal) 1240 else if (vds.isFinal) write('final ');
1250 write('final ');
1251 if (vds.type != null) { 1241 if (vds.type != null) {
1252 writeType(vds.type); 1242 writeType(vds.type);
1253 write(' '); 1243 write(' ');
1254 } 1244 }
1255 if (!vds.isConst && !vds.isFinal && vds.type == null) { 1245 if (!vds.isConst && !vds.isFinal && vds.type == null) {
1256 write('var '); 1246 write('var ');
1257 } 1247 }
1258 writeEach(',', vds.declarations, (VariableDeclaration vd) { 1248 writeEach(',', vds.declarations, (VariableDeclaration vd) {
1259 write(vd.name); 1249 write(vd.name);
1260 if (vd.initializer != null) { 1250 if (vd.initializer != null) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 write('<'); 1290 write('<');
1301 writeEach(',', type.typeArguments, writeType); 1291 writeEach(',', type.typeArguments, writeType);
1302 write('>'); 1292 write('>');
1303 } 1293 }
1304 } 1294 }
1305 1295
1306 /// A list of string quotings that the printer may use to quote strings. 1296 /// A list of string quotings that the printer may use to quote strings.
1307 // Ignore multiline quotings for now. Would need to make sure that no 1297 // Ignore multiline quotings for now. Would need to make sure that no
1308 // newline (potentially prefixed by whitespace) follows the quoting. 1298 // newline (potentially prefixed by whitespace) follows the quoting.
1309 static const _QUOTINGS = const <tree.StringQuoting>[ 1299 static const _QUOTINGS = const <tree.StringQuoting>[
1310 const tree.StringQuoting(characters.$DQ, raw: false, leftQuoteLength: 1), 1300 const tree.StringQuoting(characters.$DQ, raw: false, leftQuoteLength: 1),
1311 const tree.StringQuoting(characters.$DQ, raw: true, leftQuoteLength: 1), 1301 const tree.StringQuoting(characters.$DQ, raw: true, leftQuoteLength: 1),
1312 const tree.StringQuoting(characters.$SQ, raw: false, leftQuoteLength: 1), 1302 const tree.StringQuoting(characters.$SQ, raw: false, leftQuoteLength: 1),
1313 const tree.StringQuoting(characters.$SQ, raw: true, leftQuoteLength: 1), 1303 const tree.StringQuoting(characters.$SQ, raw: true, leftQuoteLength: 1),
1314 ]; 1304 ];
1315 1305
1316 static StringLiteralOutput analyzeStringLiteral(Expression node) { 1306 static StringLiteralOutput analyzeStringLiteral(Expression node) {
1317 // Flatten the StringConcat tree. 1307 // Flatten the StringConcat tree.
1318 List parts = []; // Expression or int (char node) 1308 List parts = []; // Expression or int (char node)
1319 void collectParts(Expression e) { 1309 void collectParts(Expression e) {
1320 if (e is StringConcat) { 1310 if (e is StringConcat) {
1321 e.expressions.forEach(collectParts); 1311 e.expressions.forEach(collectParts);
1322 } else if (e is Literal && e.value.isString) { 1312 } else if (e is Literal && e.value.isString) {
1323 for (int char in e.value.primitiveValue) { 1313 for (int char in e.value.primitiveValue) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 } else { 1354 } else {
1365 nonRaws.add(index); 1355 nonRaws.add(index);
1366 } 1356 }
1367 if (q.quote == characters.$SQ) { 1357 if (q.quote == characters.$SQ) {
1368 sqs.add(index); 1358 sqs.add(index);
1369 } else { 1359 } else {
1370 dqs.add(index); 1360 dqs.add(index);
1371 } 1361 }
1372 } 1362 }
1373 1363
1374
1375 /// Applies additional cost to each track in [penalized], and considers 1364 /// Applies additional cost to each track in [penalized], and considers
1376 /// switching from each [penalized] to a [nonPenalized] track. 1365 /// switching from each [penalized] to a [nonPenalized] track.
1377 void penalize(List<int> penalized, 1366 void penalize(List<int> penalized, List<int> nonPenalized, int endIndex,
1378 List<int> nonPenalized, 1367 num cost(tree.StringQuoting q)) {
1379 int endIndex,
1380 num cost(tree.StringQuoting q)) {
1381 for (int j in penalized) { 1368 for (int j in penalized) {
1382 // Check if another track can benefit from switching from this track. 1369 // Check if another track can benefit from switching from this track.
1383 for (int k in nonPenalized) { 1370 for (int k in nonPenalized) {
1384 num newCost = best[j].cost 1371 num newCost = best[j].cost +
1385 + 1 // Whitespace in string juxtaposition 1372 1 // Whitespace in string juxtaposition
1386 + getQuoteCost(best[k].quoting); 1373 +
1374 getQuoteCost(best[k].quoting);
1387 if (newCost < best[k].cost) { 1375 if (newCost < best[k].cost) {
1388 best[k] = new OpenStringChunk( 1376 best[k] = new OpenStringChunk(
1389 best[j].end(endIndex), 1377 best[j].end(endIndex), best[k].quoting, newCost);
1390 best[k].quoting,
1391 newCost);
1392 } 1378 }
1393 } 1379 }
1394 best[j].cost += cost(best[j].quoting); 1380 best[j].cost += cost(best[j].quoting);
1395 } 1381 }
1396 } 1382 }
1397 1383
1398 // Iterate through the string and update the score for each StringQuoting. 1384 // Iterate through the string and update the score for each StringQuoting.
1399 for (int i = 0; i < parts.length; i++) { 1385 for (int i = 0; i < parts.length; i++) {
1400 var part = parts[i]; 1386 var part = parts[i];
1401 if (part is int) { 1387 if (part is int) {
(...skipping 24 matching lines...) Expand all
1426 penalize(raws, nonRaws, i, (q) => double.INFINITY); 1412 penalize(raws, nonRaws, i, (q) => double.INFINITY);
1427 1413
1428 // Splitting a string can sometimes allow us to use a shorthand 1414 // Splitting a string can sometimes allow us to use a shorthand
1429 // string interpolation that would otherwise be illegal. 1415 // string interpolation that would otherwise be illegal.
1430 // E.g. "...${foo}x..." -> "...$foo" 'x...' 1416 // E.g. "...${foo}x..." -> "...$foo" 'x...'
1431 // If are other factors that make splitting advantageous, 1417 // If are other factors that make splitting advantageous,
1432 // we can gain even more by doing the split here. 1418 // we can gain even more by doing the split here.
1433 if (part is Identifier && 1419 if (part is Identifier &&
1434 !part.name.contains(r'$') && 1420 !part.name.contains(r'$') &&
1435 i + 1 < parts.length && 1421 i + 1 < parts.length &&
1436 isIdentifierPartNoDollar(parts[i+1])) { 1422 isIdentifierPartNoDollar(parts[i + 1])) {
1437 for (int j in nonRaws) { 1423 for (int j in nonRaws) {
1438 for (int k = 0; k < best.length; k++) { 1424 for (int k = 0; k < best.length; k++) {
1439 num newCost = best[j].cost 1425 num newCost = best[j].cost +
1440 + 1 // Whitespace in string juxtaposition 1426 1 // Whitespace in string juxtaposition
1441 - 2 // Save two curly braces 1427 -
1442 + getQuoteCost(best[k].quoting); 1428 2 // Save two curly braces
1429 +
1430 getQuoteCost(best[k].quoting);
1443 if (newCost < best[k].cost) { 1431 if (newCost < best[k].cost) {
1444 best[k] = new OpenStringChunk( 1432 best[k] = new OpenStringChunk(
1445 best[j].end(i+1), 1433 best[j].end(i + 1), best[k].quoting, newCost);
1446 best[k].quoting,
1447 newCost);
1448 } 1434 }
1449 } 1435 }
1450 } 1436 }
1451 } 1437 }
1452 } 1438 }
1453 } 1439 }
1454 1440
1455 // Select the cheapest strategy 1441 // Select the cheapest strategy
1456 OpenStringChunk bestChunk = best[0]; 1442 OpenStringChunk bestChunk = best[0];
1457 for (OpenStringChunk chunk in best) { 1443 for (OpenStringChunk chunk in best) {
(...skipping 16 matching lines...) Expand all
1474 startIndex = chunk.previous.endIndex; 1460 startIndex = chunk.previous.endIndex;
1475 } else { 1461 } else {
1476 startIndex = 0; 1462 startIndex = 0;
1477 } 1463 }
1478 if (chunk.quoting.raw) { 1464 if (chunk.quoting.raw) {
1479 write('r'); 1465 write('r');
1480 } 1466 }
1481 write(chunk.quoting.quoteChar); 1467 write(chunk.quoting.quoteChar);
1482 bool raw = chunk.quoting.raw; 1468 bool raw = chunk.quoting.raw;
1483 int quoteCode = chunk.quoting.quote; 1469 int quoteCode = chunk.quoting.quote;
1484 for (int i=startIndex; i<chunk.endIndex; i++) { 1470 for (int i = startIndex; i < chunk.endIndex; i++) {
1485 var part = parts[i]; 1471 var part = parts[i];
1486 if (part is int) { 1472 if (part is int) {
1487 int char = part; 1473 int char = part;
1488 write(getEscapedCharacter(char, quoteCode, raw)); 1474 write(getEscapedCharacter(char, quoteCode, raw));
1489 } else if (part is Identifier && 1475 } else if (part is Identifier &&
1490 !part.name.contains(r'$') && 1476 !part.name.contains(r'$') &&
1491 (i == chunk.endIndex - 1 || 1477 (i == chunk.endIndex - 1 ||
1492 !isIdentifierPartNoDollar(parts[i+1]))) { 1478 !isIdentifierPartNoDollar(parts[i + 1]))) {
1493 write(r'$'); 1479 write(r'$');
1494 write(part.name); 1480 write(part.name);
1495 } else { 1481 } else {
1496 write(r'${'); 1482 write(r'${');
1497 writeExpression(part); 1483 writeExpression(part);
1498 write('}'); 1484 write('}');
1499 } 1485 }
1500 } 1486 }
1501 write(chunk.quoting.quoteChar); 1487 write(chunk.quoting.quoteChar);
1502 } 1488 }
(...skipping 21 matching lines...) Expand all
1524 case characters.$TAB: 1510 case characters.$TAB:
1525 return r'\t'; 1511 return r'\t';
1526 case characters.$VTAB: 1512 case characters.$VTAB:
1527 return r'\v'; 1513 return r'\v';
1528 case characters.$EOF: 1514 case characters.$EOF:
1529 return r'\x00'; 1515 return r'\x00';
1530 default: 1516 default:
1531 return new String.fromCharCode(char); 1517 return new String.fromCharCode(char);
1532 } 1518 }
1533 } 1519 }
1534
1535 } 1520 }
1536 1521
1537 /// The contents of a string literal together with a strategy for printing it. 1522 /// The contents of a string literal together with a strategy for printing it.
1538 class StringLiteralOutput { 1523 class StringLiteralOutput {
1539 /// Mix of [Expression] and `int`. Each expression is a string interpolation, 1524 /// Mix of [Expression] and `int`. Each expression is a string interpolation,
1540 /// and each `int` is the character code of a character in a string literal. 1525 /// and each `int` is the character code of a character in a string literal.
1541 final List parts; 1526 final List parts;
1542 final StringChunk chunk; 1527 final StringChunk chunk;
1543 1528
1544 StringLiteralOutput(this.parts, this.chunk); 1529 StringLiteralOutput(this.parts, this.chunk);
1545 } 1530 }
1546 1531
1547
1548 /// Strategy for printing a prefix of a string literal. 1532 /// Strategy for printing a prefix of a string literal.
1549 /// A chunk represents the substring going from [:previous.endIndex:] to 1533 /// A chunk represents the substring going from [:previous.endIndex:] to
1550 /// [endIndex] (or from 0 to [endIndex] if [previous] is null). 1534 /// [endIndex] (or from 0 to [endIndex] if [previous] is null).
1551 class StringChunk { 1535 class StringChunk {
1552 final StringChunk previous; 1536 final StringChunk previous;
1553 final tree.StringQuoting quoting; 1537 final tree.StringQuoting quoting;
1554 final int endIndex; 1538 final int endIndex;
1555 1539
1556 StringChunk(this.previous, this.quoting, this.endIndex); 1540 StringChunk(this.previous, this.quoting, this.endIndex);
1557 } 1541 }
1558 1542
1559 /// [StringChunk] that has not yet been assigned an [endIndex]. 1543 /// [StringChunk] that has not yet been assigned an [endIndex].
1560 /// It additionally has a [cost] denoting the number of auxilliary characters 1544 /// It additionally has a [cost] denoting the number of auxilliary characters
1561 /// (quotes, spaces, etc) needed to print the literal using this strategy 1545 /// (quotes, spaces, etc) needed to print the literal using this strategy
1562 class OpenStringChunk { 1546 class OpenStringChunk {
1563 final StringChunk previous; 1547 final StringChunk previous;
1564 final tree.StringQuoting quoting; 1548 final tree.StringQuoting quoting;
1565 num cost; 1549 num cost;
1566 1550
1567 OpenStringChunk(this.previous, this.quoting, this.cost); 1551 OpenStringChunk(this.previous, this.quoting, this.cost);
1568 1552
1569 StringChunk end(int endIndex) { 1553 StringChunk end(int endIndex) {
1570 return new StringChunk(previous, quoting, endIndex); 1554 return new StringChunk(previous, quoting, endIndex);
1571 } 1555 }
1572 } 1556 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698