1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-12 19:22:37 +00:00
ton/crypto/fift/lib/FiftExt.fif
EmelyanenkoK 865ebfce8d
Add namespaces to Fift (#641)
* Add fift-based disassembler

* Fift improvements: namespaces, hashmaps, flow controls

* Fift: add lib with better block structuring and more

* Minor changes in fift HashMap + tests (#643)

* Minor changes in fift HashMap

* Add tests for extended fift

---------

Co-authored-by: OmicronTau <omicron@ton.org>
Co-authored-by: Tolya <1449561+tolya-yanot@users.noreply.github.com>
Co-authored-by: SpyCheese <mikle98@yandex.ru>
2023-03-10 14:16:29 +03:00

118 lines
3.6 KiB
Text

{ ?dup { 1+ { execute } { 0 swap } cond }
{ (number) ?dup 0= abort"-?" 'nop } cond
} : (interpret-prepare)
{ { include-depth 0= (seekeof?) not } {
(word-prefix-find) (interpret-prepare) (execute)
} while
} : interpret
{ ({)
{ 0 (seekeof?) abort"no }" (word-prefix-find) (interpret-prepare) (compile) over atom? not } until
(}) swap execute
} : begin-block
{ swap 0 'nop } : end-block
{ { 1 'nop } `{ begin-block }
{ { swap `{ eq? not abort"} without {" swap execute } end-block }
:: } :: {
// if{ ... }then{ ... }elseif{ ... }then{ ... }else{ ... }
{ eq? not abort"unexpected" } : ?pairs
{ dup `if eq? swap `ifnot eq? over or not abort"without if{" } : if-ifnot?
// cond then ? -- exec
{ { ' if } { ' ifnot } cond rot ({) 0 rot (compile) -rot 1 swap (compile) (})
} : (make-if)
// cond then else -- exec
{ rot ({) 0 rot (compile) -rot 2 ' cond (compile) (})
} : (make-cond)
{ `noelse `if begin-block } :: if{
{ `noelse `ifnot begin-block } :: ifnot{
{ 1 ' end-block does } : end-block-does
{ { over `else eq? } {
nip rot if-ifnot? ' swap ifnot (make-cond)
} while
swap `noelse ?pairs 0 swap
} : finish-else-chain
{ swap dup if-ifnot? drop `then {
swap `then ?pairs
swap if-ifnot? (make-if) finish-else-chain
} `{ begin-block
} end-block-does :: }then{
{ swap `{ ?pairs nip
swap `then eq? not abort"without }then{" `else
} : ?else-ok
{ ?else-ok { finish-else-chain } `{ begin-block } end-block-does :: }else{
{ ?else-ok `if begin-block } end-block-does :: }elseif{
{ ?else-ok `ifnot begin-block } end-block-does :: }elseifnot{
// while{ ... }do{ ... }
{ 2 ' while does } : (make-while)
{ `while begin-block } :: while{
{ swap `while eq? not abort"without while{" `while-do {
swap `while-do ?pairs (make-while) 0 swap
} `{ begin-block
} end-block-does :: }do{
// repeat{ ... }until{ ... }
{ swap ({) 0 rot (compile) 0 rot (compile) (}) 1 ' until does } : (make-until)
{ `repeat begin-block } :: repeat{
{ swap `repeat eq? not abort"without repeat{" `until {
swap `until ?pairs (make-until) 0 swap
} `{ begin-block
} end-block-does :: }until{
// def <name> { ... } instead of { ... } : <name>
{ bl word swap bl word "{" $cmp abort"{ expected" `def {
swap `def ?pairs -rot 3 ' (create)
} `{ begin-block
} : (def)
{ 0 (def) } :: def
{ 1 (def) } :: def::
// defrec <name> { ... } instead of recursive <name> { ... } swap !
{ recursive bl word "{" $cmp abort"{ expected" `defrec {
swap `defrec ?pairs swap ! 0 'nop
} `{ begin-block
} :: defrec
def .sgn {
if{ ?dup 0= }then{
."zero"
}elseif{ 0> }then{
."positive"
}else{
."negative"
}
cr
}
// equivalent to: { ?dup 0= { ."zero" } { 0> { ."positive" } { ."negative" } cond } cond cr } : .sgn
defrec fact {
if{ dup }then{
dup 1- fact *
}else{
drop 1
}
}
// equivalent to: recursive fact { dup { dup 1- fact * } { drop 1 } cond } swap !
// [[ ... ]] computes arbitrary constants inside definitions
// { [[ 5 dup * ]] + } : add25
// is equivalent to
// { 25 + } : add25
{ "without [[" abort } box constant ']]
{ ']] @ execute } : ]]
{ { ']] @ 2 { ']] ! call/cc } does ']] !
interpret 'nop ']] ! "]] not found" abort
} call/cc
drop 1 'nop
} :: [[
{ { over @ swap 2 { call/cc } does swap !
interpret "literal to eof" abort
} call/cc
drop execute 1 'nop
} : interpret-literal-to
// use next line only if Lists.fif is loaded (or move it to Lists.fif if FiftExt.fif becomes part of Fift.fif)
// { ( ') interpret-literal-to } :: '(
// then you can use list literals '( a b c ... ) inside definitions:
// { '( 1 2 3 ) } : test
// { '( ( `a { ."A" } ) ( `b { ."B" } ) ) assoc { cadr execute } { ."???" } cond } : test2