Integers
Fift recognizes integers in decimal, binary, and hexadecimal formats. Binary literals are prefixed by0b, hexadecimal literals are prefixed by 0x, and decimal literals do not require a prefix.
Examples:
- to change its sign; the minus sign is accepted both before and after the 0x and 0b prefixes.
Examples:
1 is pushed first, followed by 0xa (i.e., 10), followed by 3, and finally -0b10 (i.e., -2), leaving -0b10 at the top of the stack.
Fift has special syntax for decimal and common fractions. If a string consists of two valid integer literals separated by a slash /, then Fift interprets it as a fractional literal and represents it by two Integer_’s p and q in the stack, the numerator p and the denominator q.
For instance, -17/12 pushes -17 and 12 into the Fift stack, being thus equivalent to executing -17 12; and -0x11/0b1100 does the same thing. Decimal, binary, and hexadecimal fractions, such as 2.39 or -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, 2.39 is equivalent to 239 100, and -0x11.ef is equivalent to -0x11ef 0x100.
Such a representation of fractions is useful for defining “rational arithmetic operations”. For example, the following code defines two words R- and R* that carry out rational subtraction and multiplication, respectively. Word R- takes the stack a b c d, representing the fractions a/b and c/d, and produces the stack (a*d-b*c) b*d, representing the arithmetical subtraction a/b - c/d = (a*d-b*c) / (b*d). Similarly, word R* takes the stack a b c d, representing the fractions a/b and c/d, and produces the stack a*c b*d, representing the arithmetical multiplication a/b * c/d = (a*c) / (b*d).
1.7 2/3 R- 5/2 R* will produce the stack 155 60, corresponding to the arithmetical operation (1.7 - 2/3) * 5/2 = 31/30 * 5/2 = 155/60.
For advanced details on integers, see the Integers section in the Fift whitepaper.
Strings
A string is any sequence of UTF-8 characters enclosed by double quotes". When Fift recognizes a string, it pushes it into the Fift stack as a value of type String. For instance, "Hello, world!" pushes the corresponding String into the stack:
Booleans
As described in the Types page, Fift does not have a separate type for booleans. Instead, booleans are emulated usingIntegers, where -1 represents truth, and 0 falsehood. Comparison primitives normally return -1 to indicate success and 0 otherwise. Fift has the constants true and false to push these special integers into the stack:
| Word | Description |
|---|---|
true | pushes -1 into the stack. |
false | pushes 0 into the stack. |
-1. Fift has the word 0<> that transforms any non-zero integer into -1, and leaves 0 unchanged. For instance:
Null
Fift has the two wordsnull and null? to work with values of type Null. The word null pushes to the stack the null value, while the word null? consumes the value at the top of the stack and checks if such value is null or not. If the value is null, word null? pushes -1 to the stack, 0 otherwise.
For instance:
Boxes
ABox is a location or container that can be used to store exactly one value of any Fift-supported type. They are usually used to define variables and mutable data structures, like mutable tuples.
Fift provides the words hole and box to create boxes. Word hole pushes an empty box to the top of the stack, i.e., an empty box is a box containing the null value. Word box consumes the value v at the top of the stack and pushes a box containing v.
For instance:
Box may be fetched by means of word @ (pronounced “fetch”), and modified by means of word ! (pronounced “store”).
Word @ consumes the box at the top of the stack and pushes the value contained in the box. Word ! requires a stack of the form x p, where x is the value to store and p is the box in which x is going to be stored. ! consumes both x and p and stores x in p. Word ! does not push anything into the stack.
For instance:
Tuples
Tuples are ordered collections of arbitrary values of any type. When aTuple consists of values [ x1 ... xn ] (in that order), the number n is called the length of the tuple. Tuples of length two are called pairs; tuples of length three are triples. A tuple with no elements is called the empty tuple.
To construct tuples of known length, Fift provides the word tuple. The word tuple requires that the tuple’s data be laid out in the stack as follows x1 x2 ..... xn n, where x1, x2, ..., xn are the n values in the tuple, and n is the length of the tuple, located at the top of the stack. For example, to construct tuple [ 1 2 5 7 ] consisting of 4 values, execute 1 2 5 7 4 tuple, which will push the integers 1, 2, 5, 7 into the stack, then it will push integer 4, which is the tuple’s length, and finally, Fift will execute the word tuple, which will consume the numbers 1, 2, 5, 7, 4 from the stack and push the tuple [ 1 2 5 7 ] at the top of the stack.
To build pairs and triples it is possible to use the words pair and triple, respectively. For example, to build pair [ x1 x2 ], execute x1 x2 pair, which is equivalent to executing x1 x2 2 tuple. To build triple [ x1 x2 x3 ], execute x1 x2 x3 triple, which is equivalent to executing x1 x2 x3 3 tuple.
To append a value x at the end of tuple t, Fift provides the word ,. The word , requires that t and x be laid out in the stack as t x, where x is at the top of the stack. The word then consumes t and x from the stack, appends x to the end of t and pushes the resulting tuple to the end of the stack. For example, suppose the stack contains [ 1 2 ] 3, where [ 1 2 ] is a tuple, and 3 is the element to add located at the top of the stack; executing , will consume [ 1 2 ] and 3 from the stack and push the tuple [ 1 2 3] at the top of the stack.
Use word | to push the empty tuple at the top of the stack. Using words | and , in combination, allows the construction of tuples in stages, starting from the empty tuple. For instance, the following produces tuple [ 2 3 9 ] at the top of the stack:
| pushes the empty tuple at the top of the stack; 2 then pushes 2 at the top of the stack, producing the stack [ ] 2, where [ ] denotes the empty tuple. Next, word , consumes [ ] and 2, and pushes the tuple [ 2 ] at the top of the stack. Then, 3 pushes 3 at the top of the stack, producing the stack [ 2 ] 3, which then gets consumed by word , to produce tuple [ 2 3 ] at the top of the stack. Finally, 9 pushes 9 to produce stack [ 2 3 ] 9, which then gets consumed by word , to produce [ 2 3 9 ] at the top of the stack.
The components of a Tuple are not necessarily of the same type, and the components can also be a Tuple. For instance:
Tuple has been constructed, it is possible to extract any of its components, or completely unpack the Tuple into the stack. For this, Fift provides words [] and explode, respectively.
The word [] extracts a specific index from a tuple. Word [] requires that the stack has the form t i, where t is the tuple and i is the index to extract. When word [] executes, it consumes the elements t i from the stack and pushes to the top of the stack the i-th element in t. Indexes start counting from 0, so that if a tuple has n components, index i must satisfy 0 <= i < n.
For instance, the following defines a 3x3 matrix of integers Matrix, and then, accesses entry at row 1 and column 2:
6 at the top of the stack. Line Matrix 1 [] 2 [] executes as follows. First, constant Matrix pushes the entire matrix at the top of the stack. Next, 1 pushes 1 to the top of the stack, so the the stack now looks like Matrix 1. Next, word [] consumes Matrix and 1 from the stack and pushes [ 4 5 6 ] to the top of the stack, i.e., the row at index 1. Finally, 2 pushes 2 to the stack, and [] consumes [ 4 5 6 ] and 2, and pushes 6 to the top of the stack, i.e., the element at index 2. The notation Matrix 1 [] 2 [] is very reminiscent of the notation Matrix[1][2] usually found in programming languages.
The word explode extracts all the components of a tuple and pushes them into the stack. The word explode requires that the stack has the form [x1 x2 ... xn], i.e., a tuple of n elements at the top of the stack. When explode executes, it consumes the tuple at the top of the stack and produces the stack x1 x2 ... xn n, where the number of elements n is at the top of the stack.
For instance, the following defines a constant A containing the tuple [ 7 8 9 ], and the second line decomposes the tuple:
7 8 9 3 in the stack, where 3, the number at the top of the stack, is the number of elements in the original tuple.
Tuples are immutable: it is not possible to change a component of a Tuple. If the intention is to create something like an array, where the components can be freely updated, a Tuple of Boxes needs to be created.
Fift has the word allot that creates a tuple of a specified number of boxes. The word allot takes the integer n at the top of the stack and creates a tuple of n empty boxes, i.e., each box contains null. Later, it is possible to mutate the boxes using the word !.
For instance, the following defines a constant A containing a tuple of 10 empty boxes. Later, it sets the 0-th box to contain the integer 10, and 2-th box to contain string "foo".
10 A 0 [] ! pushes 10 into the stack. Then A 0 [] pushes the 0-th box into the stack. Finally, ! consumes both the box and 10 and updates the contents of the box to 10. The code "foo" A 2 [] ! has a similar explanation.
For advanced details about tuple, see the Tuples section in the Fift whitepaper.
Lists
Lisp-style lists can also be represented in Fift. A list(1 2 3) can be represented by nesting 2-tuples [ 1 [ 2 [ 3 null ] ] ], where null represents the empty list. Fift provides several words to create and deconstruct lists.
The word cons takes a stack of the form h l, where h is a value and l is a list, i.e., a nested tuple; consumes both h and l, and produces the tuple [ h l ].
For instance, the following code produces the list (1 2 3):
1 2 3 null produces the stack 1 2 3 null, where null is at the top of the stack. Then, the first cons produces the stack 1 2 [ 3 null ], where tuple [ 3 null ] is at the top of the stack. Next, the second cons produces the stack 1 [ 2 [ 3 null ] ]. Finally, the third cons produces the stack [ 1 [ 2 [ 3 null ] ] ] containing a single tuple at the top, which is the list (1 2 3).
It is so common to build fixed-length lists like in the above example, that Fift provides a special word for building a list when the elements are known. The word list takes a stack of the form x1 ... xn n, where n is the number of elements in the list, and consumes x1, ..., xn and n from the stack to produce the list (x1 .... xn) at the top of the stack.
For instance, the following produces the same list as the previous example:
The list constructed with the code:is different from the tuple constructed with the code:The list is really the nested tuple
[ 1 [ 2 [ 3 null ] ] ], while the tuple is simply [ 1 2 3 ].uncons. The word uncons consumes the list at the top of the stack and pushes the list’s head followed by the list’s tail. For instance, the following code defines a constant A containing list (5 6 7) and deconstruct the list by calling uncons several times:
uncons produces the stack 5 [ 6 [ 7 null ] ]. The second uncons the stack 5 6 [ 7 null ]. Finally, the third uncons produces the stack 5 6 7 null. Since there is a null at the top of the stack, drop removes the null to produce the stack 5 6 7.
For advanced details about lists, see the Lists section in the Fift whitepaper.
Atoms
AnAtom is an entity uniquely identified by its name. Atoms can be used to represent identifiers, labels, operation names, tags, and stack markers. Fift offers several words to create and manipulate Atoms.
The word `name pushes into the stack the atom identified by name. For instance, the following builds the list (+ 2 (* 3 4)), which is the Lisp-style representation of arithmetical expression 2 + (3 * 4):
`+ 2 `* 3 4 3 produces the stack + 2 * 3 4 3, where + and * are atoms, i.e., identifiers. Then, list produces the stack + 2 (* 3 4), where list (* 3 4) is at the top of the stack. Next, 3 produces the stack + 2 (* 3 4) 3. Finally, list produces the stack (+ 2 (* 3 4)), containing the final list at the top of the stack.
It is possible to compare atoms using the word eq?. The word eq? consumes the two top-most elements in a stack of the form u v where u and v are the atoms to compare, and pushes to the stack -1 if the atoms are equal, 0 otherwise.
For instance,
Slices
ASlice is a read-only view of a portion of a Cell. Fift uses the syntax b{<binary-data>} and x{<hex-data>} for defining slices.
b{<binary-data>} pushes a slice into the stack that contains no references and up to 1023 data bits specified in <binary-data>, which must be a string consisting only of the characters 0 and 1.
x{<hex-data>} pushes a slice into the stack that contains no references and up to 1023 data bits specified in <hex-data>. More precisely, each hex digit from <hex-data> is transformed into four binary digits in the usual fashion. After that, if the last character of <hex-data> is an underscore _, then all trailing binary zeroes and the binary digit immediately preceding them are removed from the resulting binary string.
An empty Slice can be pushed into the stack by b{} or x{}.
For example, b{00011101} and x{1d} both push the same Slice consisting of eight data bits and no references. Similarly, b{111010} and x{EA_} push the same Slice consisting of six data bits. For x{EA_} the binary representation of EA is 11101010, but since EA_ has a final underscore, the trailing zeroes in the binary representation are removed together with the binary digit immediately preceding them, i.e., the final 10, producing 111010.
To construct a Slice with some Cell references, Fift provides the word |_, which consumes the top-most two elements in a stack of the form s s', where s and s' are slices. It crates a new slice s'' obtained from s by appending a new reference to a cell containing s'; then, pushes s'' into the stack.
For instance, the following code creates a cell containing the slice b{001}, and attaches the cell as a reference to the slice b{101}:
b{101} b{001} pushes the two slices in that order. Next, |_ consumes the two slices. Then, |_ copies b{101} into a new slice s and creates a cell c containing b{001}. Finally, |_ attaches c as a reference to s and pushes s into the stack.
For advanced details about slices, see the Slices section in the Fift whitepaper. For a list of words for manipulating slices and reading their contents, see the list of common slice words page.