Getting started
First you need to include the module you want to use. For example, to include the fraction module (and all modules which are needed by the fraction module), you would do:
include ffl/frc.fs
You can also include all modules at once with:
include ffl/ffl.fs
Many modules store state in a variables. These modules provide three ways to allocate and initialize the variable. For example, after including the dynamic string module, you could:
1. Create a variable named var1 in the dictionary with:
str-create var1
2. Dynamically allocate and free an sha1 variable with:
str-new
str-free
3. If you prefer to allocate the variable yourself, you can get the necessary size with:
str%
After allocating the variable, you must initialize it with:
str-init
and when you are finished with the variable, free the internal, private variables with:
str-(free)
The documentation for all modules is listed on the documentation page. The module documentation gives an overview of all the words in that module. Also there are for an increasing number of modules small code examples.
Hands on
Modules
If you want to use a module, you start with including the module in your forth engine. For example if you want to do fraction calculations, you start with:
include ffl/frc.fs
This will include the fraction module and also all modules that are needed by the fraction module. After including you can use the module. For example, if you want to multiply two fractions, you can enter:
1 4 2 3 frc+multiply
This will multiply 1/4 times 2/3. By entering .s you will see the result: 2 12, which is 2/12. You can then normalize, convert the fraction to a string and type it by entering:
frc+to-string type
This will show the result: 1/6
Dictionary variables
The following example shows the use of modules that store a state in a variable. This example uses the sha1 module in the ffl library. First include the module in your forth engine:
include ffl/sh1.fs
Then create a sha1 variable which will contain the state of the calculation. You can create the variable in the dictionary by entering:
sh1-create var1
This creates a new word, var1, which is a sha1 variable. Next you can start calculating the sha1 algorithm by feeding data to the variable:
s" ab" var1 sh1-update
s" c" var1 sh1-update
In this example the sha1 variable is fed with the string abc. The next step is finishing the calculation. This is done by:
var1 sh1-finish sh1+to-string type
So the sha1 calculation is finished and the resulting hash value is converted to a string, which is then typed. If all went well, it should show: A9993E364706816ABA3E25717850C26C9CD0D89D which is the secure hash1 result of the string "abc".
Heap variables
Besides creating a sha1 variable in the dictionary, you can also allocate a sha1 variable on the heap by entering:
sh1-new
Now there is a dynamic allocated sha1 variable on the stack. Feeding data to this variable can be done by:
dup s" ab" rot sh1-update
dup s" c" rot sh1-update
And finishing the calculation by:
dup sh1-finish sh1+to-string type
Which resulted in the same sha1 value. When you don't need the dynamic variable anymore you can free the memory used by the variable by entering:
sh1-free
Index
Some modules allow you to use an index to access members of a collection (an array, list, etc.). All indices are zero-based, so index 0 is the first element, index 1 is the second element, and so on.
Negative indices can also be used, and index backward from the end of the collection. That is, index -1 is the last element in the collection, index -2 is the next-to-last element, and so on.
If the value of an index is not valid in a collection, the exception exp-index-out-of-range is thrown.
Reader
The tis, xis and dom modules use a reader word. This word makes it possible to feed these modules with data from different sources.
For example for feeding data from a text file, the following reader can be used:
: file-reader ( file-id -- c-addr u | 0 = Read data from a text file)
pad 80 rot read-file throw
dup IF
pad swap
THEN
;
The stack notation for the reader is ( x — c-addr u | 0), in which x is the specific state for the reader and c-addr u is the read data.
To let the tis module use this reader word, use the following example code:
\ Open the 'file.txt' file and save the file-id in variable txt-file
s" file.txt" r/o open-file throw value txt-file
\ Setup a file reader for tis1 variable
txt-file ' file-reader tis1 tis-set-reader
\ Close the file
txt-file file-close throw
The stack notation for the tis-set-reader word is (x xt tis — ), in which x is the specific state for the reader. This x is fed to the reader (see above). Xt is the reader word itself.
The xis module can also use this reader word. See the following example code:
\ Open the 'file.xml' file and save the file-id in variable reader-file
s" file.xml" r/o open-file throw value xml-file
\ Setup a file reader for xis1 variable
xml-file ' file-reader xis1 xis-set-reader
\ Close the file
xml-file file-close throw
Versions
As soon as a module of the ffl is included, the library version constant ffl.version is created. This constant returns the version number of the library. For example for version 0.4.0 the constant returns 000400.
When a module is included, it defines a constant with the version of that module. The name of this constant is the name of the module followed by '.version'. So the constant frc.version returns the version of the fraction module.
The constant for the module version starts with number 1 after the initial creation of the module. Then every time the interface of the module changes or the functionality of the module increases, the version number is increased by 1. The version number is not changed if a small bug is fixed in the module.
The version constants can be used to check if the library or module is present in the forth dictionary: [DEFINED] frc.version. It can also be used to check if the code in the dictionary is up to date: frc.version 2 =.