Fixed by backtracking in the parser, and keeping a copy of the original expression if it's a simple_expr, which is used for output in place of the folded one.
There's still the potential issue that if a global is optimized away, then it will "come back" during output and cause an error because the definition is missing.
Bugs fixed:
- %= and the new assignment operators were not emitting error on invalid types.
- List globals referenced in another global were duplicated entirely.
- Properly recognize -option in the command line.
Rest:
- Complete overhaul of the internal data structure.
- Got rid of the symbol table plus mini-trees, and made everything one big tree plus an auxiliary symbol table.
- No more special case hacks like using tuples instead of lists...
- Got rid of the EXPR hack.
- Dict-based, rather than list-based. Allows adding arbitrary data to any node or symbol entry.
- Added a few coverage tests for the new code.
- Return values can now be chained; the functions parameter requirement is gone. Still not fully convinced, though. My guess is that a parser object should be passed between functions instead. Will do for now.
- Get rid of Fold().
- Handle globalmode properly. It was sometimes active during function calls.
- Change all warning() calls to not use Unicode, just in case the output is redirected to file.
- Cosmetic fixes and TODO items.
- Parser and output modules are thoroughly tested and working.
- Most LSL immutable functions are working; some not tested; llJsonSetValue not implemented.
- Parser recognizes the following flags that alter syntax:
extendedglobalexpr: Allow full expression syntax in globals.
extendedtypecast: Allow full unary expressions in typecasts e.g. (float)~i.
extendedassignment: Enable the C assignment operators &=, ^=, |=, <<=, >>=.
explicitcast: Add explicit casts wherever they are done implicitly, e.g. float f=3; -> float f=(float)3;.
Of them, only extendedglobalexpr is useless so far, as it requires the optimizer to be working.