Since version 0.6.0 FFL uses the ANS stack notation.

Stack parameters input to and output from a word are described by: ( stack: before -- after) where stack specifies which stack is used. The code for the control-flow-stack is C:, for the return-stack it is R: and for the float stack F:. If no stack identifier is present in the notation, the data stack is used.

The before info represents the stack parameter data types before execution of the word and after represents them after execution. The top of the stack is to the right. The following symbols are used in before and after:

Symbol Data type
flag flag
true true flag
false false flag
char character
n signed number
+n non-negative number
u unsigned number
x unspecified cell
xt execution token
addr address
a-addr aligned address
c-addr character-aligned address
d double-cell signed number
+d double-cell non-negative number
ud double-cell unsigned number
xd unspecified cell pair
i*x, j*x, k*x any data type
r float number

As an addition to this table the FFL variables on the stack are represented by the three alphabetic characters of the defining module. For example the stack notation of the sh1-finish word, used in the Starting chapter is: ( sh1 -- u1 u2 u3 u4 u5 ). This word expects a sh1 variable on stack and returns five unsigned numbers. The FFL variables are actually aligned addresses (a-addr).

It is possible that a word returns different stack parameters after execution. This is described by after1 | after2.

If a word has both compile time as run time behaviour, this is described by ( before1 -- after1 ; before2 -- after2 ). The stack parameters before1 and after1 specifies stack behaviour during compilation time and before2 and after2 during run time.

A few words in the FFL parse text during compilation. Those words use the following syntax: ( before "parsed-text-abbreviation" -- after ). The parsed-text-abbreviation uses the following specifications:

Abbreviation Description
<char> the char marking the end of the parsed string
<chars> zero or more chars
<space> a delimiting space character
<spaces> zero or more spaces
<quote> a delimiting double quote
<paren> a delimiting right parenthesis
<eol> a delimiting end of line
ccc arbitrary characters, excluding the delimiter character
name a token delimited by space

Word naming

There are two different type of words in the FFL: general use words and library words.

General words

The general words perform small, general actions. They use normal, descriptive names. Exampes are nil<>, #bits/byte, begin-stringtable and so on.

Library words

The name of the library words start with a prefix, followed by a special character and ends with a descriptive name. The prefix is equal to the module name. The special character is one of the following:

Char Description
% this word returns the size of the module variable, for example: sh1%
. this word is an enumeration, variable, value, constant of defer in the module, for example: sh1.version
+ this word expects no module variables on the stack, for example: frc+multiply
- this word expects one module variable on the stack, for example: sh1-update
^ this word expects two module variables on the stack, for example: str^move

The descriptive name specifies the action that the word performs on the optional stack parameters. Some special characters are used for abbreviations:

Char Description
? the word performs a check and will return a boolean flag, for example: str-index?
@ the word fetches the state of an internal variable, for example: dtm-day@
! the word stores the state of an internal variable, for example: dtm-day!
+ the word performs an addition or incrementation, for example: dti-seconds+
- the word performs an subtraction or decrementation, for example: dti-seconds-
( ) the word performs an action on the internal state, for example: str-(free)


Due to historical reasons there are two groups of words that do not follow this naming convention. Those are module-name-create and module-name-new. Based on the name you should expect that those words expect a module variable on the stack, but actually they don't. So they should be named module-name+create and module-name+new, but again for historical reasons they are not.