Forth:Tutorials:Scripting with Ficl and Cpp

From GPWiki
Jump to: navigation, search

Embedding FICL in C/C++

A quick and dirty mini tutorial.

I like Forth. There is something about that language that keep me coming back to it. It's really simple, but feels both elegant and powerful. I just had to have it as a script language in my projects.

FICL (Forth Inspired Command Language) is a nice interpreter and that is what we're going to embed.

Here we go:

#include "ficl.h"

I don't have to comment that line, do I? Next, we must create our ficl system:

ficlSystem* sys = ficlSystemCreate(NULL);

The system contains the dictionary our scripts are going to use. Then we must create a virtual machine. It will contain the stacks and whatnot:

ficlVm* vm = ficlSystemCreateVm( sys );

The vm is where the magic happens. Remember to clean up after yourself when you are done:

ficlSystemDestroy( sys );

It will automatically destroy any created vms, so you don't have to worry about that.


That was the init and cleanup parts. Now let's run some scripts.

ficlVmEvaluate( vm, "1 1 + ." )

Wow. Just... wow. We have a calculator.


Add our own words

The fun begins when we add our own words to the system dictionary:

static void candy_man_func( ficlVm *vm )
{
    // Do nothing.
}
 
 
// and elsewhere in the code:
 
ficlDictionary *dict = ficlSystemGetDictionary( sys );
ficlWord *word = ficlDictionarySetPrimitive( dict, "CandyMan", candy_man_func, FICL_WORD_DEFAULT );


What are we doing here? We created a function that accepts a vm. We then asked the system for the current dictionary. To finish things off, we added or function to the dictionary. It can now be called from within the scripts under the name CandyMan

Nifty!

ficlVmEvaluate( vm, "CandyMan" );


If nothing at all happend, it worked! Time to make it a bit more useful.

static void candy_man_func( ficlVm *vm )
{
    // Get number of candybars
    int bars = ficlStackPopInteger( vm->dataStack );
 
    // Get the price for one candybar
    int price = ficlStackPopInteger( vm->dataStack );
 
    // Calculate the total price
    int total = bars * price;
 
    // Add a little something for rainy days...
    total += 5;
 
    // Jam it back into the stack 
    ficlStackPushInteger( vm->dataStack, total );
 
    // And we're done!
}


There. Now it does something. But you must call it with some values on the stack, otherwise you will get stack underflows.

ficlVmEvaluate( vm, " 1024 2 CandyMan ." );

There. 1024 candybars at 2 dollars each. Calculate the total sum and print it. Here is the complete source:


#include "ficl.h"
 
 
static void candy_man_func( ficlVm *vm )
{
    // Get number of candybars
    int bars = ficlStackPopInteger( vm->dataStack );
    // Get the price for one candybar
    int price = ficlStackPopInteger( vm->dataStack );
 
    // Calculate the total price
    int total = bars * price;
 
    // Add a little something for rainy days...
    total += 5;
 
    // Jam it back into the stack 
    ficlStackPushInteger( vm->dataStack, total );
 
    // And we're done!
}
 
 
int main()
{
 
    ficlSystem* sys = ficlSystemCreate(NULL);
    ficlVm* vm = ficlSystemCreateVm( sys );
 
    ficlDictionary *dict = ficlSystemGetDictionary( sys );
    ficlWord *word = ficlDictionarySetPrimitive( dict, "CandyMan", candy_man_func, FICL_WORD_DEFAULT );
 
    ficlVmEvaluate( vm, " 1024 2 CandyMan ." );
 
    ficlSystemDestroy( sys );
 
    return 0;
}

That's it

You now have FICL up and running.

FICL can be found at http://ficl.sourceforge.net/ The Links section contains links to nice Forth tutorials.