mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-12 19:22:37 +00:00
[FunC] Change priority of & | ^
operators to a more intuitive one
Before, such code `if (slices_equal() & status == 1)` was parsed as `if( (slices_equal()&status) == 1 )`. Note, that this change leads to hash changes of some verified contracts, but a new priority is more expected from the user experience.
This commit is contained in:
parent
aee51731ce
commit
7afa9292c3
3 changed files with 77 additions and 8 deletions
|
@ -137,7 +137,7 @@ int apply_profit(int value, int value_profit, int profit) {
|
|||
}
|
||||
|
||||
;; Try to withdraw from withdraw balance
|
||||
if ((remaining > 0) & ctx_member_withdraw > 0) {
|
||||
if (((remaining > 0) & ctx_member_withdraw) > 0) { ;; such strange brackets to remain hash stable after & priority fix
|
||||
int delta = min(ctx_member_withdraw, remaining);
|
||||
ctx_member_withdraw = ctx_member_withdraw - delta;
|
||||
ctx_balance_withdraw = ctx_balance_withdraw - delta;
|
||||
|
@ -294,4 +294,4 @@ int owned_balance() {
|
|||
|
||||
;; Reset sent amount
|
||||
ctx_balance_sent = 0;
|
||||
}
|
||||
}
|
||||
|
|
48
crypto/func/auto-tests/tests/op_priority.fc
Normal file
48
crypto/func/auto-tests/tests/op_priority.fc
Normal file
|
@ -0,0 +1,48 @@
|
|||
int justTrue() { return true; }
|
||||
|
||||
int test1(int x, int y, int z) method_id(101) {
|
||||
return x > 0 & y > 0 & z > 0;
|
||||
}
|
||||
|
||||
int test2(int x, int y, int z) method_id(102) {
|
||||
return x > (0 & y > 0 & z > 0);
|
||||
}
|
||||
|
||||
int test3(int x, int y, int z) method_id(103) {
|
||||
if (x < 0 | y < 0) {
|
||||
return z < 0;
|
||||
}
|
||||
return x > 0 & y > 0;
|
||||
}
|
||||
|
||||
int test4(int x, int y, int mode) method_id(104) {
|
||||
if (mode == 1) {
|
||||
return x == 10 | (y == 20);
|
||||
} if (mode == 2) {
|
||||
return x == 10 | y == 20;
|
||||
} else {
|
||||
return x == (10 | (y == 20));
|
||||
}
|
||||
}
|
||||
|
||||
int test5(int status) method_id(105) {
|
||||
return justTrue() & status == 1 & (justTrue() & status) == 1;
|
||||
}
|
||||
|
||||
() main() { }
|
||||
|
||||
{-
|
||||
TESTCASE | 101 | 1 2 3 | -1
|
||||
TESTCASE | 101 | 1 0 3 | 0
|
||||
TESTCASE | 101 | 1 2 -1 | 0
|
||||
TESTCASE | 102 | 1 0 0 | -1
|
||||
TESTCASE | 103 | -1 -2 -3 | -1
|
||||
TESTCASE | 103 | -1 -2 0 | 0
|
||||
TESTCASE | 103 | 1 2 0 | -1
|
||||
TESTCASE | 103 | 1 0 2 | 0
|
||||
TESTCASE | 104 | 10 20 1 | -1
|
||||
TESTCASE | 104 | 10 20 2 | -1
|
||||
TESTCASE | 104 | 10 20 3 | 0
|
||||
TESTCASE | 105 | 1 | -1
|
||||
TESTCASE | 105 | 0 | 0
|
||||
-}
|
|
@ -787,11 +787,11 @@ Expr* parse_expr75(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
}
|
||||
}
|
||||
|
||||
// parse E { (* | / | % | /% ) E }
|
||||
// parse E { (* | / | % | /% | ^/ | ~/ | ^% | ~% ) E }
|
||||
Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res = parse_expr75(lex, code, nv);
|
||||
while (lex.tp() == '*' || lex.tp() == '/' || lex.tp() == '%' || lex.tp() == _DivMod || lex.tp() == _DivC ||
|
||||
lex.tp() == _DivR || lex.tp() == _ModC || lex.tp() == _ModR || lex.tp() == '&') {
|
||||
lex.tp() == _DivR || lex.tp() == _ModC || lex.tp() == _ModR) {
|
||||
res->chk_rvalue(lex.cur());
|
||||
int t = lex.tp();
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
|
||||
|
@ -809,7 +809,7 @@ Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
return res;
|
||||
}
|
||||
|
||||
// parse [-] E { (+ | - | `|` | ^) E }
|
||||
// parse [-] E { (+ | -) E }
|
||||
Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res;
|
||||
int t = lex.tp();
|
||||
|
@ -828,7 +828,7 @@ Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
} else {
|
||||
res = parse_expr30(lex, code, nv);
|
||||
}
|
||||
while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|' || lex.tp() == '^') {
|
||||
while (lex.tp() == '-' || lex.tp() == '+') {
|
||||
res->chk_rvalue(lex.cur());
|
||||
t = lex.tp();
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
|
||||
|
@ -846,7 +846,7 @@ Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
return res;
|
||||
}
|
||||
|
||||
// parse E { ( << | >> | >>~ | >>^ ) E }
|
||||
// parse E { ( << | >> | ~>> | ^>> ) E }
|
||||
Expr* parse_expr17(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res = parse_expr20(lex, code, nv);
|
||||
while (lex.tp() == _Lshift || lex.tp() == _Rshift || lex.tp() == _RshiftC || lex.tp() == _RshiftR) {
|
||||
|
@ -889,9 +889,30 @@ Expr* parse_expr15(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
return res;
|
||||
}
|
||||
|
||||
// parse E { ( & | `|` | ^ ) E }
|
||||
Expr* parse_expr14(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res = parse_expr15(lex, code, nv);
|
||||
while (lex.tp() == '&' || lex.tp() == '|' || lex.tp() == '^') {
|
||||
res->chk_rvalue(lex.cur());
|
||||
int t = lex.tp();
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
|
||||
check_global_func(lex.cur(), name);
|
||||
SrcLocation loc{lex.cur().loc};
|
||||
lex.next();
|
||||
auto x = parse_expr15(lex, code, false);
|
||||
x->chk_rvalue(lex.cur());
|
||||
res = new Expr{Expr::_Apply, name, {res, x}};
|
||||
res->here = loc;
|
||||
res->set_val(t);
|
||||
res->flags = Expr::_IsRvalue;
|
||||
res->deduce_type(lex.cur());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// parse E [ ? E : E ]
|
||||
Expr* parse_expr13(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res = parse_expr15(lex, code, nv);
|
||||
Expr* res = parse_expr14(lex, code, nv);
|
||||
if (lex.tp() == '?') {
|
||||
res->chk_rvalue(lex.cur());
|
||||
SrcLocation loc{lex.cur().loc};
|
||||
|
|
Loading…
Reference in a new issue