mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[Tolk] Implement logical operators && ||
Unary logical NOT was already implemented earlier. Logical AND OR are expressed via conditional expression: * a && b -> a ? (b != 0) : 0 * a || b -> a ? 1 : (b != 0) They work as expected in any expressions. For instance, having `cond && f()`, f is called only if cond is true. For primitive cases, like `a > 0 && b > 0`, Fift code is not optimal, it could potentially be without IFs. These are moments of future optimizations. For now, it's more than enough.
This commit is contained in:
parent
16824fcfe3
commit
d110022731
4 changed files with 204 additions and 46 deletions
|
@ -57,6 +57,72 @@ fun testNotNull(x: int) {
|
|||
return [x == null, null == x, !(x == null), null == null, +(null != null)];
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
fun testAndConstCodegen() {
|
||||
return (
|
||||
[1 && 0, 0 && 1, 0 && 0, 1 && 1],
|
||||
[4 && 3 && 0, 5 && 0 && 7 && 8, (7 && 0) && -19],
|
||||
[4 && 3 && -1, 5 && -100 && 7 && 8, (7 && (1 + 2)) && -19],
|
||||
[true && false, true && true]
|
||||
);
|
||||
}
|
||||
|
||||
@method_id(107)
|
||||
fun testOrConstCodegen() {
|
||||
return (
|
||||
[1 || 0, 0 || 1, 0 || 0, 1 || 1],
|
||||
[0 || 0 || 0, 0 || (0 || 0), ((0 || 0) || 0) || 0],
|
||||
[4 || 3 || -1, 0 || -100 || 0 || 0, (0 || (1 + -1)) || -19],
|
||||
[true || false, false || false]
|
||||
);
|
||||
}
|
||||
|
||||
global eqCallsCnt: int;
|
||||
|
||||
fun eq(x: int) { return x; }
|
||||
fun eqCnt(x: int) { eqCallsCnt += 1; return x; }
|
||||
fun isGt0(x: int) { return x > 0; }
|
||||
|
||||
fun alwaysThrows(): int { throw 444 ; return 444; }
|
||||
|
||||
@method_id(108)
|
||||
fun testAndSimpleCodegen(a: int, b: int) {
|
||||
return a && b;
|
||||
}
|
||||
|
||||
@method_id(109)
|
||||
fun testOrSimpleCodegen(a: int, b: int) {
|
||||
return a > 0 || b > 0;
|
||||
}
|
||||
|
||||
@method_id(110)
|
||||
fun testLogicalOps1(x: int) {
|
||||
eqCallsCnt = 0;
|
||||
return (
|
||||
isGt0(x) || !isGt0(x) || alwaysThrows(),
|
||||
x && eqCnt(x) && eqCnt(x - 1) && eqCnt(x - 2),
|
||||
(400 == eq(x)) && alwaysThrows(),
|
||||
(500 == eq(x)) || eqCnt(x) || false,
|
||||
(500 == eq(x)) || eqCnt(x) || true,
|
||||
eqCallsCnt
|
||||
);
|
||||
}
|
||||
|
||||
@method_id(111)
|
||||
fun testLogicalOps2(first: int) {
|
||||
var s = beginCell().storeInt(1, 32).storeInt(2, 32).storeInt(3, 32).storeInt(4, 32).storeInt(5, 32).endCell().beginParse();
|
||||
var sum = 0;
|
||||
if (first && s.loadUint(32)) {
|
||||
(2 == s.loadUint(32)) && (sum += s.loadUint(32));
|
||||
(3 == s.loadUint(32)) && (sum += s.loadUint(32));
|
||||
(5 == s.preloadUint(32)) && (sum += s.loadUint(32));
|
||||
} else {
|
||||
(10 == s.loadUint(32)) || (20 == s.loadUint(32)) || (3 == s.loadUint(32)) || (4 == s.loadUint(32));
|
||||
sum += s.loadUint(32);
|
||||
}
|
||||
return (s.getRemainingBitsCount(), sum);
|
||||
}
|
||||
|
||||
fun main() {
|
||||
|
||||
}
|
||||
|
@ -80,6 +146,19 @@ fun main() {
|
|||
@testcase | 104 | 0 | 3 -1 5
|
||||
@testcase | 105 | 0 | [ 0 0 -1 -1 0 ]
|
||||
@testcase | 105 | null | [ -1 -1 0 -1 0 ]
|
||||
@testcase | 106 | | [ 0 0 0 -1 ] [ 0 0 0 ] [ -1 -1 -1 ] [ 0 -1 ]
|
||||
@testcase | 107 | | [ -1 -1 0 -1 ] [ 0 0 0 ] [ -1 -1 -1 ] [ -1 0 ]
|
||||
@testcase | 108 | 1 2 | -1
|
||||
@testcase | 108 | 1 0 | 0
|
||||
@testcase | 109 | -5 -4 | 0
|
||||
@testcase | 109 | -5 4 | -1
|
||||
@testcase | 109 | 1 99 | -1
|
||||
@testcase | 110 | 0 | -1 0 0 0 -1 2
|
||||
@testcase | 110 | 1 | -1 0 0 -1 -1 4
|
||||
@testcase | 110 | 2 | -1 0 0 -1 -1 5
|
||||
@testcase | 110 | 500 | -1 -1 0 -1 -1 3
|
||||
@testcase | 111 | 0 | 32 4
|
||||
@testcase | 111 | -1 | 0 8
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
|
@ -134,4 +213,83 @@ fun main() {
|
|||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testAndConstCodegen PROC:<{
|
||||
//
|
||||
FALSE
|
||||
0 PUSHINT
|
||||
DUP
|
||||
TRUE
|
||||
4 TUPLE
|
||||
FALSE
|
||||
0 PUSHINT
|
||||
DUP
|
||||
TRIPLE
|
||||
TRUE
|
||||
TRUE
|
||||
TRUE
|
||||
TRIPLE
|
||||
FALSE
|
||||
TRUE
|
||||
PAIR
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testOrConstCodegen PROC:<{
|
||||
//
|
||||
-1 PUSHINT
|
||||
TRUE
|
||||
FALSE
|
||||
s2 PUSH
|
||||
4 TUPLE
|
||||
FALSE
|
||||
FALSE
|
||||
FALSE
|
||||
TRIPLE
|
||||
-1 PUSHINT
|
||||
DUP
|
||||
TRUE
|
||||
TRIPLE
|
||||
-1 PUSHINT
|
||||
FALSE
|
||||
PAIR
|
||||
}>
|
||||
"""
|
||||
|
||||
Currently, && operator is implemented via ?: and is not optimal in primitive cases.
|
||||
For example, `a && b` can be expressed without IFs.
|
||||
These are moments of future optimizations. For now, it's more than enough.
|
||||
@fif_codegen
|
||||
"""
|
||||
testAndSimpleCodegen PROC:<{
|
||||
// a b
|
||||
SWAP // b a
|
||||
IF:<{ // b
|
||||
0 NEQINT // _2
|
||||
}>ELSE<{ // b
|
||||
DROP //
|
||||
0 PUSHINT // _2=0
|
||||
}>
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testOrSimpleCodegen PROC:<{
|
||||
// a b
|
||||
SWAP // b a
|
||||
0 GTINT // b _3
|
||||
IF:<{ // b
|
||||
DROP //
|
||||
-1 PUSHINT // _4=-1
|
||||
}>ELSE<{ // b
|
||||
0 GTINT // _7
|
||||
0 NEQINT // _4
|
||||
}>
|
||||
}>
|
||||
"""
|
||||
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue