mirror of
https://github.com/danog/ton.git
synced 2024-11-26 20:14:55 +01:00
2174 lines
201 KiB
TeX
2174 lines
201 KiB
TeX
\documentclass[12pt,oneside]{article}
|
|
\usepackage[T1]{fontenc}
|
|
%\usepackage{euler}
|
|
\usepackage{amssymb, amsmath, amsfonts, stmaryrd}
|
|
\usepackage[mathscr]{euscript}
|
|
\usepackage{mathrsfs}
|
|
\usepackage{theorem}
|
|
\usepackage[english]{babel}
|
|
\usepackage{bm}
|
|
\usepackage[all]{xy}
|
|
\usepackage{array}
|
|
\usepackage{multirow}
|
|
%\usepackage{chngcntr}
|
|
%\CompileMatrices
|
|
\usepackage[bookmarks=false,pdfauthor={Nikolai Durov},pdftitle={Fift: A Brief Introduction}]{hyperref}
|
|
\usepackage{fancyhdr}
|
|
\usepackage{caption}
|
|
%
|
|
\setlength{\headheight}{15.2pt}
|
|
\pagestyle{fancy}
|
|
\renewcommand{\headrulewidth}{0.5pt}
|
|
%
|
|
\def\makepoint#1{\medbreak\noindent{\bf #1.\ }}
|
|
\def\zeropoint{\setcounter{subsection}{-1}}
|
|
\def\zerosubpoint{\setcounter{subsubsection}{-1}}
|
|
\def\nxpoint{\refstepcounter{subsection}%
|
|
\smallbreak\makepoint{\thesubsection}}
|
|
\def\nxsubpoint{\refstepcounter{subsubsection}%
|
|
\smallbreak\makepoint{\thesubsubsection}}
|
|
\def\nxsubsubpoint{\refstepcounter{paragraph}%
|
|
\makepoint{\paragraph}}
|
|
%\setcounter{secnumdepth}{4}
|
|
%\counterwithin{paragraph}{subsubsection}
|
|
\def\refpoint#1{{\rm\textbf{\ref{#1}}}}
|
|
\let\ptref=\refpoint
|
|
\def\embt(#1.){\textbf{#1.}}
|
|
\def\embtx(#1){\textbf{#1}}
|
|
\def\emb#1{\textbf{#1.}}
|
|
\long\def\nodo#1{}
|
|
%
|
|
%\def\markbothsame#1{\markboth{#1}{#1}}
|
|
\fancyhf{}
|
|
\fancyfoot[C]{\thepage}
|
|
\def\markbothsame#1{\fancyhead[C]{#1}}
|
|
\def\mysection#1{\section{#1}\fancyhead[C]{\textsc{Chapter \textbf{\thesection.} #1}}}
|
|
\def\mysubsection#1{\subsection{#1}\fancyhead[C]{\small{\textsc{\textrm{\thesubsection.} #1}}}}
|
|
\def\myappendix#1{\section{#1}\fancyhead[C]{\textsc{Appendix \textbf{\thesection.} #1}}}
|
|
%
|
|
\let\tp=\textit
|
|
\let\vr=\textit
|
|
\def\workchainid{\vr{workchain\_id\/}}
|
|
\def\shardpfx{\vr{shard\_prefix}}
|
|
\def\accountid{\vr{account\_id\/}}
|
|
\def\currencyid{\vr{currency\_id\/}}
|
|
\def\uint{\tp{uint}}
|
|
\def\opsc#1{\operatorname{\textsc{#1}}}
|
|
\def\CellRepr{\opsc{CellRepr}}
|
|
\def\blkseqno{\opsc{blk-seqno}}
|
|
\def\blkprev{\opsc{blk-prev}}
|
|
\def\blkhash{\opsc{blk-hash}}
|
|
\def\Hash{\opsc{Hash}}
|
|
\def\Sha{\opsc{sha256}}
|
|
\def\SHA#1{\opsc{sha#1}}
|
|
\def\Int{\opsc{int}}
|
|
\def\height{\opsc{height}}
|
|
\def\len{\opsc{len}}
|
|
\def\leaf{\opsc{Leaf}}
|
|
\def\node{\opsc{Node}}
|
|
\def\Seqno{\opsc{SeqNo}}
|
|
\def\LT{\opsc{Lt}}
|
|
\def\NextHop{\opsc{NextHop}}
|
|
\def\root{\opsc{Root}}
|
|
\def\emptyroot{\opsc{EmptyRoot}}
|
|
\def\code{\opsc{code}}
|
|
\def\Ping{\opsc{Ping}}
|
|
\def\Store{\opsc{Store}}
|
|
\def\FindNode{\opsc{Find\_Node}}
|
|
\def\FindValue{\opsc{Find\_Value}}
|
|
\def\Bytes{\tp{Bytes}}
|
|
\def\Transaction{\tp{Transaction}}
|
|
\def\Account{\tp{Account}}
|
|
\def\State{\tp{State}}
|
|
\def\Maybe{\opsc{Maybe}}
|
|
\def\List{\opsc{List}}
|
|
\def\Block{\tp{Block}}
|
|
\def\Blockchain{\tp{Blockchain}}
|
|
\def\isValidBc{\tp{isValidBc}}
|
|
\def\evtrans{\vr{ev\_trans}}
|
|
\def\evblock{\vr{ev\_block}}
|
|
\def\Hashmap{\tp{Hashmap}}
|
|
\def\HashmapE{\tp{HashmapE}}
|
|
\def\Type{\tp{Type}}
|
|
\def\nat{\tp{nat\/}}
|
|
\def\hget{\vr{hget\/}}
|
|
\def\bbB{{\mathbb{B}}}
|
|
\def\bbP{{\mathbb{P}}}
|
|
\def\bbF{{\mathbb{F}}}
|
|
\def\bbZ{{\mathbb{Z}}}
|
|
\def\st#1{{\mathbf{#1}}}
|
|
\def\sgn{\operatorname{sgn}}
|
|
\def\charact{\operatorname{char}}
|
|
\def\caret{\^{}}
|
|
\def\cF{\mathscr{F}}
|
|
%
|
|
\hfuzz=0.8pt
|
|
|
|
\title{Fift: A Brief Introduction}
|
|
\author{Nikolai Durov}
|
|
\begin{document}
|
|
|
|
%\pagestyle{myheadings}
|
|
\maketitle
|
|
|
|
\begin{abstract}
|
|
The aim of this text is to provide a brief description of Fift, a new programming language specifically designed for creating and managing TON Blockchain smart contracts, and its features used for interaction with the TON Virtual Machine~\cite{TVM} and the TON Blockchain~\cite{TBC}.
|
|
\end{abstract}
|
|
|
|
\section*{Introduction}
|
|
\markbothsame{Introduction}
|
|
|
|
This document provides a brief description of Fift, a stack-based general-purpose programming language optimized for creating, debugging, and managing TON Blockchain smart contracts.
|
|
|
|
Fift has been specifically designed to interact with the TON Virtual Machine (TON VM or TVM)~\cite{TVM} and the TON Blockchain~\cite{TBC}. In particular, it offers native support for 257-bit integer arithmetic and TVM cell manipulation shared with TVM, as well as an interface to the Ed25519-based cryptography employed by the TON Blockchain. A macro assembler for TVM code, useful for writing new smart contracts, is also included in the Fift distribution.
|
|
|
|
Being a stack-based language, Fift is not unlike Forth. Because of the brevity of this text, some knowledge of Forth might be helpful for understanding Fift.\footnote{Good introductions to Forth exist; we can recommend~\cite{Brodie}.} However, there are significant differences between the two languages. For instance, Fift enforces runtime type-checking, and keeps values of different types (not only integers) in its stack.
|
|
|
|
A list of words (built-in functions, or primitives) defined in Fift, along with their brief descriptions, is presented in Appendix~\ref{app:words}.
|
|
|
|
Please note that the current version of this document describes a preliminary test version of Fift; some minor details are likely to change in the future.
|
|
|
|
\clearpage
|
|
\tableofcontents
|
|
|
|
\clearpage
|
|
\mysection{Overview}\label{sect:overview}
|
|
|
|
Fift is a simple stack-based programming language designed for testing and debugging the TON Virtual Machine \cite{TVM} and the TON Blockchain \cite{TBC}, but potentially useful for other purposes as well. When Fift is invoked (usually by executing a binary file called {\tt fift}), it either reads, parses, and interprets one or several source files indicated in the command line, or enters the interactive mode and interprets Fift commands read and parsed from the standard input. There is also a ``script mode'', activated by command line switch {\tt -s}, in which all command line arguments except the first one are passed to the Fift program by means of the variables {\tt \$$n$} and {\tt \$\#}. In this way, Fift can be used both for interactive experimentation and debugging as well as for writing simple scripts.
|
|
|
|
All data manipulated by Fift is kept in a (LIFO) stack. Each stack entry is supplemented by a {\em type tag}, which unambiguously determines the type of the value kept in the corresponding stack entry. The types of values supported by Fift include {\em Integer\/} (representing signed 257-bit integers), {\em Cell\/} (representing a TVM cell, which consists of up to 1023 data bits and up to four references to other cells as explained in \cite{TVM}), {\em Slice\/} (a partial view of a {\em Cell\/} used for parsing cells), and {\em Builder\/} (used for building new cells). These data types (and their implementations) are shared with TVM~\cite{TVM}, and can be safely passed from the Fift stack to the TVM stack and back when necessary (e.g., when TVM is invoked from Fift by using a Fift primitive such as {\tt runvmcode}).
|
|
|
|
In addition to the data types shared with TVM, Fift introduces some unique data types, such as {\em Bytes\/} (arbitrary byte sequences), {\em String\/} (UTF-8 strings), {\em WordList\/}, and {\em WordDef\/} (used by Fift to create new ``words'' and manipulate their definitions). In fact, Fift can be extended to manipulate arbitrary ``objects'' (represented by the generic type {\em Object}), provided they are derived from C++ class {\tt td::CntObject} in the current implementation.
|
|
|
|
Fift source files and libraries are usually kept in text files with the suffix {\tt .fif}. A search path for libraries and included files is passed to the Fift executable either in a {\tt -I} command line argument or in the {\tt FIFTPATH} environment variable. If neither is set, the default library search path {\tt /usr/lib/fift} is used.
|
|
|
|
On startup, the standard Fift library is read from the file {\tt Fift.fif} before interpreting any other sources. It must be present in the library search path, otherwise Fift execution will fail.
|
|
|
|
A fundamental Fift data structure is its global {\em dictionary}, containing {\em words}---or, more precisely, {\em word definitions\/}---that correspond both to built-in primitives and functions and to user-defined functions.\footnote{Fift words are typically shorter than functions or subroutines of other programming languages. A nice discussion and some guidelines (for Forth words) may be found in~\cite{Brodie2}.} A word can be executed in Fift simply by typing its name (a UTF-8 string without space characters) in interactive mode. When Fift starts up, some words ({\em primitives\/}) are already defined (by some C++ code in the current implementation); other words are defined in the standard library {\tt Fift.fif}. After that, the user may extend the dictionary by defining new words or redefining old ones.
|
|
|
|
The dictionary is supposed to be split into several {\em vocabularies}, or {\em name\-spaces}; however, namespaces are not implemented yet, so all words are currently defined in the same global namespace.
|
|
|
|
The Fift parser for input source files and for the standard input (in the interactive mode) is rather simple: the input is read line-by-line, then blank characters are skipped, and the longest prefix of the remaining line that is (the name of) a dictionary word is detected and removed from the input line.\footnote{Notice that in contrast to Forth, Fift word names are case-sensitive: {\tt dup} and {\tt DUP} are distinct words.} After that, the word thus found is executed, and the process repeats until the end of the line. When the input line is exhausted, a subsequent line is read from the current input file or the standard input.
|
|
|
|
In order to be detected, most words require a blank character or an end-of-line immediately after them; this is reflected by appending a space to their names in the dictionary. Other words, called {\em prefix words}, do not require a blank character immediately after them.
|
|
|
|
If no word is found, the string consisting of the first remaining characters of the input line until the next blank or end-of-line character is interpreted as an {\em Integer\/} and pushed into the stack. For instance, if we invoke Fift, type {\tt 2 3 + .} (and press Enter), Fift first pushes an {\em Integer\/} constant equal to $2$ into its stack, followed by another integer constant equal to $3$. After that, the built-in primitive ``{\tt +}'' is parsed and found in the dictionary; when invoked, it takes the two topmost elements from the stack and replaces them with their sum ($5$ in our example). Finally, ``{\tt .}'' is a primitive that prints the decimal representation of the top-of-stack {\em Integer}, followed by a space. As a result, we observe ``{\tt 5 ok}'' printed by the Fift interpreter into the standard output. The string ``{\tt ok}'' is printed by the interpreter whenever it finishes interpreting a line read from the standard input in the interactive mode.
|
|
|
|
A list of built-in words may be found in Appendix~\ref{app:words}.
|
|
|
|
\mysection{Fift basics}
|
|
This chapter provides an introduction into the basic features of the Fift programming language. The discussion is informal and incomplete at first, but gradually becomes more formal and more precise. In some cases, later chapters and Appendix~\ref{app:words} provide more details about the words first mentioned in this chapter; similarly, some tricks that will be dutifully explained in later chapters are already used here where appropriate.
|
|
|
|
\mysubsection{List of Fift stack value types}\label{p:stack.types}
|
|
Currently, the values of the following data types can be kept in a Fift stack:
|
|
\begin{itemize}
|
|
\item {\em Integer\/} --- A signed 257-bit integer. Usually denoted by $x$, $y$, or $z$ in the stack notation (when the stack effect of a Fift word is described).
|
|
\item {\em Cell\/} --- A TVM cell, consisting of up to 1023 data bits and up to 4 references to other cells (cf.~\cite{TVM}). Usually denoted by~$c$ or its variants, such as $c'$ or $c_2$.
|
|
\item {\em Slice\/} --- A partial view of a TVM cell, used for parsing data from {\em Cell\/}s. Usually denoted by~$s$.
|
|
\item {\em Builder\/} --- A partially built {\em Cell}, containing up to 1023 data bits and up to four references; can be used to create new {\em Cell\/}s. Usually denoted by~$b$.
|
|
\item {\em Null\/} --- A type with exactly one ``null'' value. Used to initialize new {\em Box\/}es. Usually denoted by~$\bot$.
|
|
\item {\em Tuple\/} --- An ordered collection of values of any of these types (not necessarily the same); can be used to represent values of arbitrary algebraic data types and Lisp-style lists.
|
|
\item {\em String\/} --- A (usually printable) UTF-8 string. Usually denoted by~$S$.
|
|
\item {\em Bytes\/} --- An arbitrary sequence of 8-bit bytes, typically used to represent binary data. Usually denoted by~$B$.
|
|
\item {\em WordList\/} --- A (partially created) list of word references, used for creating new Fift word definitions. Usually denoted by~$l$.
|
|
\item {\em WordDef\/} --- An execution token, usually representing the definition of an existing Fift word. Usually denoted by~$e$.
|
|
\item {\em Box\/} --- A location in memory that can be used to store one stack value. Usually denoted by~$p$.
|
|
\item {\em Atom\/} --- A simple entity uniquely identified by its name, a string. Can be used to represent identifiers, labels, operation names, tags, and stack markers. Usually denoted by~$a$.
|
|
\item {\em Object\/} --- An arbitrary C++ object of any class derived from base class {\tt td::CntObject}; may be used by Fift extensions to manipulate other data types and interface with other C++ libraries.
|
|
\end{itemize}
|
|
|
|
The first six types listed above are shared with TVM; the remainder are Fift-specific. Notice that not all TVM stack types are present in Fift. For instance, the TVM {\em Continuation\/} type is not explicitly recognized by Fift; if a value of this type ends up in a Fift stack, it is manipulated as a generic {\em Object}.
|
|
|
|
\mysubsection{Comments}\label{p:comments}
|
|
Fift recognizes two kinds of comments: ``{\tt // }'' (which must be followed by a space) opens a single-line comment until the end of the line, and {\tt /*} defines a multi-line comment until {\tt */}. Both words {\tt //} and {\tt /*} are defined in the standard Fift library ({\tt Fift.fif}).
|
|
|
|
\mysubsection{Terminating Fift}\label{p:exit.fift}
|
|
The word {\tt bye} terminates the Fift interpreter with a zero exit code. If a non-zero exit code is required (for instance, in Fift scripts), one can use word {\tt halt}, which terminates Fift with the given exit code (passed as an {\em Integer\/} at the top of the stack). In contrast, {\tt quit} does not quit to the operating system, but rather exits to the top level of the Fift interpreter.
|
|
|
|
\mysubsection{Simple integer arithmetic}\label{p:arith.op}
|
|
When Fift encounters a word that is absent from the dictionary, but which can be interpreted as an integer constant (or ``literal''), its value is pushed into the stack (as explained in~\ptref{p:int.lit} in more detail). Apart from that, several integer arithmetic primitives are defined:
|
|
\begin{itemize}
|
|
\item {\tt +} ($x$ $y$ -- $x+y$), replaces two {\em Integer\/}s $x$ and $y$ passed at the top of the stack with their sum $x+y$. All deeper stack elements remain intact. If either $x$ or $y$ is not an {\em Integer}, or if the sum does not fit into a signed 257-bit {\em Integer}, an exception is thrown.
|
|
\item {\tt -} ($x$ $y$ -- $x-y$), computes the difference $x-y$ of two {\em Integer\/}s $x$ and $y$. Notice that the first argument $x$ is the second entry from the top of the stack, while the second argument $y$ is taken from the top of the stack.
|
|
\item {\tt negate} ($x$ -- $-x$), changes the sign of an {\em Integer}.
|
|
\item {\tt *} ($x$ $y$ -- $xy$), computes the product $xy$ of two {\em Integer\/}s $x$ and $y$.
|
|
\item {\tt /} ($x$ $y$ -- $q:=\lfloor x/y\rfloor$), computes the floor-rounded quotient $\lfloor x/y\rfloor$ of two {\em Integer\/}s.
|
|
\item {\tt mod} ($x$ $y$ -- $r:=x\bmod y$), computes the remainder $x\bmod y=x-y\cdot\lfloor x/y\rfloor$ of division of $x$ by $y$.
|
|
\item {\tt /mod} ($x$ $y$ -- $q$ $r$), computes both the quotient and the remainder.
|
|
\item {\tt /c}, {\tt /r} ($x$ $y$ -- $q$), division words similar to {\tt /}, but using ceiling rounding ($q:=\lceil x/y\rceil$) and nearest-integer rounding ($q:=\lfloor 1/2+x/y\rfloor$), respectively.
|
|
\item {\tt /cmod}, {\tt /rmod} ($x$ $y$ -- $q$ $r:=x-qy$), division words similar to {\tt /mod}, but using ceiling or nearest-integer rounding.
|
|
\item {\tt <{}<} ($x$ $y$ -- $x\cdot 2^y$), computes an arithmetic left shift of binary number $x$ by $y\geq0$ positions, yielding $x\cdot 2^y$.
|
|
\item {\tt >{}>} ($x$ $y$ -- $q:=\lfloor x\cdot 2^{-y}\rfloor$), computes an arithmetic right shift by $y\geq0$ positions.
|
|
\item {\tt >{}>c}, {\tt >{}>r} ($x$ $y$ -- $q$), similar to {\tt >{}>}, but using ceiling or nearest-integer rounding.
|
|
\item {\tt and}, {\tt or}, {\tt xor} ($x$ $y$ -- $x\oplus y$), compute the bitwise AND, OR, or XOR of two {\em Integer\/}s.
|
|
\item {\tt not} ($x$ -- $-1-x$), bitwise complement of an {\em Integer}.
|
|
\item {\tt */} ($x$ $y$ $z$ -- $\lfloor xy/z\rfloor$), ``multiply-then-divide'': multiplies two integers $x$ and $y$ producing a 513-bit intermediate result, then divides the product by $z$.
|
|
\item {\tt */mod} ($x$ $y$ $z$ -- $q$ $r$), similar to {\tt */}, but computes both the quotient and the remainder.
|
|
\item {\tt */c}, {\tt */r} ($x$ $y$ $z$ -- $q$), {\tt */cmod}, {\tt */rmod} ($x$ $y$ $z$ -- $q$ $r$), similar to {\tt */} or {\tt */mod}, but using ceiling or nearest-integer rounding.
|
|
\item {\tt *>{}>}, {\tt *>{}>c}, {\tt *>{}>r} ($x$ $y$ $z$ -- $q$), similar to {\tt */} and its variants, but with division replaced with a right shift. Compute $q=xy/2^z$ rounded in the indicated fashion (floor, ceiling, or nearest integer).
|
|
\item {\tt <{}</}, {\tt <{}</c}, {\tt <{}</r} ($x$ $y$ $z$ -- $q$), similar to {\tt */}, but with multiplication replaced with a left shift. Compute $q=2^zx/y$ rounded in the indicated fashion (notice the different order of arguments $y$ and $z$ compared to {\tt */}).
|
|
\end{itemize}
|
|
|
|
In addition, the word ``{\tt .}'' may be used to print the decimal representation of an {\em Integer\/} passed at the top of the stack (followed by a single space), and ``{\tt x.}'' prints the hexadecimal representation of the top-of-stack integer. The integer is removed from the stack afterwards.
|
|
|
|
The above primitives can be employed to use the Fift interpreter in interactive mode as a simple calculator for arithmetic expressions represented in reverse Polish notation (with operation symbols after the operands). For instance,
|
|
\begin{verbatim}
|
|
7 4 - .
|
|
\end{verbatim}
|
|
computes $7-4=3$ and prints ``{\tt 3 ok}'', and
|
|
\begin{verbatim}
|
|
2 3 4 * + .
|
|
2 3 + 4 * .
|
|
\end{verbatim}
|
|
computes $2+3\cdot 4=14$ and $(2+3)\cdot 4=20$, and prints ``{\tt 14 20 ok}''.
|
|
|
|
\mysubsection{Stack manipulation words}\label{p:stack.ops}
|
|
Stack manipulation words rearrange one or several values near the top of the stack, regardless of their types, and leave all deeper stack values intact. Some of the most often used stack manipulation words are listed below:
|
|
\begin{itemize}
|
|
\item {\tt dup} ($x$ -- $x$ $x$), duplicates the top-of-stack entry. If the stack is empty, throws an exception.\footnote{Notice that Fift word names are case-sensitive, so one cannot type {\tt DUP} instead of {\tt dup}.}
|
|
\item {\tt drop} ($x$ -- ), removes the top-of-stack entry.
|
|
\item {\tt swap} ($x$ $y$ -- $y$ $x$), interchanges the two topmost stack entries.
|
|
\item {\tt rot} ($x$ $y$ $z$ -- $y$ $z$ $x$), rotates the three topmost stack entries.
|
|
\item {\tt -rot} ($x$ $y$ $z$ -- $z$ $x$ $y$), rotates the three topmost stack entries in the opposite direction. Equivalent to {\tt rot rot}.
|
|
\item {\tt over} ($x$ $y$ -- $x$ $y$ $x$), creates a copy of the second stack entry from the top over the top-of-stack entry.
|
|
\item {\tt tuck} ($x$ $y$ -- $y$ $x$ $y$), equivalent to {\tt swap over}.
|
|
\item {\tt nip} ($x$ $y$ -- $y$), removes the second stack entry from the top. Equivalent to {\tt swap drop}.
|
|
\item {\tt 2dup} ($x$ $y$ -- $x$ $y$ $x$ $y$), equivalent to {\tt over over}.
|
|
\item {\tt 2drop} ($x$ $y$ -- ), equivalent to {\tt drop drop}.
|
|
\item {\tt 2swap} ($a$ $b$ $c$ $d$ -- $c$ $d$ $a$ $b$), interchanges the two topmost pairs of stack entries.
|
|
\item {\tt pick} ($x_n$ \dots $x_0$ $n$ -- $x_n$ \dots $x_0$ $x_n$), creates a copy of the $n$-th entry from the top of the stack, where $n\geq0$ is also passed in the stack. In particular, {\tt 0 pick} is equivalent to {\tt dup}, and {\tt 1 pick} to {\tt over}.
|
|
\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. In particular, {\tt 1 roll} is equivalent to {\tt swap}, and {\tt 2 roll} to {\tt rot}.
|
|
\item {\tt -roll} ($x_n$ \dots $x_0$ $n$ -- $x_0$ $x_n$ \dots $x_1$), rotates the top $n$ stack entries in the opposite direction, where $n\geq0$ is also passed in the stack. In particular, {\tt 1 -roll} is equivalent to {\tt swap}, and {\tt 2 -roll} to {\tt -rot}.
|
|
\item {\tt exch} ($x_n$ \dots $x_0$ $n$ -- $x_0$ \dots $x_n$), interchanges the top of the stack with the $n$-th stack entry from the top, where $n\geq0$ is also taken from the stack. In particular, {\tt 1 exch} is equivalent to {\tt swap}, and {\tt 2 exch} to {\tt swap rot}.
|
|
\item {\tt exch2} (\dots $n$ $m$ -- \dots), interchanges the $n$-th stack entry from the top with the $m$-th stack entry from the top, where $n\geq0$, $m\geq0$ are taken from the stack.
|
|
\item {\tt ?dup} ($x$ -- $x$ $x$ or $0$), duplicates an {\em Integer\/} $x$, but only if it is non-zero. Otherwise leaves it intact.
|
|
\end{itemize}
|
|
For instance, ``{\tt 5 dup * .}'' will compute $5\cdot 5=25$ and print ``{\tt 25 ok}''.
|
|
|
|
One can use the word ``{\tt .s}''---which prints the contents of the entire stack, starting from the deepest elements, without removing the elements printed from the stack---to inspect the contents of the stack at any time, and to check the effect of any stack manipulation words. For instance,
|
|
\begin{verbatim}
|
|
1 2 3 4 .s
|
|
rot .s
|
|
\end{verbatim}
|
|
prints
|
|
\begin{verbatim}
|
|
1 2 3 4
|
|
ok
|
|
1 3 4 2
|
|
ok
|
|
\end{verbatim}
|
|
|
|
When Fift does not know how to print a stack value of an unknown type, it instead prints {\tt ???}.
|
|
|
|
\mysubsection{Defining new words}\label{p:colon.def}
|
|
In its simplest form, defining new Fift words is very easy and can be done with the aid of three special words: ``{\tt \{}'', ``{\tt \}}'', and ``{\tt :}''. One simply opens the definition with {\tt \{} (necessarily followed by a space), then lists all the words that constitute the new definition, then closes the definition with {\tt \}} (also followed by a space), and finally assigns the resulting definition (represented by a {\em WordDef\/} value in the stack) to a new word by writing {\tt:\ $\langle\textit{new-word-name}\rangle$}. For instance,
|
|
\begin{verbatim}
|
|
{ dup * } : square
|
|
\end{verbatim}
|
|
defines a new word {\tt square}, which executes {\tt dup} and {\tt *} when invoked. In this way, typing {\tt 5 square} becomes equivalent to typing {\tt 5 dup *}, and produces the same result ($25$):
|
|
\begin{verbatim}
|
|
5 square .
|
|
\end{verbatim}
|
|
prints ``{\tt 25 ok}''. One can also use the new word as a part of new definitions:
|
|
\begin{verbatim}
|
|
{ dup square square * } : **5
|
|
3 **5 .
|
|
\end{verbatim}
|
|
prints ``{\tt 243 ok}'', which indeed is $3^5$.
|
|
|
|
If the word indicated after ``{\tt :}'' is already defined, it is tacitly redefined. However, all existing definitions of other words will continue to use the old definition of the redefined word. For instance, if we redefine {\tt square} after we have already defined {\tt **5} as above, {\tt **5} will continue to use the original definition of {\tt square}.
|
|
|
|
\mysubsection{Named constants}\label{p:constants}
|
|
One can define {\em (named) constants}---i.e., words that push a predefined value when invoked---by using the defining word {\tt constant} instead of the defining word ``{\tt :}'' (colon). For instance,
|
|
\begin{verbatim}
|
|
1000000000 constant Gram
|
|
\end{verbatim}
|
|
defines a constant {\tt Gram} equal to {\em Integer\/} $10^9$. In other words, $1000000000$ will be pushed into the stack whenever {\tt Gram} is invoked:
|
|
\begin{verbatim}
|
|
Gram 2 * .
|
|
\end{verbatim}
|
|
prints ``{\tt 2000000000 ok}''.
|
|
|
|
Of course, one can use the result of a computation to initialize the value of a constant:
|
|
\begin{verbatim}
|
|
Gram 1000 / constant mGram
|
|
mGram .
|
|
\end{verbatim}
|
|
prints ``{\tt 1000000 ok}''.
|
|
|
|
The value of a constant does not necessarily have to be an {\em Integer}. For instance, one can define a string constant in the same way:
|
|
\begin{verbatim}
|
|
"Hello, world!" constant hello
|
|
hello type cr
|
|
\end{verbatim}
|
|
prints ``{\tt Hello, world!}'' on a separate line.
|
|
|
|
If a constant is redefined, all existing definitions of other words will continue to use the old value of the constant. In this respect, a constant does not behave as a global variable.
|
|
|
|
One can also store two values into one ``double'' constant by using the defining word {\tt 2constant}. For instance,
|
|
\begin{verbatim}
|
|
355 113 2constant pifrac
|
|
\end{verbatim}
|
|
defines a new word {\tt pifrac}, which will push $355$ and $113$ (in that order) when invoked. The two components of a double constant can be of different types.
|
|
|
|
If one wants to create a constant with a fixed name within a block or a colon definition, one should use {\tt =:} and {\tt 2=:} instead of {\tt constant} and {\tt 2constant}:
|
|
\begin{verbatim}
|
|
{ dup =: x dup * =: y } : setxy
|
|
3 setxy x . y . x y + .
|
|
7 setxy x . y . x y + .
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
3 9 12 ok
|
|
7 49 56 ok
|
|
\end{verbatim}
|
|
If one wants to recover the execution-time value of such a ``constant'', one can prefix the name of the constant with the word {\tt @'}:
|
|
\begin{verbatim}
|
|
{ ."( " @' x . .", " @' y . .") " } : showxy
|
|
3 setxy showxy
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
( 3 , 9 ) ok
|
|
\end{verbatim}
|
|
The drawback of this approach is that {\tt @'} has to look up the current definition of constants {\tt x} and {\tt y} in the dictionary each time {\tt showxy} is executed. Variables (cf.~\ptref{p:variables}) provide a more efficient way to achieve similar results.
|
|
|
|
\mysubsection{Integer and fractional constants, or literals}\label{p:int.lit}
|
|
Fift recognizes unnamed integer constants (called {\em literals\/} to distinguish them from named constants) in decimal, binary, and hexadecimal formats. Binary literals are prefixed by {\tt 0b}, hexadecimal literals are prefixed by {\tt 0x}, and decimal literals do not require a prefix. For instance, {\tt 0b1011}, {\tt 11}, and {\tt 0xb} represent the same integer ($11$). An integer literal may be prefixed by a minus sign ``{\tt -}'' to change its sign; the minus sign is accepted both before and after the {\tt 0x} and {\tt 0b} prefixes.
|
|
|
|
When Fift encounters a string that is absent from the dictionary but is a valid integer literal (fitting into the 257-bit signed integer type {\em Integer}), its value is pushed into the stack.
|
|
|
|
Apart from that, Fift offers some support for decimal and common fractions. If a string consists of two valid integer literals separated by a slash {\tt /}, then Fift interprets it as a fractional literal and represents it by two {\em Integer\/}s $p$ and $q$ in the stack, the numerator $p$ and the denominator $q$. For instance, {\tt -17/12} pushes $-17$ and $12$ into the Fift stack (being thus equivalent to {\tt -17 12}), and {\tt -0x11/0b1100} does the same thing. Decimal, binary, and hexadecimal fractions, such as {\tt 2.39} or {\tt -0x11.ef}, are also represented by two integers $p$ and $q$, where $q$ is a suitable power of the base (10, 2, or 16, respectively). For instance, {\tt 2.39} is equivalent to {\tt 239 100}, and {\tt -0x11.ef} is equivalent to {\tt -0x11ef 0x100}.
|
|
|
|
Such a representation of fractions is especially convenient for using them with the scaling primitive {\tt */} and its variants, thus converting common and decimal fractions into a suitable fixed-point representation. For instance, if we want to represent fractional amounts of Grams by integer amounts of nanograms, we can define some helper words
|
|
\begin{verbatim}
|
|
1000000000 constant Gram
|
|
{ Gram * } : Gram*
|
|
{ Gram swap */r } : Gram*/
|
|
\end{verbatim}
|
|
and then write {\tt 2.39 Gram*/} or {\tt 17/12 Gram*/} instead of integer literals {\tt 2390000000} or {\tt 1416666667}.
|
|
|
|
If one needs to use such Gram literals often, one can introduce a new active prefix word {\tt GR\$} as follows:
|
|
\begin{verbatim}
|
|
{ bl word (number) ?dup 0= abort"not a valid Gram amount"
|
|
1- { Gram swap */r } { Gram * } cond
|
|
1 'nop
|
|
} ::_ GR$
|
|
\end{verbatim}
|
|
makes {\tt GR\$3}, {\tt GR\$2.39}, and {\tt GR\$17/12} equivalent to integer literals {\tt 3000000000}, {\tt 2390000000}, and {\tt 1416666667}, respectively. Such values can be printed in similar form by means of the following words:
|
|
\begin{verbatim}
|
|
{ dup abs <# ' # 9 times char . hold #s rot sign #>
|
|
nip -trailing0 } : (.GR)
|
|
{ (.GR) ."GR$" type space } : .GR
|
|
-17239000000 .GR
|
|
\end{verbatim}
|
|
produces {\tt GR\$-17.239 ok}. The above definitions make use of tricks explained in later portions of this document (especially Chapter~\ptref{s:dict.compiler}).
|
|
|
|
We can also manipulate fractions by themselves by defining suitable ``rational arithmetic words'':
|
|
\begin{verbatim}
|
|
// a b c d -- (a*d-b*c) b*d
|
|
{ -rot over * 2swap tuck * rot - -rot * } : R-
|
|
// a b c d -- a*c b*d
|
|
{ rot * -rot * swap } : R*
|
|
// a b --
|
|
{ swap ._ ."/" . } : R.
|
|
1.7 2/3 R- R.
|
|
\end{verbatim}
|
|
will output ``{\tt 31/30 ok}'', indicating that $1.7-2/3=31/30$. Here ``{\tt .\_}'' is a variant of ``{\tt .}'' that does not print a space after the decimal representation of an {\em Integer}.
|
|
|
|
\mysubsection{String literals}\label{p:string.lit}
|
|
String literals are introduced by means of the prefix word {\tt "}, which scans the remainder of the line until the next {\tt "} character, and pushes the string thus obtained into the stack as a value of type {\em String}. For instance, {\tt "Hello, world!"} pushes the corresponding {\em String\/} into the stack:
|
|
\begin{verbatim}
|
|
"Hello, world!" .s
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Simple string manipulation}\label{p:string.ops}
|
|
The following words can be used to manipulate strings:
|
|
\begin{itemize}
|
|
\item {\tt"$\langle\textit{string}\rangle$"} ( -- $S$), pushes a {\em String\/} literal into the stack.
|
|
\item {\tt."$\langle\textit{string}\rangle$"} ( -- ), prints a constant string into the standard output.
|
|
\item {\tt type} ($S$ -- ), prints a {\em String\/} $S$ taken from the top of the stack into the standard output.
|
|
\item {\tt cr} ( -- ), outputs a carriage return (or a newline character) into the standard output.
|
|
\item {\tt emit} ($x$ -- ), prints a UTF-8 encoded character with Unicode codepoint given by {\em Integer\/} $x$ into the standard output.
|
|
\item {\tt char $\langle\textit{string}\rangle$} ( -- $x$), pushes an {\em Integer\/} with the Unicode codepoint of the first character of {\tt $\langle\textit{string}\rangle$}.
|
|
\item {\tt bl} ( -- $x$), pushes the Unicode codepoint of a space, i.e., 32.
|
|
\item {\tt space} ( -- ), prints one space, equivalent to {\tt bl emit}.
|
|
\item {\tt \$+} ($S$ $S'$ -- $S.S'$), concatenates two strings.
|
|
\item {\tt \$len} ($S$ -- $x$), computes the byte length (not the UTF-8 character length!) of a string.
|
|
\item {\tt +"$\langle\textit{string}\rangle$"} ($S$ -- $S'$), concatenates {\em String\/}~$S$ with a string literal. Equivalent to {\tt "$\langle\textit{string}\rangle$" \$+}.
|
|
\item {\tt word} ($x$ -- $S$), parses a word delimited by the character with the Unicode codepoint $x$ from the remainder of the current input line and pushes the result as a {\em String}. For instance, {\tt bl word abracadabra type} will print the string ``{\tt abracadabra}''. If $x=0$, skips leading spaces, and then scans until the end of the current input line. If $x=32$, skips leading spaces before parsing the next word.
|
|
\item {\tt (.)} ($x$ -- $S$), returns the {\em String\/} with the decimal representation of {\em Integer\/}~$x$.
|
|
\item {\tt (number)} ($S$ -- $0$ or $x$ $1$ or $x$ $y$ $2$), attempts to parse the {\em String\/} $S$ as an integer or fractional literal as explained in~\ptref{p:int.lit}.
|
|
\end{itemize}
|
|
For instance, {\tt ."*"}, {\tt "*" type}, {\tt 42 emit}, and {\tt char * emit} are four different ways to output a single asterisk.
|
|
|
|
\mysubsection{Boolean expressions, or flags}\label{p:bool}
|
|
Fift does not have a separate value type for representing boolean values. Instead, any non-zero {\em Integer\/} can be used to represent truth (with $-1$ being the standard representation), while a zero {\em Integer\/} represents falsehood. Comparison primitives normally return $-1$ to indicate success and $0$ otherwise.
|
|
|
|
Constants {\tt true} and {\tt false} can be used to push these special integers into the stack:
|
|
\begin{itemize}
|
|
\item {\tt true} ( -- $-1$), pushes $-1$ into the stack.
|
|
\item {\tt false} ( -- $0$), pushes $0$ into the stack.
|
|
\end{itemize}
|
|
|
|
If boolean values are standard (either $0$ or $-1$), they can be manipulated by means of bitwise logical operations {\tt and}, {\tt or}, {\tt xor}, {\tt not} (listed in~\ptref{p:arith.op}). Otherwise, they must first be reduced to the standard form using {\tt 0<>}:
|
|
\begin{itemize}
|
|
\item {\tt 0<>} ($x$ -- $x\neq0$), pushes $-1$ if {\em Integer\/} $x$ is non-zero, $0$ otherwise.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Integer comparison operations}\label{p:int.comp}
|
|
Several integer comparison operations can be used to obtain boolean values:
|
|
\begin{itemize}
|
|
\item {\tt <} ($x$ $y$ -- $?$), checks whether $x<y$ (i.e., pushes $-1$ if $x<y$, $0$ otherwise).
|
|
\item {\tt >}, {\tt =}, {\tt <>}, {\tt <=}, {\tt >=} ($x$ $y$ -- $?$), compare $x$ and $y$ and push $-1$ or $0$ depending on the result of the comparison.
|
|
\item {\tt 0<} ($x$ -- $?$), checks whether $x<0$ (i.e., pushes $-1$ if $x$ is negative, $0$ otherwise). Equivalent to {\tt 0 <}.
|
|
\item {\tt 0>}, {\tt 0=}, {\tt 0<>}, {\tt 0<=}, {\tt 0>=} ($x$ -- $?$), compare $x$ against zero.
|
|
\item {\tt cmp} ($x$ $y$ -- $z$), pushes $1$ if $x>y$, $-1$ if $x<y$, and $0$ if $x=y$.
|
|
\item {\tt sgn} ($x$ -- $y$), pushes $1$ if $x>0$, $-1$ if $x<0$, and $0$ if $x=0$. Equivalent to {\tt 0 cmp}.
|
|
\end{itemize}
|
|
Example:
|
|
\begin{verbatim}
|
|
2 3 < .
|
|
\end{verbatim}
|
|
prints ``{\tt -1 ok}'', because $2$ is less than $3$.
|
|
|
|
A more convoluted example:
|
|
\begin{verbatim}
|
|
{ "true " "false " rot 0= 1+ pick type 2drop } : ?.
|
|
2 3 < ?. 2 3 = ?. 2 3 > ?.
|
|
\end{verbatim}
|
|
prints ``{\tt true false false ok}''.
|
|
|
|
\mysubsection{String comparison operations}\label{p:string.cmp.ops}
|
|
Strings can be lexicographically compared by means of the following words:
|
|
\begin{itemize}
|
|
\item {\tt \$=} ($S$ $S'$ -- $?$), returns $-1$ if strings $S$ and $S'$ are equal, $0$ otherwise.
|
|
\item {\tt \$cmp} ($S$ $S'$ -- $x$), returns $0$ if strings $S$ and $S'$ are equal, $-1$ if $S$ is lexicographically less than $S'$, and $1$ if $S$ is lexicographically greater than $S'$.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Named and unnamed variables}\label{p:variables}
|
|
In addition to constants introduced in~\ptref{p:constants}, Fift supports {\em variables}, which are a more efficient way to represent changeable values. For instance, the last two code fragments of~\ptref{p:constants} could have been written with the aid of variables instead of constants as follows:
|
|
\begin{verbatim}
|
|
variable x variable y
|
|
{ dup x ! dup * y ! } : setxy
|
|
3 setxy x @ . y @ . x @ y @ + .
|
|
7 setxy x @ . y @ . x @ y @ + .
|
|
{ ."( " x @ . .", " y @ . .") " } : showxy
|
|
3 setxy showxy
|
|
\end{verbatim}
|
|
producing the same output as before:
|
|
\begin{verbatim}
|
|
3 9 12 ok
|
|
7 49 56 ok
|
|
( 3 , 9 ) ok
|
|
\end{verbatim}
|
|
|
|
The phrase {\tt variable x} creates a new {\em Box}, i.e., a memory location that can be used to store exactly one value of any Fift-supported type, and defines {\tt x} as a constant equal to this {\em Box\/}:
|
|
\begin{itemize}
|
|
\item {\tt variable} ( -- ), scans a blank-delimited word name $S$ from the remainder of the input, allocates an empty {\em Box}, and defines a new ordinary word $S$ as a constant, which will push the new {\em Box\/} when invoked. Equivalent to {\tt hole constant}.
|
|
\item {\tt hole} ( -- $p$), creates a new {\em Box\/}~$p$ that does not hold any value. Equivalent to {\tt null box}.
|
|
\item {\tt box} ($x$ -- $p$), creates a new {\em Box\/} containing specified value~$x$. Equivalent to {\tt hole tuck !}.
|
|
\end{itemize}
|
|
The value currently stored in a {\em Box\/} may be fetched by means of word {\tt @} (pronounced ``fetch''), and modified by means of word {\tt !} (pronounced ``store''):
|
|
\begin{itemize}
|
|
\item {\tt @} ($p$ -- $x$), fetches the value currently stored in {\em Box\/}~$p$.
|
|
\item {\tt !} ($x$ $p$ -- ), stores new value~$x$ into {\em Box\/}~$p$.
|
|
\end{itemize}
|
|
Several auxiliary words exist that can modify the current value in a more sophisticated fashion:
|
|
\begin{itemize}
|
|
\item {\tt +!} ($x$ $p$ -- ), increases the integer value stored in {\em Box\/}~$p$ by {\em Integer\/}~$x$. Equivalent to {\tt tuck @ + swap !}.
|
|
\item {\tt 1+!} ($p$ -- ), increases the integer value stored in {\em Box\/}~$p$ by one. Equivalent to {\tt 1 swap +!}.
|
|
\item {\tt 0!} ($p$ -- ), stores {\em Integer\/} $0$ into {\em Box\/}~$p$. Equivalent to {\tt 0 swap !}.
|
|
\end{itemize}
|
|
In this way we can implement a simple counter:
|
|
\begin{verbatim}
|
|
variable counter
|
|
{ counter 0! } : reset-counter
|
|
{ counter @ 1+ dup counter ! } : next-counter
|
|
reset-counter next-counter . next-counter . next-counter .
|
|
reset-counter next-counter .
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
1 2 3 ok
|
|
1 ok
|
|
\end{verbatim}
|
|
After these definitions are in place, we can even forget the definition of {\tt counter} by means of the phrase {\tt forget counter}. Then the only way to access the value of this variable is by means of {\tt reset-counter} and {\tt next-counter}.
|
|
|
|
Variables are usually created by {\tt variable} with no value, or rather with a {\em Null\/} value. If one wishes to create initialized variables, one can use the phrase {\tt box constant}:
|
|
\begin{verbatim}
|
|
17 box constant x
|
|
x 1+! x @ .
|
|
\end{verbatim}
|
|
prints ``{\tt 18 ok}''. One can even define a special defining word for initialized variables, if they are needed often:
|
|
\begin{verbatim}
|
|
{ box constant } : init-variable
|
|
17 init-variable x
|
|
"test" init-variable y
|
|
x 1+! x @ . y @ type
|
|
\end{verbatim}
|
|
prints ``{\tt 18 test ok}''.
|
|
|
|
The variables have so far only one disadvantage compared to the constants: one has to access their current values by means of an auxiliary word {\tt @}. Of course, one can mitigate this by defining a ``getter'' and a ``setter'' word for a variable, and use these words to write better-looking code:
|
|
\begin{verbatim}
|
|
variable x-box
|
|
{ x-box @ } : x
|
|
{ x-box ! } : x!
|
|
{ x x * 5 x * + 6 + } : f(x)
|
|
{ ."( " x . .", " f(x) . .") " } : .xy
|
|
3 x! .xy 5 x! .xy
|
|
\end{verbatim}
|
|
prints ``{\tt ( 3 , 30 ) ( 5 , 56 ) ok}'', which are the points $(x,f(x))$ on the graph of $f(x)=x^2+5x+6$ with $x=3$ and $x=5$.
|
|
|
|
Again, if we want to define ``getters'' for all our variables, we can first define a defining word as explained in~\ptref{p:custom.defw}, and use this word to define both a getter and a setter at the same time:
|
|
\begin{verbatim}
|
|
{ hole dup 1 ' @ does create 1 ' ! does create } : variable-set
|
|
variable-set x x!
|
|
variable-set y y!
|
|
{ ."x=" x . ."y=" y . ."x*y=" x y * . cr } : show
|
|
{ y 1+ y! } : up
|
|
{ x 1+ x! } : right
|
|
{ x y x! y! } : reflect
|
|
2 x! 5 y! show up show right show up show reflect show
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
x=2 y=5 x*y=10
|
|
x=2 y=6 x*y=12
|
|
x=3 y=6 x*y=18
|
|
x=3 y=7 x*y=21
|
|
x=7 y=3 x*y=21
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Tuples and arrays}\label{p:tuples}
|
|
Fift also supports {\em Tuple\/}s, i.e., immutable ordered collections of arbitrary values of stack value types (cf.~\ptref{p:stack.types}). When a {\em Tuple\/}~$t$ consists of values $x_1$, \dots, $x_n$ (in that order), we write $t=(x_1,\ldots,x_n)$. The number~$n$ is called the {\em length\/} of {\em Tuple\/}~$t$; it is also denoted by~$|t|$. Tuples of length two are also called {\em pairs}, tuples of length three are {\em triples}.
|
|
\begin{itemize}
|
|
\item {\tt tuple} ($x_1$ \dots $x_n$ $n$ -- $t$), creates new {\em Tuple\/} $t:=(x_1,\ldots,x_n)$ from $n\geq0$ topmost stack values.
|
|
\item {\tt pair} ($x$ $y$ -- $t$), creates new pair $t=(x,y)$. Equivalent to {\tt 2 tuple}.
|
|
\item {\tt triple} ($x$ $y$ $z$ -- $t$), creates new triple $t=(x,y,z)$. Equivalent to {\tt 3 tuple}.
|
|
\item {\tt |} ( -- $t$), creates an empty {\em Tuple\/} $t=()$. Equivalent to {\tt 0 tuple}.
|
|
\item {\tt ,} ($t$ $x$ -- $t'$), appends $x$ to the end of {\em Tuple\/}~$t$, and returns the resulting {\em Tuple\/}~$t'$.
|
|
\item {\tt .dump} ($x$ -- ), dumps the topmost stack entry in the same way as {\tt .s} dumps all stack elements.
|
|
\end{itemize}
|
|
For instance, both
|
|
\begin{verbatim}
|
|
| 2 , 3 , 9 , .dump
|
|
\end{verbatim}
|
|
and
|
|
\begin{verbatim}
|
|
2 3 9 triple .dump
|
|
\end{verbatim}
|
|
construct and print triple $(2,3,9)$:
|
|
\begin{verbatim}
|
|
[ 2 3 9 ] ok
|
|
\end{verbatim}
|
|
Notice that the components of a {\em Tuple\/} are not necessarily of the same type, and that a component of a {\em Tuple\/} can also be a {\em Tuple\/}:
|
|
\begin{verbatim}
|
|
1 2 3 triple 4 5 6 triple 7 8 9 triple triple constant Matrix
|
|
Matrix .dump cr
|
|
| 1 "one" pair , 2 "two" pair , 3 "three" pair , .dump
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
[ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
|
|
[ [ 1 "one" ] [ 2 "two" ] [ 3 "three" ] ] ok
|
|
\end{verbatim}
|
|
|
|
Once a {\em Tuple\/} has been constructed, we can extract any of its components, or completely unpack the {\em Tuple\/} into the stack:
|
|
\begin{itemize}
|
|
\item {\tt untuple} ($t$ $n$ -- $x_1$ \dots $x_n$), returns all components of a {\em Tuple\/}~$t=(x_1,\ldots,x_n)$, but only if its length is equal to~$n$. Otherwise throws an exception.
|
|
\item {\tt unpair} ($t$ -- $x$ $y$), unpacks a pair $t=(x,y)$. Equivalent to {\tt 2 untuple}.
|
|
\item {\tt untriple} ($t$ -- $x$ $y$ $z$), unpacks a triple $t=(x,y,z)$. Equivalent to {\tt 3 untuple}.
|
|
\item {\tt explode} ($t$ -- $x_1$ \dots $x_n$ $n$), unpacks a {\em Tuple\/}~$t=(x_1,\ldots,x_n)$ of unknown length~$n$, and returns that length.
|
|
\item {\tt count} ($t$ -- $n$), returns the length $n=|t|$ of {\em Tuple\/}~$t$.
|
|
\item {\tt tuple?} ($t$ -- $?$), checks whether $t$ is a {\em Tuple}, and returns $-1$ or $0$ accordingly.
|
|
\item {\tt []} ($t$ $i$ -- $x$), returns the $(i+1)$-st component $t_{i+1}$ of {\em Tuple\/}~$t$, where $0\leq i<|t|$.
|
|
\item {\tt first} ($t$ -- $x$), returns the first component of a {\em Tuple}. Equivalent to {\tt 0 []}.
|
|
\item {\tt second} ($t$ -- $x$), returns the second component of a {\em Tuple}. Equivalent to {\tt 1 []}.
|
|
\item {\tt third} ($t$ -- $x$), returns the third component of a {\em Tuple}. Equivalent to {\tt 2 []}.
|
|
\end{itemize}
|
|
For instance, we can access individual elements and rows of a matrix:
|
|
\begin{verbatim}
|
|
1 2 3 triple 4 5 6 triple 7 8 9 triple triple constant Matrix
|
|
Matrix .dump cr
|
|
Matrix 1 [] 2 [] . cr
|
|
Matrix third .dump cr
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
[ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
|
|
6
|
|
[ 7 8 9 ]
|
|
\end{verbatim}
|
|
|
|
Notice that {\em Tuple\/}s are somewhat similar to arrays of other programming languages, but are immutable: we cannot change one individual component of a {\em Tuple}. If we still want to create something like an array, we need a {\em Tuple\/} of {\em Box\/}es (cf.~\ptref{p:variables}):
|
|
\begin{itemize}
|
|
\item {\tt allot} ($n$ -- $t$), creates a {\em Tuple\/} that consists of $n$ new empty {\em Box\/}es. Equivalent to {\tt | \{ hole , \} rot times}.
|
|
\end{itemize}
|
|
For instance,
|
|
\begin{verbatim}
|
|
10 allot constant A
|
|
| 3 box , 1 box , 4 box , 1 box , 5 box , 9 box , constant B
|
|
{ over @ over @ swap rot ! swap ! } : swap-values-of
|
|
{ B swap [] } : B[]
|
|
{ B[] swap B[] swap-values-of } : swap-B
|
|
{ B[] @ . } : .B[]
|
|
0 1 swap-B 1 3 swap-B 0 2 swap-B
|
|
0 .B[] 1 .B[] 2 .B[] 3 .B[]
|
|
\end{verbatim}
|
|
creates an uninitialized array~$A$ of length~10, an initialized array~$B$ of length~6, and then interchanges some elements of $B$ and prints the first four elements of the resulting~$B$:
|
|
\begin{verbatim}
|
|
4 1 1 3 ok
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Lists}\label{p:lists}
|
|
Lisp-style lists can also be represented in Fift. First of all, two special words are introduced to manipulate values of type {\em Null}, used to represent the empty list (not to be confused with the empty {\em Tuple}):
|
|
\begin{itemize}
|
|
\item {\tt null} ( -- $\bot$), pushes the only value~$\bot$ of type {\em Null}, which is also used to represent an empty list.
|
|
\item {\tt null?} ($x$ -- $?$), checks whether~$x$ is a {\em Null}. Can also be used to check whether a list is empty.
|
|
\end{itemize}
|
|
After that, {\tt cons} and {\tt uncons} are defined as aliases for {\tt pair} and {\tt unpair}:
|
|
\begin{itemize}
|
|
\item {\tt cons} ($h$ $t$ -- $l$), constructs a list from its head (first element) $h$ and its tail (the list consisting of all remaining elements)~$t$. Equivalent to {\tt pair}.
|
|
\item {\tt uncons} ($l$ -- $h$ $t$), decomposes a non-empty list into its head and its tail. Equivalent to {\tt unpair}.
|
|
\item {\tt car} ($l$ -- $h$), returns the head of a list. Equivalent to {\tt first}.
|
|
\item {\tt cdr} ($l$ -- $t$), returns the tail of a list. Equivalent to {\tt second}.
|
|
\item {\tt cadr} ($l$ -- $h'$), returns the second element of a list. Equivalent to {\tt cdr car}.
|
|
\item {\tt list} ($x_1$ \dots $x_n$ $n$ -- $l$), constructs a list $l$ of length~$n$ with elements $x_1$, \ldots, $x_n$, in that order. Equivalent to {\tt null ' cons rot times}.
|
|
\item {\tt .l} ($l$ -- ), prints a Lisp-style list~$l$.
|
|
\end{itemize}
|
|
For instance,
|
|
\begin{verbatim}
|
|
2 3 9 3 tuple .dump cr
|
|
2 3 9 3 list dup .dump space dup .l cr
|
|
"test" swap cons .l cr
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
[ 2 3 9 ]
|
|
[ 2 [ 3 [ 9 (null) ] ] ] (2 3 9)
|
|
("test" 2 3 9)
|
|
\end{verbatim}
|
|
Notice that the three-element list $(2\ 3\ 9)$ is distinct from the triple $(2,3,9)$.
|
|
|
|
\mysubsection{Atoms}\label{p:atoms}
|
|
An {\em Atom\/} is a simple entity uniquely identified by its name. {\em Atom\/}s can be used to represent identifiers, labels, operation names, tags, and stack markers. Fift offers the following words to manipulate {\em Atom\/}s:
|
|
\begin{itemize}
|
|
\item {\tt (atom)} ($S$ $x$ -- $a$ $-1$ or $0$), returns the only {\em Atom\/} $a$ with the name given by {\em String\/}~$S$. If there is no such {\em Atom\/} yet, either creates it (if {\em Integer\/}~$x$ is non-zero) or returns a single zero to indicate failure (if $x$ is zero).
|
|
\item {\tt atom} ($S$ -- $a$), returns the only {\em Atom\/}~$a$ with the name~$S$, creating such an atom if necessary. Equivalent to {\tt true (atom) drop}.
|
|
\item {\tt `$\langle\textit{word\/}\rangle$} ( -- $a$), introduces an {\em Atom\/} literal, equal to the only {\em Atom\/} with the name equal to $\langle\textit{word\/}\rangle$. Equivalent to {\tt "$\langle\textit{word\/}\rangle$" atom}.
|
|
\item {\tt anon} ( -- $a$), creates a new unique anonymous {\em Atom}.
|
|
\item {\tt atom?} ($u$ -- $?$), checks whether $u$ is an {\em Atom}.
|
|
\item {\tt eq?} ($u$ $v$ -- $?$), checks whether $u$ and $v$ are equal {\em Integer\/}s, {\em Atom\/}s, or {\em Null\/}s. If they are not equal, or if they are of different types, or not of one of the types listed, returns zero.
|
|
\end{itemize}
|
|
|
|
For instance,
|
|
\begin{verbatim}
|
|
`+ 2 `* 3 4 3 list 3 list .l
|
|
\end{verbatim}
|
|
creates and prints the list
|
|
\begin{verbatim}
|
|
(+ 2 (* 3 4))
|
|
\end{verbatim}
|
|
which is the Lisp-style representation of arithmetical expression $2+3\cdot 4$. An interpreter for such expressions might use {\tt eq?} to check the operation sign (cf.~\ptref{p:recursion} for an explanation of recursive functions in Fift):
|
|
\begin{verbatim}
|
|
variable 'eval
|
|
{ 'eval @ execute } : eval
|
|
{ dup tuple? {
|
|
uncons uncons uncons
|
|
null? not abort"three-element list expected"
|
|
swap eval swap eval rot
|
|
dup `+ eq? { drop + } {
|
|
dup `- eq? { drop - } {
|
|
`* eq? not abort"unknown operation" *
|
|
} cond
|
|
} cond
|
|
} if
|
|
} 'eval !
|
|
`+ 2 `* 3 4 3 list 3 list dup .l cr eval . cr
|
|
\end{verbatim}
|
|
prints
|
|
\begin{verbatim}
|
|
(+ 2 (* 3 4))
|
|
14
|
|
\end{verbatim}
|
|
If we load {\tt Lisp.fif} to enable Lisp-style list syntax, we can enter
|
|
\begin{verbatim}
|
|
"Lisp.fif" include
|
|
( `+ 2 ( `* 3 4 ) ) dup .l cr eval . cr
|
|
\end{verbatim}
|
|
with the same result as before. The word {\tt (}, defined in {\tt Lisp.fif}, uses an anonymous {\em Atom\/} created by {\tt anon} to mark the current stack position, and then {\tt )} builds a list from several top stack entries, scanning the stack until the anonymous {\em Atom\/} marker is found:
|
|
\begin{verbatim}
|
|
variable ')
|
|
{ ") without (" abort } ') !
|
|
{ ') @ execute } : )
|
|
{ null { -rot 2dup eq? not } { swap rot cons } while 2drop
|
|
} : list-until-marker
|
|
{ anon dup ') @ 2 { ') ! list-until-marker } does ') ! } : (
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Command line arguments in script mode}\label{p:cmdline.ops}
|
|
The Fift interpreter can be invoked in {\em script mode\/} by passing {\tt -s} as a command line option. In this mode, all further command line arguments are not scanned for Fift startup command line options. Rather, the next argument after {\tt -s} is used as the filename of the Fift source file, and all further command line arguments are passed to the Fift program by means of special words {\tt \$$n$} and {\tt \$\#}:
|
|
\begin{itemize}
|
|
\item {\tt \$\#} ( -- $x$), pushes the total number of command-line arguments passed to the Fift program.
|
|
\item {\tt \$$n$} ( -- $S$), pushes the $n$-th command-line argument as a {\em String}~$S$. For instance, {\tt \$0} pushes the name of the script being executed, {\tt \$1} the first command line argument, and so on.
|
|
\item {\tt \$()} ($x$ -- $S$), pushes the $x$-th command-line argument similarly to {\tt \$$n$}, but with {\em Integer\/}~$x$ taken from the stack.
|
|
\end{itemize}
|
|
Additionally, if the very first line of a Fift source file begins with the two characters ``{\tt \#!}'', this line is ignored. In this way simple Fift scripts can be written in a *ix system. For instance, if
|
|
\begin{verbatim}
|
|
#!/usr/bin/fift -s
|
|
{ ."usage: " $0 type ." <num1> <num2>" cr
|
|
."Computes the product of two integers." cr 1 halt } : usage
|
|
{ ' usage if } : ?usage
|
|
$# 2 <> ?usage
|
|
$1 (number) 1- ?usage
|
|
$2 (number) 1- ?usage
|
|
* . cr
|
|
\end{verbatim}
|
|
is saved into a file {\tt cmdline.fif} in the current directory, and its execution bit is set (e.g., by {\tt chmod 755 cmdline.fif}), then it can be invoked from the shell or any other program, provided the Fift interpreter is installed as {\tt /usr/bin/fift}, and its standard library {\tt Fift.fif} is installed as {\tt /usr/lib/fift/Fift.fif}:
|
|
\begin{verbatim}
|
|
$ ./cmdline.fif 12 -5
|
|
\end{verbatim}
|
|
prints
|
|
\begin{verbatim}
|
|
-60
|
|
\end{verbatim}
|
|
when invoked from a *ix shell such as the Bourne--again shell (Bash).
|
|
|
|
\mysection{Blocks, loops, and conditionals}
|
|
Similarly to the arithmetic operations, the execution flow in Fift is controlled by stack-based primitives. This leads to an inversion typical of reverse Polish notation and stack-based arithmetic: one first pushes a block representing a conditional branch or the body of a loop into the stack, and then invokes a conditional or iterated execution primitive. In this respect, Fift is more similar to PostScript than to Forth.
|
|
|
|
\mysubsection{Defining and executing blocks}\label{p:blocks}
|
|
A block is normally defined using the special words ``{\tt \{}'' and ``{\tt \}}''. Roughly speaking, all words listed between {\tt \{} and {\tt \}} constitute the body of a new block, which is pushed into the stack as a value of type {\em WordDef}. A block may be stored as a definition of a new Fift word by means of the defining word ``{\tt :}'' as explained in \ptref{p:colon.def}, or executed by means of the word {\tt execute}:
|
|
\begin{verbatim}
|
|
17 { 2 * } execute .
|
|
\end{verbatim}
|
|
prints ``{\tt 34 ok}'', being essentially equivalent to ``{\tt 17 2 * .}''. A slightly more convoluted example:
|
|
\begin{verbatim}
|
|
{ 2 * } 17 over execute swap execute .
|
|
\end{verbatim}
|
|
applies ``anonymous function'' $x\mapsto 2x$ twice to $17$, and prints the result $2\cdot(2\cdot 17)=68$. In this way a block is an execution token, which can be duplicated, stored into a constant, used to define a new word, or executed.
|
|
|
|
The word {\tt '} recovers the current definition of a word. Namely, the construct {\tt ' $\langle\textit{word-name}\rangle$} pushes the execution token equivalent to the current definition of the word $\langle\textit{word-name}\rangle$. For instance,
|
|
\begin{verbatim}
|
|
' dup execute
|
|
\end{verbatim}
|
|
is equivalent to {\tt dup}, and
|
|
\begin{verbatim}
|
|
' dup : duplicate
|
|
\end{verbatim}
|
|
defines {\tt duplicate} as a synonym for (the current definition of) {\tt dup}.
|
|
|
|
Alternatively, we can duplicate a block to define two new words with the same definition:
|
|
\begin{verbatim}
|
|
{ dup * }
|
|
dup : square : **2
|
|
\end{verbatim}
|
|
defines both {\tt square} and {\tt **2} to be equivalent to {\tt dup *}.
|
|
|
|
\mysubsection{Conditional execution of blocks}\label{p:cond.ops}
|
|
Conditional execution of blocks is achieved using the words {\tt if}, {\tt ifnot}, and {\tt cond}:
|
|
\begin{itemize}
|
|
\item {\tt if} ($x$ $e$ -- ), executes $e$ (which must be an execution token, i.e., a {\em WordDef\/}),\footnote{A {\em WordDef\/} is more general than a {\em WordList}. For instance, the definition of the primitive {\tt +} is a {\em WordDef}, but not a {\em WordList}, because {\tt +} is not defined in terms of other Fift words.} but only if {\em Integer\/} $x$ is non-zero.
|
|
\item {\tt ifnot} ($x$ $e$ -- ), executes execution token $e$, but only if {\em Integer\/} $x$ is zero.
|
|
\item {\tt cond} ($x$ $e$ $e'$ -- ), if {\em Integer\/} $x$ is non-zero, executes $e$, otherwise executes $e'$.
|
|
\end{itemize}
|
|
|
|
For instance, the last example in \ptref{p:int.comp} can be more conveniently rewritten as
|
|
\begin{verbatim}
|
|
{ { ."true " } { ."false " } cond } : ?.
|
|
2 3 < ?. 2 3 = ?. 2 3 > ?.
|
|
\end{verbatim}
|
|
still resulting in ``{\tt true false false ok}''.
|
|
|
|
Notice that blocks can be arbitrarily nested, as already shown in the previous example. One can write, for example,
|
|
\begin{verbatim}
|
|
{ ?dup
|
|
{ 0<
|
|
{ ."negative " }
|
|
{ ."positive " }
|
|
cond
|
|
}
|
|
{ ."zero " }
|
|
cond
|
|
} : chksign
|
|
-17 chksign
|
|
\end{verbatim}
|
|
to obtain ``{\tt negative ok}'', because $-17$ is negative.
|
|
|
|
\mysubsection{Simple loops}\label{p:simple.loops}
|
|
The simplest loops are implemented by {\tt times}:
|
|
\begin{itemize}
|
|
\item {\tt times} ($e$ $n$ -- ), executes $e$ exactly $n$ times, if $n\geq0$. If $n$ is negative, throws an exception.
|
|
\end{itemize}
|
|
For instance,
|
|
\begin{verbatim}
|
|
1 { 10 * } 70 times .
|
|
\end{verbatim}
|
|
computes and prints $10^{70}$.
|
|
|
|
We can use this kind of loop to implement a simple factorial function:
|
|
\begin{verbatim}
|
|
{ 0 1 rot { swap 1+ tuck * } swap times nip } : fact
|
|
5 fact .
|
|
\end{verbatim}
|
|
prints ``{\tt 120 ok}'', because $5!=1\cdot 2\cdot 3\cdot 4\cdot 5=120$.
|
|
|
|
This loop can be modified to compute Fibonacci numbers instead:
|
|
\begin{verbatim}
|
|
{ 0 1 rot { tuck + } swap times nip } : fibo
|
|
6 fibo .
|
|
\end{verbatim}
|
|
computes the sixth Fibonacci number $F_6=13$.
|
|
|
|
\mysubsection{Loops with an exit condition}\label{p:loops}
|
|
More sophisticated loops can be created with the aid of {\tt until} and {\tt while}:
|
|
\begin{itemize}
|
|
\item {\tt until} ($e$ -- ), executes $e$, then removes the top-of-stack integer and checks whether it is zero. If it is, then begins a new iteration of the loop by executing $e$. Otherwise exits the loop.
|
|
\item {\tt while} ($e$ $e'$ -- ), executes $e$, then removes and checks the top-of-stack integer. If it is zero, exits the loop. Otherwise executes $e'$, then begins a new loop iteration by executing $e$ and checking the exit condition afterwards.
|
|
\end{itemize}
|
|
For instance, we can compute the first two Fibonacci numbers greater than 1000:
|
|
\begin{verbatim}
|
|
{ 1 0 rot { -rot over + swap rot 2dup >= } until drop
|
|
} : fib-gtr
|
|
1000 fib-gtr . .
|
|
\end{verbatim}
|
|
prints ``{\tt 1597 2584 ok}''.
|
|
|
|
We can use this word to compute the first 70 decimal digits of the golden ratio $\phi=(1+\sqrt{5})/2\approx 1.61803$:
|
|
\begin{verbatim}
|
|
1 { 10 * } 70 times dup fib-gtr */ .
|
|
\end{verbatim}
|
|
prints ``{\tt $161803\ldots2604$ ok}''.
|
|
|
|
\mysubsection{Recursion}\label{p:recursion}
|
|
Notice that, whenever a word is mentioned inside a {\tt \{ \dots \}} block, the current (compile-time) definition is included in the {\em WordList\/} being created. In this way we can refer to the previous definition of a word while defining a new version of it:
|
|
\begin{verbatim}
|
|
{ + . } : print-sum
|
|
{ ."number " . } : .
|
|
{ 1+ . } : print-next
|
|
2 . 3 . 2 3 print-sum 7 print-next
|
|
\end{verbatim}
|
|
produces ``{\tt number 2 number 3 5 number 8 ok}''. Notice that {\tt print-sum} continues to use the original definition of ``{\tt .}'', but {\tt print-next} already uses the modified ``{\tt .}''.
|
|
|
|
This feature may be convenient on some occasions, but it prevents us from introducing recursive definitions in the most straightforward fashion. For instance, the classical recursive definition of the factorial
|
|
\begin{verbatim}
|
|
{ ?dup { dup 1- fact * } { 1 } cond } : fact
|
|
\end{verbatim}
|
|
will fail to compile, because {\tt fact} happens to be an undefined word when the definition is compiled.
|
|
|
|
A simple way around this obstacle is to use the word {\tt @'} (cf.~\ptref{p:dict.lookup}) that looks up the current definition of the next word during the execution time and then executes it, similarly to what we already did in~\ptref{p:constants}:
|
|
\begin{verbatim}
|
|
{ ?dup { dup 1- @' fact * } { 1 } cond } : fact
|
|
5 fact .
|
|
\end{verbatim}
|
|
produces ``{\tt 120 ok}'', as expected.
|
|
|
|
However, this solution is rather inefficient, because it uses a dictionary lookup each time {\tt fact} is recursively executed. We can avoid this dictionary lookup by using variables (cf.~\ptref{p:variables} and \ptref{p:constants}):
|
|
\begin{verbatim}
|
|
variable 'fact
|
|
{ 'fact @ execute } : fact
|
|
{ ?dup { dup 1- fact * } { 1 } cond } 'fact !
|
|
5 fact .
|
|
\end{verbatim}
|
|
This somewhat longer definition of the factorial avoids dictionary lookups at execution time by introducing a special variable {\tt 'fact} to hold the final definition of the factorial.\footnote{Variables that hold a {\em WordDef\/} to be {\tt execute}d later are called {\em vector variables}. The process of replacing {\tt fact} with {\tt 'fact @ execute}, where {\tt 'fact} is a vector variable, is called {\em vectorization}.} Then {\tt fact} is defined to execute whatever {\em WordDef} is currently stored in {\tt 'fact}, and once the body of the recursive definition of the factorial is constructed, it is stored into this variable by means of the phrase {\tt 'fact !}, which replaces the more customary phrase {\tt :\ fact}.
|
|
|
|
We could rewrite the above definition by using special ``getter'' and ``setter'' words for vector variable {\tt 'fact} as we did for variables in \ptref{p:variables}:
|
|
\begin{verbatim}
|
|
variable 'fact
|
|
{ 'fact @ execute } : fact
|
|
{ 'fact ! } : :fact
|
|
forget 'fact
|
|
{ ?dup { dup 1- fact * } { 1 } cond } :fact
|
|
5 fact .
|
|
\end{verbatim}
|
|
If we need to introduce a lot of recursive and mutually-recursive definitions, we might first introduce a custom defining word (cf.~\ptref{p:custom.defw}) for simultaneously defining both the ``getter'' and the ``setter'' words for anonymous vector variables, similarly to what we did in~\ptref{p:variables}:
|
|
\begin{verbatim}
|
|
{ hole dup 1 { @ execute } does create 1 ' ! does create
|
|
} : vector-set
|
|
vector-set fact :fact
|
|
{ ?dup { dup 1- fact * } { 1 } cond } :fact
|
|
5 fact .
|
|
\end{verbatim}
|
|
The first three lines of this fragment define {\tt fact} and {\tt :fact} essentially in the same way they had been defined in the first four lines of the previous fragment.
|
|
|
|
If we wish to make {\tt fact} unchangeable in the future, we can add a {\tt forget :fact} line once the definition of the factorial is complete:
|
|
\begin{verbatim}
|
|
{ hole dup 1 { @ execute } does create 1 ' ! does create
|
|
} : vector-set
|
|
vector-set fact :fact
|
|
{ ?dup { dup 1- fact * } { 1 } cond } :fact
|
|
forget :fact
|
|
5 fact .
|
|
\end{verbatim}
|
|
Alternatively, we can modify the definition of {\tt vector-set} in such a way that {\tt :fact} would forget itself once it is invoked:
|
|
\begin{verbatim}
|
|
{ hole dup 1 { @ execute } does create
|
|
bl word tuck 2 { (forget) ! } does swap 0 (create)
|
|
} : vector-set-once
|
|
vector-set-once fact :fact
|
|
{ ?dup { dup 1- fact * } { 1 } cond } :fact
|
|
5 fact .
|
|
\end{verbatim}
|
|
|
|
However, some vector variables must be modified more than once, for instance, to modify the behavior of the comparison word {\tt less} in a merge sort algorithm:
|
|
\begin{verbatim}
|
|
{ hole dup 1 { @ execute } does create 1 ' ! does create
|
|
} : vector-set
|
|
vector-set sort :sort
|
|
vector-set merge :merge
|
|
vector-set less :less
|
|
{ null null rot
|
|
{ dup null? not }
|
|
{ uncons swap rot cons -rot } while drop
|
|
} : split
|
|
{ dup null? { drop } {
|
|
over null? { nip } {
|
|
over car over car less ' swap if
|
|
uncons rot merge cons
|
|
} cond
|
|
} cond
|
|
} :merge
|
|
{ dup null? {
|
|
dup cdr null? {
|
|
split sort swap sort merge
|
|
} ifnot
|
|
} ifnot
|
|
} :sort
|
|
forget :merge
|
|
forget :sort
|
|
// set `less` to compare numbers, sort a list of numbers
|
|
' < :less
|
|
3 1 4 1 5 9 2 6 5 9 list
|
|
dup .l cr sort .l cr
|
|
// set `less` to compare strings, sort a list of strings
|
|
{ $cmp 0< } :less
|
|
"once" "upon" "a" "time" "there" "lived" "a" "kitten" 8 list
|
|
dup .l cr sort .l cr
|
|
\end{verbatim}
|
|
producing the following output:
|
|
\begin{verbatim}
|
|
(3 1 4 1 5 9 2 6 5)
|
|
(1 1 2 3 4 5 5 6 9)
|
|
("once" "upon" "a" "time" "there" "lived" "a" "kitten")
|
|
("a" "a" "kitten" "lived" "once" "there" "time" "upon")
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Throwing exceptions}\label{p:exception.ops}
|
|
Two built-in words are used to throw exceptions:
|
|
\begin{itemize}
|
|
\item {\tt abort} ($S$ -- ), throws an exception with an error message taken from {\em String\/} $S$.
|
|
\item {\tt abort"$\langle\textit{message}\rangle$"} ($x$ -- ), throws an exception with the error message $\langle\textit{message}\rangle$ if $x$ is a non-zero integer.
|
|
\end{itemize}
|
|
The exception thrown by these words is represented by the C++ exception {\tt fift::IntError} with its value equal to the specified string. It is normally handled within the Fift interpreter itself by aborting all execution up to the top level and printing a message with the name of the source file being interpreted, the line number, the currently interpreted word, and the specified error message. For instance:
|
|
\begin{verbatim}
|
|
{ dup 0= abort"Division by zero" / } : safe/
|
|
5 0 safe/ .
|
|
\end{verbatim}
|
|
prints ``{\tt safe/: Division by zero}'', without the usual ``{\tt ok}''. The stack is cleared in the process.
|
|
|
|
Incidentally, when the Fift interpreter encounters an unknown word that cannot be parsed as an integer literal, an exception with the message ``{\tt -?}'' is thrown, with the effect indicated above, including the stack being cleared.
|
|
|
|
\mysection{Dictionary, interpreter, and compiler}\label{s:dict.compiler}
|
|
In this chapter we present several specific Fift words for dictionary manipulation and compiler control. The ``compiler'' is the part of the Fift interpreter that builds lists of word references (represented by {\em WordList\/} stack values) from word names; it is activated by the primitive ``{\tt \{}'' employed for defining blocks as explained in~\ptref{p:colon.def} and~\ptref{p:blocks}.
|
|
|
|
Most of the information included in this chapter is rather sophisticated and may be skipped during a first reading. However, the techniques described here are heavily employed by the Fift assembler, used to compile TVM code. Therefore, this section is indispensable if one wishes to understand the current implementation of the Fift assembler.
|
|
|
|
\mysubsection{The state of the Fift interpreter}\label{sp:fift.state}
|
|
The state of the Fift interpreter is controlled by an internal integer variable called {\tt state}, currently unavailable from Fift itself. When {\tt state} is zero, all words parsed from the input (i.e., the Fift source file or the standard input in the interactive mode) are looked up in the dictionary and immediately executed afterwards. When {\tt state} is positive, the words found in the dictionary are not executed. Instead, they (or rather the references to their current definitions) are {\em compiled}, i.e., added to the end of the {\em WordList\/} being constructed.
|
|
|
|
Typically, {\tt state} equals the number of the currently open blocks. For instance, after interpreting ``{\tt \{ 0= \{ ."zero"}'' the {\tt state} variable will be equal to two, because there are two nested blocks. The {\em WordList\/} being constructed is kept at the top of the stack.
|
|
|
|
The primitive ``{\tt \{}'' simply pushes a new empty {\em WordList\/} into the stack, and increases {\tt state} by one. The primitive ``{\tt \}}'' throws an exception if {\tt state} is already zero; otherwise it decreases {\tt state} by one, and leaves the resulting {\em WordList\/} in the stack, representing the block just constructed.\footnote{The word {\tt \}} also transforms this {\em WordList\/} into a {\em WordDef}, which has a different type tag and therefore is a different Fift value, even if the same underlying C++ object is used by the C++ implementation.} After that, if the resulting value of {\tt state} is non-zero, the new block is compiled as a literal (unnamed constant) into the encompassing block.
|
|
|
|
\mysubsection{Active and ordinary words}\label{p:active.words}
|
|
All dictionary words have a special flag indicating whether they are {\em active\/} words or {\em ordinary\/} words. By default, all words are ordinary. In particular, all words defined with the aid of ``{\tt :}'' and {\tt constant} are ordinary.
|
|
|
|
When the Fift interpreter finds a word definition in the dictionary, it checks whether it is an ordinary word. If it is, then the current word definition is either executed (if {\tt state} is zero) or ``compiled'' (if {\tt state} is greater than zero) as explained in~\ptref{sp:fift.state}.
|
|
|
|
On the other hand, if the word is active, then it is always executed, even if {\tt state} is positive. An active word is expected to leave some values $x_1$ \dots $x_n$ $n$ $e$ in the stack, where $n\geq 0$ is an integer, $x_1\dots x_n$ are $n$ values of arbitrary types, and $e$ is an execution token (a value of type {\em WordDef\/}). After that, the interpreter performs different actions depending on {\tt state}: if {\tt state} is zero, then $n$ is discarded and $e$ is executed, as if a {\tt nip execute} phrase were found. If {\tt state} is non-zero, then this collection is ``compiled'' in the current {\em WordList} (located immediately below $x_1$ in the stack) in the same way as if the {\tt (compile)} primitive were invoked. This compilation amounts to adding some code to the end of the current {\em WordList\/} that would push $x_1$, \dots, $x_n$ into the stack when invoked, and then adding a reference to $e$ (representing a delayed execution of $e$). If $e$ is equal to the special value {\tt 'nop}, representing an execution token that does nothing when executed, then this last step is omitted.
|
|
|
|
\mysubsection{Compiling literals}
|
|
When the Fift interpreter encounters a word that is absent from the dictionary, it invokes the primitive {\tt (number)} to attempt to parse it as an integer or fractional literal. If this attempt succeeds, then the special value {\tt 'nop} is pushed, and the interpretation proceeds in the same way as if an active word were encountered. In other words, if {\tt state} is zero, then the literal is simply left in the stack; otherwise, {\tt (compile)} is invoked to modify the current {\em WordList\/} so that it would push the literal when executed.
|
|
|
|
\mysubsection{Defining new active words}\label{p:def.active}
|
|
New active words are defined similarly to new ordinary words, but using ``{\tt ::}'' instead of ``{\tt :}''. For instance,
|
|
\begin{verbatim}
|
|
{ bl word 1 ' type } :: say
|
|
\end{verbatim}
|
|
defines the active word {\tt say}, which scans the next blank-separated word after itself and compiles it as a literal along with a reference to the current definition of {\tt type} into the current {\em WordList} (if {\tt state} is non-zero, i.e., if the Fift interpreter is compiling a block). When invoked, this addition to the block will push the stored string into the stack and execute {\tt type}, thus printing the next word after {\tt say}. On the other hand, if {\tt state} is zero, then these two actions are performed by the Fift interpreter immediately. In this way,
|
|
\begin{verbatim}
|
|
1 2 say hello + .
|
|
\end{verbatim}
|
|
will print ``{\tt hello3 ok}'', while
|
|
\begin{verbatim}
|
|
{ 2 say hello + . } : test
|
|
1 test 4 test
|
|
\end{verbatim}
|
|
will print ``{\tt hello3 hello6 ok}''.
|
|
|
|
Of course, a block may be used to represent the required action instead of {\tt ' type}. For instance, if we want a version of {\tt say} that prints a space after the stored word, we can write
|
|
\begin{verbatim}
|
|
{ bl word 1 { type space } } :: say
|
|
{ 2 say hello + . } : test
|
|
1 test 4 test
|
|
\end{verbatim}
|
|
to obtain ``{\tt hello 3 hello 6 ok}''.
|
|
|
|
Incidentally, the words {\tt "} (introducing a string literal) and {\tt ."} (printing a string literal) can be defined as follows:
|
|
\begin{verbatim}
|
|
{ char " word 1 'nop } ::_ "
|
|
{ char " word 1 ' type } ::_ ."
|
|
\end{verbatim}
|
|
The new defining word ``{\tt ::\_}'' defines an active {\em prefix\/} word, i.e., an active word that does not require a space afterwards.
|
|
|
|
\mysubsection{Defining words and dictionary manipulation}\label{p:dict.create}
|
|
{\em Defining words\/} are words that define new words in the Fift dictionary. For instance, ``{\tt :}'', ``{\tt ::\_}'', and {\tt constant} are defining words. All of these defining words might have been defined using the primitive {\tt (create)}; in fact, the user can introduce custom defining words if so desired. Let us list some defining words and dictionary manipulation words:
|
|
\begin{itemize}
|
|
\item {\tt create $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new ordinary word with the name equal to the next word scanned from the input, using {\em WordDef\/} $e$ as its definition. If the word already exists, it is tacitly redefined.
|
|
\item {\tt (create)} ($e$ $S$ $x$ -- ), creates a new word with the name equal to {\em String\/} $S$ and definition equal to {\em WordDef\/}~$e$, using flags passed in {\em Integer\/} $0\leq x\leq 3$. If bit $+1$ is set in $x$, creates an active word; if bit $+2$ is set in $x$, creates a prefix word.
|
|
\item {\tt : $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new ordinary word $\langle\textit{word-name}\rangle$ in the dictionary using {\em WordDef} $e$ as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.
|
|
\item {\tt forget $\langle\textit{word-name}\rangle$} ( -- ), forgets (removes from the dictionary) the definition of the specified word.
|
|
\item {\tt (forget)} ($S$ -- ), forgets the word with the name specified in {\em String}~$S$. If the word is not found, throws an exception.
|
|
\item {\tt :\_ $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new ordinary {\em prefix\/} word $\langle\textit{word-name}\rangle$, meaning that a blank or an end-of-line character is not required by the Fift input parser after the word name. In all other respects it is similar to ``{\tt:}''.
|
|
\item {\tt :: $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new {\em active\/} word $\langle\textit{word-name}\rangle$ in the dictionary using {\em WordDef} $e$ as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.
|
|
\item {\tt ::\_ $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new active {\em prefix\/} word $\langle\textit{word-name}\rangle$, meaning that a blank or an end-of-line character is not required by the Fift input parser after the word name. In all other respects it is similar to ``{\tt::}''.
|
|
\item {\tt constant $\langle\textit{word-name}\rangle$} ($x$ -- ), defines a new ordinary word $\langle\textit{word-name}\rangle$ that would push the given value $x$ when invoked.
|
|
\item {\tt 2constant $\langle\textit{word-name}\rangle$} ($x$ $y$ -- ), defines a new ordinary word named $\langle\textit{word-name}\rangle$ that would push the given values $x$ and $y$ (in that order) when invoked.
|
|
\item {\tt =: $\langle\textit{word-name}\rangle$} ($x$ -- ), defines a new ordinary word $\langle\textit{word-name}\rangle$ that would push the given value $x$ when invoked, similarly to {\tt constant}, but works inside blocks and colon definitions.
|
|
\item {\tt 2=: $\langle\textit{word-name}\rangle$} ($x$ $y$ -- ), defines a new ordinary word $\langle\textit{word-name}\rangle$ that would push the given values $x$ and $y$ (in that order) when invoked, similarly to {\tt 2constant}, but works inside blocks and colon definitions.
|
|
\end{itemize}
|
|
Notice that most of the above words might have been defined in terms of {\tt (create)}:
|
|
\begin{verbatim}
|
|
{ bl word 1 2 ' (create) } "::" 1 (create)
|
|
{ bl word 0 2 ' (create) } :: :
|
|
{ bl word 2 2 ' (create) } :: :_
|
|
{ bl word 3 2 ' (create) } :: ::_
|
|
{ bl word 0 (create) } : create
|
|
{ bl word (forget) } : forget
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Dictionary lookup}\label{p:dict.lookup}
|
|
The following words can be used to look up words in the dictionary:
|
|
\begin{itemize}
|
|
\item {\tt ' $\langle\textit{word-name}\rangle$} ( -- $e$), pushes the definition of the word $\langle\textit{word-name}\rangle$, recovered at the compile time. If the indicated word is not found, throws an exception. Notice that {\tt ' $\langle\textit{word-name}\rangle$ execute} is always equivalent to {\tt $\langle\textit{word-name}\rangle$} for ordinary words, but not for active words.
|
|
\item {\tt nop} ( -- ), does nothing.
|
|
\item {\tt 'nop} ( -- $e$), pushes the default definition of {\tt nop}---an execution token that does nothing when executed.
|
|
\item {\tt find} ($S$ -- $e$ $-1$ or $e$ $1$ or $0$), looks up {\em String\/} $S$ in the dictionary and returns its definition as a {\em WordDef\/}~$e$ if found, followed by $-1$ for ordinary words or $1$ for active words. Otherwise pushes $0$.
|
|
\item {\tt (') $\langle\textit{word-name}\rangle$} ( -- $e$), similar to {\tt '}, but returns the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked. May be used to recover current values of constants inside word definitions and other blocks by using the phrase {\tt (') $\langle\textit{word-name}\rangle$ execute}.
|
|
\item {\tt @' $\langle\textit{word-name}\rangle$} ( -- $e$), similar to {\tt (')}, but recovers the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked, and then executes this definition. May be used to recover current values of constants inside word definitions and other blocks by using the phrase {\tt @' $\langle\textit{word-name}\rangle$}, equivalent to {\tt (') $\langle\textit{word-name}\rangle$ execute}, cf.~\ptref{p:constants}.
|
|
\item {\tt [compile] $\langle\textit{word-name}\rangle$} ( -- ), compiles $\langle\textit{word-name}\rangle$ as if it were an ordinary word, even if it is active. Essentially equivalent to {\tt ' $\langle\textit{word-name}\rangle$ execute}.
|
|
\item {\tt words} ( -- ), prints the names of all words currently defined in the dictionary.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Creating and manipulating word lists}\label{p:wordlist.ops}
|
|
In the Fift stack, lists of references to word definitions and literals, to be used as blocks or word definitions, are represented by the values of the type {\em WordList}. Some words for manipulating {\em WordList\/}s include:
|
|
\begin{itemize}
|
|
\item {\tt \{} ( -- $l$), an active word that increases internal variable {\tt state} by one and pushes a new empty {\em WordList\/} into the stack.
|
|
\item {\tt \}} ($l$ -- $e$), an active word that transforms a {\em WordList} $l$ into a {\em WordDef\/} (an execution token) $e$, thus making all further modifications of~$l$ impossible, and decreases internal variable {\tt state} by one and pushes the integer $1$, followed by a {\tt 'nop}. The net effect is to transform the constructed {\em WordList\/} into an execution token and push this execution token into the stack, either immediately or during the execution of an outer block.
|
|
\item {\tt (\{)} ( -- $l$), pushes an empty {\em WordList\/} into the stack.
|
|
\item {\tt (\})} ($l$ -- $e$), transforms a {\em WordList\/} into an execution token, making all further modifications impossible.
|
|
\item {\tt (compile)} ($l$ $x_1$ \dots $x_n$ $n$ $e$ -- $l'$), extends {\em WordList\/}~$l$ so that it would push $0\leq n\leq 255$ values $x_1$, \ldots, $x_n$ into the stack and execute the execution token $e$ when invoked, where $0\leq n\leq 255$ is an {\em Integer}. If $e$ is equal to the special value {\tt 'nop}, the last step is omitted.
|
|
\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$. It is roughly equivalent to a combination of {\tt (\{)}, {\tt (compile)}, and {\tt (\})}.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Custom defining words}\label{p:custom.defw}
|
|
The word {\tt does} is actually defined in terms of simpler words:
|
|
\begin{verbatim}
|
|
{ swap ({) over 2+ -roll swap (compile) (}) } : does
|
|
\end{verbatim}
|
|
It is especially useful for defining custom defining words. For instance, {\tt constant} and {\tt 2constant} may be defined with the aid of {\tt does} and {\tt create}:
|
|
\begin{verbatim}
|
|
{ 1 'nop does create } : constant
|
|
{ 2 'nop does create } : 2constant
|
|
\end{verbatim}
|
|
Of course, non-trivial actions may be performed by the words defined by means of such custom defining words. For instance,
|
|
\begin{verbatim}
|
|
{ 1 { type space } does create } : says
|
|
"hello" says hello
|
|
"unknown error" says error
|
|
{ hello error } : test
|
|
test
|
|
\end{verbatim}
|
|
will print ``{\tt hello unknown error ok}'', because {\tt hello} is defined by means of a custom defining word {\tt says} to print ``{\tt hello}'' whenever invoked, and similarly {\tt error} prints ``{\tt unknown error}'' when invoked. The above definitions are essentially equivalent to
|
|
\begin{verbatim}
|
|
{ ."hello" } : hello
|
|
{ ."unknown error" } : error
|
|
\end{verbatim}
|
|
However, custom defining words may perform more sophisticated actions when invoked, and preprocess their arguments at compile time. For instance, the message can be computed in a non-trivial fashion:
|
|
\begin{verbatim}
|
|
"Hello, " "world!" $+ says hw
|
|
\end{verbatim}
|
|
defines word {\tt hw}, which prints ``Hello, world!'' when invoked. The string with this message is computed once at compile time (when {\tt says} is invoked), not at execution time (when {\tt hw} is invoked).
|
|
|
|
\mysection{Cell manipulation}
|
|
We have discussed the basic Fift primitives not related to TVM or the TON Blockchain so far. Now we will turn to TON-specific words, used to manipulate {\em Cell\/}s.
|
|
|
|
\mysubsection{Slice literals}\label{p:slice.lit}
|
|
Recall that a (TVM) {\em Cell\/} consists of at most 1023 data bits and at most four references to other {\em Cell\/}s, a {\em Slice\/} is a read-only view of a portion of a {\em Cell}, and a {\em Builder\/} is used to create new {\em Cell\/}s. Fift has special provisions for defining {\em Slice\/} literals (i.e., unnamed constants), which can also be transformed into {\em Cells\/} if necessary.
|
|
|
|
{\em Slice\/} literals are introduced by means of active prefix words {\tt x\{} and {\tt b\{}:
|
|
\begin{itemize}
|
|
\item {\tt b\{$\langle\textit{binary-data}\rangle$\}} ( -- $s$), creates a {\em Slice}~$s$ that contains no references and up to 1023 data bits specified in $\langle\textit{binary-data}\rangle$, which must be a string consisting only of the characters `{\tt 0}' and `{\tt 1}'.
|
|
\item {\tt x\{$\langle\textit{hex-data}\rangle$\}} ( -- $s$), creates a {\em Slice}~$s$ that contains no references and up to 1023 data bits specified in $\langle\textit{hex-data}\rangle$. More precisely, each hex digit from $\langle\textit{hex-data}\rangle$ is transformed into four binary digits in the usual fashion. After that, if the last character of $\langle\textit{hex-data}\rangle$ is an underscore {\tt \_}, then all trailing binary zeroes and the binary one immediately preceding them are removed from the resulting binary string (cf.~\cite[1.0]{TVM} for more details).
|
|
\end{itemize}
|
|
In this way, {\tt b\{00011101\}} and {\tt x\{1d\}} both push the same {\em Slice} consisting of eight data bits and no references. Similarly, {\tt b\{111010\}} and {\tt x\{EA\_\}} push the same {\em Slice\/} consisting of six data bits. An empty {\em Slice} can be represented as {\tt b\{\}} or {\tt x\{\}}.
|
|
|
|
If one wishes to define constant {\em Slice}\/s with some {\em Cell\/} references, the following words might be used:
|
|
\begin{itemize}
|
|
\item {\tt |\_} ($s$ $s'$ -- $s''$), given two {\em Slice}\/s $s$ and $s'$, creates a new {\em Slice} $s''$, which is obtained from $s$ by appending a new reference to a {\em Cell\/} containing $s'$.
|
|
\item {\tt |+} ($s$ $s'$ -- $s''$), concatenates two {\em Slice}\/s $s$ and $s'$. This means that the data bits of the new {\em Slice} $s''$ are obtained by concatenating the data bits of $s$ and $s'$, and the list of {\em Cell\/} references of $s''$ is constructed similarly by concatenating the corresponding lists for $s$ and $s'$.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Builder primitives}\label{p:builder.ops}
|
|
The following words can be used to manipulate {\em Builder\/}s, which can later be used to construct new {\em Cell\/}s:
|
|
\begin{itemize}
|
|
\item {\tt <b} ( -- $b$), creates a new empty {\em Builder}.
|
|
\item {\tt b>} ($b$ -- $c$), transforms a {\em Builder\/}~$b$ into a new {\em Cell\/}~$c$ containing the same data as~$b$.
|
|
\item {\tt i,} ($b$ $x$ $y$ -- $b'$), appends the big-endian binary representation of a signed $y$-bit integer~$x$ to {\em Builder\/}~$b$, where $0\leq y\leq 257$. If there is not enough room in $b$ (i.e., if $b$ already contains more than $1023-y$ data bits), or if {\em Integer\/}~$x$ does not fit into $y$ bits, an exception is thrown.
|
|
\item {\tt u,} ($b$ $x$ $y$ -- $b'$), appends the big-endian binary representation of an unsigned $y$-bit integer~$x$ to {\em Builder\/}~$b$, where $0\leq y\leq 256$. If the operation is impossible, an exception is thrown.
|
|
\item {\tt ref,} ($b$ $c$ -- $b'$), appends to {\em Builder\/}~$b$ a reference to {\em Cell\/}~$c$. If $b$ already contains four references, an exception is thrown.
|
|
\item {\tt s,} ($b$ $s$ -- $b'$), appends data bits and references taken from {\em Slice\/}~$s$ to {\em Builder\/}~$b$.
|
|
\item {\tt sr,} ($b$ $s$ -- $b'$), constructs a new {\em Cell\/} containing all data and references from {\em Slice\/}~$s$, and appends a reference to this cell to {\em Builder\/}~$b$. Equivalent to {\tt <b swap s, b> ref,}.
|
|
\item {\tt \$,} ($b$ $S$ -- $b'$), appends {\em String\/}~$S$ to {\em Builder\/}~$b$. The string is interpreted as a binary string of length $8n$, where $n$ is the number of bytes in the UTF-8 representation of~$S$.
|
|
\item {\tt B,} ($b$ $B$ -- $b'$), appends {\em Bytes\/}~$B$ to {\em Builder\/}~$b$.
|
|
\item {\tt b+} ($b$ $b'$ -- $b''$), concatenates two {\em Builders\/} $b$ and~$b'$.
|
|
\item {\tt bbits} ($b$ -- $x$), returns the number of data bits already stored in {\em Builder\/}~$b$. The result $x$ is an {\em Integer\/} in the range $0\dots1023$.
|
|
\item {\tt brefs} ($b$ -- $x$), returns the number of references already stored in {\em Builder\/}~$b$. The result $x$ is an {\em Integer\/} in the range $0\dots4$.
|
|
\item {\tt bbitrefs} ($b$ -- $x$ $y$), returns both the number of data bits $x$ and the number of references $y$ already stored in {\em Builder\/}~$b$.
|
|
\item {\tt brembits} ($b$ -- $x$), returns the maximum number of additional data bits that can be stored in {\em Builder\/}~$b$. Equivalent to {\tt bbits 1023 swap -}.
|
|
\item {\tt bremrefs} ($b$ -- $x$), returns the maximum number of additional cell references that can be stored in {\em Builder\/}~$b$.
|
|
\item {\tt brembitrefs} ($b$ -- $x$ $y$), returns both the maximum number of additional data bits $0\leq x\leq 1023$ and the maximum number of additional cell references $0\leq y\leq 4$ that can be stored in {\em Builder\/}~$b$.
|
|
\end{itemize}
|
|
|
|
The resulting {\em Builder\/} may be inspected by means of the non-destructive stack dump primitive {\tt .s}, or by the phrase {\tt b> <s csr.}. For instance:
|
|
\begin{verbatim}
|
|
{ <b x{4A} s, rot 16 u, swap 32 i, .s b> } : mkTest
|
|
17239 -1000000001 mkTest
|
|
<s csr.
|
|
\end{verbatim}
|
|
outputs
|
|
\begin{verbatim}
|
|
BC{000e4a4357c46535ff}
|
|
ok
|
|
x{4A4357C46535FF}
|
|
ok
|
|
\end{verbatim}
|
|
One can observe that {\tt .s} dumps the internal representation of a {\em Builder}, with two tag bytes at the beginning (usually equal to the number of cell references already stored in the {\em Builder}, and to twice the number of complete bytes stored in the {\em Builder}, increased by one if an incomplete byte is present). On the other hand, {\tt csr.\ }dumps a {\em Slice\/} (constructed from a {\em Cell\/} by {\tt <s}, cf.~\ptref{p:slice.ops}) in a form similar to that used by {\tt x\{} to define {\em Slice\/} literals (cf.~\ptref{p:slice.lit}).
|
|
|
|
Incidentally, the word {\tt mkTest} shown above (without the {\tt .s} in its definition) corresponds to the TL-B constructor
|
|
\begin{verbatim}
|
|
test#4a first:uint16 second:int32 = Test;
|
|
\end{verbatim}
|
|
and may be used to serialize values of this TL-B type.
|
|
|
|
\mysubsection{Slice primitives}\label{p:slice.ops}
|
|
The following words can be used to manipulate values of the type {\em Slice\/}, which represents a read-only view of a portion of a {\em Cell}. In this way data previously stored into a {\em Cell\/} may be deserialized, by first transforming a {\em Cell\/} into a {\em Slice}, and then extracting the required data from this {\em Slice\/} step-by-step.
|
|
\begin{itemize}
|
|
\item {\tt <s} ($c$ -- $s$), transforms a {\em Cell\/}~$c$ into a {\em Slice\/}~$s$ containing the same data. It usually marks the start of the deserialization of a cell.
|
|
\item {\tt s>} ($s$ -- ), throws an exception if {\em Slice\/}~$s$ is non-empty. It usually marks the end of the deserialization of a cell, checking whether there are any unprocessed data bits or references left.
|
|
\item {\tt i@} ($s$ $x$ -- $y$), fetches a signed big-endian $x$-bit integer from the first $x$ bits of {\em Slice}~$s$. If $s$ contains less than $x$ data bits, an exception is thrown.
|
|
\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.
|
|
\item {\tt i@?} ($s$ $x$ -- $y$ $-1$ or $0$), fetches a signed integer from a {\em Slice\/} similarly to {\tt i@}, but pushes integer $-1$ afterwards on success. 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 integer from {\em Slice\/}~$s$ and computes the remainder of this {\em Slice\/} similarly to {\tt i@+}, but pushes $-1$ afterwards to indicate success. On failure, pushes the unchanged {\em Slice\/}~$s$ and $0$ to indicate failure.
|
|
\item {\tt u@}, {\tt u@+}, {\tt u@?}, {\tt u@?+}, counterparts of {\tt i@}, {\tt i@+}, {\tt i@?}, {\tt i@?+} for deserializing unsigned integers.
|
|
\item {\tt B@} ($s$ $x$ -- $B$), fetches first $x$ bytes (i.e., $8x$ bits) from {\em Slice}~$s$, and returns them as a {\em Bytes\/} value~$B$. If there are not enough data bits in $s$, throws an exception.
|
|
\item {\tt B@+} ($s$ $x$ -- $B$ $s'$), similar to {\tt B@}, but returns the remainder of {\em Slice\/} $s$ as well.
|
|
\item {\tt B@?} ($s$ $x$ -- $B$ $-1$ or $0$), similar to {\tt B@}, but uses a flag to indicate failure instead of throwing an exception.
|
|
\item {\tt B@?+} ($s$ $x$ -- $B$ $s'$ $-1$ or $s$ $0$), similar to {\tt B@+}, but uses a flag to indicate failure instead of throwing an exception.
|
|
\item {\tt \$@}, {\tt \$@+}, {\tt \$@?}, {\tt \$@?+}, counterparts of {\tt B@}, {\tt B@+}, {\tt B@?}, {\tt B@?+}, returning the result as a (UTF-8) {\em String} instead of a {\em Bytes} value. These primitives do not check whether the byte sequence read is a valid UTF-8 string.
|
|
\item {\tt ref@} ($s$ -- $c$), fetches the first reference from {\em Slice\/}~$s$ and returns the {\em Cell}~$c$ referred to. If there are no references left, throws an exception.
|
|
\item {\tt ref@+} ($s$ -- $s'$ $c$), similar to {\tt ref@}, but returns the remainder of $s$ as well.
|
|
\item {\tt ref@?} ($s$ -- $c$ $-1$ or $0$), similar to {\tt ref@}, but uses a flag to indicate failure instead of throwing an exception.
|
|
\item {\tt ref@?+} ($s$ -- $s'$ $c$ $-1$ or $s$ $0$), similar to {\tt ref@+}, but uses a flag to indicate failure instead of throwing an exception.
|
|
\item {\tt empty?} ($s$ -- $?$), checks whether a {\em Slice\/} is empty (i.e., has no data bits and no references left), and returns $-1$ or $0$ accordingly.
|
|
\item {\tt remaining} ($s$ -- $x$ $y$), returns both the number of data bits $x$ and the number of cell references $y$ remaining in {\em Slice\/}~$s$.
|
|
\item {\tt sbits} ($s$ -- $x$), returns the number of data bits $x$ remaining in {\em Slice\/}~$s$.
|
|
\item {\tt srefs} ($s$ -- $x$), returns the number of cell references $x$ remaining in {\em Slice\/}~$s$.
|
|
\item {\tt sbitrefs} ($s$ -- $x$ $y$), returns both the number of data bits $x$ and the number of cell references $y$ remaining in {\em Slice\/}~$s$. Equivalent to {\tt remaining}.
|
|
\item {\tt \$>s} ($S$ -- $s$), transforms {\em String}~$S$ into a {\em Slice}. Equivalent to {\tt <b swap \$, b> <s}.
|
|
\item {\tt s>c} ($s$ -- $c$), creates a {\em Cell}~$c$ directly from a {\em Slice}~$s$. Equivalent to {\tt <b swap s, b>}.
|
|
\item {\tt csr.} ($s$ -- ), recursively prints a {\em Slice}~$s$. 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.
|
|
\end{itemize}
|
|
For instance, values of the TL-B type {\tt Test} discussed in~\ptref{p:builder.ops}
|
|
\begin{verbatim}
|
|
test#4a first:uint16 second:int32 = Test;
|
|
\end{verbatim}
|
|
may be deserialized as follows:
|
|
\begin{verbatim}
|
|
{ <s 8 u@+ swap 0x4a <> abort"constructor tag mismatch"
|
|
16 u@+ 32 i@+ s> } : unpackTest
|
|
x{4A4357C46535FF} s>c unpackTest swap . .
|
|
\end{verbatim}
|
|
prints ``{\tt 17239 -1000000001 ok}'' as expected.
|
|
|
|
Of course, if one needs to check constructor tags often, a helper word can be defined for this purpose:
|
|
\begin{verbatim}
|
|
{ dup remaining abort"references in constructor tag"
|
|
tuck u@ -rot u@+ -rot <> abort"constructor tag mismatch"
|
|
} : tag?
|
|
{ <s x{4a} tag? 16 u@+ 32 i@+ s> } : unpackTest
|
|
x{4A4357C46535FF} s>c unpackTest swap . .
|
|
\end{verbatim}
|
|
We can do even better with the aid of active prefix words (cf.~\ptref{p:active.words} and~\ptref{p:def.active}):
|
|
\begin{verbatim}
|
|
{ dup remaining abort"references in constructor tag"
|
|
dup 256 > abort"constructor tag too long"
|
|
tuck u@ 2 { -rot u@+ -rot <> abort"constructor tag mismatch" }
|
|
} : (tagchk)
|
|
{ [compile] x{ 2drop (tagchk) } ::_ ?x{
|
|
{ [compile] b{ 2drop (tagchk) } ::_ ?b{
|
|
{ <s ?x{4a} 16 u@+ 32 i@+ s> } : unpackTest
|
|
x{4A4357C46535FF} s>c unpackTest swap . .
|
|
\end{verbatim}
|
|
A shorter but less efficient solution would be to reuse the previously defined {\tt tag?}:
|
|
\begin{verbatim}
|
|
{ [compile] x{ drop ' tag? } ::_ ?x{
|
|
{ [compile] b{ drop ' tag? } ::_ ?b{
|
|
x{11EF55AA} ?x{11E} dup csr.
|
|
?b{110} csr.
|
|
\end{verbatim}
|
|
first outputs ``{\tt x\{F55AA\}}'', and then throws an exception with the message ``constructor tag mismatch''.
|
|
|
|
\mysubsection{Cell hash operations}\label{p:hash.ops}
|
|
There are few words that operate on {\em Cell\/}s directly. The most important of them computes the {\em ($\Sha$-based) representation hash\/} of a given cell (cf.~\cite[3.1]{TVM}), which can be roughly described as the $\Sha$ hash of the cell's data bits concatenated with recursively computed hashes of the cells referred to by this cell:
|
|
\begin{itemize}
|
|
\item {\tt hash} ($c$ -- $B$), computes the $\Sha$-based representation hash of {\em Cell\/}~$c$ (cf.~\cite[3.1]{TVM}), which unambiguously defines $c$ and all its descendants (provided there are no collisions for $\Sha$). The result is returned as a {\em Bytes\/} value consisting of exactly 32 bytes.
|
|
\item {\tt shash} ($s$ -- $B$), computes the $\Sha$-based representation hash of a {\em Slice\/} by first transforming it into a cell. Equivalent to {\tt s>c hash}.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Bag-of-cells operations}\label{p:boc.ops}
|
|
A {\em bag of cells\/} is a collection of one or more cells along with all their descendants. It can usually be serialized into a sequence of bytes (represented by a {\em Bytes\/} value in Fift) and then saved into a file or transferred by network. Afterwards, it can be deserialized to recover the original cells. The TON Blockchain systematically represents different data structures (including the TON Blockchain blocks) as a tree of cells according to a certain TL-B scheme (cf.~\cite{TBC}, where this scheme is explained in detail), and then these trees of cells are routinely imported into bags of cells and serialized into binary files.
|
|
|
|
Fift words for manipulating bags of cells include:
|
|
\begin{itemize}
|
|
\item {\tt B>boc} ($B$ -- $c$), deserializes a ``standard'' bag of cells (i.e., a bag of cells with exactly one root cell) represented by {\em Bytes} $B$, and returns the root {\em Cell\/} $c$.
|
|
\item {\tt boc+>B} ($c$ $x$ -- $B$), creates and serializes a ``standard'' bag of cells, containing one root {\em Cell\/}~$c$ along with all its descendants. An {\em Integer\/} parameter $0\leq x\leq 31$ is used to pass flags indicating the additional options for bag-of-cells serialization, with individual bits having the following effect:
|
|
\begin{itemize}
|
|
\item $+1$ enables bag-of-cells index creation (useful for lazy deserialization of large bags of cells).
|
|
\item $+2$ includes the CRC32-C of all data into the serialization (useful for checking data integrity).
|
|
\item $+4$ explicitly stores the hash of the root cell into the serialization (so that it can be quickly recovered afterwards without a complete deserialization).
|
|
\item $+8$ stores hashes of some intermediate (non-leaf) cells (useful for lazy deserialization of large bags of cells).
|
|
\item $+16$ stores cell cache bits to control caching of deserialized cells.
|
|
\end{itemize}
|
|
Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON Blockchain external messages) and $x=31$ for large bags of cells (e.g., TON Blockchain blocks).
|
|
\item {\tt boc>B} ($c$ -- $B$), serializes a small ``standard'' bag of cells with root {\em Cell\/}~$c$ and all its descendants. Equivalent to {\tt 0 boc+>B}.
|
|
\end{itemize}
|
|
For instance, the cell created in~\ptref{p:builder.ops} with a value of TL-B {\tt Test} type may be serialized as follows:
|
|
\begin{verbatim}
|
|
{ <b x{4A} s, rot 16 u, swap 32 i, b> } : mkTest
|
|
17239 -1000000001 mkTest boc>B Bx.
|
|
\end{verbatim}
|
|
outputs ``{\tt B5EE9C7201040101000000000900000E4A4357C46535FF ok}''. Here {\tt Bx.} is the word that prints the hexadecimal representation of a {\em Bytes} value.
|
|
|
|
\mysubsection{Binary file I/O and Bytes manipulation}\label{p:bytes.ops}
|
|
The following words can be used to manipulate values of type {\em Bytes\/} (arbitrary byte sequences) and to read them from or write them into binary files:
|
|
\begin{itemize}
|
|
\item {\tt B\{$\langle{\textit{hex-digits}}\rangle$\}} ( -- $B$), pushes a {\em Bytes} literal containing data represented by an even number of hexadecimal digits.
|
|
\item {\tt Bx.} ($B$ -- ), prints the hexadecimal representation of a {\em Bytes\/} value. Each byte is represented by exactly two uppercase hexadecimal digits.
|
|
\item {\tt file>B} ($S$ -- $B$), reads the (binary) file with the name specified in {\em String\/}~$S$ and returns its contents as a {\em Bytes\/} value. If the file does not exist, an exception is thrown.
|
|
\item {\tt B>file} ($B$ $S$ -- ), creates a new (binary) file with the name specified in {\em String\/}~$S$ and writes data from {\em Bytes}~$B$ into the new file. If the specified file already exists, it is overwritten.
|
|
\item {\tt file-exists?} ($S$ -- $?$), checks whether the file with the name specified in {\em String\/}~$S$ exists.
|
|
\end{itemize}
|
|
For instance, the bag of cells created in the example in~\ptref{p:boc.ops} can be saved to disk as {\tt sample.boc} as follows:
|
|
\begin{verbatim}
|
|
{ <b x{4A} s, rot 16 u, swap 32 i, b> } : mkTest
|
|
17239 -1000000001 mkTest boc>B "sample.boc" B>file
|
|
\end{verbatim}
|
|
It can be loaded and deserialized afterwards (even in another Fift session) by means of {\tt file>B} and {\tt B>boc}:
|
|
\begin{verbatim}
|
|
{ <s 8 u@+ swap 0x4a <> abort"constructor tag mismatch"
|
|
16 u@+ 32 i@+ s> } : unpackTest
|
|
"sample.boc" file>B B>boc unpackTest swap . .
|
|
\end{verbatim}
|
|
prints ``{\tt 17239 -1000000001 ok}''.
|
|
|
|
Additionally, there are several words for directly packing (serializing) data into {\em Bytes\/} values, and unpacking (deserializing) them afterwards. They can be combined with {\tt B>file} and {\tt file>B} to save data directly into binary files, and load them afterwards.
|
|
\begin{itemize}
|
|
\item {\tt Blen} ($B$ -- $x$), returns the length of a {\em Bytes\/} value~$B$ in bytes.
|
|
\item {\tt Bhash} ($B$ -- $B'$), computes the $\Sha$ hash of a {\em Bytes\/} value. The hash is returned as a 32-byte {\em Bytes\/} value.
|
|
\item {\tt B=} ($B$ $B'$ -- $?$), checks whether two {\em Bytes\/} sequences are equal.
|
|
\item {\tt Bcmp} ($B$ $B'$ -- $x$), lexicographically compares two {\em Bytes\/} sequences, and returns $-1$, $0$, or $1$, depending on the comparison result.
|
|
\item {\tt B>i@} ($B$ $x$ -- $y$), deserializes the first $x/8$ bytes of a {\em Bytes} value~$B$ as a signed big-endian $x$-bit {\em Integer}~$y$.
|
|
\item {\tt B>i@+} ($B$ $x$ -- $B'$ $y$), deserializes the first $x/8$ bytes of $B$ as a signed big-endian $x$-bit {\em Integer}~$y$ similarly to {\tt B>i@}, but also returns the remaining bytes of~$B$.
|
|
\item {\tt B>u@}, {\tt B>u@+}, variants of {\tt B>i@} and {\tt B>i@+} deserializing unsigned integers.
|
|
\item {\tt B>Li@}, {\tt B>Li@+}, {\tt B>Lu@}, {\tt B>Lu@+}, little-endian variants of {\tt B>i@}, {\tt B>i@+}, {\tt B>u@}, {\tt B>u@+}.
|
|
\item {\tt B|} ($B$ $x$ -- $B'$ $B''$), cuts the first $x$ bytes from a {\em Bytes} value~$B$, and returns both the first $x$ bytes ($B'$) and the remainder ($B''$) as new {\em Bytes} values.
|
|
\item {\tt i>B} ($x$ $y$ -- $B$), stores a signed big-endian $y$-bit {\em Integer}~$x$ into a {\em Bytes} value $B$ consisting of exactly $y/8$ bytes. Integer $y$ must be a multiple of eight in the range $0\ldots256$.
|
|
\item {\tt u>B} ($x$ $y$ -- $B$), stores an unsigned big-endian $y$-bit {\em Integer}~$x$ into a {\em Bytes} value $B$ consisting of exactly $y/8$ bytes, similarly to {\tt i>B}.
|
|
\item {\tt Li>B}, {\tt Lu>B}, little-endian variants of {\tt i>B} and {\tt u>B}.
|
|
\item {\tt B+} ($B'$ $B''$ -- $B$), concatenates two {\em Bytes\/} sequences.
|
|
\end{itemize}
|
|
|
|
\mysection{TON-specific operations}
|
|
This chapter describes the TON-specific Fift words, with the exception of the words used for {\em Cell\/} manipulation, already discussed in the previous chapter.
|
|
|
|
\mysubsection{Ed25519 cryptography}\label{p:ed25519.ops}
|
|
Fift offers an interface to the same Ed25519 elliptic curve cryptography used by TVM, described in Appendix~$A$ of~\cite{TBC}:
|
|
\begin{itemize}
|
|
\item {\tt now} ( -- $x$), returns the current Unixtime as an {\em Integer}.
|
|
\item {\tt newkeypair} ( -- $B$ $B'$), generates a new Ed25519 private/public key pair, and returns both the private key $B$ and the public key $B'$ as 32-byte {\em Bytes\/} values. The quality of the keys is good enough for testing purposes. Real applications must feed enough entropy into OpenSSL PRNG before generating Ed25519 keypairs.
|
|
\item {\tt priv>pub} ($B$ -- $B'$), computes the public key corresponding to a private Ed25519 key. Both the public key~$B'$ and the private key~$B$ are represented by 32-byte {\em Bytes\/} values.
|
|
\item {\tt ed25519\_sign} ($B$ $B'$ -- $B''$), signs data $B$ with the Ed25519 private key $B'$ (a 32-byte {\em Bytes\/} value) and returns the signature as a 64-byte {\em Bytes\/} value~$B''$.
|
|
\item {\tt ed25519\_sign\_uint} ($x$ $B'$ -- $B''$), converts a big-endian unsigned 256-bit integer $x$ into a 32-byte sequence and signs it using the Ed25519 private key $B'$ similarly to {\tt ed25519\_sign}. Equivalent to {\tt swap 256 u>B swap ed25519\_sign}. The integer $x$ to be signed is typically computed as the hash of some data.
|
|
\item {\tt ed25519\_chksign} ($B$ $B'$ $B''$ -- $?$), checks whether $B'$ is a valid Ed25519 signature of data $B$ with the public key $B''$.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Smart-contract address parser}\label{p:smc.addr.ops}
|
|
Two special words can be used to parse TON smart-contract addresses in human-readable (base64 or base64url) forms:
|
|
\begin{itemize}
|
|
\item {\tt smca>\$} ($x$ $y$ $z$ -- $S$), packs a standard TON smart-contract address with workchain $x$ (a signed 32-bit {\em Integer}) and in-workchain address $y$ (an unsigned 256-bit {\em Integer\/}) into a 48-character string $S$ (the human-readable representation of the address) according to flags~$z$. Possible individual flags in~$z$ are: $+1$ for non-bounceable addresses, $+2$ for testnet-only addresses, and $+4$ for base64url output instead of base64.
|
|
\item {\tt \$>smca} ($S$ -- $x$ $y$ $z$ $-1$ or $0$), unpacks a standard TON smart-contract address from its human-readable string representation~$S$. On success, returns the signed 32-bit workchain $x$, the unsigned 256-bit in-workchain address $y$, the flags $z$ (where $+1$ means that the address is non-bounceable, $+2$ that the address is testnet-only), and $-1$. On failure, pushes $0$.
|
|
\end{itemize}
|
|
A sample human-readable smart-contract address could be deserialized and displayed as follows:
|
|
\begin{verbatim}
|
|
"Ef9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfYFX"
|
|
$>smca 0= abort"bad address"
|
|
rot . swap x. . cr
|
|
\end{verbatim}
|
|
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.
|
|
\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 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.
|
|
\end{itemize}
|
|
Fift also offers some support for prefix dictionaries:
|
|
\begin{itemize}
|
|
\item {\tt pfxdict!} ($v$ $k$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds key-value pair $(k,v)$, both represented by {\em Slice\/}s, into a prefix dictionary $s$ with keys of length at most~$n$. On success, returns the modified dictionary $s'$ and $-1$. On failure, returns the original dictionary $s$ and $0$.
|
|
\item {\tt pfxdict!+} ($v$ $k$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds key-value pair $(k,v)$ into prefix dictionary $s$ similarly to {\tt pfxdict!}, but fails if the key already exists.
|
|
\item {\tt pfxdict@} ($k$ $s$ $n$ -- $v$ $-1$ or $0$), looks up key $k$ (represented by a {\em Slice\/}) in the prefix dictionary $s$ with the length of keys limited by $n$ bits. On success, returns the value found $v$ and $-1$. On failure, returns $0$.
|
|
\end{itemize}
|
|
|
|
\mysubsection{Invoking TVM from Fift}\label{p:tvm.ops}
|
|
TVM can be linked with the Fift interpreter. In this case, several Fift primitives become available that can be used to invoke TVM with arguments provided from Fift. The arguments can be prepared in the Fift stack, which is passed in its entirety to the new instance of TVM. The resulting stack and the exit code are passed back to Fift and can be examined afterwards.
|
|
\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 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}.
|
|
\end{itemize}
|
|
For example, one can create an instance of TVM running some simple code as follows:
|
|
\begin{verbatim}
|
|
2 3 9 x{1221} runvmcode .s
|
|
\end{verbatim}
|
|
The TVM stack is initialized by three integers $2$, $3$, and $9$ (in this order; $9$ is the topmost entry), and then the {\em Slice\/} {\tt x\{1221\}} containing 16 data bits and no references is transformed into a TVM continuation and executed. By consulting Appendix~A of~\cite{TVM}, we see that {\tt x\{12\}} is the code of the TVM instruction {\tt XCHG s1, s2}, and that {\tt x\{21\}} is the code of the TVM instruction {\tt OVER} (not to be confused with the Fift primitive {\tt over}, which incidentally has the same effect on the stack). The result of the above execution is:
|
|
\begin{verbatim}
|
|
execute XCHG s1,s2
|
|
execute OVER
|
|
execute implicit RET
|
|
3 2 9 2 0
|
|
ok
|
|
\end{verbatim}
|
|
Here $0$ is the exit code (indicating successful TVM termination), and {\tt 3 2 9 2} is the final TVM stack state.
|
|
|
|
If an unhandled exception is generated during the TVM execution, the code of this exception is returned as the exit code:
|
|
\begin{verbatim}
|
|
2 3 9 x{122} runvmcode .s
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
execute XCHG s1,s2
|
|
handling exception code 6: invalid or too short opcode
|
|
default exception handler, terminating vm with exit code 6
|
|
0 6
|
|
ok
|
|
\end{verbatim}
|
|
Notice that TVM is executed with internal logging enabled, and its log is displayed in the standard output.
|
|
|
|
Simple TVM programs may be represented by {\em Slice\/} literals with the aid of the {\tt x\{\dots\}} construct similarly to the above examples. More sophisticated programs are usually created with the aid of the Fift assembler as explained in the next chapter.
|
|
|
|
\mysection{Using the Fift assembler}
|
|
The {\em Fift assembler\/} is a short program (currently less than 30KiB) written completely in Fift that transforms human-readable mnemonics of TVM instructions into their binary representation. For instance, one could write {\tt <\{ s1 s2 XCHG OVER \}>s} instead of {\tt x\{1221\}} in the example discussed in~\ptref{p:tvm.ops}, provided the Fift assembler has been loaded beforehand (usually by the phrase {\tt "Asm.fif" include}).
|
|
|
|
\mysubsection{Loading the Fift assembler}\label{p:asm.load}
|
|
The Fift assembler is usually located in file {\tt Asm.fif} in the Fift library directory (which usually contains standard Fift library files such as {\tt Fift.fif}). It is typically loaded by putting the phrase {\tt "Asm.fif" include} at the very beginning of a program that needs to use Fift assembler:
|
|
\begin{itemize}
|
|
\item {\tt include} ($S$ -- ), loads and interprets a Fift source file from the path given by {\em String\/}~$S$. 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$.
|
|
\end{itemize}
|
|
The current implementation of the Fift assembler makes heavy use of custom defining words (cf.~\ptref{p:custom.defw}); its source can be studied as a good example of how defining words might be used to write very compact Fift programs (cf.\ also the original edition of~\cite{Brodie}, where a simple 8080 Forth assembler is discussed).
|
|
|
|
In the future, almost all of the words defined by the Fift assembler will be moved to a separate vocabulary (namespace). Currently they are defined in the global namespace, because Fift does not support namespaces yet.
|
|
|
|
\mysubsection{Fift assembler basics}
|
|
The Fift assembler inherits from Fift its postfix operation notation, i.e., the arguments or parameters are written before the corresponding instructions. For instance, the TVM assembler instruction represented as {\tt XCHG s1,s2} in \cite{TVM} is represented in the Fift assembler as {\tt s1 s2 XCHG}.
|
|
|
|
Fift assembler code is usually opened by a special opening word, such as {\tt <\{}, and terminated by a closing word, such as {\tt \}>} or {\tt \}>s}. For instance,
|
|
\begin{verbatim}
|
|
"Asm.fif" include
|
|
<{ s1 s2 XCHG OVER }>s
|
|
csr.
|
|
\end{verbatim}
|
|
compiles two TVM instructions {\tt XCHG s1,s2} and {\tt OVER}, and returns the result as a {\em Slice\/} (because {\tt \}>s} is used). The resulting {\em Slice\/} is displayed by {\tt csr.}, yielding
|
|
\begin{verbatim}
|
|
x{1221}
|
|
\end{verbatim}
|
|
One can use Appendix A of \cite{TVM} and verify that {\tt x\{12\}} is indeed the (codepage zero) code of the TVM instruction {\tt XCHG s1,s2}, and that {\tt x\{21\}} is the code of the TVM instruction {\tt OVER} (not to be confused with Fift primitive {\tt over}).
|
|
|
|
In the future, we will assume that the Fift assember is already loaded and omit the phrase {\tt "Asm.fif" include} from our examples.
|
|
|
|
The Fift assembler uses the Fift stack in a straightforward fashion, using the top several stack entries to hold a {\em Builder\/} with the code being assembled, and the arguments to TVM instructions. For example:
|
|
\begin{itemize}
|
|
\item {\tt <\{} ( -- $b$), begins a portion of Fift assembler code by pushing an empty {\em Builder\/} into the Fift stack (and potentially switching the namespace to the one containing all Fift assembler-specific words). Approximately equivalent to {\tt <b}.
|
|
\item {\tt \}>} ($b$ -- $b'$), terminates a portion of Fift assembler code and returns the assembled portion as a {\em Builder\/} (and potentially recovers the original namespace). Approximately equivalent to {\tt nop} in most situations.
|
|
\item {\tt \}>c} ($b$ -- $c$), terminates a portion of Fift assembler code and returns the assembled portion as a {\em Cell\/} (and potentially recovers the original namespace). Approximately equivalent to {\tt b>}.
|
|
\item {\tt \}>s} ($b$ -- $s$), terminates a portion of Fift assembler code similarly to {\tt \}>}, but returns the assembled portion as a {\em Slice\/}. Equivalent to {\tt \}>c <s}.
|
|
\item {\tt OVER} ($b$ -- $b'$), assembles the code of the TVM instruction {\tt OVER} by appending it to the {\em Builder\/} at the top of the stack. Approximately equivalent to {\tt x\{21\} s,}.
|
|
\item {\tt s1} ( -- $s$), pushes a special {\em Slice\/} used by the Fift assembler to represent the ``stack register'' {\tt s1} of TVM.
|
|
\item {\tt s0}\dots{\tt s15} ( -- $s$), words similar to {\tt s1}, but pushing the {\em Slice\/} representing other ``stack registers'' of TVM. Notice that {\tt s16}\dots{\tt s255} must be accessed using the word {\tt s()}.
|
|
\item {\tt s()} ($x$ -- $s$), takes an {\em Integer\/} argument $0\leq x\leq 255$ and returns a special {\em Slice\/} used by the Fift assembler to represent ``stack register'' ${\texttt s}(x)$.
|
|
\item {\tt XCHG} ($b$ $s$ $s'$ -- $b'$), takes two special {\em Slice\/}s representing two ``stack registers'' ${\texttt s}(i)$ and ${\texttt s}(j)$ from the stack, and appends to {\em Builder\/}~$b$ the code for the TVM instruction {\tt XCHG s$(i)$,s$(j)$}.
|
|
\end{itemize}
|
|
In particular, note that the word {\tt OVER} defined by the Fift assembler has a completely different effect from Fift primitive {\tt over}.
|
|
|
|
The actual action of {\tt OVER} and other Fift assembler words is somewhat more complicated than that of {\tt x\{21\} s,}. If the new instruction code does not fit into the {\em Builder}~$b$ (i.e., if $b$ would contain more than 1023 data bits after adding the new instruction code), then this and all subsequent instructions are assembled into a new {\em Builder\/} $\tilde b$, and the old {\em Builder}~$b$ is augmented by a reference to the {\em Cell\/} obtained from $\tilde b$ once the generation of $\tilde b$ is finished. In this way long stretches of TVM code are automatically split into chains of valid {\em Cell\/}s containing at most 1023 bits each. Because TVM interprets a lonely cell reference at the end of a continuation as an implicit {\tt JMPREF}, this partitioning of TVM code into cells has almost no effect on the execution.
|
|
|
|
\mysubsection{Pushing integer constants}
|
|
The TVM instruction {\tt PUSHINT $x$}, pushing an {\em Integer\/} constant $x$ when invoked, can be assembled with the aid of Fift assembler words {\tt INT} or {\tt PUSHINT}:
|
|
\begin{itemize}
|
|
\item {\tt PUSHINT} ($b$ $x$ -- $b'$), assembles TVM instruction {\tt PUSHINT $x$} into a {\em Builder}.
|
|
\item {\tt INT} ($b$ $x$ -- $b'$), equivalent to {\tt PUSHINT}.
|
|
\end{itemize}
|
|
Notice that the argument to {\tt PUSHINT} is an {\em Integer\/} value taken from the Fift stack and is not necessarily a literal. For instance, {\tt <\{ 239 17 * INT \}>s} is a valid way to assemble a {\tt PUSHINT 4063} instruction, because $239\cdot17=4063$. Notice that the multiplication is performed by Fift during assemble time, not during the TVM runtime. The latter computation might be performed by means of {\tt <\{ 239 INT 17 INT MUL \}>s}:
|
|
\begin{verbatim}
|
|
<{ 239 17 * INT }>s dup csr. runvmcode .s 2drop
|
|
<{ 239 INT 17 INT MUL }>s dup csr. runvmcode .s 2drop
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
x{810FDF}
|
|
execute PUSHINT 4063
|
|
execute implicit RET
|
|
4063 0
|
|
ok
|
|
x{8100EF8011A8}
|
|
execute PUSHINT 239
|
|
execute PUSHINT 17
|
|
execute MUL
|
|
execute implicit RET
|
|
4063 0
|
|
ok
|
|
\end{verbatim}
|
|
Notice that the Fift assembler chooses the shortest encoding of the {\tt PUSHINT}~$x$ instruction depending on its argument~$x$.
|
|
|
|
\mysubsection{Immediate arguments}
|
|
Some TVM instructions (such as {\tt PUSHINT}) accept immediate arguments. These arguments are usually passed to the Fift word assembling the corresponding instruction in the Fift stack. Integer immediate arguments are usually represented by {\em Integer\/}s, cells by {\em Cell\/}s, continuations by {\em Builder\/}s and {\em Cell\/}s, and cell slices by {\em Slice\/}s. For instance, {\tt 17 ADDCONST} assembles TVM instruction {\tt ADDCONST 17}, and {\tt x\{ABCD\_\} PUSHSLICE} assembles {\tt PUSHSLICE xABCD\_}:
|
|
\begin{verbatim}
|
|
239 <{ 17 ADDCONST x{ABCD_} PUSHSLICE }>s dup csr.
|
|
runvmcode . swap . csr.
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
x{A6118B2ABCD0}
|
|
execute ADDINT 17
|
|
execute PUSHSLICE xABCD_
|
|
execute implicit RET
|
|
0 256 x{ABCD_}
|
|
\end{verbatim}
|
|
|
|
On some occasions, the Fift assembler pretends to be able to accept immediate arguments that are out of range for the corresponding TVM instruction. For instance, {\tt ADDCONST $x$} is defined only for $-128\leq x<128$, but the Fift assembler accepts {\tt 239 ADDCONST}:
|
|
\begin{verbatim}
|
|
17 <{ 239 ADDCONST }>s dup csr. runvmcode .s
|
|
\end{verbatim}
|
|
produces
|
|
\begin{verbatim}
|
|
x{8100EFA0}
|
|
execute PUSHINT 239
|
|
execute ADD
|
|
execute implicit RET
|
|
256 0
|
|
\end{verbatim}
|
|
We can see that ``{\tt ADDCONST 239}'' has been tacitly replaced by {\tt PUSHINT 239} and {\tt ADD}. This feature is convenient when the immediate argument to {\tt ADDCONST} is itself a result of a Fift computation, and it is difficult to estimate whether it will always fit into the required range.
|
|
|
|
In some cases, there are several versions of the same TVM instructions, one accepting an immediate argument and another without any arguments. For instance, there are both {\tt LSHIFT $n$} and {\tt LSHIFT} instructions. In the Fift assembler, such variants are assigned distinct mnemonics. In particular, {\tt LSHIFT $n$} is represented by {\tt $n$ LSHIFT\#}, and {\tt LSHIFT} is represented by itself.
|
|
|
|
\mysubsection{Immediate continuations}\label{p:imm.cont}
|
|
When an immediate argument is a continuation, it is convenient to create the corresponding {\em Builder\/} in the Fift stack by means of a nested {\tt <\{} \dots {\tt \}>} construct. For instance, TVM assembler instructions
|
|
\begin{verbatim}
|
|
PUSHINT 1
|
|
SWAP
|
|
PUSHCONT {
|
|
MULCONST 10
|
|
}
|
|
REPEAT
|
|
\end{verbatim}
|
|
can be assembled and executed by
|
|
\begin{verbatim}
|
|
7
|
|
<{ 1 INT SWAP <{ 10 MULCONST }> PUSHCONT REPEAT }>s dup csr.
|
|
runvmcode drop .
|
|
\end{verbatim}
|
|
producing
|
|
\begin{verbatim}
|
|
x{710192A70AE4}
|
|
execute PUSHINT 1
|
|
execute SWAP
|
|
execute PUSHCONT xA70A
|
|
execute REPEAT
|
|
repeat 7 more times
|
|
execute MULINT 10
|
|
execute implicit RET
|
|
repeat 6 more times
|
|
...
|
|
repeat 1 more times
|
|
execute MULINT 10
|
|
execute implicit RET
|
|
repeat 0 more times
|
|
execute implicit RET
|
|
10000000
|
|
\end{verbatim}
|
|
|
|
More convenient ways to use literal continuations created by means of the Fift assembler exist. For instance, the above example can be also assembled by
|
|
\begin{verbatim}
|
|
<{ 1 INT SWAP CONT:<{ 10 MULCONST }> REPEAT }>s csr.
|
|
\end{verbatim}
|
|
or even
|
|
\begin{verbatim}
|
|
<{ 1 INT SWAP REPEAT:<{ 10 MULCONST }> }>s csr.
|
|
\end{verbatim}
|
|
both producing ``{\tt x\{710192A70AE4\} ok}''.
|
|
|
|
Incidentally, a better way of implementing the above loop is by means of {\tt REPEATEND}:
|
|
\begin{verbatim}
|
|
7 <{ 1 INT SWAP REPEATEND 10 MULCONST }>s dup csr.
|
|
runvmcode drop .
|
|
\end{verbatim}
|
|
or
|
|
\begin{verbatim}
|
|
7 <{ 1 INT SWAP REPEAT: 10 MULCONST }>s dup csr.
|
|
runvmcode drop .
|
|
\end{verbatim}
|
|
both produce ``{\tt x\{7101E7A70A\}}'' and output ``{\tt 10000000}'' after seven iterations of the loop.
|
|
|
|
Notice that several TVM instructions that store a continuation in a separate cell reference (such as {\tt JMPREF}) accept their argument in a {\em Cell}, not in a {\em Builder}. In such situations, the {\tt <\{ \dots\ \}>c} construct can be used to produce this immediate argument.
|
|
|
|
\mysubsection{Control flow: loops and conditionals}
|
|
Almost all TVM control flow instructions---such as {\tt IF}, {\tt IFNOT}, {\tt IFRET}, {\tt IFNOTRET}, {\tt IFELSE}, {\tt WHILE}, {\tt WHILEEND}, {\tt REPEAT}, {\tt REPEATEND}, {\tt UNTIL}, and {\tt UNTILEND}---can be assembled similarly to {\tt REPEAT} and {\tt REPEATEND} in the examples of~\ptref{p:imm.cont} when applied to literal continuations. For instance, TVM assembler code
|
|
\begin{verbatim}
|
|
DUP
|
|
PUSHINT 1
|
|
AND
|
|
PUSHCONT {
|
|
MULCONST 3
|
|
INC
|
|
}
|
|
PUSHCONT {
|
|
RSHIFT 1
|
|
}
|
|
IFELSE
|
|
\end{verbatim}
|
|
which computes $3n+1$ or $n/2$ depending on whether its argument $n$ is odd or even, can be assembled and applied to $n=7$ by
|
|
\begin{verbatim}
|
|
<{ DUP 1 INT AND
|
|
IF:<{ 3 MULCONST INC }>ELSE<{ 1 RSHIFT# }>
|
|
}>s dup csr.
|
|
7 swap runvmcode drop .
|
|
\end{verbatim}
|
|
producing
|
|
\begin{verbatim}
|
|
x{2071B093A703A492AB00E2}
|
|
ok
|
|
execute DUP
|
|
execute PUSHINT 1
|
|
execute AND
|
|
execute PUSHCONT xA703A4
|
|
execute PUSHCONT xAB00
|
|
execute IFELSE
|
|
execute MULINT 3
|
|
execute INC
|
|
execute implicit RET
|
|
execute implicit RET
|
|
22 ok
|
|
\end{verbatim}
|
|
Of course, a more compact and efficient way to implement this conditional expression would be
|
|
\begin{verbatim}
|
|
<{ DUP 1 INT AND
|
|
IF:<{ 3 MULCONST INC }>ELSE: 1 RSHIFT#
|
|
}>s dup csr.
|
|
\end{verbatim}
|
|
or
|
|
\begin{verbatim}
|
|
<{ DUP 1 INT AND
|
|
CONT:<{ 3 MULCONST INC }> IFJMP
|
|
1 RSHIFT#
|
|
}>s dup csr.
|
|
\end{verbatim}
|
|
both producing the same code ``{\tt x\{2071B093A703A4DCAB00\}}''.
|
|
|
|
Fift assembler words that can be used to produce such ``high-level'' conditionals and loops include {\tt IF:<\{}, {\tt IFNOT:<\{}, {\tt IFJMP:<\{}, {\tt \}>ELSE<\{}, {\tt \}>ELSE:}, {\tt \}>IF}, {\tt REPEAT:<\{}, {\tt UNTIL:<\{}, {\tt WHILE:<\{}, {\tt \}>DO<\{}, {\tt \}>DO:}, {\tt AGAIN:<\{}, {\tt \}>AGAIN}, {\tt \}>REPEAT}, and {\tt \}>UNTIL}. Their complete list can be found in the source file {\tt Asm.fif}. For instance, an UNTIL loop can be created by {\tt UNTIL:<\{ \dots\ \}>} or {\tt <\{ \dots\ \}>UNTIL}, and a WHILE loop by {\tt WHILE:<\{ \dots\ \}>DO<\{ \dots\ \}>}.
|
|
|
|
If we choose to keep a conditional branch in a separate cell, we can use the {\tt <\{ \dots\ \}>c} construct along with instructions such as {\tt IFJMPREF}:
|
|
\begin{verbatim}
|
|
<{ DUP 1 INT AND
|
|
<{ 3 MULCONST INC }>c IFJMPREF
|
|
1 RSHIFT#
|
|
}>s dup csr.
|
|
3 swap runvmcode .s
|
|
\end{verbatim}
|
|
has the same effect as the code from the previous example when executed, but it is contained in two separate cells:
|
|
\begin{verbatim}
|
|
x{2071B0E302AB00}
|
|
x{A703A4}
|
|
execute DUP
|
|
execute PUSHINT 1
|
|
execute AND
|
|
execute IFJMPREF (2946....A1DD)
|
|
execute MULINT 3
|
|
execute INC
|
|
execute implicit RET
|
|
10 0
|
|
\end{verbatim}
|
|
|
|
\mysubsection{Macro definitions}
|
|
Because TVM instructions are implemented in the Fift assembler using Fift words that have a predictable effect on the Fift stack, the Fift assembler is automatically a macro assembler, supporting macro definitions. For instance, suppose that we wish to define a macro definition {\tt RANGE $x$ $y$}, which checks whether the TVM top-of-stack value is between integer literals $x$ and $y$ (inclusive). This macro definition can be implemented as follows:
|
|
\begin{verbatim}
|
|
{ 2dup > ' swap if
|
|
rot DUP rot GEQINT SWAP swap LEQINT AND
|
|
} : RANGE
|
|
<{ DUP 17 239 RANGE IFNOT: DROP ZERO }>s dup csr.
|
|
66 swap runvmcode drop .
|
|
\end{verbatim}
|
|
which produces
|
|
\begin{verbatim}
|
|
x{2020C210018100F0B9B0DC3070}
|
|
execute DUP
|
|
execute DUP
|
|
execute GTINT 16
|
|
execute SWAP
|
|
execute PUSHINT 240
|
|
execute LESS
|
|
execute AND
|
|
execute IFRET
|
|
66
|
|
\end{verbatim}
|
|
Notice that {\tt GEQINT} and {\tt LEQINT} are themselves macro definitions defined in {\tt Asm.fif}, because they do not correspond directly to TVM instructions. For instance, {\tt $x$ GEQINT} corresponds to the TVM instruction {\tt GTINT $x-1$}.
|
|
|
|
Incidentally, the above code can be shortened by two bytes by replacing {\tt IFNOT: DROP ZERO} with {\tt AND}.
|
|
|
|
\mysubsection{Larger programs and subroutines}\label{p:asm.prog}
|
|
Larger TVM programs, such as TON Blockchain smart contracts, typically consist of several mutually recursive subroutines, with one or several of them selected as top-level subroutines (called {\tt main()} or {\tt recv\_internal()} for smart contracts). The execution starts from one of the top-level subroutines, which is free to call any of the other defined subroutines, which in turn can call whatever other subroutines they need.
|
|
|
|
Such TVM programs are implemented by means of a selector function, which accepts an extra integer argument in the TVM stack; this integer selects the actual subroutine to be invoked (cf.~\cite[4.6]{TVM}). Before execution, the code of this selector function is loaded both into special register {\tt c3} and into the current continuation {\tt cc}. The selector of the main function (usually zero) is pushed into the initial stack, and the TVM execution is started. Afterwards a subroutine can be invoked by means of a suitable TVM instruction, such as {\tt CALLDICT $n$}, where $n$ is the (integer) selector of the subroutine to be called.
|
|
|
|
The Fift assembler offers several words facilitating the implementation of such large TVM programs. In particular, subroutines can be defined separately and assigned symbolic names (instead of numeric selectors), which can be used to call them afterwards. The Fift assembler automatically creates a selector function from these separate subroutines and returns it as the top-level assembly result.
|
|
|
|
Here is a simple example of such a program consisting of several subroutines. This program computes the complex number $(5+i)^4\cdot(239-i)$:
|
|
\begin{verbatim}
|
|
"Asm.fif" include
|
|
|
|
PROGRAM{
|
|
|
|
NEWPROC add
|
|
NEWPROC sub
|
|
NEWPROC mul
|
|
|
|
sub <{ s3 s3 XCHG2 SUB s2 XCHG0 SUB }>s PROC
|
|
|
|
// compute (5+i)^4 * (239-i)
|
|
main PROC:<{
|
|
5 INT 1 INT // 5+i
|
|
2DUP
|
|
mul CALL
|
|
2DUP
|
|
mul CALL
|
|
239 INT -1 INT
|
|
mul JMP
|
|
}>
|
|
|
|
add PROC:<{
|
|
s1 s2 XCHG
|
|
ADD -ROT ADD SWAP
|
|
}>
|
|
|
|
// a b c d -- ac-bd ad+bc : complex number multiplication
|
|
mul PROC:<{
|
|
s3 s1 PUSH2 // a b c d a c
|
|
MUL // a b c d ac
|
|
s3 s1 PUSH2 // a b c d ac b d
|
|
MUL // a b c d ac bd
|
|
SUB // a b c d ac-bd
|
|
s4 s4 XCHG2 // ac-bd b c a d
|
|
MUL // ac-bd b c ad
|
|
-ROT MUL ADD
|
|
}>
|
|
|
|
}END>s
|
|
dup csr.
|
|
runvmdict .s
|
|
\end{verbatim}
|
|
This program produces:
|
|
\begin{verbatim}
|
|
x{FF00F4A40EF4A0F20B}
|
|
x{D9_}
|
|
x{2_}
|
|
x{1D5C573C00D73C00E0403BDFFC5000E_}
|
|
x{04A81668006_}
|
|
x{2_}
|
|
x{140CE840A86_}
|
|
x{14CC6A14CC6A2854112A166A282_}
|
|
implicit PUSH 0 at start
|
|
execute SETCP 0
|
|
execute DICTPUSHCONST 14 (xC_,1)
|
|
execute DICTIGETJMP
|
|
execute PUSHINT 5
|
|
execute PUSHINT 1
|
|
execute 2DUP
|
|
execute CALLDICT 3
|
|
execute SETCP 0
|
|
execute DICTPUSHCONST 14 (xC_,1)
|
|
execute DICTIGETJMP
|
|
execute PUSH2 s3,s1
|
|
execute MUL
|
|
...
|
|
execute ROTREV
|
|
execute MUL
|
|
execute ADD
|
|
execute implicit RET
|
|
114244 114244 0
|
|
\end{verbatim}
|
|
|
|
Some observations and comments based on the previous example follow:
|
|
\begin{itemize}
|
|
\item A TVM program is opened by {\tt PROGRAM\{} and closed by either {\tt \}END>c} (which returns the assembled program as a {\em Cell\/}) or {\tt \}END>s} (which returns a {\em Slice\/}).
|
|
\item A new subroutine is declared by means of the phrase {\tt NEWPROC $\langle\textit{name}\rangle$}. This declaration assigns the next positive integer as a selector for the newly-declared subroutine, and stores this integer into the constant $\langle\textit{name}\rangle$. For instance, the above declarations define {\tt add}, {\tt sub}, and {\tt mul} as integer constants equal to 1, 2, and 3, respectively.
|
|
\item Some subroutines are predeclared and do not need to be declared again by {\tt NEWPROC}. For instance, {\tt main} is a subroutine identifier bound to the integer constant (selector) 0.
|
|
\item Other predefined subroutine selectors such as {\tt recv\_internal} (equal to $0$) or {\tt recv\_external} (equal to $-1$), useful for implementing TON Blockchain smart contracts (cf.~\cite[4.4]{TBC}), can be declared by means of {\tt constant} (e.g., {\tt -1 constant recv\_external}).
|
|
\item A subroutine can be defined either with the aid of the word {\tt PROC}, which accepts the integer selector of the subroutine and the {\em Slice} containing the code for this subroutine, or with the aid of the construct {\tt $\langle\textit{selector}\rangle$ PROC:<\{ \dots\ \}>}, convenient for defining larger subroutines.
|
|
\item {\tt CALLDICT} and {\tt JMPDICT} instructions may be assembled with the aid of the words {\tt CALL} and {\tt JMP}, which accept the integer selector of the subroutine to be called as an immediate argument passed in the Fift stack.
|
|
\item The current implementation of the Fift assembler collects all subroutines into a dictionary with 14-bit signed integer keys. Therefore, all subroutine selectors must be in the range $-2^{13}\dots 2^{13}-1$.
|
|
\item If a subroutine with an unknown selector is called during runtime, an exception with code $11$ is thrown by the code automatically inserted by the Fift assembler. This code also automatically selects codepage zero for instruction encoding by means of a {\tt SETCP0} instruction.
|
|
\item The Fift assembler checks that all subroutines declared by {\tt NEWPROC} are actually defined by {\tt PROC} or {\tt PROC:<\{} before the end of the program. It also checks that a subroutine is not redefined.
|
|
\end{itemize}
|
|
|
|
One should bear in mind that very simple programs (including the simplest smart contracts) may be made more compact by eliminating this general subroutine selection machinery in favor of custom subroutine selection code and removing unused subroutines. For instance, the above example can be transformed into
|
|
\begin{verbatim}
|
|
<{ 11 THROWIF
|
|
CONT:<{ s3 s1 PUSH2 MUL s3 s1 PUSH2 MUL SUB
|
|
s4 s4 XCHG2 MUL -ROT MUL ADD }>
|
|
5 INT 1 INT 2DUP s4 PUSH CALLX
|
|
2DUP s4 PUSH CALLX
|
|
ROT 239 INT -1 INT ROT JMPX
|
|
}>s
|
|
dup csr.
|
|
runvmdict .s
|
|
\end{verbatim}
|
|
which produces
|
|
\begin{verbatim}
|
|
x{F24B9D5331A85331A8A15044A859A8A075715C24D85C24D8588100EF7F58D9}
|
|
implicit PUSH 0 at start
|
|
execute THROWIF 11
|
|
execute PUSHCONT x5331A85331A8A15044A859A8A0
|
|
execute PUSHINT 5
|
|
execute PUSHINT 1
|
|
execute 2DUP
|
|
execute PUSH s4
|
|
execute EXECUTE
|
|
execute PUSH2 s3,s1
|
|
execute MUL
|
|
...
|
|
execute XCHG2 s4,s4
|
|
execute MUL
|
|
execute ROTREV
|
|
execute MUL
|
|
execute ADD
|
|
execute implicit RET
|
|
114244 114244 0
|
|
\end{verbatim}
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
%
|
|
% bibliography
|
|
%
|
|
%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\clearpage
|
|
\markbothsame{\textsc{References}}
|
|
|
|
\begin{thebibliography}{2}
|
|
\bibitem{Brodie}
|
|
{\sc L.~Brodie}, {\sl Starting Forth: Introduction to the FORTH Language and Operating System for Beginners and Professionals}, 2nd edition, Prentice Hall, 1987. Available at \url{https://www.forth.com/starting-forth/}.
|
|
|
|
\bibitem{Brodie2}
|
|
{\sc L.~Brodie}, {\sl Thinking Forth: A language and philosophy for solving problems}, Prentice Hall, 1984. Available at \url{http://thinking-forth.sourceforge.net/}.
|
|
|
|
\bibitem{TON}
|
|
{\sc N.~Durov}, {\sl Telegram Open Network}, 2017.
|
|
|
|
\bibitem{TVM}
|
|
{\sc N.~Durov}, {\sl Telegram Open Network Virtual Machine}, 2018.
|
|
|
|
\bibitem{TBC}
|
|
{\sc N.~Durov}, {\sl Telegram Open Network Blockchain}, 2018.
|
|
\end{thebibliography}
|
|
|
|
\clearpage
|
|
\appendix\myappendix{List of Fift words}\label{app:words}
|
|
This Appendix provides an alphabetic list of almost all Fift words---including primitives and definitions from the standard library {\tt Fift.fif}, but excluding Fift assembler words defined in {\tt Asm.fif} (because the Fift assembler is simply an application from the perspective of Fift). Some experimental words have been omitted from this list. Other words may have been added to or removed from Fift after this text was written. The list of all words available in your Fift interpreter may be inspected by executing {\tt words}.
|
|
|
|
Each word is described by its name, followed by its {\em stack notation\/} in parentheses, indicating several values near the top of the Fift stack before and after the execution of the word; all deeper stack entries are usually assumed to be left intact. After that, a text description of the word's effect is provided. If the word has been discussed in a previous section of this document, a reference to this section is included.
|
|
|
|
Active words and active prefix words that parse a portion of the input stream immediately after their occurrence are listed here in a modified way. Firstly, these words are listed alongside the portion of the input that they parse; the segment of each entry that is actually a Fift word is underlined for emphasis. Secondly, their stack effect is usually described from the user's perspective, and reflects the actions performed during the execution phase of the encompassing blocks and word definitions.
|
|
|
|
For example, the active prefix word {\tt B\{}, used for defining {\em Bytes\/} literals (cf.~\ptref{p:bytes.ops}), is listed as {\tt \underline{B\{}$\langle\textit{hex-digits}\rangle$\}}, and its stack effect is shown as ( -- $B$) instead of ( -- $B$ $1$ $e$), even though the real effect of the execution of the active word {\tt B\{} during the compilation phase of an encompassing block or word definition is the latter one (cf.~\ptref{p:active.words}).
|
|
|
|
\begin{itemize}
|
|
\item {\tt !} ($x$ $p$ -- ), stores new value~$x$ into {\em Box\/}~$p$, cf.~\ptref{p:variables}.
|
|
\item {\tt\underline{"}$\langle\textit{string}\rangle$"} ( -- $S$), pushes a {\em String\/} literal into the stack, cf.~\ptref{p:string.lit} and~\ptref{p:string.ops}.
|
|
\item {\tt \#} ($x$ $S$ -- $x'$ $S'$), performs one step of the conversion of {\em Integer\/}~$x$ into its decimal representation by appending to {\em String\/}~$S$ one decimal digit representing $x\bmod10$. The quotient $x':=\lfloor x/10\rfloor$ is returned as well.
|
|
\item {\tt \#>} ($S$ -- $S'$), finishes the conversion of an {\em Integer\/} into its human-readable representation (decimal or otherwise) started with {\tt <\#} by reversing {\em String~$S$}. Equivalent to {\tt \$reverse}.
|
|
\item {\tt \#s} ($x$ $S$ -- $x'$ $S'$), performs {\tt \#} one or more times until the quotient $x'$ becomes non-positive. Equivalent to {\tt \{ \# over 0<= \} until}.
|
|
\item {\tt \$\#} ( -- $x$), pushes the total number of command-line arguments passed to the Fift program, cf.~\ptref{p:cmdline.ops}. Defined only when the Fift interpreter is invoked in script mode (with the {\tt -s} command line argument).
|
|
\item {\tt\underline{\$(}$\langle\textit{string\/}\rangle$)} ( -- \dots), looks up the word {\tt \$$\langle\textit{string\/}\rangle$} during execution time and executes its current definition. Typically used to access the current values of command-line arguments, e.g., {\tt \$(2)} is essentially equivalent to {\tt @' \$2}.
|
|
\item {\tt \$()} ($x$ -- $S$), pushes the $x$-th command-line argument similarly to {\tt \$$n$}, but with {\em Integer\/}~$x\geq0$ taken from the stack, cf.~\ptref{p:cmdline.ops}. Defined only when the Fift interpreter is invoked in script mode (with the {\tt -s} command line argument).
|
|
\item {\tt \$+} ($S$ $S'$ -- $S.S'$), concatenates two strings, cf.~\ptref{p:string.ops}.
|
|
\item {\tt \$,} ($b$ $S$ -- $b'$), appends {\em String\/}~$S$ to {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}. The string is interpreted as a binary string of length $8n$, where $n$ is the number of bytes in the UTF-8 representation of~$S$.
|
|
\item {\tt \$$n$} ( -- $S$), pushes the $n$-th command-line argument as a {\em String}~$S$, cf.~\ptref{p:cmdline.ops}. For instance, {\tt \$0} pushes the name of the script being executed, {\tt \$1} the first command line argument, and so on. Defined only when the Fift interpreter is invoked in script mode (with the {\tt -s} command line argument).
|
|
\item {\tt \$=} ($S$ $S'$ -- $?$), returns $-1$ if strings $S$ and $S'$ are equal, $0$ otherwise, cf.~\ptref{p:string.cmp.ops}. Equivalent to {\tt \$cmp 0=}.
|
|
\item {\tt \$>s} ($S$ -- $s$), transforms the {\em String\/}~$S$ into a {\em Slice}, cf.~\ptref{p:slice.ops}. Equivalent to {\tt <b swap \$, b> <s}.
|
|
\item {\tt \$>smca} ($S$ -- $x$ $y$ $z$ $-1$ or $0$), unpacks a standard TON smart-contract address from its human-readable string representation~$S$, cf.~\ptref{p:smc.addr.ops}. On success, returns the signed 32-bit workchain $x$, the unsigned 256-bit in-workchain address $y$, the flags $z$ (where $+1$ means that the address is non-bounceable, $+2$ that the address is testnet-only), and $-1$. On failure, pushes $0$.
|
|
\item {\tt \$@} ($s$ $x$ -- $S$), fetches the first $x$ bytes (i.e., $8x$ bits) from {\em Slice}~$s$, and returns them as a UTF-8 {\em String\/}~$S$, cf.~\ptref{p:slice.ops}. If there are not enough data bits in $s$, throws an exception.
|
|
\item {\tt \$@+} ($s$ $x$ -- $S$ $s'$), similar to {\tt \$@}, but returns the remainder of {\em Slice\/} $s$ as well, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt \$@?} ($s$ $x$ -- $S$ $-1$ or $0$), similar to {\tt \$@}, but uses a flag to indicate failure instead of throwing an exception, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt \$@?+} ($s$ $x$ -- $S$ $s'$ $-1$ or $s$ $0$), similar to {\tt \$@+}, but uses a flag to indicate failure instead of throwing an exception, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt \$cmp} ($S$ $S'$ -- $x$), returns $0$ if strings $S$ and $S'$ are equal, $-1$ if $S$ is lexicographically less than $S'$, and $1$ if $S$ is lexicographically greater than $S'$, cf.~\ptref{p:string.cmp.ops}.
|
|
\item {\tt \$len} ($S$ -- $x$), computes the byte length (not the UTF-8 character length!) of a string, cf.~\ptref{p:string.ops}.
|
|
\item {\tt \$reverse} ($S$ -- $S'$), reverses the order of UTF-8 characters in {\em String\/}~$S$. If $S$ is not a valid UTF-8 string, the return value is undefined and may be also invalid.
|
|
\item {\tt \%1<{<}} ($x$ $y$ -- $z$), computes $z:=x\bmod 2^y=x\&(2^y-1)$ for two {\em Integer\/}s $x$ and $0\leq y\leq 256$.
|
|
\item {\tt \underline{'} $\langle\textit{word-name}\rangle$} ( -- $e$), returns the execution token equal to the current (compile-time) definition of $\langle\textit{word-name}\rangle$, cf.~\ptref{p:blocks}. If the specified word is not found, throws an exception.
|
|
\item {\tt 'nop} ( -- $e$), pushes the default definition of {\tt nop}---an execution token that does nothing when executed, cf.~\ptref{p:dict.lookup}.
|
|
\item {\tt \underline{(')} $\langle\textit{word-name}\rangle$} ( -- $e$), similar to {\tt '}, but returns the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked, cf.~\ptref{p:dict.lookup}. May be used to recover the current values of constants inside word definitions and other blocks by using the phrase {\tt (') $\langle\textit{word-name}\rangle$ execute}.
|
|
\item {\tt (-trailing)} ($S$ $x$ -- $S'$), removes from {\em String}~$S$ all trailing characters with UTF-8 codepoint~$x$.
|
|
\item {\tt (.)} ($x$ -- $S$), returns the {\em String\/} with the decimal representation of {\em Integer\/}~$x$. Equivalent to {\tt dup abs <\# \#s rot sign \#> nip}.
|
|
\item {\tt (atom)} ($S$ $x$ -- $a$ $-1$ or $0$), returns the only {\em Atom\/} $a$ with the name given by {\em String\/}~$S$, cf.~\ptref{p:atoms}. If there is no such {\em Atom\/} yet, either creates it (if {\em Integer\/}~$x$ is non-zero) or returns a single zero to indicate failure (if $x$ is zero).
|
|
\item {\tt (b.)} ($x$ -- $S$), returns the {\em String\/} with the binary representation of {\em Integer\/}~$x$.
|
|
\item {\tt (compile)} ($l$ $x_1$ \dots $x_n$ $n$ $e$ -- $l'$), extends {\em WordList\/}~$l$ so that it would push $0\leq n\leq 255$ values $x_1$, \ldots, $x_n$ into the stack and execute the execution token $e$ when invoked, where $0\leq n\leq 255$ is an {\em Integer}, cf.~\ptref{p:wordlist.ops}. If $e$ is equal to the special value {\tt 'nop}, the last step is omitted.
|
|
\item {\tt (create)} ($e$ $S$ $x$ -- ), creates a new word with the name equal to {\em String\/}~$S$ and definition equal to {\em WordDef\/}~$e$, using flags passed in {\em Integer\/} $0\leq x\leq 3$, cf.~\ptref{p:dict.create}. If bit $+1$ is set in $x$, creates an active word; if bit $+2$ is set in $x$, creates a prefix word.
|
|
\item {\tt (def?)} ($S$ -- $?$), checks whether the word $S$ is defined.
|
|
\item {\tt (dump)} ($x$ -- $S$), returns a {\em String\/} with a dump of the topmost stack value~$x$, in the same format as employed by {\tt .dump}.
|
|
\item {\tt (execute)} ($x_1$ \dots $x_n$ $n$ $e$ -- \dots), executes execution token $e$, but first checks that there are at least $0\leq n\leq 255$ values in the stack apart from $n$ and $e$ themselves. It is a counterpart of {\tt (compile)} that may be used to immediately ``execute'' (perform the intended runtime action of) an active word after its immediate execution, as explained in~\ptref{p:active.words}.
|
|
\item {\tt (forget)} ($S$ -- ), forgets the word with the name specified in {\em String}~$S$, cf.~\ptref{p:dict.create}. If the word is not found, throws an exception.
|
|
\item {\tt (number)} ($S$ -- $0$ or $x$ $1$ or $x$ $y$ $2$), attempts to parse the {\em String\/} $S$ as an integer or fractional literal, cf.~\ptref{p:string.ops} and~\ptref{p:int.lit}. On failure, returns a single $0$. On success, returns $x$ $1$ if $S$ is a valid integer literal with value $x$, or $x$ $y$ $2$ if $S$ is a valid fractional literal with value $x/y$.
|
|
\item {\tt (x.)} ($x$ -- $S$), returns the {\em String\/} with the hexadecimal representation of {\em Integer\/}~$x$.
|
|
\item {\tt (\{)} ( -- $l$), pushes an empty {\em WordList\/} into the stack, cf.~\ptref{p:wordlist.ops}
|
|
\item {\tt (\})} ($l$ -- $e$), transforms a {\em WordList\/} into an execution token ({\em WordDef\/}), making all further modifications impossible, cf.~\ptref{p:wordlist.ops}.
|
|
\item {\tt *} ($x$ $y$ -- $xy$), computes the product $xy$ of two {\em Integer\/}s $x$ and $y$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt */} ($x$ $y$ $z$ -- $\lfloor xy/z\rfloor$), ``multiply-then-divide'': multiplies two integers $x$ and $y$ producing a 513-bit intermediate result, then divides the product by $z$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt */c} ($x$ $y$ $z$ -- $\lceil xy/z\rceil$), ``multiply-then-divide'' with ceiling rounding: multiplies two integers $x$ and $y$ producing a 513-bit intermediate result, then divides the product by $z$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt */cmod} ($x$ $y$ $z$ -- $q$ $r$), similar to {\tt */c}, but computes both the quotient $q:=\lceil xy/z\rceil$ and the remainder $r:=xy-qz$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt */mod} ($x$ $y$ $z$ -- $q$ $r$), similar to {\tt */}, but computes both the quotient $q:=\lfloor xy/z\rfloor$ and the remainder $r:=xy-qz$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt */r} ($x$ $y$ $z$ -- $q:=\lfloor xy/z+1/2\rfloor$), ``multiply-then-divide'' with nearest-integer rounding: multiplies two integers $x$ and $y$ with 513-bit intermediate result, then divides the product by $z$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt */rmod} ($x$ $y$ $z$ -- $q$ $r$), similar to {\tt */r}, but computes both the quotient $q:=\lfloor xy/z+1/2\rfloor$ and the remainder $r:=xy-qz$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt *>{}>} ($x$ $y$ $z$ -- $q$), similar to {\tt */}, but with division replaced with a right shift, cf.~\ptref{p:arith.op}. Computes $q:=\lfloor xy/2^z\rfloor$ for $0\leq z\leq 256$. Equivalent to {\tt 1<{}< */}.
|
|
\item {\tt *>{}>c} ($x$ $y$ $z$ -- $q$), similar to {\tt */c}, but with division replaced with a right shift, cf.~\ptref{p:arith.op}. Computes $q:=\lceil xy/2^z\rceil$ for $0\leq z\leq 256$. Equivalent to {\tt 1<{}< */c}.
|
|
\item {\tt *>{}>r} ($x$ $y$ $z$ -- $q$), similar to {\tt */r}, but with division replaced with a right shift, cf.~\ptref{p:arith.op}. Computes $q:=\lfloor xy/2^z+1/2\rfloor$ for $0\leq z\leq 256$. Equivalent to {\tt 1<{}< */r}.
|
|
\item {\tt *mod} ($x$ $y$ $z$ -- $r$), similar to {\tt */mod}, but computes only the remainder $r:=xy-qz$, where $q:=\lfloor xy/z\rfloor$. Equivalent to {\tt */mod nip}.
|
|
\item {\tt +} ($x$ $y$ -- $x+y$), computes the sum $x+y$ of two {\em Integer\/}s $x$ and $y$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt +!} ($x$ $p$ -- ), increases the integer value stored in {\em Box\/}~$p$ by {\em Integer\/}~$x$, cf.~\ptref{p:variables}. Equivalent to {\tt tuck @ + swap !}.
|
|
\item {\tt\underline{+"}$\langle\textit{string}\rangle$"} ($S$ -- $S'$), concatenates {\em String\/}~$S$ with a string literal, cf.~\ptref{p:string.ops}. Equivalent to {\tt "$\langle\textit{string}\rangle$" \$+}.
|
|
\item {\tt ,} ($t$ $x$ -- $t'$), appends $x$ to the end of {\em Tuple\/}~$t$, and returns the resulting {\em Tuple\/}~$t'$, cf.~\ptref{p:tuples}.
|
|
\item {\tt -} ($x$ $y$ -- $x-y$), computes the difference $x-y$ of two {\em Integer\/}s $x$ and $y$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt -!} ($x$ $p$ -- ), decreases the integer value stored in {\em Box\/}~$p$ by {\em Integer\/}~$x$. Equivalent to {\tt swap negate swap +!}.
|
|
\item {\tt -1} ( -- $-1$), pushes {\em Integer\/} $-1$.
|
|
\item {\tt -1<{}<} ($x$ -- $-2^x$), computes $-2^x$ for $0\leq x\leq 256$. Approximately equivalent to {\tt 1<{}< negate} or {\tt -1 swap <{}<}, but works for $x=256$ as well.
|
|
\item {\tt -roll} ($x_n$ \dots $x_0$ $n$ -- $x_0$ $x_n$ \dots $x_1$), rotates the top $n$ stack entries in the opposite direction, 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$ -- $z$ $x$ $y$), rotates the three topmost stack entries in the opposite direction, cf.~\ptref{p:stack.ops}. Equivalent to {\tt rot rot}.
|
|
\item {\tt -trailing} ($S$ -- $S'$), removes from {\em String\/}~$S$ all trailing spaces. Equivalent to {\tt bl (-trailing)}.
|
|
\item {\tt -trailing0} ($S$ -- $S'$), removes from {\em String\/}~$S$ all trailing `{\tt 0}' characters. Equivalent to {\tt char 0 (-trailing)}.
|
|
\item {\tt .} ($x$ -- ), prints the decimal representation of {\em Integer\/}~$x$, followed by a single space, cf.~\ptref{p:arith.op}. Equivalent to {\tt .\_ space}.
|
|
\item {\tt\underline{."}$\langle\textit{string}\rangle$"} ( -- ), prints a constant string into the standard output, cf.~\ptref{p:string.ops}.
|
|
\item {\tt .\_} ($x$ -- ), prints the decimal representation of {\em Integer\/}~$x$ without any spaces. Equivalent to {\tt (.)~type}.
|
|
\item {\tt .dump} ($x$ -- ), dumps the topmost stack entry in the same way as {\tt .s} dumps all stack elements, cf.~\ptref{p:tuples}. Equivalent to {\tt (dump) type space}.
|
|
\item {\tt .l} ($l$ -- ), prints a Lisp-style list~$l$, cf.~\ptref{p:lists}.
|
|
\item {\tt .s} ( -- ), dumps all stack entries starting from the deepest, leaving them intact, cf.~\ptref{p:stack.ops}. Human-readable representations of stack entries are output separated by spaces, followed by an end-of-line character.
|
|
\item {\tt .sl} ( -- ), dumps all stack entries leaving them intact similarly to {\tt .s}, but showing each entry as a List-style list~$l$ as {\tt .l} does.
|
|
\item {\tt .tc} ( -- ), outputs the total number of allocated cells into the standard error stream.
|
|
\item {\tt /} ($x$ $y$ -- $q:=\lfloor x/y\rfloor$), computes the floor-rounded quotient $\lfloor x/y\rfloor$ of two {\em Integer\/}s, cf.~\ptref{p:arith.op}.
|
|
\item {\tt \underline{/*} $\langle\textit{multiline-comment}\rangle$ */} ( -- ), skips a multi-line comment delimited by word ``{\tt */}'' (followed by a blank or an end-of-line character), cf.~\ptref{p:comments}.
|
|
\item {\tt \underline{//} $\langle\textit{comment-to-eol}\rangle$} ( -- ), skips a single-line comment until the end of the current line, cf.~\ptref{p:comments}.
|
|
\item {\tt /c} ($x$ $y$ -- $q:=\lceil x/y\rceil$), computes the ceiling-rounded quotient $\lceil x/y\rceil$ of two {\em Integer\/}s, cf.~\ptref{p:arith.op}.
|
|
\item {\tt /cmod} ($x$ $y$ -- $q$ $r$), computes both the ceiling-rounded quotient $q:=\lceil x/y\rceil$ and the remainder $r:=x-qy$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt /mod} ($x$ $y$ -- $q$ $r$), computes both the floor-rounded quotient $q:=\lfloor x/y\rfloor$ and the remainder $r:=x-qy$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt /r} ($x$ $y$ -- $q$), computes the nearest-integer-rounded quotient $\lfloor x/y+1/2\rfloor$ of two {\em Integer\/}s, cf.~\ptref{p:arith.op}.
|
|
\item {\tt /rmod} ($x$ $y$ -- $q$ $r$), computes both the nearest-integer-rounded quotient $q:=\lfloor x/y+1/2\rfloor$ and the remainder $r:=x-qy$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt 0} ( -- $0$), pushes {\em Integer\/} $0$.
|
|
\item {\tt 0!} ($p$ -- ), stores {\em Integer\/} $0$ into {\em Box\/}~$p$, cf.~\ptref{p:variables}. Equivalent to {\tt 0 swap !}.
|
|
\item {\tt 0<} ($x$ -- $?$), checks whether $x<0$ (i.e., pushes $-1$ if $x$ is negative, $0$ otherwise), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 <}.
|
|
\item {\tt 0<=} ($x$ -- $?$), checks whether $x\leq0$ (i.e., pushes $-1$ if $x$ is non-positive, $0$ otherwise), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 <=}.
|
|
\item {\tt 0<>} ($x$ -- $?$), checks whether $x\neq0$ (i.e., pushes $-1$ if $x$ is non-zero, $0$ otherwise), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 <>}.
|
|
\item {\tt 0=} ($x$ -- $?$), checks whether $x=0$ (i.e., pushes $-1$ if $x$ is zero, $0$ otherwise), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 =}.
|
|
\item {\tt 0>} ($x$ -- $?$), checks whether $x>0$ (i.e., pushes $-1$ if $x$ is positive, $0$ otherwise), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 >}.
|
|
\item {\tt 0>=} ($x$ -- $?$), checks whether $x\geq0$ (i.e., pushes $-1$ if $x$ is non-negative, $0$ otherwise), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 >=}.
|
|
\item {\tt 1} ( -- $1$), pushes {\em Integer\/} $1$.
|
|
\item {\tt 1+} ($x$ -- $x+1$), computes $x+1$. Equivalent to {\tt 1 +}.
|
|
\item {\tt 1+!} ($p$ -- ), increases the integer value stored in {\em Box\/}~$p$ by one, cf.~\ptref{p:variables}. Equivalent to {\tt 1 swap +!}.
|
|
\item {\tt 1-} ($x$ -- $x-1$), computes $x-1$. Equivalent to {\tt 1 -}.
|
|
\item {\tt 1-!} ($p$ -- ), decreases the integer value stored in {\em Box\/}~$p$ by one. Equivalent to {\tt -1 swap +!}.
|
|
\item {\tt 1<{}<} ($x$ -- $2^x$), computes $2^x$ for $0\leq x\leq 255$. Equivalent to {\tt 1 swap <{}<}.
|
|
\item {\tt 1<{}<1-} ($x$ -- $2^x-1$), computes $2^x-1$ for $0\leq x\leq 256$. Almost equivalent to {\tt 1<{}< 1-}, but works for $x=256$.
|
|
\item {\tt 2} ( -- $2$), pushes {\em Integer\/} $2$.
|
|
\item {\tt 2*} ($x$ -- $2x$), computes $2x$. Equivalent to {\tt 2 *}.
|
|
\item {\tt 2+} ($x$ -- $x+2$), computes $x+2$. Equivalent to {\tt 2 +}.
|
|
\item {\tt 2-} ($x$ -- $x-2$), computes $x-2$. Equivalent to {\tt 2 -}.
|
|
\item {\tt 2/} ($x$ -- $\lfloor x/2\rfloor$), computes $\lfloor x/2\rfloor$. Equivalent to {\tt 2 /} or to {\tt 1 >{}>}.
|
|
\item {\tt \underline{2=:} $\langle\textit{word-name}\rangle$} ($x$ $y$ -- ), an active variant of {\tt 2constant}: defines a new ordinary word $\langle\textit{word-name}\rangle$ that would push the given values $x$ and $y$ when invoked, cf.~\ptref{p:constants}.
|
|
\item {\tt 2constant} ($x$ $y$ -- ), scans a blank-delimited word name $S$ from the remainder of the input, and defines a new ordinary word $S$ as a double constant, which will push the given values $x$ and $y$ (of arbitrary types) when invoked, cf.~\ptref{p:dict.create}.
|
|
\item {\tt 2drop} ($x$ $y$ -- ), removes the two topmost stack entries, cf.~\ptref{p:stack.ops}. Equivalent to {\tt drop drop}.
|
|
\item {\tt 2dup} ($x$ $y$ -- $x$ $y$ $x$ $y$), duplicates the topmost pair of stack entries, cf.~\ptref{p:stack.ops}. Equivalent to {\tt over over}.
|
|
\item {\tt 2over} ($x$ $y$ $z$ $w$ -- $x$ $y$ $z$ $w$ $x$ $y$), duplicates the second topmost pair of stack entries.
|
|
\item {\tt 2swap} ($a$ $b$ $c$ $d$ -- $c$ $d$ $a$ $b$), interchanges the two topmost pairs of stack entries, cf.~\ptref{p:stack.ops}.
|
|
\item {\tt \underline{:} $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new ordinary word $\langle\textit{word-name}\rangle$ in the dictionary using {\em WordDef\/} $e$ as its definition, cf.~\ptref{p:dict.create}. If the specified word is already present in the dictionary, it is tacitly redefined.
|
|
\item {\tt \underline{::} $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new active word $\langle\textit{word-name}\rangle$ in the dictionary using {\em WordDef\/} $e$ as its definition, cf.~\ptref{p:dict.create}. If the specified word is already present in the dictionary, it is tacitly redefined.
|
|
\item {\tt \underline{::\_} $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new active prefix word $\langle\textit{word-name}\rangle$ in the dictionary using {\em WordDef\/} $e$ as its definition, cf.~\ptref{p:dict.create}. If the specified word is already present in the dictionary, it is tacitly redefined.
|
|
\item {\tt \underline{:\_} $\langle\textit{word-name}\rangle$} ($e$ -- ), defines a new ordinary prefix word $\langle\textit{word-name}\rangle$ in the dictionary using {\em WordDef\/} $e$ as its definition, cf.~\ptref{p:dict.create}. If the specified word is already present in the dictionary, it is tacitly redefined.
|
|
\item {\tt <} ($x$ $y$ -- $?$), checks whether $x<y$ (i.e., pushes $-1$ if {\em Integer\/}~$x$ is less than {\em Integer\/}~$y$, $0$ otherwise), cf.~\ptref{p:int.comp}.
|
|
\item {\tt <\#} ( -- $S$), pushes an empty {\em String}. Typically used for starting the conversion of an {\em Integer\/} into its human-readable representation, decimal or in another base. Equivalent to {\tt ""}.
|
|
\item {\tt <{}<} ($x$ $y$ -- $x\cdot 2^y$), computes an arithmetic left shift of binary number $x$ by $y\geq0$ positions, yielding $x\cdot 2^y$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt <{}</} ($x$ $y$ $z$ -- $q$), computes $q:=\lfloor 2^zx/y\rfloor$ for $0\leq z\leq 256$ producing a 513-bit intermediate result, similarly to {\tt */}, cf.~\ptref{p:arith.op}. Equivalent to {\tt 1<{}< swap */}.
|
|
\item {\tt <{}</c} ($x$ $y$ $z$ -- $q$), computes $q:=\lceil 2^zx/y\rceil$ for $0\leq z\leq 256$ producing a 513-bit intermediate result, similarly to {\tt */c}, cf.~\ptref{p:arith.op}. Equivalent to {\tt 1<{}< swap */c}.
|
|
\item {\tt <{}</r} ($x$ $y$ $z$ -- $q$), computes $q:=\lfloor 2^zx/y+1/2\rfloor$ for $0\leq z\leq 256$ producing a 513-bit intermediate result, similarly to {\tt */r}, cf.~\ptref{p:arith.op}. Equivalent to {\tt 1<{}< swap */r}.
|
|
\item {\tt <=} ($x$ $y$ -- $?$), checks whether $x\leq y$ (i.e., pushes $-1$ if {\em Integer\/}~$x$ is less than or equal to {\em Integer\/}~$y$, $0$ otherwise), cf.~\ptref{p:int.comp}.
|
|
\item {\tt <>} ($x$ $y$ -- $?$), checks whether $x\neq y$ (i.e., pushes $-1$ if {\em Integer\/}s~$x$ and~$y$ are not equal, $0$ otherwise), cf.~\ptref{p:int.comp}.
|
|
\item {\tt <b} ( -- $b$), creates a new empty {\em Builder}, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt <s} ($c$ -- $s$), transforms a {\em Cell\/}~$c$ into a {\em Slice\/}~$s$ containing the same data, cf.~\ptref{p:slice.ops}. It usually marks the start of the deserialization of a cell.
|
|
\item {\tt =} ($x$ $y$ -- $?$), checks whether $x=y$ (i.e., pushes $-1$ if {\em Integer\/}s~$x$ and~$y$ are equal, $0$ otherwise), cf.~\ptref{p:int.comp}.
|
|
\item {\tt \underline{=:} $\langle\textit{word-name}\rangle$} ($x$ -- ), an active variant of {\tt constant}: defines a new ordinary word $\langle\textit{word-name}\rangle$ that would push the given value $x$ when invoked, cf.~\ptref{p:constants}.
|
|
\item {\tt >} ($x$ $y$ -- $?$), checks whether $x>y$ (i.e., pushes $-1$ if {\em Integer\/}~$x$ is greater than {\em Integer\/}~$y$, $0$ otherwise), cf.~\ptref{p:int.comp}.
|
|
\item {\tt >=} ($x$ $y$ -- $?$), checks whether $x\geq y$ (i.e., pushes $-1$ if {\em Integer\/}~$x$ is greater than or equal to {\em Integer\/}~$y$, $0$ otherwise), cf.~\ptref{p:int.comp}.
|
|
\item {\tt >{}>} ($x$ $y$ -- $q:=\lfloor x\cdot 2^{-y}\rfloor$), computes an arithmetic right shift of binary number $x$ by $0\leq y\leq 256$ positions, cf.~\ptref{p:arith.op}. Equivalent to {\tt 1<{}< /}.
|
|
\item {\tt >{}>c} ($x$ $y$ -- $q:=\lceil x\cdot 2^{-y}\rceil$), computes the ceiling-rounded quotient $q$ of $x$ by $2^y$ for $0\leq y\leq 256$, cf.~\ptref{p:arith.op}. Equivalent to {\tt 1<{}< /c}.
|
|
\item {\tt >{}>r} ($x$ $y$ -- $q:=\lfloor x\cdot 2^{-y}+1/2\rfloor$), computes the nearest-integer-rounded quotient $q$ of $x$ by $2^y$ for $0\leq y\leq 256$, cf.~\ptref{p:arith.op}. Equivalent to {\tt 1<{}< /r}.
|
|
\item {\tt ?dup} ($x$ -- $x$ $x$ or $0$), duplicates an {\em Integer\/} $x$, but only if it is non-zero, cf.~\ptref{p:stack.ops}. Otherwise leaves it intact.
|
|
\item {\tt @} ($p$ -- $x$), fetches the value currently stored in {\em Box\/}~$p$, cf.~\ptref{p:variables}.
|
|
\item {\tt \underline{@'} $\langle\textit{word-name}\rangle$} ( -- $e$), recovers the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked, and then executes this definition, cf.~\ptref{p:constants} and~\ptref{p:dict.lookup}. May be used to recover current values of constants inside word definitions and other blocks by using the phrase {\tt @' $\langle\textit{word-name}\rangle$}, equivalent to {\tt (') $\langle\textit{word-name}\rangle$ execute}.
|
|
\item {\tt B+} ($B'$ $B''$ -- $B$), concatenates two {\em Bytes\/} values, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B,} ($b$ $B$ -- $b'$), appends {\em Bytes\/}~$B$ to {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}. If there is no room in $b$ for $B$, throws an exception.
|
|
\item {\tt B=} ($B$ $B'$ -- $?$), checks whether two {\em Bytes\/} sequences are equal, and returns $-1$ or $0$ depending on the comparison outcome, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>Li@} ($B$ $x$ -- $y$), deserializes the first $x/8$ bytes of a {\tt Bytes} value~$B$ as a signed little-endian $x$-bit {\em Integer}~$y$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>Li@+} ($B$ $x$ -- $B'$ $y$), deserializes the first $x/8$ bytes of $B$ as a signed little-endian $x$-bit {\em Integer}~$y$ similarly to {\tt B>Li@}, but also returns the remaining bytes of~$B$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>Lu@} ($B$ $x$ -- $y$), deserializes the first $x/8$ bytes of a {\tt Bytes} value~$B$ as an unsigned little-endian $x$-bit {\em Integer}~$y$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>Lu@+} ($B$ $x$ -- $B'$ $y$), deserializes the first $x/8$ bytes of $B$ as an unsigned little-endian $x$-bit {\em Integer}~$y$ similarly to {\tt B>Lu@}, but also returns the remaining bytes of~$B$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>boc} ($B$ -- $c$), deserializes a ``standard'' bag of cells (i.e., a bag of cells with exactly one root cell) represented by {\em Bytes\/}~$B$, and returns the root {\em Cell\/}~$c$, cf.~\ptref{p:boc.ops}.
|
|
\item {\tt B>file} ($B$ $S$ -- ), creates a new (binary) file with the name specified in {\em String\/}~$S$ and writes data from {\em Bytes}~$B$ into the new file, cf.~\ptref{p:bytes.ops}. If the specified file already exists, it is overwritten.
|
|
\item {\tt B>i@} ($B$ $x$ -- $y$), deserializes the first $x/8$ bytes of a {\tt Bytes} value~$B$ as a signed big-endian $x$-bit {\em Integer}~$y$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>i@+} ($B$ $x$ -- $B'$ $y$), deserializes the first $x/8$ bytes of $B$ as a signed big-endian $x$-bit {\em Integer}~$y$ similarly to {\tt B>i@}, but also returns the remaining bytes of~$B$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>u@} ($B$ $x$ -- $y$), deserializes the first $x/8$ bytes of a {\tt Bytes} value~$B$ as an unsigned big-endian $x$-bit {\em Integer}~$y$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B>u@+} ($B$ $x$ -- $B'$ $y$), deserializes the first $x/8$ bytes of $B$ as an unsigned big-endian $x$-bit {\em Integer}~$y$ similarly to {\tt B>u@}, but also returns the remaining bytes of~$B$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B@} ($s$ $x$ -- $B$), fetches the first $x$ bytes (i.e., $8x$ bits) from {\em Slice}~$s$, and returns them as a {\em Bytes\/} value~$B$, cf.~\ptref{p:slice.ops}. If there are not enough data bits in $s$, throws an exception.
|
|
\item {\tt B@+} ($s$ $x$ -- $B$ $s'$), similar to {\tt B@}, but returns the remainder of {\em Slice\/} $s$ as well, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt B@?} ($s$ $x$ -- $B$ $-1$ or $0$), similar to {\tt B@}, but uses a flag to indicate failure instead of throwing an exception, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt B@?+} ($s$ $x$ -- $B$ $s'$ $-1$ or $s$ $0$), similar to {\tt B@+}, but uses a flag to indicate failure instead of throwing an exception, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt Bcmp} ($B$ $B'$ -- $x$), lexicographically compares two {\em Bytes\/} sequences, and returns $-1$, $0$, or $1$, depending on the comparison result, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt Bhash} ($B$ -- $B'$), computes the $\Sha$ hash of a {\em Bytes\/} value, cf.~\ptref{p:bytes.ops}. The hash is returned as a 32-byte {\em Bytes\/} value.
|
|
\item {\tt Blen} ($B$ -- $x$), returns the length of a {\em Bytes\/} value~$B$ in bytes, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt Bx.} ($B$ -- ), prints the hexadecimal representation of a {\em Bytes\/} value, cf.~\ptref{p:bytes.ops}. Each byte is represented by exactly two uppercase hexadecimal digits.
|
|
\item {\tt \underline{B\{}$\langle{\textit{hex-digits}}\rangle$\}} ( -- $B$), pushes a {\em Bytes\/} literal containing data represented by an even number of hexadecimal digits, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt B|} ($B$ $x$ -- $B'$ $B''$), cuts the first $x$ bytes from a {\em Bytes\/} value~$B$, and returns both the first $x$ bytes ($B'$) and the remainder ($B''$) as new {\em Bytes\/} values, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt Li>B} ($x$ $y$ -- $B$), stores a signed little-endian $y$-bit {\em Integer\/}~$x$ into a {\em Bytes\/} value $B$ consisting of exactly $y/8$ bytes. Integer $y$ must be a multiple of eight in the range $0\ldots256$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt Lu>B} ($x$ $y$ -- $B$), stores an unsigned little-endian $y$-bit {\em Integer\/}~$x$ into a {\em Bytes\/} value $B$ consisting of exactly $y/8$ bytes. Integer $y$ must be a multiple of eight in the range $0\ldots256$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt \underline{[}} ( -- ), opens an internal interpreter session even if {\tt state} is greater than zero, i.e., all subsequent words are executed immediately instead of being compiled.
|
|
\item {\tt []} ($t$ $i$ -- $x$), returns the $(i+1)$-st component $t_{i+1}$ of {\em Tuple\/}~$t$, where $0\leq i<|t|$, cf.~\ptref{p:tuples}.
|
|
\item {\tt \underline{[compile]} $\langle\textit{word-name}\rangle$} ( -- ), compiles $\langle\textit{word-name}\rangle$ as if it were an ordinary word, even if it is active, cf.~\ptref{p:dict.lookup}. Essentially equivalent to {\tt ' $\langle\textit{word-name}\rangle$ execute}.
|
|
\item {\tt \underline{]}} ($x_1$ \dots $x_n$ $n$ -- ), closes an internal interpreter session opened by {\tt [} and invokes {\tt (compile)} or {\tt (execute)} afterwards depending on whether {\tt state} is greater than zero. For instance, {\tt \{ [ 2 3 + 1 ] * \}} is equivalent to {\tt \{ 5 * \}}.
|
|
\item {\tt \underline{`}$\langle\textit{word\/}\rangle$} ( -- $a$), introduces an {\em Atom\/} literal, equal to the only {\em Atom\/} with the name equal to $\langle\textit{word\/}\rangle$, cf.~\ptref{p:atoms}. Equivalent to {\tt "$\langle\textit{word\/}\rangle$" atom}.
|
|
\item {\tt abort} ($S$ -- ), throws an exception with an error message taken from {\em String\/}~$S$, cf.~\ptref{p:exception.ops}.
|
|
\item {\tt \underline{abort"}$\langle\textit{message}\rangle$"} ($x$ -- ), throws an exception with the error message $\langle\textit{message}\rangle$ if the {\em Integer\/}~$x$ is non-zero, cf.~\ptref{p:exception.ops}.
|
|
\item {\tt abs} ($x$ -- $|x|$), computes the absolute value $|x|=\max(x,-x)$ of {\em Integer\/}~$x$. Equivalent to {\tt dup negate max}.
|
|
\item {\tt allot} ($n$ -- $t$), creates a new array, i.e., a {\em Tuple\/} that consists of $n$ new empty {\em Box\/}es, cf.~\ptref{p:tuples}. Equivalent to {\tt | \{ hole , \} rot times}.
|
|
\item {\tt and} ($x$ $y$ -- $x\& y$), computes the bitwise AND of two {\em Integer\/}s, cf.~\ptref{p:arith.op}.
|
|
\item {\tt anon} ( -- $a$), creates a new unique anonymous {\em Atom}, cf.~\ptref{p:atoms}.
|
|
\item {\tt atom} ($S$ -- $a$), returns the only {\em Atom\/}~$a$ with the name~$S$, creating such an atom if necessary, cf.~\ptref{p:atoms}. Equivalent to {\tt true (atom) drop}.
|
|
\item {\tt atom?} ($u$ -- $?$), checks whether $u$ is an {\em Atom}, cf.~\ptref{p:atoms}.
|
|
\item {\tt b+} ($b$ $b'$ -- $b''$), concatenates two {\em Builders\/} $b$ and~$b'$, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt b.} ($x$ -- ), prints the binary representation of an {\em Integer\/}~$x$, followed by a single space. Equivalent to {\tt b.\_ space}.
|
|
\item {\tt b.\_} ($x$ -- ), prints the binary representation of an {\em Integer\/}~$x$ without any spaces. Equivalent to {\tt (b.)~type}.
|
|
\item {\tt b>} ($b$ -- $c$), transforms a {\em Builder\/}~$b$ into a new {\em Cell\/}~$c$ containing the same data as~$b$, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt b>idict!} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new value $v$ (represented by a {\em Builder}) 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 b>idict!+} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new key-value pair $(x,v)$ into dictionary $s$ similarly to {\tt b>idict!}, but fails if the key already exists by returning the unchanged dictionary $s$ and $0$, cf.~\ptref{p:hashmap.ops}.
|
|
\item {\tt b>udict!} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new value $v$ (represented by a {\em Builder}) with key given by unsigned 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 b>udict!+} ($v$ $x$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds a new key-value pair $(x,v)$ into dictionary $s$ similarly to {\tt b>udict!}, but fails if the key already exists by returning the unchanged dictionary $s$ and $0$, cf.~\ptref{p:hashmap.ops}.
|
|
\item {\tt bbitrefs} ($b$ -- $x$ $y$), returns both the number of data bits $x$ and the number of references $y$ already stored in {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt bbits} ($b$ -- $x$), returns the number of data bits already stored in {\em Builder\/}~$b$. The result $x$ is an {\em Integer\/} in the range $0\dots1023$, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt bl} ( -- $x$), pushes the Unicode codepoint of a space, i.e., 32, cf.~\ptref{p:string.ops}.
|
|
\item {\tt boc+>B} ($c$ $x$ -- $B$), creates and serializes a ``standard'' bag of cells, containing one root {\em Cell\/}~$c$ along with all its descendants, cf.~\ptref{p:boc.ops}. An {\em Integer\/} parameter $0\leq x\leq 31$ is used to pass flags indicating the additional options for bag-of-cells serialization, with individual bits having the following effect:
|
|
\begin{itemize}
|
|
\item $+1$ enables bag-of-cells index creation (useful for lazy deserialization of large bags of cells).
|
|
\item $+2$ includes the CRC32-C of all data into the serialization (useful for checking data integrity).
|
|
\item $+4$ explicitly stores the hash of the root cell into the serialization (so that it can be quickly recovered afterwards without a complete deserialization).
|
|
\item $+8$ stores hashes of some intermediate (non-leaf) cells (useful for lazy deserialization of large bags of cells).
|
|
\item $+16$ stores cell cache bits to control caching of deserialized cells.
|
|
\end{itemize}
|
|
Typical values of $x$ are $x=0$ or $x=2$ for very small bags of cells (e.g., TON Blockchain external messages) and $x=31$ for large bags of cells (e.g., TON Blockchain blocks).
|
|
\item {\tt boc>B} ($c$ -- $B$), serializes a small ``standard'' bag of cells with root {\em Cell\/}~$c$ and all its descendants, cf.~\ptref{p:boc.ops}. Equivalent to {\tt 0 boc+>B}.
|
|
\item {\tt box} ($x$ -- $p$), creates a new {\em Box\/} containing specified value~$x$, cf.~\ptref{p:variables}. Equivalent to {\tt hole tuck !}.
|
|
\item {\tt brefs} ($b$ -- $x$), returns the number of references already stored in {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}. The result $x$ is an {\em Integer\/} in the range $0\dots4$.
|
|
\item {\tt brembitrefs} ($b$ -- $x$ $y$), returns both the maximum number of additional data bits $0\leq x\leq 1023$ and the maximum number of additional cell references $0\leq y\leq 4$ that can be stored in {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt brembits} ($b$ -- $x$), returns the maximum number of additional data bits that can be stored in {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}. Equivalent to {\tt bbits 1023 swap -}.
|
|
\item {\tt bremrefs} ($b$ -- $x$), returns the maximum number of additional cell references that can be stored in {\em Builder\/}~$b$, cf.~\ptref{p:builder.ops}.
|
|
\item {\tt bye} ( -- ), quits the Fift interpreter to the operating system with a zero exit code, cf.~\ptref{p:exit.fift}. Equivalent to {\tt 0 halt}.
|
|
\item {\tt \underline{b\{}$\langle\textit{binary-data}\rangle$\}} ( -- $s$), creates a {\em Slice}~$s$ that contains no references and up to 1023 data bits specified in $\langle\textit{binary-data}\rangle$, which must be a string consisting only of the characters `{\tt 0}' and `{\tt 1}', cf.~\ptref{p:slice.lit}.
|
|
\item {\tt caddr} ($l$ -- $h''$), returns the third element of a list. Equivalent to {\tt cddr car}.
|
|
\item {\tt cadr} ($l$ -- $h'$), returns the second element of a list, cf.~\ptref{p:lists}. Equivalent to {\tt cdr car}.
|
|
\item {\tt car} ($l$ -- $h$), returns the head of a list, cf.~\ptref{p:lists}. Equivalent to {\tt first}.
|
|
\item {\tt cddr} ($l$ -- $t'$), returns the tail of the tail of a list. Equivalent to {\tt cdr cdr}.
|
|
\item {\tt cdr} ($l$ -- $t$), returns the tail of a list, cf.~\ptref{p:lists}. Equivalent to {\tt second}.
|
|
\item {\tt \underline{char} $\langle\textit{string}\rangle$} ( -- $x$), pushes an {\em Integer\/} with the Unicode codepoint of the first character of {\tt $\langle\textit{string}\rangle$}, cf.~\ptref{p:string.ops}. For instance, {\tt char *} is equivalent to {\tt 42}.
|
|
\item {\tt chr} ($x$ -- $S$), returns a new {\em String\/}~$S$ consisting of one UTF-8 encoded character with Unicode codepoint~$x$.
|
|
\item {\tt cmp} ($x$ $y$ -- $z$), compares two {\em Integer\/}s $x$ and~$y$, and pushes $1$ if $x>y$, $-1$ if $x<y$, and $0$ if $x=y$, cf.~\ptref{p:int.comp}. Approximately equivalent to {\tt - sgn}.
|
|
\item {\tt cond} ($x$ $e$ $e'$ -- ), if {\em Integer\/} $x$ is non-zero, executes $e$, otherwise executes $e'$, cf.~\ptref{p:cond.ops}.
|
|
\item {\tt cons} ($h$ $t$ -- $l$), constructs a list from its head (first element) $h$ and its tail (the list consisting of all remaining elements)~$t$, cf.~\ptref{p:lists}. Equivalent to {\tt pair}.
|
|
\item {\tt constant} ($x$ -- ), scans a blank-delimited word name $S$ from the remainder of the input, and defines a new ordinary word $S$ as a constant, which will push the given value $x$ (of arbitrary type) when invoked, cf.~\ptref{p:dict.create} and~\ptref{p:constants}.
|
|
\item {\tt count} ($t$ -- $n$), returns the length $n=|t|$ of {\em Tuple\/}~$t$, cf.~\ptref{p:tuples}.
|
|
\item {\tt cr} ( -- ), outputs a carriage return (or a newline character) into the standard output, cf.~\ptref{p:string.ops}.
|
|
\item {\tt create} ($e$ -- ), defines a new ordinary word with the name equal to the next word scanned from the input, using {\em WordDef\/} $e$ as its definition, cf.~\ptref{p:dict.create}. If the word already exists, it is tacitly redefined.
|
|
\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 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.
|
|
\item {\tt ed25519\_chksign} ($B$ $B'$ $B''$ -- $?$), checks whether $B'$ is a valid Ed25519-signature of data $B$ with the public key $B''$, cf.~\ptref{p:ed25519.ops}.
|
|
\item {\tt ed25519\_sign} ($B$ $B'$ -- $B''$), signs data $B$ with the Ed25519 private key $B'$ (a 32-byte {\em Bytes\/} value) and returns the signature as a 64-byte {\em Bytes\/} value~$B''$, cf.~\ptref{p:ed25519.ops}.
|
|
\item {\tt ed25519\_sign\_uint} ($x$ $B'$ -- $B''$), converts a big-endian unsigned 256-bit integer $x$ into a 32-byte sequence and signs it using the Ed25519 private key $B'$ similarly to {\tt ed25519\_sign}, cf.~\ptref{p:ed25519.ops}. Equivalent to {\tt swap 256 u>B swap ed25519\_sign}. The integer $x$ to be signed is typically computed as the hash of some data.
|
|
\item {\tt emit} ($x$ -- ), prints a UTF-8 encoded character with Unicode codepoint given by {\em Integer\/} $x$ into the standard output, cf.~\ptref{p:string.ops}. For instance, {\tt 42 emit} prints an asterisk ``{\tt *}'', and {\tt 916 emit} prints a Greek Delta ``{\tt $\Delta$}''. Equivalent to {\tt chr type}.
|
|
\item {\tt empty?} ($s$ -- $?$), checks whether a {\em Slice\/} is empty (i.e., has no data bits and no references left), and returns $-1$ or $0$ accordingly, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt eq?} ($u$ $v$ -- $?$), checks whether $u$ and $v$ are equal {\em Integer\/}s, {\em Atom\/}s, or {\em Null\/}s, cf.~\ptref{p:atoms}. If they are not equal, or if they are of different types, or not of one of the types listed, returns zero.
|
|
\item {\tt exch} ($x_n$ \dots $x_0$ $n$ -- $x_0$ \dots $x_n$), interchanges the top of the stack with the $n$-th stack entry from the top, where $n\geq0$ is also taken from the stack, cf.~\ptref{p:stack.ops}. In particular, {\tt 1 exch} is equivalent to {\tt swap}, and {\tt 2 exch} to {\tt swap rot}.
|
|
\item {\tt exch2} (\dots $n$ $m$ -- \dots), interchanges the $n$-th stack entry from the top with the $m$-th stack entry from the top, where $n\geq0$, $m\geq0$ are taken from the stack, cf.~\ptref{p:stack.ops}.
|
|
\item {\tt execute} ($e$ -- \dots), executes the execution token ({\em WordDef\/}) $e$, cf.~\ptref{p:blocks}.
|
|
\item {\tt explode} ($t$ -- $x_1$ \dots $x_n$ $n$), unpacks a {\em Tuple\/}~$t=(x_1,\ldots,x_n)$ of unknown length~$n$, and returns that length, cf.~\ptref{p:tuples}.
|
|
\item {\tt false} ( -- $0$), pushes $0$ into the stack, cf.~\ptref{p:bool}. Equivalent to {\tt 0}.
|
|
\item {\tt file-exists?} ($S$ -- $?$), checks whether the file with the name specified in {\em String\/}~$S$ exists, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt file>B} ($S$ -- $B$), reads the (binary) file with the name specified in {\em String\/}~$S$ and returns its contents as a {\em Bytes\/} value, cf.~\ptref{p:bytes.ops}. If the file does not exist, an exception is thrown.
|
|
\item {\tt find} ($S$ -- $e$ $-1$ or $e$ $1$ or $0$), looks up {\em String\/} $S$ in the dictionary and returns its definition as a {\em WordDef\/}~$e$ if found, followed by $-1$ for ordinary words or $1$ for active words, cf.~\ptref{p:dict.lookup}. Otherwise pushes $0$.
|
|
\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 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 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$ -- $B$), computes the $\Sha$-based representation hash of {\em Cell\/}~$c$ (cf.~\cite[3.1]{TVM}), which unambiguously defines $c$ and all its descendants (provided there are no collisions for $\Sha$), cf.~\ptref{p:hash.ops}. The result is returned as a {\em Bytes\/} value consisting of exactly 32 bytes.
|
|
\item {\tt hold} ($S$ $x$ -- $S'$), appends to {\em String\/}~$S$ one UTF-8 encoded character with Unicode codepoint~$x$. Equivalent to {\tt chr \$+}.
|
|
\item {\tt hole} ( -- $p$), creates a new {\em Box\/}~$p$ that does not hold any value, cf.~\ptref{p:variables}. Equivalent to {\tt null box}.
|
|
\item {\tt i,} ($b$ $x$ $y$ -- $b'$), appends the big-endian binary representation of a signed $y$-bit integer~$x$ to {\em Builder\/}~$b$, where $0\leq y\leq 257$, cf.~\ptref{p:builder.ops}. If there is not enough room in $b$ (i.e., if $b$ already contains more than $1023-y$ data bits), or if {\em Integer\/}~$x$ does not fit into $y$ bits, an exception is thrown.
|
|
\item {\tt i>B} ($x$ $y$ -- $B$), stores a signed big-endian $y$-bit {\em Integer\/}~$x$ into a {\em Bytes\/} value $B$ consisting of exactly $y/8$ bytes. Integer $y$ must be a multiple of eight in the range $0\ldots256$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt i@} ($s$ $x$ -- $y$), fetches a signed big-endian $x$-bit integer from the first $x$ bits of {\em Slice}~$s$, cf.~\ptref{p:slice.ops}. If $s$ contains less than $x$ data bits, an exception is thrown.
|
|
\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 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$.
|
|
\item {\tt list} ($x_1$ \dots $x_n$ $n$ -- $l$), constructs a list $l$ of length~$n$ with elements $x_1$, \ldots, $x_n$, in that order, cf.~\ptref{p:lists}. Equivalent to {\tt null ' cons rot times}.
|
|
\item {\tt max} ($x$ $y$ -- $z$), computes the maximum $z:=\max(x,y)$ of two {\em Integer\/}s $x$ and~$y$. Equivalent to {\tt minmax nip}.
|
|
\item {\tt min} ($x$ $y$ -- $z$), computes the minimum $z:=\min(x,y)$ of two {\em Integer\/}s $x$ and~$y$. Equivalent to {\tt minmax drop}.
|
|
\item {\tt minmax} ($x$ $y$ -- $z$ $t$), computes both the minimum $z:=\min(x,y)$ and the maximum $t:=\max(x,y)$ of two {\em Integer\/}s $x$ and~$y$.
|
|
\item {\tt mod} ($x$ $y$ -- $r:=x\bmod y$), computes the remainder $x\bmod y=x-y\cdot\lfloor x/y\rfloor$ of division of $x$ by $y$, cf.~\ptref{p:arith.op}.
|
|
\item {\tt negate} ($x$ -- $-x$), changes the sign of an {\em Integer}, cf.~\ptref{p:arith.op}.
|
|
\item {\tt newkeypair} ( -- $B$ $B'$), generates a new Ed25519 private/public key pair, and returns both the private key $B$ and the public key $B'$ as 32-byte {\em Bytes\/} values, cf.~\ptref{p:ed25519.ops}. The quality of the keys is good enough for testing purposes. Real applications must feed enough entropy into OpenSSL PRNG before generating Ed25519 keypairs.
|
|
\item {\tt nil} ( -- $t$), pushes the empty {\em Tuple\/}~$t=()$. Equivalent to {\tt 0 tuple}.
|
|
\item {\tt nip} ($x$ $y$ -- $y$), removes the second stack entry from the top, cf.~\ptref{p:stack.ops}. Equivalent to {\tt swap drop}.
|
|
\item {\tt nop} ( -- ), does nothing, cf.~\ptref{p:dict.lookup}.
|
|
\item {\tt not} ($x$ -- $-1-x$), computes the bitwise complement of an {\em Integer}, cf.~\ptref{p:arith.op}.
|
|
\item {\tt now} ( -- $x$), returns the current Unixtime as an {\em Integer}, cf.~\ptref{p:ed25519.ops}.
|
|
\item {\tt null} ( -- $\bot$), pushes the {\em Null\/} value, cf.~\ptref{p:lists}
|
|
\item {\tt null!} ($p$ -- ), stores a {\em Null\/} value into {\em Box\/}~$p$. Equivalent to {\tt null swap !}.
|
|
\item {\tt null?} ($x$ -- $?$), checks whether $x$ is {\em Null}, cf.~\ptref{p:lists}.
|
|
\item {\tt or} ($x$ $y$ -- $x|y$), computes the bitwise OR of two {\em Integer\/}s, cf.~\ptref{p:arith.op}.
|
|
\item {\tt over} ($x$ $y$ -- $x$ $y$ $x$), creates a copy of the second stack entry from the top over the top-of-stack entry, cf.~\ptref{p:stack.ops}.
|
|
\item {\tt pair} ($x$ $y$ -- $t$), creates new pair $t=(x,y)$, cf.~\ptref{p:tuples}. Equivalent to {\tt 2 tuple} or to {\tt | rot , swap ,}.
|
|
\item {\tt pfxdict!} ($v$ $k$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds key-value pair $(k,v)$, both represented by {\em Slice\/}s, into a prefix dictionary $s$ with keys of length at most~$n$, cf.~\ptref{p:hashmap.ops}. On success, returns the modified dictionary $s'$ and $-1$. On failure, returns the original dictionary $s$ and $0$.
|
|
\item {\tt pfxdict!+} ($v$ $k$ $s$ $n$ -- $s'$ $-1$ or $s$ $0$), adds key-value pair $(k,v)$ into prefix dictionary $s$ similarly to {\tt pfxdict!}, but fails if the key already exists, cf.~\ptref{p:hashmap.ops}.
|
|
\item {\tt pfxdict@} ($k$ $s$ $n$ -- $v$ $-1$ or $0$), looks up key $k$ (represented by a {\em Slice\/}) in the prefix dictionary $s$ with the length of keys limited by $n$ bits, cf.~\ptref{p:hashmap.ops}. On success, returns the value found as a {\em Slice\/} $v$ and $-1$. On failure, returns $0$.
|
|
\item {\tt pick} ($x_n$ \dots $x_0$ $n$ -- $x_n$ \dots $x_0$ $x_n$), creates a copy of the $n$-th entry from the top of the stack, where $n\geq0$ is also passed in the stack, cf.~\ptref{p:stack.ops}. In particular, {\tt 0 pick} is equivalent to {\tt dup}, and {\tt 1 pick} to {\tt over}.
|
|
\item {\tt priv>pub} ($B$ -- $B'$), computes the public key corresponding to a private Ed25519 key, cf.~\ptref{p:ed25519.ops}. Both the public key~$B'$ and the private key~$B$ are represented by 32-byte {\em Bytes\/} values.
|
|
\item {\tt quit} ($\dots$ -- ), exits to the topmost level of the Fift interpreter (without printing an {\tt ok} in interactive mode) and clears the stack, cf.~\ptref{p:exit.fift}.
|
|
\item {\tt ref,} ($b$ $c$ -- $b'$), appends to {\em Builder\/}~$b$ a reference to {\em Cell\/}~$c$, cf.~\ptref{p:builder.ops}. If $b$ already contains four references, an exception is thrown.
|
|
\item {\tt ref@} ($s$ -- $c$), fetches the first reference from the {\em Slice\/}~$s$ and returns the {\em Cell}~$c$ referred to, cf.~\ptref{p:slice.ops}. If there are no references left, throws an exception.
|
|
\item {\tt ref@+} ($s$ -- $s'$ $c$), fetches the first reference from the {\em Slice\/} $s$ similarly to {\tt ref@}, but returns the remainder of $s$ as well, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt ref@?} ($s$ -- $c$ $-1$ or $0$), fetches the first reference from the {\em Slice}~$s$ similarly to {\tt ref@}, but uses a flag to indicate failure instead of throwing an exception, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt ref@?+} ($s$ -- $s'$ $c$ $-1$ or $s$ $0$), similar to {\tt ref@+}, but uses a flag to indicate failure instead of throwing an exception, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt remaining} ($s$ -- $x$ $y$), returns both the number of data bits $x$ and the number of cell references $y$ remaining in the {\em Slice}~$s$, cf.~\ptref{p:slice.ops}.
|
|
\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 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 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>}.
|
|
\item {\tt sbitrefs} ($s$ -- $x$ $y$), returns both the number of data bits $x$ and the number of cell references $y$ remaining in {\em Slice}~$s$, cf.~\ptref{p:slice.ops}. Equivalent to {\tt remaining}.
|
|
\item {\tt sbits} ($s$ -- $x$), returns the number of data bits $x$ remaining in {\em Slice}~$s$, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt second} ($t$ -- $x$), returns the second component of a {\em Tuple}, cf.~\ptref{p:tuples}. Equivalent to {\tt 1 []}.
|
|
\item {\tt sgn} ($x$ -- $y$), computes the sign of an {\em Integer\/} $x$ (i.e., pushes $1$ if $x>0$, $-1$ if $x<0$, and $0$ if $x=0$), cf.~\ptref{p:int.comp}. Equivalent to {\tt 0 cmp}.
|
|
\item {\tt shash} ($s$ -- $B$), computes the $\Sha$-based representation hash of a {\em Slice\/} by first transforming it into a cell, cf.~\ptref{p:hash.ops}. Equivalent to {\tt s>c hash}.
|
|
\item {\tt sign} ($S$ $x$ -- $S'$), appends a minus sign ``{\tt -}'' to {\em String\/}~$S$ if {\em Integer\/}~$x$ is negative. Otherwise leaves $S$ intact.
|
|
\item {\tt single} ($x$ -- $t$), creates new singleton $t=(x)$, i.e., a one-element {\em Tuple}. Equivalent to {\tt 1 tuple}.
|
|
\item {\tt skipspc} ( -- ), skips blank characters from the current input line until a non-blank or an end-of-line character is found.
|
|
\item {\tt smca>\$} ($x$ $y$ $z$ -- $S$), packs a standard TON smart-contract address with workchain $x$ (a signed 32-bit {\em Integer\/}) and in-workchain address $y$ (an unsigned 256-bit {\em Integer\/}) into a 48-character string $S$ (the human-readable representation of the address) according to flags~$z$, cf.~\ptref{p:smc.addr.ops}. Possible individual flags in~$z$ are: $+1$ for non-bounceable addresses, $+2$ for testnet-only addresses, and $+4$ for base64url output instead of base64.
|
|
\item {\tt space} ( -- ), outputs a single space. Equivalent to {\tt bl emit} or to {\tt ." "}.
|
|
\item {\tt sr,} ($b$ $s$ -- $b'$), constructs a new {\em Cell\/} containing all data and references from {\em Slice\/}~$s$, and appends a reference to this cell to {\em Builder}~$b$, cf.~\ptref{p:builder.ops}. Equivalent to {\tt s>c ref,}.
|
|
\item {\tt srefs} ($s$ -- $x$), returns the number of cell references $x$ remaining in {\em Slice}~$s$, cf.~\ptref{p:slice.ops}.
|
|
\item {\tt swap} ($x$ $y$ -- $y$ $x$), interchanges the two topmost stack entries, cf.~\ptref{p:stack.ops}.
|
|
\item {\tt ten} ( -- $10$), pushes {\em Integer\/} constant 10.
|
|
\item {\tt third} ($t$ -- $x$), returns the third component of a {\em Tuple}, cf.~\ptref{p:tuples}. Equivalent to {\tt 2 []}.
|
|
\item {\tt times} ($e$ $n$ -- ), executes execution token ({\em WordDef\/}) $e$ exactly $n$ times, if $n\geq0$, cf.~\ptref{p:simple.loops}. If $n$ is negative, throws an exception.
|
|
\item {\tt triple} ($x$ $y$ $z$ -- $t$), creates new triple $t=(x,y,z)$, cf.~\ptref{p:tuples}. Equivalent to {\tt 3 tuple}.
|
|
\item {\tt true} ( -- $-1$), pushes $-1$ into the stack, cf.~\ptref{p:bool}. Equivalent to {\tt -1}.
|
|
\item {\tt tuck} ($x$ $y$ -- $y$ $x$ $y$), equivalent to {\tt swap over}, cf.~\ptref{p:stack.ops}.
|
|
\item {\tt tuple} ($x_1$ \dots $x_n$ $n$ -- $t$), creates new {\em Tuple\/} $t:=(x_1,\ldots,x_n)$ from $n\geq0$ topmost stack values, cf.~\ptref{p:tuples}. Equivalent to {\tt dup 1 reverse | \{ swap , \} rot times}, but more efficient.
|
|
\item {\tt tuple?} ($t$ -- $?$), checks whether $t$ is a {\em Tuple}, and returns $-1$ or $0$ accordingly.
|
|
\item {\tt type} ($s$ -- ), prints a {\em String\/} $s$ taken from the top of the stack into the standard output, cf.~\ptref{p:string.ops}.
|
|
\item {\tt u,} ($b$ $x$ $y$ -- $b'$), appends the big-endian binary representation of an unsigned $y$-bit integer~$x$ to {\em Builder\/}~$b$, where $0\leq y\leq 256$, cf.~\ptref{p:builder.ops}. If the operation is impossible, an exception is thrown.
|
|
\item {\tt u>B} ($x$ $y$ -- $B$), stores an unsigned big-endian $y$-bit {\em Integer\/}~$x$ into a {\em Bytes\/} value $B$ consisting of exactly $y/8$ bytes. Integer $y$ must be a multiple of eight in the range $0\ldots256$, cf.~\ptref{p:bytes.ops}.
|
|
\item {\tt u@} ($s$ $x$ -- $y$), fetches an unsigned big-endian $x$-bit integer from the first $x$ bits of {\em Slice}~$s$, cf.~\ptref{p:slice.ops}. If $s$ contains less than $x$ data bits, an exception is thrown.
|
|
\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 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.
|
|
\item {\tt unpair} ($t$ -- $x$ $y$), unpacks a pair $t=(x,y)$, cf.~\ptref{p:tuples}. Equivalent to {\tt 2 untuple}.
|
|
\item {\tt unsingle} ($t$ -- $x$), unpacks a singleton $t=(x)$. Equivalent to {\tt 1 untuple}.
|
|
\item {\tt until} ($e$ -- ), an until loop, cf.~\ptref{p:loops}: executes {\em WordDef\/}~$e$, then removes the top-of-stack integer and checks whether it is zero. If it is, then begins a new iteration of the loop by executing $e$. Otherwise exits the loop.
|
|
\item {\tt untriple} ($t$ -- $x$ $y$ $z$), unpacks a triple $t=(x,y,z)$, cf.~\ptref{p:tuples}. Equivalent to {\tt 3 untuple}.
|
|
\item {\tt untuple} ($t$ $n$ -- $x_1$ \dots $x_n$), returns all components of a {\em Tuple\/}~$t=(x_1,\ldots,x_n)$, but only if its length is equal to~$n$, cf.~\ptref{p:tuples}. Otherwise throws an exception.
|
|
\item {\tt variable} ( -- ), scans a blank-delimited word name $S$ from the remainder of the input, allocates an empty {\em Box}, and defines a new ordinary word $S$ as a constant, which will push the new {\em Box\/} when invoked, cf.~\ptref{p:variables}. Equivalent to {\tt hole constant}.
|
|
\item {\tt while} ($e$ $e'$ -- ), a while loop, cf.~\ptref{p:loops}: executes {\em WordDef\/}~$e$, then removes and checks the top-of-stack integer. If it is zero, exits the loop. Otherwise executes {\em WordDef\/}~$e'$, then begins a new loop iteration by executing $e$ and checking the exit condition afterwards.
|
|
\item {\tt word} ($x$ -- $s$), parses a word delimited by the character with the Unicode codepoint $x$ from the remainder of the current input line and pushes the result as a {\em String}, cf.~\ptref{p:string.ops}. For instance, {\tt bl word abracadabra type} will print the string ``{\tt abracadabra}''. If $x=0$, skips leading spaces, and then scans until the end of the current input line. If $x=32$, skips leading spaces before parsing the next word.
|
|
\item {\tt words} ( -- ), prints the names of all words currently defined in the dictionary, cf.~\ptref{p:dict.lookup}.
|
|
\item {\tt x.} ($x$ -- ), prints the hexadecimal representation (without the {\tt 0x} prefix) of an {\em Integer\/}~$x$, followed by a single space. Equivalent to {\tt x.\_ space}.
|
|
\item {\tt x.\_} ($x$ -- ), prints the hexadecimal representation (without the {\tt 0x} prefix) of an {\em Integer\/}~$x$ without any spaces. Equivalent to {\tt (x.)~type}.
|
|
\item {\tt xor} ($x$ $y$ -- $x\oplus y$), computes the bitwise eXclusive OR of two {\em Integer\/}s, cf.~\ptref{p:arith.op}.
|
|
\item {\tt \underline{x\{}$\langle\textit{hex-data}\rangle$\}} ( -- $s$), creates a {\em Slice}~$s$ that contains no references and up to 1023 data bits specified in $\langle\textit{hex-data}\rangle$, cf.~\ptref{p:slice.lit}. More precisely, each hex digit from $\langle\textit{hex-data}\rangle$ is transformed into four binary digits in the usual fashion. After that, if the last character of $\langle\textit{hex-data}\rangle$ is an underscore {\tt \_}, then all trailing binary zeroes and the binary one immediately preceding them are removed from the resulting binary string (cf.~\cite[1.0]{TVM} for more details). For instance, {\tt x\{6C\_\}} is equivalent to {\tt b\{01101\}}.
|
|
\item {\tt \underline{\{}} ( -- $l$), an active word that increases internal variable {\tt state} by one and pushes a new empty {\em WordList\/} into the stack, cf.~\ptref{p:wordlist.ops}.
|
|
\item {\tt |} ( -- $t$), creates an empty {\em Tuple\/} $t=()$, cf.~\ptref{p:tuples}. Equivalent to {\tt nil} and to {\tt 0 tuple}.
|
|
\item {\tt |+} ($s$ $s'$ -- $s''$), concatenates two {\em Slice}\/s $s$ and $s'$, cf.~\ptref{p:slice.lit}. This means that the data bits of the new {\em Slice\/} $s''$ are obtained by concatenating the data bits of $s$ and $s'$, and the list of {\em Cell\/} references of $s''$ is constructed similarly by concatenating the corresponding lists for $s$ and $s'$. Equivalent to {\tt <b rot s, swap s, b> <s}.
|
|
\item {\tt |\_} ($s$ $s'$ -- $s''$), given two {\em Slice\/}s $s$ and $s'$, creates a new {\em Slice\/} $s''$, which is obtained from $s$ by appending a new reference to a {\em Cell\/} containing $s'$, cf.~\ptref{p:slice.lit}. Equivalent to {\tt <b rot s, swap s>c ref, b> <s}.
|
|
\item {\tt \underline{\}}} ($l$ -- $e$), an active word that transforms a {\em WordList\/}~$l$ into a {\em WordDef\/} (an execution token) $e$, thus making all further modifications of~$l$ impossible, and decreases internal variable {\tt state} by one; then pushes the integer $1$, followed by a {\tt 'nop}, cf.~\ptref{p:wordlist.ops}. The net effect is to transform the constructed {\em WordList\/} into an execution token and push this execution token into the stack, either immediately or during the execution of an outer block.
|
|
\end{itemize}
|
|
|
|
\end{document}
|