Page 1 of 1

array of functions

Posted: Tue Sep 10, 2013 11:32 pm
by sandras
I need to have an array which mostly contains function pointers, but also has some pointers to other arrays of functions in it. for example:

Code: Select all

typedef void (*func)(void);
func array1[] = {func1, func2, (func)array2};
func array2[] = {func3, func4};
I'm compiling it with lots of warning flags, and the compiler complains, saying:
program.c:2:31: warning: ISO C forbids conversion of object pointer to function pointer type [-pedantic]
How can I make the warning disappear? I would like to keep using the warning flags.

Re: array of functions

Posted: Tue Sep 10, 2013 11:58 pm
by Combuster
Apart from the forward declaration, you're trying to define an array as { func1, func2, {func3, func4} }, rather than { func1, func2, func3, func4 }.

The result is that you end up casting an array (data pointer) to a function (code pointer), which is forbidden by the C standard (probably because of harvard architectures). Besides, it points out a design flaw in your system since it's not being properly typed - where do you keep the information if an entry is an array or a function? shouldn't they be together in the same object?

Re: array of functions

Posted: Wed Sep 11, 2013 12:37 am
by h0bby1
sometime, doing like that can avoid a warning

func array1[] = {func1, func2, *((func *)((void *)(&array2))};

because pointers of differents types can be casted to any other pointer type according to C

but maybe there is a bug in your code if you attempt to add array2 to array1 it's not the good code :) maybe you should use initializing function to add function in it from an array instead of pre initialized array

Re: array of functions

Posted: Wed Sep 11, 2013 1:29 am
by bwat
Combuster wrote:Besides, it points out a design flaw in your system since it's not being properly typed - where do you keep the information if an entry is an array or a function? shouldn't they be together in the same object?
If it is a statically linked function, wont the type can be determinable at run-time by the fact that all such code routines are stored in the text segment? If the address < _etext then it's a function. This is no different to code that determines the shape of a union at run-time, in fact it is more economical with memory as it is uses implicit information. Plenty of programming languages that lack tagged data will type check dynamically on addresses like this as well. It's very common.

Re: array of functions

Posted: Wed Sep 11, 2013 4:05 am
by qw

Re: array of functions

Posted: Wed Sep 11, 2013 4:09 am
by AJ
Hi,

Could you explain what you are trying to do at a slightly higher level? Chances are that there is a better implementation. As inferred by Combuster, casting an array to a function pointer just to get it to fit inside another array of a different type probably suggests a broken design.

Cheers,
Adam

Re: array of functions

Posted: Wed Sep 11, 2013 5:04 am
by sandras
Basically I'm using threaded code to implement Forth.

I have two stacks and a bunch of functions that operate on them. Function pointers are placed in the arrays. The main loop calls these functions in order, one after the other. Some functions need arguments that cannot be found on the stacks. For example a "call" function would need the address of another array of function pointers. The argument for "call" is placed in the array right after the address to it. This is where the "func array1[] = {func1, func2, (func)array2};" stuff comes from.

Hope this helps.

Re: array of functions

Posted: Wed Sep 11, 2013 5:15 am
by AJ
Hi,

I have no knowlege of Forth, but how recursive is this? Could you have a top-level array, which points to "function arrays"? Some of your "function arrays" would contain only one item, but it wouldn't break the typing system (unless you need further nesting on top of this...). If it's any more complex than that, perhaps a different high-level container would work better?

Cheers,
Adam

Re: array of functions

Posted: Wed Sep 11, 2013 5:43 am
by Combuster
Based on what Wikipedia has to say on Forth, there are two primitive instructions in the language:
push immediate (store it as a tag, and the immediate)
call word (store as a tag, and a reference to the word's name)
Because you're not compiling, you can't create functions to load predefined variables, nor can you create functions for newly defined words - or altered ones. And because aritrary numbers can be anything, distinguishing them by address doesn't work either.

Hence if you insist on using threaded mechanics, the logical solution would be to define functions as tuples of the interpreter code responsible for the operation, and any arguments to make it happen - because one value is not going to cut it.

i.e. stored functions are best defined as arrays of structs { void (*operation)(void*); void* data; }, with func being the push operation, a direct call to predefined words, or an indirect call storing, another function (i.e. array of tuples). Next to that, you get the regular call stack and data stack used in actual execution, which shouldn't be too much of a problem.

Re: array of functions

Posted: Wed Sep 11, 2013 6:15 am
by bwat
Combuster wrote:Based on what Wikipedia has to say on Forth, there are two primitive instructions in the language:
push immediate (store it as a tag, and the immediate)
call word (store as a tag, and a reference to the word's name)
No. There's more than a few words needed to bring a Forth up. Different authors have a different set of primitives. As one example the UK FIG suggest NEXT, ENTER, EXIT, DOVAR, DOCON, LIT,& @, !, +, BRANCH, ?BRANCH, SWAP, >R, R>.
Combuster wrote: Because you're not compiling, you can't create functions to load predefined variables, nor can you create functions for newly defined words - or altered ones. And because aritrary numbers can be anything, distinguishing them by address doesn't work either.
The instruction LIT takes care of literal data. He doesn't need to parse literal data at run time, LIT knows that literal data will follow it. Now, if he inlines subroutines then he could very well be compiling and he could very well generate machine code to load predefined variables. It's just that he passes all arguments via explicit Forth stack pushes. See Andy Valencia's VAX Forth for an example of that.
Combuster wrote: Hence if you insist on using threaded mechanics, the logical solution would be to define functions as tuples of the interpreter code responsible for the operation, and any arguments to make it happen - because one value is not going to cut it.
You've just halved his code density and removed any opportunity to use any of the common Forth execution models out there.

Re: array of functions

Posted: Wed Sep 11, 2013 9:03 am
by Owen

Code: Select all

union word {
    void (*function)(union word *stack);
    void *ptr;
    uintptr_t uint;
    intptr_t int
}

word code[] = {
    { .function=lit },
    { .uint=1 },
    { .function=lit },
    { .uint=1 },
    { .function=add },
}

Re: array of functions

Posted: Wed Sep 11, 2013 10:30 am
by Combuster
bwat wrote:You've just halved his code density
Which is not true because you obviously did not read.

Re: array of functions

Posted: Wed Sep 11, 2013 11:59 am
by bwat
You need to explain that one.