views:

195

answers:

3

In my interpreter I have built-in functions available in the language like print exit input, etc. These functions can obviously be accessed from inside the language. The interpreter then looks for the corresponding function with the right name in a vector and calls it via a pointer stored with its name.

So I gather all these functions in files like io.cpp, string.cpp, arithmetic.cpp. But I have to add every function to the function list in the interpreter in order for it to be found.

So in these function files I have things like:

void print( arg )
{
     cout << arg.ToString;
}

I'd add this print function to the interpreter function list with:

interpreter.AddFunc( "print", print );
  • But where should I call the interpreter.AddFunc?

I can't just put it there below the print function as it has to be in a function according to the C++ syntax.

  • Where and how should all the functions be added to the list?
+1  A: 

The simplest is to keep a map of function names to function pointers and load that at program startup. You already have the functions linked into the interpreter executable, so they are accessible at the time main() is called.

You can also come up with a scheme where functions are defiled in the dynamic libraries (.dll or .so depending on the platform) and some configuration file maps function names to libraries/entry points.

Nikolai N Fetissov
Function pointers are not necessarily of the same type, and I don't remember a generic function pointer in the sense that `void *` is a generic data pointer. Possibly functors would do better.
David Thornley
That of course depends. Functors, wrapper functions, etc. should work.
Nikolai N Fetissov
+2  A: 

In each module (io, string, etc.), define a method that registers the module with the interpreter, e.g.:

void IOModule::Register(Interpreter &interpreter) {
    interpreter.AddFunc( "print", print );
    //...
}

This can also be a normal function if your module is not implemented in a class.

Then in your application's main initialization, call the register method of all modules.

This approach helps keep things modular: The main application initialization needs to know which modules exist, but the details of which functions are exported are left to the module itself.

interjay
You could push it one step further by allowing the functions to register themselves into the module automagically. Though it would be easier if we were talking functors rather than functions.
Matthieu M.
+1  A: 

Is everything included in every interpreter? If so, I would recommend adding it either in a constructor (assuming the interpreter is an object) or an init method.

If not, you may want to consider adding an "include" type directive in your language. Then you do it when you encounter the include directive.

patros