@@ -101,6 +101,7 @@ public class LuaTranslator {
101101
102102 final ImProg prog ;
103103 final LuaCompilationUnit luaModel ;
104+ private final LuaStatements deferredMainInit = LuaAst .LuaStatements ();
104105 private final Set <String > usedNames = new HashSet <>(Arrays .asList (
105106 // reserved function names
106107 "print" , "tostring" , "error" ,
@@ -180,7 +181,7 @@ public LuaMethod initFor(ImMethod a) {
180181 GetAForB <ImClass , LuaVariable > luaClassVar = new GetAForB <ImClass , LuaVariable >() {
181182 @ Override
182183 public LuaVariable initFor (ImClass a ) {
183- return LuaAst .LuaVariable (uniqueName (a .getName ()), LuaAst .LuaNoExpr ( ));
184+ return LuaAst .LuaVariable (uniqueName (a .getName ()), LuaAst .LuaTableConstructor ( LuaAst . LuaTableFields () ));
184185 }
185186 };
186187
@@ -321,9 +322,10 @@ public LuaCompilationUnit translate() {
321322 initClassTables (c );
322323 }
323324
325+ emitExperimentalHashtableLeakGuards ();
326+ prependDeferredMainInitToMain ();
324327 cleanStatements ();
325328 enforceLuaLocalLimits ();
326- emitExperimentalHashtableLeakGuards ();
327329
328330 return luaModel ;
329331 }
@@ -353,12 +355,39 @@ private void ensureWurstContextCallbackHelpers() {
353355 }
354356
355357 private void emitExperimentalHashtableLeakGuards () {
356- luaModel .add (LuaAst .LuaLiteral ("-- Wurst experimental Lua assertion guards: raw WC3 hashtable natives must not be called." ));
358+ deferMainInit (LuaAst .LuaLiteral ("-- Wurst experimental Lua assertion guards: raw WC3 hashtable natives must not be called." ));
359+ deferMainInit (LuaAst .LuaLiteral ("do" ));
360+ deferMainInit (LuaAst .LuaLiteral (" local __wurst_guard_ok = pcall(function()" ));
357361 for (String nativeName : allHashtableNativeNames ()) {
358- luaModel . add (LuaAst .LuaLiteral ("if " + nativeName + " ~= nil then " + nativeName
362+ deferMainInit (LuaAst .LuaLiteral (" if " + nativeName + " ~= nil then " + nativeName
359363 + " = function(...) error(\" Wurst Lua assertion failed: unexpected call to native " + nativeName
360364 + ". Expected __wurst_" + nativeName + ".\" ) end end" ));
361365 }
366+ deferMainInit (LuaAst .LuaLiteral (" end)" ));
367+ deferMainInit (LuaAst .LuaLiteral (" if not __wurst_guard_ok then" ));
368+ deferMainInit (LuaAst .LuaLiteral (" -- Some Lua runtimes lock native globals. Compile-time leak checks stay authoritative." ));
369+ deferMainInit (LuaAst .LuaLiteral (" end" ));
370+ deferMainInit (LuaAst .LuaLiteral ("end" ));
371+ }
372+
373+ private void deferMainInit (LuaStatement statement ) {
374+ deferredMainInit .add (statement );
375+ }
376+
377+ private void prependDeferredMainInitToMain () {
378+ if (deferredMainInit .isEmpty ()) {
379+ return ;
380+ }
381+ ImFunction mainIm = imTr .getMainFunc ();
382+ if (mainIm == null ) {
383+ return ;
384+ }
385+ LuaFunction mainLua = luaFunc .getFor (mainIm );
386+ LuaStatements mainBody = mainLua .getBody ();
387+ for (int i = deferredMainInit .size () - 1 ; i >= 0 ; i --) {
388+ LuaStatement stmt = deferredMainInit .remove (i );
389+ mainBody .add (0 , stmt );
390+ }
362391 }
363392
364393 public static void assertNoLeakedHashtableNativeCalls (String luaCode ) {
@@ -534,15 +563,17 @@ private void createInstanceOfFunction() {
534563
535564 private void createObjectIndexFunctions () {
536565 String vName = "__wurst_objectIndexMap" ;
537- LuaVariable v = LuaAst .LuaVariable (vName , LuaAst .LuaTableConstructor (LuaAst .LuaTableFields (
538- LuaAst .LuaTableNamedField ("counter" , LuaAst .LuaExprIntVal ("0" ))
539- )));
566+ LuaVariable v = LuaAst .LuaVariable (vName , LuaAst .LuaExprNull ());
540567 luaModel .add (v );
541-
542- LuaVariable im = LuaAst .LuaVariable ("__wurst_number_wrapper_map" , LuaAst .LuaTableConstructor (LuaAst .LuaTableFields (
568+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprVarAccess (v ), LuaAst .LuaTableConstructor (LuaAst .LuaTableFields (
543569 LuaAst .LuaTableNamedField ("counter" , LuaAst .LuaExprIntVal ("0" ))
544- )));
570+ ))));
571+
572+ LuaVariable im = LuaAst .LuaVariable ("__wurst_number_wrapper_map" , LuaAst .LuaExprNull ());
545573 luaModel .add (im );
574+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprVarAccess (im ), LuaAst .LuaTableConstructor (LuaAst .LuaTableFields (
575+ LuaAst .LuaTableNamedField ("counter" , LuaAst .LuaExprIntVal ("0" ))
576+ ))));
546577
547578 {
548579 String [] code = {
@@ -597,12 +628,13 @@ private void createObjectIndexFunctions() {
597628 }
598629
599630 private void createStringIndexFunctions () {
600- LuaVariable map = LuaAst .LuaVariable ("__wurst_string_index_map" , LuaAst .LuaTableConstructor (LuaAst .LuaTableFields (
631+ LuaVariable map = LuaAst .LuaVariable ("__wurst_string_index_map" , LuaAst .LuaExprNull ());
632+ luaModel .add (map );
633+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprVarAccess (map ), LuaAst .LuaTableConstructor (LuaAst .LuaTableFields (
601634 LuaAst .LuaTableNamedField ("counter" , LuaAst .LuaExprIntVal ("0" )),
602635 LuaAst .LuaTableNamedField ("byString" , LuaAst .LuaTableConstructor (LuaAst .LuaTableFields ())),
603636 LuaAst .LuaTableNamedField ("byIndex" , LuaAst .LuaTableConstructor (LuaAst .LuaTableFields ()))
604- )));
605- luaModel .add (map );
637+ ))));
606638
607639 {
608640 String [] code = {
@@ -995,8 +1027,6 @@ private void translateClass(ImClass c) {
9951027
9961028 luaModel .add (initMethod );
9971029
998- classVar .setInitialValue (emptyTable ());
999-
10001030 // translate functions
10011031 for (ImFunction f : c .getFunctions ()) {
10021032 translateFunc (f );
@@ -1038,14 +1068,14 @@ private void initClassTables(ImClass c) {
10381068 // set supertype metadata:
10391069 LuaTableFields superClasses = LuaAst .LuaTableFields ();
10401070 collectSuperClasses (superClasses , c , new HashSet <>());
1041- luaModel . add (LuaAst .LuaAssignment (LuaAst .LuaExprFieldAccess (
1071+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprFieldAccess (
10421072 LuaAst .LuaExprVarAccess (classVar ),
10431073 WURST_SUPERTYPES ),
10441074 LuaAst .LuaTableConstructor (superClasses )
10451075 ));
10461076
10471077 // set typeid metadata:
1048- luaModel . add (LuaAst .LuaAssignment (LuaAst .LuaExprFieldAccess (
1078+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprFieldAccess (
10491079 LuaAst .LuaExprVarAccess (classVar ),
10501080 ExprTranslation .TYPE_ID ),
10511081 LuaAst .LuaExprIntVal ("" + prog .attrTypeId ().get (c ))
@@ -1100,7 +1130,7 @@ private void createMethods(ImClass c, LuaVariable classVar) {
11001130 if (impl == null || impl .getImplementation () == null ) {
11011131 continue ;
11021132 }
1103- luaModel . add (LuaAst .LuaAssignment (LuaAst .LuaExprFieldAccess (
1133+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprFieldAccess (
11041134 LuaAst .LuaExprVarAccess (classVar ),
11051135 e .getKey ()),
11061136 LuaAst .LuaExprFuncRef (luaFunc .getFor (impl .getImplementation ()))
@@ -1343,8 +1373,9 @@ private void translateGlobal(ImVar v) {
13431373 return ;
13441374 }
13451375 LuaVariable lv = luaVar .getFor (v );
1346- lv .setInitialValue (defaultValue ( v . getType () ));
1376+ lv .setInitialValue (LuaAst . LuaExprNull ( ));
13471377 luaModel .add (lv );
1378+ deferMainInit (LuaAst .LuaAssignment (LuaAst .LuaExprVarAccess (lv ), defaultValue (v .getType ())));
13481379 }
13491380
13501381 private LuaExpr defaultValue (ImType type ) {
0 commit comments