|
Planned Feature: Callbacks / All-purpose Function Pointers Displaying 1-4 of 4 total.
1
Overkill
|
Hey guys, I thought I'd mention another planned feature for Verge some day.
Might take a long time to get around to completing, but I think it's pretty much important in liberating Verge from a few of its current restrictions.
We need to allow fully-free function pointers for both VC and Lua, in a way that's backwards compatible with current Verge code! And, it should be doable, given a little bit of grudge work by people.
To accomplish this, a bunch of stuff needs to change. We need to add a new variable type in Verge's script engine signatures, which will allow for all-purpose function pointers in VC code, and first-class function pointers in Lua.
Effectively, all builtin functions will take a "callback" instead of strictly a string.
As a result, in Lua, you get to pass anonymous functions to stuff like HookRetrace.
In VC, you would be able to get optionally compile-time error reporting if a function does not exist, through new VC syntax features. The syntax is backwards compatible with old code, so all hooks/calls using string names will still work.
VergeCModifying VC is annoying. It always is. The compiler and interpreter have made things really frustrating, mainly because it wasn't designed with certain flexibilities in mind when it was first created. That said, I think it can be done, with a bit of planning. And plan I did!
Here is how the VergeC would work! Introduces Reserved Keywordcallback Variable Declaration Syntaxcallback <return type>(<signature>) <name><array size (optional)>; Notes about Callback SignaturesSignatures for callback declarations may give their parameters names, but aren't required to (unlike real functions). In other words, they can just give the expected types, if they want to. This makes it a little bit cleaner when dealing with a lot of callbacksNotes about Scoping:These variables would be allowed to be declared anywhere ints and strings are allowed.
This means local callbacks, and callbacks as arguments.
The no-struct/no-array limitations on local callbacks would apply.
Er... maybe they won't be passable to varargs functions. We'll see. If they are though, tons more flexibility.Examples
// No args-void return type.
callback void() f;
// With an string return type.
callback string() f;
// As an array, each returning ints, and taking a string argument
callback int(string) crap[60];
struct Item
{
string name;
// Inside of a struct, multiple arguments
callback void(int itemIndex, int user, int target) useItem;
}
Item itemCollection[50];
// As an argument
void CallSomething(callback void() f)
{
f();
}
// As a return value.
callback int(string) GetCrap(int i)
{
return crap[x];
}
Callback ExpressionsThese expressions are used when resolving the value for an assignment or argument pass regarding callbacks. Only these types of expressions can be assigned to callback variables. Anything else should cause an error.mycallback = 0; The null-function expression. Does not "exist" if passed to FunctionExists(callback void). If called, this function will do nothing. Note that, an int variable with value 0 will not work instead, but this is for a reason since any other int index won't be meaningful.mycallback = MyFunction; Resolve a function reference at compile time. Function must exist in VC (ie. not library code, but this might change), and must match the exact signature to compile. Map-VC function references can occur, but only in the file the function is declared. mycallback = "My" + "Function";
string somestring = "MyFunctio";
mycallback = somestring + "n"; Resolve a function reference from a string at runtime using a name-table lookup. Required for map-VC functions to be made in system-VC code. If the lookup fails, the actual value given will be the null-function.
There's no == operator defined on callbacks, and there won't be much need for equality-testing functions, I figure. (and if you need to, just use strings as before).
On the other hand, existance checking will be there, to allow callbacks to tell when they're holding a null-function instead of something that will actually do something when called. To do this though, we pretty much have to promote the FunctionExists(f) builtin function into an operator, which will work on any callback expression, instead of just strings as it is right now.
Oh, and of course, you need to be allowed to call the callbacks:
callback void() talk = HelloWorld;
talk();
Notice how everything is backwards compatible with current VC, but introduces new features. That in mind, everyone can keep legacy code around, but adapt new VC to use function pointers. Function pointers can be faster than current string lookups (if resolved at compile-time), because the function index can be known in advance.The Script Library
Now, with that out of the way, to allow the flexibility to be introduced into the rest of the engine, the script library needs modifications!
All of the existing callback function stuff uses strings, which are names to void functions that take no arguments. So we can pretty much introduce one extra signature type for void builtin callbacks.
Pretty much have something like this:
callback void() trigger.onStep;
callback void() trigger.beforeEntityScript;
void CallFunction(callback void f(), ... args);
void HookRetrace(callback void() render_routine);
void HookEntityRender(int ent, callback void() render_routine); And so on. Also, remove FunctionExists(string funcname) from VC, since we'll be introducing a FunctionExists that works on any callback.LuaOkay, but what about Lua?
Well, we'd be able to use the new signatures that we introduced for VC.
Add a few simple cases to the argument validator and execute function stuff.
We'd need to update the current hooks to be a class with an int reference to the Lua registry. Simple enough, I think.
These are the simplest things to add, since it doesn't involve any compiler modifications.
So I might be able to FIRST add anonymous function support for Lua, and from there, chisel in VC stuff.
Afterwards, in Lua, we'd get to do weird funky things like:v3.HookRetrace(function()
vx.screen:RectFill(0, 0, vx.screen.width, vx.screen.height, 0)
end) or having a function inside a table pointed to directly:v3.HookRetrace(clouds.Render)
or having a function call a function on a table, so you can have pointers to object methods:
local world = NewWorld();
v3.HookTimer(function()
world:Update()
end)
Will take a fair deal of thinking and grunt to get there though. But, I dunno, after all this stuff is done, we get some sexy results!
Posted on 2009-08-23 16:20:09 (last edited on 2009-11-07 12:19:05)
|
Overkill
|
I've been told to make a small revision to the declaration syntax to something like this instead
callback <return type>(<signature>) <name><array size (optional)>;
This way it makes arrays of callbacks less ugly to declare, and makes things more consistent with function return values. So we'd get something like this:
callback void() func[50];
callback int(int, int) add;
callback void() getFunc(int i)
{
return func[i];
}
Posted on 2009-08-24 20:13:37
|
Overkill
|
Hooray! This feature is completed, save for modifying the builtin functions to use callback void() instead of strings where possible. So now we get generic function pointers in both VC and Lua. Hooray! (Although Lua also gets to pass around anonymous functions, something VC doesn't have and probably won't unless I go crazytowns).
Posted on 2009-08-30 22:17:46
|
Overkill
|
I am reminded that I suck and need to go in and convert Verge to use callbacks instead of strings where it is possible. Old code will still work the same, just new code will now be able to pass any function instead of just run-time strings. ONE OF THESE DAYS.
Posted on 2009-11-06 01:24:12
|
Displaying 1-4 of 4 total.
1
|
|