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

Side by Side Diff: tests/compiler/dart2js/dart_printer_test.dart

Issue 250523003: dart2dart backend: AST and unparser for backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 library dart_printer_test;
2
3 import '../../../sdk/lib/_internal/compiler/implementation/dart_backend/dart_pri nter.dart';
4 import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.da rt';
5 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
6 import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart';
7 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart' show DartString;
8 import 'dart:mirrors';
9 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart' as tr ee;
10 import '../../../sdk/lib/_internal/compiler/implementation/string_validator.dart ';
11
12 /// For debugging the [AstBuilder] stack. Prints information about [x].
13 void show(x) {
14 StringBuffer buf = new StringBuffer();
15 Unparser unparser = new Unparser(buf);
16 void unparse(x) {
17 if (x is Expression)
18 unparser.writeExpression(x);
19 else if (x is TypeAnnotation)
20 unparser.writeType(x);
21 else if (x is Statement)
22 unparser.writeStatement(x);
23 else if (x is List) {
24 buf.write('[');
25 bool first = true;
26 for (var y in x) {
27 if (first)
28 first = false;
29 else
30 buf.write(', ');
31 unparse(y);
32 }
33 buf.write(']');
34 }
35 }
36 unparse(x);
37 print("${x.runtimeType}: ${buf.toString()}");
38 }
39
40 class PrintDiagnosticListener implements DiagnosticListener {
41 void log(message) {
42 print(message);
43 }
44
45 void internalError(Spannable spannable, message) {
46 print(message);
47 }
48
49 SourceSpan spanFromSpannable(Spannable node) {
50 return new SourceSpan(null, 0, 0);
51 }
52
53 void reportFatalError(Spannable node, MessageKind errorCode,
54 [Map arguments = const {}]) {
55 print(errorCode);
56 throw new Error();
57 }
58
59 void reportError(Spannable node, MessageKind errorCode,
60 [Map arguments = const {}]) {
61 print(errorCode);
62 }
63
64 void reportWarning(Spannable node, MessageKind errorCode,
65 [Map arguments = const {}]) {
66 print(errorCode);
67 }
68
69 void reportHint(Spannable node, MessageKind errorCode,
70 [Map arguments = const {}]) {
71 print(errorCode);
72 }
73
74 void reportInfo(Spannable node, MessageKind errorCode,
75 [Map arguments = const {}]) {
76 print(errorCode);
77 }
78
79 withCurrentElement(element, f()) {
80 f();
81 }
82 }
83
84 class AstBuilder extends Listener {
85 final List stack = [];
86 final StringValidator stringValidator
87 = new StringValidator(new PrintDiagnosticListener());
88
89 String asName(e) {
90 if (e is Identifier)
91 return e.name;
92 else if (e == null)
93 return null;
94 else
95 throw 'Expression is not a name: ${e.runtimeType}';
96 }
97
98 TypeAnnotation asType(x) {
99 if (x is TypeAnnotation)
100 return x;
101 if (x is Identifier)
102 return new TypeAnnotation(x.name);
103 if (x == null)
104 return null;
105 else
106 throw "Not a type: ${x.runtimeType}";
107 }
108
109 Parameter asParameter(x) {
110 if (x is Parameter)
111 return x;
112 if (x is Identifier)
113 return new Parameter(x.name);
114 else
115 throw "Not a parameter: ${x.runtimeType}";
116 }
117
118 void push(node) {
119 stack.add(node);
120 }
121 dynamic peek() {
122 return stack.last;
123 }
124 dynamic pop([coerce(x) = null]) {
125 var x = stack.removeLast();
126 if (coerce != null)
127 return coerce(x);
128 else
129 return x;
130 }
131 List popList(int count, [List result, coerce(x) = null]) {
132 if (result == null)
133 result = <Node>[];
134 for (int i=0; i<count; i++) {
135 var x = stack[stack.length-count+i];
136 if (coerce != null) {
137 x = coerce(x);
138 }
139 result.add(x);
140 }
141 stack.removeRange(stack.length-count, stack.length);
142 return result;
143 }
144 popTypeAnnotation() {
145 List<TypeAnnotation> args = pop();
146 if (args == null)
147 return null;
148 String name = pop(asName);
149 return new TypeAnnotation(name, args);
150 }
151
152 // EXPRESSIONS
153 endCascade() {
154 throw "Cascade not supported yet";
155 }
156 endIdentifierList(int count) {
157 push(popList(count, <Identifier>[]));
158 }
159 endTypeList(int count) {
160 push(popList(count, <TypeAnnotation>[], asType));
161 }
162 beginLiteralString(Token token) {
163 String source = token.value;
164 tree.StringQuoting quoting = StringValidator.quotingFromString(source);
165 push(quoting);
166 push(token); // collect token at the end
167 }
168 handleStringPart(Token token) {
169 push(token); // collect token at the end
170 }
171 endLiteralString(int interpCount) {
172 List parts = popList(2 * interpCount + 1, []);
173 tree.StringQuoting quoting = pop();
174 List<Expression> members = <Expression>[];
175 for (var i=0; i<parts.length; i++) {
176 var part = parts[i];
177 if (part is Expression) {
178 members.add(part);
179 } else {
180 assert(part is Token);
181 DartString str = stringValidator.validateInterpolationPart(
182 part as Token,
183 quoting,
184 isFirst: i == 0,
185 isLast: i == parts.length - 1);
186 members.add(new Literal(new StringConstant(str)));
187 }
188 }
189 push(new StringConcat(members));
190 }
191 handleStringJuxtaposition(int litCount) {
192 push(new StringConcat(popList(litCount, <Expression>[])));
193 }
194 endArguments(int count, begin, end) {
195 push(popList(count, <Argument>[]));
196 }
197 handleNoArguments(token) {
198 push(null);
199 }
200 handleNoTypeArguments(token) {
201 push(<TypeAnnotation>[]);
202 }
203 endTypeArguments(int count, t, y) {
204 List<TypeAnnotation> args = <TypeAnnotation>[];
205 for (var i=0; i<count; i++) {
206 args.add(popTypeAnnotation());
207 }
208 push(args.reversed.toList(growable:false));
209 }
210 handleVoidKeyword(token) {
211 push(new Identifier("void"));
212 push(<TypeAnnotation>[]); // prepare for popTypeAnnotation
213 }
214 handleQualified(Token period) {
215 String last = pop(asName);
216 String first = pop(asName);
217 push(new Identifier('$first.$last'));
218 }
219 endSend(t) {
220 List<Argument> arguments = pop();
221 if (arguments == null)
222 return; // not a function call
223 Expression selector = pop();
224 push(new CallFunction(selector, arguments));
225 }
226 endThrowExpression(t, tt) {
227 push(new Throw(pop()));
228 }
229 handleAssignmentExpression(Token token) {
230 Expression right = pop();
231 Expression left = pop();
232 push(new Assignment(left, token.value, right));
233 }
234 handleBinaryExpression(Token token) {
235 Expression right = pop();
236 Receiver left = pop();
237 String tokenString = token.stringValue;
238 if (tokenString == '.') {
239 if (right is CallFunction) {
240 String name = (right.callee as Identifier).name;
241 push(new CallMethod(left, name, right.arguments));
242 } else {
243 push(new FieldExpression(left, (right as Identifier).name));
244 }
245 } else {
246 push(new BinaryOperator(left, tokenString, right));
247 }
248 }
249 handleConditionalExpression(question, colon) {
250 Expression elseExpression = pop();
251 Expression thenExpression = pop();
252 Expression condition = pop();
253 push(new Conditional(condition, thenExpression, elseExpression));
254 }
255 handleIdentifier(Token t) {
256 push(new Identifier(t.value));
257 }
258 handleOperator(t) {
259 push(new Identifier(t.value));
260 }
261 handleIndexedExpression(open, close) {
262 Expression index = pop();
263 Receiver object = pop();
264 push(new IndexExpression(object, index));
265 }
266 handleIsOperator(operathor, not, endToken) {
267 TypeAnnotation type = popTypeAnnotation();
268 Expression exp = pop();
269 TypeOperator r = new TypeOperator(exp, 'is', type);
270 if (not != null) {
271 push(new UnaryOperator('!', r));
272 } else {
273 push(r);
274 }
275 }
276 handleAsOperator(operathor, endToken) {
277 TypeAnnotation type = popTypeAnnotation();
278 Expression exp = pop();
279 push(new TypeOperator(exp, 'as', type));
280 }
281 handleLiteralBool(Token t) {
282 bool value = t.value == 'true';
283 push(new Literal(value ? new TrueConstant() : new FalseConstant()));
284 }
285 handleLiteralDouble(t) {
286 push(new Literal(new DoubleConstant(double.parse(t.value))));
287 }
288 handleLiteralInt(Token t) {
289 push(new Literal(new IntConstant(int.parse(t.value))));
290 }
291 handleLiteralNull(t) {
292 push(new Literal(new NullConstant()));
293 }
294 endLiteralSymbol(Token hash, int idCount) {
295 List<Identifier> ids = popList(idCount, <Identifier>[]);
296 push(new LiteralSymbol(ids.map((id) => id.name).join('.')));
297 }
298 handleLiteralList(int count, begin, constKeyword, end) {
299 List<Expression> exps = popList(count, <Expression>[]);
300 List<TypeAnnotation> types = pop();
301 assert(types.length <= 1);
302 push(new LiteralList(exps,
303 isConst: constKeyword != null,
304 typeArgument: types.length == 0 ? null : types[0]
305 ));
306 }
307 handleLiteralMap(int count, begin, constKeyword, end) {
308 List<LiteralMapEntry> entries = popList(count, <LiteralMapEntry>[]);
309 List<TypeAnnotation> types = pop();
310 assert(types.length == 0 || types.length == 2);
311 push(new LiteralMap(entries,
312 isConst: constKeyword != null,
313 typeArguments: types
314 ));
315 }
316 endLiteralMapEntry(colon, endToken) {
317 Expression value = pop();
318 Expression key = pop();
319 push(new LiteralMapEntry(key,value));
320 }
321 handleNamedArgument(colon) {
322 Expression exp = pop();
323 Identifier name = pop();
324 push(new NamedArgument(name.name, exp));
325 }
326 endConstructorReference(Token start, Token period, Token end) {
327 if (period == null) {
328 push(null); // indicate missing constructor name
329 }
330 }
331 handleNewExpression(t) {
332 List<Argument> args = pop();
333 String constructorName = pop(asName);
334 TypeAnnotation type = popTypeAnnotation();
335 push(new CallNew(type, args, constructorName: constructorName));
336 }
337 handleConstExpression(t) {
338 List<Argument> args = pop();
339 String constructorName = pop(asName);
340 TypeAnnotation type = popTypeAnnotation();
341 push(new CallNew(type, args, constructorName: constructorName,
342 isConst:true));
343 }
344 handleParenthesizedExpression(t) {
345 // do nothing, just leave expression on top of stack
346 }
347 handleSuperExpression(t) {
348 push(new SuperReceiver());
349 }
350 handleThisExpression(t) {
351 push(new This());
352 }
353 handleUnaryPostfixAssignmentExpression(Token t) {
354 push(new Increment.postfix(pop(), t.value));
355 }
356 handleUnaryPrefixAssignmentExpression(Token t) {
357 push(new Increment.prefix(pop(), t.value));
358 }
359 handleUnaryPrefixExpression(Token t) {
360 push(new UnaryOperator(t.value, pop()));
361 }
362
363 handleFunctionTypedFormalParameter(tok) {
364 // handled in endFormalParameter
365 }
366 endFormalParameter(thisKeyword) {
367 Expression defaultValue = null;
368 var x = pop();
369 if (x is DefaultValue) {
370 defaultValue = x.expression;
371 x = pop();
372 }
373 if (x is Parameters) {
374 String name = pop(asName);
375 TypeAnnotation returnType = popTypeAnnotation();
376 push(new Parameter.function(name, returnType, x, defaultValue));
377 } else {
378 String name = asName(x);
379 TypeAnnotation type = popTypeAnnotation();
380 push(new Parameter(name, type:type, defaultValue:defaultValue));
381 }
382 }
383 handleValuedFormalParameter(eq, tok) {
384 push(new DefaultValue(pop()));
385 }
386 endOptionalFormalParameters(int count, begin, end) {
387 bool isNamed = end.value == '}';
388 push(popList(count, <Parameter>[], asParameter));
389 push(isNamed); // Indicate optional parameters to endFormalParameters.
390 }
391 endFormalParameters(count, begin, end) {
392 if (count == 0) {
393 push(new Parameters([]));
394 return;
395 }
396 var last = pop(); // Detect if optional parameters are present.
397 if (last is bool) { // See endOptionalFormalParameters.
398 List<Parameter> optional = pop();
399 List<Parameter> required = popList(count-1, <Parameter>[], asParameter);
400 push(new Parameters(required, optional, last));
401 } else {
402 // No optional parameters.
403 List<Parameter> required = popList(count-1, <Parameter>[], asParameter);
404 required.add(last);
405 push(new Parameters(required));
406 }
407 }
408 handleNoFormalParameters(tok) {
409 push(new Parameters([]));
410 }
411 endUnamedFunction(t) {
412 Statement body = pop();
413 Parameters parameters = pop();
414 push(new FunctionExpression(parameters, body));
415 }
416 handleNoType(Token token) {
417 push(null);
418 }
419
420 endReturnStatement(bool hasExpression, begin, end) {
421 // This is also called for functions whose body is "=> expression"
422 if (hasExpression) {
423 push(new Return(pop()));
424 } else {
425 push(new Return());
426 }
427 }
428
429 endExpressionStatement(Token token) {
430 push(new ExpressionStatement(pop()));
431 }
432
433 endDoWhileStatement(Token doKeyword, Token whileKeyword, Token end) {
434 Expression condition = pop();
435 Statement body = pop();
436 push(new DoWhile(body, condition));
437 }
438
439 endWhileStatement(Token whileKeyword, Token end) {
440 Statement body = pop();
441 Expression condition = pop();
442 push(new While(condition, body));
443 }
444
445 endBlock(int count, Token begin, Token end) {
446 push(new Block(popList(count, <Statement>[])));
447 }
448
449 endRethrowStatement(Token throwToken, Token endToken) {
450 push(new Rethrow());
451 }
452
453 endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
454 Statement finallyBlock = null;
455 if (finallyKeyword != null) {
456 finallyBlock = pop();
457 }
458 List<CatchBlock> catchBlocks = popList(catchCount, <CatchBlock>[]);
459 Statement tryBlock = pop();
460 push(new Try(tryBlock, catchBlocks, finallyBlock));
461 }
462
463 void handleCatchBlock(Token onKeyword, Token catchKeyword) {
464 Statement block = pop();
465 String exceptionVar = null;
466 String stackVar = null;
467 if (catchKeyword != null) {
468 Parameters params = pop();
469 exceptionVar = params.requiredParameters[0].name;
470 if (params.requiredParameters.length > 1) {
471 stackVar = params.requiredParameters[1].name;
472 }
473 }
474 TypeAnnotation type = onKeyword == null ? null : pop();
475 push(new CatchBlock(block,
476 onType: type,
477 exceptionVar: exceptionVar,
478 stackVar: stackVar
479 ));
480 }
481
482 endSwitchStatement(Token switchKeyword, Token end) {
483 List<SwitchCase> cases = pop();
484 Expression expression = pop();
485 push(new Switch(expression, cases));
486 }
487
488 endSwitchBlock(int caseCount, Token begin, Token end) {
489 push(popList(caseCount, <SwitchCase>[]));
490 }
491
492 handleSwitchCase(int labelCount, int caseCount, Token defaultKeyword,
493 int statementCount, Token first, Token end) {
494 List<Statement> statements = popList(statementCount, <Statement>[]);
495 List<Expression> cases = popList(caseCount, <Expression>[]);
496 if (defaultKeyword != null) {
497 cases = null;
498 }
499 push(new SwitchCase(cases, statements));
500 }
501
502 handleCaseMatch(Token caseKeyword, Token colon) {
503 // do nothing, leave case expression on stack
504 }
505
506 handleBreakStatement(bool hasTarget, Token breakKeyword, Token end) {
507 String target = hasTarget ? pop(asName) : null;
508 push(new Break(target));
509 }
510
511 handleContinueStatement(bool hasTarget, Token continueKeyword, Token end) {
512 String target = hasTarget ? pop(asName) : null;
513 push(new Continue(target));
514 }
515
516 handleEmptyStatement(Token token) {
517 push(new EmptyStatement());
518 }
519
520
521 VariableDefinition asVariableDefinition(x) {
522 if (x is VariableDefinition)
523 return x;
524 if (x is Identifier)
525 return new VariableDefinition(x.name);
526 throw "Not a variable definition: ${x.runtimeType}";
527 }
528
529 endVariablesDeclaration(int count, Token end) {
530 List<VariableDefinition> variables =
531 popList(count, <VariableDefinition>[], asVariableDefinition);
532 TypeAnnotation type = popTypeAnnotation();
533 push(new VariableDefinitions(variables,
534 type: type,
535 isFinal: false, // TODO(asgerf): Parse modifiers.
536 isConst: false
537 ));
538 }
539
540 endInitializer(Token assign) {
541 Expression init = pop();
542 String name = pop(asName);
543 push(new VariableDefinition(name, init));
544 }
545
546 endIfStatement(Token ifToken, Token elseToken) {
547 Statement elsePart = (elseToken == null) ? null : pop();
548 Statement thenPart = pop();
549 Expression condition = pop();
550 push(new If(condition, thenPart, elsePart));
551 }
552
553 endForStatement(int updateCount, Token begin, Token end) {
554 Statement body = pop();
555 List<Expression> updates = popList(updateCount, <Expression>[]);
556 ExpressionStatement condition = pop(); // parsed as expression statement
557 Expression exp = condition == null ? null : condition.expression;
558 Node initializer = pop();
559 push(new For(initializer, exp, updates, body));
560 }
561
562 handleNoExpression(Token token) {
563 push(null);
564 }
565
566 endForIn(Token begin, Token inKeyword, Token end) {
567 Statement body = pop();
568 Expression exp = pop();
569 Node declaredIdentifier = pop();
570 push(new ForIn(declaredIdentifier, exp, body));
571 }
572
573 handleAssertStatement(Token assertKeyword, Token semicolonToken) {
574 Expression exp = pop();
575 Expression call = new CallFunction(new Identifier("assert"), [exp]);
576 push(new ExpressionStatement(call));
577 }
578
579 endLabeledStatement(int labelCount) {
580 Statement statement = pop();
581 for (int i=0; i<labelCount; i++) {
582 String label = pop(asName);
583 statement = new LabeledStatement(label, statement);
584 }
585 push(statement);
586 }
587
588 endFunctionDeclaration(Token end) {
589 Statement body = pop();
590 Parameters parameters = pop();
591 String name = pop(asName);
592 TypeAnnotation returnType = popTypeAnnotation();
593 push(new FunctionStatement(name, parameters, body, returnType));
594 }
595
596 endFunctionBody(int count, Token begin, Token end) {
597 push(new Block(popList(count, <Statement>[])));
598 }
599 }
600
601 class DefaultValue {
602 final Expression expression;
603 DefaultValue(this.expression);
604 }
605
606 /// Compares ASTs for structural equality.
607 void checkDeepEqual(x, y) {
608 if (x is List && y is List) {
609 if (x.length != y.length)
610 return;
611 for (var i=0; i<x.length; i++) {
612 checkDeepEqual(x[i], y[i]);
613 }
614 }
615 else if (x is Node && y is Node) {
616 if (x.runtimeType != y.runtimeType)
617 throw new Error();
618 InstanceMirror xm = reflect(x);
619 InstanceMirror ym = reflect(y);
620 for (Symbol name in xm.type.instanceMembers.keys) {
621 if (reflectClass(Object).declarations.containsKey(name)) {
622 continue; // do not check things from Object, such as hashCode
623 }
624 MethodMirror mm = xm.type.instanceMembers[name];
625 if (mm.isGetter) {
626 var xv = xm.getField(name).reflectee;
627 var yv = ym.getField(name).reflectee;
628 checkDeepEqual(xv,yv);
629 }
630 }
631 }
632 else if (x is PrimitiveConstant && y is PrimitiveConstant) {
633 checkDeepEqual(x.value, y.value);
634 }
635 else if (x is DartString && y is DartString) {
636 if (x.slowToString() != y.slowToString()) {
637 throw new Error();
638 }
639 }
640 else {
641 if (x != y) {
642 throw new Error();
643 }
644 }
645 }
646
647 Expression parseExpression(String code) {
648 SourceFile file = new StringSourceFile('', code);
649 Scanner scan = new Scanner(file);
650 Token tok = scan.tokenize();
651 AstBuilder builder = new AstBuilder();
652 Parser parser = new Parser(builder);
653 tok = parser.parseExpression(tok);
654 if (builder.stack.length != 1 || tok.kind != EOF_TOKEN) {
655 throw "Parse error in $code";
656 }
657 return builder.pop();
658 }
659 Statement parseStatement(String code) {
660 SourceFile file = new StringSourceFile('', code);
661 Scanner scan = new Scanner(file);
662 Token tok = scan.tokenize();
663 AstBuilder builder = new AstBuilder();
664 Parser parser = new Parser(builder);
665 tok = parser.parseStatement(tok);
666 if (builder.stack.length != 1 || tok.kind != EOF_TOKEN) {
667 throw "Parse error in $code";
668 }
669 return builder.pop();
670 }
671
672 String unparseExpression(Expression exp) {
673 StringBuffer buf = new StringBuffer();
674 new Unparser(buf).writeExpression(exp);
675 return buf.toString();
676 }
677 String unparseStatement(Statement stmt) {
678 StringBuffer buf = new StringBuffer();
679 new Unparser(buf).writeStatement(stmt);
680 return buf.toString();
681 }
682
683 /// Parses [code], unparses the resulting AST, then parses the unparsed text.
684 /// The ASTs from the first and second parse are then compared for structural
685 /// equality. Alternatively, if [expected] is not an empty string, the second
686 /// parse must match the AST of parsing [expected].
687 void checkFn(String code, String expected, Function parse, Function unparse) {
688 String unparsed = "";
689 try {
690 var firstParse = parse(code);
691 unparsed = unparse(firstParse);
692 var secondParse = parse(unparsed);
693 var baseline = expected == "" ? firstParse : parse(expected);
694 checkDeepEqual(baseline, secondParse);
Kevin Millikin (Google) 2014/04/24 13:27:25 I guess this should be Expect.isTrue(checkDeepEqua
695 } catch (e, stack) {
696 print("INPUT: ${code}");
697 print("OUTPUT: ${unparsed}");
698 print("ERROR: $e");
699 if (e is! String)
700 print(stack);
701 print("-----------");
702 }
703 }
704
705 void checkExpression(String code, [String expected=""]) {
706 checkFn(code, expected, parseExpression, unparseExpression);
707 }
708 void checkStatement(String code, [String expected=""]) {
709 checkFn(code, expected, parseStatement, unparseStatement);
710 }
711
712 void debugTokens(String code) {
713 SourceFile file = new StringSourceFile('', code);
714 Scanner scan = new Scanner(file);
715 Token tok = scan.tokenize();
716 while (tok.next != tok) {
717 print(tok.toString());
718 tok = tok.next;
719 }
720 }
721
722 void main() {
723 // To check if these tests are effective, one should manually alter
724 // something in [Unparser] and see if a test fails.
725
726 checkExpression(" a + b + c");
727 checkExpression("(a + b) + c");
728 checkExpression(" a + (b + c)");
729
730 checkExpression(" a + b - c");
731 checkExpression("(a + b) - c");
732 checkExpression(" a + (b - c)");
733
734 checkExpression(" a - b + c");
735 checkExpression("(a - b) + c");
736 checkExpression(" a - (b + c)");
737
738 checkExpression(" a * b + c");
739 checkExpression("(a * b) + c");
740 checkExpression(" a * (b + c)");
741
742 checkExpression(" a + b * c");
743 checkExpression("(a + b) * c");
744 checkExpression(" a + (b * c)");
745
746 checkExpression(" a * b * c");
747 checkExpression("(a * b) * c");
748 checkExpression(" a * (b * c)");
749
750 checkExpression("a is T");
751 checkExpression("a is! T");
752 checkExpression("!(a is T)");
753
754 checkExpression("a is T.x");
755 checkExpression("a is! T.x");
756 checkExpression("!(a is T.x)");
757 checkExpression("!(a is T).x");
758
759 checkExpression("a as T.x");
760 checkExpression("(a as T).x");
761
762 checkExpression("a == b");
763 checkExpression("a != b");
764 checkExpression("!(a == b)", "a != b");
765
766 checkExpression("a && b ? c : d");
767 checkExpression("(a && b) ? c : d");
768 checkExpression("a && (b ? c : d)");
769
770 checkExpression("a || b ? c : d");
771 checkExpression("(a || b) ? c : d");
772 checkExpression("a || (b ? c : d)");
773
774 checkExpression(" a ? b : c && d");
775 checkExpression(" a ? b : (c && d)");
776 checkExpression("(a ? b : c) && d");
777
778 checkExpression(" a ? b : c = d");
779 checkExpression(" a ? b : (c = d)");
780
781 checkExpression("(a == b) == c");
782 checkExpression("a == (b == c)");
783
784 checkExpression(" a < b == c");
785 checkExpression("(a < b) == c");
786 checkExpression(" a < (b == c)");
787
788 checkExpression(" a == b < c");
789 checkExpression("(a == b) < c");
790 checkExpression(" a == (b < c)");
791
792 checkExpression("x.f()");
793 checkExpression("(x.f)()");
794
795 checkExpression("x.f()()");
796 checkExpression("(x.f)()()");
797
798 checkExpression("x.f().g()");
799 checkExpression("(x.f)().g()");
800
801 checkExpression("x.f()");
802 checkExpression("x.f(1 + 2)");
803 checkExpression("x.f(1 + 2, 3 + 4)");
804 checkExpression("x.f(1 + 2, foo:3 + 4)");
805 checkExpression("x.f(1 + 2, foo:3 + 4, bar: 5)");
806 checkExpression("x.f(foo:3 + 4)");
807 checkExpression("x.f(foo:3 + 4, bar: 5)");
808
809 checkExpression("x.f.g.h");
810 checkExpression("(x.f).g.h");
811 checkExpression("(x.f.g).h");
812
813 checkExpression(" a = b + c");
814 checkExpression(" a = (b + c)");
815 checkExpression("(a = b) + c");
816
817 checkExpression("a + (b = c)");
818
819 checkExpression("dx * dx + dy * dy < r * r",
820 "((dx * dx) + (dy * dy)) < (r * r)");
821 checkExpression("mid = left + right << 1",
822 "mid = ((left + right) << 1)");
823 checkExpression("a + b % c * -d ^ e - f ~/ x & ++y / z++ | w > a ? b : c");
824 checkExpression("a + b % c * -d ^ (e - f) ~/ x & ++y / z++ | w > a ? b : c");
825
826 checkExpression("'foo'");
827 checkExpression("'foo' 'bar'", "'foobar'");
828
829 checkExpression("{}.length");
830 checkExpression("{x: 1+2}.length");
831 checkExpression("<String,int>{}.length");
832 checkExpression("<String,int>{x: 1+2}.length");
833
834 checkExpression("[].length");
835 checkExpression("[1+2].length");
836 checkExpression("<num>[].length");
837 checkExpression("<num>[1+2].length");
838
839 checkExpression("x + -y");
840 checkExpression("x + --y");
841 checkExpression("x++ + y");
842 checkExpression("x + ++y");
843 checkExpression("x-- - y");
844 checkExpression("x-- - -y");
845 checkExpression("x - --y");
846
847 checkExpression("x && !y");
848 checkExpression("!x && y");
849 checkExpression("!(x && y)");
850
851 checkExpression(" super + 1 * 2");
852 checkExpression("(super + 1) * 2");
853 checkExpression(" super + (1 * 2)");
854 checkExpression("x + -super");
855 checkExpression("x-- - -super");
856 checkExpression("x - -super");
857 checkExpression("x && !super");
858
859 checkExpression("super.f(1, 2) + 3");
860 checkExpression("super.f + 3");
861
862 checkExpression(r"'foo\nbar'");
863 checkExpression(r"'foo\r\nbar'");
864 checkExpression(r"'foo\rbar'");
865 checkExpression(r"'foo\'bar'");
866 checkExpression(r"""'foo"bar'""");
867 checkExpression(r"r'foo\nbar'");
868 checkExpression("''");
869 checkExpression("r''");
870
871 var sq = "'";
872 var dq = '"';
873 checkExpression("'$dq$dq' \"$sq$sq\"");
874 checkExpression("'$dq$dq$dq$dq' \"$sq$sq$sq$sq\"");
875 checkExpression(r"'\$\$\$\$\$\$\$\$\$'");
876 checkExpression("'$dq$dq$dq' '\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n' \"$sq$sq$sq\"");
877 checkExpression("'$dq$dq$dq' '\\r\\r\\r\\r\\r\\r\\r\\r\\r\\r' \"$sq$sq$sq\"");
878 checkExpression("'$dq$dq$dq' '\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n' \"$sq$sq$sq\"");
879
880 checkExpression(r"'$foo'");
881 checkExpression(r"'${foo}x'");
882 checkExpression(r"'${foo}x\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'");
883 checkExpression(r"'abc' '${foo}' r'\\\\\\\'");
884
885 checkExpression(r"'${$x}'");
886 checkExpression(r"'${$x}y'");
887
888 checkStatement("var x, y, z;");
889 checkStatement("final x, y, z;");
890 checkStatement("dynamic x, y, z;");
891 checkStatement("String x, y, z;");
892 checkStatement("List<int> x, y, z;");
893 checkStatement("final dynamic x, y, z;");
894 checkStatement("final String x, y, z;");
895 checkStatement("final List<int> x, y, z;");
896
897 checkStatement("var x = y, z;");
898 checkStatement("var x, y = z;");
899 checkStatement("var x = y = z;");
900
901 // Note: We sometimes have to pass an expected string to account for
902 // block flattening which does not preserve structural AST equality
903 checkStatement("if (x) if (y) foo(); else bar(); ");
904 checkStatement("if (x) { if (y) foo(); } else bar(); ");
905 checkStatement("if (x) { if (y) foo(); else bar(); }",
906 "if (x) if (y) foo(); else bar(); ");
907
908 checkStatement("if (x) while (y) if (z) foo(); else bar(); ");
909 checkStatement("if (x) while (y) { if (z) foo(); } else bar(); ");
910 checkStatement("if (x) while (y) { if (z) foo(); else bar(); }",
911 "if (x) while (y) if (z) foo(); else bar(); ");
912
913 checkStatement("{var x = 1; {var x = 2;} return x;}");
914 checkStatement("{var x = 1; {x = 2;} return x;}",
915 "{var x = 1; x = 2; return x;}");
916
917 checkStatement("if (x) {var x = 1;}");
918
919 checkStatement("({'foo': 1}).bar();");
920 checkStatement("({'foo': 1}).length;");
921 checkStatement("({'foo': 1}).length + 1;");
922 checkStatement("({'foo': 1})['foo'].toString();");
923 checkStatement("({'foo': 1})['foo'] = 3;");
924 checkStatement("({'foo': 1}['foo']());");
925 checkStatement("({'foo': 1}['foo'])();");
926 checkStatement("({'foo': 1})['foo'].x++;");
927 checkStatement("({'foo': 1}) is Map;");
928 checkStatement("({'foo': 1}) as Map;");
929 checkStatement("({'foo': 1}) is util.Map;");
930 checkStatement("({'foo': 1}) + 1;");
931
932 checkStatement("[1].bar();");
933 checkStatement("1.bar();");
934 checkStatement("'foo'.bar();");
935
936 checkStatement("do while(x); while (y);");
937 checkStatement("{do; while(x); while (y);}");
938
939 }
940
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698