mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Add try/catch to FunC (#560)
* Add try-catch * Fix 'return' bugs * Update tests * Fix 'SETCONTVARARGS' bug * Fix 'SETCONTVARARGS' bug again * Check deep stack * Add throw_arg Co-authored-by: legaii <jgates.ardux@gmail.com>
This commit is contained in:
parent
dd9cdba587
commit
e1be988df5
8 changed files with 365 additions and 0 deletions
113
crypto/func/test/tc1.fc
Normal file
113
crypto/func/test/tc1.fc
Normal file
|
@ -0,0 +1,113 @@
|
|||
() test1() impure {
|
||||
int i = 3;
|
||||
repeat (3) {
|
||||
try {
|
||||
int j = i;
|
||||
i *= 2;
|
||||
throw_unless(500, j <= 10);
|
||||
} catch (x, e) {
|
||||
i -= 2;
|
||||
}
|
||||
i += i + 1;
|
||||
}
|
||||
throw_unless(501, i == 43);
|
||||
}
|
||||
|
||||
int divide_by_ten(int num) {
|
||||
try {
|
||||
throw_unless(500, num < 10);
|
||||
} catch (x, e) {
|
||||
return divide_by_ten(num - 10) + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
() test2() impure {
|
||||
int n = divide_by_ten(37);
|
||||
throw_unless(502, n == 3);
|
||||
}
|
||||
|
||||
(int, int) swap_int(int a, int b) {
|
||||
try {
|
||||
a = a * b;
|
||||
b = a / b;
|
||||
a = a / b;
|
||||
return (a, b);
|
||||
} catch (x, e) {
|
||||
throw_unless(500, b == 0);
|
||||
}
|
||||
return (0, a);
|
||||
}
|
||||
|
||||
() test3() impure {
|
||||
int a = 0;
|
||||
int b = 57;
|
||||
try {
|
||||
(a, b) = swap_int(a, b);
|
||||
} catch (x, e) {
|
||||
throw_unless(500, a == 0);
|
||||
a = b;
|
||||
b = 0;
|
||||
}
|
||||
throw_unless(503, (a == 57) & (b == 0));
|
||||
}
|
||||
|
||||
int get_x(int x, int y) {
|
||||
try {
|
||||
} catch (x, e) {
|
||||
return -1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
int get_y(int x, int y) {
|
||||
try {
|
||||
return -1;
|
||||
} catch (x, e) {
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
() test4() impure {
|
||||
throw_unless(504, get_x(3, 4) == 3);
|
||||
throw_unless(504, get_y(3, 4) == -1);
|
||||
}
|
||||
|
||||
(int, int, int, int, int) foo(int a, int b, int c, int d, int e) {
|
||||
try {
|
||||
throw(11);
|
||||
} catch (x, y) {
|
||||
a += 1;
|
||||
b += 2;
|
||||
c += 3;
|
||||
d += 4;
|
||||
e += 5;
|
||||
}
|
||||
return (a, b, c, d, e);
|
||||
}
|
||||
|
||||
() test5() impure {
|
||||
var (a, b, c, d, e) = foo(10, 20, 30, 40, 50);
|
||||
throw_unless(505, (a == 11) & (b == 22) & (c == 33) & (d == 44) & (e == 55));
|
||||
}
|
||||
|
||||
() test6() impure {
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
try {
|
||||
b = 3;
|
||||
} catch (x, y) {
|
||||
b = 12;
|
||||
}
|
||||
throw_unless(506, (a == 0) & (b == 3) & (c == 0));
|
||||
}
|
||||
|
||||
() main() {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
}
|
84
crypto/func/test/tc2.fc
Normal file
84
crypto/func/test/tc2.fc
Normal file
|
@ -0,0 +1,84 @@
|
|||
forall X -> int cast_to_int(X x) asm "NOP";
|
||||
forall X -> builder cast_to_builder(X x) asm "NOP";
|
||||
|
||||
_ test1_body() {
|
||||
int a = 3;
|
||||
builder b = begin_cell();
|
||||
int c = 1;
|
||||
try {
|
||||
c = 3;
|
||||
throw_arg(b, 100);
|
||||
} catch (x, y) {
|
||||
return (a + c + y, cast_to_builder(x));
|
||||
}
|
||||
return (0, null());
|
||||
}
|
||||
|
||||
() test1() impure {
|
||||
var (x, y) = test1_body();
|
||||
throw_unless(101, x == 104);
|
||||
throw_unless(102, y.builder_refs() == y.builder_bits());
|
||||
}
|
||||
|
||||
_ test2_body(int a, int b, int c) {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
throw_arg_if(1, 201, a + b + c == 3);
|
||||
throw_arg_if(2, 201, a == 3);
|
||||
throw_arg_unless(1, 202, b == 4);
|
||||
return 1;
|
||||
} catch (y, x) {
|
||||
int y = y.cast_to_int();
|
||||
throw_arg_unless(y, x, x == 202);
|
||||
throw_arg(y + 1, 200);
|
||||
}
|
||||
} catch (y, x) {
|
||||
int y = y.cast_to_int();
|
||||
throw_arg_if(y, x, x == 200);
|
||||
throw_arg_if(y + 2, x, y < 2);
|
||||
throw_arg_if(y + 3, 203, a + b + c == 4);
|
||||
throw_arg_unless(y + 4, 204, b == 4);
|
||||
return 3;
|
||||
}
|
||||
} catch (y, x) {
|
||||
int y = y.cast_to_int();
|
||||
try {
|
||||
throw_arg_if(y, x, x == 200);
|
||||
throw_arg_if(y + 1, 200, x == 201);
|
||||
throw_arg_if(x - 203, 200, x == 202);
|
||||
throw_arg_if(y, 200, x == 203);
|
||||
throw_arg_if(a + 4, 205, a + b + c == 5);
|
||||
throw_arg(7, 200);
|
||||
} catch (v, u) {
|
||||
int v = v.cast_to_int();
|
||||
throw_arg_unless(v, u, u == 205);
|
||||
if (c == 0) {
|
||||
return b + 4;
|
||||
}
|
||||
throw_arg(v + 1, 200);
|
||||
}
|
||||
}
|
||||
} catch (y, x) {
|
||||
throw_unless(x, x == 200);
|
||||
return y.cast_to_int();
|
||||
}
|
||||
return null();
|
||||
}
|
||||
|
||||
() test2() impure {
|
||||
throw_unless(201, test2_body(0, 4, 0) == 1);
|
||||
throw_unless(202, test2_body(0, 5, 0) == 2);
|
||||
throw_unless(203, test2_body(3, 4, 0) == 3);
|
||||
throw_unless(204, test2_body(3, 0, 0) == 4);
|
||||
throw_unless(205, test2_body(3, 1, 0) == 5);
|
||||
throw_unless(206, test2_body(3, 2, 0) == 6);
|
||||
throw_unless(207, test2_body(3, 1, 2) == 7);
|
||||
throw_unless(208, test2_body(3, 1, 1) == 8);
|
||||
}
|
||||
|
||||
() main() {
|
||||
test1();
|
||||
test2();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue