mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[Tolk] Change order of assignment evaluation, lhs first
In FunC (and in Tolk before), the assignment > lhs = rhs evaluation order (at IR level) was "rhs first, lhs second". In practice, this did not matter, because lhs could only be a primitive: > (v1, v2) = getValue() Left side of assignment actually has no "evaluation". Since Tolk implemented indexed access, there could be > getTensor().0 = getValue() or (in the future) > getObject().field = getValue() where evaluation order becomes significant. Now evaluation order will be to "lhs first, rhs second" (more expected from user's point of view), which will become significant when building control flow graph.
This commit is contained in:
parent
2a68c8610b
commit
1389ff6789
20 changed files with 602 additions and 456 deletions
|
@ -144,15 +144,16 @@ fun test95() {
|
|||
"""
|
||||
test95 PROC:<{
|
||||
...
|
||||
next GETGLOB // '10
|
||||
3 PUSHINT // '10 '12=3
|
||||
4 PUSHINT // '10 '12=3 '13=4
|
||||
5 PUSHINT // '10 '12=3 '13=4 '14=5
|
||||
TRIPLE // '15 '16
|
||||
next SETGLOB
|
||||
next GETGLOB // g_next
|
||||
3 PUSHINT // g_next '14=3
|
||||
4 PUSHINT // g_next '14=3 '15=4
|
||||
5 PUSHINT // g_next '14=3 '15=4 '16=5
|
||||
TRIPLE // '10 '11
|
||||
SWAP
|
||||
cur SETGLOB
|
||||
cur GETGLOB // '17
|
||||
next GETGLOB // '17 '18
|
||||
next SETGLOB
|
||||
cur GETGLOB // g_cur
|
||||
next GETGLOB // g_cur g_next
|
||||
}>
|
||||
"""
|
||||
*/
|
||||
|
|
|
@ -147,5 +147,5 @@ fun main() {
|
|||
// x.0 x.1
|
||||
"""
|
||||
|
||||
@code_hash 7627024945492125068389905298530400936797031708759561372406088054030801992712
|
||||
@code_hash 61280273714870328160131559159866470128402169974050439159015534193532598351244
|
||||
*/
|
||||
|
|
|
@ -26,6 +26,185 @@ fun typesAsIdentifiers(builder: builder) {
|
|||
return int;
|
||||
}
|
||||
|
||||
global callOrder: tuple;
|
||||
|
||||
fun getTensor_12() {
|
||||
callOrder.tuplePush(100);
|
||||
return (1, 2);
|
||||
}
|
||||
fun getTensor_1X(x: int) {
|
||||
callOrder.tuplePush(101);
|
||||
return (1, x);
|
||||
}
|
||||
fun getTuple_12() {
|
||||
callOrder.tuplePush(110);
|
||||
return [1, 2];
|
||||
}
|
||||
fun getTuple_1X(x: int) {
|
||||
callOrder.tuplePush(111);
|
||||
return [1, x];
|
||||
}
|
||||
fun getUntypedTuple_12() {
|
||||
callOrder.tuplePush(120);
|
||||
var t = createEmptyTuple(); t.tuplePush(1); t.tuplePush(2);
|
||||
return t;
|
||||
}
|
||||
fun getUntypedTuple_1X(x: int) {
|
||||
callOrder.tuplePush(121);
|
||||
var t = createEmptyTuple(); t.tuplePush(1); t.tuplePush(x);
|
||||
return t;
|
||||
}
|
||||
fun getIntValue5() {
|
||||
callOrder.tuplePush(10);
|
||||
return 5;
|
||||
}
|
||||
fun getIntValueX(x: int) {
|
||||
callOrder.tuplePush(11);
|
||||
return x;
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun test102() {
|
||||
callOrder = createEmptyTuple();
|
||||
var x = 0;
|
||||
getTensor_12().0 = getIntValue5();
|
||||
getTensor_1X(5).1 = getIntValue5();
|
||||
getTensor_1X(x = 10).0 = getIntValueX(x);
|
||||
return (callOrder, x);
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun test103() {
|
||||
callOrder = createEmptyTuple();
|
||||
var x = 0;
|
||||
getTuple_12().0 = getIntValue5();
|
||||
getTuple_1X(5).1 = getIntValue5();
|
||||
getTuple_1X(x = 10).0 = getIntValueX(x);
|
||||
return (callOrder, x);
|
||||
}
|
||||
|
||||
@method_id(104)
|
||||
fun test104() {
|
||||
callOrder = createEmptyTuple();
|
||||
var x = 0;
|
||||
getUntypedTuple_12().0 = getIntValue5();
|
||||
getUntypedTuple_1X(5).1 = getIntValue5();
|
||||
getUntypedTuple_1X(x = 10).0 = getIntValueX(x);
|
||||
return (callOrder, x);
|
||||
}
|
||||
|
||||
@method_id(105)
|
||||
fun test105() {
|
||||
callOrder = createEmptyTuple();
|
||||
getTensor_12().0 = getTensor_1X(getIntValue5()).1 = getIntValueX(getTensor_12().1);
|
||||
return callOrder;
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
fun test106() {
|
||||
callOrder = createEmptyTuple();
|
||||
getTuple_12().0 = getTuple_1X(getIntValue5()).1 = getIntValueX(getTuple_12().1);
|
||||
return callOrder;
|
||||
}
|
||||
|
||||
global t107: (int, int);
|
||||
|
||||
@method_id(107)
|
||||
fun test107() {
|
||||
((t107 = (1, 2)).0, (t107 = (3, 4)).1) = (5, 6);
|
||||
return t107;
|
||||
}
|
||||
|
||||
global g108: int;
|
||||
fun assertEq(a: int, b: int) {
|
||||
assert(a == b, 10);
|
||||
return b;
|
||||
}
|
||||
|
||||
@method_id(108)
|
||||
fun test108() {
|
||||
callOrder = createEmptyTuple();
|
||||
g108 = 0;
|
||||
getTensor_1X(g108 = 8).1 = assertEq(g108, 8);
|
||||
return (callOrder, g108);
|
||||
}
|
||||
|
||||
@method_id(109)
|
||||
fun test109() {
|
||||
callOrder = createEmptyTuple();
|
||||
var x = 0;
|
||||
[getTuple_12().0, getTuple_1X(x = getIntValue5()).1, getTuple_1X(x += 10).0] = [getIntValue5(), getIntValue5(), getIntValueX(x)];
|
||||
return (callOrder, x);
|
||||
}
|
||||
|
||||
global g110: int;
|
||||
global t110: (int, int);
|
||||
|
||||
@method_id(110)
|
||||
fun test110() {
|
||||
callOrder = createEmptyTuple();
|
||||
var xy = [0, 0];
|
||||
[xy.0, getTuple_1X(g110 = 8).0] = [g110 += 5, getIntValueX(g110 += 10)];
|
||||
[xy.1, getTuple_1X((t110 = (8, 9)).0).1] = [t110.0 += 5, getIntValueX(t110.1 += 10)];
|
||||
return (xy, callOrder, g110, t110);
|
||||
}
|
||||
|
||||
@method_id(111)
|
||||
fun test111() {
|
||||
callOrder = createEmptyTuple();
|
||||
var z = -1;
|
||||
var xy = [0, z = 0];
|
||||
var rhs = [getIntValueX(xy.1 += 10), xy.1, xy.0, z += 50];
|
||||
[xy.0, getTuple_1X(g110 = 8 + getIntValueX(xy.1)).0, xy.1, z] = rhs;
|
||||
return (xy, g110, callOrder, z);
|
||||
}
|
||||
|
||||
@method_id(112)
|
||||
fun test112() {
|
||||
var xy = [1, 2];
|
||||
((((xy))).0, ((xy.1))) = ((xy).1, ((xy.0)));
|
||||
return xy;
|
||||
}
|
||||
|
||||
@method_id(113)
|
||||
fun test113() {
|
||||
var (a, t, z) = (1, [2,3], (-1,-1));
|
||||
(a, t, a, z, t.1, z.1) = (10, [a,12], 13, (a, t.1), 14, t.1);
|
||||
return (a, t, z);
|
||||
}
|
||||
|
||||
global g114: int;
|
||||
global t114: [int, int];
|
||||
global z114: (int, int);
|
||||
|
||||
@method_id(114)
|
||||
fun test114() {
|
||||
g114 = 1;
|
||||
t114 = [2, 3];
|
||||
(g114, t114, g114, z114, t114.1, z114.1) = (10, [g114,12], 13, (g114, t114.1), 14, t114.1);
|
||||
return (g114, t114, z114);
|
||||
}
|
||||
|
||||
@method_id(115)
|
||||
fun test115() {
|
||||
callOrder = createEmptyTuple();
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
[getTensor_1X(x = 5).0, y] = getTuple_1X(x = 9);
|
||||
return (callOrder, x, y);
|
||||
}
|
||||
|
||||
@method_id(116)
|
||||
fun test116() {
|
||||
var (a,b,c,d) = (0,0,0,0);
|
||||
var rhs = [1, 2, 3, 4];
|
||||
var rhs2 = ([a,b,c,d] = rhs);
|
||||
__expect_type(rhs2, "[int, int, int, int]");
|
||||
return (a, b, c, d, rhs2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun main(value: int) {
|
||||
var (x: int, y) = (autoInferIntNull(value), autoInferIntNull(value * 2));
|
||||
if (x == null && y == null) { return null; }
|
||||
|
@ -37,4 +216,35 @@ fun main(value: int) {
|
|||
@testcase | 0 | 6 | -1
|
||||
@testcase | 0 | 11 | (null)
|
||||
@testcase | 101 | 78 | 88
|
||||
@testcase | 102 | | [ 100 10 101 10 101 11 ] 10
|
||||
@testcase | 103 | | [ 110 10 111 10 111 11 ] 10
|
||||
@testcase | 104 | | [ 120 10 121 10 121 11 ] 10
|
||||
@testcase | 105 | | [ 100 10 101 100 11 ]
|
||||
@testcase | 106 | | [ 110 10 111 110 11 ]
|
||||
@testcase | 107 | | 3 4
|
||||
@testcase | 108 | | [ 101 ] 8
|
||||
@testcase | 109 | | [ 110 10 111 111 10 10 11 ] 15
|
||||
@testcase | 110 | | [ 13 13 ] [ 111 11 111 11 ] 23 13 19
|
||||
@testcase | 111 | | [ 10 0 ] 18 [ 11 11 111 ] 50
|
||||
@testcase | 112 | | [ 2 1 ]
|
||||
@testcase | 113 | | 13 [ 1 14 ] 1 3
|
||||
@testcase | 114 | | 13 [ 1 14 ] 1 3
|
||||
@testcase | 115 | | [ 101 111 ] 9 9
|
||||
@testcase | 116 | | 1 2 3 4 [ 1 2 3 4 ]
|
||||
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test116 PROC:<{
|
||||
//
|
||||
1 PUSHINT // '10=1
|
||||
2 PUSHINT // '10=1 '11=2
|
||||
3 PUSHINT // '10=1 '11=2 '12=3
|
||||
4 PUSHINT // '10=1 '11=2 '12=3 '13=4
|
||||
4 TUPLE // rhs
|
||||
DUP // rhs rhs
|
||||
4 UNTUPLE // rhs2 a b c d
|
||||
4 ROLL // a b c d rhs2
|
||||
}>
|
||||
"""
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,7 @@ Below, I just give examples of @fif_codegen tag:
|
|||
"""
|
||||
main PROC:<{
|
||||
// s
|
||||
17 PUSHINT // s '1=17
|
||||
17 PUSHINT // s '3=17
|
||||
OVER // s z=17 t
|
||||
WHILE:<{
|
||||
...
|
||||
|
|
|
@ -21,6 +21,26 @@ fun plus(mutate self: int, y: int): int {
|
|||
|
||||
fun eq<X>(v: X): X { return v; }
|
||||
|
||||
global gTup: [int];
|
||||
global gTens: (int, int);
|
||||
|
||||
@method_id(100)
|
||||
fun testCodegenSimple() {
|
||||
var t1 = [1];
|
||||
t1.0 = 2;
|
||||
debugPrintString("");
|
||||
var t2 = [[1]];
|
||||
t2.0.0 = 2;
|
||||
debugPrintString("");
|
||||
gTup = [1];
|
||||
gTup.0 = 2;
|
||||
debugPrintString("");
|
||||
gTens = (1,2);
|
||||
gTens.1 = 4;
|
||||
debugPrintString("");
|
||||
return (t1, t2, gTup, gTens);
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun test101() {
|
||||
var t = (1, (2, 3), [4, 5, [6, 7]], 8);
|
||||
|
@ -241,30 +261,60 @@ fun main(){}
|
|||
|
||||
@fif_codegen
|
||||
"""
|
||||
testCodegenNoPureIndexedAccess PROC:<{
|
||||
testCodegenSimple PROC:<{
|
||||
//
|
||||
0 PUSHINT // '8=0
|
||||
1 PUSHINT // '2=1
|
||||
SINGLE // t1
|
||||
2 PUSHINT // t1 '3=2
|
||||
0 SETINDEX // t1
|
||||
x{} PUSHSLICE // t1 '6
|
||||
STRDUMP DROP
|
||||
1 PUSHINT // t1 '10=1
|
||||
SINGLE // t1 '9
|
||||
SINGLE // t1 t2
|
||||
2 PUSHINT // t1 t2 '11=2
|
||||
OVER // t1 t2 '11=2 t2
|
||||
0 INDEX // t1 t2 '11=2 '14
|
||||
SWAP // t1 t2 '14 '11=2
|
||||
0 SETINDEX // t1 t2 '14
|
||||
0 SETINDEX // t1 t2
|
||||
x{} PUSHSLICE // t1 t2 '17
|
||||
STRDUMP DROP
|
||||
1 PUSHINT // t1 t2 '20=1
|
||||
SINGLE // t1 t2 '18
|
||||
gTup SETGLOB
|
||||
2 PUSHINT // t1 t2 '21=2
|
||||
gTup GETGLOB // t1 t2 '21=2 g_gTup
|
||||
SWAP // t1 t2 g_gTup '21=2
|
||||
0 SETINDEX // t1 t2 g_gTup
|
||||
gTup SETGLOB
|
||||
x{} PUSHSLICE // t1 t2 '25
|
||||
STRDUMP DROP
|
||||
1 PUSHINT // t1 t2 '28=1
|
||||
2 PUSHINT // t1 t2 '26=1 '27=2
|
||||
PAIR
|
||||
gTens SETGLOB
|
||||
4 PUSHINT // t1 t2 g_gTens.1=4
|
||||
gTens GETGLOB
|
||||
UNPAIR // t1 t2 g_gTens.1=4 g_gTens.0 g_gTens.1
|
||||
DROP // t1 t2 g_gTens.1=4 g_gTens.0
|
||||
SWAP // t1 t2 g_gTens.0 g_gTens.1=4
|
||||
PAIR
|
||||
gTens SETGLOB
|
||||
x{} PUSHSLICE // t1 t2 '36
|
||||
STRDUMP DROP
|
||||
gTup GETGLOB // t1 t2 g_gTup
|
||||
gTens GETGLOB
|
||||
UNPAIR // t1 t2 g_gTup g_gTens.0 g_gTens.1
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test104 PROC:<{
|
||||
testCodegenNoPureIndexedAccess PROC:<{
|
||||
//
|
||||
5 PUSHINT // '2=5
|
||||
DUP // '2=5 '3=5
|
||||
PAIR // '1
|
||||
SINGLE // m
|
||||
10 PUSHINT // m '5=10
|
||||
20 PUSHINT // m '5=10 '6=20
|
||||
s2 PUSH // m '5=10 '6=20 m
|
||||
0 INDEX // m '10=10 '12=20 '8
|
||||
SWAP // m '10=10 '8 '12=20
|
||||
1 SETINDEX // m '10=10 '8
|
||||
SWAP // m '8 '10=10
|
||||
0 SETINDEX // m '8
|
||||
0 SETINDEX // m
|
||||
...
|
||||
0 PUSHINT // '8=0
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
fun main() {
|
||||
var c = 1;
|
||||
(c, c) = (2, 3);
|
||||
var t = createEmptyTuple();
|
||||
t.0 = (1, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr one variable modified twice inside the same expression
|
||||
@stderr a tuple can not have `(int, int)` inside, because it occupies 2 stack slots in TVM, not 1
|
||||
*/
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
fun incThree(mutate a: int, mutate b: int, mutate c: int) {}
|
||||
|
||||
fun main() {
|
||||
var c = [[[1, 2]]];
|
||||
incThree(mutate c.0.0.0, mutate c.0.0.1, mutate c.0.0.0);
|
||||
fun main(cs: slice) {
|
||||
var cb = cs.tupleSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr one variable modified twice inside the same expression
|
||||
@stderr referencing a method for `tuple` with object of type `slice`
|
||||
*/
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
global gg: (int, int);
|
||||
|
||||
fun main() {
|
||||
[gg.0, gg.1, gg.0] = [0, 1, 0];
|
||||
var t = createEmptyTuple();
|
||||
var xy = t.0 as (int, int);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr one variable modified twice inside the same expression
|
||||
@stderr a tuple can not have `(int, int)` inside, because it occupies 2 stack slots in TVM, not 1
|
||||
*/
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
global gg: (int, [int, int]);
|
||||
|
||||
fun main() {
|
||||
(gg.1.0, gg.1, gg.1.1) = (0, [1, 2], 3);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr one variable both modified and read inside the same expression
|
||||
*/
|
|
@ -1,9 +0,0 @@
|
|||
fun main() {
|
||||
var ab = (1, 2);
|
||||
(ab, ab.1) = ((2, 3), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr one variable both modified and read inside the same expression
|
||||
*/
|
|
@ -1,9 +0,0 @@
|
|||
fun main() {
|
||||
var t = createEmptyTuple();
|
||||
t.0 = (1, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr can not put `(int, int)` into a tuple, because it occupies 2 stack slots in TVM, not 1
|
||||
*/
|
|
@ -1,8 +0,0 @@
|
|||
fun main(cs: slice) {
|
||||
var cb = cs.tupleSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr referencing a method for `tuple` with object of type `slice`
|
||||
*/
|
|
@ -7,5 +7,5 @@ fun main() {
|
|||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr can not put `(int, builder)` into a tuple, because it occupies 2 stack slots in TVM, not 1
|
||||
@stderr a tuple can not have `(int, builder)` inside, because it occupies 2 stack slots in TVM, not 1
|
||||
*/
|
||||
|
|
|
@ -307,7 +307,7 @@ fun main(){}
|
|||
...
|
||||
incrementTwoInPlace CALLDICT // x y sum1
|
||||
-ROT
|
||||
10 PUSHINT // sum1 x y '10=10
|
||||
10 PUSHINT // sum1 x y '11=10
|
||||
incrementTwoInPlace CALLDICT // sum1 x y sum2
|
||||
s1 s3 s0 XCHG3 // x y sum1 sum2
|
||||
}>
|
||||
|
|
|
@ -133,7 +133,7 @@ fun main() {
|
|||
"""
|
||||
test7 PROC:<{
|
||||
...
|
||||
LDOPTREF // b '8 '7
|
||||
LDOPTREF // b '9 '8
|
||||
DROP // b c
|
||||
ISNULL // b '11
|
||||
10 MULCONST // b '13
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue