Function pointer idea text dump

OpenZC Development Topics
Post Reply
User avatar
Emily
ZC Developer
Posts: 51
Joined: Sat Feb 08, 2020 11:07 pm
PureZC Username: Emily
AGN Username: Emily
Contact:

Function pointer idea text dump

Post by Emily »

I had a lovely epiphany about function pointers, and textdumped them into discord. Posting here as a backup, so I don't lose this before it comes time to actually use it:
VenrobToday at 4:25 PM
Just hopped in to look at this because my brain decided to think about function pointers
....and I understand a lot more about what would need to be done to implement them than the last time I looked at this.
Probably the most insane part to code would be the typematching for params
it'd require a type templating system
because it'd need to manually parse different types for int(*proc)() vs int(*proc)(int) or void(*proc)()
...arrays SORT OF have something set up for this in the parser, although it goes mostly unused, as the array types decay to their base type, due to presumably gray not having finished plans relating to arrays.
so, it would need to be duplicated, with a more complex flex/bison syntax for handling it
Realistically, it would need to work more similarly to class Function of the parser than pre-existing types
To store the ZASM line number, as well, would require a conversion later on in compile.
Also, pointers to INTERNAL functions would be another beast entirely; possibly not sane to add
especially due to the inline process
realistically, if it were to be added, then an inline function which has it's function pointer referenced ANYWHERE in the code, would need to also function as a non-inline function when referenced via pointers, requiring additional ZASM generation.
Given, a single funcflag would easily allow this; as said ZASM generation already would occur, if not explicitly disabled by the inline flag
so, a funcflag as FUNCFLAG_PROCREF to indicate that a function had it's pointer taken, anywhere, by any bit of code, would need to have an existing location to zasm-jump to, therefore overruling the inline.
The inline would still be able to behave normally on direct calls, but would fail to do so for proc calls, as they would need to always use a normal ZASM line reference.
Now, while I have an idea for func pointers, structs still elude me; as they would need some code that functions more similarly to string/array literals, which I still haven't hit the necessary level of understanding for.
but, function pointers may be closer to possible than we think.....
As for if attempting them in 2.55 would be sane.... I would only even begin to consider that if I were able to sanely finish pretty much everything else on my current todo list, and have the sanity and energy to attempt it after that. I would totally understand it being put off to next version, as it's a large change.
I may well play with it in a branch at some point regardless, if I have the time and my interest is peaked enough.
The major thing about function pointers to think about is, most of it is on the parser-side; structs would need far more on the interpreter-side. At least, with reference to string/array literals as being more interpreter-side; I'm unsure how good a comparison it is.

Code: Select all

int test(int x){return x+5;}
int test2(int x){return x*2;}
///////
int(*proc)(int) testFunc; //initialized to 0, as any other data member
testFunc = &test;
/*the dereference here, '&test', will run a small bit of allocation code;
it will allocate a function object in the interpreter,
similar to... bitmaps or files? or arrays? Something along those lines.*/
Trace(testFunc->Call(10)); //Traces 15
testFunc = &test2;
Trace(testFunc->Call(10)); //Traces 20
This would be a basic outline of how it might look.
I believe using ->Call() as the syntax may be saner for GlobalSymbols to handle?
but, it'll still need a new system in GlobalSymbols to handle having a non-constant function table for the call...
Aside from that, testFunc(10) may simply work; though what then would occur if I named the variable test instead? Should it call the function named test, or the proc pointer named test? That would be an issue to handle, wherein ->Call() would render it irrelevant.
Anyway, the big thing here is the allocation that occurs on &test; that would need to generate ZASM similarly to functions which generate new bitmaps or such; something like ALLOCATEFUNC (line number)
If that same line number is already allocated, it would simply return the existing entry, instead of allocating a new one; as duplicates would be useless, and only a waste of memory.
Adding the line number in ZASM like that would be trivial; it would work as a normal function call, using a new LabelArgument, and be visited by the ArgumentVisitor via the normal system; nothing even remotely new would need to be written to make that possible, the systems required are already in place. It would simply need a new expr type for &funcname, which generates the zasm command for allocation. This would also give us the required syntax for pointers/references should we desire it at a later date.
The good part here, as I mentioned earlier, is that it's mostly parser-side; the only things that need to exist on the interpreter is a way to store the ZASM line number, via an indexing system similar to how all of our current pointer types function; most similar to things like bitmaps and files which are arbitrarily allocated, as opposed to sprite types with existing UIDs.
And also, a way to call to said function with a variable number of params; but only the number needs to be known, not the type, as types don't exist in ZASM.
Another problem to look at would be overload-matching; multiple same-name functions with different params. It'd have no way to know which to grab a ref to simply via &name
Potentially &name(type,type,type); though I fear that would cause conflicts in the bison.
Perhaps &name<type,type,type>, similarly to what was done with casting to prevent conflicts, would function properly.
(I don't expect that would conflict with casting, due to how the bison is set up for that)
Return type need not be specified there, I believe, as you cannot have overloaded functions such that they have the same param types and differing return types.
though, extremely thorough function matching tests would need to occur, as that's likely the most fragile part of this entire system.
....There's my 30 minute straight thought dump on the matter. I do love when my brain just decides Oh, you want to do something? Too bad, you have an IDEA!
ZC Dev since Sept 2018

Post Reply