Skip to content

Commit bee8ccd

Browse files
committed
Tolk v1.1 wasm and stdlib
1 parent 9c31b3e commit bee8ccd

12 files changed

+637
-223
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ton/tolk-js",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Tolk Language compiler (next-generation FunC)",
55
"main": "dist/index.js",
66
"bin": "./dist/cli.js",

src/tolk-stdlib/common.tolk

Lines changed: 533 additions & 180 deletions
Large diffs are not rendered by default.

src/tolk-stdlib/gas-payments.tolk

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// A part of standard library for Tolk
2-
tolk 1.0
2+
tolk 1.1
33

44
/**
55
Gas and payment related primitives.
@@ -32,24 +32,24 @@ fun setGasLimitToMaximum(): void
3232
fun setGasLimit(limit: int): void
3333
asm "SETGASLIMIT"
3434

35-
/// Calculates fee (amount in nanotoncoins to be paid) for a transaction which consumed [gasUsed] gas units.
35+
/// Calculates fee (amount in nanotoncoins to be paid) for a transaction which consumed `gasUsed` gas units.
3636
fun calculateGasFee(workchain: int8, gasUsed: int): coins
3737
asm(gasUsed workchain) "GETGASFEE"
3838

39-
/// Same as [calculateGasFee], but without flat price (you have supposed to read https://docs.ton.org/develop/howto/fees-low-level)
39+
/// Same as [calculateGasFee], but without flat price. [Docs about fees](https://docs.ton.org/develop/howto/fees-low-level)
4040
fun calculateGasFeeWithoutFlatPrice(workchain: int8, gasUsed: coins): coins
4141
asm(gasUsed workchain) "GETGASFEESIMPLE"
4242

43-
/// Calculates amount of nanotoncoins you should pay for storing a contract of provided size for [seconds].
44-
/// [bits] and [cells] represent contract state (code + data).
43+
/// Calculates amount of nanotoncoins you should pay for storing a contract of provided size for `seconds`.
44+
/// `bits` and `cells` represent contract state (code + data).
4545
fun calculateStorageFee(workchain: int8, seconds: int, bits: int, cells: int): coins
4646
asm(cells bits seconds workchain) "GETSTORAGEFEE"
4747

4848
/// Calculates amount of nanotoncoins you should pay to send a message of a specified size.
4949
fun calculateForwardFee(workchain: int8, bits: int, cells: int): coins
5050
asm(cells bits workchain) "GETFORWARDFEE"
5151

52-
/// Same as [calculateForwardFee], but without lump price (you have supposed to read https://docs.ton.org/develop/howto/fees-low-level)
52+
/// Same as [calculateForwardFee], but without lump price. [Docs about fees](https://docs.ton.org/develop/howto/fees-low-level)
5353
fun calculateForwardFeeWithoutLumpPrice(workchain: int8, bits: int, cells: int): coins
5454
asm(cells bits workchain) "GETFORWARDFEESIMPLE"
5555

src/tolk-stdlib/lisp-lists.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// A part of standard library for Tolk
2-
tolk 1.0
2+
tolk 1.1
33

44
/**
55
Lisp-style lists are nested 2-elements tuples: `[1, [2, [3, null]]]` represents list `[1, 2, 3]`.

src/tolk-stdlib/tvm-dicts.tolk

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// A part of standard library for Tolk
2-
tolk 1.0
2+
tolk 1.1
33

44
/**
5-
Dictionaries are represented as `cell` data type (cells can store anything, dicts in particular).
6-
Currently, they have very low-level API very close to TVM internals.
5+
Low-level API working with TVM dictionaries.
6+
Not recommended to use, since it's very complicated and error-prone.
7+
Use `map<K, V>` instead, it's even more efficient then low-level dict API.
8+
9+
Dictionaries are represented as `cell` data type.
710
Most of functions are duplicated for three common cases:
811
- iDict* - dicts with signed integer keys
912
- uDict* - dicts with unsigned integer keys
@@ -14,10 +17,12 @@ tolk 1.0
1417
*/
1518

1619
/// In @stdlib/common.tolk, there is a type alias:
17-
/// `type dict = cell?`
20+
/// ```
21+
/// type dict = cell?
22+
/// ```
1823
/// For clarity, we use "dict" instead of a "cell?" where a cell-dictionary is assumed.
1924

20-
/// Creates an empty dictionary, which is actually a null value. Equivalent to PUSHNULL
25+
/// Creates an empty dictionary, which is actually a null value. Equivalent to `PUSHNULL`
2126
@pure
2227
fun createEmptyDict(): dict
2328
asm "NEWDICT"
@@ -86,28 +91,28 @@ fun dict.uDictSetIfExists(mutate self, keyLen: int, key: int, value: slice): boo
8691

8792

