blob: 0cf6359acfc1b8bad4b890aaa3650bf9d6f6b192 [file] [log] [blame]
// Copyright (c) 2019, 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";
// Tests that static extensions can be used for all operators.
void main() {
Object a = "a";
Object b = "b";
Object c = "c";
expect("(-a)", -a);
expect("(~a)", ~a);
expect("(a+b)", a + b);
expect("(a-b)", a - b);
expect("(a*b)", a * b);
expect("(a/b)", a / b);
expect("(a%b)", a % b);
expect("(a~/b)", a ~/ b);
expect("(a|b)", a | b);
expect("(a&b)", a & b);
expect("(a^b)", a ^ b);
expect("(a<b)", a < b);
expect("(a>b)", a > b);
expect("(a<=b)", a <= b);
expect("(a>=b)", a >= b);
expect("(a<<b)", a << b);
expect("(a>>b)", a >> b);
// expect("(a>>>b)", a >>> b);
expect("a(b)", a(b));
expect("a(b,c)", a(b, c));
expect("a[b]", a[b]);
expect("c", a[b] = c, "a[b]=c");
// Operator-assignment works and evaluates to its RHS value.
expect("(a.field+b)", a.field += b, "a.field=(a.field+b)");
expect("(a.field-b)", a.field -= b, "a.field=(a.field-b)");
expect("(a.field*b)", a.field *= b, "a.field=(a.field*b)");
expect("(a.field/b)", a.field /= b, "a.field=(a.field/b)");
expect("(a.field%b)", a.field %= b, "a.field=(a.field%b)");
expect("(a.field~/b)", a.field ~/= b, "a.field=(a.field~/b)");
expect("(a.field|b)", a.field |= b, "a.field=(a.field|b)");
expect("(a.field&b)", a.field &= b, "a.field=(a.field&b)");
expect("(a.field^b)", a.field ^= b, "a.field=(a.field^b)");
expect("(a.field<<b)", a.field <<= b, "a.field=(a.field<<b)");
expect("(a.field>>b)", a.field >>= b, "a.field=(a.field>>b)");
// expect("(a.field>>>b)", a.field >>>= b, "a.field=(a.field>>>b)");
// Even on index operations.
expect("(a[c]+b)", a[c] += b, "a[c]=(a[c]+b)");
expect("(a[c]-b)", a[c] -= b, "a[c]=(a[c]-b)");
expect("(a[c]*b)", a[c] *= b, "a[c]=(a[c]*b)");
expect("(a[c]/b)", a[c] /= b, "a[c]=(a[c]/b)");
expect("(a[c]%b)", a[c] %= b, "a[c]=(a[c]%b)");
expect("(a[c]~/b)", a[c] ~/= b, "a[c]=(a[c]~/b)");
expect("(a[c]|b)", a[c] |= b, "a[c]=(a[c]|b)");
expect("(a[c]&b)", a[c] &= b, "a[c]=(a[c]&b)");
expect("(a[c]^b)", a[c] ^= b, "a[c]=(a[c]^b)");
expect("(a[c]<<b)", a[c] <<= b, "a[c]=(a[c]<<b)");
expect("(a[c]>>b)", a[c] >>= b, "a[c]=(a[c]>>b)");
// expect("(a[c]>>>b)", a[c] >>>= b, "a[c]=(a[c]>>>b)");
// And ++/-- expands to their assignments.
expect("(a.field+1)", ++a.field, "a.field=(a.field+1)");
expect("(a.field-1)", --a.field, "a.field=(a.field-1)");
expect("a.field", a.field++, "a.field=(a.field+1)");
expect("a.field", a.field--, "a.field=(a.field-1)");
expect("(a[b]+1)", ++a[b], "a[b]=(a[b]+1)");
expect("(a[b]-1)", --a[b], "a[b]=(a[b]-1)");
expect("a[b]", a[b]++, "a[b]=(a[b]+1)");
expect("a[b]", a[b]--, "a[b]=(a[b]-1)");
// Combinations.
expect("(a+b[b(c)]((a*b)))", a + b[c[a] = b(c)](a * b), "c[a]=b(c)");
// Operator precedence is unaffected by being extensions.
expect("(c<((-a)|(b^((~c)&((a<<b)>>((c-a)+((((b*c)~/a)%b)/c)))))))",
c < -a | b ^ ~c & a << b >> c - a + b * c ~/ a % b / c);
expect("((((((((((((c/b)%a)~/c)*b)+a)-c)<<b)>>a)&(~c))^b)|(-a))>b)",
c / b % a ~/ c * b + a - c << b >> a & ~c ^ b | -a > b);
}
// Last value set by []= or setter.
String setValue = "";
void expect(String expect, Object value, [String? expectSet]) {
Expect.equals(expect, value, "value");
if (expectSet != null) Expect.equals(expectSet, setValue, "assignment");
}
extension Ops on Object {
Object operator -() => "(-${this})";
Object operator ~() => "(~${this})";
Object operator +(Object other) => "(${this}+$other)";
Object operator -(Object other) => "(${this}-$other)";
Object operator *(Object other) => "(${this}*$other)";
Object operator /(Object other) => "(${this}/$other)";
Object operator %(Object other) => "(${this}%$other)";
Object operator ~/(Object other) => "(${this}~/$other)";
Object operator |(Object other) => "(${this}|$other)";
Object operator &(Object other) => "(${this}&$other)";
Object operator ^(Object other) => "(${this}^$other)";
Object operator <(Object other) => "(${this}<$other)";
Object operator >(Object other) => "(${this}>$other)";
Object operator <=(Object other) => "(${this}<=$other)";
Object operator >=(Object other) => "(${this}>=$other)";
Object operator <<(Object other) => "(${this}<<$other)";
Object operator >>(Object other) => "(${this}>>$other)";
// TODO: enable `>>>` when it has been implemented.
// String operator >>>(Object other) => "(${this}>>>$other)";
// Cannot make an extension method for `==` because it's declared by Object.
Object operator [](Object other) => "${this}[$other]";
void operator []=(Object other, Object value) {
setValue = "${this}[$other]=$value";
}
Object call([arg1, arg2]) =>
"${this}(${[arg1, arg2].where((x) => x != null).join(",")})";
Object get field => "${this}.field";
void set field(Object other) {
setValue = "${this}.field=$other";
}
}