This revealed that the code for setting Par.i was wrong before, but didn't
matter because the jump target for all CONDN was set afterwards. But the
jumptarget for COND was set directly, and must be adjusted to account for
the bytecode that gets optimized away.
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.