8893
@pure
89-
fun dict.iDictGetRef(self, keyLen: int, key: int): (dict, bool)
94+
fun dict.iDictGetRef(self, keyLen: int, key: int): (cell?, bool)
9095
asm(key self keyLen) "DICTIGETREF" "NULLSWAPIFNOT"
9196

9297
@pure
93-
fun dict.uDictGetRef(self, keyLen: int, key: int): (dict, bool)
98+
fun dict.uDictGetRef(self, keyLen: int, key: int): (cell?, bool)
9499
asm(key self keyLen) "DICTUGETREF" "NULLSWAPIFNOT"
95100

96101
@pure
97-
fun dict.sDictGetRef(self, keyLen: int, key: slice): (dict, bool)
102+
fun dict.sDictGetRef(self, keyLen: int, key: slice): (cell?, bool)
98103
asm(key self keyLen) "DICTGETREF" "NULLSWAPIFNOT"
99104

100105

101106
@pure
102-
fun dict.iDictGetRefOrNull(self, keyLen: int, key: int): dict
107+
fun dict.iDictGetRefOrNull(self, keyLen: int, key: int): cell?
103108
asm(key self keyLen) "DICTIGETOPTREF"
104109

105110
@pure
106-
fun dict.uDictGetRefOrNull(self, keyLen: int, key: int): dict
111+
fun dict.uDictGetRefOrNull(self, keyLen: int, key: int): cell?
107112
asm(key self keyLen) "DICTUGETOPTREF"
108113

109114
@pure
110-
fun dict.sDictGetRefOrNull(self, keyLen: int, key: slice): dict
115+
fun dict.sDictGetRefOrNull(self, keyLen: int, key: slice): cell?
111116
asm(key self keyLen) "DICTGETOPTREF"
112117

113118

@@ -138,11 +143,11 @@ fun dict.sDictSetAndGet(mutate self, keyLen: int, key: slice, value: slice): (sl
138143

139144

140145
@pure
141-
fun dict.iDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): dict
146+
fun dict.iDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): cell?
142147
asm(value key self keyLen) "DICTISETGETOPTREF"
143148

144149
@pure
145-
fun dict.uDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): dict
150+
fun dict.uDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): cell?
146151
asm(value key self keyLen) "DICTUSETGETOPTREF"
147152

148153

@@ -228,15 +233,15 @@ fun dict.sDictGetFirst(self, keyLen: int): (slice?, slice?, bool)
228233
asm (-> 1 0 2) "DICTMIN" "NULLSWAPIFNOT2"
229234

230235
@pure
231-
fun dict.iDictGetFirstAsRef(self, keyLen: int): (int?, dict, bool)
236+
fun dict.iDictGetFirstAsRef(self, keyLen: int): (int?, cell?, bool)
232237
asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2"
233238

234239
@pure
235-
fun dict.uDictGetFirstAsRef(self, keyLen: int): (int?, dict, bool)
240+
fun dict.uDictGetFirstAsRef(self, keyLen: int): (int?, cell?, bool)
236241
asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2"
237242

238243
@pure
239-
fun dict.sDictGetFirstAsRef(self, keyLen: int): (slice?, dict, bool)
244+
fun dict.sDictGetFirstAsRef(self, keyLen: int): (slice?, cell?, bool)
240245
asm (-> 1 0 2) "DICTMINREF" "NULLSWAPIFNOT2"
241246

242247

@@ -253,15 +258,15 @@ fun dict.sDictGetLast(self, keyLen: int): (slice?, slice?, bool)
253258
asm (-> 1 0 2) "DICTMAX" "NULLSWAPIFNOT2"
254259

255260
@pure
256-
fun dict.iDictGetLastAsRef(self, keyLen: int): (int?, dict, bool)
261+
fun dict.iDictGetLastAsRef(self, keyLen: int): (int?, cell?, bool)
257262
asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2"
258263

259264
@pure
260-
fun dict.uDictGetLastAsRef(self, keyLen: int): (int?, dict, bool)
265+
fun dict.uDictGetLastAsRef(self, keyLen: int): (int?, cell?, bool)
261266
asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2"
262267

263268
@pure
264-
fun dict.sDictGetLastAsRef(self, keyLen: int): (slice?, dict, bool)
269+
fun dict.sDictGetLastAsRef(self, keyLen: int): (slice?, cell?, bool)
265270
asm (-> 1 0 2) "DICTMAXREF" "NULLSWAPIFNOT2"
266271

267272

