Sei-Lisa/LSL-PyOptimizer

Keeping flags for constants intact in the output?

codeviolet opened this issue · 4 comments

Hi. Is there any way to use your excellent LSL-PyOptimizer to clean up scripts while keeping the constant flags intact in the output (like ZERO_VECTOR, CHANGED_LINK, and all the other constants defined in builtins.txt)?

The reason is that I was hoping to use your scripts to clean up some LSL for public release but still keep them human-readable. The dead code removal and the other features are just perfect for this but I would like the constant flags to remain as text in the results, rather than being converted to their true values.

For example, at the moment, CHANGED_LINK is converted to 32, and ZERO_VECTOR is converted to <((float)0), ((float)0), ((float)0)>. However, I would like all the flags to remain as (or be converted back to) the original text versions for the results.

I have tried the -ConstFold option but that does not seem to achieve what I want.

Thanks again for all your amazing work :)

The conversion of constants is done at the parsing stage; constants are immediately transformed to their values when storing them in the AST. There's currently no node in the AST able to track the names of the constants used.

Keeping the constants intact would impact the complexity of latter optimization stages. However, maybe it is possible to add information of what constant a value was originally, and transform it back at output time, provided it still preserves its value (for example, constant folding would transform ZERO_ROTATION/<0.5,0.5,0.5,0.5> into <((float)-0.5),((float)-0.5),((float)-0.5),0.5> and there would be no way to recover ZERO_ROTATION back unless constant folding is not applied).

There's one more thing. In the ZERO_VECTOR example you mention, keeping the constants would be counter-productive, because <0, 0, 0> uses less memory than ZERO_VECTOR (24 bytes vs. 33 bytes; see http://wiki.secondlife.com/wiki/User:Pedro_Oval/Mono_code_memory_usage for a reference). I guess that it would be possible to perform such transformation only if optfloats is off.

I'll look into this, but I don't promise anything.

One workaround that would allow you to achieve the desired goal is to remove the constants from builtins.txt and to add them to the script as variables, removing them afterwards.

The program can be forced to use a different builtins file by using the option -b.

This link contains the builtins file without the constants:

http://seis.shop.tm/sei/builtins-no-constants.txt

And this link contains all the constants, that you can append to the beginning of the script and remove them after the output:

http://seis.shop.tm/sei/constants-as-vars.lsl.txt

You also need to adjust the code to not make TRUE and FALSE reserved words. To achieve that, you can just remove 'TRUE' and 'FALSE' from parse.base_keywords (lslopt/lslparse.py line 197 as of this writing; see

'if', 'else', 'for', 'do', 'while', 'print', 'TRUE', 'FALSE'))
)

The optimizer run line would be something like this (assuming you have saved builtins-no-constants.txt in the same directory as main.py):

./main.py -b builtins-no-constants.txt -O -dcr,-optsigns,-optfloats,-listlength <filename>

The disabled options would preserve most of the original code intact. Constant folding would still be performed. I would advise to disable it as well, by adding -constfold to the options.

To clarify, the method is to make the optimizer think that they are not constants, but variables, by removing all actual constants and declaring them as variables at the top of the script. That should preserve the names as long as DCR is disabled. In the output, they should appear in the same order, so they should be easy to remove.

I'm concerned that doing this might trigger issue #3, though. If so, special handling may be needed when using a constant name inside a list, by removing the constant for input to the optimizer and adding it back after the output. Sorry if that's the case.

EDIT: On reflection, issue #3 is only triggered with DCR enabled, so this method is probably safe.

Thank you for your lateral thinking, it's worked very well by retaining much more readability while auto-formatting the scripts. Just what was needed :) I had tried a few other options designed for code beautification but mostly intended for JavaScript and none worked well on LSL.