Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ton/tolk-js",
"version": "1.0.0",
"version": "1.1.0",
"description": "Tolk Language compiler (next-generation FunC)",
"main": "dist/index.js",
"bin": "./dist/cli.js",
Expand Down
713 changes: 533 additions & 180 deletions src/tolk-stdlib/common.tolk

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions src/tolk-stdlib/gas-payments.tolk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// A part of standard library for Tolk
tolk 1.0
tolk 1.1

/**
Gas and payment related primitives.
Expand Down Expand Up @@ -32,24 +32,24 @@ fun setGasLimitToMaximum(): void
fun setGasLimit(limit: int): void
asm "SETGASLIMIT"

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

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

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

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

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

Expand Down
2 changes: 1 addition & 1 deletion src/tolk-stdlib/lisp-lists.tolk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// A part of standard library for Tolk
tolk 1.0
tolk 1.1

/**
Lisp-style lists are nested 2-elements tuples: `[1, [2, [3, null]]]` represents list `[1, 2, 3]`.
Expand Down
61 changes: 41 additions & 20 deletions src/tolk-stdlib/tvm-dicts.tolk
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// A part of standard library for Tolk
tolk 1.0
tolk 1.1

/**
Dictionaries are represented as `cell` data type (cells can store anything, dicts in particular).
Currently, they have very low-level API very close to TVM internals.
Low-level API working with TVM dictionaries.
Not recommended to use, since it's very complicated and error-prone.
Use `map<K, V>` instead, it's even more efficient then low-level dict API.

Dictionaries are represented as `cell` data type.
Most of functions are duplicated for three common cases:
- iDict* - dicts with signed integer keys
- uDict* - dicts with unsigned integer keys
Expand All @@ -14,10 +17,12 @@ tolk 1.0
*/

/// In @stdlib/common.tolk, there is a type alias:
/// `type dict = cell?`
/// ```
/// type dict = cell?
/// ```
/// For clarity, we use "dict" instead of a "cell?" where a cell-dictionary is assumed.

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


@pure
fun dict.iDictGetRef(self, keyLen: int, key: int): (dict, bool)
fun dict.iDictGetRef(self, keyLen: int, key: int): (cell?, bool)
asm(key self keyLen) "DICTIGETREF" "NULLSWAPIFNOT"

@pure
fun dict.uDictGetRef(self, keyLen: int, key: int): (dict, bool)
fun dict.uDictGetRef(self, keyLen: int, key: int): (cell?, bool)
asm(key self keyLen) "DICTUGETREF" "NULLSWAPIFNOT"

@pure
fun dict.sDictGetRef(self, keyLen: int, key: slice): (dict, bool)
fun dict.sDictGetRef(self, keyLen: int, key: slice): (cell?, bool)
asm(key self keyLen) "DICTGETREF" "NULLSWAPIFNOT"


@pure
fun dict.iDictGetRefOrNull(self, keyLen: int, key: int): dict
fun dict.iDictGetRefOrNull(self, keyLen: int, key: int): cell?
asm(key self keyLen) "DICTIGETOPTREF"

@pure
fun dict.uDictGetRefOrNull(self, keyLen: int, key: int): dict
fun dict.uDictGetRefOrNull(self, keyLen: int, key: int): cell?
asm(key self keyLen) "DICTUGETOPTREF"

@pure
fun dict.sDictGetRefOrNull(self, keyLen: int, key: slice): dict
fun dict.sDictGetRefOrNull(self, keyLen: int, key: slice): cell?
asm(key self keyLen) "DICTGETOPTREF"


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


@pure
fun dict.iDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): dict
fun dict.iDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): cell?
asm(value key self keyLen) "DICTISETGETOPTREF"

@pure
fun dict.uDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): dict
fun dict.uDictSetAndGetRefOrNull(mutate self, keyLen: int, key: int, value: cell): cell?
asm(value key self keyLen) "DICTUSETGETOPTREF"


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

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

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

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


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

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

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

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


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

