Files
sdk/tests/language_2/cascade/precedence_test.dart
T
Robert Nystrom fc1b1ecc71 Move files under language_2 into subdirectories.
Change-Id: Idbcc965a27e9ffeedf5e0a1068b019de4193070f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127745
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
2019-12-11 19:18:00 +00:00

184 lines
4.0 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
class A {
int value;
A(this.value);
void set(int value) {
this.value = value;
}
int get() => value;
int operator [](int index) => value + index;
void operator []=(int index, int newValue) {
value += -index + newValue;
}
void test(int expected) {
Expect.equals(expected, value);
}
Function limp(int n) {
if (n == 0) return set;
return () => limp(n - 1);
}
A get self => this;
A operator +(A other) {
this.value += other.value;
return this;
}
}
class Box {
A value;
Box(this.value);
A operator [](int pos) => value;
void operator []=(int pos, A a) {
value = a;
}
A get x => value;
void set x(A a) {
value = a;
}
}
// Subset of grammar being tested.
//
// expression:
// assignableExpression assignmentOperator expression
// | conditionalExpression cascadeSection*
// ;
// expressionWithoutCascade:
// assignableExpression assignmentOperator expressionWithoutCascade
// | conditionalExpression
// ;
// expressionList:
// expression (',' expression)*
// ;
// assignableExpression:
//      primary (arguments* assignableSelector)+
//    | super assignableSelector
//   | identifier
// ;
// conditionalExpression:
//     logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
// ;
// primary:
// thisExpression
// | super assignableSelector
// | functionExpression
// | literal
// | identifier
// | newExpression
// | constObjectExpression
// | '(' expression ')'
//    ;
// assignableSelector:
//      '[' expression ']'
//    | '.' identifier
//    ;
//
// In words:
// An assignableExpression is either a variable or something ending in
// [expression] or .identifier.
main() {
A a = new A(42);
A original = a;
A b = new A(87);
fa() => a;
Box box = new Box(a);
// Different expressions on the left-hand side of '..'.
// conditionalExpression >> postfixExpression > primary selector*
Expect.equals(
a,
a
..set(37)
..get());
a.test(37);
Expect.equals(
a,
fa()
..set(42)
..get());
a.test(42);
Expect.equals(
a,
box.x
..set(37)
..get());
a.test(37);
// '..' binds to 'b + a', i.e., to the 'b' object, not to 'a'.
Expect.equals(
b,
b + a
..test(124)
..set(117)
..get());
b.test(117);
a.test(37);
// expression :: conditionalExpression cascadeSection
// and conditionalExpression ends in expressionWithoutCascade.
// I.e., '..' binds to the entire condition expression, not to 'b'.
(a.value == 37) ? a : b
..set(42);
a.test(42);
// This binds .. to 'a', not 'c=a', and performs assignment after reading
// c.get().
A c = new A(21);
c = a..set(c.get()); // FAILING.
Expect.equals(a, c);
Expect.equals(original, a);
a.test(21); // Fails as 42 if above is parsed as (c = a)..set(c.get()).
// Should be parsed as (box..x = (c = a))..x.test(21).
c = null;
box
..x = c = a
..x.test(21);
c.test(21);
// Other variants
c = null;
box
..x = c = (a..test(21))
..x.test(21);
c.test(21);
c = null;
box
..x = (c = a..test(21))
..x.test(21);
c.test(21);
// Should work the same:
(a..set(42))..test(42);
a
..set(21)
..test(21);
c = null;
Box originalBox = box;
// Should parse as:
// box = (box..x = (a.value == 21 ? b : c)..x.test(117));
box = box
..x = a.value == 21 ? b : c
..x.test(117);
Expect.equals(originalBox, box);
Expect.equals(box.value, b);
// New cascades are allowed inside an expressionWithoutCascade if properly
// delimited.
box
..x = (a
..set(42)
..test(42))
..x.test(42);
}