User-defined operators: Tests

This commit is contained in:
wechman
2023-01-25 00:29:10 +01:00
committed by Kamil Śliwak
parent fd6359000e
commit 1edb74dbc9
85 changed files with 2138 additions and 1 deletions
@@ -0,0 +1,20 @@
type Int is int16;
using {add as +, add} for Int;
function add(Int _a, Int _b) pure returns (Int) {
return Int.wrap(Int.unwrap(_a) + Int.unwrap(_b));
}
contract C {
function f() pure public returns (Int) {
return Int.wrap(5) + Int.wrap(5);
}
function g() pure public returns (Int) {
return Int.wrap(7).add(Int.wrap(6));
}
}
// ----
// f() -> 10
// g() -> 13
@@ -0,0 +1,125 @@
type Int is int128;
using {
bitor as |, bitand as &, bitxor as ^, bitnot as ~,
add as +, sub as -, unsub as -, mul as *, div as /, mod as %,
eq as ==, noteq as !=, lt as <, gt as >, leq as <=, geq as >=,
shl as <<, sar as >>, exp as **, not as !
} for Int;
function uw(Int x) pure returns (int128) {
return Int.unwrap(x);
}
function w(int128 x) pure returns (Int) {
return Int.wrap(x);
}
function bitor(Int, Int) pure returns (Int) {
return w(10);
}
function bitand(Int, Int) pure returns (Int) {
return w(11);
}
function bitxor(Int, Int) pure returns (Int) {
return w(12);
}
function bitnot(Int) pure returns (Int) {
return w(13);
}
function add(Int x, Int) pure returns (Int) {
return w(uw(x) + 10);
}
function sub(Int, Int) pure returns (Int) {
return w(15);
}
function unsub(Int) pure returns (Int) {
return w(16);
}
function mul(Int, Int) pure returns (Int) {
return w(17);
}
function div(Int, Int) pure returns (Int) {
return w(18);
}
function mod(Int, Int) pure returns (Int) {
return w(19);
}
function eq(Int x, Int) pure returns (bool) {
return uw(x) == 1;
}
function noteq(Int x, Int) pure returns (bool) {
return uw(x) == 2;
}
function lt(Int x, Int) pure returns (bool) {
return uw(x) < 10;
}
function gt(Int x, Int) pure returns (bool) {
return uw(x) > 10;
}
function leq(Int x, Int) pure returns (bool) {
return uw(x) <= 10;
}
function geq(Int x, Int) pure returns (bool) {
return uw(x) >= 10;
}
function shl(Int, Int) pure returns (Int) {
return w(20);
}
function sar(Int, Int) pure returns (Int) {
return w(21);
}
function exp(Int, Int) pure returns (Int) {
return w(22);
}
function not(Int) pure returns (Int) {
return w(23);
}
contract C {
function test_bitor() public pure returns (Int) { return w(1) | w(2); }
function test_bitand() public pure returns (Int) { return w(1) & w(2); }
function test_bitxor() public pure returns (Int) { return w(1) ^ w(2); }
function test_bitnot() public pure returns (Int) { return ~w(1); }
function test_add(int128 x) public pure returns (Int) { return w(x) + w(2); }
function test_sub() public pure returns (Int) { return w(1) - w(2); }
function test_unsub() public pure returns (Int) { return -w(1); }
function test_mul() public pure returns (Int) { return w(1) * w(2); }
function test_div() public pure returns (Int) { return w(1) / w(2); }
function test_mod() public pure returns (Int) { return w(1) % w(2); }
function test_eq(int128 x) public pure returns (bool) { return w(x) == w(2); }
function test_neq(int128 x) public pure returns (bool) { return w(x) != w(2); }
function test_lt(int128 x) public pure returns (bool) { return w(x) < w(2); }
function test_gt(int128 x) public pure returns (bool) { return w(x) > w(2); }
function test_leq(int128 x) public pure returns (bool) { return w(x) <= w(2); }
function test_geq(int128 x) public pure returns (bool) { return w(x) >= w(2); }
function test_shl() public pure returns (Int) { return w(1) << w(2); }
function test_sar() public pure returns (Int) { return w(1) >> w(2); }
function test_exp() public pure returns (Int) { return w(1) ** w(2); }
function test_not() public pure returns (Int) { return !w(1); }
}
// ----
// test_bitor() -> 10
// test_bitand() -> 11
// test_bitxor() -> 12
// test_bitnot() -> 13
// test_add(int128): 4 -> 14
// test_add(int128): 104 -> 114
// test_sub() -> 15
// test_unsub() -> 16
// test_mul() -> 17
// test_div() -> 18
// test_mod() -> 19
// test_eq(int128): 1 -> true
// test_eq(int128): 2 -> false
// test_neq(int128): 2 -> true
// test_neq(int128): 1 -> false
// test_lt(int128): 9 -> true
// test_lt(int128): 10 -> false
// test_gt(int128): 11 -> true
// test_gt(int128): 10 -> false
// test_leq(int128): 10 -> true
// test_leq(int128): 11 -> false
// test_geq(int128): 10 -> true
// test_geq(int128): 9 -> false
// test_shl() -> 20
// test_sar() -> 21
// test_exp() -> 22
// test_not() -> 23
@@ -0,0 +1,93 @@
type Int is int64;
using {
bitor as |, bitand as &, bitxor as ^, bitnot as ~, shl as <<, sar as >>,
add as +, sub as -, unsub as -, mul as *, div as /, mod as %, exp as **,
eq as ==, noteq as !=,
not as !
} for Int;
function uw(Int x) pure returns (int64) { return Int.unwrap(x); }
function w(int64 x) pure returns (Int) { return Int.wrap(x); }
function bitor(Int x, Int y) pure returns (Int) { return w(uw(x) | uw(y)); }
function bitand(Int x, Int y) pure returns (Int) { return w(uw(x) & uw(y)); }
function bitxor(Int x, Int y) pure returns (Int) { return w(uw(x) ^ uw(y)); }
function bitnot(Int x) pure returns (Int) { return w(~uw(x)); }
function shl(Int x, Int y) pure returns (Int) { return w(uw(x) << uint64(uw(y))); }
function sar(Int x, Int y) pure returns (Int) { return w(uw(x) >> uint64(uw(y))); }
function add(Int x, Int y) pure returns (Int) { return w(uw(x) + uw(y)); }
function sub(Int x, Int y) pure returns (Int) { return w(uw(x) - uw(y)); }
function unsub(Int x) pure returns (Int) { return w(-uw(x)); }
function mul(Int x, Int y) pure returns (Int) { return w(uw(x) * uw(y)); }
function div(Int x, Int y) pure returns (Int) { return w(uw(x) / uw(y)); }
function mod(Int x, Int y) pure returns (Int) { return w(uw(x) % uw(y)); }
function exp(Int x, Int y) pure returns (Int) { return w(uw(x) ** uint64(uw(y))); }
function eq(Int x, Int y) pure returns (bool) { return uw(x) == uw(y); }
function noteq(Int x, Int y) pure returns (bool) { return uw(x) != uw(y); }
function not(Int x) pure returns (Int) { return w((uw(x) == 0 ? int64(1) : int64(0))); }
contract C {
Int constant I0 = Int.wrap(0);
Int constant I1 = Int.wrap(1);
Int constant I2 = Int.wrap(2);
Int constant I3 = Int.wrap(3);
Int constant I4 = Int.wrap(4);
Int constant I5 = Int.wrap(5);
Int constant I6 = Int.wrap(6);
Int constant I7 = Int.wrap(7);
Int constant I10 = Int.wrap(10);
Int constant I13 = Int.wrap(13);
Int constant I15 = Int.wrap(15);
Int constant I20 = Int.wrap(20);
Int constant I128 = Int.wrap(128);
function test_bitwise() public pure {
assert(Int.unwrap(I0 & I0 | I1) == (0 & 0 | 1));
assert(Int.unwrap(I0 & I0 | I1) == ((0 & 0) | 1));
}
function test_bitwise_arithmetic() public pure {
assert(Int.unwrap(I1 << I1 + I1 & ~I1 | I1 << I2 * I3 - I1 & ~I3) == (1 << 1 + 1 & ~1 | 1 << 2 * 3 - 1 & ~3));
assert(Int.unwrap(I1 << I1 + I1 & ~I1 | I1 << I2 * I3 - I1 & ~I3) == (((1 << (1 + 1)) & (~1)) | ((1 << ((2 * 3) - 1)) & (~3))));
}
function test_arithmetic() public pure {
assert(Int.unwrap(I1 + I2 ** I3 / I4 - I5 % I6 * I7) == (1 + 2 ** 3 / 4 - 5 % 6 * 7));
assert(Int.unwrap(I1 + I2 ** I3 / I4 - I5 % I6 * I7) == ((1 + ((2 ** 3) / 4)) - ((5 % 6) * 7)));
}
function test_not() public pure {
assert((!I0 + I1) == I2);
assert((!I0 * I1) != I2);
assert((!I0 << I2) == I4);
assert((!I0 | I3) == I3);
assert((!~-I1 + I1) == I2);
}
function test_all() public pure {
assert(
Int.unwrap(I128 + I1 - I10 + I4 & ~I1 ^ ~I1 >> I1 + I1 << I3 ** I2 | -I15 % -I10 * I20 / I2 + I13 & ~I3) ==
(128 + 1 - 10 + 4 & ~1 ^ ~1 >> 1 + 1 << 3 ** 2 | -15 % -10 * 20 / 2 + 13 & ~3)
);
assert(
Int.unwrap(I128 + I1 - I10 + I4 & ~I1 ^ ~I1 >> I1 + I1 << I3 ** I2 | -I15 % -I10 * I20 / I2 + I13 & ~I3) ==
(
(
((((128 + 1) - 10) + 4) & (~1)) ^
(((~1) >> (1 + 1)) << (3 ** 2))
) |
((((((-15) % (-10)) * 20) / 2) + 13) & (~3))
)
);
}
}
// ----
// test_bitwise() ->
// test_bitwise_arithmetic() ->
// test_arithmetic() ->
// test_not() ->
// test_all() ->
@@ -0,0 +1,18 @@
type A is address;
using {add as +} for A;
function add(A a, A b) pure returns (A) {
return A.wrap(address(uint160(A.unwrap(a)) + uint160(A.unwrap(b))));
}
contract C {
function g() public pure returns (A) {
A a = A.wrap(0x3333333333333333333333333333333333333333);
A b = A.wrap(0x1111111111111111111111111111111111111111);
A c = A.wrap(0x5555555555555555555555555555555555555555);
return a + b + c;
}
}
// ----
// g() -> 0x9999999999999999999999999999999999999999
@@ -0,0 +1,26 @@
type Int is int16;
using {add as +} for Int;
function add(Int, Int) returns (Int) {
B b = new B();
return b.f();
}
contract B {
Int s;
function f() external returns (Int) {
s = Int.wrap(3);
return s;
}
}
contract C {
function test() public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// test() -> 3
// gas legacy: 119695
@@ -0,0 +1,28 @@
==== Source: s1.sol ====
type Int is int;
using {add1 as +} for Int global;
function add1(Int, Int) pure returns (Int) {
return Int.wrap(3);
}
==== Source: s2.sol ====
import {Int} from "s1.sol";
using {add2 as +} for Int;
function add2(Int, Int) pure returns (Int) {
return Int.wrap(7);
}
==== Source: s3.sol ====
import {Int} from "s2.sol";
contract C {
function f() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// f() -> 3
@@ -0,0 +1,40 @@
type Int is int;
function add1(Int, Int) pure returns (Int) {
return Int.wrap(1);
}
function add2(Int, Int) pure returns (Int) {
return Int.wrap(2);
}
contract C1 {
using {add1 as +} for Int;
function f() public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C2 {
using {add2 as +} for Int;
function f() public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C {
function test1() public returns (Int) {
C1 c = new C1();
return c.f();
}
function test2() public returns (Int) {
C2 c = new C2();
return c.f();
}
}
// ----
// test1() -> 1
// test2() -> 2
@@ -0,0 +1,41 @@
type Int is int128;
function addA(Int, Int) pure returns (Int) {
return Int.wrap(1);
}
function addB(Int, Int) pure returns (Int) {
return Int.wrap(3);
}
function addC(Int, Int) pure returns (Int) {
return Int.wrap(7);
}
contract A {
using {addA as +} for Int;
function testA() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract B is A {
using {addB as +} for Int;
function testB() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
contract C is A, B {
using {addC as +} for Int;
function testC() pure public returns (Int) {
return Int.wrap(0) + Int.wrap(0);
}
}
// ----
// testA() -> 1
// testB() -> 3
// testC() -> 7
@@ -0,0 +1,22 @@
type Fixed is int128;
using {add as +, mul as *} for Fixed;
int constant MULTIPLIER = 10**18;
function add(Fixed a, Fixed b) pure returns (Fixed) {
return Fixed.wrap(Fixed.unwrap(a) + Fixed.unwrap(b));
}
function mul(Fixed a, Fixed b) pure returns (Fixed) {
int intermediate = (int(Fixed.unwrap(a)) * int(Fixed.unwrap(b))) / MULTIPLIER;
if (int128(intermediate) != intermediate) { revert("Overflow"); }
return Fixed.wrap(int128(intermediate));
}
contract C {
function applyInterest(Fixed value, Fixed percentage) public pure returns (Fixed result) {
return value + value * percentage;
}
}
// ----
// applyInterest(int128,int128): 500000000000000000000, 100000000000000000 -> 550000000000000000000
@@ -0,0 +1,29 @@
==== Source: s1.sol ====
type Int is int;
using {add as +} for Int global;
using {add as +} for Int;
function add(Int a, Int b) pure returns (Int) {
return Int.wrap(Int.unwrap(a) + Int.unwrap(b));
}
function test_add() pure returns (Int) {
return Int.wrap(1) + Int.wrap(2);
}
==== Source: s2.sol ====
import "s1.sol";
contract C2 {
function test1() pure public returns (Int) {
return test_add();
}
function test2() pure public returns (Int) {
return Int.wrap(3) + Int.wrap(4);
}
}
// ----
// test1() -> 3
// test2() -> 7
@@ -0,0 +1,25 @@
type Int is int16;
using {unsub as -} for Int global;
using {sub as -} for Int;
function sub(Int a, Int b) pure returns (Int) {
return Int.wrap(Int.unwrap(a) - Int.unwrap(b));
}
function unsub(Int a) pure returns (Int) {
return Int.wrap(-Int.unwrap(a));
}
contract C {
function test_sub() public returns (Int) {
return Int.wrap(7) - Int.wrap(2);
}
function test_unsub() public returns (Int) {
return -Int.wrap(4);
}
}
// ----
// test_sub() -> 5
// test_unsub() -> -4
@@ -0,0 +1,15 @@
type Int is int16;
using {keccak256 as +} for Int;
function keccak256(Int a, Int b) pure returns (Int) {
return Int.wrap(Int.unwrap(a) + Int.unwrap(b));
}
contract C {
function test() public returns (Int) {
return Int.wrap(3) + Int.wrap(4);
}
}
// ----
// test() -> 7
@@ -0,0 +1,30 @@
==== Source: a.sol ====
library L {
type Int is int128;
function add(Int, Int) pure public returns (Int) {
return Int.wrap(7);
}
function sub(Int) pure public returns (Int) {
return Int.wrap(5);
}
}
==== Source: b.sol ====
import "a.sol" as a;
contract C {
using {a.L.add as +} for a.L.Int;
using {a.L.sub as -} for a.L.Int;
function f() pure public returns (a.L.Int) {
return a.L.Int.wrap(0) + a.L.Int.wrap(0);
}
function g() pure public returns (a.L.Int) {
return - a.L.Int.wrap(0);
}
}
// ----
// f() -> 7
// g() -> 5
@@ -0,0 +1,26 @@
library L {
type Int is int128;
error DivisionByZero();
modifier nonZero(Int a) {
if (Int.unwrap(a) == 0)
revert("Division by zero");
_;
}
function div(Int a, Int b) pure public nonZero(b) returns (Int) {
return Int.wrap(Int.unwrap(a) / Int.unwrap(b));
}
}
contract C {
using {L.div as /} for L.Int;
function testDiv(L.Int a, L.Int b) pure public returns (L.Int) {
return a / b;
}
}
// ----
// testDiv(int128,int128): 10, 2 -> 5
// testDiv(int128,int128): 10, 0 -> FAILURE, hex"08c379a0", 0x20, 0x10, "Division by zero"
@@ -0,0 +1,22 @@
==== Source: a.sol ====
library L {
type Int is int128;
function add(Int, Int) pure public returns (Int) {
return Int.wrap(7);
}
}
==== Source: b.sol ====
import "a.sol" as a;
==== Source: c.sol ====
import "b.sol" as b;
contract C {
using {b.a.L.add as +} for b.a.L.Int;
function f() pure public returns (b.a.L.Int) {
return b.a.L.Int.wrap(0) + b.a.L.Int.wrap(0);
}
}
// ----
// f() -> 7
@@ -0,0 +1,26 @@
type SmallInt is int;
type BigInt is int;
using {addSmall as +} for SmallInt;
using {addBig as +} for BigInt;
function addSmall(SmallInt a, SmallInt b) pure returns (SmallInt) {
return SmallInt.wrap(SmallInt.unwrap(a) + SmallInt.unwrap(b));
}
function addBig(BigInt a, BigInt b) pure returns (BigInt) {
return BigInt.wrap(10 * (BigInt.unwrap(a) + BigInt.unwrap(b)));
}
contract C {
function small() public pure returns (SmallInt) {
return SmallInt.wrap(1) + SmallInt.wrap(2);
}
function big() public pure returns (BigInt) {
return BigInt.wrap(3) + BigInt.wrap(4);
}
}
// ----
// small() -> 3
// big() -> 70
@@ -0,0 +1,20 @@
type Int is int32;
using {foo as +, foo as -} for Int;
function foo(Int a, Int b) pure returns(Int) {
return Int.wrap(Int.unwrap(a) + Int.unwrap(b));
}
contract C {
function f() pure public returns (Int) {
return Int.wrap(2) + Int.wrap(3);
}
function g() pure public returns (Int) {
return Int.wrap(6) - Int.wrap(1);
}
}
// ----
// f() -> 5
// g() -> 7