|
24 | 24 | import de.peeeq.wurstscript.jassinterpreter.TestSuccessException; |
25 | 25 | import de.peeeq.wurstscript.jassprinter.JassPrinter; |
26 | 26 | import de.peeeq.wurstscript.luaAst.LuaCompilationUnit; |
| 27 | +import de.peeeq.wurstscript.luaAst.*; |
27 | 28 | import de.peeeq.wurstscript.translation.imtranslation.ImTranslator; |
28 | 29 | import de.peeeq.wurstscript.translation.imtranslation.RecycleCodeGeneratorQueue; |
29 | 30 | import de.peeeq.wurstscript.utils.Utils; |
@@ -460,6 +461,7 @@ private void translateAndTestLua(String name, boolean executeProg, WurstGui gui, |
460 | 461 | compiler.runCompiletime(new WurstProjectConfigData(), false, false); |
461 | 462 |
|
462 | 463 | LuaCompilationUnit luaCode = compiler.transformProgToLua(); |
| 464 | + checkLuaRootPurity(luaCode); |
463 | 465 | StringBuilder sb = new StringBuilder(); |
464 | 466 | luaCode.print(sb, 0); |
465 | 467 |
|
@@ -543,16 +545,114 @@ private void checkLuaSyntax(String luaExecutable, File luaFile) throws IOExcepti |
543 | 545 |
|
544 | 546 | private String getLuaExecutable() { |
545 | 547 | File bundledLuaWin = new File("src/test/resources/lua53.exe"); |
546 | | - if (bundledLuaWin.exists()) { |
547 | | - return bundledLuaWin.getPath(); |
548 | | - } |
549 | 548 | File bundledLuaUnix = new File("src/test/resources/lua53"); |
550 | | - if (bundledLuaUnix.exists()) { |
551 | | - return bundledLuaUnix.getPath(); |
| 549 | + String osName = System.getProperty("os.name", "").toLowerCase(); |
| 550 | + boolean isWindows = osName.contains("win"); |
| 551 | + |
| 552 | + if (isWindows) { |
| 553 | + if (bundledLuaWin.exists()) { |
| 554 | + return bundledLuaWin.getPath(); |
| 555 | + } |
| 556 | + if (bundledLuaUnix.exists()) { |
| 557 | + return bundledLuaUnix.getPath(); |
| 558 | + } |
| 559 | + } else { |
| 560 | + if (bundledLuaUnix.exists()) { |
| 561 | + // best effort in case execute bit was lost by checkout settings |
| 562 | + // (e.g. core.filemode false on some environments) |
| 563 | + bundledLuaUnix.setExecutable(true); |
| 564 | + if (bundledLuaUnix.canExecute()) { |
| 565 | + return bundledLuaUnix.getPath(); |
| 566 | + } |
| 567 | + } |
| 568 | + if (bundledLuaWin.exists() && bundledLuaWin.canExecute()) { |
| 569 | + return bundledLuaWin.getPath(); |
| 570 | + } |
552 | 571 | } |
553 | 572 | return "lua"; |
554 | 573 | } |
555 | 574 |
|
| 575 | + private void checkLuaRootPurity(LuaCompilationUnit luaCode) { |
| 576 | + Set<String> forbiddenRootCalls = Set.of( |
| 577 | + "CreateTrigger", "CreateTimer", "CreateUnit", "DestroyTrigger", "TimerStart", |
| 578 | + "CreateTimerBJ", "StartTimerBJ", "GetLastCreatedTimerBJ", |
| 579 | + "InitHashtable", "SaveInteger", "SaveBoolean", "SaveReal", "SaveStr", |
| 580 | + "LoadInteger", "LoadBoolean", "LoadReal", "LoadStr", "FlushChildHashtable" |
| 581 | + ); |
| 582 | + |
| 583 | + for (LuaStatement stmt : luaCode) { |
| 584 | + if (stmt instanceof LuaVariable) { |
| 585 | + LuaExprOpt initialValue = ((LuaVariable) stmt).getInitialValue(); |
| 586 | + if (initialValue instanceof LuaExpr) { |
| 587 | + assertNoForbiddenRootCall((LuaExpr) initialValue, forbiddenRootCalls); |
| 588 | + } |
| 589 | + } else if (stmt instanceof LuaAssignment) { |
| 590 | + assertNoForbiddenRootCall(((LuaAssignment) stmt).getRight(), forbiddenRootCalls); |
| 591 | + } else if (stmt instanceof LuaExprFunctionCallByName) { |
| 592 | + String funcName = ((LuaExprFunctionCallByName) stmt).getFuncName(); |
| 593 | + if (forbiddenRootCalls.contains(funcName)) { |
| 594 | + throw new Error("Lua root purity violation: forbidden root call to " + funcName); |
| 595 | + } |
| 596 | + } else if (stmt instanceof LuaExprFunctionCall) { |
| 597 | + String funcName = ((LuaExprFunctionCall) stmt).getFunc().getName(); |
| 598 | + if (forbiddenRootCalls.contains(funcName)) { |
| 599 | + throw new Error("Lua root purity violation: forbidden root call to " + funcName); |
| 600 | + } |
| 601 | + } |
| 602 | + } |
| 603 | + } |
| 604 | + |
| 605 | + private void assertNoForbiddenRootCall(LuaExpr expr, Set<String> forbiddenRootCalls) { |
| 606 | + if (expr instanceof LuaExprFunctionCallByName) { |
| 607 | + String name = ((LuaExprFunctionCallByName) expr).getFuncName(); |
| 608 | + if (forbiddenRootCalls.contains(name)) { |
| 609 | + throw new Error("Lua root purity violation: forbidden root call to " + name); |
| 610 | + } |
| 611 | + for (LuaExpr arg : ((LuaExprFunctionCallByName) expr).getArguments()) { |
| 612 | + assertNoForbiddenRootCall(arg, forbiddenRootCalls); |
| 613 | + } |
| 614 | + } else if (expr instanceof LuaExprFunctionCall) { |
| 615 | + String name = ((LuaExprFunctionCall) expr).getFunc().getName(); |
| 616 | + if (forbiddenRootCalls.contains(name)) { |
| 617 | + throw new Error("Lua root purity violation: forbidden root call to " + name); |
| 618 | + } |
| 619 | + for (LuaExpr arg : ((LuaExprFunctionCall) expr).getArguments()) { |
| 620 | + assertNoForbiddenRootCall(arg, forbiddenRootCalls); |
| 621 | + } |
| 622 | + } else if (expr instanceof LuaExprFunctionCallE) { |
| 623 | + LuaExprFunctionCallE call = (LuaExprFunctionCallE) expr; |
| 624 | + assertNoForbiddenRootCall(call.getFuncExpr(), forbiddenRootCalls); |
| 625 | + for (LuaExpr arg : call.getArguments()) { |
| 626 | + assertNoForbiddenRootCall(arg, forbiddenRootCalls); |
| 627 | + } |
| 628 | + } else if (expr instanceof LuaExprArrayAccess) { |
| 629 | + LuaExprArrayAccess a = (LuaExprArrayAccess) expr; |
| 630 | + assertNoForbiddenRootCall(a.getLeft(), forbiddenRootCalls); |
| 631 | + for (LuaExpr index : a.getIndexes()) { |
| 632 | + assertNoForbiddenRootCall(index, forbiddenRootCalls); |
| 633 | + } |
| 634 | + } else if (expr instanceof LuaExprBinary) { |
| 635 | + LuaExprBinary b = (LuaExprBinary) expr; |
| 636 | + assertNoForbiddenRootCall(b.getLeftExpr(), forbiddenRootCalls); |
| 637 | + assertNoForbiddenRootCall(b.getRight(), forbiddenRootCalls); |
| 638 | + } else if (expr instanceof LuaExprUnary) { |
| 639 | + assertNoForbiddenRootCall(((LuaExprUnary) expr).getRight(), forbiddenRootCalls); |
| 640 | + } else if (expr instanceof LuaExprFieldAccess) { |
| 641 | + assertNoForbiddenRootCall(((LuaExprFieldAccess) expr).getReceiver(), forbiddenRootCalls); |
| 642 | + } else if (expr instanceof LuaTableConstructor) { |
| 643 | + for (LuaTableField field : ((LuaTableConstructor) expr).getTableFields()) { |
| 644 | + if (field instanceof LuaTableNamedField) { |
| 645 | + assertNoForbiddenRootCall(((LuaTableNamedField) field).getVal(), forbiddenRootCalls); |
| 646 | + } else if (field instanceof LuaTableExprField) { |
| 647 | + assertNoForbiddenRootCall(((LuaTableExprField) field).getFieldKey(), forbiddenRootCalls); |
| 648 | + assertNoForbiddenRootCall(((LuaTableExprField) field).getVal(), forbiddenRootCalls); |
| 649 | + } else if (field instanceof LuaTableSingleField) { |
| 650 | + assertNoForbiddenRootCall(((LuaTableSingleField) field).getVal(), forbiddenRootCalls); |
| 651 | + } |
| 652 | + } |
| 653 | + } |
| 654 | + } |
| 655 | + |
556 | 656 | private void translateAndTest(String name, boolean executeProg, |
557 | 657 | boolean executeTests, WurstGui gui, WurstCompilerJassImpl compiler, |
558 | 658 | WurstModel model, boolean executeProgOnlyAfterTransforms) throws Error { |
|
0 commit comments