As the new parser approaches completion, it is time to start considering the implications. I have already made the executive decision of implementing half of this in the past, but what has been implemented will need some recoding, and the new parser allows for marvelous new extensions I would like to take advantage of. As such, I figure it would be good of me to draw up this proposal both to inform developers and open the floor for comments before they are implemented.
Developers heretofore have used the global enigma::instance_event_iterator
to determine the current instance and interface with its locals. At first glance, there's nothing wrong with this, but when we really consider its implications, we start to see its limitations:
- Threads cannot manipulate this variable concurrently.
- Sideways casts between virtual ancestors cannot be made correctly in other files.
- Functions which change scope must synchronize their use of this variable.
- This variable does not, in itself, affect the scoping of scripts and functions called therein.
We can correct all of this by having reflexive functions, such as instance_destroy()
, take an additional parameter, _E_SELF
, of a particular C++ instance type (eg, _OBJ_object0*
This is similar to the mechanism with which you are likely already familiar, the varargs
type, which allows you to request an stdargs-like overload which you can treat like an array of parameters. It is similar in that each of these are semantics that can be declared in C++, but only used in EDL via the intervention of the parser.
The proposal, then, is as follows:
- Any parameter with the type enigma::varargs will be allowed to be passed an infinite number of parameters, as an array. The parser will handle packing the parameters given into the array in an efficient manner.
- Any parameter with the name _E_SELF and a pointer-to type will be invisible to the user and filled in by the compiler with a pointer to the instance in question, meaning this in events and member scripts, and with->inst in with statements.
The lexical stipulations should be my concern rather than yours. Basically, don't assume you can do anything stupid. For instance, the following is a set of legal overloads:
int max(double, double);
int max(double, double, varargs);
While the following is ambiguous:
int max(double, double);
The reason, of course, is that if you pass it two doubles, both functions are equally logical choices. Now, I could choose to give weight to the concrete matches precedence, but I'm asking for your opinions on that, first.
Now, as for the _E_SELF
parameter, if you think you have a better method of unambiguous identification for this which corrects issue (2) given above, let me know. Or, if you prefer a different name, such as just SELF, let me know as well. Otherwise, this will be the new format for the prototype:
void instance_destroy(enigma::object_basic* _E_SELF);
So, post suggestions, or be aware that these two modifications mean changes to the API, including existing functions.
Floor's open. Be informed. Feel free to contribute.