@pure
fun dict.sDictGetNext(self, keyLen: int, pivot: slice): (slice?, slice?, bool)
asm(pivot self keyLen -> 1 0 2) "DICTGETNEXT" "NULLSWAPIFNOT2"

@pure
fun dict.iDictGetNextOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
asm(pivot self keyLen -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2"
Expand All @@ -281,6 +290,10 @@ fun dict.iDictGetNextOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool
fun dict.uDictGetNextOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
asm(pivot self keyLen -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2"

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


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

@pure
fun dict.sDictGetPrev(self, keyLen: int, pivot: slice): (slice?, slice?, bool)
asm(pivot self keyLen -> 1 0 2) "DICTGETPREV" "NULLSWAPIFNOT2"

@pure
fun dict.iDictGetPrevOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
asm(pivot self keyLen -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2"
Expand All @@ -298,9 +315,13 @@ fun dict.iDictGetPrevOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool
fun dict.uDictGetPrevOrEqual(self, keyLen: int, pivot: int): (int?, slice?, bool)
asm(pivot self keyLen -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2"

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


/**
Prefix dictionary primitives.
Prefix dictionary primitives.
*/

@pure
Expand Down
6 changes: 3 additions & 3 deletions src/tolk-stdlib/tvm-lowlevel.tolk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// A part of standard library for Tolk
tolk 1.0
tolk 1.1

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

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

/// Moves a variable or a value [x] to the top of the stack.
/// Moves a variable to the top of the stack.
@pure
fun T.stackMoveToTop(mutate self): void
asm "NOP"
2 changes: 1 addition & 1 deletion src/tolkfiftlib.js

Large diffs are not rendered by default.

Binary file modified src/tolkfiftlib.wasm
Binary file not shown.
40 changes: 40 additions & 0 deletions tests/codegen-checks.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {runTolkCompiler, getTolkCompilerVersion, TolkResultSuccess, TolkResultError} from "../src";
import fs from "fs";

const EXPECT_TO_CONTAIN = [
`
check1() PROC:<{
NEWC
ENDC
CTOS
HASHSU
}>
`
]

const EXPECT_NOT_TO_CONTAIN = [
'HASHBU',
]

describe('codegen-checks', () => {
let outFiftCode = ''

beforeAll(async () => {
let result = await runTolkCompiler({
entrypointFileName: "codegen-checks.tolk",
fsReadCallback: path => fs.readFileSync(`./tests/contracts/${path}`, 'utf-8')
}) as TolkResultSuccess

expect(result.status).toEqual('ok')
outFiftCode = result.fiftCode
})

it('check contains', () => {
for (let subFift of EXPECT_TO_CONTAIN) {
expect(outFiftCode).toContain(subFift.trim())
}
for (let subFift of EXPECT_NOT_TO_CONTAIN) {
expect(outFiftCode).not.toContain(subFift)
}
})
})
8 changes: 8 additions & 0 deletions tests/contracts/codegen-checks.tolk
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@method_id(101)
fun check1() {
return beginCell().endCell().beginParse().hash()
}

fun main() {

}
4 changes: 3 additions & 1 deletion tests/contracts/use-dicts.tolk
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ fun prepareDict_3_30_4_40_5_x(valueAt5: int): dict {
return dict;
}

fun main(){}
fun main(){
prepareDict_3_30_4_40_5_x;
}
10 changes: 0 additions & 10 deletions tests/tolk-js.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,6 @@ describe('tolk-js', () => {
expect((res as any).message).toBe(undefined)
})

it('should pass experimentalOptions', async () => {
let res = await runTolkCompiler({
entrypointFileName: 'with-unused.tolk',
fsReadCallback: path => fs.readFileSync(`./tests/contracts/${path}`, 'utf-8'),
experimentalOptions: 'remove-unused-functions'
}) as TolkResultSuccess

expect(res.fiftCode).not.toContain('unusedF')
})

it('should return sourcesSnapshot', async () => {
let result = await runTolkCompiler({
entrypointFileName: "wallet-code.tolk",
Expand Down