Using for for operators.

This commit is contained in:
chriseth
2022-09-28 11:32:03 +02:00
committed by wechman
parent 2201526a90
commit 3bd047f188
28 changed files with 607 additions and 93 deletions
@@ -0,0 +1,16 @@
type MyInt is int;
using {add as +} for MyInt;
function add(MyInt, MyInt) pure returns (bool) {
return true;
}
contract C {
function f() public pure returns (bool t) {
t = MyInt.wrap(2) + MyInt.wrap(7);
}
}
// ====
// compileViaYul: also
// ----
// f() -> true
@@ -0,0 +1,75 @@
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 >=
} 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(1);
}
function bitand(Int, Int) pure returns (Int) {
return w(2);
}
function bitxor(Int, Int) pure returns (Int) {
return w(3);
}
function bitnot(Int) pure returns (Int) {
return w(4);
}
function add(Int, Int) pure returns (Int) {
return w(5);
}
function sub(Int, Int) pure returns (Int) {
return w(6);
}
function unsub(Int) pure returns (Int) {
return w(7);
}
function mul(Int, Int) pure returns (Int) {
return w(8);
}
function div(Int, Int) pure returns (Int) {
return w(9);
}
function mod(Int, Int) pure returns (Int) {
return w(10);
}
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) == 3;
}
function gt(Int x, Int) pure returns (bool) {
return uw(x) == 4;
}
function leq(Int x, Int) pure returns (bool) {
return uw(x) == 5;
}
function geq(Int x, Int) pure returns (bool) {
return uw(x) == 6;
}
// TODO test that side-effects are executed properly.
contract C {
function f1() public pure returns (Int) {
require(w(1) | w(2) == w(1));
require(!(w(1) | w(2) == w(2)));
return w(1) | w(2);
}
// TODO all the other operators
}
// ====
// compileViaYul: also
// ----
// f1()
@@ -0,0 +1,24 @@
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;
}
}
// ====
// compileViaYul: also
// ----
// applyInterest(int128,int128): 500000000000000000000, 100000000000000000 -> 550000000000000000000
@@ -0,0 +1,10 @@
type Type is uint;
using {f as +} for Type;
function f(Type, Type) pure returns (Type) {}
Type constant t = Type.wrap(1);
Type constant u = v + t;
Type constant v = u + t;
// ----
// TypeError 8349: (141-146): Initial value for constant variable has to be compile-time constant.
// TypeError 8349: (166-171): Initial value for constant variable has to be compile-time constant.
@@ -0,0 +1,4 @@
using {f as +} for uint;
function f(uint, uint) pure returns (uint) {}
// ----
// TypeError 5332: (7-8): Operators can only be implemented for user-defined types and not for contracts.