It pointed always to Pars + Func->GetParCount(). The only users were
VARN_CONTEXT, which can be replaced with PARN_CONTEXT that way, and
FOREACH_NEXT, where the parser can do the math and simply give a number
relative to the current stack position, like regular variable usages do.
This can happen when an engine function is made to call a script function
when the stack is almost exhausted. Since there was nothing catching that
exception, it'd mean a program abort. Move the bulk of the exception
handler to the outer Exec function, and only keep the saving of the exact
code position in the inner one.
While at it, simplify the pushing of the parameters to simply push the
right amount of parameters instead of pushing ten and then popping the
excess. Also move the creation of dummy parameters for DirectExec into
DirectExec().
In earlier C4Script versions, there were multiple variants of expressions,
all followed by the same operator options, but nowadays everything is more
uniform.
This bug manifested itself in mysteriously growing PropLists with nil keys.
Some usages of Clear were simply to clean the newly-allocated table, and
need to continue to do so.
It isn't clear whether that call is necessary since the C4AulScriptEngine
constructor already does this, but it is clear that duplicating the call
all over is a bad idea.
This allows the removal of quite a few return C4Void();.
Also stop pretending that Nillable<void> is the same class as Nillable<T>.
Its only function was as an implementation detail for C4Void, which doesn't
need any implementation details anymore.
This avoids duplication of code in C4AulObjectFunc and C4AulEngineFunc
at the cost of boilerplate code working around the lack of partial
function template spezializations.
Instead of ThisImpl and ExecImpl, we could have multiple C4AulEngineFunc
spezializations deriving from a common template, but that would require
even longer and duplicated boilerplate.
This allows one to use the C4Value constructor instead of
C4ValueConv. To avoid unintended implicit conversions like
const char * to bool, add a private template constructor that
catches everything not in the list of intended constructors.
In the long term, there is no reason DirectExec should be concerned with
C4AulScript/C4ScriptHost. In the meantime, the lookup code from Fneval can
be moved into the function.
This allows eval in scenario script to access scenario script locals, but
that seems harmless.
Instead of tracking the status with a variable, simply test the loop-end
condition directly, and reduce code duplication between empty and non-empty
array contents.
Most of the changes are for exception safety. The parser references the
function stored in Fn when the function body contains a syntax error, so
the function has to stay around. In order to avoid memory leaks, store the
function and its containing proplist in their destinations before they get
fully parsed.
This doesn't allow functions directly in static constants or arrays.
Future work: Putting the owning proplist in the scope chain.
The C4AulScript containing the source of the function was already mostly
used to get the relevant proplist or available from context. This will
allow more than one proplist plus the global one per scripthost to contain
functions.
Apparently, this wasn't done already because of compatibility concerns. The
beginning of a release cycle is the perfect moment to finally complete the
prevention of using deleted objects from script.
Min/Max with array parameter will return the smallest/largest value of
all elements of the array. If any array element is not an integer, nor
convertible to integer, the function will fail.
This prevents a crash when an incompatible engine function is used as an
engine callback function.
Unfortunately, this breaks any scripts that have wrong type information in
engine callbacks and only worked because those were ignored.
The engine has a few more usages of the operators, but they don't look
prone to overflowing. The other operators in Script already used SetInt,
which always truncates to 32 bit.
This was used to name snapshot releases of the Network2 branch, and has
seen almost no use since.
C4ENGINEINFO(LONG) was a duplicate of C4ENGINENAME and C4ENGINECAPTION.
Translate() used to select the script which it checked for translations
before actually looking up the string key. Change it so if the object
the context of which it was called in doesn't have a matching
translation, the string table of the script containing the call is used
instead.
Getting the error summary written to the log/console automatically may
be useful for general game usage, but when testing Aul we just end up
with thousands of useless messages in the output. Let the caller log the
message if it's really desired.
The C++ standard library comes with perfectly fine implementations of
these functions, so there's no point in reimplementing them just for the
hell of it.
We already require support for std::unique_ptr, which itself requires
support for rvalue references. As such, we know we can use rvalue
references, and thus don't have to keep carrying dead code around.
Instead of just writing the raw string to stderr, escape them first so
newlines and other control characters don't result in strangely
formatted output.
The shapes library has such pointer chains. The leaks were getting pretty heavy because they included pointers to C4AulFuncs, which kept a lot of parts of the script engine and string tables in memory.
The string table of System.ocg scripts (except the global System.ocg) pointed to nowhere after the initial load phase, but is still required for reload. Added a ref counting option to keep these string tables alive.
The desync was caused by PropList->GetProperties returning the properties in an arbitrary order. They are now sorted first.
The debug logs are left in place, because I assume that I will need them again and they prove to be helpful.
While none of the mismatches were having a side-effect, this silences a
number of -Wreorder warnings which were drowning out potentially
important diagnostics.
Example: this.EditCursorCommands = ["Explode(20)"] on an item will offer a menu entry to explode the object. Commands may be either strings or function pointers, but function pointers will always be called by name.
src/script/C4Script.cpp:159:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (long i = 0; i < sizeof(values) / sizeof(*values); ++i) \
^