Skip to content

Commit 0fb8c1c

Browse files
committed
[Tolk] Support serialization for enums
1 parent 1ebdc0a commit 0fb8c1c

16 files changed

+471
-6
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
enum C3 : int {
3+
}
4+
5+
/**
6+
@compilation_should_fail
7+
@stderr serialization type of `enum` must be intN: `int8` / `uint32` / etc.
8+
*/

tolk-tester/tests/maps-tests.tolk

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ struct DataWithCell {
3232
payload: cell? = null
3333
}
3434

35+
enum HashMode: uint16 {
36+
NoHash = 0,
37+
PartialHash = 80,
38+
TotalHash = 255,
39+
}
40+
3541
fun map<K, V>.calculateSize(self) {
3642
var size = 0;
3743
var r = self.findFirst();
@@ -500,6 +506,21 @@ fun test40() {
500506
);
501507
}
502508

509+
@method_id(141)
510+
fun test41() {
511+
var m = createEmptyMap<int8, HashMode>();
512+
m.set(-7, HashMode.NoHash);
513+
m.addIfNotExists(111, HashMode.TotalHash);
514+
m.replaceIfExists(-7, HashMode.PartialHash);
515+
516+
val k7 = m.get(-7);
517+
return (
518+
m.exists(8), m.mustGet(111) == HashMode.TotalHash,
519+
k7.isFound, k7.loadValue() == HashMode.NoHash, k7.loadValue() == HashMode.PartialHash
520+
);
521+
}
522+
523+
503524
fun main() {
504525
__expect_type(createEmptyMap<int8, (int32, int64)>, "() -> map<int8, (int32, int64)>");
505526
}
@@ -546,6 +567,7 @@ fun main() {
546567
@testcase | 138 | 4 | 55
547568
@testcase | 139 | | 0 -1 2
548569
@testcase | 140 | | 0 0 -1 777 -1 0 777 (null) typeid-1 (null) 0
570+
@testcase | 141 | | 0 -1 -1 0 -1
549571

550572
@fif_codegen
551573
"""

tolk-tester/tests/pack-unpack-2.tolk

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,15 @@ struct WithNullableMaps {
418418
m4: map<int32, int64> | int32
419419
}
420420

421+
enum EStoredAsInt8 { M100 = -100, Z = 0, P100 = 100 }
422+
enum EStoredAsUint1 { ZERO, ONE }
423+
424+
struct WithEnums {
425+
e1: EStoredAsInt8
426+
e2: EStoredAsUint1
427+
rem: uint7 = 0
428+
}
429+
421430

422431
// ---------------------------------------------
423432

@@ -749,7 +758,7 @@ fun test_serializeMaps() {
749758
}
750759
return (w.m1.isEmpty(), w.m2.isEmpty(), d3.isFound, d3.loadValue(), kl);
751760
}
752-
761+
753762
@method_id(231)
754763
fun test_nullableMaps() {
755764
var o: WithNullableMaps = {
@@ -772,6 +781,15 @@ fun test_nullableMaps() {
772781
return (o.m1 == null, o.m1!.isEmpty(), o.m2 == null, o.m2!.isEmpty(), o.m3 == null, o.m4 is int32);
773782
}
774783

784+
@method_id(232)
785+
fun test_SimpleEnums() {
786+
run<WithEnums>({e1: EStoredAsInt8.M100, e2: EStoredAsUint1.ZERO}, stringHexToSlice("9c00"));
787+
run<WithEnums>({e1: EStoredAsInt8.Z, e2: EStoredAsUint1.ZERO}, stringHexToSlice("0000"));
788+
run<WithEnums>({e1: EStoredAsInt8.P100, e2: EStoredAsUint1.ONE, rem: 1}, stringHexToSlice("6481"));
789+
return -1;
790+
}
791+
792+
775793
fun main() {
776794
var t: JustInt32 = { value: 10 };
777795
var c = t.toCell();
@@ -814,4 +832,5 @@ fun main() {
814832
@testcase | 229 | | -1
815833
@testcase | 230 | | 0 -1 -1 3 30 8 1
816834
@testcase | 231 | | 0 -1 0 0 -1 0
835+
@testcase | 232 | | -1
817836
*/

tolk-tester/tests/pack-unpack-5.tolk

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,23 @@ fun test20() {
205205
CellInner8_1.getDeclaredPackPrefixLen(), CellInner8_1.getDeclaredPackPrefix());
206206
}
207207

208+
enum Color { Red, Green, Blue }
209+
enum EInt9 { P133 = 133, M1 = -1 }
210+
enum EUint6 { P63 = 63, P30 = 30, P1 = 1 }
211+
enum EUint1 { A, B }
212+
enum EInt1 { A = -1, B }
213+
enum EUint123 { Z, V5 = 5, E123 = 1<<122, E123_2 = (1<<122) + (1<<121) }
214+
type EUint123Alias = EUint123
215+
216+
@method_id(121)
217+
fun test21() {
218+
return (
219+
Color.estimate(), EInt9.estimate(), EUint6.estimate(),
220+
EUint1.estimate(), EInt1.estimate(), EInt1.estimate(),
221+
EUint123.estimate(), EUint123Alias.estimate(),
222+
)
223+
}
224+
208225
fun main() {
209226
__expect_type(int8.estimatePackSize(), "(int, int, int, int)");
210227
}
@@ -222,4 +239,5 @@ fun main() {
222239
@testcase | 110 | | [ 32 9999 0 4 ] [ 33 9999 0 8 ]
223240
@testcase | 111 | | [ 1023 1023 0 1 ] [ 0 0 2 2 ]
224241
@testcase | 120 | | 16 4128 1 1
242+
@testcase | 121 | | [ 2 2 0 0 ] [ 9 9 0 0 ] [ 6 6 0 0 ] [ 1 1 0 0 ] [ 1 1 0 0 ] [ 1 1 0 0 ] [ 123 123 0 0 ] [ 123 123 0 0 ]
225243
*/

tolk-tester/tests/pack-unpack-7.tolk

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,22 @@ fun Tensor3Skipping1.packToBuilder(self, mutate b: builder) {
100100
b.storeUint(self.0, 8).storeUint(self.2, 8);
101101
}
102102

103+
enum Color {
104+
Red,
105+
Green,
106+
Blue,
107+
}
108+
109+
type UnsafeColor = Color
110+
111+
fun UnsafeColor.unpackFromSlice(mutate s: slice) {
112+
return s.loadUint(2) as Color
113+
}
114+
115+
fun UnsafeColor.packToBuilder(self, mutate b: builder) {
116+
b.storeUint(self as int, 2)
117+
}
118+
103119

104120
@method_id(101)
105121
fun test1() {
@@ -155,6 +171,15 @@ fun test7() {
155171
return t.toCell().load();
156172
}
157173

174+
@method_id(108)
175+
fun test8(c: UnsafeColor) {
176+
var way1 = beginCell().storeAny(c).endCell();
177+
var way2 = c.toCell();
178+
__expect_type(way2, "Cell<UnsafeColor>");
179+
assert (way1.hash() == way2.hash()) throw 123;
180+
return way2.load();
181+
}
182+
158183
fun main() {
159184
__expect_type("" as TelegramString, "TelegramString");
160185
}
@@ -169,6 +194,8 @@ fun main() {
169194
@testcase | 105 | | 123 1
170195
@testcase | 106 | | 6 2 255 0 8 9
171196
@testcase | 107 | | 1 0 3
197+
@testcase | 108 | 0 | 0
198+
@testcase | 108 | 3 | 3
172199

173200
@fif_codegen
174201
"""
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
enum EFits2Bits { ZERO, ONE, TWO }
2+
3+
fun EFits2Bits.sliceWithZero(): slice asm "b{00} PUSHSLICE"
4+
fun EFits2Bits.sliceWithThree(): slice asm "b{11} PUSHSLICE"
5+
6+
enum EStartFrom1 {
7+
ONE = 1
8+
TWO
9+
THREE
10+
}
11+
12+
enum EFillsAllUint3 {
13+
p0, p1, p2, p3, p4, p5, p6, p7
14+
}
15+
16+
enum EStartFromM2 {
17+
M2 = -2,
18+
M1, ZERO, P1, P2, P3 = 3,
19+
}
20+
21+
enum EFits8Bits {
22+
E0 = 0;
23+
E110 = 110;
24+
E220 = 220;
25+
}
26+
27+
const MAX_UINT = 115792089237316195423570985008687907853269984665640564039457584007913129639935
28+
29+
enum EMinMax {
30+
MIN_INT = -115792089237316195423570985008687907853269984665640564039457584007913129639935 - 1,
31+
MAX_INT = +115792089237316195423570985008687907853269984665640564039457584007913129639935,
32+
}
33+
34+
enum E0Max {
35+
ZERO,
36+
MAX_INT = +115792089237316195423570985008687907853269984665640564039457584007913129639935,
37+
}
38+
39+
struct WithEnumsUnion {
40+
u: EFits8Bits | EStartFromM2
41+
}
42+
43+
enum Role: int8 {
44+
Admin, User,
45+
}
46+
47+
fun (Role, Role).decode(mutate self, s: slice) {
48+
self = s.loadAny()
49+
}
50+
51+
enum EncodedVari : varint16 {
52+
ONE = 1,
53+
TWO = 2,
54+
MANY = 1<<100,
55+
}
56+
57+
58+
@method_id(101)
59+
fun test1() {
60+
var e = EFits2Bits.fromSlice(EFits2Bits.sliceWithZero());
61+
return (e == EFits2Bits.ZERO, e == EFits2Bits.TWO);
62+
}
63+
64+
@method_id(102)
65+
fun test2(c: EFits2Bits) {
66+
try {
67+
return (c.toCell().beginParse().loadAny<EFits2Bits>() == c) as int
68+
} catch (ex) {
69+
return ex * 10
70+
}
71+
}
72+
73+
@method_id(103)
74+
fun test3() {
75+
return EStartFrom1.fromCell(EStartFrom1.ONE.toCell())
76+
}
77+
78+
@method_id(104)
79+
fun test4(v: EFillsAllUint3) {
80+
return EFillsAllUint3.fromCell(v.toCell())
81+
}
82+
83+
@method_id(105)
84+
fun test5(s: slice) {
85+
return EStartFromM2.fromSlice(s, {assertEndAfterReading: false})
86+
}
87+
88+
@method_id(106)
89+
fun test6() {
90+
try {
91+
return (4 as EFits2Bits).toCell().beginParse().loadUint(1)
92+
} catch (ex) {
93+
return ex
94+
}
95+
}
96+
97+
@method_id(107)
98+
fun test7(v: EFits8Bits) {
99+
try { return EFits8Bits.fromCell(v.toCell()) as int }
100+
catch (ex) { return ex * 1000 }
101+
}
102+
103+
@method_id(108)
104+
fun test8() {
105+
var s_min = beginCell().storeInt(-MAX_UINT - 1, 257).endCell();
106+
var s_max = beginCell().storeInt(+MAX_UINT, 257).endCell();
107+
return (
108+
EMinMax.fromCell(s_min) == EMinMax.MIN_INT, EMinMax.fromCell(s_max) == EMinMax.MAX_INT,
109+
EMinMax.fromCell(s_max) == EMinMax.MIN_INT, EMinMax.fromCell(s_min) == EMinMax.MAX_INT,
110+
)
111+
}
112+
113+
@method_id(109)
114+
fun test9() {
115+
var s_min = beginCell().storeUint(0, 256).endCell();
116+
var s_max = beginCell().storeUint(MAX_UINT, 256).endCell();
117+
return (
118+
E0Max.fromCell(s_min) == E0Max.ZERO, E0Max.fromCell(s_max) == E0Max.MAX_INT,
119+
)
120+
}
121+
122+
@method_id(110)
123+
fun test10() {
124+
var w1 = WithEnumsUnion{u: EFits8Bits.E110}.toCell().load();
125+
var w2 = WithEnumsUnion{u: (220 as EFits8Bits)}.toCell().load();
126+
var w3 = WithEnumsUnion{u: ([0] as tuple).get<EStartFromM2>(0)}.toCell().load();
127+
var w4 = WithEnumsUnion{u: EStartFromM2.P3}.toCell().load();
128+
return (
129+
w1.u is EFits8Bits && w1.u == EFits8Bits.E110,
130+
w2.u is EFits8Bits && w2.u == EFits8Bits.E220,
131+
w3.u is EStartFromM2 && w3.u == EStartFromM2.ZERO,
132+
w4.u is EStartFromM2 && w4.u == EStartFromM2.P3,
133+
w4.u is EFits8Bits && w4.u == EFits8Bits.E220,
134+
)
135+
}
136+
137+
@method_id(111)
138+
fun test11() {
139+
var (r1, r2) = (-1 as Role, -1 as Role);
140+
val before = (r1 == Role.Admin, r2 == Role.Admin);
141+
(r1, r2).decode(stringHexToSlice("0001"));
142+
return (before, r1, r2, r1 == Role.Admin, r2 == Role.Admin, r1 == Role.User, r2 == Role.User)
143+
}
144+
145+
@method_id(112)
146+
fun test12() {
147+
var c3_one = EncodedVari.fromSlice(stringHexToSlice("1018_"));
148+
var c3_many = EncodedVari.fromSlice(stringHexToSlice("d100000000000000000000000008_"));
149+
return (c3_one, c3_one == EncodedVari.MANY, c3_many == EncodedVari.MANY);
150+
}
151+
152+
fun main() {
153+
154+
}
155+
156+
/**
157+
@testcase | 101 | | -1 0
158+
@testcase | 102 | 1 | -1
159+
@testcase | 102 | 3 | 50
160+
@testcase | 103 | | 1
161+
@testcase | 104 | 3 | 3
162+
@testcase | 104 | 7 | 7
163+
@testcase | 105 | x{d} | -2
164+
@testcase | 105 | x{7} | 3
165+
@testcase | 106 | | 5
166+
@testcase | 107 | 0 | 0
167+
@testcase | 107 | 110 | 110
168+
@testcase | 107 | 220 | 220
169+
@testcase | 107 | -50 | 5000
170+
@testcase | 107 | 1 | 5000
171+
@testcase | 107 | 222 | 5000
172+
@testcase | 108 | | -1 -1 0 0
173+
@testcase | 109 | | -1 -1
174+
@testcase | 110 | | -1 -1 -1 -1 0
175+
@testcase | 111 | | 0 0 0 1 -1 0 0 -1
176+
@testcase | 112 | | 1 0 -1
177+
178+
@fif_codegen
179+
"""
180+
test1() PROC:<{
181+
b{00} PUSHSLICE
182+
2 LDU
183+
OVER
184+
2 GTINT
185+
5 THROWIF
186+
ENDS
187+
"""
188+
189+
@fif_codegen
190+
"""
191+
test4() PROC:<{ // v
192+
NEWC // v b
193+
3 STU // b
194+
ENDC // '4
195+
CTOS // s
196+
3 LDU // '9 s
197+
ENDS // '9
198+
}>
199+
"""
200+
201+
@fif_codegen
202+
"""
203+
test5() PROC:<{
204+
// s
205+
3 PLDI
206+
DUP
207+
-2 LESSINT
208+
5 THROWIF
209+
DUP
210+
3 GTINT
211+
5 THROWIF
212+
}>
213+
"""
214+
215+
*/

0 commit comments

Comments
 (0)