mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[Tolk] Get rid of ~tilda with mutate
and self
methods
This is a very big change. If FunC has `.methods()` and `~methods()`, Tolk has only dot, one and only way to call a `.method()`. A method may mutate an object, or may not. It's a behavioral and semantic difference from FunC. - `cs.loadInt(32)` modifies a slice and returns an integer - `b.storeInt(x, 32)` modifies a builder - `b = b.storeInt()` also works, since it not only modifies, but returns - chained methods also work, they return `self` - everything works exactly as expected, similar to JS - no runtime overhead, exactly same Fift instructions - custom methods are created with ease - tilda `~` does not exist in Tolk at all
This commit is contained in:
parent
12ff28ac94
commit
d9dba320cc
85 changed files with 2710 additions and 1965 deletions
|
@ -1,3 +1,5 @@
|
|||
import "@stdlib/tvm-lowlevel"
|
||||
|
||||
fun pair_first<X, Y>(p: [X, Y]): X asm "FIRST";
|
||||
|
||||
fun one(dummy: tuple) {
|
||||
|
@ -35,13 +37,34 @@ fun test88(x: int) {
|
|||
@method_id(89)
|
||||
fun test89(last: int) {
|
||||
var t: tuple = createEmptyTuple();
|
||||
t~tuplePush(1);
|
||||
t~tuplePush(2);
|
||||
t~tuplePush(3);
|
||||
t~tuplePush(last);
|
||||
t.tuplePush(1);
|
||||
t.tuplePush(2);
|
||||
t.tuplePush(3);
|
||||
t.tuplePush(last);
|
||||
return (t.tupleAt(0), t.tupleAt(t.tupleSize() - 1), t.tupleFirst(), t.tupleLast());
|
||||
}
|
||||
|
||||
@pure fun get10() { return 10; }
|
||||
|
||||
@method_id(91)
|
||||
fun touchCodegen2() {
|
||||
var f = get10();
|
||||
f.stackMoveToTop();
|
||||
return f;
|
||||
}
|
||||
|
||||
@method_id(92)
|
||||
fun testDumpDontPolluteStack() {
|
||||
var f = get10();
|
||||
f.debugPrint();
|
||||
debugPrint(10);
|
||||
var s = "asdf";
|
||||
s.debugPrintString();
|
||||
debugDumpStack();
|
||||
debugPrintString("my");
|
||||
return (f, getRemainingBitsCount(s));
|
||||
}
|
||||
|
||||
@method_id(93)
|
||||
fun testStartBalanceCodegen1() {
|
||||
var t = getMyOriginalBalanceWithExtraCurrencies();
|
||||
|
@ -65,7 +88,27 @@ fun testStartBalanceCodegen2() {
|
|||
@testcase | 88 | 5 | 234
|
||||
@testcase | 88 | 50 | 0
|
||||
@testcase | 89 | 4 | 1 4 1 4
|
||||
@testcase | 91 | | 10
|
||||
@testcase | 92 | | 10 32
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
touchCodegen2 PROC:<{
|
||||
//
|
||||
get10 CALLDICT // f
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testDumpDontPolluteStack PROC:<{
|
||||
...
|
||||
DUMPSTK
|
||||
x{6d79} PUSHSLICE // f s _9
|
||||
STRDUMP DROP
|
||||
SBITS // f _11
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
|
|
|
@ -4,8 +4,6 @@ fun f(a: int, b: int, c: int, d: int, e: int, f: int): (int, int) {
|
|||
return (Dx/D,Dy/D);
|
||||
};;;;
|
||||
|
||||
fun mulDivR(x: int, y: int, z: int): int { return mulDivRound(x, y, z); }
|
||||
|
||||
fun calc_phi(): int {
|
||||
var n = 1;
|
||||
repeat (70) { n*=10; };
|
||||
|
@ -14,7 +12,7 @@ fun calc_phi(): int {
|
|||
do {
|
||||
(p,q)=(q,p+q);
|
||||
} while (q <= n); //;;
|
||||
return mulDivR(p, n, q);
|
||||
return mulDivRound(p, n, q);
|
||||
}
|
||||
|
||||
fun calc_sqrt2(): int {
|
||||
|
@ -26,7 +24,7 @@ fun calc_sqrt2(): int {
|
|||
var t = p + q;
|
||||
(p, q) = (q, t + q);
|
||||
} while (q <= n);
|
||||
return mulDivR(p, n, q);
|
||||
return mulDivRound(p, n, q);
|
||||
}
|
||||
|
||||
fun calc_root(m: auto): auto {
|
||||
|
@ -63,18 +61,14 @@ fun ataninv(base: int, q: int): int { // computes base*atan(1/q)
|
|||
return sum;
|
||||
}
|
||||
|
||||
fun arctanInv(base: int, q: int): int { return ataninv(base, q); }
|
||||
|
||||
fun calc_pi(): int {
|
||||
var base: int = 64;
|
||||
repeat (70) { base *= 10; }
|
||||
return (arctanInv(base << 2, 5) - arctanInv(base, 239))~>>4;
|
||||
return (ataninv(base << 2, 5) - ataninv(base, 239))~>>4;
|
||||
}
|
||||
|
||||
fun calcPi(): int { return calc_pi(); }
|
||||
|
||||
fun main(): int {
|
||||
return calcPi();
|
||||
return calc_pi();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,12 +5,18 @@ fun main(a: int, b: int, c: int, d: int, e: int, f: int): (int, int) {
|
|||
return (Dx / D, Dy / D);
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun testDivMod(x: int, y: int) {
|
||||
return [divMod(x, y), modDiv(x, y), mulDivMod(x, y, 10)];
|
||||
}
|
||||
|
||||
/**
|
||||
method_id | in | out
|
||||
@testcase | 0 | 1 1 1 -1 10 6 | 8 2
|
||||
@testcase | 0 | 817 -31 624 -241 132272 272276 | 132 -788
|
||||
@testcase | 0 | -886 562 498 -212 -36452 -68958 | -505 -861
|
||||
@testcase | 0 | 448 -433 -444 792 150012 -356232 | -218 -572
|
||||
@testcase | 0 | -40 -821 433 -734 -721629 -741724 | -206 889
|
||||
@testcase | 0 | -261 -98 -494 868 -166153 733738 | 263 995
|
||||
method_id | in | out
|
||||
@testcase | 0 | 1 1 1 -1 10 6 | 8 2
|
||||
@testcase | 0 | 817 -31 624 -241 132272 272276 | 132 -788
|
||||
@testcase | 0 | -886 562 498 -212 -36452 -68958 | -505 -861
|
||||
@testcase | 0 | 448 -433 -444 792 150012 -356232 | -218 -572
|
||||
@testcase | 0 | -40 -821 433 -734 -721629 -741724 | -206 889
|
||||
@testcase | 0 | -261 -98 -494 868 -166153 733738 | 263 995
|
||||
@testcase | 101 | 112 3 | [ 37 1 1 37 33 6 ]
|
||||
*/
|
||||
|
|
|
@ -4,35 +4,32 @@ fun unsafe_tuple<X>(x: X): tuple
|
|||
fun inc(x: int, y: int): (int, int) {
|
||||
return (x + y, y * 10);
|
||||
}
|
||||
fun ~inc(x: int, y: int): (int, int) {
|
||||
(x, y) = inc(x, y);
|
||||
return (x, y);
|
||||
}
|
||||
|
||||
fun ~incWrap(x: int, y: int): (int, int) {
|
||||
return ~inc(x, y);
|
||||
fun `~inc`(mutate self: int, y: int): int {
|
||||
val (newX, newY) = inc(self, y);
|
||||
self = newX;
|
||||
return newY;
|
||||
}
|
||||
|
||||
@method_id(11)
|
||||
fun test_return(x: int): (int, int, int, int, int, int, int) {
|
||||
return (x, x~incWrap(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
return (x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
}
|
||||
|
||||
@method_id(12)
|
||||
fun test_assign(x: int): (int, int, int, int, int, int, int) {
|
||||
var (x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int) = (x, x~inc(x / 20), x, x=x*2, x, x+=1, x);
|
||||
var (x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int) = (x, x.`~inc`(x / 20), x, x=x*2, x, x+=1, x);
|
||||
return (x1, x2, x3, x4, x5, x6, x7);
|
||||
}
|
||||
|
||||
@method_id(13)
|
||||
fun test_tuple(x: int): tuple {
|
||||
var t: tuple = unsafe_tuple([x, x~incWrap(x / 20), x, x = x * 2, x, x += 1, x]);
|
||||
var t: tuple = unsafe_tuple([x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x]);
|
||||
return t;
|
||||
}
|
||||
|
||||
@method_id(14)
|
||||
fun test_tuple_assign(x: int): (int, int, int, int, int, int, int) {
|
||||
var [x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int] = [x, x~inc(x / 20), x, x = x * 2, x, x += 1, x];
|
||||
var [x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int] = [x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x];
|
||||
return (x1, x2, x3, x4, x5, x6, x7);
|
||||
}
|
||||
|
||||
|
@ -42,7 +39,7 @@ fun foo1(x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int): (int, i
|
|||
|
||||
@method_id(15)
|
||||
fun test_call_1(x: int): (int, int, int, int, int, int, int) {
|
||||
return foo1(x, x~inc(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
return foo1(x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
}
|
||||
|
||||
fun foo2(x1: int, x2: int, x3456: (int, int, int, int), x7: int): (int, int, int, int, int, int, int) {
|
||||
|
@ -52,7 +49,7 @@ fun foo2(x1: int, x2: int, x3456: (int, int, int, int), x7: int): (int, int, int
|
|||
|
||||
@method_id(16)
|
||||
fun test_call_2(x: int): (int, int, int, int, int, int, int) {
|
||||
return foo2(x, x~incWrap(x / 20), (x, x = x * 2, x, x += 1), x);
|
||||
return foo2(x, x.`~inc`(x / 20), (x, x = x * 2, x, x += 1), x);
|
||||
}
|
||||
|
||||
fun asm_func(x1: int, x2: int, x3: int, x4: int, x5: int, x6: int, x7: int): (int, int, int, int, int, int, int)
|
||||
|
@ -61,28 +58,28 @@ asm
|
|||
|
||||
@method_id(17)
|
||||
fun test_call_asm_old(x: int): (int, int, int, int, int, int, int) {
|
||||
return asm_func(x, x += 1, x, x, x~inc(x / 20), x, x = x * 2);
|
||||
return asm_func(x, x += 1, x, x, x.`~inc`(x / 20), x, x = x * 2);
|
||||
}
|
||||
|
||||
@method_id(18)
|
||||
fun test_call_asm_new(x: int): (int, int, int, int, int, int, int) {
|
||||
return asm_func(x, x~incWrap(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
return asm_func(x, x.`~inc`(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
}
|
||||
|
||||
global xx: int;
|
||||
@method_id(19)
|
||||
fun test_global(x: int): (int, int, int, int, int, int, int) {
|
||||
xx = x;
|
||||
return (xx, xx~incWrap(xx / 20), xx, xx = xx * 2, xx, xx += 1, xx);
|
||||
return (xx, xx.`~inc`(xx / 20), xx, xx = xx * 2, xx, xx += 1, xx);
|
||||
}
|
||||
|
||||
@method_id(20)
|
||||
fun test_if_else(x: int): (int, int, int, int, int) {
|
||||
if (x > 10) {
|
||||
return (x~inc(8), x + 1, x = 1, x <<= 3, x);
|
||||
return (x.`~inc`(8), x + 1, x = 1, x <<= 3, x);
|
||||
} else {
|
||||
xx = 9;
|
||||
return (x, x~inc(-4), x~inc(-1), x >= 1, x = x + xx);
|
||||
return (x, x.`~inc`(-4), x.`~inc`(-1), x >= 1, x = x + xx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +100,12 @@ fun main() {
|
|||
@testcase | 20 | 80 | 80 89 1 8 8
|
||||
@testcase | 20 | 9 | 9 -40 -10 -1 13
|
||||
|
||||
@fif_codegen_avoid ~incWrap
|
||||
@fif_codegen
|
||||
"""
|
||||
~inc PROC:<{
|
||||
// self y
|
||||
inc CALLDICT // self newY
|
||||
}>
|
||||
"""
|
||||
@code_hash 97139400653362069936987769894397430077752335662822462908581556703209313861576
|
||||
*/
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
fun empty_tuple2(): tuple
|
||||
asm "NIL";
|
||||
@pure
|
||||
fun tpush2<X>(t: tuple, x: X): (tuple, ())
|
||||
fun tpush2<X>(mutate self: tuple, x: X): void
|
||||
asm "TPUSH";
|
||||
fun myEmptyTuple(): tuple { return empty_tuple2(); }
|
||||
fun myTuplePush<X>(t: tuple, value: X): (tuple, ()) { return tpush2(t, value); }
|
||||
|
||||
@pure
|
||||
fun asm_func_1(x: int, y: int, z: int): tuple
|
||||
|
@ -20,31 +18,27 @@ asm (y z x -> 0) "3 TUPLE";
|
|||
fun asm_func_4(a: int, b: (int, (int, int)), c: int): tuple
|
||||
asm (b a c -> 0) "5 TUPLE";
|
||||
|
||||
fun asmFunc1(x: int, y: int, z: int): tuple { return asm_func_1(x, y, z); }
|
||||
fun asmFunc3(x: int, y: int, z: int): tuple { return asm_func_3(x, y, z); }
|
||||
|
||||
@pure
|
||||
fun asm_func_modify(a: tuple, b: int, c: int): (tuple, ())
|
||||
asm (c b a -> 0) "SWAP TPUSH SWAP TPUSH";
|
||||
fun asmFuncModify(a: tuple, b: int, c: int): (tuple, ()) { return asm_func_modify(a, b, c); }
|
||||
fun asm_func_modify(mutate self: tuple, b: int, c: int): void
|
||||
asm (c b self) "SWAP TPUSH SWAP TPUSH";
|
||||
|
||||
global t: tuple;
|
||||
|
||||
fun foo(x: int): int {
|
||||
t~myTuplePush(x);
|
||||
t.tpush2(x);
|
||||
return x * 10;
|
||||
}
|
||||
|
||||
@method_id(11)
|
||||
fun test_old_1(): (tuple, tuple) {
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = asmFunc1(foo(11), foo(22), foo(33));
|
||||
var t2: tuple = asm_func_1(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
@method_id(12)
|
||||
fun test_old_2(): (tuple, tuple) {
|
||||
t = myEmptyTuple();
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = asm_func_2(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
@ -58,7 +52,7 @@ fun test_old_3(): (tuple, tuple) {
|
|||
|
||||
@method_id(14)
|
||||
fun test_old_4(): (tuple, tuple) {
|
||||
t = myEmptyTuple();
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = empty_tuple2();
|
||||
// This actually computes left-to-right even without compute-asm-ltr
|
||||
t2 = asm_func_4(foo(11), (foo(22), (foo(33), foo(44))), foo(55));
|
||||
|
@ -69,21 +63,21 @@ fun test_old_4(): (tuple, tuple) {
|
|||
fun test_old_modify(): (tuple, tuple) {
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = empty_tuple2();
|
||||
t2~asmFuncModify(foo(22), foo(33));
|
||||
t2.asm_func_modify(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
@method_id(16)
|
||||
fun test_old_dot(): (tuple, tuple) {
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = foo(11).asmFunc3(foo(22), foo(33));
|
||||
var t2: tuple = foo(11).asm_func_3(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
@method_id(21)
|
||||
fun test_new_1(): (tuple, tuple) {
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = asmFunc1(foo(11), foo(22), foo(33));
|
||||
var t2: tuple = asm_func_1(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
|
@ -112,7 +106,7 @@ fun test_new_4(): (tuple, tuple) {
|
|||
fun test_new_modify(): (tuple, tuple) {
|
||||
t = empty_tuple2();
|
||||
var t2: tuple = empty_tuple2();
|
||||
t2~asm_func_modify(foo(22), foo(33));
|
||||
t2.asm_func_modify(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
// Here we test "functions that just wrap other functions" (camelCase in particular):
|
||||
// > builder beginCell() { return begin_cell(); }
|
||||
// Such functions, when called, are explicitly inlined during code generation (even without `inline` modifier).
|
||||
// It means, that `beginCell()` is replaced to `begin_cell()` (and effectively to `NEWC`).
|
||||
// Moreover, body of `beginCell` is NOT codegenerated at all.
|
||||
// Hence, we can write camelCase wrappers (as well as more intelligible namings around stdlib functions)
|
||||
// without affecting performance and even bytecode hashes.
|
||||
// This works with ~functions also. And even works with wrappers of wrappers.
|
||||
// Moreover, such wrappers can reorder input parameters, see a separate test camel2.tolk.
|
||||
import "@stdlib/tvm-dicts"
|
||||
|
||||
fun myBeginCell(): builder { return beginCell(); }
|
||||
fun myEndCell(b: builder): cell { return endCell(b); }
|
||||
fun myStoreRef(b: builder, c: cell): builder { return storeRef(b, c); }
|
||||
fun myStoreUint(b: builder, i: int, bw: int): builder { return storeUint(b, i, bw); }
|
||||
|
||||
// 'inline' is not needed actually, but if it exists, it's just ignored
|
||||
@inline
|
||||
@pure
|
||||
fun myBeginParse(c: cell): slice { return beginParse(c); }
|
||||
@inline
|
||||
@pure
|
||||
fun mySkipBits(s: slice, len: int): slice { return skipBits(s, len); }
|
||||
@inline
|
||||
@pure
|
||||
fun ~mySkipBits(s: slice, len: int): (slice, ()) { return ~skipBits(s, len); }
|
||||
@inline
|
||||
@pure
|
||||
fun ~myLoadUint(s: slice, len: int): (slice, int) { return loadUint(s, len); }
|
||||
|
||||
fun myComputeDataSize(c: cell, maxCells: int): (int, int, int) { return calculateCellSizeStrict(c, maxCells); }
|
||||
|
||||
fun dict__new(): cell { return createEmptyDict(); }
|
||||
fun dict__iset(dict: cell, keyLen: int, index: int, value: slice): cell { return iDictSet(dict, keyLen, index, value); }
|
||||
fun ~dict__iset(dict: cell, keyLen: int, index: int, value: slice): (cell, ()) { return ~iDictSet(dict, keyLen, index, value); }
|
||||
fun dict__tryIGet(dict: cell, keyLen: int, index: int): (slice, int) { return iDictGet(dict, keyLen, index); }
|
||||
fun dict__tryIGetMin(dict: cell, keyLen: int): (int, slice, int) { return iDictGetFirst(dict, keyLen); }
|
||||
|
||||
@pure
|
||||
fun triple_second<X, Y, Z>(p: [X, Y, Z]): Y
|
||||
asm "SECOND";
|
||||
|
||||
fun myEmptyTuple(): tuple { return createEmptyTuple(); }
|
||||
fun emptyTuple1(): tuple { return myEmptyTuple(); }
|
||||
fun emptyTuple11(): tuple { return emptyTuple1(); }
|
||||
fun myTuplePush<X>(t: tuple, value: X): tuple { return tuplePush(t, value); }
|
||||
fun ~myTuplePush<X>(t: tuple, value: X): (tuple, ()) { return ~tuplePush(t, value); }
|
||||
fun myTupleAt<X>(t: tuple, index: int): X { return tupleAt(t, index); }
|
||||
fun tripleSecond<X1, Y2, Z3>(p: [X1, Y2, Z3]): Y2 { return triple_second(p); }
|
||||
@pure
|
||||
fun nullValue<X>(): X
|
||||
asm "PUSHNULL";
|
||||
|
||||
fun initial1(x: tuple): tuple { return x; }
|
||||
fun initial2(x: tuple): tuple { return initial1(x); }
|
||||
|
||||
// int add(int x, int y) { return x + y; } // this is also a wrapper, as its body is _+_(x,y)
|
||||
|
||||
fun fake1(a: int, b: int, c: int): void
|
||||
asm(a b c) "DROP DROP DROP";
|
||||
fun fake2(a: int, b: int, c: int): void
|
||||
asm(b c a) "DROP DROP DROP";
|
||||
fun fake3(a: int, b: int, c: int): ()
|
||||
asm(c a b) "DROP DROP DROP";
|
||||
fun fake4(a: int, b: int, c: int): ()
|
||||
asm(c b a) "DROP DROP DROP";
|
||||
|
||||
fun fake1Wrapper(a: int, b: int, c: int) { return fake1(a, b, c); }
|
||||
fun fake2Wrapper(a: int, b: int, c: int) { return fake2(a, b, c); }
|
||||
fun fake3Wrapper(a: int, b: int, c: int) { return fake3(a, b, c); }
|
||||
fun fake4Wrapper(a: int, b: int, c: int) { return fake4(a, b, c); }
|
||||
|
||||
@method_id(101)
|
||||
fun test1(): [int, int, int] {
|
||||
var x: int = 1;
|
||||
var y: int = 1;
|
||||
var to_be_ref: cell = myBeginCell().myEndCell();
|
||||
var in_c: builder = myBeginCell().myStoreUint(123, 8);
|
||||
in_c = myStoreRef(in_c, to_be_ref);
|
||||
var (a, b, c) = myComputeDataSize(in_c.myEndCell(), 10);
|
||||
assert(!(b != 8)) throw 101;
|
||||
assert(!(c != 1), 101);
|
||||
return [a, b + x, c + y];
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun test2(): [[int, int, int], int, int, int] {
|
||||
var dict: cell = dict__new();
|
||||
dict = dict__iset(dict, 32, 456, myBeginCell().myStoreUint(4560, 32).myEndCell().myBeginParse());
|
||||
dict.dict__iset(32, 789, myBeginCell().myStoreUint(7890, 32).myEndCell().myBeginParse());
|
||||
dict~dict__iset(32, 123, myBeginCell().myStoreUint(0, 64).myStoreUint(1230, 32).myStoreUint(1231, 32).myStoreUint(1232, 32).myEndCell().myBeginParse());
|
||||
|
||||
var (mink, minv, _) = dict__tryIGetMin(dict, 32);
|
||||
// skip 64 bits
|
||||
minv~mySkipBits(16);
|
||||
minv = minv.mySkipBits(16);
|
||||
minv.mySkipBits(11); // does nothing
|
||||
(minv, _) = ~mySkipBits(minv, 16);
|
||||
mySkipBits(minv, 11); // does nothing
|
||||
minv~mySkipBits(16);
|
||||
// load 3*32
|
||||
var minv1 = minv~myLoadUint(32);
|
||||
var minv2 = minv~myLoadUint(32);
|
||||
var minv3 = minv~myLoadUint(32);
|
||||
|
||||
var (_, found123) = dict__tryIGet(dict, 32, 123);
|
||||
var (_, found456) = dict__tryIGet(dict, 32, 456);
|
||||
var (_, found789) = dict__tryIGet(dict, 32, 789);
|
||||
return [[minv1, minv2, minv3], found123, found456, found789];
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun test3(): tuple {
|
||||
var with34: tuple = initial2(emptyTuple1());
|
||||
with34~myTuplePush(34);
|
||||
|
||||
var t: tuple = emptyTuple11();
|
||||
t = myTuplePush(t, 12);
|
||||
myTuplePush(t, emptyTuple11()); // does nothing
|
||||
t~myTuplePush(emptyTuple1());
|
||||
t~myTuplePush(with34.myTupleAt(0));
|
||||
t.myTuplePush("123"s); // does nothing
|
||||
|
||||
var tri: [cell, int, cell] = [nullValue(), 90 + 1, null];
|
||||
var f: int = tripleSecond(tri);
|
||||
(t, _) = ~myTuplePush(t, f);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
@method_id(104)
|
||||
fun test4(a: int, b: int, c: int): int {
|
||||
fake1Wrapper(a, b, c);
|
||||
fake2Wrapper(a, b, c);
|
||||
fake3Wrapper(a, b, c);
|
||||
fake4Wrapper(a, b, c);
|
||||
return 10;
|
||||
}
|
||||
|
||||
fun main(): int {
|
||||
var x: int = now();
|
||||
return 30;
|
||||
}
|
||||
|
||||
/**
|
||||
method_id | in | out
|
||||
@testcase | 101 | | [ 2 9 2 ]
|
||||
@testcase | 102 | | [ [ 1230 1231 1232 ] -1 -1 0 ]
|
||||
@testcase | 103 | | [ 12 [] 34 91 ]
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
main PROC:<{
|
||||
//
|
||||
30 PUSHINT
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test1 PROC:<{
|
||||
//
|
||||
NEWC // _5
|
||||
ENDC // to_be_ref
|
||||
NEWC // to_be_ref _8
|
||||
123 PUSHINT // to_be_ref _8 _9=123
|
||||
SWAP // to_be_ref _9=123 _8
|
||||
8 STU // to_be_ref in_c
|
||||
STREF // in_c
|
||||
ENDC // _16
|
||||
10 PUSHINT // _16 _17=10
|
||||
CDATASIZE // a b c
|
||||
OVER // a b c b
|
||||
8 NEQINT // a b c _21
|
||||
101 THROWIF
|
||||
DUP // a b c c
|
||||
1 NEQINT // a b c _26
|
||||
101 THROWIF
|
||||
SWAP // a c b
|
||||
INC // a c _30
|
||||
SWAP // a _30 c
|
||||
INC // a _30 _31
|
||||
TRIPLE // _29
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test2 PROC:<{
|
||||
...
|
||||
16 PUSHINT // dict minv _45=16
|
||||
SDSKIPFIRST // dict minv
|
||||
16 PUSHINT // dict minv _47=16
|
||||
SDSKIPFIRST // dict minv
|
||||
16 PUSHINT // dict minv _52=16
|
||||
SDSKIPFIRST // dict minv
|
||||
16 PUSHINT // dict minv _57=16
|
||||
SDSKIPFIRST // dict minv
|
||||
...
|
||||
32 PUSHINT // dict minv1 minv2 minv3 found123 found456 _83=32
|
||||
789 PUSHINT // dict minv1 minv2 minv3 found123 found456 _83=32 _84=789
|
||||
s0 s7 s7 XCHG3 // found456 minv1 minv2 minv3 found123 _84=789 dict _83=32
|
||||
DICTIGET
|
||||
NULLSWAPIFNOT // found456 minv1 minv2 minv3 found123 _101 _102
|
||||
NIP // found456 minv1 minv2 minv3 found123 found789
|
||||
...
|
||||
4 TUPLE // _86
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test3 PROC:<{
|
||||
//
|
||||
NIL // _1
|
||||
initial1 CALLDICT // with34
|
||||
...
|
||||
TRIPLE // t tri
|
||||
SECOND // t f
|
||||
TPUSH // t
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test4 PROC:<{
|
||||
// a b c
|
||||
s2 s1 s0 PUSH3 // a b c a b c
|
||||
DROP DROP DROP
|
||||
s1 s0 s2 PUSH3 // a b c b c a
|
||||
DROP DROP DROP
|
||||
s0 s2 s1 PUSH3 // a b c c a b
|
||||
DROP DROP DROP
|
||||
s0 s2 XCHG // c b a
|
||||
DROP DROP DROP
|
||||
10 PUSHINT // _7=10
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen_avoid DECLPROC myBeginCell
|
||||
@fif_codegen_avoid DECLPROC myStoreUint
|
||||
@fif_codegen_avoid DECLPROC myStoreRef
|
||||
@fif_codegen_avoid DECLPROC myComputeDataSize
|
||||
@fif_codegen_avoid DECLPROC tryIdictGet
|
||||
@fif_codegen_avoid DECLPROC myEmptyTuple
|
||||
@fif_codegen_avoid DECLPROC myStoreUint
|
||||
@fif_codegen_avoid DECLPROC initial2
|
||||
@fif_codegen_avoid DECLPROC add
|
||||
@fif_codegen_avoid DECLPROC increase
|
||||
*/
|
|
@ -1,204 +0,0 @@
|
|||
// Here we also test "functions that just wrap other functions" like in camel1.tolk,
|
||||
// but when they reorder arguments, e.g.
|
||||
// > T f(x,y) { return anotherF(y,x); }
|
||||
// This also works, even for wrappers of wrappers, even if anotherF is asm(with reorder).
|
||||
// But swapping arguments may sometimes lead to bytecode changes (see test2),
|
||||
// both with compute-asm-ltr and without it.
|
||||
|
||||
fun myBeginCell(): builder { return beginCell(); }
|
||||
fun myEndCell(b: builder): cell { return endCell(b); }
|
||||
fun myStoreRef1(b: builder, c: cell): builder { return storeRef(b, c); }
|
||||
fun myStoreRef2(c: cell, b: builder): builder { return storeRef(b, c); }
|
||||
fun myStoreUint1(b: builder, x: int, bw: int): builder { return storeUint(b, x, bw); }
|
||||
fun myStoreUint2(b: builder, bw: int, x: int): builder { return storeUint(b, x, bw); }
|
||||
|
||||
fun computeDataSize1(c: cell, maxCells: int): (int, int, int) { return calculateCellSizeStrict(c, maxCells); }
|
||||
fun computeDataSize2(maxCells: int, c: cell): (int, int, int) { return calculateCellSizeStrict(c, maxCells); }
|
||||
|
||||
fun fake(a: int, b: int, c: int): void
|
||||
asm "DROP DROP DROP";
|
||||
fun fake2(b: int, c: int, a: int) { return fake(a,b,c); }
|
||||
fun fake3(c: int, a: int, b: int) { return fake(a,b,c); }
|
||||
fun fake4(c: int, b: int, a: int) { return fake(a,b,c); }
|
||||
|
||||
@method_id(101)
|
||||
fun test1(): (int, int, int) {
|
||||
var x: int = 1;
|
||||
var y: int = 1;
|
||||
var to_be_ref: cell = myBeginCell().myEndCell();
|
||||
var in_c: builder = myBeginCell().myStoreUint1(123, 8);
|
||||
in_c = myStoreRef1(in_c, to_be_ref);
|
||||
var (a, b, c) = computeDataSize1(in_c.myEndCell(), 10);
|
||||
assert(!0, 101);
|
||||
return (a, b + x, c + y);
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun test2(): (int, int, int) {
|
||||
var x: int = 1;
|
||||
var y: int = 1;
|
||||
var to_be_ref: cell = myBeginCell().myEndCell();
|
||||
var in_c: builder = myBeginCell().myStoreUint2(8, 123);
|
||||
in_c = myStoreRef2(to_be_ref, in_c);
|
||||
var (a, b, c) = computeDataSize2(10, in_c.myEndCell());
|
||||
return (a, b + x, c + y);
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun test3(): (int, int, int) {
|
||||
var x: int = 1;
|
||||
var y: int = 1;
|
||||
var to_be_ref: cell = beginCell().endCell();
|
||||
var in_c: builder = beginCell().storeUint(123, 8);
|
||||
in_c = storeRef(in_c, to_be_ref);
|
||||
var (a, b, c) = calculateCellSizeStrict(in_c.endCell(), 10);
|
||||
return (a, b + x, c + y);
|
||||
}
|
||||
|
||||
fun beginCell1(): builder { return beginCell(); }
|
||||
fun beginCell11(): builder { return beginCell1(); }
|
||||
fun beginCell111(): builder { return beginCell11(); }
|
||||
|
||||
fun endCell1(b: builder): cell { return endCell(b); }
|
||||
fun endCell11(b: builder): cell { return endCell1(b); }
|
||||
|
||||
fun beginParse1(c: cell): slice { return beginParse(c); }
|
||||
fun beginParse11(c: cell): slice { return beginParse1(c); }
|
||||
|
||||
fun storeInt1(b: builder, bw: int, x: int): builder { return storeInt(b, x, bw); }
|
||||
fun storeInt11(bw: int, x: int, b: builder): builder { return storeInt1(b, bw, x); }
|
||||
fun storeInt111(b: builder, x: int, bw: int): builder { return storeInt11(bw, x, b); }
|
||||
|
||||
@method_id(104)
|
||||
fun test4(): slice {
|
||||
var b: builder = beginCell111();
|
||||
b = storeInt11(32, 1, b);
|
||||
b = storeInt111(b, 2, 32).storeInt111(3, 32);
|
||||
return b.endCell11().beginParse11();
|
||||
}
|
||||
|
||||
@method_id(105)
|
||||
fun test5(a: int, b: int, c: int): int {
|
||||
fake(a, b, c);
|
||||
fake2(b, c, a);
|
||||
fake3(c, a, b);
|
||||
fake4(c, b, a);
|
||||
return a;
|
||||
}
|
||||
|
||||
fun main() {
|
||||
throw 0;
|
||||
}
|
||||
|
||||
/**
|
||||
method_id | in | out
|
||||
@testcase | 101 | | 2 9 2
|
||||
@testcase | 102 | | 2 9 2
|
||||
@testcase | 103 | | 2 9 2
|
||||
@testcase | 104 | | CS{Cell{0018000000010000000200000003} bits: 0..96; refs: 0..0}
|
||||
|
||||
test1 and test3 fif code is absolutely identical, test2 (due to reorder) is a bit different:
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test1 PROC:<{
|
||||
//
|
||||
NEWC // _5
|
||||
ENDC // to_be_ref
|
||||
NEWC // to_be_ref _8
|
||||
123 PUSHINT // to_be_ref _8 _9=123
|
||||
SWAP // to_be_ref _9=123 _8
|
||||
8 STU // to_be_ref in_c
|
||||
STREF // in_c
|
||||
ENDC // _16
|
||||
10 PUSHINT // _16 _17=10
|
||||
CDATASIZE // a b c
|
||||
SWAP // a c b
|
||||
INC // a c _23
|
||||
SWAP // a _23 c
|
||||
INC // a _23 _24
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test2 PROC:<{
|
||||
//
|
||||
NEWC // _5
|
||||
ENDC // to_be_ref
|
||||
NEWC // to_be_ref _8
|
||||
123 PUSHINT // to_be_ref _8 _10=123
|
||||
SWAP // to_be_ref _10=123 _8
|
||||
8 STU // to_be_ref in_c
|
||||
STREF // in_c
|
||||
10 PUSHINT
|
||||
SWAP
|
||||
ENDC
|
||||
SWAP
|
||||
CDATASIZE // a b c
|
||||
SWAP // a c b
|
||||
INC // a c _19
|
||||
SWAP // a _19 c
|
||||
INC // a _19 _20
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test3 PROC:<{
|
||||
//
|
||||
NEWC // _5
|
||||
ENDC // to_be_ref
|
||||
NEWC // to_be_ref _8
|
||||
123 PUSHINT // to_be_ref _8 _9=123
|
||||
SWAP // to_be_ref _9=123 _8
|
||||
8 STU // to_be_ref in_c
|
||||
STREF // in_c
|
||||
ENDC // _16
|
||||
10 PUSHINT // _16 _17=10
|
||||
CDATASIZE // a b c
|
||||
SWAP // a c b
|
||||
INC // a c _19
|
||||
SWAP // a _19 c
|
||||
INC // a _19 _20
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test4 PROC:<{
|
||||
//
|
||||
NEWC // b
|
||||
1 PUSHINT // b _3=1
|
||||
SWAP // _3=1 b
|
||||
32 STI // b
|
||||
2 PUSHINT
|
||||
SWAP // _5=2 b
|
||||
32 STI
|
||||
3 PUSHINT
|
||||
SWAP
|
||||
32 STI // b
|
||||
ENDC // _11
|
||||
CTOS // _12
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test5 PROC:<{
|
||||
// a b c
|
||||
s2 s1 s0 PUSH3 // a b c a b c
|
||||
DROP DROP DROP
|
||||
s2 s1 s0 PUSH3 // a b c a b c
|
||||
DROP DROP DROP
|
||||
s2 s1 s0 PUSH3 // a b c a b c
|
||||
DROP DROP DROP
|
||||
s2 PUSH
|
||||
-ROT // a a b c
|
||||
DROP DROP DROP
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen_avoid myStoreUint1
|
||||
@fif_codegen_avoid myStoreUint2
|
||||
*/
|
|
@ -1,95 +0,0 @@
|
|||
// Here we test that if you declare a wrapper like
|
||||
// > builder beginCell() { return begin_cell(); }
|
||||
// but use it NOT only as a direct call, BUT as a 1-st class function
|
||||
// (save to a variable, return from a function, etc.)
|
||||
// it also works, since a function becomes codegenerated (though direct calls are expectedly inlined).
|
||||
|
||||
fun myBeginCell(): builder { return beginCell(); }
|
||||
fun myEndCell(b: builder): cell { return endCell(b); }
|
||||
fun myStoreRef(b: builder, c: cell): builder { return storeRef(b, c); }
|
||||
fun myStoreUint3(i: int, bw: int, b: builder): builder { return storeUint(b, i, bw); }
|
||||
|
||||
fun computeDataSize2(maxCells: int, c: cell): (int, int, int) { return calculateCellSizeStrict(c, maxCells); }
|
||||
|
||||
fun myEmptyTuple(): tuple { return createEmptyTuple(); }
|
||||
fun myTuplePush<X>(t: tuple, value: X): tuple { return tuplePush(t, value); }
|
||||
fun ~myTuplePush<X>(t: tuple, value: X): (tuple, ()) { return ~tuplePush(t, value); }
|
||||
fun myTupleGetFirst<X>(t: tuple): X { return tupleFirst(t); }
|
||||
|
||||
|
||||
@inline
|
||||
fun getBeginEnd(): (auto, auto) {
|
||||
return (myBeginCell, myEndCell);
|
||||
}
|
||||
|
||||
fun begAndStore(beg: auto, store: auto, x: int): builder {
|
||||
return store(x, 8, beg());
|
||||
}
|
||||
|
||||
fun test1(): (int, int, int) {
|
||||
var (_, computer) = (0, computeDataSize2);
|
||||
var (beg, end) = getBeginEnd();
|
||||
|
||||
var t: tuple = myEmptyTuple();
|
||||
t~myTuplePush(myStoreRef);
|
||||
var refStorer = myTupleGetFirst(t);
|
||||
|
||||
var x: int = 1;
|
||||
var y: int = 1;
|
||||
var to_be_ref: cell = myBeginCell().myEndCell();
|
||||
var in_c: builder = begAndStore(beg, myStoreUint3, 123);
|
||||
in_c = refStorer(in_c, to_be_ref);
|
||||
var (a, b, c) = computer(10, end(in_c));
|
||||
return (a, b + x, c + y);
|
||||
}
|
||||
|
||||
fun main(): (int, int, int) {
|
||||
return test1();
|
||||
}
|
||||
|
||||
/**
|
||||
method_id | in | out
|
||||
@testcase | 0 | | 2 9 2
|
||||
|
||||
@fif_codegen DECLPROC myBeginCell
|
||||
@fif_codegen DECLPROC computeDataSize2
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
myStoreUint3 PROC:<{
|
||||
// i bw b
|
||||
SWAP // i b bw
|
||||
STUX // _3
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
myStoreRef PROC:<{
|
||||
// b c
|
||||
SWAP // c b
|
||||
STREF // _2
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
CONT:<{
|
||||
computeDataSize2 CALLDICT
|
||||
}> // computer
|
||||
getBeginEnd INLINECALLDICT // computer beg end
|
||||
NIL // computer beg end t
|
||||
...
|
||||
NEWC // computer beg end refStorer _19
|
||||
ENDC // computer beg end refStorer to_be_ref
|
||||
...
|
||||
CONT:<{
|
||||
myStoreUint3 CALLDICT
|
||||
}>
|
||||
...
|
||||
begAndStore CALLDICT // computer to_be_ref end refStorer in_c
|
||||
"""
|
||||
|
||||
@fif_codegen_avoid myEmptyTuple
|
||||
@fif_codegen_avoid myTuplePush
|
||||
*/
|
|
@ -1,145 +0,0 @@
|
|||
// Here we test that a just-return function is not a valid wrapper, it will not be inlined.
|
||||
// (doesn't use all arguments, has different pureness, has method_id, etc.)
|
||||
|
||||
fun myStoreUint(b: builder, x: int, unused: int): builder { return storeUint(b, x, x); }
|
||||
fun throwIf(excNo: int, cond: int) { assert(!cond) throw excNo; }
|
||||
|
||||
fun initial1(x: auto) { return x; }
|
||||
fun initial2(x: auto) { return initial1(x); }
|
||||
|
||||
@pure
|
||||
fun asm_func_4(a: int, b: (int, (int, int)), c: int): tuple
|
||||
asm (b a c -> 0) "5 TUPLE";
|
||||
fun asmFunc4(a: int, b: (int, (int, int)), c: int): tuple { return asm_func_4(a, b, c); }
|
||||
|
||||
fun postpone_elections(): int {
|
||||
return false;
|
||||
}
|
||||
|
||||
fun setAndGetData(ret: int): int {
|
||||
var c: cell = beginCell().storeUint(ret, 8).endCell();
|
||||
setContractData(c);
|
||||
var s: slice = getContractData().beginParse();
|
||||
throwIf(101, 0);
|
||||
return s~loadUint(8);
|
||||
}
|
||||
|
||||
fun setAndGetDataWrapper(ret: int): int {
|
||||
return setAndGetData(ret);
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun test1(): int {
|
||||
var c: cell = beginCell().myStoreUint(32, 10000000).endCell();
|
||||
var s: slice = c.beginParse();
|
||||
return s~loadUint(32);
|
||||
}
|
||||
|
||||
get fun test2(ret: int): int {
|
||||
return setAndGetDataWrapper(ret);
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun test3(): int {
|
||||
return initial2(10);
|
||||
}
|
||||
|
||||
global t: tuple;
|
||||
|
||||
fun foo(x: int): int {
|
||||
t~tuplePush(x);
|
||||
return x * 10;
|
||||
}
|
||||
|
||||
@method_id(104)
|
||||
fun test4(): (tuple, tuple) {
|
||||
t = createEmptyTuple();
|
||||
var t2: tuple = asmFunc4(foo(11), (foo(22), (foo(33), foo(44))), foo(55));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
@method_id(105)
|
||||
fun test5(): int {
|
||||
if (1) {
|
||||
return postpone_elections();
|
||||
}
|
||||
return 123;
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
fun test6(): int {
|
||||
return add2(1, 2); // doesn't inline since declared below
|
||||
}
|
||||
|
||||
fun main(ret: int): int {
|
||||
return setAndGetDataWrapper(ret);
|
||||
}
|
||||
|
||||
fun onExternalMessage(ret: int): int {
|
||||
return setAndGetData(ret);
|
||||
}
|
||||
|
||||
// currently, functions implemented after usage, can't be inlined, since inlining is legacy, not AST
|
||||
fun add2(x: int, y: int): int { return x + y; }
|
||||
|
||||
/**
|
||||
method_id | in | out
|
||||
@testcase | 101 | | 32
|
||||
@testcase | 103 | | 10
|
||||
@testcase | 104 | | [ 11 22 33 44 55 ] [ 220 330 440 110 550 ]
|
||||
@testcase | 105 | | 0
|
||||
@testcase | 106 | | 3
|
||||
@testcase | 74435 | 99 | 99
|
||||
@testcase | 0 | 98 | 98
|
||||
@testcase | -1 | 97 | 97
|
||||
|
||||
@fif_codegen DECLPROC myStoreUint
|
||||
@fif_codegen DECLPROC throwIf
|
||||
@fif_codegen DECLPROC postpone_elections
|
||||
@fif_codegen DECLPROC add2
|
||||
@fif_codegen 74435 DECLMETHOD test2
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test3 PROC:<{
|
||||
//
|
||||
10 PUSHINT // _0=10
|
||||
initial2 CALLDICT // _1
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test2 PROC:<{
|
||||
// ret
|
||||
setAndGetData CALLDICT // _1
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
11 PUSHINT
|
||||
foo CALLDICT
|
||||
22 PUSHINT
|
||||
foo CALLDICT
|
||||
33 PUSHINT
|
||||
foo CALLDICT
|
||||
44 PUSHINT
|
||||
foo CALLDICT
|
||||
55 PUSHINT
|
||||
foo CALLDICT
|
||||
asmFunc4 CALLDICT // t2
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
test6 PROC:<{
|
||||
//
|
||||
1 PUSHINT // _0=1
|
||||
2 PUSHINT // _0=1 _1=2
|
||||
add2 CALLDICT // _2
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen_avoid setAndGetDataWrapper
|
||||
*/
|
|
@ -1,121 +1,136 @@
|
|||
fun store_u32(b: builder, value: int): builder {
|
||||
return b.storeUint(value, 32);
|
||||
}
|
||||
fun ~store_u32(b: builder, value: int): (builder, ()) {
|
||||
return ~storeUint(b, value, 32);
|
||||
fun store_u32(mutate self: builder, value: int): self {
|
||||
return self.storeUint(value, 32);
|
||||
}
|
||||
|
||||
fun load_u32(cs: slice): (slice, int) {
|
||||
return cs.loadUint(32);
|
||||
fun load_u32(mutate self: slice): int {
|
||||
return self.loadUint(32);
|
||||
}
|
||||
|
||||
fun my_loadInt(s: slice, len: int): (slice, int)
|
||||
asm(s len -> 1 0) "LDIX"; // top is "value slice"
|
||||
fun my_storeInt(b: builder, x: int, len: int): builder
|
||||
asm(x b len) "STIX";
|
||||
fun ~my_storeInt(b: builder, x: int, len: int): (builder, ())
|
||||
asm(x b len) "STIX";
|
||||
fun myLoadInt(mutate self: slice, len: int): int
|
||||
asm(-> 1 0) "LDIX";
|
||||
fun myStoreInt(mutate self: builder, x: int, len: int): self
|
||||
asm(x self len) "STIX";
|
||||
|
||||
@method_id(101)
|
||||
fun test1(): [int,int,int,int,int] {
|
||||
var b: builder = beginCell().storeUint(1, 32);
|
||||
b = b.storeUint(2, 32);
|
||||
b~storeUint(3, 32);
|
||||
b.storeUint(3, 32);
|
||||
b = b.store_u32(4);
|
||||
b~store_u32(5);
|
||||
b.store_u32(5);
|
||||
|
||||
var cs: slice = b.endCell().beginParse();
|
||||
var (cs redef, one: int) = cs.loadUint(32);
|
||||
var (two: int, three: int) = (cs~loadUint(32), cs~load_u32());
|
||||
var (cs redef, four: int) = cs.load_u32();
|
||||
var five: int = cs~load_u32();
|
||||
var one: int = cs.loadUint(32);
|
||||
var (two: int, three: int) = (cs.loadUint(32), cs.load_u32());
|
||||
var four: int = cs.load_u32();
|
||||
var five: int = cs.load_u32();
|
||||
|
||||
return [one,two,three,four,five];
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun test2(): [int,int,int] {
|
||||
var b: builder = beginCell().my_storeInt(1, 32);
|
||||
b = b.my_storeInt(2, 32);
|
||||
b~my_storeInt(3, 32);
|
||||
var b: builder = beginCell().myStoreInt(1, 32);
|
||||
b = b.myStoreInt(2, 32);
|
||||
b.myStoreInt(3, 32);
|
||||
|
||||
var cs: slice = b.endCell().beginParse();
|
||||
var (cs redef, one: int) = cs.my_loadInt(32);
|
||||
var (two: int, three: int) = (cs~my_loadInt(32), cs~my_loadInt(32));
|
||||
var one: int = cs.myLoadInt(32);
|
||||
var (two: int, three: int) = (cs.myLoadInt(32), cs.myLoadInt(32));
|
||||
|
||||
return [one,two,three];
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun test3(ret: int): int {
|
||||
var (_, same: int) = beginCell().storeUint(ret,32).endCell().beginParse().loadUint(32);
|
||||
val same: int = beginCell().storeUint(ret,32).endCell().beginParse().loadUint(32);
|
||||
return same;
|
||||
}
|
||||
|
||||
@method_id(104)
|
||||
fun test4(): [int,int] {
|
||||
var b: builder = my_storeInt(beginCell(), 1, 32);
|
||||
b = storeInt(storeInt(b, 2, 32), 3, 32);
|
||||
var b: builder = beginCell().myStoreInt(1, 32);
|
||||
b = b.storeInt(2, 32).storeInt(3, 32);
|
||||
|
||||
var cs: slice = b.endCell().beginParse();
|
||||
var cs32: slice = cs.getFirstBits(32); // todo s.first_bits()~loadUint() doesn't work, 'lvalue expected'
|
||||
var (one, _, three) = (cs32~loadInt(32), cs~skipBits(64), cs~load_u32());
|
||||
var (one, _, three) = (cs.getFirstBits(32).loadUint(32), cs.skipBits(64), cs.load_u32());
|
||||
|
||||
return [one,three];
|
||||
}
|
||||
|
||||
@method_id(105)
|
||||
fun test5(): [int,int] {
|
||||
var cref: cell = endCell(store_u32(beginCell(), 105));
|
||||
var cref: cell = endCell(beginCell().store_u32(105));
|
||||
var c: cell = beginCell().storeRef(cref).storeRef(cref).store_u32(1).endCell();
|
||||
|
||||
var cs: slice = beginParse(c);
|
||||
// todo I want cs~loadRef().beginParse()~load_u32(), but 'lvalue expected'
|
||||
var ref1 = cs~loadRef().beginParse();
|
||||
var ref2 = cs~loadRef().beginParse();
|
||||
var sto5x2: int = ref1~load_u32() + ref2~loadUint(32);
|
||||
return [sto5x2, cs~load_u32()];
|
||||
}
|
||||
|
||||
|
||||
fun ~sumNumbersInSlice(s: slice): (slice, int) {
|
||||
var result = 0;
|
||||
while (!s.isEndOfSliceBits()) {
|
||||
result += s~loadUint(32);
|
||||
}
|
||||
return (s, result);
|
||||
var sto5x2: int = cs.loadRef().beginParse().load_u32() + cs.loadRef().beginParse().loadUint(32);
|
||||
return [sto5x2, cs.load_u32()];
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
fun test6() {
|
||||
var ref = beginCell().storeInt(100, 32).endCell();
|
||||
var s: slice = beginCell().storeInt(1, 32).storeInt(2, 32).storeRef(ref).endCell().beginParse();
|
||||
var result = (getRemainingBitsCount(s), s~sumNumbersInSlice(), getRemainingBitsCount(s), isEndOfSlice(s), isEndOfSliceBits(s), isEndOfSliceRefs(s));
|
||||
var ref2: cell = s~loadRef();
|
||||
var s2: slice = ref2.beginParse();
|
||||
s.assertEndOfSlice();
|
||||
return (result, s2~loadInt(32), s2.isEndOfSlice());
|
||||
return beginCell().storeUint(1, 32).storeUint(2, 32).storeUint(3, 32);
|
||||
}
|
||||
|
||||
@method_id(107)
|
||||
fun test7() {
|
||||
// since .store() methods now mutate, this piece of code works not as earlier (mutates uri_builder)
|
||||
var uri_builder = beginCell();
|
||||
var uri_slice = uri_builder.storeSlice(".json").endCell().beginParse();
|
||||
var image_slice = uri_builder.storeSlice(".png").endCell().beginParse();
|
||||
return (uri_builder.getBuilderBitsCount(), uri_slice.getRemainingBitsCount(), image_slice.getRemainingBitsCount());
|
||||
}
|
||||
|
||||
@method_id(108)
|
||||
fun test8() {
|
||||
var uri_builder = beginCell();
|
||||
var fresh = uri_builder;
|
||||
var uri_slice = fresh.storeSlice(".json").endCell().beginParse();
|
||||
var fresh redef = uri_builder;
|
||||
var image_slice = fresh.storeSlice(".png").endCell().beginParse();
|
||||
return (uri_builder.getBuilderBitsCount(), uri_slice.getRemainingBitsCount(), image_slice.getRemainingBitsCount());
|
||||
}
|
||||
|
||||
|
||||
fun sumNumbersInSlice(mutate self: slice): int {
|
||||
var result = 0;
|
||||
while (!self.isEndOfSliceBits()) {
|
||||
result += self.loadUint(32);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@method_id(110)
|
||||
fun test10() {
|
||||
var ref = beginCell().storeInt(100, 32).endCell();
|
||||
var s: slice = beginCell().storeInt(1, 32).storeInt(2, 32).storeRef(ref).endCell().beginParse();
|
||||
var result = (getRemainingBitsCount(s), s.sumNumbersInSlice(), getRemainingBitsCount(s), isEndOfSlice(s), isEndOfSliceBits(s), isEndOfSliceRefs(s));
|
||||
var ref2: cell = s.loadRef();
|
||||
var s2: slice = ref2.beginParse();
|
||||
s.assertEndOfSlice();
|
||||
return (result, s2.loadInt(32), s2.isEndOfSlice());
|
||||
}
|
||||
|
||||
@method_id(111)
|
||||
fun test11() {
|
||||
var s: slice = beginCell().storeInt(1, 32).storeInt(2, 32).storeInt(3, 32).storeInt(4, 32).storeInt(5, 32).storeInt(6, 32).storeInt(7, 32).endCell().beginParse();
|
||||
var size1 = getRemainingBitsCount(s);
|
||||
s~skipBits(32);
|
||||
s.skipBits(32);
|
||||
var s1: slice = s.getFirstBits(64);
|
||||
var n1 = s1~loadInt(32);
|
||||
var n1 = s1.loadInt(32);
|
||||
var size2 = getRemainingBitsCount(s);
|
||||
s~loadInt(32);
|
||||
s.loadInt(32);
|
||||
var size3 = getRemainingBitsCount(s);
|
||||
s~removeLastBits(32);
|
||||
s.removeLastBits(32);
|
||||
var size4 = getRemainingBitsCount(s);
|
||||
var n2 = s~loadInt(32);
|
||||
var n2 = s.loadInt(32);
|
||||
var size5 = getRemainingBitsCount(s);
|
||||
return (n1, n2, size1, size2, size3, size4, size5);
|
||||
}
|
||||
|
||||
@method_id(108)
|
||||
fun test108() {
|
||||
@method_id(112)
|
||||
fun test12() {
|
||||
var (result1, result2) = (0, 0);
|
||||
try {
|
||||
beginCell().storeRef(beginCell().endCell()).endCell().beginParse().assertEndOfSlice();
|
||||
|
@ -132,45 +147,45 @@ fun test108() {
|
|||
return (result1, result2);
|
||||
}
|
||||
|
||||
@method_id(109)
|
||||
fun test109() {
|
||||
@method_id(113)
|
||||
fun test13() {
|
||||
var ref2 = beginCell().storeInt(1, 32).endCell();
|
||||
var ref1 = beginCell().storeInt(1, 32).storeRef(ref2).endCell();
|
||||
var c = beginCell().storeInt(444, 32).storeRef(ref1).storeRef(ref1).storeRef(ref1).storeRef(ref2).storeInt(4, 32).endCell();
|
||||
var (n_cells1, n_bits1, n_refs1) = c.calculateCellSizeStrict(10);
|
||||
var s = c.beginParse();
|
||||
s~loadRef();
|
||||
s~loadRef();
|
||||
var n = s~loadInt(32);
|
||||
s.loadRef();
|
||||
s.loadRef();
|
||||
var n = s.loadInt(32);
|
||||
var (n_cells2, n_bits2, n_refs2) = s.calculateSliceSizeStrict(10);
|
||||
return ([n_cells1, n_bits1, n_refs1], [n_cells2, n_bits2, n_refs2], n);
|
||||
}
|
||||
|
||||
@method_id(110)
|
||||
@method_id(114)
|
||||
fun test110(x: int) {
|
||||
var s = beginCell().storeBool(x < 0).storeBool(0).storeBool(x).endCell().beginParse();
|
||||
return (s~loadBool(), s~loadBool(), s~loadBool());
|
||||
return (s.loadBool(), s.loadBool(), s.loadBool());
|
||||
}
|
||||
|
||||
@method_id(111)
|
||||
@method_id(115)
|
||||
fun test111() {
|
||||
var s = beginCell().storeMessageOp(123).storeMessageQueryId(456)
|
||||
.storeAddressNone().storeAddressNone()
|
||||
.storeUint(0, 32)
|
||||
.storeUint(123, 32).storeUint(456, 64).storeUint(789, 64)
|
||||
.endCell().beginParse();
|
||||
var op1 = s~loadUint(32);
|
||||
var q1 = s~loadUint(64);
|
||||
var op1 = s.loadUint(32);
|
||||
var q1 = s.loadUint(64);
|
||||
if (s.addressIsNone()) {
|
||||
s~skipBits(2);
|
||||
s.skipBits(2);
|
||||
}
|
||||
if (s~loadBool() == 0) {
|
||||
assert(s~loadBool() == 0) throw 444;
|
||||
s~skipBits(32);
|
||||
if (s.loadBool() == 0) {
|
||||
assert(s.loadBool() == 0) throw 444;
|
||||
s.skipBouncedPrefix();
|
||||
}
|
||||
var op2 = s~loadMessageOp();
|
||||
var q2 = s~loadMessageQueryId();
|
||||
s~skipBits(64);
|
||||
var op2 = s.loadMessageOp();
|
||||
var q2 = s.loadMessageQueryId();
|
||||
s.skipBits(64);
|
||||
s.assertEndOfSlice();
|
||||
assert(isMessageBounced(0x001)) throw 444;
|
||||
return (op1, q1, op2, q2);
|
||||
|
@ -186,11 +201,31 @@ fun main(): int {
|
|||
@testcase | 103 | 103 | 103
|
||||
@testcase | 104 | | [ 1 3 ]
|
||||
@testcase | 105 | | [ 210 1 ]
|
||||
@testcase | 106 | | 64 3 0 0 -1 0 100 -1
|
||||
@testcase | 107 | | 2 3 224 192 160 128 96
|
||||
@testcase | 108 | | 9 100
|
||||
@testcase | 109 | | [ 3 128 5 ] [ 2 96 3 ] 444
|
||||
@testcase | 110 | -1 | -1 0 -1
|
||||
@testcase | 110 | 0 | 0 0 0
|
||||
@testcase | 111 | | 123 456 123 456
|
||||
@testcase | 107 | | 72 40 72
|
||||
@testcase | 108 | | 0 40 32
|
||||
@testcase | 110 | | 64 3 0 0 -1 0 100 -1
|
||||
@testcase | 111 | | 2 3 224 192 160 128 96
|
||||
@testcase | 112 | | 9 100
|
||||
@testcase | 113 | | [ 3 128 5 ] [ 2 96 3 ] 444
|
||||
@testcase | 114 | -1 | -1 0 -1
|
||||
@testcase | 114 | 0 | 0 0 0
|
||||
@testcase | 115 | | 123 456 123 456
|
||||
|
||||
Note, that since 'compute-asm-ltr' became on be default, chaining methods codegen is not quite optimal.
|
||||
@fif_codegen
|
||||
"""
|
||||
test6 PROC:<{
|
||||
//
|
||||
NEWC // _1
|
||||
1 PUSHINT // _1 _2=1
|
||||
SWAP // _2=1 _1
|
||||
32 STU // _0
|
||||
2 PUSHINT // _0 _6=2
|
||||
SWAP // _6=2 _0
|
||||
32 STU // _0
|
||||
3 PUSHINT // _0 _10=3
|
||||
SWAP // _10=3 _0
|
||||
32 STU // _0
|
||||
}>
|
||||
"""
|
||||
*/
|
||||
|
|
|
@ -43,9 +43,6 @@ asm "SDEQ";
|
|||
fun stslicer(b: builder, s: slice): builder
|
||||
asm "STSLICER";
|
||||
|
||||
fun myStoreUint(b: builder, x: int, len: int): builder { return storeUint(b, x, len); }
|
||||
fun endSlice(b: builder): slice { return endcs(b); }
|
||||
|
||||
fun main() {
|
||||
var i1: int = iget1();
|
||||
var i2: int = iget2();
|
||||
|
@ -59,8 +56,8 @@ fun main() {
|
|||
var s2: slice = sget2();
|
||||
var s3: slice = newc().stslicer(str1).stslicer(str2r).endcs();
|
||||
|
||||
assert(sdeq(s1, newc().myStoreUint(str1int, 12 * nibbles).endcs())) throw int111;
|
||||
assert(sdeq(s2, newc().storeUint(str2int, 6 * nibbles).endSlice())) throw 112;
|
||||
assert(sdeq(s1, newc().storeUint(str1int, 12 * nibbles).endcs())) throw int111;
|
||||
assert(sdeq(s2, newc().storeUint(str2int, 6 * nibbles).endcs())) throw 112;
|
||||
assert(sdeq(s3, newc().storeUint(0x636f6e737431AABBCC, 18 * nibbles).endcs())) throw 113;
|
||||
|
||||
var i4: int = iget240();
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import "@stdlib/tvm-dicts"
|
||||
|
||||
fun ~addIntToIDict(iDict: cell, key: int, number: int): (cell, ()) {
|
||||
iDict~iDictSetBuilder(32, key, beginCell().storeInt(number, 32));
|
||||
return (iDict, ());
|
||||
fun addIntToIDict(mutate self: cell, key: int, number: int): void {
|
||||
return self.iDictSetBuilder(32, key, beginCell().storeInt(number, 32));
|
||||
}
|
||||
|
||||
fun calculateDictLen(d: cell) {
|
||||
|
@ -15,40 +14,40 @@ fun calculateDictLen(d: cell) {
|
|||
return len;
|
||||
}
|
||||
|
||||
fun ~loadTwoDigitNumberFromSlice(s: slice): (slice, int) {
|
||||
var n1 = s~loadInt(8);
|
||||
var n2 = s~loadInt(8);
|
||||
return (s, (n1 - 48) * 10 + (n2 - 48));
|
||||
fun loadTwoDigitNumberFromSlice(mutate self: slice): int {
|
||||
var n1 = self.loadInt(8);
|
||||
var n2 = self.loadInt(8);
|
||||
return (n1 - 48) * 10 + (n2 - 48);
|
||||
}
|
||||
|
||||
|
||||
@method_id(101)
|
||||
fun test101(getK1: int, getK2: int, getK3: int) {
|
||||
var dict = createEmptyDict();
|
||||
dict~uDictSetBuilder(32, 1, beginCell().storeUint(1, 32));
|
||||
var (old1: slice, found1) = dict~uDictSetAndGet(32, getK1, beginCell().storeUint(2, 32).endCell().beginParse());
|
||||
var (old2: slice, found2) = dict~uDictSetAndGet(32, getK2, beginCell().storeUint(3, 32).endCell().beginParse());
|
||||
dict.uDictSetBuilder(32, 1, beginCell().storeUint(1, 32));
|
||||
var (old1: slice, found1) = dict.uDictSetAndGet(32, getK1, beginCell().storeUint(2, 32).endCell().beginParse());
|
||||
var (old2: slice, found2) = dict.uDictSetAndGet(32, getK2, beginCell().storeUint(3, 32).endCell().beginParse());
|
||||
var (cur3: slice, found3) = dict.uDictGet(32, getK3);
|
||||
return (
|
||||
found1 ? old1~loadUint(32) : -1,
|
||||
found2 ? old2~loadUint(32) : -1,
|
||||
found3 ? cur3~loadUint(32) : -1
|
||||
found1 ? old1.loadUint(32) : -1,
|
||||
found2 ? old2.loadUint(32) : -1,
|
||||
found3 ? cur3.loadUint(32) : -1
|
||||
);
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun test102() {
|
||||
var dict = createEmptyDict();
|
||||
dict~addIntToIDict(2, 102);
|
||||
dict~addIntToIDict(1, 101);
|
||||
dict~addIntToIDict(4, 104);
|
||||
dict~addIntToIDict(3, 103);
|
||||
dict.addIntToIDict(2, 102);
|
||||
dict.addIntToIDict(1, 101);
|
||||
dict.addIntToIDict(4, 104);
|
||||
dict.addIntToIDict(3, 103);
|
||||
var deleted = createEmptyTuple();
|
||||
var shouldBreak = false;
|
||||
while (!shouldBreak) {
|
||||
var (kDel, kVal, wasDel) = dict~iDictDeleteLastAndGet(32);
|
||||
var (kDel, kVal, wasDel) = dict.iDictDeleteLastAndGet(32);
|
||||
if (wasDel) {
|
||||
deleted~tuplePush([kDel, kVal~loadInt(32)]);
|
||||
deleted.tuplePush([kDel, kVal.loadInt(32)]);
|
||||
} else {
|
||||
shouldBreak = true;
|
||||
}
|
||||
|
@ -59,38 +58,38 @@ fun test102() {
|
|||
@method_id(103)
|
||||
fun test103() {
|
||||
var dict = createEmptyDict();
|
||||
dict~uDictSetBuilderIfNotExists(32, 1,beginCell().storeInt(1, 32));
|
||||
dict~uDictSetBuilderIfNotExists(32, 1,beginCell().storeInt(1, 32));
|
||||
dict.uDictSetBuilderIfNotExists(32, 1,beginCell().storeInt(1, 32));
|
||||
dict.uDictSetBuilderIfNotExists(32, 1,beginCell().storeInt(1, 32));
|
||||
var len1 = calculateDictLen(dict);
|
||||
dict~uDictSetBuilderIfExists(32, 2,beginCell().storeInt(1, 32));
|
||||
dict~uDictSetBuilderIfExists(32, 2,beginCell().storeInt(1, 32));
|
||||
dict.uDictSetBuilderIfExists(32, 2,beginCell().storeInt(1, 32));
|
||||
dict.uDictSetBuilderIfExists(32, 2,beginCell().storeInt(1, 32));
|
||||
var len2 = calculateDictLen(dict);
|
||||
dict~uDictSetBuilder(32, 3,beginCell().storeInt(1, 32));
|
||||
dict~uDictSetBuilderIfExists(32, 3,beginCell().storeInt(1, 32));
|
||||
dict.uDictSetBuilder(32, 3,beginCell().storeInt(1, 32));
|
||||
dict.uDictSetBuilderIfExists(32, 3,beginCell().storeInt(1, 32));
|
||||
var len3 = calculateDictLen(dict);
|
||||
var (delK1, _, _) = dict~uDictDeleteFirstAndGet(32);
|
||||
var (delK2, _, _) = dict~uDictDeleteFirstAndGet(32);
|
||||
var (delK3, _, _) = dict~uDictDeleteFirstAndGet(32);
|
||||
var (delK1, _, _) = dict.uDictDeleteFirstAndGet(32);
|
||||
var (delK2, _, _) = dict.uDictDeleteFirstAndGet(32);
|
||||
var (delK3, _, _) = dict.uDictDeleteFirstAndGet(32);
|
||||
return (len1, len2, len3, delK1, delK2, delK3);
|
||||
}
|
||||
|
||||
@method_id(104)
|
||||
fun test104() {
|
||||
var dict = createEmptyDict();
|
||||
dict~sDictSetBuilder(32, "7800", beginCell().storeUint(5 + 48, 8).storeUint(6 + 48, 8));
|
||||
dict~sDictSet(32, "key1", "12");
|
||||
var (old1, _) = dict~sDictSetAndGet(32, "key1", "34");
|
||||
var (old2, _) = dict~sDictDeleteAndGet(32, "key1");
|
||||
dict.sDictSetBuilder(32, "7800", beginCell().storeUint(5 + 48, 8).storeUint(6 + 48, 8));
|
||||
dict.sDictSet(32, "key1", "12");
|
||||
var (old1, _) = dict.sDictSetAndGet(32, "key1", "34");
|
||||
var (old2, _) = dict.sDictDeleteAndGet(32, "key1");
|
||||
var (restK, restV, _) = dict.sDictGetFirst(32);
|
||||
var (restK1, restV1, _) = dict~sDictDeleteLastAndGet(32);
|
||||
var (restK1, restV1, _) = dict.sDictDeleteLastAndGet(32);
|
||||
assert (restK.isSliceBitsEqual(restK1)) throw 123;
|
||||
assert (restV.isSliceBitsEqual(restV1)) throw 123;
|
||||
return (
|
||||
old1~loadTwoDigitNumberFromSlice(),
|
||||
old2~loadTwoDigitNumberFromSlice(),
|
||||
restV~loadTwoDigitNumberFromSlice(),
|
||||
restK~loadTwoDigitNumberFromSlice(),
|
||||
restK~loadTwoDigitNumberFromSlice()
|
||||
old1.loadTwoDigitNumberFromSlice(),
|
||||
old2.loadTwoDigitNumberFromSlice(),
|
||||
restV.loadTwoDigitNumberFromSlice(),
|
||||
restK.loadTwoDigitNumberFromSlice(),
|
||||
restK.loadTwoDigitNumberFromSlice()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
fun prepareDict_3_30_4_40_5_x(valueAt5: int): cell {
|
||||
var dict: cell = createEmptyDict();
|
||||
dict~idict_set_builder(32, 3, begin_cell().store_int(30, 32));
|
||||
dict~idict_set_builder(32, 4, begin_cell().store_int(40, 32));
|
||||
dict~idict_set_builder(32, 5, begin_cell().store_int(valueAt5, 32));
|
||||
dict.idict_set_builder(32, 3, begin_cell().store_int(30, 32));
|
||||
dict.idict_set_builder(32, 4, begin_cell().store_int(40, 32));
|
||||
dict.idict_set_builder(32, 5, begin_cell().store_int(valueAt5, 32));
|
||||
return dict;
|
||||
}
|
||||
|
||||
fun lookupIdxByValue(idict32: cell, value: int): int {
|
||||
var cur_key = -1;
|
||||
do {
|
||||
var (cur_key redef, cs: slice, found: int) = idict32.idict_get_next?(32, cur_key);
|
||||
var (cur_key redef, cs: slice, found: int) = idict32.idictGetNext(32, cur_key);
|
||||
// one-line condition (via &) doesn't work, since right side is calculated immediately
|
||||
if (found) {
|
||||
if (cs~load_int(32) == value) {
|
||||
if (cs.loadInt(32) == value) {
|
||||
return cur_key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import "@stdlib/tvm-dicts"
|
|||
|
||||
fun prepareDict_3_30_4_40_5_x(valueAt5: int): cell {
|
||||
var dict: cell = createEmptyDict();
|
||||
dict~iDictSetBuilder(32, 3, beginCell().storeInt(30, 32));
|
||||
dict~iDictSetBuilder(32, 4, beginCell().storeInt(40, 32));
|
||||
dict~iDictSetBuilder(32, 5, beginCell().storeInt(valueAt5, 32));
|
||||
dict.iDictSetBuilder(32, 3, beginCell().storeInt(30, 32));
|
||||
dict.iDictSetBuilder(32, 4, beginCell().storeInt(40, 32));
|
||||
dict.iDictSetBuilder(32, 5, beginCell().storeInt(valueAt5, 32));
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ fun lookupIdxByValue(idict32: cell, value: int): int {
|
|||
var (cur_key redef, cs: slice, found: int) = idict32.iDictGetNext(32, cur_key);
|
||||
// one-line condition (via &) doesn't work, since right side is calculated immediately
|
||||
if (found) {
|
||||
if (cs~loadInt(32) == value) {
|
||||
if (cs.loadInt(32) == value) {
|
||||
return cur_key;
|
||||
}
|
||||
}
|
||||
|
|
9
tolk-tester/tests/invalid-call-1.tolk
Normal file
9
tolk-tester/tests/invalid-call-1.tolk
Normal file
|
@ -0,0 +1,9 @@
|
|||
fun main() {
|
||||
return true();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
The message is weird now, but later I'll rework error messages anyway.
|
||||
@stderr cannot apply expression of type int to an expression of type (): cannot unify type () -> ??3 with int
|
||||
*/
|
14
tolk-tester/tests/invalid-call-2.tolk
Normal file
14
tolk-tester/tests/invalid-call-2.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
fun add1(x: int) {
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val adder_fn = add1;
|
||||
var x = 10;
|
||||
return adder_fn(mutate x);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr `mutate` used for non-mutate argument
|
||||
*/
|
12
tolk-tester/tests/invalid-call-3.tolk
Normal file
12
tolk-tester/tests/invalid-call-3.tolk
Normal file
|
@ -0,0 +1,12 @@
|
|||
fun with2Params(x: int, y: int) {
|
||||
|
||||
}
|
||||
|
||||
fun main() {
|
||||
return with2Params(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr too few arguments in call to `with2Params`, expected 2, have 1
|
||||
*/
|
13
tolk-tester/tests/invalid-call-4.tolk
Normal file
13
tolk-tester/tests/invalid-call-4.tolk
Normal file
|
@ -0,0 +1,13 @@
|
|||
fun methodWith1Param(self: int, param: int) {
|
||||
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val x = 10;
|
||||
x.methodWith1Param(2, "asdf");
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr too many arguments in call to `methodWith1Param`, expected 1, have 2
|
||||
*/
|
13
tolk-tester/tests/invalid-call-5.tolk
Normal file
13
tolk-tester/tests/invalid-call-5.tolk
Normal file
|
@ -0,0 +1,13 @@
|
|||
fun inc(x: int) {
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
fun main() {
|
||||
return inc(_);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr rvalue expected
|
||||
@stderr inc(_)
|
||||
*/
|
12
tolk-tester/tests/invalid-call-6.tolk
Normal file
12
tolk-tester/tests/invalid-call-6.tolk
Normal file
|
@ -0,0 +1,12 @@
|
|||
fun nothing() {
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val x = 0;
|
||||
return x.nothing();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr `nothing` has no parameters and can not be called as method
|
||||
*/
|
14
tolk-tester/tests/invalid-call-7.tolk
Normal file
14
tolk-tester/tests/invalid-call-7.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
fun main() {
|
||||
beginCell()
|
||||
.storeAddressNone()
|
||||
.storeUint(3, 32)
|
||||
.storeUnexisting()
|
||||
.storeInt(1, 32)
|
||||
.endCell();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr undefined symbol `storeUnexisting`
|
||||
@stderr .storeUnexisting()
|
||||
*/
|
8
tolk-tester/tests/invalid-call-8.tolk
Normal file
8
tolk-tester/tests/invalid-call-8.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun main() {
|
||||
var incoming_ton: int = get_incoming_value().3();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr expected method name, got `3`
|
||||
*/
|
|
@ -1,5 +1,5 @@
|
|||
fun main(): int {
|
||||
;; this is not a comment
|
||||
;; here is not a comment
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
fun main() {
|
||||
val imm = 10;
|
||||
get seqno(self: int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr immutable variables are not supported yet
|
||||
*/
|
||||
@stderr get methods can't have `mutate` and `self` params
|
||||
*/
|
||||
|
|
11
tolk-tester/tests/invalid-mutate-1.tolk
Normal file
11
tolk-tester/tests/invalid-mutate-1.tolk
Normal file
|
@ -0,0 +1,11 @@
|
|||
fun f(x: int) {}
|
||||
|
||||
fun cantAssignToVal() {
|
||||
val x = 10;
|
||||
f(x += 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `x`
|
||||
*/
|
16
tolk-tester/tests/invalid-mutate-10.tolk
Normal file
16
tolk-tester/tests/invalid-mutate-10.tolk
Normal file
|
@ -0,0 +1,16 @@
|
|||
fun increment(mutate x: int) {
|
||||
x = x + 1;
|
||||
}
|
||||
|
||||
fun cantCallMutatingAsAMember() {
|
||||
var x = 0;
|
||||
x.increment();
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr function `increment` mutates parameter `x`
|
||||
@stderr consider calling `increment(mutate x)`, not `x.increment`()
|
||||
@stderr alternatively, rename parameter to `self` to make it a method
|
||||
*/
|
8
tolk-tester/tests/invalid-mutate-11.tolk
Normal file
8
tolk-tester/tests/invalid-mutate-11.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun load32(self: slice): int {
|
||||
return self.loadUint(32);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying `self` (call a mutating method), which is immutable by default
|
||||
*/
|
14
tolk-tester/tests/invalid-mutate-12.tolk
Normal file
14
tolk-tester/tests/invalid-mutate-12.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
fun increment(mutate x: int) {
|
||||
|
||||
}
|
||||
|
||||
fun main() {
|
||||
var x = 0;
|
||||
var inc = increment;
|
||||
inc(x);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr saving `increment` into a variable is impossible, since it has `mutate` parameters and thus can only be called directly
|
||||
*/
|
8
tolk-tester/tests/invalid-mutate-13.tolk
Normal file
8
tolk-tester/tests/invalid-mutate-13.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun onInternalMessage(mutate in_msg_body: slice) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr invalid declaration of a reserved function
|
||||
*/
|
8
tolk-tester/tests/invalid-mutate-14.tolk
Normal file
8
tolk-tester/tests/invalid-mutate-14.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun main(cs: slice) {
|
||||
return loadInt(cs, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr `loadInt` is a mutating method; consider calling `cs.loadInt()`, not `loadInt(cs)`
|
||||
*/
|
12
tolk-tester/tests/invalid-mutate-15.tolk
Normal file
12
tolk-tester/tests/invalid-mutate-15.tolk
Normal file
|
@ -0,0 +1,12 @@
|
|||
fun asdf(mutate cs: slice) {}
|
||||
|
||||
fun main(cs: slice) {
|
||||
cs.asdf();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr function `asdf` mutates parameter `cs`
|
||||
@stderr consider calling `asdf(mutate cs)`, not `cs.asdf`()
|
||||
@stderr alternatively, rename parameter to `self` to make it a method
|
||||
*/
|
10
tolk-tester/tests/invalid-mutate-2.tolk
Normal file
10
tolk-tester/tests/invalid-mutate-2.tolk
Normal file
|
@ -0,0 +1,10 @@
|
|||
fun cantAssignToVal() {
|
||||
val x = 10;
|
||||
var y = 20;
|
||||
[y, x] = [30, 40];
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `x`
|
||||
*/
|
11
tolk-tester/tests/invalid-mutate-3.tolk
Normal file
11
tolk-tester/tests/invalid-mutate-3.tolk
Normal file
|
@ -0,0 +1,11 @@
|
|||
const op_increase = 0x123;
|
||||
|
||||
fun cantAssignToConst() {
|
||||
var x = 10;
|
||||
(x, op_increase) = (20, 30);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `op_increase`
|
||||
*/
|
14
tolk-tester/tests/invalid-mutate-4.tolk
Normal file
14
tolk-tester/tests/invalid-mutate-4.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
fun inc(mutate x: int) {
|
||||
x += 1;
|
||||
}
|
||||
|
||||
fun cantPassToMutatingFunction() {
|
||||
val myVal = 10;
|
||||
inc(mutate myVal);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `myVal`
|
||||
*/
|
14
tolk-tester/tests/invalid-mutate-5.tolk
Normal file
14
tolk-tester/tests/invalid-mutate-5.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
fun cantCallMutatingMethod(c: cell) {
|
||||
val s: slice = c.beginParse();
|
||||
if (1) {
|
||||
var s: slice = c.beginParse();
|
||||
s.loadRef(); // this is ok, 's' is another variable
|
||||
}
|
||||
val i = s.loadUint(32);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `s` (call a mutating method)
|
||||
@stderr s.loadUint
|
||||
*/
|
16
tolk-tester/tests/invalid-mutate-6.tolk
Normal file
16
tolk-tester/tests/invalid-mutate-6.tolk
Normal file
|
@ -0,0 +1,16 @@
|
|||
const op_increase = 0x123;
|
||||
|
||||
fun inc(mutate x: int): int {
|
||||
x += 10;
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
fun cantCallMutatingFunctionWithImmutable() {
|
||||
return inc(mutate op_increase);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `op_increase` (call a mutating function)
|
||||
@stderr inc(mutate op_increase)
|
||||
*/
|
15
tolk-tester/tests/invalid-mutate-7.tolk
Normal file
15
tolk-tester/tests/invalid-mutate-7.tolk
Normal file
|
@ -0,0 +1,15 @@
|
|||
fun incBoth(mutate x: int, mutate y: int) {
|
||||
x += 10;
|
||||
y += 10;
|
||||
}
|
||||
|
||||
fun cantCallMutatingFunctionWithRvalue() {
|
||||
var x = 10;
|
||||
incBoth(mutate x, mutate 30);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr lvalue expected (call a mutating function)
|
||||
@stderr incBoth(mutate x, mutate 30)
|
||||
*/
|
10
tolk-tester/tests/invalid-mutate-8.tolk
Normal file
10
tolk-tester/tests/invalid-mutate-8.tolk
Normal file
|
@ -0,0 +1,10 @@
|
|||
fun cantRedefImmutable() {
|
||||
val x = 10;
|
||||
var (y: int, x redef) = (20, 30);
|
||||
return (y, x);
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying an immutable variable `x` (left side of assignment)
|
||||
*/
|
9
tolk-tester/tests/invalid-mutate-9.tolk
Normal file
9
tolk-tester/tests/invalid-mutate-9.tolk
Normal file
|
@ -0,0 +1,9 @@
|
|||
fun increment(self: int) {
|
||||
self = self + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr modifying `self` (left side of assignment), which is immutable by default
|
||||
@stderr probably, you want to declare `mutate self`
|
||||
*/
|
8
tolk-tester/tests/invalid-self-1.tolk
Normal file
8
tolk-tester/tests/invalid-self-1.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun cantReturnFromSelf(mutate self: int): self {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr invalid return from `self` function
|
||||
*/
|
8
tolk-tester/tests/invalid-self-2.tolk
Normal file
8
tolk-tester/tests/invalid-self-2.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun cantUseSelfAsType(mutate x: int) {
|
||||
var y: self = x;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr `self` type can be used only as a return type of a function (enforcing it to be chainable)
|
||||
*/
|
10
tolk-tester/tests/invalid-self-3.tolk
Normal file
10
tolk-tester/tests/invalid-self-3.tolk
Normal file
|
@ -0,0 +1,10 @@
|
|||
fun cantReturnSelf(mutate x: int): int {
|
||||
x += 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr using `self` in a non-member function (it does not accept the first `self` parameter)
|
||||
@stderr return self
|
||||
*/
|
9
tolk-tester/tests/invalid-self-4.tolk
Normal file
9
tolk-tester/tests/invalid-self-4.tolk
Normal file
|
@ -0,0 +1,9 @@
|
|||
fun cantReturnNothingFromSelf(mutate self: int): self {
|
||||
self = self + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr missing return; forgot `return self`?
|
||||
@stderr }
|
||||
*/
|
15
tolk-tester/tests/invalid-self-5.tolk
Normal file
15
tolk-tester/tests/invalid-self-5.tolk
Normal file
|
@ -0,0 +1,15 @@
|
|||
fun increment(mutate self: int): self {
|
||||
self = self + 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
fun cantReturnAnotherSelf(mutate self: int): self {
|
||||
self = self + 1;
|
||||
var x = 0;
|
||||
return x.increment();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr invalid return from `self` function
|
||||
*/
|
8
tolk-tester/tests/invalid-self-6.tolk
Normal file
8
tolk-tester/tests/invalid-self-6.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun increment(x: int, self: int): int {
|
||||
return x + self;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr `self` can only be the first parameter
|
||||
*/
|
8
tolk-tester/tests/invalid-self-7.tolk
Normal file
8
tolk-tester/tests/invalid-self-7.tolk
Normal file
|
@ -0,0 +1,8 @@
|
|||
fun increment(x: int): int {
|
||||
return self + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr using `self` in a non-member function
|
||||
*/
|
19
tolk-tester/tests/invalid-typing-3.tolk
Normal file
19
tolk-tester/tests/invalid-typing-3.tolk
Normal file
|
@ -0,0 +1,19 @@
|
|||
fun incInt(mutate self: int): self {
|
||||
self += 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
fun appendBuilder(mutate self: builder): self {
|
||||
self.storeUint(1, 32);
|
||||
return self;
|
||||
}
|
||||
|
||||
fun cantMixDifferentThis() {
|
||||
var x = 0;
|
||||
return x.incInt().appendBuilder().incInt();
|
||||
}
|
||||
|
||||
/**
|
||||
@compilation_should_fail
|
||||
@stderr cannot apply function appendBuilder : builder -> (builder, ()) to arguments of type int: cannot unify type int with builder
|
||||
*/
|
14
tolk-tester/tests/invalid-typing-4.tolk
Normal file
14
tolk-tester/tests/invalid-typing-4.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
fun incNotChained(mutate self: int) {
|
||||
self = self + 1;
|
||||
}
|
||||
|
||||
fun cantCallNotChainedMethodsInAChain(x: int) {
|
||||
return x.incNotChained().incNotChained();
|
||||
}
|
||||
|
||||
/**
|
||||
The error is very weird, but nevertheless, the type system prevents of doing such errors.
|
||||
|
||||
@compilation_should_fail
|
||||
@stderr cannot apply function incNotChained : int -> (int, ()) to arguments of type (): cannot unify type () with int
|
||||
*/
|
14
tolk-tester/tests/invalid-typing-5.tolk
Normal file
14
tolk-tester/tests/invalid-typing-5.tolk
Normal file
|
@ -0,0 +1,14 @@
|
|||
fun incNotChained(mutate self: int) {
|
||||
self = self + 1;
|
||||
}
|
||||
|
||||
fun failWhenReturnANotChainedValue(x: int): int {
|
||||
return x.incNotChained();
|
||||
}
|
||||
|
||||
/**
|
||||
The error is very weird, but nevertheless, the type system prevents of doing such errors.
|
||||
|
||||
@compilation_should_fail
|
||||
@stderr previous function return type int cannot be unified with return statement expression type (): cannot unify type () with int
|
||||
*/
|
27
tolk-tester/tests/known-bugs.tolk
Normal file
27
tolk-tester/tests/known-bugs.tolk
Normal file
|
@ -0,0 +1,27 @@
|
|||
fun increment(mutate x: int): int {
|
||||
x = x + 1;
|
||||
return x;
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun bugWithModifyingMethodInsideSameExpression() {
|
||||
/*
|
||||
The same bug existed in FunC:
|
||||
#pragma allow-post-modification;
|
||||
(int, int) ~increment(int x) { x = x + 5; return (x, x); }
|
||||
int main() { int x = 0; x += x~increment(); return x; }
|
||||
It's related to using a variable modified by ~method inside the same expression.
|
||||
*/
|
||||
var x = 0;
|
||||
x = x + increment(mutate x);
|
||||
return x;
|
||||
}
|
||||
|
||||
fun main() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
// correct: 2
|
||||
@testcase | 101 | | 1
|
||||
*/
|
337
tolk-tester/tests/mutate-methods.tolk
Normal file
337
tolk-tester/tests/mutate-methods.tolk
Normal file
|
@ -0,0 +1,337 @@
|
|||
fun incrementInPlace(mutate self: int, byValue: int): void {
|
||||
self = self + byValue;
|
||||
}
|
||||
|
||||
fun incrementTwoInPlace(mutate self: int, mutate y: int, byValue: int): int {
|
||||
self.incrementInPlace(byValue);
|
||||
y += byValue;
|
||||
return self + y;
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun testIncrement1() {
|
||||
var x = 50;
|
||||
var y = 30;
|
||||
incrementInPlace(mutate x, 10);
|
||||
incrementInPlace(mutate x, 10);
|
||||
incrementInPlace(mutate y, 10);
|
||||
y.incrementInPlace(10);
|
||||
incrementInPlace(mutate y, 10);
|
||||
return (x, y);
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun testIncrement2() {
|
||||
var x = 50;
|
||||
var y = 30;
|
||||
val sum1 = incrementTwoInPlace(mutate x, mutate y, 10);
|
||||
val sum2 = x.incrementTwoInPlace(mutate y, 10);
|
||||
return (x, y, sum1, sum2);
|
||||
}
|
||||
|
||||
|
||||
fun load_next(mutate cs: slice): int {
|
||||
return loadInt(mutate cs, 32);
|
||||
}
|
||||
|
||||
fun myLoadInt(mutate self: slice, len: int): int
|
||||
asm(-> 1 0) "LDIX";
|
||||
fun myStoreInt(mutate self: builder, x: int, len: int): self
|
||||
asm(x self len) "STIX";
|
||||
|
||||
@inline_ref
|
||||
fun unpack_utils_info(mutate utils_info_sl: slice): (int, int) {
|
||||
return (
|
||||
utils_info_sl.myLoadInt(32),
|
||||
utils_info_sl.myLoadInt(32)
|
||||
);
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun testSlices1() {
|
||||
var b: builder = beginCell().storeInt(1, 32).myStoreInt(2, 32);
|
||||
b.myStoreInt(3, 32);
|
||||
var c: cell = b.myStoreInt(4, 32).storeInt(5, 32).endCell();
|
||||
var cs = c.beginParse();
|
||||
var first = cs.preloadInt(32);
|
||||
unpack_utils_info(mutate cs);
|
||||
return (first, cs.myLoadInt(32), cs.loadInt(32));
|
||||
}
|
||||
|
||||
fun load_decimal_symbol(mutate self: slice): int {
|
||||
// load decimal from bits using utf-8 table
|
||||
var n: int = self.loadUint(8);
|
||||
n = n - 48;
|
||||
assert(n >= 0) throw 400;
|
||||
assert(n <= 9) throw 400;
|
||||
return n;
|
||||
}
|
||||
|
||||
@method_id(104)
|
||||
fun testSlices2() {
|
||||
var cs = "123";
|
||||
return (cs.load_decimal_symbol(), cs.load_decimal_symbol(), cs.load_decimal_symbol());
|
||||
}
|
||||
|
||||
global v1: int;
|
||||
global v2: int;
|
||||
global v3: int;
|
||||
|
||||
@method_id(105)
|
||||
fun testGlobals() {
|
||||
v1 = 0;
|
||||
v2 = 0;
|
||||
v3 = 100;
|
||||
v3 += incrementTwoInPlace(mutate v1, mutate v2, 5);
|
||||
return (v1, v2, v3);
|
||||
}
|
||||
|
||||
fun withNameShadowing(mutate x: int, pivot: int, extra: int) {
|
||||
x += pivot;
|
||||
if (pivot < 100) {
|
||||
var x = 100 + extra;
|
||||
if (pivot < 50) {
|
||||
var x = 50 + extra;
|
||||
return x + extra;
|
||||
} else {
|
||||
x += extra;
|
||||
return x + extra;
|
||||
}
|
||||
} else {
|
||||
x += extra;
|
||||
return -100 + extra;
|
||||
}
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
fun testNameShadowing() {
|
||||
var x = 0;
|
||||
var sum = 0;
|
||||
sum += withNameShadowing(mutate x, 100, 10);
|
||||
sum += withNameShadowing(mutate x, 50, 10);
|
||||
sum += withNameShadowing(mutate x, 0, 10);
|
||||
return (x, sum);
|
||||
}
|
||||
|
||||
fun updateTwoItems(mutate self: (int, int), byValue: int) {
|
||||
val (first, second) = self;
|
||||
self = (first + byValue, second + byValue);
|
||||
}
|
||||
|
||||
@method_id(107)
|
||||
fun testMutableTensor() {
|
||||
var t = (40, 50);
|
||||
t.updateTwoItems(10);
|
||||
updateTwoItems(mutate t, 10);
|
||||
return t;
|
||||
}
|
||||
|
||||
@pure
|
||||
fun myStoreUint(mutate self: builder, x: int, len: int): self
|
||||
asm(x self len) "STIX";
|
||||
|
||||
@pure
|
||||
fun myStoreU32(mutate self: builder, x: int): self {
|
||||
return self.storeUint(x, 32);
|
||||
}
|
||||
|
||||
fun getSumOfNumbersInCell(c: cell): int {
|
||||
var sum = 0;
|
||||
var s = c.beginParse();
|
||||
var n_numbers = s.getRemainingBitsCount() / 32;
|
||||
repeat (n_numbers) {
|
||||
sum += s.loadUint(32);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@method_id(110)
|
||||
fun testStoreChaining() {
|
||||
var b = beginCell().storeUint(1, 32).storeUint(2, 32).storeUint(3, 32);
|
||||
b.storeUint(4, 32);
|
||||
b.myStoreUint(5, 32).storeUint(6, 32);
|
||||
storeUint(mutate b, 7, 32);
|
||||
b = b.storeUint(8, 32);
|
||||
b = b.storeUint(9, 32).storeUint(10, 32);
|
||||
|
||||
return getBuilderBitsCount(b);
|
||||
}
|
||||
|
||||
@method_id(111)
|
||||
fun testStoreChainingCustom() {
|
||||
var b = beginCell().myStoreUint(1, 32).myStoreUint(2, 32).myStoreUint(3, 32);
|
||||
b.myStoreUint(4, 32);
|
||||
b.myStoreUint(5, 32).myStoreUint(6, 32);
|
||||
myStoreUint(mutate b, 7, 32);
|
||||
b = b.myStoreUint(8, 32);
|
||||
b = b.myStoreUint(9, 32).myStoreUint(10, 32);
|
||||
val sum1 = getSumOfNumbersInCell(b.endCell());
|
||||
|
||||
b = beginCell().myStoreU32(1).storeUint(2, 32).myStoreU32(3);
|
||||
b.myStoreU32(4);
|
||||
b.myStoreU32(5).myStoreU32(6);
|
||||
myStoreU32(mutate b, 7);
|
||||
b = b.myStoreU32(8);
|
||||
b = b.storeUint(9, 32).myStoreU32(10);
|
||||
val sum2 = getSumOfNumbersInCell(b.endCell());
|
||||
|
||||
return (sum1, sum2);
|
||||
}
|
||||
|
||||
fun myStoreU32_and_mutate_x(mutate self: builder, mutate x: int): void {
|
||||
return myStoreUint(mutate self, x += 10, 32);
|
||||
}
|
||||
|
||||
@method_id(112)
|
||||
fun testStoreAndMutateBoth() {
|
||||
var x = 3;
|
||||
var b: builder = beginCell().myStoreUint(1, 32);
|
||||
b.myStoreU32_and_mutate_x(mutate x);
|
||||
b.myStoreU32(3).myStoreU32_and_mutate_x(mutate x);
|
||||
b.myStoreU32_and_mutate_x(mutate x);
|
||||
|
||||
var cs: slice = b.endCell().beginParse();
|
||||
var (n1,n2,n3,n4,n5) = (cs.loadUint(32),cs.loadUint(32),cs.loadUint(32),cs.loadUint(32),cs.loadUint(32));
|
||||
assert(n5 == x) throw 100;
|
||||
|
||||
return [n1,n2,n3,n4,n5];
|
||||
}
|
||||
|
||||
global ccc: builder;
|
||||
|
||||
@method_id(113)
|
||||
fun testStoreChainingForGlobal() {
|
||||
ccc = beginCell().storeUint(1, 32).myStoreUint(2, 32).myStoreU32(3);
|
||||
ccc.storeUint(4, 32);
|
||||
ccc.storeUint(5, 32).myStoreU32(6);
|
||||
storeUint(mutate ccc, 7, 32);
|
||||
ccc = ccc.myStoreU32(8);
|
||||
ccc = ccc.storeUint(9, 32).myStoreUint(10, 32);
|
||||
|
||||
return getBuilderBitsCount(ccc);
|
||||
}
|
||||
|
||||
fun alwaysThrows(): int { throw 123; return 123; }
|
||||
fun loadIntFromCell(c: cell, len: int) { return c.beginParse().loadUint(len); }
|
||||
|
||||
@method_id(114)
|
||||
fun testLoadIntForTemporaryObject() {
|
||||
val c0 = beginCell().storeUint(0, 32).endCell();
|
||||
val c4 = beginCell().storeUint(4, 32).endCell();
|
||||
return (
|
||||
beginCell().storeUint(1, 32).endCell().beginParse().loadUint(32),
|
||||
beginCell().storeUint(2, 32).endCell().beginParse().loadUint(32),
|
||||
c0.beginParse().loadUint(32) ? alwaysThrows() : loadIntFromCell(c4, 32)
|
||||
);
|
||||
}
|
||||
|
||||
@pure
|
||||
fun myStoreUint_pure(mutate self: builder): void
|
||||
asm "STIX";
|
||||
|
||||
fun myStoreUint_impure(mutate self: builder): void
|
||||
asm "STIX";
|
||||
|
||||
fun testStoreUintPureUnusedResult() {
|
||||
var b = beginCell();
|
||||
b.myStoreUint_pure();
|
||||
var s = b.endCell().beginParse();
|
||||
val ii = s.loadUint(32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fun testStoreUintImpureUnusedResult() {
|
||||
var b = beginCell();
|
||||
b.myStoreUint_impure();
|
||||
var s = b.endCell().beginParse();
|
||||
val ii = s.loadUint(32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
global counter: int;
|
||||
|
||||
fun writeNext2(mutate self: builder): self {
|
||||
return self.storeUint(counter += 1, 32).storeUint(counter += 1, 32);
|
||||
}
|
||||
|
||||
fun resetCounter(mutate self: builder): self {
|
||||
counter = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
@method_id(115)
|
||||
fun testExplicitReturn() {
|
||||
counter = 0;
|
||||
return (
|
||||
beginCell().writeNext2().writeNext2().resetCounter().writeNext2().endCell().getSumOfNumbersInCell(),
|
||||
counter
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
fun main(){}
|
||||
|
||||
/**
|
||||
@testcase | 101 | | 70 60
|
||||
@testcase | 102 | | 70 50 100 120
|
||||
@testcase | 103 | | 1 3 4
|
||||
@testcase | 104 | | 1 2 3
|
||||
@testcase | 105 | | 5 5 110
|
||||
@testcase | 106 | | 160 110
|
||||
@testcase | 107 | | 60 70
|
||||
@testcase | 110 | | 320
|
||||
@testcase | 111 | | 55 55
|
||||
@testcase | 112 | | [ 1 13 3 23 33 ]
|
||||
@testcase | 113 | | 320
|
||||
@testcase | 114 | | 1 2 4
|
||||
@testcase | 115 | | 13 2
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
incrementInPlace PROC:<{
|
||||
// self byValue
|
||||
ADD // self
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testIncrement2 PROC:<{
|
||||
...
|
||||
incrementTwoInPlace CALLDICT // x y sum1
|
||||
-ROT
|
||||
10 PUSHINT // sum1 x y _9=10
|
||||
incrementTwoInPlace CALLDICT // sum1 x y sum2
|
||||
s1 s3 s0 XCHG3 // x y sum1 sum2
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
load_next PROC:<{
|
||||
// cs
|
||||
32 LDI // _1 cs
|
||||
SWAP // cs _1
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testStoreUintPureUnusedResult PROC:<{
|
||||
//
|
||||
0 PUSHINT // _12=0
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testStoreUintImpureUnusedResult PROC:<{
|
||||
//
|
||||
NEWC // b
|
||||
STIX // _2
|
||||
DROP //
|
||||
0 PUSHINT // _12=0
|
||||
}>
|
||||
"""
|
||||
|
||||
*/
|
|
@ -30,13 +30,11 @@ global `some()var`:int;
|
|||
}
|
||||
|
||||
@method_id(113)fun`unary+bitwise-constant`():[int,int,int]{
|
||||
// todo spaces are still not allowed before ~
|
||||
return [~-~~+-3, ~+3-~ 9, -(-~+-20-~ 10+3+~ 38&39)];
|
||||
return [~-~~+-3, ~+3-~9, -(-~+-20-~ 10+3+~38&39)];
|
||||
}
|
||||
|
||||
@method_id(114)fun`unary+bitwize-parametrized`(c3:int, c9:int, c20:int, c10:int, c38:int):[int,int,int]{
|
||||
// todo spaces are still not allowed before ~
|
||||
return [~-~~+-c3, ~+c3-~ `c9`, -(-~+-c20-~ c10+c3+~ c38&39)];
|
||||
return [~-~~+-c3, ~+c3-~`c9`, -(-~+-c20-~c10+c3+~c38&39)];
|
||||
}
|
||||
|
||||
fun add3(a: int, b: int, c: int) { return a+b+c; }
|
||||
|
@ -49,16 +47,16 @@ fun add3(a: int, b: int, c: int) { return a+b+c; }
|
|||
return [add3(fst2,snd2,trd2),add3(fst1,snd1,trd1)];
|
||||
}
|
||||
|
||||
fun `load:u32`(cs: slice): (slice, int) {
|
||||
return cs.loadUint(32);
|
||||
fun `load:u32`(mutate self: slice): int {
|
||||
return self.loadUint(32);
|
||||
}
|
||||
|
||||
@method_id(116) fun `call_~_via_backticks`():[int,int,int,int] {
|
||||
var b:builder = beginCell().storeUint(1, 32).storeUint(2, 32).storeUint(3, 32).storeUint(4, 32);
|
||||
var `cs`:slice = b.endCell().beginParse();
|
||||
var (`cs` redef,one:int) = `cs`.`loadUint`(32);
|
||||
var (two:int,three:int) = (`cs`~`loadUint`(32), cs~`load:u32`());
|
||||
var (cs redef,four:int) = cs.`load:u32`();
|
||||
val one:int=`cs`.`loadUint`(32);
|
||||
val (two:int,three:int) = (`cs`.`loadUint`(32), cs.`load:u32`());
|
||||
val four:int = cs.`load:u32`();
|
||||
return [one,two,three,four];
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ fun test1() {
|
|||
|
||||
var t = createEmptyTuple();
|
||||
do {
|
||||
var num = numbers~listNext();
|
||||
t~tuplePush(num);
|
||||
var num = numbers.listNext();
|
||||
t.tuplePush(num);
|
||||
} while (numbers != null);
|
||||
|
||||
return (h, numbers == null, t);
|
||||
|
@ -63,7 +63,7 @@ fun test4() {
|
|||
@method_id(105)
|
||||
fun test5() {
|
||||
var n = getUntypedNull();
|
||||
return !(null == n) ? n~loadInt(32) : 100;
|
||||
return !(null == n) ? n.loadInt(32) : 100;
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
|
@ -75,7 +75,7 @@ fun test6(x: int) {
|
|||
fun test7() {
|
||||
var b = beginCell().storeMaybeRef(null);
|
||||
var s = b.endCell().beginParse();
|
||||
var c = s~loadMaybeRef();
|
||||
var c = s.loadMaybeRef();
|
||||
return (null == c) * 10 + (b != null);
|
||||
}
|
||||
|
||||
|
@ -145,14 +145,14 @@ fun main() {
|
|||
"""
|
||||
test7 PROC:<{
|
||||
...
|
||||
LDOPTREF // b _17 _16
|
||||
LDOPTREF // b _20 _19
|
||||
DROP // b c
|
||||
ISNULL // b _10
|
||||
10 MULCONST // b _12
|
||||
SWAP // _12 b
|
||||
ISNULL // _12 _13
|
||||
0 EQINT // _12 _14
|
||||
ADD // _15
|
||||
ISNULL // b _13
|
||||
10 MULCONST // b _15
|
||||
SWAP // _15 b
|
||||
ISNULL // _15 _16
|
||||
0 EQINT // _15 _17
|
||||
ADD // _18
|
||||
}>
|
||||
"""
|
||||
*/
|
||||
|
|
113
tolk-tester/tests/parse-address.tolk
Normal file
113
tolk-tester/tests/parse-address.tolk
Normal file
|
@ -0,0 +1,113 @@
|
|||
const cc1 = "0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e"a;
|
||||
const cc2 = "EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF"a;
|
||||
|
||||
fun verifyAddr(addr: slice, workchain: int, number: int) {
|
||||
assert (addr.getRemainingBitsCount() == 3 + 8 + 256) throw 112;
|
||||
addr.skipBits(3);
|
||||
assert (addr.loadUint(8) == workchain) throw 111;
|
||||
assert (addr.loadUint(256) == number) throw 111;
|
||||
}
|
||||
|
||||
fun main() {
|
||||
verifyAddr("Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF"a, 255, 23158417847463239084714197001737581570653996933128112807891516801582625927987);
|
||||
verifyAddr("EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c"a, 0, 0);
|
||||
verifyAddr("EQCRDM9h4k3UJdOePPuyX40mCgA4vxge5Dc5vjBR8djbEKC5"a, 0, 65607996509792174074532427555986248720836864382484024657400295821210434460432);
|
||||
verifyAddr("UQCOgxbCOjOLH_cEuQdGgS23zBM5SrQQepMFedjK-oixYbis"a, 0, 64460038539088394980732229180523693489682583665805557562964506609821558550881);
|
||||
verifyAddr("EQDa4VOnTYlLvDJ0gZjNYm5PXfSmmtL6Vs6A_CZEtXCNICq_"a, 0, 99002318936150612861744867526221033858534811876886359650897405270877291973920);
|
||||
verifyAddr("Ef8BtXO9bcTMXjg9bgivKh4lhJmZWQPP6_rb9vfjlTP5FJtM"a, 255, 772910975127952880303441415761050161913031788763061162001556772893733681428);
|
||||
verifyAddr("Ef89xh-uy860-mCcvS8zcAUs8bApmxLGygDLEKjUk5RL-311"a, 255, 27941138149036269893630478666581900122707382189183906805784676408403709676539);
|
||||
verifyAddr("Ef_vA6yRfmt2P4UHnxlrQUZFcBnKux8mL2eMqBgpeMFPorr4"a, 255, 108109262375472472702582493362335418330829651067377177643099076957184687427490);
|
||||
verifyAddr("Ef8o6AM9sUZ8rOqLFY8PYeaC3gbopZR1BMkE8fcD0r5NnmCi"a, 255, 18502444830824300068094395885436326119386947594392869497312068745716154912158);
|
||||
verifyAddr("Ef_fvrd0hBoVJUxoi7wH173Zk8NPiyVvxh5IoYSjEYZbOhsu"a, 255, 101202732337223525952216789200341489000836292542250083765062769181728788863802);
|
||||
verifyAddr("Ef9nzj6RBc4mQ6p3ng7mGJ7tp7MbzERhe7obkM9A0wnCCEcf"a, 255, 46952625717497919357580310066854892621799390294920450816077086267929711460872);
|
||||
verifyAddr("Ef9rU-_AAnBkHB71TIC3QvUf5LcAsvj0B4IoYzAXLpEFd5CA"a, 255, 48545777798729612074233611768739897492467685225150339217043102685589809464695);
|
||||
verifyAddr("Ef9LynHHKgBxY6-l-W_dWN-CtGT2_ji5rN3EzOI-p9zWEfq6"a, 255, 34281152017620085319078796986198022632548048219136747083019177301186013091345);
|
||||
verifyAddr("Ef9hMd78gzSiVsK0zz0AHtEja8x1UoB_NDZMjn-l86NQK_2Y"a, 255, 43962460814164090767878334494257755557842170134382045184921495822637115592747);
|
||||
verifyAddr("Ef80FNJ5NJO4-0QwlVAWckUZXdk-PfYDexDZ1-ju9SxhF0A6"a, 255, 23557057702048801338698514499604413540742716310574705490458593067566768087319);
|
||||
verifyAddr("Ef_fdIbThooPs4_r2DE_Z6ZsWycJdHLnsuKAJHTcbaZaipez"a, 255, 101071650030310556115830521522496708686577365303530257137459798093298869361290);
|
||||
verifyAddr("Ef_lva0qEiZhWrrZJl-IJxyCcTQmmTo71fIWyQ31HxJ8NurV"a, 255, 103914771557158282349484109182290824591675204108148026180964788916630125182006);
|
||||
verifyAddr("Ef8sMGKypw006AeRYqimLjmY2Ufp-SHk8C0ZJBNgVBlzw_Nr"a, 255, 19987255184378161380023126214650814972824352533523055905552702178965809886147);
|
||||
verifyAddr("EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff+W72r5gqPrHF"a, 0, 91561894446285001782438967260723928368560331318344957259023550817453781559870);
|
||||
verifyAddr("EQCaSCHVak-jIc9ANutTAfHpZNM3YdGky7yaDzsTrg0WhFlm"a, 0, 69783625181781015447914682554083924798054947959007050695795761257887453484676);
|
||||
verifyAddr("EQBS9U3AfD15fGmOtRMXQAxcPVBwNuItfLcDni9fkbTyyNX0"a, 0, 37523067738561024305547433298623118197038688994386001017161816416175242146504);
|
||||
verifyAddr("EQBiMNL9qNWMAkJHuM0BFneYcuHL17kzS4pswpaEO-NGWrFG"a, 0, 44412924025649114419413541526870954696667907029239618728289150652715284776538);
|
||||
verifyAddr("EQAUzE-Nef80O9dLZy91HfPiOb6EEQ8YqyWKyIU-KeaYLNUi"a, 0, 9407242825041766837311851458322335726136775042891143504070507665010681354284);
|
||||
verifyAddr("EQD-nhrinjv0B4LTgr0dRHTHwH1MOsgGhKBXJZd7vESMZUf1"a, 0, 115166810931401616117484448645661180241548402534908005320733783571353775148133);
|
||||
verifyAddr("EQAVD3Fni9I6j8XeSIl-wAGBEhqhame6OtAY0GScKT0D9X6f"a, 0, 9525855215156855607080079714361451576383963668563135377495902959388099150837);
|
||||
verifyAddr("EQC6ACq3VANZjqfRBy7JMHkpLwqQ9qyYJsCIGx1mYbQgxaKw"a, 0, 84130484652351964071210477536969520113177637645401392541565606610268614566085);
|
||||
verifyAddr("EQCIJLNFIko5CvpKn9oAkrDgLocDOoD4vwmHxNx_fsG_LkwW"a, 0, 61579391178099797614367237687950512448308156724136883899001108680249616482094);
|
||||
verifyAddr("EQCe4AYIBce1pAk2qJJPSs1OzyZRlKjkfq8zuC8D7erv6DUP"a, 0, 71861245445432818728925844931259040612664802586395398157190478191760507596776);
|
||||
verifyAddr("EQCtrtTXEAoSpoERmiqOnICe9LHxn2N89N4BH9qdHlrG-U0i"a, 0, 78559023162479717496981724991265882229440558807791659796411897368395464230649);
|
||||
verifyAddr("EQBBlraAps0OZaB9Q8ePQn2wVAaL1G411A-dNppyWe3X3GIT"a, 0, 29666621803903557832193058147214384979915773445007872807927344851911086823388);
|
||||
verifyAddr("EQBiASqUqaVizrozLRbszkWC2kETbkhpO2qniDVDPPg2_0W8"a, 0, 44328719889509369519441680467651025944540360433148852643949783408843779749631);
|
||||
verifyAddr("EQBu2Q1EO8gIoNA1qoGWnHUudKfmqlKEDTQE-DxN-_4sdg14"a, 0, 50137910719490808065414827264266674858051167131188257457782826342827836714102);
|
||||
verifyAddr("EQA5bvxWd5-q2vJUVqR9AlbEIfdFysLR0PXGgVlBf8x5hWuF"a, 0, 25977927117604457079092522008276392864656238504700352770597256138254994667909);
|
||||
verifyAddr("EQBguMSHjFv5bfoOdshr3ruS9ymSZzhRKMovoNrxGxZXvmee"a, 0, 43748489720571123896506696370504498290006245978262404519821633796370658121662);
|
||||
verifyAddr("EQAxL0oF1-zNgimPKthbDnYS4xj94rHtfNRN7_Pd1r2LNNv3"a, 0, 22246882279393590648219842750911786376759362211171398419754426796438233910068);
|
||||
verifyAddr("EQANX1uRKGZfyPIwEaIXrR0ZOqadct5q10dvKxWIxx7SQqzW"a, 0, 6048549475100840191738010856156544571222758030966479209409932714701987172930);
|
||||
verifyAddr("EQBitdFDoU5DWSjfKq7AsO29RIwAnBzzvcVVSn5ekQoB9Liv"a, 0, 44647902768175374073183447303109856895983123510911038181495138821771906122228);
|
||||
verifyAddr("EQBgbux7VSjqJHP7ByRK1q4QuVZbpSCesNgvz5qad3lfXX_B"a, 0, 43618018778298854282398238948198420936771670943015013768514626213000552996701);
|
||||
verifyAddr("EQDisBd8U7M3CEOZ8gcWCdetdmJi3AI31zIT5qBwOdmUbsxY"a, 0, 102533830955233207294921564956803510155400341370448300698800842506363763004526);
|
||||
verifyAddr("EQAZpn_eynVlf7Ii2d6jP_p1URPrdF9F3S7DiudQyelkjzwE"a, 0, 11602000355550451044739442929923326898313570892134000961608306166632391730319);
|
||||
verifyAddr("EQDE0HBgfkOiqHezLtExBGTvOs8eitthHQosBjW3BmDy1y2K"a, 0, 89021598108837008984355105304701054698583123510131754065320641619941010764503);
|
||||
verifyAddr("EQDyT36zktBN9PVWvZ1joRxhIfEUgCPt4F2isa-enUA_d6CP"a, 0, 109600164736599393471831241268953938618560132398692391517933933264745646800759);
|
||||
verifyAddr("EQDSMUGwt25IQd3_yHjI03F71G8Kp2GMaMEv2TiWoTKbsyRH"a, 0, 95072727086440754059372943502908629555499501854161516009430039520728770059187);
|
||||
verifyAddr("EQAgK1EcrvEuL9sCtoj3cNhVNOuf3lo5GIPE2gn1fwZZYB3j"a, 0, 14550545393206146289454646242321274637527057595221202748348667645886114191712);
|
||||
verifyAddr("EQCDKqL5w_6MD-Z7AOButu-uR-ZJTsgNU1fu464hn9grY81U"a, 0, 59328315557704100696483472039557119625141880163887490602190749720459366378339);
|
||||
verifyAddr("EQB1aVMyFBhnlYXmQjsma0S63kvxKU7ccZKFNCFTwX7ASPv4"a, 0, 53106696421104300082516512931084483581353095629408473618166869610568148238408);
|
||||
verifyAddr("EQBbjrXHoxDyh1ZYGBdBoQgLaScxW6pZR1hEhJC8BqF-5Kgq"a, 0, 41412616102566803060532874463898939692666425753852274254609049615175463829220);
|
||||
verifyAddr("EQC-QeZ13QP0lszxNKt380fCWuaV94vwC/bfuqmrlg1/fJPA"a, 0, 86055876869280374285292827775555707420719385459150221433115419095878595346300);
|
||||
verifyAddr("EQAiUwpF27vXCngqNhf_TQ5E_06ah0G4zuSrnfU7CLLaht5H"a, 0, 15525356059048115813946213102829493539706126913595626308144289257869196581510);
|
||||
verifyAddr("EQBqiVjmhe2iVGmgOSDO1FGjSiz_AMtb1w7lLEiP4XIF_SFy"a, 0, 48187833566271418625754761625661652107159264793429628379411792200127405491709);
|
||||
verifyAddr("EQDmwvaK2d_SbaPdpOM60effPWeKsksgDVwFPEyxuftM396K"a, 0, 104376425077737068747642645125299653296942252727305637929378053253273342397663);
|
||||
verifyAddr("EQDWtPZZgF7wvIMUHZQojuD3utiuivsW7WslRJ33dgv-5yc8"a, 0, 97114682311034709685427168495629428400170984047839002197324103884924936519399);
|
||||
verifyAddr("EQAA7z0JI0JKqbN-1uENKz9JrxIO5ZRY-ehMeg9fPncx50Ck"a, 0, 422697701361909095759185681783393186844038628935759044330165207027374567911);
|
||||
verifyAddr("EQBVUHRoCq6coQYUwOAhGSoAmQ6Mpm7dFlDYon6HMgWV8Ftr"a, 0, 38588743302295548905191533977469452945717219128199196974980570837505276220912);
|
||||
verifyAddr("EQCTdvDCf0bA5dOPI1-44tB2ZfNcMGiklzvg27TovgDEqM6E"a, 0, 66700138358140658950710678965721715920748906761125730971082529064117803730088);
|
||||
verifyAddr("EQBDBKE5WGKIlnoi3OOzw7vkKKIX55eWjPvgxJWwek8AyL2J"a, 0, 30313140970524770883308749215942283658935592719811899513010665548955593408712);
|
||||
verifyAddr("EQAvCSyLCo21GrqLAifdov4WkOxuGQCjMRxgF1cXSaNzLHZe"a, 0, 21274912932379789207153885262858116665851037273450532982121514600400844714796);
|
||||
verifyAddr("EQCsLpDeHB2qpRbmsCb_0xmsYVNx1NgeYrvHGT1TDrHkDgL4"a, 0, 77880084760844670718511036557364450189323549135231036747480176919181282894862);
|
||||
verifyAddr("EQCTQ8kPwyX92r48gCIL_pLN_RcQT9ghZygnmDTYkOkuW_j5"a, 0, 66609755171046741472463433430016629628609840960137226492652665879987546041947);
|
||||
verifyAddr("EQCTrFRSHt-tfk7WxK9ZHQmqLcgxXxTK7wGfCEbqgY2W9Mcx"a, 0, 66794468397542182731534559853537484892417154018190804733043974345563210356468);
|
||||
verifyAddr("EQCv28y49GdaLncoclv0ISdDlMUY_cxDPGNWFCPT8t4GuqUJ"a, 0, 79543100951881731989812212377176715376834409392116644269458867858071577560762);
|
||||
verifyAddr("EQCVL-k6deDR56Z8pcb0Btg0lGfaivOGfdDCD1vvyRsyL9vS"a, 0, 67479265933941008511790471646564661743401752930295407567346938670637286896175);
|
||||
verifyAddr("EQD6t2dXDjZxF1DqunKF-8dEWivJdliY_0FYiCXnthuqnDCa"a, 0, 113402258385556889021060606279033166272577193563727959698596277924908309916316);
|
||||
verifyAddr("EQDE98XNzXiPq7VnbJJ2M4-Ht3tX_OWR0xUTTnDC8NObLmyU"a, 0, 89091094739778473356272490822716056624384395256388481953562551087642791090990);
|
||||
verifyAddr("EQDfeRDE1TDhwt478CDR0Q7MDwqcTUhfjqyTT59mgoAaF6f7"a, 0, 101079669463449311486034260688909914923832300293253430457119371423825321269783);
|
||||
verifyAddr("EQDijcEyUKa-QgCbeGlggQk1uBtt2ZRHyW4Y4gB4R6MN6RLW"a, 0, 102473162609487797404330889623966425536887610061087715571345738626121871855081);
|
||||
verifyAddr("EQDOtFOt41skbjBkZF89oYXpoDECjlxIzD-ShWAOYyzuxqLA"a, 0, 93495056812773926196963707371665512785268729004579280701087533371037976424134);
|
||||
verifyAddr("EQDuJKSFWU7AYqH6KLFfAbYvMuz346eWmJvG6_2NYE42_B4T"a, 0, 107715199938628393100813870735031557263256555616273999363057194279168054802172);
|
||||
verifyAddr("EQDwGu4vFv1e3wn8min_iy7OPJXegOYTFQ5bZFZ5a5ZPiBpX"a, 0, 108602665568837301744601989570019709742180613578164394799026726718721456754568);
|
||||
verifyAddr("EQC4G2ph6AS_mD_-cIv4aIYm1z5jAgCW_TTDEr72ygXOP2X-"a, 0, 83274003234732023403481554420859495155084746906198543572711543697320249249343);
|
||||
verifyAddr("EQDpUkyAa6lZ12P3ZB2PL_rmWwI1I55BU4kxw_rssFL5dswA"a, 0, 105534303174146507629736518862713754948570412188900908177600861330298381728118);
|
||||
verifyAddr("EQDoIA20MF1qEcSPtROdCu5ukGx9dVjgMeJh1oQ4A4cf_Jif"a, 0, 104993214557977037193613824776415934089204193426692473563548548423424814817276);
|
||||
verifyAddr("EQDpUkyAa6lZ12P3ZB2PL_rmWwI1I55BU4kxw_rssFL5dswA"a, 0, 105534303174146507629736518862713754948570412188900908177600861330298381728118);
|
||||
verifyAddr("EQClLO4EnZ_rTyV1GVpWy53pLgWJRki5c4ZzuM_1O_ClBkO9"a, 0, 74711004027159342540251007601464500186374346239921204216319145006974068892934);
|
||||
verifyAddr("EQDmkj65Ab_m0aZaW8IpKw4kYqIgITw_HRstYEkVQ6NIYCyW"a, 0, 104290347741656803921830951060768893809692975574470790497562993373950614128736);
|
||||
verifyAddr("EQCqNTwAYUNhPFS0RgqZoTLGJcQQxbAJ7csUo4YO3_TONLab"a, 0, 76987241268612358571638783428744566580605181728938801022059780105627411729972);
|
||||
verifyAddr("EQCL3DmCynaRK7-vsfeNmd4Jj-UxAIHPvA4qS2xwaL6UpLbF"a, 0, 63260589232981964910240894899061676480139492286430589202252472895352724165796);
|
||||
verifyAddr("EQDbU1SVEjBE73oUqgAoM9gDcShUkM5EC2PgoCjuwVUKo-Ee"a, 0, 99203745911752606845646497420891218522647962685916739950275357890977532807843);
|
||||
verifyAddr("EQD02VdcF4TDbCKLLhZJ39NQTu6aWq2LnLjp0oXqbNu_BANK"a, 0, 110748343802097970709980079967961144373090790244250392237586606542170934198020);
|
||||
verifyAddr("EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA"a, 0, 51839428943991432793039248316067731096592274748149794482308513726460953499586);
|
||||
verifyAddr("UQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPuwA"a, 0, 91561894446285001782438967260723928368560331318344957259023550817453781559870);
|
||||
verifyAddr("EQAUTbQiM522Y_XJ_T98QPhPhTmb4nV--VSPiha8kC6kRfPO"a, 0, 9183547432069678364603018431103042146626948674383548774683927217595824907333);
|
||||
verifyAddr("EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE"a, 0, 45985353862647206060987594732861817093328871106941773337270673759241903247880);
|
||||
verifyAddr("UQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPuwA"a, 0, 91561894446285001782438967260723928368560331318344957259023550817453781559870);
|
||||
verifyAddr("kQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPgpP"a, 0, 91561894446285001782438967260723928368560331318344957259023550817453781559870);
|
||||
verifyAddr("kf-Dfdg-YQXaR2Q97gZJ4fGBtmV1DHOU1y1RPyyZZtRy_Ikh"a, 255, 59475331506450494976393625198911249698879029820580340449086829444312920781564);
|
||||
verifyAddr("0:527964d55cfa6eb731f4bfc07e9d025098097ef8505519e853986279bd8400d8"a, 0, 37304138005561100291416421295333982606153966175434134130332440738068913455320);
|
||||
verifyAddr("0:0000000000000000000000000000000000000000000000000000000000000000"a, 0, 0);
|
||||
verifyAddr("0:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFfffffffffffffffffffffffffffff"a, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639935);
|
||||
verifyAddr("0:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"a, 0, 23158417847463239084714197001737581570653996933128112807891516801582625927987);
|
||||
verifyAddr("0:0000000000000000000000000000000000000000000000000000000000000000"a, 0, 0);
|
||||
verifyAddr("1:527964d55cfa6eb731f4bfc07e9d025098097ef8505519e853986279bd8400d8"a, 1, 37304138005561100291416421295333982606153966175434134130332440738068913455320);
|
||||
verifyAddr("9:527964d55cfa6eb731f4bfc07e9d025098097ef8505519e853986279bd8400d8"a, 9, 37304138005561100291416421295333982606153966175434134130332440738068913455320);
|
||||
verifyAddr("99:527964d55cfa6eb731f4bfc07e9d025098097ef8505519e853986279bd8400d8"a, 99, 37304138005561100291416421295333982606153966175434134130332440738068913455320);
|
||||
verifyAddr("-1:527964d55cfa6eb731f4bfc07e9d025098097ef8505519e853986279bd8400d8"a, 255, 37304138005561100291416421295333982606153966175434134130332440738068913455320);
|
||||
|
||||
return cc1.isSliceBitsEqual(cc2);
|
||||
}
|
||||
|
||||
/**
|
||||
@testcase | 0 | | -1
|
||||
*/
|
|
@ -13,8 +13,8 @@ fun f_pure2(): int {
|
|||
fun get_contract_data(): (int, int) {
|
||||
var c: cell = getContractData();
|
||||
var cs: slice = c.beginParse();
|
||||
cs~loadBits(32);
|
||||
var value: int = cs~loadUint(16);
|
||||
cs.loadBits(32);
|
||||
var value: int = cs.loadUint(16);
|
||||
return (1, value);
|
||||
}
|
||||
|
||||
|
|
213
tolk-tester/tests/self-keyword.tolk
Normal file
213
tolk-tester/tests/self-keyword.tolk
Normal file
|
@ -0,0 +1,213 @@
|
|||
fun incChained(mutate self: int): self {
|
||||
self = self + 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
fun incChained2(mutate self: int): self {
|
||||
return self.incChained();
|
||||
}
|
||||
|
||||
fun incChained3(mutate self: int): self {
|
||||
incChained(mutate self);
|
||||
return self;
|
||||
}
|
||||
|
||||
fun incChained4(mutate self: int): self {
|
||||
self.incChained();
|
||||
return self;
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun testIncChainedCodegen(x: int) {
|
||||
return x.incChained().incChained2().incChained3().incChained4();
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
fun testIncChained() {
|
||||
var x: int = 10;
|
||||
incChained(mutate x);
|
||||
x.incChained();
|
||||
x.incChained2();
|
||||
x.incChained2().incChained();
|
||||
x = x.incChained();
|
||||
x = x.incChained2().incChained().incChained2();
|
||||
return x.incChained();
|
||||
}
|
||||
|
||||
fun incChainedWithMiddleReturn(mutate self: int, maxValue: int): self {
|
||||
if (self >= maxValue) {
|
||||
return self;
|
||||
}
|
||||
self += 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
@method_id(103)
|
||||
fun testIncChainedWithMiddleReturn(x: int) {
|
||||
x.incChainedWithMiddleReturn(10).incChainedWithMiddleReturn(10);
|
||||
x = x.incChainedWithMiddleReturn(10).incChainedWithMiddleReturn(10);
|
||||
return x.incChainedWithMiddleReturn(10).incChainedWithMiddleReturn(999);
|
||||
}
|
||||
|
||||
fun incChainedMutatingBoth(mutate self: int, mutate y: int): self {
|
||||
self += 1;
|
||||
y += 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
global c104: int;
|
||||
|
||||
@method_id(104)
|
||||
fun testIncChainedMutatingBoth() {
|
||||
var (x, y) = (0, 0);
|
||||
c104 = 0;
|
||||
x.incChainedMutatingBoth(mutate y).incChainedMutatingBoth(mutate y);
|
||||
incChainedMutatingBoth(mutate x, mutate y);
|
||||
x = x.incChainedMutatingBoth(mutate c104).incChainedMutatingBoth(mutate c104).incChainedMutatingBoth(mutate y);
|
||||
return (x, y, c104);
|
||||
}
|
||||
|
||||
fun incTensorChained(mutate self: (int, int)): self {
|
||||
val (f, s) = self;
|
||||
self = (f + 1, s + 1);
|
||||
return self;
|
||||
}
|
||||
|
||||
@method_id(105)
|
||||
fun testIncTensorChained(f: int, s: int) {
|
||||
var tens = (f, s);
|
||||
tens.incTensorChained().incTensorChained();
|
||||
return tens.incTensorChained().incTensorChained();
|
||||
}
|
||||
|
||||
fun incConditionalChainable(mutate self: int, mutate another: int, ifLessThan: int): self {
|
||||
another += 1;
|
||||
return self.incChained() < ifLessThan ? self.incChained().incChained() : self;
|
||||
}
|
||||
|
||||
@method_id(106)
|
||||
fun testIncConditionalChainable(x: int) {
|
||||
var y = 0;
|
||||
x.incConditionalChainable(mutate y, 5).incConditionalChainable(mutate y, 5);
|
||||
x = x.incConditionalChainable(mutate y, 5).incConditionalChainable(mutate y, 5);
|
||||
return (x.incConditionalChainable(mutate y, 5), y);
|
||||
}
|
||||
|
||||
fun checkNotEq(self: int, throwIfEq: int): void {
|
||||
if (self == throwIfEq) {
|
||||
throw 100 + throwIfEq;
|
||||
}
|
||||
}
|
||||
|
||||
@method_id(107)
|
||||
fun testNotMutatingSelf(arg: int) {
|
||||
try {
|
||||
arg.checkNotEq(100);
|
||||
arg.checkNotEq(101);
|
||||
arg.checkNotEq(102);
|
||||
return 0;
|
||||
} catch (code) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
global c108: int;
|
||||
|
||||
fun checkNotEqChainable(self: int, throwIfEq: int): self {
|
||||
c108 += 1;
|
||||
if (self != throwIfEq) {
|
||||
return self;
|
||||
}
|
||||
throw 100 + throwIfEq;
|
||||
return self;
|
||||
}
|
||||
|
||||
@method_id(108)
|
||||
fun testNotMutatingChainableSelf(arg: int) {
|
||||
c108 = 0;
|
||||
try {
|
||||
arg.checkNotEqChainable(100).checkNotEqChainable(101).checkNotEqChainable(102);
|
||||
arg = arg.checkNotEqChainable(100).checkNotEqChainable(101).checkNotEqChainable(102);
|
||||
return (arg, c108);
|
||||
} catch (code) {
|
||||
return (code, c108);
|
||||
}
|
||||
}
|
||||
|
||||
global onceFailed109: int;
|
||||
|
||||
fun checkNotEqChainableMutateAnother(self: int, throwIfEq: int, mutate toInc: int): self {
|
||||
if (onceFailed109) { return self; }
|
||||
toInc += 1;
|
||||
try { return self.checkNotEqChainable(throwIfEq); }
|
||||
catch { onceFailed109 = 1; return self; }
|
||||
}
|
||||
|
||||
global c109: int;
|
||||
|
||||
@method_id(109)
|
||||
fun testNotMutatingChainableSelfMutateAnother(initial: int) {
|
||||
val arg = initial;
|
||||
var x = 0;
|
||||
c108 = 0;
|
||||
c109 = 0;
|
||||
onceFailed109 = 0;
|
||||
arg.checkNotEqChainableMutateAnother(100, mutate x)
|
||||
.checkNotEqChainableMutateAnother(101, mutate c109)
|
||||
.checkNotEqChainableMutateAnother(102, mutate x);
|
||||
return (arg, c108, c109, x);
|
||||
}
|
||||
|
||||
|
||||
fun main() { }
|
||||
|
||||
/**
|
||||
@testcase | 101 | 5 | 9
|
||||
@testcase | 102 | | 20
|
||||
@testcase | 103 | 1 | 7
|
||||
@testcase | 103 | 100 | 101
|
||||
@testcase | 103 | 8 | 11
|
||||
@testcase | 104 | | 6 4 2
|
||||
@testcase | 105 | 1 2 | 5 6
|
||||
@testcase | 106 | -20 | -5 5
|
||||
@testcase | 106 | -1 | 8 5
|
||||
@testcase | 106 | 7 | 12 5
|
||||
@testcase | 107 | 200 | 0
|
||||
@testcase | 107 | 102 | 202
|
||||
@testcase | 108 | 200 | 200 6
|
||||
@testcase | 108 | 101 | 201 0
|
||||
@testcase | 109 | 200 | 200 3 1 2
|
||||
@testcase | 109 | 100 | 100 0 0 1
|
||||
@testcase | 109 | 102 | 102 2 1 2
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
incChained PROC:<{
|
||||
// self
|
||||
INC // self
|
||||
}>
|
||||
incChained2 PROC:<{
|
||||
// self
|
||||
incChained CALLDICT // self
|
||||
}>
|
||||
incChained3 PROC:<{
|
||||
// self
|
||||
incChained CALLDICT // self
|
||||
}>
|
||||
incChained4 PROC:<{
|
||||
// self
|
||||
incChained CALLDICT // self
|
||||
}>
|
||||
"""
|
||||
|
||||
@fif_codegen
|
||||
"""
|
||||
testIncChainedCodegen PROC:<{
|
||||
// x
|
||||
incChained CALLDICT // x
|
||||
incChained2 CALLDICT // x
|
||||
incChained3 CALLDICT // x
|
||||
incChained4 CALLDICT // x
|
||||
}>
|
||||
"""
|
||||
*/
|
|
@ -243,7 +243,7 @@ fun tanh_f258(x: int, n: int): int {
|
|||
repeat (n) {
|
||||
a = (c -= Two) + mulDivRound(x2, 1 << 239, a); // a := 2k+1+x^2/a as fixed250, k=n+1,n,...,2
|
||||
}
|
||||
a = (stackMoveToTop(3) << 254) + mulDivRound(x2, 1 << 243, a); // a := 3+x^2/a as fixed254
|
||||
a = (3 << 254) + mulDivRound(x2, 1 << 243, a); // a := 3+x^2/a as fixed254
|
||||
// y = x/(1+a') = x - x*a'/(1+a') = x - x*x^2/(a+x^2) where a' = x^2/a
|
||||
return x - (mulDivRound(x, x2, a + (x2 ~>> 7)) ~>> 7);
|
||||
}
|
||||
|
@ -257,12 +257,12 @@ fun expm1_f257(x: int): int {
|
|||
// (almost) compute tanh(x/2) first; x/2 as fixed258 = x as fixed257
|
||||
var x2: int = mulDivRound(x, x, 1 << 255); // x^2 as fixed261
|
||||
var Two: int = (1 << 251); // 2. as fixed250
|
||||
var a: int = stackMoveToTop(39) << 250; // a=2n+5 as fixed250
|
||||
var a: int = 39 << 250; // a=2n+5 as fixed250
|
||||
var c = a;
|
||||
repeat (17) {
|
||||
a = (c -= Two) + mulDivRound(x2, 1 << 239, a); // a := 2k+1+x^2/a as fixed250, k=n+1,n,...,2
|
||||
}
|
||||
a = (stackMoveToTop(3) << 254) + mulDivRound(x2, 1 << 243, a); // a := 3+x^2/a as fixed254
|
||||
a = (3 << 254) + mulDivRound(x2, 1 << 243, a); // a := 3+x^2/a as fixed254
|
||||
// now tanh(x/2) = x/(1+a') where a'=x^2/a ; apply exp(x)-1=2*tanh(x/2)/(1-tanh(x/2))
|
||||
var t: int = (x ~>> 4) - a; // t:=x-a as fixed254
|
||||
return x - mulDivRound(x2, t / 2, a + mulrshiftr256(x, t) ~/ 4) ~/ 4; // x - x^2 * (x-a) / (a + x*(x-a))
|
||||
|
@ -306,12 +306,12 @@ fun fixed248_exp2(x: int): int {
|
|||
fun tan_f260_inlined(x: int): int {
|
||||
var x2: int = mulrshiftr256(x, x); // x^2 as fixed264
|
||||
var Two: int = (1 << 251); // 2. as fixed250
|
||||
var a: int = stackMoveToTop(33) << 250; // a=2n+5 as fixed250
|
||||
var a: int = 33 << 250; // a=2n+5 as fixed250
|
||||
var c = a;
|
||||
repeat (14) {
|
||||
a = (c -= Two) - mulDivRound(x2, 1 << 236, a); // a := 2k+1-x^2/a as fixed250, k=n+1,n,...,2
|
||||
}
|
||||
a = (stackMoveToTop(3) << 254) - mulDivRound(x2, 1 << 240, a); // a := 3-x^2/a as fixed254
|
||||
a = (3 << 254) - mulDivRound(x2, 1 << 240, a); // a := 3-x^2/a as fixed254
|
||||
// y = x/(1-a') = x + x*a'/(1-a') = x + x*x^2/(a-x^2) where a' = x^2/a
|
||||
return x + (mulDivRound(x / 2, x2, a - (x2 ~>> 10)) ~>> 9);
|
||||
}
|
||||
|
@ -330,12 +330,12 @@ fun tan_f260(x: int): int {
|
|||
fun tan_f258_inlined(x: int): int {
|
||||
var x2: int = mulrshiftr256(x, x); // x^2 as fixed260
|
||||
var Two: int = (1 << 251); // 2. as fixed250
|
||||
var a: int = stackMoveToTop(41) << 250; // a=2n+5 as fixed250
|
||||
var a: int = 41 << 250; // a=2n+5 as fixed250
|
||||
var c = a;
|
||||
repeat (18) {
|
||||
a = (c -= Two) - mulDivRound(x2, 1 << 240, a); // a := 2k+1-x^2/a as fixed250, k=n+1,n,...,2
|
||||
}
|
||||
a = (stackMoveToTop(3) << 254) - mulDivRound(x2, 1 << 244, a); // a := 3-x^2/a as fixed254
|
||||
a = (3 << 254) - mulDivRound(x2, 1 << 244, a); // a := 3-x^2/a as fixed254
|
||||
// y = x/(1-a') = x + x*a'/(1-a') = x + x*x^2/(a-x^2) where a' = x^2/a
|
||||
return x + (mulDivRound(x / 2, x2, a - (x2 ~>> 6)) ~>> 5);
|
||||
}
|
||||
|
@ -546,9 +546,8 @@ fun atanh_f261(x: int, n: int): int {
|
|||
fun log_aux_f257(x: int): (int, int) {
|
||||
var s: int = log2_floor_p1(x);
|
||||
x <<= 256 - s;
|
||||
var t: int = stackMoveToTop(-1 << 256);
|
||||
var t: int = -1 << 256;
|
||||
if ((x >> 249) <= 90) {
|
||||
// t~stackMoveToTop();
|
||||
t >>= 1;
|
||||
s -= 1;
|
||||
}
|
||||
|
@ -593,7 +592,7 @@ fun pow33b(m: int): int {
|
|||
fun log_auxx_f260(x: int): (int, int, int) {
|
||||
var s: int = log2_floor_p1(x) - 1;
|
||||
x <<= 255 - s; // rescale to 1 <= x < 2 as fixed255
|
||||
var t: int = stackMoveToTop(2873) << 244; // ~ (33/32)^11 ~ sqrt(2) as fixed255
|
||||
var t: int = 2873 << 244; // ~ (33/32)^11 ~ sqrt(2) as fixed255
|
||||
var x1: int = (x - t) >> 1;
|
||||
var q: int = mulDivRound(x1, 65, x1 + t) + 11; // crude approximation to round(log(x)/log(33/32))
|
||||
// t = 1; repeat (q) { t *= 33; } // t:=33^q, 0<=q<=22
|
||||
|
@ -742,13 +741,14 @@ fun atan_aux_prereduce(x: int): (int, int, int) {
|
|||
var tc: int = 7214596; // tan(13*theta) as fixed24 where theta=atan(1/32)
|
||||
var t1: int = mulDivRound(xu - tc, 1 << 88, xu * tc + (1 << 48)); // tan(x') as fixed64 where x'=atan(x)-13*theta
|
||||
// t1/(3+t1^2) * 3073/32 = x'/3 * 3072/32 = x' / (96/3072) = x' / theta
|
||||
var q: int = mulDivRound(t1 * 3073, 1 << 59, t1 * t1 + (stackMoveToTop(3) << 128)) + 13; // approximately round(atan(x)/theta), 0<=q<=25
|
||||
var q: int = mulDivRound(t1 * 3073, 1 << 59, t1 * t1 + (3 << 128)) + 13; // approximately round(atan(x)/theta), 0<=q<=25
|
||||
var (pa, pb) = (33226912, 5232641); // (32+I)^5
|
||||
var (qh, ql) = divMod(q, 5);
|
||||
var (a, b) = (1 << (5 * (51 - q)), 0); // (1/32^q, 0) as fixed255
|
||||
repeat (ql) {
|
||||
// a+b*I *= 32+I
|
||||
(a, b) = (sub_rev(stackMoveToTop(b), 32 * a), a + 32 * b); // same as (32 * a - b, 32 * b + a), but more efficient
|
||||
b.stackMoveToTop();
|
||||
(a, b) = (sub_rev(b, 32 * a), a + 32 * b); // same as (32 * a - b, 32 * b + a), but more efficient
|
||||
}
|
||||
repeat (qh) {
|
||||
// a+b*I *= (32+I)^5 = pa + pb*I
|
||||
|
@ -807,7 +807,7 @@ fun atan_auxx_f256(x: int): (int, int) {
|
|||
@inline_ref
|
||||
fun atan_f255(x: int): int {
|
||||
var s: int = (x ~>> 256);
|
||||
stackMoveToTop(x);
|
||||
x.stackMoveToTop();
|
||||
if (s) {
|
||||
x = lshift256divr(-1 << 255, x); // x:=-1/x as fixed256
|
||||
} else {
|
||||
|
@ -880,7 +880,7 @@ fun fixed248_acos(x: int): int {
|
|||
@inline_ref
|
||||
fun fixed248_atan(x: int): int {
|
||||
var s: int = (x ~>> 249);
|
||||
stackMoveToTop(x);
|
||||
x.stackMoveToTop();
|
||||
if (s) {
|
||||
s = sign(s);
|
||||
x = lshift256divr(-1 << 248, x); // x:=-1/x as fixed256
|
||||
|
@ -897,7 +897,7 @@ fun fixed248_atan(x: int): int {
|
|||
@inline_ref
|
||||
fun fixed248_acot(x: int): int {
|
||||
var s: int = (x ~>> 249);
|
||||
stackMoveToTop(x);
|
||||
x.stackMoveToTop();
|
||||
if (s) {
|
||||
x = lshift256divr(-1 << 248, x); // x:=-1/x as fixed256
|
||||
s = 0;
|
||||
|
@ -918,7 +918,7 @@ fun fixed248_acot(x: int): int {
|
|||
/// fixed252 nrand();
|
||||
@inline_ref
|
||||
fun nrand_f252(): int {
|
||||
var (x, s, t, A, B, r0) = (nan(), stackMoveToTop(29483) << 236, stackMoveToTop(-3167) << 239, 12845, 16693, 9043);
|
||||
var (x, s, t, A, B, r0) = (nan(), 29483 << 236, -3167 << 239, 12845, 16693, 9043);
|
||||
// 4/sqrt(e*Pi) = 1.369 loop iterations on average
|
||||
do {
|
||||
var (u, v) = (random() / 16 + 1, mulDivRound(random() - (1 << 255), 7027, 1 << 16)); // fixed252; 7027=ceil(sqrt(8/e)*2^12)
|
||||
|
@ -950,7 +950,7 @@ fun nrand_f252(): int {
|
|||
/// fixed252 nrand_fast();
|
||||
@inline_ref
|
||||
fun nrand_fast_f252(): int {
|
||||
var t: int = stackMoveToTop(-3) << 253; // -6. as fixed252
|
||||
var t: int = -3 << 253; // -6. as fixed252
|
||||
repeat (12) {
|
||||
t += random() / 16; // add together 12 uniformly random numbers
|
||||
}
|
||||
|
@ -979,8 +979,8 @@ fun fixed248_nrand_fast(): int {
|
|||
}
|
||||
|
||||
@pure
|
||||
fun ~tset<X>(t: tuple, idx: int, value: X): (tuple, ())
|
||||
asm(t value idx) "SETINDEXVAR";
|
||||
fun tset<X>(mutate self: tuple, idx: int, value: X): void
|
||||
asm(self value idx) "SETINDEXVAR";
|
||||
|
||||
// computes 1-acos(x)/Pi by a very simple, extremely slow (~70k gas) and imprecise method
|
||||
// fixed256 acos_prepare_slow(fixed255 x);
|
||||
|
@ -1014,12 +1014,12 @@ fun asin_slow_f255(x: int): int {
|
|||
fun test_nrand(n: int): tuple {
|
||||
var t: tuple = createEmptyTuple();
|
||||
repeat (255) {
|
||||
t~tuplePush(0);
|
||||
t.tuplePush(0);
|
||||
}
|
||||
repeat (n) {
|
||||
var x: int = fixed248_nrand();
|
||||
var bucket: int = (abs(x) >> 243); // 255 buckets starting from x=0, each 1/32 wide
|
||||
t~tset(bucket, t.tupleAt(bucket) + 1);
|
||||
t.tset(bucket, t.tupleAt(bucket) + 1);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -1210,14 +1210,14 @@ fun main() {
|
|||
// return atan_aux_f256(1); // atan(1/2^256)*2^261 = 32
|
||||
//return fixed248_nrand();
|
||||
// return test_nrand(100000);
|
||||
var One2: int = stackMoveToTop(1 << 255);
|
||||
var One2: int = 1 << 255;
|
||||
// return asin_f255(One);
|
||||
// return asin_f255(-2 * One ~/ -3);
|
||||
var arg: int = mulDivRound(12, One2, 17); // 12/17
|
||||
// return [ asin_slow_f255(arg), asin_f255(arg) ];
|
||||
// return [ acos_slow_f255(arg), acos_f255(arg) ];
|
||||
// return 4 * atan_f255(One ~/ 5) - atan_f255(One ~/ 239); // 4 * atan(1/5) - atan(1/239) = Pi/4 as fixed255
|
||||
var One3: int = stackMoveToTop(1 << 248);
|
||||
var One3: int = 1 << 248;
|
||||
// return fixed248_atan(One) ~/ 5); // atan(1/5)
|
||||
// return fixed248_acot(One ~/ 239); // atan(1/5)
|
||||
}
|
||||
|
|
|
@ -17,11 +17,8 @@ fun bar(x: int, y: int): (int, int) {
|
|||
}
|
||||
return (x + 1, y);
|
||||
}
|
||||
fun bar2(x: int, y: int): (int,int) {
|
||||
return bar(x, y);
|
||||
}
|
||||
fun main(x: int, y: int): (int, int) {
|
||||
(x, y) = bar2(x, y);
|
||||
(x, y) = bar(x, y);
|
||||
return (x, y * 10);
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
fun main(): int {
|
||||
var c: cell = my_begin_cell().storeInt(demo_10, 32).my_end_cell();
|
||||
var cs: slice = my_begin_parse(c);
|
||||
var ten: int = cs~loadInt(32);
|
||||
var ten: int = cs.loadInt(32);
|
||||
return 1 + demo1(ten) + demo_var;
|
||||
}
|
||||
|
||||
|
|
22
tolk-tester/tests/var-apply.tolk
Normal file
22
tolk-tester/tests/var-apply.tolk
Normal file
|
@ -0,0 +1,22 @@
|
|||
fun getBeginCell() {
|
||||
return beginCell;
|
||||
}
|
||||
|
||||
fun getBeginParse() {
|
||||
return beginParse;
|
||||
}
|
||||
|
||||
@method_id(101)
|
||||
fun testVarApply1() {
|
||||
var (_, f_end_cell) = (0, endCell);
|
||||
var b: builder = (getBeginCell())().storeInt(1, 32);
|
||||
b.storeInt(2, 32);
|
||||
var s = (getBeginParse())(f_end_cell(b));
|
||||
return (s.loadInt(32), s.loadInt(32));
|
||||
}
|
||||
|
||||
fun main() {}
|
||||
|
||||
/**
|
||||
@testcase | 101 | | 1 2
|
||||
*/
|
|
@ -1,6 +1,6 @@
|
|||
@method_id(101)
|
||||
fun test1(cs: slice) {
|
||||
return cs~loadUint(8)+cs~loadUint(8)+cs~loadUint(8)+cs~loadUint(8);
|
||||
return cs.loadUint(8)+cs.loadUint(8)+cs.loadUint(8)+cs.loadUint(8);
|
||||
}
|
||||
|
||||
@method_id(102)
|
||||
|
@ -12,15 +12,15 @@ fun test2(cs: slice) {
|
|||
}
|
||||
|
||||
fun main(cs: slice) {
|
||||
return (cs~loadUint(8), cs~loadUint(8), cs~loadUint(8), cs~loadUint(8));
|
||||
return (cs.loadUint(8), cs.loadUint(8), cs.loadUint(8), cs.loadUint(8));
|
||||
}
|
||||
|
||||
fun f(cs: slice) {
|
||||
return (cs~loadUint(8), cs~loadUint(8), cs~loadUint(8), cs~loadUint(8),
|
||||
cs~loadUint(8), cs~loadUint(8), cs~loadUint(8), cs~loadUint(8),
|
||||
cs~loadUint(8), cs~loadUint(8), cs~loadUint(8), cs~loadUint(8),
|
||||
cs~loadUint(8), cs~loadUint(8), cs~loadUint(8), cs~loadUint(8),
|
||||
cs~loadUint(8), cs~loadUint(8), cs~loadUint(8), cs~loadUint(8));
|
||||
return (cs.loadUint(8), cs.loadUint(8), cs.loadUint(8), cs.loadUint(8),
|
||||
cs.loadUint(8), cs.loadUint(8), cs.loadUint(8), cs.loadUint(8),
|
||||
cs.loadUint(8), cs.loadUint(8), cs.loadUint(8), cs.loadUint(8),
|
||||
cs.loadUint(8), cs.loadUint(8), cs.loadUint(8), cs.loadUint(8),
|
||||
cs.loadUint(8), cs.loadUint(8), cs.loadUint(8), cs.loadUint(8));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue