|
|
|
@ -1331,17 +1331,17 @@ rot . swap x. . cr
|
|
|
|
|
outputs ``{\tt -1 538fa7\dots 0f7d 0}'', meaning that the specified address is in workchain $-1$ (the masterchain of the TON Blockchain), and that the 256-bit address inside workchain $-1$ is 0x538\dots f7d.
|
|
|
|
|
|
|
|
|
|
\mysubsection{Dictionary manipulation}\label{p:hashmap.ops}
|
|
|
|
|
Fift has several words for {\em hashmap\/} or {\em (TVM) dictionary\/} manipulation, corresponding to values of TL-B type {\tt HashmapE $n$ $X$} as described in~\cite[3.3]{TVM}. These (TVM) dictionaries are not to be confused with the Fift dictionary, which is a completely different thing. A dictionary of TL-B type {\tt HashmapE $n$ $X$} is essentially a key-value collection with distinct $n$-bit keys (where $0\leq n\leq 1023$) and values of an arbitrary TL-B type $X$. Dictionaries are represented by trees of cells (the complete layout may be found in \cite[3.3]{TVM}) and stored as values of type {\em Cell\/} or {\em Slice\/} in the Fift stack.
|
|
|
|
|
Fift has several words for {\em hashmap\/} or {\em (TVM) dictionary\/} manipulation, corresponding to values of TL-B type {\tt HashmapE $n$ $X$} as described in~\cite[3.3]{TVM}. These (TVM) dictionaries are not to be confused with the Fift dictionary, which is a completely different thing. A dictionary of TL-B type {\tt HashmapE $n$ $X$} is essentially a key-value collection with distinct $n$-bit keys (where $0\leq n\leq 1023$) and values of an arbitrary TL-B type $X$. Dictionaries are represented by trees of cells (the complete layout may be found in \cite[3.3]{TVM}) and stored as values of type {\em Cell\/} or {\em Slice\/} in the Fift stack. Sometimes empty dictionaries are represented by the {\em Null\/} value.
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item {\tt dictnew} ( -- $s$), pushes a {\em Slice\/} that represents a new empty dictionary.
|
|
|
|
|
\item {\tt idict!} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new value $v$ (represented by a {\em Slice}) with key given by signed big-endian $n$-bit integer $x$ into dictionary $s$ with $n$-bit keys, and returns the new dictionary $s'$ and $-1$ on success. Otherwise the unchanged dictionary $s$ and $0$ are returned.
|
|
|
|
|
\item {\tt idict!+} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new key-value pair $(x,v)$ into dictionary $s$ similarly to {\tt idict!}, but fails if the key already exists by returning the unchanged dictionary $s$ and $0$.
|
|
|
|
|
\item {\tt dictnew} ( -- $D$), pushes a {\em Null\/} value that represents a new empty dictionary.
|
|
|
|
|
\item {\tt idict!} ($v$ $x$ $D$ $n$ -- $D'$ $-1$ or $D$ $0$), adds a new value $v$ (represented by a {\em Slice}) with key given by signed big-endian $n$-bit integer $x$ into dictionary $D$ (represented by a {\em Cell\/} or a {\em Null\/}) with $n$-bit keys, and returns the new dictionary $D'$ and $-1$ on success. Otherwise the unchanged dictionary $D$ and $0$ are returned.
|
|
|
|
|
\item {\tt idict!+} ($v$ $x$ $D$ $n$ -- $D'$ $-1$ or $D$ $0$), adds a new key-value pair $(x,v)$ into dictionary $D$ similarly to {\tt idict!}, but fails if the key already exists by returning the unchanged dictionary $D$ and $0$.
|
|
|
|
|
\item {\tt b>idict!}, {\tt b>idict!+}, variants of {\tt idict!} and {\tt idict!+} accepting the new value $v$ in a {\em Builder\/} instead of a {\em Slice}.
|
|
|
|
|
\item {\tt udict!}, {\tt udict!+}, {\tt b>udict!}, {\tt b>udict!+}, variants of {\tt idict!}, {\tt idict!+}, {\tt b>idict!}, {\tt b>idict!+}, but with an unsigned $n$-bit integer $x$ used as a key.
|
|
|
|
|
\item {\tt idict@} ($x$ $s$ $n$ -- $v$ $-1$ or $0$), looks up the key represented by signed big-endian $n$-bit {\em Integer\/}~$x$ in the dictionary represented by {\em Slice\/}~$s$. If the key is found, returns the corresponding value as a {\em Slice\/}~$v$ and $-1$. Otherwise returns $0$.
|
|
|
|
|
\item {\tt udict@} ($x$ $s$ $n$ -- $v$ $-1$ or $0$), similar to {\tt idict@}, but with an {\em un}signed big-endian $n$-bit {\em Integer\/}~$x$ used as a key.
|
|
|
|
|
\item {\tt dictmap} ($s$ $n$ $e$ -- $s'$), applies execution token $e$ (i.e., an anonymous function) to each of the key-value pairs stored in a dictionary $s$ with $n$-bit keys. The execution token is executed once for each key-value pair, with a {\em Builder\/} $b$ and a {\em Slice\/} $v$ (containing the value) pushed into the stack before executing $e$. After the execution $e$ must leave in the stack either a modified {\em Builder\/} $b'$ (containing all data from~$b$ along with the new value $v'$) and $-1$, or $0$ indicating failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt dictmerge} ($s$ $s'$ $n$ $e$ -- $s''$), combines two dictionaries $s$ and $s'$ with $n$-bit keys into one dictionary $s''$ with the same keys. If a key is present in only one of the dictionaries $s$ and $s'$, this key and the corresponding value are copied verbatim to the new dictionary $s''$. Otherwise the execution token (anonymous function) $e$ is invoked to merge the two values $v$ and $v'$ corresponding to the same key $k$ in $s$ and $s'$, respectively. Before $e$ is invoked, a {\em Builder\/}~$b$ and two {\em Slice}s $v$ and $v'$ representing the two values to be merged are pushed. After the execution $e$ leaves either a modified {\em Builder\/}~$b'$ (containing the original data from $b$ along with the combined value) and $-1$, or $0$ on failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt idict@} ($x$ $D$ $n$ -- $v$ $-1$ or $0$), looks up the key represented by signed big-endian $n$-bit {\em Integer\/}~$x$ in the dictionary represented by {\em Cell\/}~$D$. If the key is found, returns the corresponding value as a {\em Slice\/}~$v$ and $-1$. Otherwise returns $0$.
|
|
|
|
|
\item {\tt udict@} ($x$ $D$ $n$ -- $v$ $-1$ or $0$), similar to {\tt idict@}, but with an {\em un}signed big-endian $n$-bit {\em Integer\/}~$x$ used as a key.
|
|
|
|
|
\item {\tt dictmap} ($D$ $n$ $e$ -- $s'$), applies execution token $e$ (i.e., an anonymous function) to each of the key-value pairs stored in a dictionary $D$ with $n$-bit keys. The execution token is executed once for each key-value pair, with a {\em Builder\/} $b$ and a {\em Slice\/} $v$ (containing the value) pushed into the stack before executing $e$. After the execution $e$ must leave in the stack either a modified {\em Builder\/} $b'$ (containing all data from~$b$ along with the new value $v'$) and $-1$, or $0$ indicating failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt dictmerge} ($D$ $D'$ $n$ $e$ -- $D''$), combines two dictionaries $D$ and $D'$ with $n$-bit keys into one dictionary $D''$ with the same keys. If a key is present in only one of the dictionaries $D$ and $D'$, this key and the corresponding value are copied verbatim to the new dictionary $D''$. Otherwise the execution token (anonymous function) $e$ is invoked to merge the two values $v$ and $v'$ corresponding to the same key $k$ in $D$ and $D'$, respectively. Before $e$ is invoked, a {\em Builder\/}~$b$ and two {\em Slice}s $v$ and $v'$ representing the two values to be merged are pushed. After the execution $e$ leaves either a modified {\em Builder\/}~$b'$ (containing the original data from $b$ along with the combined value) and $-1$, or $0$ on failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\end{itemize}
|
|
|
|
|
Fift also offers some support for prefix dictionaries:
|
|
|
|
|
\begin{itemize}
|
|
|
|
@ -1355,10 +1355,12 @@ TVM can be linked with the Fift interpreter. In this case, several Fift primitiv
|
|
|
|
|
\begin{itemize}
|
|
|
|
|
\item {\tt runvmcode} (\dots $s$ -- \dots $x$), invokes a new instance of TVM with the current continuation {\tt cc} initialized from {\em Slice\/} $s$, thus executing code~$s$ in TVM. The original Fift stack (without $s$) is passed in its entirety as the initial stack of TVM. When TVM terminates, its resulting stack is used as the new Fift stack, with the exit code $x$ pushed at its top. If $x$ is non-zero, indicating that TVM has been terminated by an unhandled exception, the next stack entry from the top contains the parameter of this exception, and $x$ is the exception code. All other entries are removed from the stack in this case.
|
|
|
|
|
\item {\tt runvmdict} (\dots $s$ -- \dots $x$), invokes a new instance of TVM with the current continuation {\tt cc} initialized from {\em Slice\/} $s$ similarly to {\tt runvmcode}, but also initializes the special register {\tt c3} with the same value, and pushes a zero into the initial TVM stack before the TVM execution begins. In a typical application {\em Slice\/}~$s$ consists of a subroutine selection code that uses the top-of-stack {\em Integer\/} to select the subroutine to be executed, thus enabling the definition and execution of several mutually-recursive subroutines (cf.~\cite[4.6]{TVM} and~\ptref{p:asm.prog}). The selector equal to zero corresponds to the {\tt main()} subroutine in a large TVM program.
|
|
|
|
|
\item {\tt runvm} (\dots $s$ $c$ -- \dots $x$ $c'$), invokes a new instance of TVM with both the current continuation {\tt cc} and the special register {\tt c3} initialized from {\em Slice\/}~$s$, and pushes a zero into the initial TVM stack similarly to {\tt runvmdict}, but also initializes special register {\tt c4} (the ``root of persistent data'', cf.~\cite[1.4]{TVM}) with {\em Cell\/}~$c$. The final value of {\tt c4} is returned at the top of the final Fift stack as another {\em Cell\/}~$c'$. In this way one can emulate the execution of smart contracts that inspect or modify their persistent storage.
|
|
|
|
|
\item {\tt runvm} (\dots $s$ $c$ -- \dots $x$ $c'$), invokes a new instance of TVM with both the current continuation {\tt cc} and the special register {\tt c3} initialized from {\em Slice\/}~$s$, similarly to {\tt runvmdict} (without pushing an extra zero to the initial TVM stack; if necessary, it can be pushed explicitly under $s$), and also initializes special register {\tt c4} (the ``root of persistent data'', cf.~\cite[1.4]{TVM}) with {\em Cell\/}~$c$. The final value of {\tt c4} is returned at the top of the final Fift stack as another {\em Cell\/}~$c'$. In this way one can emulate the execution of smart contracts that inspect or modify their persistent storage.
|
|
|
|
|
\item {\tt runvmctx} (\dots $s$ $c$ $t$ -- \dots $x$ $c'$), a variant of {\tt runvm} that also initializes {\tt c7} (the ``context'') with {\em Tuple\/}~$t$. In this way the execution of a TVM smart contract inside TON Blockchain can be completely emulated, if the correct context is loaded into {\tt c7} (cf.~\cite[4.4.10]{TBC}).
|
|
|
|
|
\item {\tt gasrunvmcode} (\dots $s$ $z$ -- \dots $x$ $z'$), a gas-aware version of {\tt runvmcode} that accepts an extra {\em Integer\/} argument $z$ (the original gas limit) at the top of the stack, and returns the gas consumed by this TVM run as a new top-of-stack {\em Integer\/} value~$z'$.
|
|
|
|
|
\item {\tt gasrunvmdict} (\dots $s$ $z$ -- \dots $x$ $z'$), a gas-aware version of {\tt runvmdict}.
|
|
|
|
|
\item {\tt gasrunvm} (\dots $s$ $c$ $z$ -- \dots $x$ $c'$ $z'$), a gas-aware version of {\tt runvm}.
|
|
|
|
|
\item {\tt gasrunvmctx} (\dots $s$ $c$ $t$ $z$ -- \dots $x$ $c'$ $z'$), a gas-aware version of {\tt runvmctx}.
|
|
|
|
|
\end{itemize}
|
|
|
|
|
For example, one can create an instance of TVM running some simple code as follows:
|
|
|
|
|
\begin{verbatim}
|
|
|
|
@ -2039,9 +2041,9 @@ Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON
|
|
|
|
|
\item {\tt csr.} ($s$ -- ), recursively prints a {\em Slice}~$s$, cf.~\ptref{p:slice.ops}. On the first line, the data bits of $s$ are displayed in hexadecimal form embedded into an {\tt x\{\dots\}} construct similar to the one used for {\em Slice\/} literals (cf.~\ptref{p:slice.lit}). On the next lines, the cells referred to by $s$ are printed with larger indentation.
|
|
|
|
|
\item {\tt \underline{def?} $\langle\textit{word-name\/}\rangle$} ( -- $?$), checks whether the word $\langle\textit{word-name\/}\rangle$ is defined at execution time, and returns $-1$ or $0$ accordingly.
|
|
|
|
|
\item {\tt depth} ( -- $n$), returns the current depth (the total number of entries) of the Fift stack as an {\em Integer\/} $n\geq0$.
|
|
|
|
|
\item {\tt dictmap} ($s$ $n$ $e$ -- $s'$), applies execution token $e$ (i.e., an anonymous function) to each of the key-value pairs stored in a dictionary $s$ with $n$-bit keys, cf.~\ptref{p:hashmap.ops}. The execution token is executed once for each key-value pair, with a {\em Builder\/} $b$ and a {\em Slice\/} $v$ (containing the value) pushed into the stack before executing $e$. After the execution $e$ must leave in the stack either a modified {\em Builder\/} $b'$ (containing all data from~$b$ along with the new value $v'$) and $-1$, or $0$ indicating failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt dictmerge} ($s$ $s'$ $n$ $e$ -- $s''$), combines two dictionaries $s$ and $s'$ with $n$-bit keys into one dictionary $s''$ with the same keys, cf.~\ptref{p:hashmap.ops}. If a key is present in only one of the dictionaries $s$ and $s'$, this key and the corresponding value are copied verbatim to the new dictionary $s''$. Otherwise the execution token (anonymous function) $e$ is invoked to merge the two values $v$ and $v'$ corresponding to the same key $k$ in $s$ and $s'$, respectively. Before $e$ is invoked, a {\em Builder\/}~$b$ and two {\em Slice\/}s $v$ and $v'$ representing the two values to be merged are pushed. After the execution $e$ leaves either a modified {\em Builder\/}~$b'$ (containing the original data from $b$ along with the combined value) and $-1$, or $0$ on failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt dictnew} ( -- $s$), pushes a {\em Slice\/} that represents a new empty dictionary, cf.~\ptref{p:hashmap.ops}. Equivalent to {\tt b\{0\}}.
|
|
|
|
|
\item {\tt dictmap} ($D$ $n$ $e$ -- $D'$), applies execution token $e$ (i.e., an anonymous function) to each of the key-value pairs stored in a dictionary $D$ with $n$-bit keys, cf.~\ptref{p:hashmap.ops}. The execution token is executed once for each key-value pair, with a {\em Builder\/} $b$ and a {\em Slice\/} $v$ (containing the value) pushed into the stack before executing $e$. After the execution $e$ must leave in the stack either a modified {\em Builder\/} $b'$ (containing all data from~$b$ along with the new value $v'$) and $-1$, or $0$ indicating failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt dictmerge} ($D$ $D'$ $n$ $e$ -- $D''$), combines two dictionaries $D$ and $D'$ with $n$-bit keys into one dictionary $D''$ with the same keys, cf.~\ptref{p:hashmap.ops}. If a key is present in only one of the dictionaries $D$ and $D'$, this key and the corresponding value are copied verbatim to the new dictionary $D''$. Otherwise the execution token (anonymous function) $e$ is invoked to merge the two values $v$ and $v'$ corresponding to the same key $k$ in $D$ and $D'$, respectively. Before $e$ is invoked, a {\em Builder\/}~$b$ and two {\em Slice\/}s $v$ and $v'$ representing the two values to be merged are pushed. After the execution $e$ leaves either a modified {\em Builder\/}~$b'$ (containing the original data from $b$ along with the combined value) and $-1$, or $0$ on failure. In the latter case, the corresponding key is omitted from the new dictionary.
|
|
|
|
|
\item {\tt dictnew} ( -- $D$), pushes the {\em Null\/} value that represents a new empty dictionary, cf.~\ptref{p:hashmap.ops}. Equivalent to {\tt null}.
|
|
|
|
|
\item {\tt does} ($x_1$ \dots $x_n$ $n$ $e$ -- $e'$), creates a new execution token $e'$ that would push $n$ values $x_1$, \dots, $x_n$ into the stack and then execute $e$ when invoked, cf.~\ptref{p:wordlist.ops}. It is roughly equivalent to a combination of {\tt (\{)}, {\tt (compile)}, and {\tt (\})}.
|
|
|
|
|
\item {\tt drop} ($x$ -- ), removes the top-of-stack entry, cf.~\ptref{p:stack.ops}.
|
|
|
|
|
\item {\tt dup} ($x$ -- $x$ $x$), duplicates the top-of-stack entry, cf.~\ptref{p:stack.ops}. If the stack is empty, throws an exception.
|
|
|
|
@ -2062,8 +2064,9 @@ Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON
|
|
|
|
|
\item {\tt first} ($t$ -- $x$), returns the first component of a {\em Tuple}, cf.~\ptref{p:tuples}. Equivalent to {\tt 0 []}.
|
|
|
|
|
\item {\tt fits} ($x$ $y$ -- $?$), checks whether {\em Integer\/}~$x$ is a signed $y$-bit integer (i.e., whether $-2^{y-1}\leq x<2^{y-1}$ for $0\leq y\leq 1023$), and returns $-1$ or $0$ accordingly.
|
|
|
|
|
\item {\tt forget} ( -- ), forgets (removes from the dictionary) the definition of the next word scanned from the input, cf.~\ptref{p:dict.create}.
|
|
|
|
|
\item {\tt gasrunvm} (\dots $s$ $c$ $z$ -- \dots $x$ $c'$ $z'$), a gas-aware version of {\tt runvm}, cf.~\ptref{p:tvm.ops}: invokes a new instance of TVM with both the current continuation {\tt cc} and the special register {\tt c3} initialized from {\em Slice\/}~$s$, and pushes a zero into the initial TVM stack similarly to {\tt runvmdict}, but also initializes special register {\tt c4} (the ``root of persistent data'', cf.~\cite[1.4]{TVM}) with {\em Cell\/}~$c$. Then starts the new TVM instance with the gas limit set to $z$. The actually consumed gas $z'$ is returned at the top of the final Fift stack, and the final value of {\tt c4} is returned immediately below the top of the final Fift stack as another {\em Cell\/}~$c'$.
|
|
|
|
|
\item {\tt gasrunvm} (\dots $s$ $c$ $z$ -- \dots $x$ $c'$ $z'$), a gas-aware version of {\tt runvm}, cf.~\ptref{p:tvm.ops}: invokes a new instance of TVM with both the current continuation {\tt cc} and the special register {\tt c3} initialized from {\em Slice\/}~$s$, and initializes special register {\tt c4} (the ``root of persistent data'', cf.~\cite[1.4]{TVM}) with {\em Cell\/}~$c$. Then starts the new TVM instance with the gas limit set to $z$. The actually consumed gas $z'$ is returned at the top of the final Fift stack, and the final value of {\tt c4} is returned immediately below the top of the final Fift stack as another {\em Cell\/}~$c'$.
|
|
|
|
|
\item {\tt gasrunvmcode} (\dots $s$ $z$ -- \dots $x$ $z'$), a gas-aware version of {\tt runvmcode}, cf.~\ptref{p:tvm.ops}: invokes a new instance of TVM with the current continuation {\tt cc} initialized from {\em Slice\/} $s$ and with the gas limit set to $z$, thus executing code~$s$ in TVM. The original Fift stack (without $s$) is passed in its entirety as the initial stack of the new TVM instance. When TVM terminates, its resulting stack is used as the new Fift stack, with the exit code $x$ and the actually consumed gas $z'$ pushed at its top. If $x$ is non-zero, indicating that TVM has been terminated by an unhandled exception, the next stack entry from the top contains the parameter of this exception, and $x$ is the exception code. All other entries are removed from the stack in this case.
|
|
|
|
|
\item {\tt gasrunvmctx} (\dots $s$ $c$ $t$ $z$ -- \dots $x$ $c'$ $z'$), a gas-aware version of {\tt runvmctx}, cf.~\ptref{p:tvm.ops}. Differs from {\tt gasrunmv} in that it initializes {\tt c7} with {\em Tuple\/}~$t$.
|
|
|
|
|
\item {\tt gasrunvmdict} (\dots $s$ $z$ -- \dots $x$ $z'$), a gas-aware version of {\tt runvmdict}, cf.~\ptref{p:tvm.ops}: invokes a new instance of TVM with the current continuation {\tt cc} initialized from {\em Slice\/} $s$ and sets the gas limit to $z$ similarly to {\tt gasrunvmcode}, but also initializes the special register {\tt c3} with the same value, and pushes a zero into the initial TVM stack before the TVM execution begins. The actually consumed gas is returned as an {\em Integer\/} $z'$. In a typical application {\em Slice\/}~$s$ consists of a subroutine selection code that uses the top-of-stack {\em Integer\/} to select the subroutine to be executed, thus enabling the definition and execution of several mutually-recursive subroutines (cf.~\cite[4.6]{TVM} and~\ptref{p:asm.prog}). The selector equal to zero corresponds to the {\tt main()} subroutine in a large TVM program.
|
|
|
|
|
\item {\tt halt} ($x$ -- ), quits to the operating system similarly to {\tt bye}, but uses {\em Integer\/} $x$ as the exit code, cf.~\ptref{p:exit.fift}.
|
|
|
|
|
\item {\tt hash} ($c$ -- $x$), a deprecated version of {\tt hashu}. Use {\tt hashu} or {\tt hashB} instead.
|
|
|
|
@ -2077,9 +2080,9 @@ Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON
|
|
|
|
|
\item {\tt i@+} ($s$ $x$ -- $y$ $s'$), fetches a signed big-endian $x$-bit integer from the first $x$ bits of {\em Slice}~$s$ similarly to {\tt i@}, but returns the remainder of $s$ as well, cf.~\ptref{p:slice.ops}.
|
|
|
|
|
\item {\tt i@?} ($s$ $x$ -- $y$ $-1$ or $0$), fetches a signed big-endian integer from a {\em Slice\/} similarly to {\tt i@}, but pushes integer $-1$ afterwards on success, cf.~\ptref{p:slice.ops}. If there are less than $x$ bits left in $s$, pushes integer $0$ to indicate failure.
|
|
|
|
|
\item {\tt i@?+} ($s$ $x$ -- $y$ $s'$ $-1$ or $s$ $0$), fetches a signed big-endian integer from {\em Slice\/}~$s$ and computes the remainder of this {\em Slice\/} similarly to {\tt i@+}, but pushes $-1$ afterwards to indicate success, cf.~\ptref{p:slice.ops}. On failure, pushes the unchanged {\em Slice\/}~$s$ and $0$ to indicate failure.
|
|
|
|
|
\item {\tt idict!} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new value $v$ (represented by a {\em Slice\/}) with key given by signed big-endian $n$-bit integer $x$ into dictionary $s$ with $n$-bit keys, and returns the new dictionary $s'$ and $-1$ on success, cf.~\ptref{p:hashmap.ops}. Otherwise the unchanged dictionary $s$ and $0$ are returned.
|
|
|
|
|
\item {\tt idict!+} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new key-value pair $(x,v)$ into dictionary $s$ similarly to {\tt idict!}, but fails if the key already exists by returning the unchanged dictionary $s$ and $0$, cf.~\ptref{p:hashmap.ops}.
|
|
|
|
|
\item {\tt idict@} ($x$ $s$ $n$ -- $v$ $-1$ or $0$), looks up key represented by signed big-endian $n$-bit {\em Integer\/}~$x$ in the dictionary represented by {\em Slice\/}~$s$, cf.~\ptref{p:hashmap.ops}. If the key is found, returns the corresponding value as a {\em Slice\/}~$v$ and $-1$. Otherwise returns $0$.
|
|
|
|
|
\item {\tt idict!} ($v$ $x$ $D$ $n$ -- $D'$ $-1$ or $D$ $0$), adds a new value $v$ (represented by a {\em Slice\/}) with key given by signed big-endian $n$-bit integer $x$ into dictionary $D$ with $n$-bit keys, and returns the new dictionary $D'$ and $-1$ on success, cf.~\ptref{p:hashmap.ops}. Otherwise the unchanged dictionary $D$ and $0$ are returned.
|
|
|
|
|
\item {\tt idict!+} ($v$ $x$ $D$ $n$ -- $D'$ $-1$ or $D$ $0$), adds a new key-value pair $(x,v)$ into dictionary $D$ similarly to {\tt idict!}, but fails if the key already exists by returning the unchanged dictionary $D$ and $0$, cf.~\ptref{p:hashmap.ops}.
|
|
|
|
|
\item {\tt idict@} ($x$ $D$ $n$ -- $v$ $-1$ or $0$), looks up key represented by signed big-endian $n$-bit {\em Integer\/}~$x$ in the dictionary represented by {\em Cell\/} or {\em Null\/}~$D$, cf.~\ptref{p:hashmap.ops}. If the key is found, returns the corresponding value as a {\em Slice\/}~$v$ and $-1$. Otherwise returns $0$.
|
|
|
|
|
\item {\tt if} ($x$ $e$ -- ), executes execution token (i.e., a {\em WordDef\/}) $e$, but only if {\em Integer\/} $x$ is non-zero, cf.~\ptref{p:cond.ops}.
|
|
|
|
|
\item {\tt ifnot} ($x$ $e$ -- ), executes execution token $e$, but only if {\em Integer\/} $x$ is zero, cf.~\ptref{p:cond.ops}.
|
|
|
|
|
\item {\tt include} ($S$ -- ), loads and interprets a Fift source file from the path given by {\em String\/}~$S$, cf.~\ptref{p:asm.load}. If the filename $S$ does not begin with a slash, the Fift include search path, typically taken from the {\tt FIFTPATH} environment variable or the {\tt -I} command-line argument of the Fift interpreter (and equal to {\tt /usr/lib/fift} if both are absent), is used to locate~$S$.
|
|
|
|
@ -2116,9 +2119,10 @@ Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON
|
|
|
|
|
\item {\tt reverse} ($x_1$ \dots $x_n$ $y_1$ \dots $y_m$ $n$ $m$ -- $x_n$ \dots $x_1$ $y_1$ \dots $y_m$), reverses the order of $n$ stack entries located immediately below the topmost $m$ elements, where both $0\leq m,n\leq 255$ are passed in the stack.
|
|
|
|
|
\item {\tt roll} ($x_n$ \dots $x_0$ $n$ -- $x_{n-1}$ \dots $x_0$ $x_n$), rotates the top $n$ stack entries, where $n\geq0$ is also passed in the stack, cf.~\ptref{p:stack.ops}. In particular, {\tt 1 roll} is equivalent to {\tt swap}, and {\tt 2 roll} to {\tt rot}.
|
|
|
|
|
\item {\tt rot} ($x$ $y$ $z$ -- $y$ $z$ $x$), rotates the three topmost stack entries.
|
|
|
|
|
\item {\tt runvm} (\dots $s$ $c$ -- \dots $x$ $c'$), invokes a new instance of TVM with both the current continuation {\tt cc} and the special register {\tt c3} initialized from {\em Slice\/}~$s$, and initializes special register {\tt c4} (the ``root of persistent data'', cf.~\cite[1.4]{TVM}) with {\em Cell\/}~$c$, cf.~\ptref{p:tvm.ops}. In contrast with {\tt runvmdict}, does not push an implicit zero into the initial TVM stack; if necessary, it can be explicitly passed under~$s$. The final value of {\tt c4} is returned at the top of the final Fift stack as another {\em Cell\/}~$c'$. In this way one can emulate the execution of smart contracts that inspect or modify their persistent storage.
|
|
|
|
|
\item {\tt runvmcode} (\dots $s$ -- \dots $x$), invokes a new instance of TVM with the current continuation {\tt cc} initialized from {\em Slice\/} $s$, thus executing code~$s$ in TVM, cf.~\ptref{p:tvm.ops}. The original Fift stack (without $s$) is passed in its entirety as the initial stack of the new TVM instance. When TVM terminates, its resulting stack is used as the new Fift stack, with the exit code $x$ pushed at its top. If $x$ is non-zero, indicating that TVM has been terminated by an unhandled exception, the next stack entry from the top contains the parameter of this exception, and $x$ is the exception code. All other entries are removed from the stack in this case.
|
|
|
|
|
\item {\tt runvmctx} (\dots $s$ $c$ $t$ -- \dots $x$ $c'$), a variant of {\tt runvm} that also initializes {\tt c7} (the ``context register'' of TVM) with {\em Tuple\/}~$t$, cf.~\ptref{p:tvm.ops}.
|
|
|
|
|
\item {\tt runvmdict} (\dots $s$ -- \dots $x$), invokes a new instance of TVM with the current continuation {\tt cc} initialized from {\em Slice\/} $s$ similarly to {\tt runvmcode}, but also initializes the special register {\tt c3} with the same value, and pushes a zero into the initial TVM stack before start, cf.~\ptref{p:tvm.ops}. In a typical application {\em Slice\/}~$s$ consists of a subroutine selection code that uses the top-of-stack {\em Integer\/} to select the subroutine to be executed, thus enabling the definition and execution of several mutually-recursive subroutines (cf.~\cite[4.6]{TVM} and~\ptref{p:asm.prog}). The selector equal to zero corresponds to the {\tt main()} subroutine in a large TVM program.
|
|
|
|
|
\item {\tt runvm} (\dots $s$ $c$ -- \dots $x$ $c'$), invokes a new instance of TVM with both the current continuation {\tt cc} and the special register {\tt c3} initialized from {\em Slice\/}~$s$, and pushes a zero into the initial TVM stack similarly to {\tt runvmdict}, but also initializes special register {\tt c4} (the ``root of persistent data'', cf.~\cite[1.4]{TVM}) with {\em Cell\/}~$c$, cf.~\ptref{p:tvm.ops}. The final value of {\tt c4} is returned at the top of the final Fift stack as another {\em Cell\/}~$c'$. In this way one can emulate the execution of smart contracts that inspect or modify their persistent storage.
|
|
|
|
|
\item {\tt s,} ($b$ $s$ -- $b'$), appends data bits and references taken from {\em Slice}~$s$ to {\em Builder}~$b$, cf.~\ptref{p:builder.ops}.
|
|
|
|
|
\item {\tt s>} ($s$ -- ), throws an exception if {\em Slice\/}~$s$ is non-empty, cf.~\ptref{p:slice.ops}. It usually marks the end of the deserialization of a cell, checking whether there are any unprocessed data bits or references left.
|
|
|
|
|
\item {\tt s>c} ($s$ -- $c$), creates a {\em Cell}~$c$ directly from a {\em Slice}~$s$, cf.~\ptref{p:slice.ops}. Equivalent to {\tt <b swap s, b>}.
|
|
|
|
@ -2150,9 +2154,9 @@ Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON
|
|
|
|
|
\item {\tt u@+} ($s$ $x$ -- $y$ $s'$), fetches an unsigned big-endian $x$-bit integer from the first $x$ bits of {\em Slice}~$s$ similarly to {\tt u@}, but returns the remainder of $s$ as well, cf.~\ptref{p:slice.ops}.
|
|
|
|
|
\item {\tt u@?} ($s$ $x$ -- $y$ $-1$ or $0$), fetches an unsigned big-endian integer from a {\em Slice\/} similarly to {\tt u@}, but pushes integer $-1$ afterwards on success, cf.~\ptref{p:slice.ops}. If there are less than $x$ bits left in $s$, pushes integer $0$ to indicate failure.
|
|
|
|
|
\item {\tt u@?+} ($s$ $x$ -- $y$ $s'$ $-1$ or $s$ $0$), fetches an unsigned big-endian integer from {\em Slice\/}~$s$ and computes the remainder of this {\em Slice\/} similarly to {\tt u@+}, but pushes $-1$ afterwards to indicate success, cf.~\ptref{p:slice.ops}. On failure, pushes the unchanged {\em Slice\/}~$s$ and $0$ to indicate failure.
|
|
|
|
|
\item {\tt udict!} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new value $v$ (represented by a {\em Slice\/}) with key given by big-endian unsigned $n$-bit integer $x$ into dictionary $s$ with $n$-bit keys, and returns the new dictionary $s'$ and $-1$ on success, cf.~\ptref{p:hashmap.ops}. Otherwise the unchanged dictionary $s$ and $0$ are returned.
|
|
|
|
|
\item {\tt udict!+} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new key-value pair $(x,v)$ into dictionary $s$ similarly to {\tt udict!}, but fails if the key already exists by returning the unchanged dictionary $s$ and $0$, cf.~\ptref{p:hashmap.ops}.
|
|
|
|
|
\item {\tt udict@} ($x$ $s$ $n$ -- $v$ $-1$ or $0$), looks up key represented by unsigned big-endian $n$-bit {\em Integer\/}~$x$ in the dictionary represented by {\em Slice\/}~$s$, cf.~\ptref{p:hashmap.ops}. If the key is found, returns the corresponding value as a {\em Slice\/}~$v$ and $-1$. Otherwise returns $0$.
|
|
|
|
|
\item {\tt udict!} ($v$ $x$ $D$ $n$ -- $D'$ $-1$ or $D$ $0$), adds a new value $v$ (represented by a {\em Slice\/}) with key given by big-endian unsigned $n$-bit integer $x$ into dictionary $D$ with $n$-bit keys, and returns the new dictionary $D'$ and $-1$ on success, cf.~\ptref{p:hashmap.ops}. Otherwise the unchanged dictionary $D$ and $0$ are returned.
|
|
|
|
|
\item {\tt udict!+} ($v$ $x$ $D$ $n$ -- $D'$ $-1$ or $D$ $0$), adds a new key-value pair $(x,v)$ into dictionary $D$ similarly to {\tt udict!}, but fails if the key already exists by returning the unchanged dictionary $D$ and $0$, cf.~\ptref{p:hashmap.ops}.
|
|
|
|
|
\item {\tt udict@} ($x$ $D$ $n$ -- $v$ $-1$ or $0$), looks up key represented by unsigned big-endian $n$-bit {\em Integer\/}~$x$ in the dictionary represented by {\em Cell\/} or {\em Null\/}~$D$, cf.~\ptref{p:hashmap.ops}. If the key is found, returns the corresponding value as a {\em Slice\/}~$v$ and $-1$. Otherwise returns $0$.
|
|
|
|
|
\item {\tt ufits} ($x$ $y$ -- $?$), checks whether {\em Integer\/}~$x$ is an unsigned $y$-bit integer (i.e., whether $0\leq x<2^y$ for $0\leq y\leq 1023$), and returns $-1$ or $0$ accordingly.
|
|
|
|
|
\item {\tt uncons} ($l$ -- $h$ $t$), decomposes a non-empty list into its head and its tail, cf.~\ptref{p:lists}. Equivalent to {\tt unpair}.
|
|
|
|
|
\item {\tt \underline{undef?} $\langle\textit{word-name\/}\rangle$} ( -- $?$), checks whether the word $\langle\textit{word-name\/}\rangle$ is undefined at execution time, and returns $-1$ or $0$ accordingly.
|
|
|
|
|