Syntax-wise I chose to make it as strict as possible to reduce the chance of errors: Virtual base functions must be declared with the 'virtual' keyword, and overrides in child classes with the 'override' keyword. This way any mismatch in parameters that otherwise would cause silent failure will outright produce a compile error.
- Since the number of small allocations here is extremely high this will help a lot to prevent fragmentation and since most nodes are collected up front and this is done when no large resources are being loaded it won't cause heap spikes.
let Emit methods delete FxExpression arrays when they are done.
- For some reason the deletion process does not work 100%, there are always some nodes left behind and so far I haven't found them. This ensures that these arrays do not live any longer than needed.
- fixed: The state cast hack for DECORATE could not properly create state constants.
Instead they were passed to FxRuntimeStateIndex without resolving them to something constant. This adds proper handling of constant indices within that class.
* use the function build list instead of the function to pass the info. The function is permanent so not the best place for compile-time info.
* pass along the current state index which is needed to calculate the target state.
- fixed: The state index comparison against 0 was broken.
- fixed: Resolving codegen nodes must set the strictness flag per function so that ZSCRIPT and DECORATE are done properly.
- fixed: divisions wasted one register for each operation due to a double allocation.
- changed math operations to use less registers. There was a well-intended change to allocate the destination first, but the better approach is to first allocate the operands and free then before allocating the destination register.
- added support for global variables to the code generator - not the compiler, though. For the handful of entries this is needed for it may just as well be done manually. So far FLevelLocals level is the only one being exported.
- fixed: The VM disassembler truncated 64 bit pointers to 15 digits because the output buffer was too small.
- resolve entire FxSequences instead of aborting on the first failed entry. This allows to output all errors at once.
- exported thinker iterator and drop item chain to scripting. Unlike its native counterpart the script-side iterator is wrapped into a DObject to allow proper handling for memory management.
- fixed: The VMFunctionBuilder only distinguished between member and action functions but failed on static ones.
- fixed: FxAssign did not add all needed type casts. Except for purely numeric types it will now wrap the expression in an FxTypeCast. Numeric handling remains unchanged for both performance reasons and not altering semantics for DECORATE.
- exported all internal flags as variables to scripting. They still cannot be used in an actor definition.
- make ATAG_STATE the same as ATAG_GENERIC. Since state pointers exist as actual variables they can take both values which on occasion can trigger some asserts.
- gave PClass a bExported flag, so that scripts cannot see purely internal classes. Especially the types like PInt can cause problems.
Todo: we need readonly references to safely expose the actor defaults. Right now some badly behaving code could overwrite them.
- fixed: FxMinusSign trashed local variables that were used with negation.
- fixed: FxConditional only handled ints and floats, but not pointers and strings.
- fixed: A 'no states in non-actors' error was triggered, even for classes without any states.
- fixed several occurenced where vectors were treated as floats. NOTE: The entire codegen.cpp file needs to be carefully reviewed for bad use of the REGT_ constants, there's probably more places where using them has broken some type checks.
- fixed: committed test version of zscript.txt instead of changed actor.txt by accident.
Initialization and assignment for strings is working with this commit.
- removed the bogus optional value from the first A_Jump argument. A quick test with an older ZDoom revealed that this was never working - and implementing it would make things a lot more complicated, especially error checking in the code generator.
- fixed: The check for insufficient parameters to a function call was missing.
- removed mulv_kr and divv_kr instructions. The first are redundant and the second are useless. Maybe remove all other vector/const operations as well? They won't get used by the code generator.
- fixed disassembly of vector multiplication and division instructions.
- fixed: ZCCCompiler did not process array access nodes.
- fixed: Function argument names were not placed in the destination list by the compiler.
- scriptified several trivial functions from p_actionfunctions.cpp.
- disabled the assert in PType::GetRegType. This assert blocks any use to check for types that are incompatible with function parameters.
- pass the default parameter constants to the native functions. At the moment this is not used yet.
- use the function defaults to complete argument lists to script functions.
- fixed all default values that got flagged by the expression evaluator as non-constant. Most were state labels and colors which were defaulted to "". The proper value is null for states and 0 for colors.
- also replaced all "" defaults for names with "none".
- fixed: Script functions did not receive the function name when being created.
- relaxed the asserts for PARAM_STATE, because the VM knows nothing about ATAG_STATE. Any state variable's content (e.g. Actor.SeeState) will receive ATAG_GENERIC, rather than ATAG_STATE.
- added a 'NeedResult' flag so that certain operations can create shorter code if the result of the expression is not needed. So far only used for postdecrement/increment statements on local variables (which is the most frequent case where this matters.)
- fixed postincrement and decrement for local variables. Due to the result preservation semantics it created faulty code.
- synthesize PField entries from the flag list for AActor. This intentionally excludes the bounce flags for now.
- allow deprecated flags that do not call the deprecated flag handler.
- disallow constructs like (a = b) = c by not allowing an address request on an assignment operation.
- restrict modify/assign on boolean variables to the bit operators. Everything else needs to promote the result to an integer to make sense so it should be disallowed.
- added the above for the 'if' condition. It works for integers, floats and pointers and will save 3 instructions if the condition is a non-boolean that can be implicitly casted to bool.
- added a TESTN instruction. This is like TEST but negates the operand. This was added to avoid flooding the constant table with too many case labels. With TEST and TESTN combined, all numbers between -65535 and 65535 can be kept entirely inside the instruction. Numbers outside this range still use a BEQ instruction.
- added master and tracer to the list of exported variables.
- fixed: 'none' as class type must map to the real null pointer so that it won't get rejected by the stricter type checks.
- added handling for member function calls to zcc_compile.cpp.
- fixed: FxMemberFunctionCall may not delete the self expression if it gets passed on to the actual function call.
- fixed emission of the self pointer in FxVMFunctionCall. I did not realize that the self expression only sets up a register for the value, not pushing it onto the stack.
Ironically this only requires a very minor change in the calling code and an added member for the VMFunction to tell that code how many parameters to pass.
This change will allow to turn the vast majority of action functions into regular members, the only ones that still need to be an action function are the few that actually use the pointers.
This is not testable right now because finally the action function mess has come full circle. The current setup makes it impossible to call action functions from non-action functions because the needed info is local to the functions.
Long avoided, this needs to be refactored now so that the different semantics for action functions are no longer needed.
- fixed: FxMemberIdentifier checked for ClassPointers instead of object pointers to resolve the left hand side of the expression.
- allow comparison of pointers.
The generated object code can definitely use an optimization pass but that's something left for later when more things are working. Right now it creates one opcode more than necessary for all member accesses (instead of using the offset in the store command it calculates an actual address of the variable in another address register) and can create one too many for non-constant expressions being assigned to local variables (a move between two registers because the emitted expression on the right hand side does not know that it can emit to the actual variable's register.)
- create proper variable data from the function prototype instead of assuming that there's just 3 pointers.
- added a printable name to VMScriptFunction for error output during gameplay in case something goes wrong.
All break and continue statements were collected in one list, and each loop statement taking hold of that entire list, including the breaks and continues from previous outer loops.
Changed it so that loop statements contain the jump addresses themselves and set a pointer in FCompileContext, so that the jump point can be set directly in the loop statement - and an error printed if there is none in the resolving stage, not the emitting one.
Consolidated the identical backpatching code of the three loop statement nodes into a subfunction.
- handle all binary operators which are already implemented in the code generator.
- implemented sizeof/alignof operators in code generator.
- rewrote RequestAddress so that its return value is not the writability of an address but the mere existence. Also changed it to not output errors itself because those cannot be dealt with by the calling function.
- added the '>>>' (unsigned shift) operator. Although, with unsigned numbers available, this is technically not really needed, DECORATE supports this so ZScript should, too, if only for the benefit of making conversion tools easier to handle.
- fixed: FxBinary::ResolveLR' check for numeric operations was incomplete. Like far too many other places it just assumed that everything with ValueType->GetRegType() == REGT_INT is a numeric type, but for names this is not the case.
- added a descriptive name to all types for error messages.
- added a generic type cast node to the code generator.
- added a few more cast operations to the 'cast' VM instruction.
- extended FxClassTypeCast to handle all possible input that can be cast to a class pointer, not just names.
- implemented handling of the basic math operators so that heretic/beast.txt can be processed.
This is working, aside from still needing the type casts to properly transform the strings to class pointers.
For the random functions this class only handles the default-RNG version. The one with an explicit RNG needs to be done separately because the parser produces different output for them.
- added a truncation warning to FxIntCast, which only occurs with ZScript, not with DECORATE. FxBoolCast is intentionally left out because it would defeat the reason for this cast type.
- removed Self parameter from FxFunctionCall. Actual member function calls through an object require quite different handling so lumping these two together makes no sense.
- added a workaround to deal with ACS_NamedExecuteWithResult to both the compiler and FindClassMemberFunction. The way the ZScript compiler sets this up means that it will call the builtin, not the actual action function, so the parser needs to do some explicit check to get past the same-named action function.
- pass a proper self pointer to FxActionSpecial. Although it's still not being used, propagating design shortcuts through several function levels is a very, very bad idea.
* explicitly require passing the owning class when creating it.
* extract self pointer class when adding a variant.
* put the flags on the single variants, we can not fully rule out that they will be 100% identical, if variants ever get allowed.
* Allow PFunction to work without a VMFunction being attached.
* The Variant for a function must store the prototype itself instead of relying on the VMFunction it points to. Otherwise it would not be possible to reference a prototype during compilation of the function because it does not exist yet.
* Give the variant a list of the function's argument's names, because these are also needed to compile the function.
* create an anonymous function symbol when the function gets registered to the builder. At this point we have all the needed information to set it up correctly, but later this is no longer the case. This is the most convenient info to have here because it contains everything that's needed to compile the function in the proper context, so it has to be present when starting compilation.
* added some preparations to implement special handling for weapons and custom inventory items, which can run action functions in another actor's context. This part is not active yet but the basics are present in SetImplicitArgs.