wurstscript / WurstScript

Programming language and toolkit to create Warcraft III Maps
https://wurstlang.org
Apache License 2.0
225 stars 30 forks source link

Improve Lua optimizers #1063

Closed Jampi0n closed 2 years ago

Jampi0n commented 2 years ago

Bugfixes and improvements for Lua optimizers. Implements some handling of tuples and members that was missing and could cause:

Compiler error due to unattached variables, when doing some optimizations with tuples -inline -localOptimizations -lua ``` package MyTest function locals() returns bool var d = vec2(1,0) d.y = 2 return d.x == 1 init if locals() print("Success") ```
Wrong output script due to incorrect assumptions by the optimizer -inline -localOptimizations -lua ``` package ListSort import LinkedList init let list = new LinkedList() list.add(1,2) list.sort() print(list.get(0)) print(list.get(1)) ``` This prints 1 and 0. It is caused by the split function in LinkedList: ``` ... let tmp = halfRef.next halfRef.next = dummy return tmp ``` Without stacktraces, only the member set halfRef.next is between the tmp accesses and the optimizer would think tmp equals halfRef.next, so it can just return halfRef.next.

The optimizer now also deals better with tuple literals and avoids copying them after constructing them. There are still possible improvements for tuples, but I first wanted to fix the bugs.

Unused members are now removed like in Jass.

Some Lua translation steps that relied on type information were moved before local optimizations:

This makes it possible to unify some types before the optimizers, allowing more local merging. Arrays and tuple types are kept, because they are required for the initialization.

I actually only found the first issue by running all unit tests with Lua and getting the error. With these changes all unit tests also passed in Lua with the same optimizer options as in Jass, as long as execution is disabled for Lua. Maybe it would be good to have unit tests by default also compile with Lua just so compiler errors would be detected.

Frotty commented 2 years ago

Cool that you still finished it, massive props 👍 I plan to use it for jass to lua map optimization in w3p.

Maybe it would be good to have unit tests by default also compile with Lua just so compiler errors would be detected.

Yea, could be enabled by default. I guess only the lua execution binary is the problem?

Jampi0n commented 2 years ago

I guess only the lua execution binary is the problem?

Executing Lua with standard library generally doesn't work, because it uses natives (e.g. InitHashtable for compiletime state). With the above two changes and disabling Lua execution while standard library is enabled, all but one test pass. The test that fails is enum_to_int_test, because enum to int cast works differently in Lua and the third value in the enum is not necessarily 2. That's probably something that should be changed as well, considering the manual states:

The coalescent integer value starts at 0, incrementing with each succeeding enum member. So for MyUnitState FLYING will be 0, GROUND 1 and WATER 2.