@@ -273,6 +278,10 @@ fun dict.iDictGetNext(self, keyLen: int, pivot: int): (int?, slice?, bool)
273278
fun dict.uDictGetNext(self, keyLen: int, pivot: int): (int?, slice?, bool)
274279
asm(pivot self keyLen -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2"
275280

281+
@pure
282+
fun dict.sDictGetNext(self, keyLen: int, pivot: slice): (slice?, slice?, bool)
283+
asm(pivot self keyLen -> 1 0 2) "DICTGETNEXT" "NULLSWAPIFNOT2"
284+
276285
@pure
277286
fun dict.iDictGetNextOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
278287
asm(pivot self keyLen -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2"
@@ -281,6 +290,10 @@ fun dict.iDictGetNextOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool
281290
fun dict.uDictGetNextOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
282291
asm(pivot self keyLen -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2"
283292

293+
@pure
294+
fun dict.sDictGetNextOrEqual(self, keyLen: int, pivot: slice): (slice?, slice?, bool)
295+
asm(pivot self keyLen -> 1 0 2) "DICTGETNEXTEQ" "NULLSWAPIFNOT2"
296+
284297

285298
@pure
286299
fun dict.iDictGetPrev(self, keyLen: int, pivot: int): (int?, slice?, bool)
@@ -290,6 +303,10 @@ fun dict.iDictGetPrev(self, keyLen: int, pivot: int): (int?, slice?, bool)
290303
fun dict.uDictGetPrev(self, keyLen: int, pivot: int): (int?, slice?, bool)
291304
asm(pivot self keyLen -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2"
292305

306+
@pure
307+
fun dict.sDictGetPrev(self, keyLen: int, pivot: slice): (slice?, slice?, bool)
308+
asm(pivot self keyLen -> 1 0 2) "DICTGETPREV" "NULLSWAPIFNOT2"
309+
293310
@pure
294311
fun dict.iDictGetPrevOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
295312
asm(pivot self keyLen -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2"
@@ -298,9 +315,13 @@ fun dict.iDictGetPrevOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool
298315
fun dict.uDictGetPrevOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
299316
asm(pivot self keyLen -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2"
300317

318+
@pure
319+
fun dict.sDictGetPrevOrEqual(self, keyLen: int, pivot: slice): (slice?, slice?, bool)
320+
asm(pivot self keyLen -> 1 0 2) "DICTGETPREVEQ" "NULLSWAPIFNOT2"
321+
301322

302323
/**
303-
Prefix dictionary primitives.
324+
Prefix dictionary primitives.
304325
*/
305326

306327
@pure

src/tolk-stdlib/tvm-lowlevel.tolk

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// A part of standard library for Tolk
2-
tolk 1.0
2+
tolk 1.1
33

44
/// Usually `c3` has a continuation initialized by the whole code of the contract. It is used for function calls.
55
/// The primitive returns the current value of `c3`.
@@ -14,12 +14,12 @@ fun getTvmRegisterC3(): continuation
1414
fun setTvmRegisterC3(c: continuation): void
1515
asm "c3 POP"
1616

17-
/// Transforms a `slice` [s] into a simple ordinary continuation `c`, with `c.code = s` and an empty stack and savelist.
17+
/// Transforms a slice into a simple ordinary continuation, with `c.code = s` and an empty stack and savelist.
1818
@pure
1919
fun transformSliceToContinuation(s: slice): continuation
2020
asm "BLESS"
2121

22-
/// Moves a variable or a value [x] to the top of the stack.
22+
/// Moves a variable to the top of the stack.
2323
@pure
2424
fun T.stackMoveToTop(mutate self): void
2525
asm "NOP"

src/tolkfiftlib.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tolkfiftlib.wasm

96.6 KB
Binary file not shown.

tests/codegen-checks.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {runTolkCompiler, getTolkCompilerVersion, TolkResultSuccess, TolkResultError} from "../src";
2+
import fs from "fs";
3+
4+
const EXPECT_TO_CONTAIN = [
5+
`
6+
check1() PROC:<{
7+
NEWC
8+
ENDC
9+
CTOS
10+
HASHSU
11+
}>
12+
`
13+
]
14+
15+
const EXPECT_NOT_TO_CONTAIN = [
16+
'HASHBU',
17+
]
18+
19+
describe('codegen-checks', () => {
20+
let outFiftCode = ''
21+
22+
beforeAll(async () => {
23+
let result = await runTolkCompiler({
24+
entrypointFileName: "codegen-checks.tolk",
25+
fsReadCallback: path => fs.readFileSync(`./tests/contracts/${path}`, 'utf-8')
26+
}) as TolkResultSuccess
27+
28+
expect(result.status).toEqual('ok')
29+
outFiftCode = result.fiftCode
30+
})
31+
32+
it('check contains', () => {
33+
for (let subFift of EXPECT_TO_CONTAIN) {
34+
expect(outFiftCode).toContain(subFift.trim())
35+
}
36+
for (let subFift of EXPECT_NOT_TO_CONTAIN) {
37+
expect(outFiftCode).not.toContain(subFift)
38+
}
39+
})
40+
})
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@method_id(101)
2+
fun check1() {
3+
return beginCell().endCell().beginParse().hash()
4+
}
5+
6+
fun main() {
7+
8+
}

0 commit comments

Comments
 (0)