Open MurphyMc opened 3 years ago
I thought it would be easy too but I messed around for a few minutes and it's trickier than it seemed. Consider:
test( 5 )
routine test( n:Int32 )
trace n
endRoutine
Compiles to:
RogueGlobal__test__Int32( ((RogueClassGlobal*)ROGUE_SINGLETON(Global)), 5 );
# equivalent to
RogueGlobal__test__Int32( ROGUE_SINGLETON(Global), 5 );
We can't do a macro like ROGUE_CALL_ROUTINE( RogueGlobal__test__Int32, 5 )
due to macros not allowing a variable number of arguments.
We can't make a function like Rogue_call_routine( void* fn, ... );
because we'd lose the function type.
Only thing I can think of would be to generate a call forwarding function for each routine, but it doesn't seem worth the ROI.
I hadn't thought of the macro approach, but there are variadic macros! They've historically had a problem in many cases when being called with zero arguments, but GCC has long had an extension to fix it, and it's now been standardized in C++20 or something, and MSVC supports it. So maybe that's a viable option? See: https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
(Update: Immediately after having posted the above, the downside of the macro approach occurs to me: they're not useful for using the Rogue routine as a callback for some C/C++ API that wants a function.)
I've lost a lot of context, so I may be forgetting something obvious, but... are these methods being generated as normal methods on the Global singleton? What if they were global methods on the global singleton? No hidden argument in that case, right? (Even if this works, I have no idea what it might break.)
Oh - that's the solution! Routines are currently object METHODS
of Global
, but indeed they work perfectly well as GLOBAL METHODS
of Global
. I'll make that change sometime soon.
Does this change anything with respect to using the fat arrow operator on such methods from within Rogue? That's the thing that occurs to me might lead to breaking something somewhere.
Good call again! I remember now that's the reason we made them object methods instead of class methods: if you call Global.xyz
then you can get a function reference with Global=>xyz
.
It's prolly still worth switching back to class methods and then doing more work on that function reference operator to automatically generate a Function object (when necessary) that will call the global method.
Just to see if I'm understanding, the proposed solution is:
Is that it?
What does fat arrow actually do on a GLOBAL METHOD now? Not compile? If fat arrow on GLOBAL METHODS currently just doesn't work, this seems like a win anyway (since it'd work with any GM, not just routines).
Looks like a fat arrow on a global method works just fine already (!). So I'll try just switching routines to be GLOBAL METHODS and maybe it will be as easy as that.
Fixed here: https://github.com/AbePralle/Rogue/commit/cd4e3aae453130777abdce8d2d07a2732a038ab8
Works great!
A long while ago, I think I either suggested or changed the code for routines so that they're methods on Global. A downside here is that from a C perspective, they take a reference to the Global singleton, which makes them harder to call from C/C++.
Probably lots of ways to fix which don't really cost anything.