Skip to content

Commit f00ff75

Browse files
authored
[FunC] Make Expr::VarApply always impure (#1381)
Expr::_VarApply is now always impure. It means, that for `some_var()`, don't make any considerations about runtime value, it's always called.
1 parent 89f136e commit f00ff75

File tree

3 files changed

+137
-2
lines changed

3 files changed

+137
-2
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
tuple empty_tuple() asm "NIL";
2+
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
3+
builder begin_cell() asm "NEWC";
4+
cell end_cell(builder b) asm "ENDC";
5+
slice begin_parse(cell c) asm "CTOS";
6+
7+
8+
_ getBeginCell() {
9+
return begin_cell;
10+
}
11+
12+
_ getBeginParse() {
13+
return begin_parse;
14+
}
15+
16+
(int, int) test101() method_id(101) {
17+
var (_, f_end_cell) = (0, end_cell);
18+
builder b = (getBeginCell())().store_int(1, 32);
19+
b~store_int(2, 32);
20+
var s = (getBeginParse())(f_end_cell(b));
21+
return (s~load_int(32), s~load_int(32));
22+
}
23+
24+
() my_throw_always() inline {
25+
throw(1000);
26+
}
27+
28+
_ get_raiser() inline {
29+
return my_throw_always;
30+
}
31+
32+
int test102() method_id(102) {
33+
try {
34+
var raiser = get_raiser();
35+
raiser(); ;; `some_var()` is always impure, the compiler has no considerations about its runtime value
36+
return 0;
37+
} catch (_, code) {
38+
return code;
39+
}
40+
}
41+
42+
int sum(int a, int b) impure inline {
43+
throw_unless(1000, a + b < 24);
44+
return a + b;
45+
}
46+
47+
int mul(int a, int b) impure inline {
48+
throw_unless(1001, a * b < 24);
49+
return a * b;
50+
}
51+
52+
int sum_pure(int a, int b) inline {
53+
throw_unless(1000, a + b < 24);
54+
return a + b;
55+
}
56+
57+
int mul_pure(int a, int b) inline {
58+
throw_unless(1001, a * b < 24);
59+
return a * b;
60+
}
61+
62+
int demo_handler(int op, int query_id, int a, int b) {
63+
if (op == 0xF2) {
64+
var func = query_id % 2 == 0 ? sum : mul;
65+
int result = func(a, b);
66+
return 0; ;; result not used, we test that func is nevertheless called
67+
}
68+
if (op == 0xF3) {
69+
var func = query_id % 2 == 0 ? sum_pure : mul_pure;
70+
int result = func(a, b);
71+
return 0; ;; the same for sum_pure, since `some_var()` is always impure
72+
}
73+
if (op == 0xF4) {
74+
var func = query_id % 2 == 0 ? sum : mul;
75+
int result = func(a, b);
76+
return result;
77+
}
78+
return -1;
79+
}
80+
81+
tuple test103() method_id(103) {
82+
tuple t = empty_tuple();
83+
try {
84+
t~tpush(demo_handler(0xF2, 122, 100, 200));
85+
} catch(_, code) {
86+
t~tpush(code);
87+
}
88+
try {
89+
t~tpush(demo_handler(0xF4, 122, 100, 200));
90+
} catch(_, code) {
91+
t~tpush(code);
92+
}
93+
try {
94+
t~tpush(demo_handler(0xF3, 122, 10, 10));
95+
} catch(_, code) {
96+
t~tpush(code);
97+
}
98+
try {
99+
t~tpush(demo_handler(0xF3, 123, 10, 10));
100+
} catch(_, code) {
101+
t~tpush(code);
102+
}
103+
return t;
104+
}
105+
106+
() always_throw2(int x) impure {
107+
throw (239 + x);
108+
}
109+
110+
global int -> () global_f;
111+
112+
int test104() method_id(104) {
113+
try {
114+
global_f = always_throw2;
115+
global_f(1);
116+
return 0;
117+
} catch (_, code) {
118+
return code;
119+
}
120+
}
121+
122+
() main() {
123+
}
124+
125+
126+
{-
127+
method_id | in | out
128+
TESTCASE | 101 | | 1 2
129+
TESTCASE | 102 | | 1000
130+
TESTCASE | 103 | | [ 1000 1000 0 1001 ]
131+
TESTCASE | 104 | | 240
132+
-}

crypto/func/gen-abscode.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,10 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
380380
}
381381
res.push_back(tfunc[0]);
382382
auto rvect = new_tmp_vect(code);
383-
code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
383+
auto& op = code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
384+
if (flags & _IsImpure) {
385+
op.flags |= Op::_Impure;
386+
}
384387
return rvect;
385388
}
386389
case _Const: {

crypto/func/parse-func.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ Expr* make_func_apply(Expr* fun, Expr* x) {
427427
res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure);
428428
} else {
429429
res = new Expr{Expr::_VarApply, {fun, x}};
430-
res->flags = Expr::_IsRvalue;
430+
res->flags = Expr::_IsRvalue | Expr::_IsImpure; // for `some_var()`, don't make any considerations about runtime value, it's impure
431431
}
432432
return res;
433433
}

0 commit comments

Comments
 (0)