Potential priorities for v2.1
Posted: 24 Nov 2022, 04:07
These are things that I intend to prioritize for v2.1... at the moment.
Module support. Aside from the obvious benefits, I intend to prioritize this for two reasons:
1. I imagine it could be used to minimize the impact on backward-compatibility that introducing new features will have. One simple example is that right now, any script using X as a global variable would break if a new built-in class or function named X is added, because classes and functions can't be reassigned. Modules may also provide a natural boundary for language-affecting directives, such as to enable backward-incompatible language improvements within one module while allowing older code to execute as part of the same script.
2. Out of respect for the effort that Helgef went to, developing two implementations (#142, #162).
Some other features might spring up during development of modules. For instance, making the implementation more able to deal with arbitrary namespaces (module-level variables vs. global variables) may also facilitate lexically scoped variables. (A lexically scoped variable has its visibility and lifetime tied to the block which encloses it, rather than the function. This is especially useful within loops containing closures.)
The current implementation has a single global C++ object g_script, which owns all lines of code and global variables/functions, and has many other responsibilities. Parsing script code at runtime is potentially unsafe because a syntax error could effectively leave g_script in an invalid state, and this is one barrier to implementing a function for loading additional scripts at runtime. (It appears that AutoHotkey_H's addFile handles it by backing up and restoring the properties of g_script, but it does not appear to account for the possibility that an incomplete function or class is added to the global namespace.) The code would need to be refactored to properly implement modules, and at the same time it would become closer to ideal for allowing scripts to be loaded dynamically. Of course, a dynamically loaded script could itself be a module.
Structured objects, i.e. typed properties. The primary purpose is basically "struct support", but this would be more flexible than (just) having a dedicated struct type. Instances of a class with typed properties would have additional space allocated for them, coinciding with how C handles structs, so they can fill that role. The definition or redefinition of typed properties would not be permitted after creating the first instance. Aside from their use with external functions, classes utilizing typed properties could be more memory-efficient, more robust, and probably faster to initialize and delete.
Importing native functions. DllCall.Bind(Type1, , ... RetType) is a trivial way to construct a function that the script can call, without having to supply the parameter types every time; but it isn't the easiest to optimize and doesn't have much flexibility when it comes to custom types, parameter conversion and memory management. Recent betas implemented some internal changes where many built-in functions are now ordinary C++ functions with statically-typed parameters, and parameter conversion and validation is performed by some central code based on the function's signature. I intend to build on this to allow the script to construct its own script functions that call native functions, with performance closer to built-in functions and greater flexibility than DllCall. This can then be optimized to improve the performance of both built-in functions (which took a slight hit in some cases) and imported functions, by assembling machine code when the function is composed, instead of interpreting the signature when it is called.
Later, this may lead to built-in support for importing COM type libraries and WinRT APIs.
Those are the things that have most interested me recently, but there may be more:
Event queuing. Currently events are "raised" and processed by posting them to one of the script's windows. Critical claims to "buffer" events, but actually does it by trying to leave them in the Win32 message queue. This has a number of problems, such as:
- Sometimes it backfires, such as when drag-drop is being performed in a ListView, and messages get "bounced" in and out of the queue because system code is dispatching messages and AutoHotkey is queuing them up again.
- It is not suitable for scenarios where AutoHotkey's interpreter might be embedded in another application, with its own message loop.
- Some events are limited to just the parameters that can fit into a PostMessage call, where additional parameters might otherwise be available.
- It is difficult to queue events based on priority, so the current implementation just discards events of lower priority than the current pseudo-thread.
Depending on the pace of development and what release schedule I decide on, other more trivial features may be implemented, and some of this might not make it into v2.1. If I'm not making much progress on something big, I might implement something small to keep my motivation up.
I do not intend to introduce new features immediately into the stable branch as I (and Chris) did with v1; instead, there will be an alpha branch with completed features being merged into a stable release periodically, perhaps every 6 - 24 months, depending on the amount of progress.