OpenEuphoria: Euphoria v4.1

# OpenEuphoria Manual

## Euphoria v4.1

routine or constant name search

| Up |  |  | TOC | Index
<< 5 Formal Syntax | < 6.4 Euphoria To C Translator | Up: 6 Mini-Guides | 6.6 Multitasking in Euphoria > | 7 Included Tools >>

## 6.5 Indirect Routine Calling

Euphoria does not have function pointers. However, it enables you to call any routine, including some internal to the interpreter, in an indirect way, using two different sets of identifiers.

### 6.5.1 Indirect Calling a Routine Coded in Euphoria

The following applies to any routine coded in Euphoria that your program uses, whether it is defined in the standard library, any third party library or your own code. It does not apply to routines implemented in the backend.

#### 6.5.1.1 Getting a Routine Identifier

Whenever a routine is in scope, you can supply its name to the builtin `routine_id` function, which returns a small integer:

    include get.e
    constant value_id = routine_id("value")

Because `value` is defined as `public`, that routine is in scope. This ensures the call succeeds. A failed call returns `-1`, else a small nonnegative integer.

You can then feed this integer to `call_func` or `call_proc` as appropriate. It does not matter whether the routine is still in scope at the time you make that call. Once the id is gotten, it's valid.

#### 6.5.1.2 Calling Euphoria Routines by Id

This is very similar to using c_func or c_proc to interface with external code.

##### Function Calling

This is done as follows:

    result = call_func(id_of_the_routine,argument_sequence)

where

- `id_of_the_routine` is an id you obtained from routine_id.
- `argument_sequence` is the list of the parameters to pass, enclosed into curly braces

    include get.e

    constant value_id = routine_id("value")
    result = call_func(value_id, {"Model 36A", 6, GET_LONG_ANSWER})
    -- result is {GET_SUCCESS, 36, 4, 1}

This is equivalent to

    result = value("Model 36A", 6, GET_LONG_ANSWER)

##### Procedure Calling

The same formalism applies, but using `call_proc` instead. The differences are almost the same as between c_func and c_proc.

    include std/pretty.e

    constant pretty_id = routine_id("pretty_print")

    call_proc(pretty_id,{1, some_object, some_options})

This does the same as a straightforward

    include std/pretty.e

    pretty_print(1, some_object, some_options)

The difference with c_proc is that you can call an external function using c_proc and thus ignore its return value, like in C. Note that you cannot use `call_proc` to invoke a Euphoria function, only C functions.

#### 6.5.1.3 Why Call Indirectly?

Calling functions and procedures indirectly can seem more complicated and slower than just calling the routine directly, but indirect calls can be used when the name of the routine you want to call might not be known until run-time.

    integer foo_id

    function bar(integer x)
        return call_func(foo_id,{x})
    end function

    function foo_dev1(integer y)
    	return y + 1
    end function

    function foo_dev2(integer y)
    	return y - 1
    end function

    function foo_dev3(integer y)
    	return y * y - 3
    end function

    function user_opt(object x)
    	 ...
    end function

    -- Initialize foo ID
    switch user_opt("dev") do
    	case 1 then
    		foo_id = routine_id("foo_dev1")
    	case 2 then
    		foo_id = routine_id("foo_dev2")
    	case else
    		foo_id = routine_id("foo_dev3")
    end switch

One last word: when calling a routine indirectly, its full parameter list must be passed, even if some of its parameters are defaulted. This limitation may be overcome in future versions.

### 6.5.2 Calling Euphoria Internals

A number of Euphoria routines are defined in different ways depending on the platform they will run on. It would be cumbersome, and at times downright impossible, to put such code in include files or to make the routine fully builtin.

A solution to this is provided by `machine_func` and `machine_proc`. User code normally never needs to use these. Various examples are to be found in the standard library.

These primitives are called like this:

    machine_proc(id, argument)
    result = machine_func(id, argument)

`argument` is either an atom, or a sequence standing for one or more parameters. Since the first parameter does not need to be a constant, you may use some sort of dynamic calling. The circumstances where it is useful are rare.

The complete list of known values for `id` is to be found in the file `source/execute.h`.

Defining new identifiers and overriding `machine_func` or `machine_proc` to handle them is an easy way to extend the capabilities of the interpreter.

| Up |  |  | TOC | Index
<< 5 Formal Syntax | < 6.4 Euphoria To C Translator | Up: 6 Mini-Guides | 6.6 Multitasking in Euphoria > | 7 Included Tools >>