|
22 | 22 |
|
23 | 23 | public class LuaTranslator { |
24 | 24 | private static final int LUA_LOCALS_LIMIT = 200; |
| 25 | + private static final List<String> REQUIRED_WURST_HASHTABLE_HELPERS = Arrays.asList( |
| 26 | + "__wurst_InitHashtable", |
| 27 | + "__wurst_SaveInteger", "__wurst_SaveBoolean", "__wurst_SaveReal", "__wurst_SaveStr", |
| 28 | + "__wurst_LoadInteger", "__wurst_LoadBoolean", "__wurst_LoadReal", "__wurst_LoadStr", |
| 29 | + "__wurst_HaveSavedInteger", "__wurst_HaveSavedBoolean", "__wurst_HaveSavedReal", "__wurst_HaveSavedString", |
| 30 | + "__wurst_FlushChildHashtable", "__wurst_FlushParentHashtable", |
| 31 | + "__wurst_RemoveSavedInteger", "__wurst_RemoveSavedBoolean", "__wurst_RemoveSavedReal", "__wurst_RemoveSavedString" |
| 32 | + ); |
25 | 33 | private static final Set<String> HASHTABLE_NATIVE_NAMES = new HashSet<>(Arrays.asList( |
26 | 34 | "InitHashtable", |
27 | 35 | "SaveInteger", "SaveBoolean", "SaveReal", "SaveStr", |
@@ -202,6 +210,7 @@ public LuaCompilationUnit translate() { |
202 | 210 | createInstanceOfFunction(); |
203 | 211 | createObjectIndexFunctions(); |
204 | 212 | createEnsureTypeFunctions(); |
| 213 | + ensureWurstHashtableHelpers(); |
205 | 214 |
|
206 | 215 | for (ImVar v : prog.getGlobals()) { |
207 | 216 | translateGlobal(v); |
@@ -230,6 +239,19 @@ public LuaCompilationUnit translate() { |
230 | 239 | return luaModel; |
231 | 240 | } |
232 | 241 |
|
| 242 | + /** |
| 243 | + * Always emit internal hashtable helper functions used by Lua lowering. |
| 244 | + * This keeps compiletime migration data loading robust even if the |
| 245 | + * corresponding Warcraft natives are unavailable or filtered out. |
| 246 | + */ |
| 247 | + private void ensureWurstHashtableHelpers() { |
| 248 | + for (String helper : REQUIRED_WURST_HASHTABLE_HELPERS) { |
| 249 | + LuaFunction f = LuaAst.LuaFunction(helper, LuaAst.LuaParams(), LuaAst.LuaStatements()); |
| 250 | + LuaNatives.get(f); |
| 251 | + luaModel.add(f); |
| 252 | + } |
| 253 | + } |
| 254 | + |
233 | 255 | private boolean isFixedEntryPoint(ImFunction function) { |
234 | 256 | return function == imTr.getMainFunc() || function == imTr.getConfFunc(); |
235 | 257 | } |
@@ -444,24 +466,29 @@ function defaultArray(d) |
444 | 466 | } |
445 | 467 |
|
446 | 468 | private void createEnsureTypeFunctions() { |
447 | | - LuaFunction[] ensureTypeFunctions = {ensureIntFunction, ensureBoolFunction, ensureRealFunction, ensureStrFunction}; |
448 | | - String[] defaultValue = {"0", "false", "0.0", "\"\""}; |
449 | | - for(int i = 0; i < ensureTypeFunctions.length; ++i) { |
450 | | - LuaFunction ensureTypeFunction = ensureTypeFunctions[i]; |
451 | | - String[] code = { |
452 | | - "if x == nil then", |
453 | | - " return " + defaultValue[i], |
454 | | - "else", |
455 | | - " return " + (ensureTypeFunction == ensureIntFunction ? "math.tointeger(x)" : "x"), |
456 | | - "end" |
457 | | - }; |
458 | | - |
459 | | - ensureTypeFunction.getParams().add(LuaAst.LuaVariable("x", LuaAst.LuaNoExpr())); |
460 | | - for (String c : code) { |
461 | | - ensureTypeFunction.getBody().add(LuaAst.LuaLiteral(c)); |
462 | | - } |
463 | | - luaModel.add(ensureTypeFunction); |
464 | | - } |
| 469 | + ensureIntFunction.getParams().add(LuaAst.LuaVariable("x", LuaAst.LuaNoExpr())); |
| 470 | + ensureIntFunction.getBody().add(LuaAst.LuaLiteral("local n = tonumber(x)")); |
| 471 | + ensureIntFunction.getBody().add(LuaAst.LuaLiteral("if n == nil then return 0 end")); |
| 472 | + ensureIntFunction.getBody().add(LuaAst.LuaLiteral("local i = math.tointeger(n)")); |
| 473 | + ensureIntFunction.getBody().add(LuaAst.LuaLiteral("if i == nil then return 0 end")); |
| 474 | + ensureIntFunction.getBody().add(LuaAst.LuaLiteral("return i")); |
| 475 | + luaModel.add(ensureIntFunction); |
| 476 | + |
| 477 | + ensureBoolFunction.getParams().add(LuaAst.LuaVariable("x", LuaAst.LuaNoExpr())); |
| 478 | + ensureBoolFunction.getBody().add(LuaAst.LuaLiteral("if x == nil then return false end")); |
| 479 | + ensureBoolFunction.getBody().add(LuaAst.LuaLiteral("return x")); |
| 480 | + luaModel.add(ensureBoolFunction); |
| 481 | + |
| 482 | + ensureRealFunction.getParams().add(LuaAst.LuaVariable("x", LuaAst.LuaNoExpr())); |
| 483 | + ensureRealFunction.getBody().add(LuaAst.LuaLiteral("local n = tonumber(x)")); |
| 484 | + ensureRealFunction.getBody().add(LuaAst.LuaLiteral("if n == nil then return 0.0 end")); |
| 485 | + ensureRealFunction.getBody().add(LuaAst.LuaLiteral("return n")); |
| 486 | + luaModel.add(ensureRealFunction); |
| 487 | + |
| 488 | + ensureStrFunction.getParams().add(LuaAst.LuaVariable("x", LuaAst.LuaNoExpr())); |
| 489 | + ensureStrFunction.getBody().add(LuaAst.LuaLiteral("if x == nil then return \"\" end")); |
| 490 | + ensureStrFunction.getBody().add(LuaAst.LuaLiteral("return tostring(x)")); |
| 491 | + luaModel.add(ensureStrFunction); |
465 | 492 | } |
466 | 493 |
|
467 | 494 | private void cleanStatements() { |
|
0 commit comments