mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[FunC] Make all functions impure by default, add "pure" specifier
This commit is contained in:
parent
a3e9e03019
commit
85c60d1263
61 changed files with 3511 additions and 3500 deletions
|
@ -1,17 +1,17 @@
|
|||
tuple empty_tuple() asm "NIL";
|
||||
forall X -> (tuple, ()) tpush(tuple t, X x) asm "TPUSH";
|
||||
tuple empty_tuple() pure asm "NIL";
|
||||
forall X -> (tuple, ()) tpush(tuple t, X x) pure asm "TPUSH";
|
||||
tuple emptyTuple() { return empty_tuple(); }
|
||||
forall X -> (tuple, ()) tuplePush(tuple t, X value) { return tpush(t, value); }
|
||||
|
||||
tuple asm_func_1(int x, int y, int z) asm "3 TUPLE";
|
||||
tuple asm_func_2(int x, int y, int z) asm (z y x -> 0) "3 TUPLE";
|
||||
tuple asm_func_3(int x, int y, int z) asm (y z x -> 0) "3 TUPLE";
|
||||
tuple asm_func_4(int a, (int, (int, int)) b, int c) asm (b a c -> 0) "5 TUPLE";
|
||||
tuple asm_func_1(int x, int y, int z) pure asm "3 TUPLE";
|
||||
tuple asm_func_2(int x, int y, int z) pure asm (z y x -> 0) "3 TUPLE";
|
||||
tuple asm_func_3(int x, int y, int z) pure asm (y z x -> 0) "3 TUPLE";
|
||||
tuple asm_func_4(int a, (int, (int, int)) b, int c) pure asm (b a c -> 0) "5 TUPLE";
|
||||
|
||||
_ asmFunc1(int x, int y, int z) { return asm_func_1(x, y, z); }
|
||||
_ asmFunc3(int x, int y, int z) { return asm_func_3(x, y, z); }
|
||||
|
||||
(tuple, ()) asm_func_modify(tuple a, int b, int c) asm (c b a -> 0) "SWAP TPUSH SWAP TPUSH";
|
||||
(tuple, ()) asm_func_modify(tuple a, int b, int c) pure asm (c b a -> 0) "SWAP TPUSH SWAP TPUSH";
|
||||
(tuple, ()) asmFuncModify(tuple a, int b, int c) { return asm_func_modify(a, b, c); }
|
||||
|
||||
global tuple t;
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
;; This works with ~functions also. And even works with wrappers of wrappers.
|
||||
;; Moreover, such wrappers can reorder input parameters, see a separate test camel2.fc.
|
||||
|
||||
builder begin_cell() asm "NEWC";
|
||||
cell end_cell(builder b) asm "ENDC";
|
||||
builder store_ref(builder b, cell c) asm(c b) "STREF";
|
||||
slice begin_parse(cell c) asm "CTOS";
|
||||
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
|
||||
(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
|
||||
builder begin_cell() pure asm "NEWC";
|
||||
cell end_cell(builder b) pure asm "ENDC";
|
||||
builder store_ref(builder b, cell c) pure asm(c b) "STREF";
|
||||
slice begin_parse(cell c) pure asm "CTOS";
|
||||
slice skip_bits(slice s, int len) pure asm "SDSKIPFIRST";
|
||||
(slice, ()) ~skip_bits(slice s, int len) pure asm "SDSKIPFIRST";
|
||||
|
||||
builder beginCell() { return begin_cell(); }
|
||||
cell endCell(builder b) { return end_cell(b); }
|
||||
|
@ -21,19 +21,19 @@ builder storeRef(builder b, cell c) { return store_ref(b, c); }
|
|||
builder storeUint(builder b, int i, int bw) { return store_uint(b, i, bw); }
|
||||
|
||||
;; 'inline' is not needed actually, but if it exists, it's just ignored
|
||||
slice beginParse(cell c) inline { return begin_parse(c); }
|
||||
slice skipBits(slice s, int len) inline { return skip_bits(s, len); }
|
||||
(slice, ()) ~skipBits(slice s, int len) inline { return ~skip_bits(s, len); }
|
||||
(slice, int) ~loadUint(slice s, int len) inline { return load_uint(s, len); }
|
||||
slice beginParse(cell c) pure inline { return begin_parse(c); }
|
||||
slice skipBits(slice s, int len) pure inline { return skip_bits(s, len); }
|
||||
(slice, ()) ~skipBits(slice s, int len) pure inline { return ~skip_bits(s, len); }
|
||||
(slice, int) ~loadUint(slice s, int len) pure inline { return load_uint(s, len); }
|
||||
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
|
||||
(int, int, int) computeDataSize(cell c, int maxCells) impure { return compute_data_size(c, maxCells); }
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) asm "CDATASIZE";
|
||||
(int, int, int) computeDataSize(cell c, int maxCells) { return compute_data_size(c, maxCells); }
|
||||
|
||||
cell new_dict() asm "NEWDICT";
|
||||
cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
|
||||
(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
|
||||
(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
|
||||
(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
|
||||
cell new_dict() pure asm "NEWDICT";
|
||||
cell idict_set(cell dict, int key_len, int index, slice value) pure asm(value index dict key_len) "DICTISET";
|
||||
(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) pure asm(value index dict key_len) "DICTISET";
|
||||
(slice, int) idict_get?(cell dict, int key_len, int index) pure asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
|
||||
(int, slice, int) idict_get_min?(cell dict, int key_len) pure asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
|
||||
|
||||
cell dict::new() { return new_dict(); }
|
||||
cell dict::iset(cell dict, int keyLen, int index, slice value) { return idict_set(dict, keyLen, index, value); }
|
||||
|
@ -41,11 +41,11 @@ cell dict::iset(cell dict, int keyLen, int index, slice value) { return idict_se
|
|||
(slice, int) dict::tryIGet(cell dict, int keyLen, int index) { return idict_get?(dict, keyLen, index); }
|
||||
(int, slice, int) dict::tryIGetMin(cell dict, int keyLen) { return idict_get_min?(dict, keyLen); }
|
||||
|
||||
tuple empty_tuple() asm "NIL";
|
||||
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
|
||||
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
|
||||
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
|
||||
forall X -> X null() asm "PUSHNULL";
|
||||
tuple empty_tuple() pure asm "NIL";
|
||||
forall X -> tuple tpush(tuple t, X value) pure asm "TPUSH";
|
||||
forall X -> (tuple, ()) ~tpush(tuple t, X value) pure asm "TPUSH";
|
||||
forall X, Y, Z -> Y triple_second([X, Y, Z] p) pure asm "SECOND";
|
||||
forall X -> X null() pure asm "PUSHNULL";
|
||||
|
||||
tuple emptyTuple() { return empty_tuple(); }
|
||||
tuple emptyTuple1() { return emptyTuple(); }
|
||||
|
@ -54,19 +54,19 @@ forall X -> tuple tuplePush(tuple t, X value) { return tpush(t, value); }
|
|||
forall X -> (tuple, ()) ~tuplePush(tuple t, X value) { return ~tpush(t, value); }
|
||||
forall X -> X tupleAt(tuple t, int index) { return at(t, index); }
|
||||
forall X1, Y2, Z3 -> Y2 tripleSecond([X1, Y2, Z3] p) { return triple_second(p); }
|
||||
forall X -> X nullValue() asm "PUSHNULL";
|
||||
forall X -> X nullValue() pure asm "PUSHNULL";
|
||||
|
||||
() throwIf(int excNo, int condition) impure { return throw_if(excNo, condition); }
|
||||
() throwIf(int excNo, int condition) { return throw_if(excNo, condition); }
|
||||
|
||||
tuple initial1(tuple x) { return x; }
|
||||
_ initial2(x) { return initial1(x); }
|
||||
|
||||
int add(int x, int y) { return x + y; } ;; this is also a wrapper, as its body is _+_(x,y)
|
||||
|
||||
() fake1(int a, int b, int c) impure asm(a b c) "DROP DROP DROP";
|
||||
() fake2(int a, int b, int c) impure asm(b c a) "DROP DROP DROP";
|
||||
() fake3(int a, int b, int c) impure asm(c a b) "DROP DROP DROP";
|
||||
() fake4(int a, int b, int c) impure asm(c b a) "DROP DROP DROP";
|
||||
() fake1(int a, int b, int c) asm(a b c) "DROP DROP DROP";
|
||||
() fake2(int a, int b, int c) asm(b c a) "DROP DROP DROP";
|
||||
() fake3(int a, int b, int c) asm(c a b) "DROP DROP DROP";
|
||||
() fake4(int a, int b, int c) asm(c b a) "DROP DROP DROP";
|
||||
|
||||
() fake1Wrapper(int a, int b, int c) { return fake1(a, b, c); }
|
||||
() fake2Wrapper(int a, int b, int c) { return fake2(a, b, c); }
|
||||
|
@ -95,9 +95,9 @@ int add(int x, int y) { return x + y; } ;; this is also a wrapper, as its body i
|
|||
;; skip 64 bits
|
||||
minv~skipBits(16);
|
||||
minv = minv.skipBits(16);
|
||||
minv.skipBits(16000); ;; does nothing
|
||||
minv.skipBits(11); ;; does nothing
|
||||
(minv, _) = ~skipBits(minv, 16);
|
||||
skipBits(minv, 16000); ;; does nothing
|
||||
skipBits(minv, 11); ;; does nothing
|
||||
minv~skipBits(16);
|
||||
;; load 3*32
|
||||
var minv1 = minv~loadUint(32);
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
#pragma compute-asm-ltr;
|
||||
|
||||
builder begin_cell() asm "NEWC";
|
||||
cell end_cell(builder b) asm "ENDC";
|
||||
slice begin_parse(cell c) asm "CTOS";
|
||||
builder store_ref(builder b, cell c) asm(c b) "STREF";
|
||||
builder begin_cell() pure asm "NEWC";
|
||||
cell end_cell(builder b) pure asm "ENDC";
|
||||
slice begin_parse(cell c) pure asm "CTOS";
|
||||
builder store_ref(builder b, cell c) pure asm(c b) "STREF";
|
||||
|
||||
builder beginCell() { return begin_cell(); }
|
||||
cell endCell(builder b) { return end_cell(b); }
|
||||
|
@ -19,13 +19,13 @@ builder storeRef2(cell c, builder b) { return store_ref(b, c); }
|
|||
builder storeUint1(builder b, int x, int bw) { return store_uint(b, x, bw); }
|
||||
builder storeUint2(builder b, int bw, int x) { return store_uint(b, x, bw); }
|
||||
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
|
||||
(int, int, int) computeDataSize1(cell c, int maxCells) impure { return compute_data_size(c, maxCells); }
|
||||
(int, int, int) computeDataSize2(int maxCells, cell c) impure { return compute_data_size(c, maxCells); }
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) pure asm "CDATASIZE";
|
||||
(int, int, int) computeDataSize1(cell c, int maxCells) { return compute_data_size(c, maxCells); }
|
||||
(int, int, int) computeDataSize2(int maxCells, cell c) { return compute_data_size(c, maxCells); }
|
||||
|
||||
() throwIf(int condition, int excNo) impure { return throw_if(excNo, condition); }
|
||||
() throwIf(int condition, int excNo) { return throw_if(excNo, condition); }
|
||||
|
||||
() fake(int a, int b, int c) impure asm "DROP DROP DROP";
|
||||
() fake(int a, int b, int c) asm "DROP DROP DROP";
|
||||
() fake2(int b, int c, int a) { return fake(a,b,c); }
|
||||
() fake3(int c, int a, int b) { return fake(a,b,c); }
|
||||
() fake4(int c, int b, int a) { return fake(a,b,c); }
|
||||
|
|
|
@ -4,22 +4,22 @@
|
|||
;; (save to a variable, return from a function, etc.)
|
||||
;; it also works, since a function becomes codegenerated (though direct calls are expectedly inlined).
|
||||
|
||||
builder begin_cell() asm "NEWC";
|
||||
cell end_cell(builder b) asm "ENDC";
|
||||
builder store_ref(builder b, cell c) asm(c b) "STREF";
|
||||
builder begin_cell() pure asm "NEWC";
|
||||
cell end_cell(builder b) pure asm "ENDC";
|
||||
builder store_ref(builder b, cell c) pure asm(c b) "STREF";
|
||||
|
||||
builder beginCell() { return begin_cell(); }
|
||||
cell endCell(builder b) { return end_cell(b); }
|
||||
builder storeRef(builder b, cell c) { return store_ref(b, c); }
|
||||
builder storeUint3(int i, int bw, builder b) { return store_uint(b, i, bw); }
|
||||
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
|
||||
(int, int, int) computeDataSize2(int maxCells, cell c) impure { return compute_data_size(c, maxCells); }
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) asm "CDATASIZE";
|
||||
(int, int, int) computeDataSize2(int maxCells, cell c) { return compute_data_size(c, maxCells); }
|
||||
|
||||
tuple empty_tuple() asm "NIL";
|
||||
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
|
||||
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
|
||||
forall X -> X first(tuple t) asm "FIRST";
|
||||
tuple empty_tuple() pure asm "NIL";
|
||||
forall X -> tuple tpush(tuple t, X value) pure asm "TPUSH";
|
||||
forall X -> (tuple, ()) ~tpush(tuple t, X value) pure asm "TPUSH";
|
||||
forall X -> X first(tuple t) pure asm "FIRST";
|
||||
|
||||
tuple emptyTuple() { return empty_tuple(); }
|
||||
forall X -> tuple tuplePush(tuple t, X value) { return tpush(t, value); }
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
;; 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.)
|
||||
|
||||
builder begin_cell() asm "NEWC";
|
||||
cell end_cell(builder b) asm "ENDC";
|
||||
slice begin_parse(cell c) asm "CTOS";
|
||||
() set_data(cell c) impure asm "c4 POP";
|
||||
cell get_data() asm "c4 PUSH";
|
||||
tuple empty_tuple() asm "NIL";
|
||||
forall X -> (tuple, ()) tpush(tuple t, X x) asm "TPUSH";
|
||||
builder begin_cell() pure asm "NEWC";
|
||||
cell end_cell(builder b) pure asm "ENDC";
|
||||
slice begin_parse(cell c) pure asm "CTOS";
|
||||
() set_data(cell c) asm "c4 POP";
|
||||
cell get_data() pure asm "c4 PUSH";
|
||||
tuple empty_tuple() pure asm "NIL";
|
||||
forall X -> (tuple, ()) tpush(tuple t, X x) pure asm "TPUSH";
|
||||
|
||||
builder storeUint(builder b, int x, int unused) { return store_uint(b, x, x); }
|
||||
() throwIf(int excNo, int cond) impure { throw_if(excNo, cond); }
|
||||
() throwIf2(int excNo, int cond) { return throw_if(excNo, cond); }
|
||||
() throwIf(int excNo, int cond) { throw_if(excNo, cond); }
|
||||
|
||||
_ initial1(x) { return x; }
|
||||
_ initial2(x) { return initial1(x); }
|
||||
|
||||
tuple asm_func_4(int a, (int, (int, int)) b, int c) asm (b a c -> 0) "5 TUPLE";
|
||||
tuple asm_func_4(int a, (int, (int, int)) b, int c) pure asm (b a c -> 0) "5 TUPLE";
|
||||
_ asmFunc4(int a, (int, (int, int)) b, int c) { return asm_func_4(a, b, c); }
|
||||
|
||||
int postpone_elections() {
|
||||
|
@ -28,7 +27,6 @@ int postpone_elections() {
|
|||
set_data(c);
|
||||
slice s = get_data().begin_parse();
|
||||
throwIf(101, 0);
|
||||
var unused = throwIf2(101, 0);
|
||||
return s~load_uint(8);
|
||||
}
|
||||
|
||||
|
@ -90,7 +88,6 @@ TESTCASE | -1 | 97 | 97
|
|||
|
||||
@fif_codegen DECLPROC storeUint
|
||||
@fif_codegen DECLPROC throwIf
|
||||
@fif_codegen DECLPROC throwIf2
|
||||
@fif_codegen DECLPROC postpone_elections
|
||||
@fif_codegen 74435 DECLMETHOD test2
|
||||
|
||||
|
|
|
@ -28,14 +28,14 @@ const int int240 = ((int1 + int2) * 10) << 3;
|
|||
|
||||
int iget240() { return int240; }
|
||||
|
||||
builder newc() asm "NEWC";
|
||||
slice endcs(builder b) asm "ENDC" "CTOS";
|
||||
int sdeq (slice s1, slice s2) asm "SDEQ";
|
||||
builder stslicer(builder b, slice s) asm "STSLICER";
|
||||
builder newc() pure asm "NEWC";
|
||||
slice endcs(builder b) pure asm "ENDC" "CTOS";
|
||||
int sdeq (slice s1, slice s2) pure asm "SDEQ";
|
||||
builder stslicer(builder b, slice s) pure asm "STSLICER";
|
||||
|
||||
builder storeUint(builder b, int x, int len) { return store_uint(b, x, len); }
|
||||
_ endSlice(builder b) { return endcs(b); }
|
||||
() throwUnless(int excno, int cond) impure { return throw_unless(excno, cond); }
|
||||
() throwUnless(int excno, int cond) { return throw_unless(excno, cond); }
|
||||
|
||||
_ main() {
|
||||
int i1 = iget1();
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
global int g;
|
||||
|
||||
_ foo_repeat() impure inline {
|
||||
_ foo_repeat() inline {
|
||||
g = 1;
|
||||
repeat(5) {
|
||||
g *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
int foo_until() impure inline {
|
||||
int foo_until() inline {
|
||||
g = 1;
|
||||
int i = 0;
|
||||
do {
|
||||
|
@ -17,7 +17,7 @@ int foo_until() impure inline {
|
|||
return i;
|
||||
}
|
||||
|
||||
int foo_while() impure inline {
|
||||
int foo_while() inline {
|
||||
g = 1;
|
||||
int i = 0;
|
||||
while (i < 10) {
|
||||
|
|
|
@ -26,9 +26,9 @@ int string_crc32() method_id {
|
|||
return "transfer(slice, int)"c;
|
||||
}
|
||||
|
||||
builder newc() asm "NEWC";
|
||||
builder newc() pure asm "NEWC";
|
||||
slice endcs(builder b) asm "ENDC" "CTOS";
|
||||
int sdeq (slice s1, slice s2) asm "SDEQ";
|
||||
int sdeq (slice s1, slice s2) pure asm "SDEQ";
|
||||
|
||||
_ main() {
|
||||
slice s_ascii = ascii_slice();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "../../../smartcont/mathlib.fc";
|
||||
|
||||
forall X -> (tuple, ()) ~tset(tuple t, int idx, X val) asm(t val idx) "SETINDEXVAR";
|
||||
forall X -> (tuple, ()) ~tset(tuple t, int idx, X val) pure asm(t val idx) "SETINDEXVAR";
|
||||
|
||||
;; computes 1-acos(x)/Pi by a very simple, extremely slow (~70k gas) and imprecise method
|
||||
;; fixed256 acos_prepare_slow(fixed255 x);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue