├── .github
└── workflows
│ └── jarbuild.yml
├── .hgignore
├── .idea
├── artifacts
│ └── unluac_jar.xml
└── vcs.xml
├── README.md
├── authors.txt
├── license.txt
├── out
└── .gitkeep
├── src
├── META-INF
│ └── MANIFEST.MF
└── unluac
│ ├── Configuration.java
│ ├── Main.java
│ ├── Version.java
│ ├── assemble
│ ├── Assembler.java
│ ├── AssemblerException.java
│ ├── Directive.java
│ └── Tokenizer.java
│ ├── decompile
│ ├── AssertionManager.java
│ ├── Code.java
│ ├── CodeExtract.java
│ ├── Constant.java
│ ├── ControlFlowHandler.java
│ ├── Declaration.java
│ ├── Decompiler.java
│ ├── Disassembler.java
│ ├── Function.java
│ ├── Op.java
│ ├── OpcodeMap.java
│ ├── OperandFormat.java
│ ├── Output.java
│ ├── OutputProvider.java
│ ├── Registers.java
│ ├── Upvalues.java
│ ├── Validator.java
│ ├── VariableFinder.java
│ ├── Walker.java
│ ├── block
│ │ ├── AlwaysLoop.java
│ │ ├── Block.java
│ │ ├── Break.java
│ │ ├── ContainerBlock.java
│ │ ├── DoEndBlock.java
│ │ ├── ElseEndBlock.java
│ │ ├── ForBlock.java
│ │ ├── ForBlock50.java
│ │ ├── ForBlock51.java
│ │ ├── Goto.java
│ │ ├── IfThenElseBlock.java
│ │ ├── IfThenEndBlock.java
│ │ ├── OnceLoop.java
│ │ ├── OuterBlock.java
│ │ ├── RepeatBlock.java
│ │ ├── SetBlock.java
│ │ ├── TForBlock.java
│ │ └── WhileBlock.java
│ ├── condition
│ │ ├── AndCondition.java
│ │ ├── BinaryCondition.java
│ │ ├── Condition.java
│ │ ├── ConstantCondition.java
│ │ ├── FinalSetCondition.java
│ │ ├── NotCondition.java
│ │ ├── OrCondition.java
│ │ └── TestCondition.java
│ ├── expression
│ │ ├── BinaryExpression.java
│ │ ├── ClosureExpression.java
│ │ ├── ConstantExpression.java
│ │ ├── Expression.java
│ │ ├── FunctionCall.java
│ │ ├── GlobalExpression.java
│ │ ├── LocalVariable.java
│ │ ├── TableLiteral.java
│ │ ├── TableReference.java
│ │ ├── UnaryExpression.java
│ │ ├── UpvalueExpression.java
│ │ └── Vararg.java
│ ├── operation
│ │ ├── CallOperation.java
│ │ ├── GlobalSet.java
│ │ ├── LoadNil.java
│ │ ├── MultipleRegisterSet.java
│ │ ├── Operation.java
│ │ ├── RegisterSet.java
│ │ ├── ReturnOperation.java
│ │ ├── TableSet.java
│ │ └── UpvalueSet.java
│ ├── statement
│ │ ├── Assignment.java
│ │ ├── Declare.java
│ │ ├── FunctionCallStatement.java
│ │ ├── Label.java
│ │ ├── Return.java
│ │ └── Statement.java
│ └── target
│ │ ├── GlobalTarget.java
│ │ ├── TableTarget.java
│ │ ├── Target.java
│ │ ├── UpvalueTarget.java
│ │ └── VariableTarget.java
│ ├── parse
│ ├── BHeader.java
│ ├── BInteger.java
│ ├── BIntegerType.java
│ ├── BList.java
│ ├── BObject.java
│ ├── BObjectType.java
│ ├── LAbsLineInfo.java
│ ├── LAbsLineInfoType.java
│ ├── LBoolean.java
│ ├── LBooleanType.java
│ ├── LConstantType.java
│ ├── LFunction.java
│ ├── LFunctionType.java
│ ├── LHeader.java
│ ├── LHeaderType.java
│ ├── LLocal.java
│ ├── LLocalType.java
│ ├── LNil.java
│ ├── LNumber.java
│ ├── LNumberType.java
│ ├── LObject.java
│ ├── LSourceLines.java
│ ├── LString.java
│ ├── LStringType.java
│ ├── LUpvalue.java
│ └── LUpvalueType.java
│ ├── test
│ ├── Compare.java
│ ├── LuaC.java
│ ├── LuaSpec.java
│ ├── RunExtendedTests.java
│ ├── RunTest.java
│ ├── RunTests.java
│ ├── TestFiles.java
│ ├── TestReport.java
│ ├── TestResult.java
│ ├── TestSuite.java
│ └── UnluacSpec.java
│ └── util
│ ├── Stack.java
│ └── StringUtils.java
├── test
└── src
│ ├── 51_adjust02.lua
│ ├── 51_adjust03.lua
│ ├── 51_ellipsis.lua
│ ├── 51_ellipsis02.lua
│ ├── 51_expression.lua
│ ├── 51_expression03.lua
│ ├── 51_expression2.lua
│ ├── 51_method03.lua
│ ├── 51_string03.lua
│ ├── 52_goto01.lua
│ ├── 52_goto02.lua
│ ├── 52_goto03.lua
│ ├── 52_loadkx01.lua
│ ├── 53_expression.lua
│ ├── 53_expression02.lua
│ ├── 54_tbc01.lua
│ ├── adjust01.lua
│ ├── adjust04.lua
│ ├── adjust05.lua
│ ├── adjust06.lua
│ ├── always01.lua
│ ├── always02.lua
│ ├── always03.lua
│ ├── always04.lua
│ ├── assign.lua
│ ├── booleanassign01.lua
│ ├── booleanassign02.lua
│ ├── booleanassign03.lua
│ ├── booleanassign04.lua
│ ├── booleanassign05.lua
│ ├── booleanassign06.lua
│ ├── booleanassign07.lua
│ ├── booleanassign08.lua
│ ├── booleanassign09.lua
│ ├── booleanassign10.lua
│ ├── booleanassign11.lua
│ ├── booleanassign12.lua
│ ├── booleanassign13.lua
│ ├── booleanassign14.lua
│ ├── booleanassign15.lua
│ ├── booleanassign16.lua
│ ├── booleanassign17.lua
│ ├── booleanassign18.lua
│ ├── booleanassign19.lua
│ ├── booleanassign20.lua
│ ├── booleanassign21.lua
│ ├── booleanassign22.lua
│ ├── booleanassign23.lua
│ ├── booleanassign24.lua
│ ├── booleanassign25.lua
│ ├── booleanassign26.lua
│ ├── booleanassign27.lua
│ ├── booleanassign28.lua
│ ├── booleanexpression01.lua
│ ├── booleanexpression02.lua
│ ├── booleanexpression03.lua
│ ├── booleanexpression04.lua
│ ├── booleanexpression05.lua
│ ├── booleanexpression06.lua
│ ├── booleanexpression07.lua
│ ├── booleanexpression08.lua
│ ├── booleanexpression09.lua
│ ├── booleanexpression10.lua
│ ├── booleanmultiassign01.lua
│ ├── booleanmultiassign02.lua
│ ├── booleanselfassign01.lua
│ ├── break01.lua
│ ├── break02.lua
│ ├── break03.lua
│ ├── break04.lua
│ ├── break05.lua
│ ├── break06.lua
│ ├── break07.lua
│ ├── break08.lua
│ ├── break09.lua
│ ├── break10.lua
│ ├── close01.lua
│ ├── close02.lua
│ ├── close03.lua
│ ├── close04.lua
│ ├── closure.lua
│ ├── combinebassign01.lua
│ ├── combinebassign02.lua
│ ├── combinebassign03.lua
│ ├── combinebassign04.lua
│ ├── combinebassign05.lua
│ ├── combinebassign07.lua
│ ├── combinebexpression01.lua
│ ├── combinebexpression02.lua
│ ├── combinebexpression03.lua
│ ├── combinebexpression04.lua
│ ├── combinebexpression05.lua
│ ├── combinebexpression06.lua
│ ├── combinebexpression07.lua
│ ├── compare01.lua
│ ├── compareassign01.lua
│ ├── compareassign02.lua
│ ├── compareexpression.lua
│ ├── compareexpression02.lua
│ ├── compareorder01.lua
│ ├── compareorder02.lua
│ ├── compareorder03.lua
│ ├── compareorder04.lua
│ ├── compareorder05.lua
│ ├── compareorder06.lua
│ ├── compareorder07.lua
│ ├── compareorder08.lua
│ ├── complexassign01.lua
│ ├── complexassign02.lua
│ ├── complexassign03.lua
│ ├── condition.lua
│ ├── condition02.lua
│ ├── condition03.lua
│ ├── control01.lua
│ ├── control02.lua
│ ├── control03.lua
│ ├── control04.lua
│ ├── control05.lua
│ ├── control06.lua
│ ├── control07.lua
│ ├── declare.lua
│ ├── declare02.lua
│ ├── declare03.lua
│ ├── declare04.lua
│ ├── declare05.lua
│ ├── doend01.lua
│ ├── doend02.lua
│ ├── doend03.lua
│ ├── doend04.lua
│ ├── doend05.lua
│ ├── doend06.lua
│ ├── doend07.lua
│ ├── doend08.lua
│ ├── ellipsis03.lua
│ ├── else01.lua
│ ├── else02.lua
│ ├── else03.lua
│ ├── else04.lua
│ ├── else05.lua
│ ├── else06.lua
│ ├── else07.lua
│ ├── expression.lua
│ ├── expression02.lua
│ ├── final01.lua
│ ├── final02.lua
│ ├── functioncall.lua
│ ├── if01.lua
│ ├── if02.lua
│ ├── if03.lua
│ ├── if04.lua
│ ├── if05.lua
│ ├── if06.lua
│ ├── if07.lua
│ ├── ifthen.lua
│ ├── ifthenelse.lua
│ ├── inlineconstant01.lua
│ ├── inlinefunction01.lua
│ ├── inlinefunction02.lua
│ ├── literal.lua
│ ├── literallist.lua
│ ├── localbooleanassign.lua
│ ├── localfunction01.lua
│ ├── localfunction02.lua
│ ├── localfunction03.lua
│ ├── localfunction04.lua
│ ├── loop01.lua
│ ├── loop02.lua
│ ├── loop03.lua
│ ├── loop04.lua
│ ├── method01.lua
│ ├── method02.lua
│ ├── multiassign.lua
│ ├── multiassign02.lua
│ ├── multiassign03.lua
│ ├── multiassign04.lua
│ ├── multiassign05.lua
│ ├── multiassign06.lua
│ ├── multiliteraltarget.lua
│ ├── nestedif.lua
│ ├── nestedif02.lua
│ ├── number01.lua
│ ├── number02.lua
│ ├── number03.lua
│ ├── once01.lua
│ ├── once02.lua
│ ├── once03.lua
│ ├── once04.lua
│ ├── once05.lua
│ ├── repeat.lua
│ ├── repeat02.lua
│ ├── repeat03.lua
│ ├── report01_full.lua
│ ├── report01a.lua
│ ├── report01b.lua
│ ├── report01c.lua
│ ├── report01d.lua
│ ├── report02.lua
│ ├── report02a.lua
│ ├── report02b.lua
│ ├── report02c.lua
│ ├── report02d.lua
│ ├── report02e.lua
│ ├── report03.lua
│ ├── report04.lua
│ ├── report05.lua
│ ├── scope02.lua
│ ├── scope03.lua
│ ├── self01.lua
│ ├── string01.lua
│ ├── string02.lua
│ ├── string04.lua
│ ├── table01.lua
│ ├── table02.lua
│ ├── table03.lua
│ ├── table06.lua
│ ├── table07.lua
│ ├── unused01.lua
│ ├── upvalue01.lua
│ ├── upvalue02.lua
│ ├── upvalue03.lua
│ ├── upvalue04.lua
│ ├── upvalue05.lua
│ ├── while.lua
│ ├── while02.lua
│ ├── while03.lua
│ ├── while04.lua
│ ├── while05.lua
│ ├── while06.lua
│ └── while07.lua
└── unluac.iml
/.github/workflows/jarbuild.yml:
--------------------------------------------------------------------------------
1 | name: unluac Nightly Build
2 | on: push
3 |
4 | jobs:
5 | jarbuild:
6 | name: Build Jar
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - name: Get commit info
11 | id: vars
12 | shell: bash
13 | run: |
14 | echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
15 | echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
16 | - name: Setup JDK
17 | uses: actions/setup-java@v1
18 | with:
19 | java-version: '9.0.4'
20 | - name: Build
21 | run: |
22 | mkdir build
23 | javac -d build -sourcepath src src/unluac/*.java
24 | jar -cfm build/unluac.jar src/META-INF/MANIFEST.MF -C build .
25 | - name: Upload
26 | uses: actions/upload-artifact@v2
27 | with:
28 | name: unluac-${{ steps.vars.outputs.branch }}-${{ steps.vars.outputs.sha_short }}.jar
29 | path: build/unluac.jar
--------------------------------------------------------------------------------
/.hgignore:
--------------------------------------------------------------------------------
1 | syntax: glob
2 | .gradle
3 | bin
4 | build
5 | luac
6 | test/working
7 | *.orig
8 | *.rej
9 |
--------------------------------------------------------------------------------
/.idea/artifacts/unluac_jar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # unluac for MiWifi
2 |
3 | 
4 |
5 | Xiaomi Router encrypts its lua files in models AC2100, AX3600, R4.
6 |
7 | They modified the Lua interpreter, which introduces string encryption, shifted opcode order, and customized opcodes.
8 |
9 | This unluac is imported from upstream unluac at 2020.6.14
10 |
11 | Credits:
12 | - @lvqier for the initial port from https://github.com/lvqier/unluac
13 | - unluac team for a brilliant luac decompiler
14 |
--------------------------------------------------------------------------------
/authors.txt:
--------------------------------------------------------------------------------
1 | tehtmi -- main developer
2 | Thomas Klaeger -- added support for Lua 5.0
3 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-2016 tehtmi
2 | With Portions Copyright (c) 2014 Thomas Klaeger
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/out/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NyaMisty/unluac_miwifi/20a679402a409b6c3829e7fcba96cf5c49cffd08/out/.gitkeep
--------------------------------------------------------------------------------
/src/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: unluac.Main
3 |
4 |
--------------------------------------------------------------------------------
/src/unluac/Configuration.java:
--------------------------------------------------------------------------------
1 | package unluac;
2 |
3 | public class Configuration {
4 |
5 | public enum Mode {
6 | DECOMPILE,
7 | DISASSEMBLE,
8 | ASSEMBLE,
9 | }
10 |
11 | public enum VariableMode {
12 | DEFAULT,
13 | FINDER,
14 | }
15 |
16 | public boolean rawstring = false;
17 | public Mode mode = Mode.DECOMPILE;
18 | public VariableMode variable = VariableMode.DEFAULT;
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/unluac/assemble/AssemblerException.java:
--------------------------------------------------------------------------------
1 | package unluac.assemble;
2 |
3 | @SuppressWarnings("serial")
4 | public class AssemblerException extends Exception {
5 |
6 | AssemblerException(String msg) {
7 | super(msg);
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/unluac/assemble/Tokenizer.java:
--------------------------------------------------------------------------------
1 | package unluac.assemble;
2 |
3 | import java.io.IOException;
4 | import java.io.Reader;
5 |
6 | public class Tokenizer {
7 |
8 | private StringBuilder b;
9 | private Reader r;
10 |
11 | public Tokenizer(Reader r) {
12 | this.r = r;
13 | b = new StringBuilder();
14 | }
15 |
16 | public String next() throws IOException {
17 | b.setLength(0);
18 |
19 | boolean inToken = false;
20 | boolean inString = false;
21 | boolean isLPrefix = false;
22 |
23 | for(;;) {
24 | int code = r.read();
25 | if(code == -1) break;
26 | char c = (char)code;
27 | //if(c == '\n') System.out.println("line");
28 | if(Character.isWhitespace(c)) {
29 | if(inToken && !inString) {
30 | break;
31 | } else if(inString) {
32 | b.append(c);
33 | }
34 | } else if(inString && c == '"') {
35 | b.append(c);
36 | break;
37 | } else {
38 | if((!inToken || isLPrefix) && c == '"') {
39 | inString = true;
40 | } else if(!inToken && c == 'L') {
41 | isLPrefix = true;
42 | } else {
43 | isLPrefix = false;
44 | }
45 | inToken = true;
46 | b.append(c);
47 | }
48 | }
49 |
50 | //System.out.println("token: <" + b.toString() + ">");
51 |
52 | if(b.length() == 0) {
53 | return null;
54 | } else {
55 | return b.toString();
56 | }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/unluac/decompile/AssertionManager.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | public class AssertionManager {
4 |
5 | public static boolean assertCritical(boolean condition, String message) {
6 | if(condition) {
7 | // okay
8 | } else {
9 | critical(message);
10 | }
11 | return condition;
12 | }
13 |
14 | public static void critical(String message) {
15 | throw new IllegalStateException(message);
16 | }
17 |
18 | //static only
19 | private AssertionManager() {}
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/unluac/decompile/CodeExtract.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | import unluac.Version;
4 |
5 | public class CodeExtract {
6 |
7 | public static class Field {
8 |
9 | public Field(int size, int shift) {
10 | this(size, shift, 0);
11 | }
12 |
13 | public Field(int size, int shift, int offset) {
14 | this.size = size;
15 | this.shift = shift;
16 | this.mask = size_to_mask(size);
17 | this.offset = offset;
18 | }
19 |
20 | public int extract(int codepoint) {
21 | return ((codepoint >>> shift) & mask) - offset;
22 | }
23 |
24 | public boolean check(int x) {
25 | return ((x + offset) & ~mask) == 0;
26 | }
27 |
28 | public int encode(int x) {
29 | return (x + offset) << shift;
30 | }
31 |
32 | public int clear(int codepoint) {
33 | return codepoint & ~(mask << shift);
34 | }
35 |
36 | public int max() {
37 | return mask - offset;
38 | }
39 |
40 | public final int size;
41 | private final int shift;
42 | private final int mask;
43 | private final int offset;
44 |
45 | }
46 |
47 | public CodeExtract(Version version, int sizeOp, int sizeA, int sizeB, int sizeC) {
48 | switch(version.instructionformat.get()) {
49 | case LUA50:
50 | op = new Field(sizeOp, 0);
51 | A = new Field(sizeA, sizeB + sizeC + sizeOp);
52 | B = new Field(sizeB, sizeB + sizeOp);
53 | C = new Field(sizeC, sizeOp);
54 | k = null;
55 | Ax = null;
56 | sJ = null;
57 | Bx = new Field(sizeB + sizeC, sizeOp);
58 | sBx = new Field(sizeB + sizeC, sizeOp, size_to_mask(sizeB + sizeC) / 2);
59 | x = new Field(32, 0);
60 | break;
61 | case LUA51:
62 | op = new Field(6, 0);
63 | A = new Field(8, 6);
64 | B = new Field(9, 23);
65 | C = new Field(9, 14);
66 | k = null;
67 | Ax = new Field(26, 6);
68 | sJ = null;
69 | Bx = new Field(18, 14);
70 | sBx = new Field(18, 14, 131071);
71 | x = new Field(32, 0);
72 | break;
73 | case LUA54:
74 | op = new Field(7, 0);
75 | A = new Field(8, 7);
76 | B = new Field(8, 16);
77 | C = new Field(8, 24);
78 | k = new Field(1, 15);
79 | Ax = new Field(25, 7);
80 | sJ = new Field(25, 7, (1 << 24) - 1);
81 | Bx = new Field(17, 15);
82 | sBx = new Field(17, 15, (1 << 16) - 1);
83 | x = new Field(32, 0);
84 | break;
85 | default:
86 | throw new IllegalStateException();
87 | }
88 | Integer rk_offset = version.rkoffset.get();
89 | this.rk_offset = (rk_offset == null) ? -1 : rk_offset;
90 | }
91 |
92 | public boolean is_k(int field) {
93 | return field >= rk_offset;
94 | }
95 |
96 | public int get_k(int field) {
97 | return field - rk_offset;
98 | }
99 |
100 | public int encode_k(int constant) {
101 | return constant + rk_offset;
102 | }
103 |
104 | public final Field op;
105 | public final Field A;
106 | public final Field B;
107 | public final Field C;
108 | public final Field k;
109 | public final Field Ax;
110 | public final Field sJ;
111 | public final Field Bx;
112 | public final Field sBx;
113 | public final Field x;
114 |
115 | private final int rk_offset;
116 |
117 | private static int size_to_mask(int size) {
118 | return (int)((1L << size) - 1);
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/src/unluac/decompile/Declaration.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | import unluac.parse.LLocal;
4 |
5 | public class Declaration {
6 |
7 | public final String name;
8 | public final int begin;
9 | public final int end;
10 | public int register;
11 | public boolean tbc;
12 |
13 | /**
14 | * Whether this is an invisible for-loop book-keeping variable.
15 | */
16 | public boolean forLoop = false;
17 |
18 | /**
19 | * Whether this is an explicit for-loop declared variable.
20 | */
21 | public boolean forLoopExplicit = false;
22 |
23 | public Declaration(LLocal local, Code code) {
24 | int adjust = 0;
25 | if(local.start >= 1) {
26 | Op op = code.op(local.start);
27 | if(op == Op.MMBIN || op == Op.MMBINI || op == Op.MMBINK || op == Op.EXTRAARG) {
28 | adjust--;
29 | }
30 | }
31 | this.name = local.toString();
32 | this.begin = local.start + adjust;
33 | this.end = local.end;
34 | this.tbc = false;
35 | }
36 |
37 | public Declaration(String name, int begin, int end) {
38 | this.name = name;
39 | this.begin = begin;
40 | this.end = end;
41 | }
42 |
43 | public boolean isSplitBy(int begin, int end) {
44 | return (begin <= this.begin && this.begin < end && end <= this.end)
45 | || (begin <= this.end && this.end < end - 1 && this.begin < begin);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/unluac/decompile/Function.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | import unluac.Version;
4 | import unluac.decompile.expression.ConstantExpression;
5 | import unluac.decompile.expression.GlobalExpression;
6 | import unluac.parse.LFunction;
7 |
8 | public class Function {
9 |
10 | private Version version;
11 | private Constant[] constants;
12 | private final CodeExtract extract;
13 |
14 | public Function(LFunction function) {
15 | version = function.header.version;
16 | constants = new Constant[function.constants.length];
17 | for(int i = 0; i < constants.length; i++) {
18 | constants[i] = new Constant(function.constants[i]);
19 | }
20 | extract = function.header.extractor;
21 | }
22 |
23 | public boolean isConstant(int register) {
24 | return extract.is_k(register);
25 | }
26 |
27 | public int constantIndex(int register) {
28 | return extract.get_k(register);
29 | }
30 |
31 | public ConstantExpression getGlobalName(int constantIndex) {
32 | if(!constants[constantIndex].isIdentifier(version)) throw new IllegalStateException();
33 | return getConstantExpression(constantIndex);
34 | }
35 |
36 | public ConstantExpression getConstantExpression(int constantIndex) {
37 | Constant constant = constants[constantIndex];
38 | return new ConstantExpression(constant, constant.isIdentifier(version), constantIndex);
39 | }
40 |
41 | public GlobalExpression getGlobalExpression(int constantIndex) {
42 | return new GlobalExpression(getGlobalName(constantIndex), constantIndex);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/unluac/decompile/OperandFormat.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | public enum OperandFormat {
4 | A(Field.A, Format.RAW),
5 | AR(Field.A, Format.REGISTER),
6 | AU(Field.A, Format.UPVALUE),
7 | B(Field.B, Format.RAW),
8 | BR(Field.B, Format.REGISTER),
9 | BRK(Field.B, Format.REGISTER_K),
10 | BK(Field.B, Format.CONSTANT),
11 | BKS(Field.B, Format.CONSTANT_STRING),
12 | BI(Field.B, Format.IMMEDIATE_INTEGER),
13 | BsI(Field.B, Format.IMMEDIATE_SIGNED_INTEGER),
14 | BU(Field.B, Format.UPVALUE),
15 | C(Field.C, Format.RAW),
16 | CR(Field.C, Format.REGISTER),
17 | CRK(Field.C, Format.REGISTER_K),
18 | CRK54(Field.C, Format.REGISTER_K54),
19 | CK(Field.C, Format.CONSTANT),
20 | CKI(Field.C, Format.CONSTANT_INTEGER),
21 | CKS(Field.C, Format.CONSTANT_STRING),
22 | CI(Field.C, Format.IMMEDIATE_INTEGER),
23 | CsI(Field.C, Format.IMMEDIATE_SIGNED_INTEGER),
24 | k(Field.k, Format.RAW),
25 | Ax(Field.Ax, Format.RAW),
26 | sJ(Field.sJ, Format.JUMP),
27 | Bx(Field.Bx, Format.RAW),
28 | BxK(Field.Bx, Format.CONSTANT),
29 | BxJ(Field.Bx, Format.JUMP),
30 | BxJ1(Field.Bx, Format.JUMP, 1),
31 | BxJn(Field.Bx, Format.JUMP_NEGATIVE),
32 | BxF(Field.Bx, Format.FUNCTION),
33 | sBxJ(Field.sBx, Format.JUMP),
34 | sBxI(Field.sBx, Format.IMMEDIATE_INTEGER),
35 | sBxF(Field.sBx, Format.IMMEDIATE_FLOAT),
36 | x(Field.x, Format.RAW);
37 |
38 | public final Field field;
39 | public final Format format;
40 | public final int offset;
41 |
42 | private OperandFormat(Field field, Format format) {
43 | this(field, format, 0);
44 | }
45 |
46 | private OperandFormat(Field field, Format format, int offset) {
47 | this.field = field;
48 | this.format = format;
49 | this.offset = offset;
50 | }
51 |
52 | public static enum Field {
53 | A,
54 | B,
55 | C,
56 | k,
57 | Ax,
58 | sJ,
59 | Bx,
60 | sBx,
61 | x,
62 | }
63 |
64 | public static enum Format {
65 | RAW,
66 | REGISTER,
67 | UPVALUE,
68 | REGISTER_K,
69 | REGISTER_K54,
70 | CONSTANT,
71 | CONSTANT_INTEGER,
72 | CONSTANT_STRING,
73 | FUNCTION,
74 | IMMEDIATE_INTEGER,
75 | IMMEDIATE_SIGNED_INTEGER,
76 | IMMEDIATE_FLOAT,
77 | JUMP,
78 | JUMP_NEGATIVE,
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/unluac/decompile/Output.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | public class Output {
4 |
5 | private OutputProvider out;
6 | private int indentationLevel = 0;
7 | private int position = 0;
8 |
9 | public Output() {
10 | this(new OutputProvider() {
11 |
12 | @Override
13 | public void print(String s) {
14 | System.out.print(s);
15 | }
16 |
17 | @Override
18 | public void print(byte b) {
19 | System.out.write(b);
20 | }
21 |
22 | @Override
23 | public void println() {
24 | System.out.println();
25 | }
26 |
27 | });
28 | }
29 |
30 | public Output(OutputProvider out) {
31 | this.out = out;
32 | }
33 |
34 | public void indent() {
35 | indentationLevel += 2;
36 | }
37 |
38 | public void dedent() {
39 | indentationLevel -= 2;
40 | }
41 |
42 | public int getIndentationLevel() {
43 | return indentationLevel;
44 | }
45 |
46 | public int getPosition() {
47 | return position;
48 | }
49 |
50 | public void setIndentationLevel(int indentationLevel) {
51 | this.indentationLevel = indentationLevel;
52 | }
53 |
54 | private void start() {
55 | if(position == 0) {
56 | for(int i = indentationLevel; i != 0; i--) {
57 | out.print(" ");
58 | position++;
59 | }
60 | }
61 | }
62 |
63 | public void print(String s) {
64 | start();
65 | out.print(s);
66 | position += s.length();
67 | }
68 |
69 | public void print(byte b) {
70 | start();
71 | out.print(b);
72 | position += 1;
73 | }
74 |
75 | public void println() {
76 | start();
77 | out.println();
78 | position = 0;
79 | }
80 |
81 | public void println(String s) {
82 | print(s);
83 | println();
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/unluac/decompile/OutputProvider.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | public interface OutputProvider {
4 |
5 | public void print(String s);
6 |
7 | public void print(byte b);
8 |
9 | public void println();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/unluac/decompile/Upvalues.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | import unluac.decompile.expression.UpvalueExpression;
4 | import unluac.parse.LFunction;
5 | import unluac.parse.LUpvalue;
6 |
7 | public class Upvalues {
8 |
9 | private final LUpvalue[] upvalues;
10 |
11 | public Upvalues(LFunction func, Declaration[] parentDecls, int line) {
12 | this.upvalues = func.upvalues;
13 | for(LUpvalue upvalue : upvalues) {
14 | if(upvalue.name == null || upvalue.name.isEmpty()) {
15 | if(upvalue.instack) {
16 | if(parentDecls != null) {
17 | for(Declaration decl : parentDecls) {
18 | if(decl.register == upvalue.idx && line >= decl.begin && line < decl.end) {
19 | upvalue.name = decl.name;
20 | break;
21 | }
22 | }
23 | }
24 | } else {
25 | LUpvalue[] parentvals = func.parent.upvalues;
26 | if(upvalue.idx >= 0 && upvalue.idx < parentvals.length) {
27 | upvalue.name = parentvals[upvalue.idx].name;
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
34 | public String getName(int index) {
35 | if(index < upvalues.length && upvalues[index].name != null && !upvalues[index].name.isEmpty()) {
36 | return upvalues[index].name;
37 | } else {
38 | //TODO: SET ERROR
39 | return "_UPVALUE" + index + "_";
40 | }
41 | }
42 |
43 | public UpvalueExpression getExpression(int index) {
44 | return new UpvalueExpression(getName(index));
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/unluac/decompile/Validator.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | public class Validator {
4 |
5 | public static void process(Decompiler d) {
6 | Code code = d.code;
7 | for(int line = 1; line <= code.length; line++) {
8 | switch(code.op(line)) {
9 | case EQ: {
10 | /* TODO
11 | AssertionManager.assertCritical(
12 | line + 1 <= code.length && code.isJMP(line + 1),
13 | "ByteCode validation failed; EQ instruction is not followed by JMP"
14 | );
15 | break;*/
16 | }
17 | case LT: {
18 | break;
19 | }
20 | default:
21 | break;
22 | }
23 | }
24 | }
25 |
26 | //static only
27 | private Validator() {}
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/unluac/decompile/Walker.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile;
2 |
3 | import unluac.decompile.expression.Expression;
4 | import unluac.decompile.statement.Statement;
5 |
6 | public class Walker {
7 |
8 | public void visitStatement(Statement stmt) {
9 |
10 | }
11 |
12 | public void visitExpression(Expression expr) {
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/AlwaysLoop.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Function;
5 | import unluac.decompile.Output;
6 | import unluac.decompile.expression.ConstantExpression;
7 | import unluac.decompile.statement.Statement;
8 | import unluac.parse.LFunction;
9 |
10 | public class AlwaysLoop extends ContainerBlock {
11 |
12 | private final boolean repeat;
13 |
14 | private ConstantExpression condition;
15 |
16 | public AlwaysLoop(LFunction function, int begin, int end, boolean repeat) {
17 | super(function, begin, end, 0);
18 | this.repeat = repeat;
19 | condition = null;
20 | }
21 |
22 | @Override
23 | public int scopeEnd() {
24 | return end - 2;
25 | }
26 |
27 | @Override
28 | public boolean breakable() {
29 | return true;
30 | }
31 |
32 | @Override
33 | public boolean isUnprotected() {
34 | return true;
35 | }
36 |
37 | @Override
38 | public int getUnprotectedTarget() {
39 | return begin;
40 | }
41 |
42 | @Override
43 | public int getUnprotectedLine() {
44 | return end - 1;
45 | }
46 |
47 | @Override
48 | public int getLoopback() {
49 | return begin;
50 | }
51 |
52 | @Override
53 | public void print(Decompiler d, Output out) {
54 | if(repeat) {
55 | out.println("repeat");
56 | } else {
57 | out.print("while ");
58 | if(condition == null) {
59 | out.print("true");
60 | } else {
61 | condition.print(d, out);
62 | }
63 | out.println(" do");
64 | }
65 | out.indent();
66 | Statement.printSequence(d, out, statements);
67 | out.dedent();
68 | if(repeat) {
69 | out.print("until false");
70 | } else {
71 | out.print("end");
72 | }
73 | }
74 |
75 | @Override
76 | public boolean useConstant(Function f, int index) {
77 | if(!repeat && condition == null) {
78 | condition = f.getConstantExpression(index);
79 | return true;
80 | } else {
81 | return false;
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/src/unluac/decompile/block/Block.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Registers;
5 | import unluac.decompile.operation.Operation;
6 | import unluac.decompile.statement.Statement;
7 | import unluac.parse.LFunction;
8 |
9 | abstract public class Block extends Statement implements Comparable {
10 |
11 | protected final LFunction function;
12 | public int begin;
13 | public int end;
14 | private final int priority;
15 | public boolean loopRedirectAdjustment = false;
16 | protected boolean scopeUsed = false;
17 |
18 | public Block(LFunction function, int begin, int end, int priority) {
19 | this.function = function;
20 | this.begin = begin;
21 | this.end = end;
22 | this.priority = priority;
23 | }
24 |
25 | abstract public void addStatement(Statement statement);
26 |
27 | public void resolve(Registers r) {}
28 |
29 | public boolean contains(Block block) {
30 | return begin <= block.begin && end >= block.end;
31 | }
32 |
33 | public boolean contains(int line) {
34 | return begin <= line && line < end;
35 | }
36 |
37 | public int scopeEnd() {
38 | return end - 1;
39 | }
40 |
41 | public void useScope() {
42 | scopeUsed = true;
43 | }
44 |
45 | /**
46 | * An unprotected block is one that ends in a JMP instruction.
47 | * If this is the case, any inner statement that tries to jump
48 | * to the end of this block will be redirected.
49 | *
50 | * (One of the Lua compiler's few optimizations is that is changes
51 | * any JMP that targets another JMP to the ultimate target. This
52 | * is what I call redirection.)
53 | */
54 | abstract public boolean isUnprotected();
55 |
56 | public int getUnprotectedTarget() {
57 | throw new IllegalStateException(this.toString());
58 | }
59 |
60 | public int getUnprotectedLine() {
61 | throw new IllegalStateException(this.toString());
62 | }
63 |
64 | abstract public int getLoopback();
65 |
66 | abstract public boolean breakable();
67 |
68 | abstract public boolean isContainer();
69 |
70 | abstract public boolean isEmpty();
71 |
72 | public boolean allowsPreDeclare() {
73 | return false;
74 | }
75 |
76 | public boolean isSplitable() {
77 | return false;
78 | }
79 |
80 | public Block[] split(int line) {
81 | throw new IllegalStateException();
82 | }
83 |
84 | @Override
85 | public int compareTo(Block block) {
86 | if(this.begin < block.begin) {
87 | return -1;
88 | } else if(this.begin == block.begin) {
89 | if(this.end < block.end) {
90 | return 1;
91 | } else if(this.end == block.end) {
92 | return this.priority - block.priority;
93 | } else {
94 | return -1;
95 | }
96 | } else {
97 | return 1;
98 | }
99 | }
100 |
101 | public Operation process(Decompiler d) {
102 | final Statement statement = this;
103 | return new Operation(end - 1) {
104 |
105 | @Override
106 | public Statement process(Registers r, Block block) {
107 | return statement;
108 | }
109 |
110 | };
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/Break.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 | import unluac.decompile.statement.Statement;
7 | import unluac.parse.LFunction;
8 |
9 | public class Break extends Block {
10 |
11 | public final int target;
12 | public String comment;
13 |
14 | public Break(LFunction function, int line, int target) {
15 | super(function, line, line, 2);
16 | this.target = target;
17 | }
18 |
19 | @Override
20 | public void walk(Walker w) {
21 | w.visitStatement(this);
22 | }
23 |
24 | @Override
25 | public void addStatement(Statement statement) {
26 | throw new IllegalStateException();
27 | }
28 |
29 | @Override
30 | public boolean isContainer() {
31 | return false;
32 | }
33 |
34 | @Override
35 | public boolean isEmpty() {
36 | return true;
37 | }
38 |
39 | @Override
40 | public boolean breakable() {
41 | return false;
42 | }
43 |
44 | @Override
45 | public boolean isUnprotected() {
46 | //Actually, it is unprotected, but not really a block
47 | return false;
48 | }
49 |
50 | @Override
51 | public int getLoopback() {
52 | throw new IllegalStateException();
53 | }
54 |
55 | @Override
56 | public void print(Decompiler d, Output out) {
57 | out.print("do break end");
58 | if(comment != null) out.print(" -- " + comment);
59 | }
60 |
61 | @Override
62 | public void printTail(Decompiler d, Output out) {
63 | out.print("break");
64 | if(comment != null) out.print(" -- " + comment);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/ContainerBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import unluac.decompile.Walker;
7 | import unluac.decompile.statement.Statement;
8 | import unluac.parse.LFunction;
9 |
10 | abstract public class ContainerBlock extends Block {
11 |
12 | protected final List statements;
13 |
14 | public ContainerBlock(LFunction function, int begin, int end, int priority) {
15 | super(function, begin, end, priority);
16 | statements = new ArrayList(Math.max(4, end - begin + 1));
17 | }
18 |
19 | @Override
20 | public void walk(Walker w) {
21 | w.visitStatement(this);
22 | for(Statement statement : statements) {
23 | statement.walk(w);
24 | }
25 | }
26 |
27 | @Override
28 | public boolean isContainer() {
29 | return begin < end;
30 | }
31 |
32 | @Override
33 | public boolean isEmpty() {
34 | return statements.isEmpty();
35 | }
36 |
37 | @Override
38 | public void addStatement(Statement statement) {
39 | statements.add(statement);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/DoEndBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.statement.Statement;
6 | import unluac.parse.LFunction;
7 |
8 | public class DoEndBlock extends ContainerBlock {
9 |
10 | public DoEndBlock(LFunction function, int begin, int end) {
11 | super(function, begin, end, 1);
12 | }
13 |
14 | @Override
15 | public boolean breakable() {
16 | return false;
17 | }
18 |
19 | @Override
20 | public boolean isUnprotected() {
21 | return false;
22 | }
23 |
24 | public boolean allowsPreDeclare() {
25 | return true;
26 | }
27 |
28 | @Override
29 | public int getLoopback() {
30 | throw new IllegalStateException();
31 | }
32 |
33 | @Override
34 | public void print(Decompiler d, Output out) {
35 | out.println("do");
36 | out.indent();
37 | Statement.printSequence(d, out, statements);
38 | out.dedent();
39 | out.print("end");
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/ElseEndBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.statement.Statement;
6 | import unluac.parse.LFunction;
7 |
8 | public class ElseEndBlock extends ContainerBlock {
9 |
10 | public IfThenElseBlock partner;
11 |
12 | public ElseEndBlock(LFunction function, int begin, int end) {
13 | super(function, begin, end, -1);
14 | }
15 |
16 | @Override
17 | public int compareTo(Block block) {
18 | if(block == partner) {
19 | return 1;
20 | } else {
21 | int result = super.compareTo(block);
22 | return result;
23 | }
24 | }
25 |
26 | @Override
27 | public boolean breakable() {
28 | return false;
29 | }
30 |
31 | @Override
32 | public boolean isUnprotected() {
33 | return false;
34 | }
35 |
36 | @Override
37 | public int getLoopback() {
38 | throw new IllegalStateException();
39 | }
40 |
41 | @Override
42 | public void print(Decompiler d, Output out) {
43 | if(statements.size() == 1 && statements.get(0) instanceof IfThenEndBlock) {
44 | out.print("else");
45 | statements.get(0).print(d, out);
46 | } else if(statements.size() == 2 && statements.get(0) instanceof IfThenElseBlock && statements.get(1) instanceof ElseEndBlock) {
47 | out.print("else");
48 | statements.get(0).print(d, out);
49 | statements.get(1).print(d, out);
50 | } else {
51 | out.print("else");
52 | out.println();
53 | out.indent();
54 | Statement.printSequence(d, out, statements);
55 | out.dedent();
56 | out.print("end");
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/ForBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Registers;
6 | import unluac.decompile.Walker;
7 | import unluac.decompile.expression.Expression;
8 | import unluac.decompile.statement.Statement;
9 | import unluac.decompile.target.Target;
10 | import unluac.parse.LFunction;
11 |
12 | abstract public class ForBlock extends ContainerBlock {
13 |
14 | protected final int register;
15 | protected final boolean forvarClose;
16 | protected final boolean innerClose;
17 |
18 | protected Target target;
19 | protected Expression start;
20 | protected Expression stop;
21 | protected Expression step;
22 |
23 | public ForBlock(LFunction function, int begin, int end, int register, boolean forvarClose, boolean innerClose) {
24 | super(function, begin, end, -1);
25 | this.register = register;
26 | this.forvarClose = forvarClose;
27 | this.innerClose = innerClose;
28 | }
29 |
30 | abstract public void handleVariableDeclarations(Registers r);
31 |
32 | @Override
33 | public void walk(Walker w) {
34 | w.visitStatement(this);
35 | start.walk(w);
36 | stop.walk(w);
37 | step.walk(w);
38 | for(Statement statement : statements) {
39 | statement.walk(w);
40 | }
41 | }
42 |
43 | @Override
44 | public int scopeEnd() {
45 | int scopeEnd = end - 2;
46 | if(forvarClose) scopeEnd--;
47 | if(innerClose) scopeEnd--;
48 | return scopeEnd;
49 | }
50 |
51 | @Override
52 | public boolean breakable() {
53 | return true;
54 | }
55 |
56 | @Override
57 | public boolean isUnprotected() {
58 | return false;
59 | }
60 |
61 | @Override
62 | public int getLoopback() {
63 | throw new IllegalStateException();
64 | }
65 |
66 | @Override
67 | public void print(Decompiler d, Output out) {
68 | out.print("for ");
69 | target.print(d, out, false);
70 | out.print(" = ");
71 | start.print(d, out);
72 | out.print(", ");
73 | stop.print(d, out);
74 | if(!step.isInteger() || step.asInteger() != 1) {
75 | out.print(", ");
76 | step.print(d, out);
77 | }
78 | out.print(" do");
79 | out.println();
80 | out.indent();
81 | Statement.printSequence(d, out, statements);
82 | out.dedent();
83 | out.print("end");
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/ForBlock50.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.parse.LFunction;
5 |
6 | public class ForBlock50 extends ForBlock {
7 |
8 | public ForBlock50(LFunction function, int begin, int end, int register, boolean innerClose) {
9 | super(function, begin, end, register, false, innerClose);
10 | }
11 |
12 | @Override
13 | public void resolve(Registers r) {
14 | target = r.getTarget(register, begin - 1);
15 | start = r.getValue(register, begin - 2);
16 | stop = r.getValue(register + 1, begin - 1);
17 | step = r.getValue(register + 2, begin - 1);
18 | }
19 |
20 | @Override
21 | public void handleVariableDeclarations(Registers r) {
22 | r.setExplicitLoopVariable(register, begin - 1, end - 1);
23 | r.setInternalLoopVariable(register + 1, begin - 1, end - 1);
24 | r.setInternalLoopVariable(register + 2, begin - 1, end - 1);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/ForBlock51.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.parse.LFunction;
5 |
6 | public class ForBlock51 extends ForBlock {
7 |
8 | public ForBlock51(LFunction function, int begin, int end, int register, boolean forvarClose, boolean innerClose) {
9 | super(function, begin, end, register, forvarClose, innerClose);
10 | }
11 |
12 | @Override
13 | public void resolve(Registers r) {
14 | target = r.getTarget(register + 3, begin - 1);
15 | start = r.getValue(register, begin - 1);
16 | stop = r.getValue(register + 1, begin - 1);
17 | step = r.getValue(register + 2, begin - 1);
18 | }
19 |
20 | @Override
21 | public void handleVariableDeclarations(Registers r) {
22 | r.setInternalLoopVariable(register, begin - 2, end - 1);
23 | r.setInternalLoopVariable(register + 1, begin - 2, end - 1);
24 | r.setInternalLoopVariable(register + 2, begin - 2, end - 1);
25 | int explicitEnd = end - 2;
26 | if(forvarClose) explicitEnd--;
27 | r.setExplicitLoopVariable(register + 3, begin - 1, explicitEnd);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/Goto.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 | import unluac.decompile.statement.Statement;
7 | import unluac.parse.LFunction;
8 |
9 | public class Goto extends Block {
10 |
11 | public final int target;
12 |
13 | public Goto(LFunction function, int line, int target) {
14 | super(function, line, line, 2);
15 | this.target = target;
16 | }
17 |
18 | @Override
19 | public void walk(Walker w) {
20 | w.visitStatement(this);
21 | }
22 |
23 | @Override
24 | public void addStatement(Statement statement) {
25 | throw new IllegalStateException();
26 | }
27 |
28 | @Override
29 | public boolean isContainer() {
30 | return false;
31 | }
32 |
33 | @Override
34 | public boolean isEmpty() {
35 | return true;
36 | }
37 |
38 | @Override
39 | public boolean breakable() {
40 | return false;
41 | }
42 |
43 | @Override
44 | public boolean isUnprotected() {
45 | //Actually, it is unprotected, but not really a block
46 | return false;
47 | }
48 |
49 | @Override
50 | public int getLoopback() {
51 | throw new IllegalStateException();
52 | }
53 |
54 | @Override
55 | public void print(Decompiler d, Output out) {
56 | out.print("goto lbl_" + target);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/IfThenElseBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Registers;
6 | import unluac.decompile.Walker;
7 | import unluac.decompile.condition.Condition;
8 | import unluac.decompile.expression.Expression;
9 | import unluac.decompile.statement.Statement;
10 | import unluac.parse.LFunction;
11 |
12 | public class IfThenElseBlock extends ContainerBlock {
13 |
14 | private final Condition cond;
15 | private final int elseTarget;
16 | public ElseEndBlock partner;
17 |
18 | private Expression condexpr;
19 |
20 | public IfThenElseBlock(LFunction function, Condition cond, int begin, int end, int elseTarget) {
21 | super(function, begin, end, -1);
22 | this.cond = cond;
23 | this.elseTarget = elseTarget;
24 | }
25 |
26 | @Override
27 | public void resolve(Registers r) {
28 | condexpr = cond.asExpression(r);
29 | }
30 |
31 | @Override
32 | public void walk(Walker w) {
33 | w.visitStatement(this);
34 | condexpr.walk(w);
35 | for(Statement statement : statements) {
36 | statement.walk(w);
37 | }
38 | }
39 |
40 | @Override
41 | public boolean suppressNewline() {
42 | return true;
43 | }
44 |
45 | @Override
46 | public int compareTo(Block block) {
47 | if(block == partner) {
48 | return -1;
49 | } else {
50 | return super.compareTo(block);
51 | }
52 | }
53 |
54 | @Override
55 | public boolean breakable() {
56 | return false;
57 | }
58 |
59 | @Override
60 | public int scopeEnd() {
61 | return end - 2;
62 | }
63 |
64 | @Override
65 | public boolean isUnprotected() {
66 | return true;
67 | }
68 |
69 | @Override
70 | public int getUnprotectedLine() {
71 | return end - 1;
72 | }
73 |
74 | @Override
75 | public int getUnprotectedTarget() {
76 | return elseTarget;
77 | }
78 |
79 | @Override
80 | public int getLoopback() {
81 | throw new IllegalStateException();
82 | }
83 |
84 | @Override
85 | public void print(Decompiler d, Output out) {
86 | out.print("if ");
87 | condexpr.print(d, out);
88 | out.print(" then");
89 | out.println();
90 | out.indent();
91 |
92 | Statement.printSequence(d, out, statements);
93 |
94 | out.dedent();
95 |
96 | // Handle the "empty else" case
97 | if(end == elseTarget) {
98 | out.println("else");
99 | out.println("end");
100 | }
101 |
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/OnceLoop.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.statement.Statement;
6 | import unluac.parse.LFunction;
7 |
8 | public class OnceLoop extends ContainerBlock {
9 |
10 | public OnceLoop(LFunction function, int begin, int end) {
11 | super(function, begin, end, 0);
12 | }
13 |
14 | @Override
15 | public int scopeEnd() {
16 | return end - 1;
17 | }
18 |
19 | @Override
20 | public boolean breakable() {
21 | return true;
22 | }
23 |
24 | @Override
25 | public boolean isUnprotected() {
26 | return false;
27 | }
28 |
29 | @Override
30 | public int getLoopback() {
31 | return begin;
32 | }
33 |
34 | @Override
35 | public void print(Decompiler d, Output out) {
36 | out.println("repeat");
37 | out.indent();
38 | Statement.printSequence(d, out, statements);
39 | out.dedent();
40 | out.print("until true");
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/OuterBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.statement.Return;
6 | import unluac.decompile.statement.Statement;
7 | import unluac.parse.LFunction;
8 |
9 | public class OuterBlock extends ContainerBlock {
10 |
11 | public OuterBlock(LFunction function, int length) {
12 | super(function, 0, length + 1, -2);
13 | }
14 |
15 | @Override
16 | public boolean breakable() {
17 | return false;
18 | }
19 |
20 | @Override
21 | public boolean isUnprotected() {
22 | return false;
23 | }
24 |
25 | @Override
26 | public int getLoopback() {
27 | throw new IllegalStateException();
28 | }
29 |
30 | @Override
31 | public int scopeEnd() {
32 | return (end - 1) + function.header.version.outerblockscopeadjustment.get();
33 | }
34 |
35 | @Override
36 | public void print(Decompiler d, Output out) {
37 | /* extra return statement */
38 | int last = statements.size() - 1;
39 | if(last < 0 || !(statements.get(last) instanceof Return)) {
40 | throw new IllegalStateException(statements.get(last).toString());
41 | }
42 | statements.remove(last);
43 | Statement.printSequence(d, out, statements);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/RepeatBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Registers;
6 | import unluac.decompile.Walker;
7 | import unluac.decompile.condition.Condition;
8 | import unluac.decompile.expression.Expression;
9 | import unluac.decompile.statement.Statement;
10 | import unluac.parse.LFunction;
11 |
12 | public class RepeatBlock extends ContainerBlock {
13 |
14 | private final Condition cond;
15 | private final int scopeEnd;
16 |
17 | private Expression condexpr;
18 |
19 | public RepeatBlock(LFunction function, Condition cond, int begin, int end) {
20 | this(function, cond, begin, end, end - 1);
21 | }
22 |
23 | public RepeatBlock(LFunction function, Condition cond, int begin, int end, int scopeEnd) {
24 | super(function, begin, end, 0);
25 | this.cond = cond;
26 | this.scopeEnd = scopeEnd;
27 | }
28 |
29 | @Override
30 | public void resolve(Registers r) {
31 | condexpr = cond.asExpression(r);
32 | }
33 |
34 | @Override
35 | public void walk(Walker w) {
36 | w.visitStatement(this);
37 | for(Statement statement : statements) {
38 | statement.walk(w);
39 | }
40 | condexpr.walk(w);
41 | }
42 |
43 | @Override
44 | public int scopeEnd() {
45 | return scopeEnd;
46 | }
47 |
48 | @Override
49 | public boolean breakable() {
50 | return true;
51 | }
52 |
53 | @Override
54 | public boolean isUnprotected() {
55 | return false;
56 | }
57 |
58 | @Override
59 | public int getLoopback() {
60 | throw new IllegalStateException();
61 | }
62 |
63 | @Override
64 | public void print(Decompiler d, Output out) {
65 | out.print("repeat");
66 | out.println();
67 | out.indent();
68 | Statement.printSequence(d, out, statements);
69 | out.dedent();
70 | out.print("until ");
71 | condexpr.print(d, out);
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/unluac/decompile/block/WhileBlock.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.block;
2 |
3 | import unluac.Version;
4 | import unluac.decompile.Decompiler;
5 | import unluac.decompile.Output;
6 | import unluac.decompile.Registers;
7 | import unluac.decompile.Walker;
8 | import unluac.decompile.condition.Condition;
9 | import unluac.decompile.expression.Expression;
10 | import unluac.decompile.statement.Statement;
11 | import unluac.parse.LFunction;
12 |
13 | public class WhileBlock extends ContainerBlock {
14 |
15 | private Condition cond;
16 | private final int unprotectedTarget;
17 | private final boolean splitable;
18 |
19 | private Expression condexpr;
20 |
21 | public WhileBlock(LFunction function, Condition cond, int begin, int end, int unprotectedTarget) {
22 | super(function, begin, end, -1);
23 | this.cond = cond;
24 | this.unprotectedTarget = unprotectedTarget;
25 | this.splitable = (function.header.version.whileformat.get() == Version.WhileFormat.TOP_CONDITION);
26 | }
27 |
28 | @Override
29 | public void resolve(Registers r) {
30 | condexpr = cond.asExpression(r);
31 | }
32 |
33 | @Override
34 | public void walk(Walker w) {
35 | w.visitStatement(this);
36 | condexpr.walk(w);
37 | for(Statement statement : statements) {
38 | statement.walk(w);
39 | }
40 | }
41 |
42 | @Override
43 | public int scopeEnd() {
44 | return end - 2;
45 | }
46 |
47 | @Override
48 | public boolean breakable() {
49 | return true;
50 | }
51 |
52 | @Override
53 | public boolean isUnprotected() {
54 | return unprotectedTarget != -1;
55 | }
56 |
57 | @Override
58 | public int getUnprotectedLine() {
59 | if(unprotectedTarget == -1) {
60 | throw new IllegalStateException();
61 | }
62 | return end - 1;
63 | }
64 |
65 | @Override
66 | public int getUnprotectedTarget() {
67 | if(unprotectedTarget == -1) {
68 | throw new IllegalStateException();
69 | }
70 | return unprotectedTarget;
71 | };
72 |
73 | @Override
74 | public int getLoopback() {
75 | throw new IllegalStateException();
76 | }
77 |
78 | @Override
79 | public boolean isSplitable() {
80 | return splitable && cond.isSplitable();
81 | }
82 |
83 | @Override
84 | public Block[] split(int line) {
85 | Condition[] conds = cond.split();
86 | cond = conds[0];
87 | return new Block[] {
88 | new IfThenElseBlock(function, conds[1], begin, line + 1, end - 1),
89 | new ElseEndBlock(function, line + 1, end - 1),
90 | };
91 | }
92 |
93 | @Override
94 | public void print(Decompiler d, Output out) {
95 | out.print("while ");
96 | condexpr.print(d, out);
97 | out.print(" do");
98 | out.println();
99 | out.indent();
100 | Statement.printSequence(d, out, statements);
101 | out.dedent();
102 | out.print("end");
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/AndCondition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.BinaryExpression;
5 | import unluac.decompile.expression.Expression;
6 |
7 | public class AndCondition implements Condition {
8 |
9 | private Condition left;
10 | private Condition right;
11 |
12 | public AndCondition(Condition left, Condition right) {
13 | this.left = left;
14 | this.right = right;
15 | }
16 |
17 | @Override
18 | public Condition inverse() {
19 | if(invertible()) {
20 | return new OrCondition(left.inverse(), right.inverse());
21 | } else {
22 | return new NotCondition(this);
23 | }
24 | }
25 |
26 | @Override
27 | public boolean invertible() {
28 | return right.invertible();
29 | }
30 |
31 | @Override
32 | public int register() {
33 | return right.register();
34 | }
35 |
36 | @Override
37 | public boolean isRegisterTest() {
38 | return false;
39 | }
40 |
41 | @Override
42 | public boolean isOrCondition() {
43 | return false;
44 | }
45 |
46 | @Override
47 | public boolean isSplitable() {
48 | return true;
49 | }
50 |
51 | @Override
52 | public Condition[] split() {
53 | return new Condition[] {left, right};
54 | }
55 |
56 | @Override
57 | public Expression asExpression(Registers r) {
58 | return new BinaryExpression("and", left.asExpression(r), right.asExpression(r), Expression.PRECEDENCE_AND, Expression.ASSOCIATIVITY_NONE);
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return left + " and " + right;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/Condition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.ConstantExpression;
5 | import unluac.decompile.expression.Expression;
6 |
7 | public interface Condition {
8 |
9 | public static enum OperandType {
10 | R,
11 | RK,
12 | K,
13 | I,
14 | F,
15 | }
16 |
17 | public static class Operand {
18 |
19 | public Operand(OperandType type, int value) {
20 | this.type = type;
21 | this.value = value;
22 | }
23 |
24 | public Expression asExpression(Registers r, int line) {
25 | switch(type) {
26 | case R: return r.getExpression(this.value, line);
27 | case RK: return r.getKExpression(this.value, line);
28 | case K: return r.getFunction().getConstantExpression(this.value);
29 | case I: return ConstantExpression.createInteger(this.value);
30 | case F: return ConstantExpression.createDouble((double) this.value);
31 | default: throw new IllegalStateException();
32 | }
33 | }
34 |
35 | public boolean isRegister(Registers r) {
36 | switch(type) {
37 | case R: return true;
38 | case RK: return !r.isKConstant(this.value);
39 | case K: return false;
40 | case I: return false;
41 | case F: return false;
42 | default: throw new IllegalStateException();
43 | }
44 | }
45 |
46 | public int getUpdated(Registers r, int line) {
47 | switch(type) {
48 | case R: return r.getUpdated(this.value, line);
49 | case RK:
50 | if(r.isKConstant(this.value)) throw new IllegalStateException();
51 | return r.getUpdated(this.value, line);
52 | default: throw new IllegalStateException();
53 | }
54 | }
55 |
56 | public final OperandType type;
57 | public final int value;
58 |
59 | }
60 |
61 | public Condition inverse();
62 |
63 | public boolean invertible();
64 |
65 | public int register();
66 |
67 | public boolean isRegisterTest();
68 |
69 | public boolean isOrCondition();
70 |
71 | public boolean isSplitable();
72 |
73 | public Condition[] split();
74 |
75 | public Expression asExpression(Registers r);
76 |
77 | @Override
78 | public String toString();
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/ConstantCondition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.ConstantExpression;
5 | import unluac.decompile.expression.Expression;
6 |
7 | public class ConstantCondition implements Condition {
8 |
9 | private int register;
10 | private boolean value;
11 |
12 | public ConstantCondition(int register, boolean value) {
13 | this.register = register;
14 | this.value = value;
15 | }
16 |
17 | @Override
18 | public Condition inverse() {
19 | return new ConstantCondition(register, !value);
20 | }
21 |
22 | @Override
23 | public boolean invertible() {
24 | return true;
25 | }
26 |
27 | @Override
28 | public int register() {
29 | return register;
30 | }
31 |
32 | @Override
33 | public boolean isRegisterTest() {
34 | return false;
35 | }
36 |
37 | @Override
38 | public boolean isOrCondition() {
39 | return false;
40 | }
41 |
42 | @Override
43 | public boolean isSplitable() {
44 | return false;
45 | }
46 |
47 | @Override
48 | public Condition[] split() {
49 | throw new IllegalStateException();
50 | }
51 |
52 | @Override
53 | public Expression asExpression(Registers r) {
54 | return ConstantExpression.createBoolean(value);
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/FinalSetCondition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.ConstantExpression;
5 | import unluac.decompile.expression.Expression;
6 |
7 | public class FinalSetCondition implements Condition {
8 |
9 | public static enum Type {
10 | NONE,
11 | REGISTER,
12 | VALUE,
13 | }
14 |
15 | public int line;
16 | private int register;
17 | public Type type;
18 |
19 | public FinalSetCondition(int line, int register) {
20 | this.line = line;
21 | this.register = register;
22 | this.type = Type.NONE;
23 | if(register < 0) {
24 | throw new IllegalStateException();
25 | }
26 | }
27 |
28 | @Override
29 | public Condition inverse() {
30 | return new NotCondition(this);
31 | }
32 |
33 | @Override
34 | public boolean invertible() {
35 | return false;
36 | }
37 |
38 | @Override
39 | public int register() {
40 | return register;
41 | }
42 |
43 | @Override
44 | public boolean isRegisterTest() {
45 | return false;
46 | }
47 |
48 | @Override
49 | public boolean isOrCondition() {
50 | return false;
51 | }
52 |
53 | @Override
54 | public boolean isSplitable() {
55 | return false;
56 | }
57 |
58 | @Override
59 | public Condition[] split() {
60 | throw new IllegalStateException();
61 | }
62 |
63 | @Override
64 | public Expression asExpression(Registers r) {
65 | Expression expr;
66 | switch(type) {
67 | case REGISTER:
68 | expr = r.getExpression(register, line + 1);
69 | break;
70 | case VALUE:
71 | expr = r.getValue(register, line + 1);
72 | break;
73 | case NONE:
74 | default:
75 | expr = ConstantExpression.createDouble(register + ((double)line) / 100.0);
76 | break;
77 | }
78 | if(expr == null) {
79 | throw new IllegalStateException();
80 | }
81 | return expr;
82 | }
83 |
84 | @Override
85 | public String toString() {
86 | return "(" + register + ")";
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/NotCondition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.Expression;
5 | import unluac.decompile.expression.UnaryExpression;
6 |
7 | public class NotCondition implements Condition {
8 |
9 | private Condition cond;
10 |
11 | public NotCondition(Condition cond) {
12 | this.cond = cond;
13 | }
14 |
15 | @Override
16 | public Condition inverse() {
17 | return cond;
18 | }
19 |
20 | @Override
21 | public boolean invertible() {
22 | return true;
23 | }
24 |
25 | @Override
26 | public int register() {
27 | return cond.register();
28 | }
29 |
30 | @Override
31 | public boolean isRegisterTest() {
32 | return cond.isRegisterTest();
33 | }
34 |
35 | @Override
36 | public boolean isOrCondition() {
37 | return false;
38 | }
39 |
40 | @Override
41 | public boolean isSplitable() {
42 | return false;
43 | }
44 |
45 | @Override
46 | public Condition[] split() {
47 | throw new IllegalStateException();
48 | }
49 |
50 | @Override
51 | public Expression asExpression(Registers r) {
52 | return new UnaryExpression("not ", cond.asExpression(r), Expression.PRECEDENCE_UNARY);
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return "not (" + cond + ")";
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/OrCondition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.BinaryExpression;
5 | import unluac.decompile.expression.Expression;
6 |
7 | public class OrCondition implements Condition {
8 |
9 | private Condition left;
10 | private Condition right;
11 |
12 | public OrCondition(Condition left, Condition right) {
13 | this.left = left;
14 | this.right = right;
15 | }
16 |
17 | @Override
18 | public Condition inverse() {
19 | if(invertible()) {
20 | return new AndCondition(left.inverse(), right.inverse());
21 | } else {
22 | return new NotCondition(this);
23 | }
24 | }
25 |
26 | @Override
27 | public boolean invertible() {
28 | return right.invertible();
29 | }
30 |
31 | @Override
32 | public int register() {
33 | return right.register();
34 | }
35 |
36 | @Override
37 | public boolean isRegisterTest() {
38 | return false;
39 | }
40 |
41 | @Override
42 | public boolean isOrCondition() {
43 | return true;
44 | }
45 |
46 | @Override
47 | public boolean isSplitable() {
48 | return false;
49 | }
50 |
51 | @Override
52 | public Condition[] split() {
53 | throw new IllegalStateException();
54 | }
55 |
56 | @Override
57 | public Expression asExpression(Registers r) {
58 | return new BinaryExpression("or", left.asExpression(r), right.asExpression(r), Expression.PRECEDENCE_OR, Expression.ASSOCIATIVITY_NONE);
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return "(" + left + " or " + right + ")";
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/unluac/decompile/condition/TestCondition.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.condition;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.expression.Expression;
5 |
6 | public class TestCondition implements Condition {
7 |
8 | private int line;
9 | private int register;
10 |
11 | public TestCondition(int line, int register) {
12 | this.line = line;
13 | this.register = register;
14 | }
15 |
16 | @Override
17 | public Condition inverse() {
18 | return new NotCondition(this);
19 | }
20 |
21 | @Override
22 | public boolean invertible() {
23 | return false;
24 | }
25 |
26 | @Override
27 | public int register() {
28 | return register;
29 | }
30 |
31 | @Override
32 | public boolean isRegisterTest() {
33 | return true;
34 | }
35 |
36 | @Override
37 | public boolean isOrCondition() {
38 | return false;
39 | }
40 |
41 | @Override
42 | public boolean isSplitable() {
43 | return false;
44 | }
45 |
46 | @Override
47 | public Condition[] split() {
48 | throw new IllegalStateException();
49 | }
50 |
51 | @Override
52 | public Expression asExpression(Registers r) {
53 | return r.getExpression(register, line);
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | return "(" + register + ")";
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/BinaryExpression.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class BinaryExpression extends Expression {
8 |
9 | private final String op;
10 | private final Expression left;
11 | private final Expression right;
12 | private final int associativity;
13 |
14 | public static BinaryExpression replaceRight(BinaryExpression template, Expression replacement) {
15 | return new BinaryExpression(template.op, template.left, replacement, template.precedence, template.associativity);
16 | }
17 |
18 | public BinaryExpression(String op, Expression left, Expression right, int precedence, int associativity) {
19 | super(precedence);
20 | this.op = op;
21 | this.left = left;
22 | this.right = right;
23 | this.associativity = associativity;
24 | }
25 |
26 | @Override
27 | public void walk(Walker w) {
28 | w.visitExpression(this);
29 | left.walk(w);
30 | right.walk(w);
31 | }
32 |
33 | @Override
34 | public boolean isUngrouped() {
35 | return !beginsWithParen();
36 | }
37 |
38 | @Override
39 | public int getConstantIndex() {
40 | return Math.max(left.getConstantIndex(), right.getConstantIndex());
41 | }
42 |
43 | @Override
44 | public boolean beginsWithParen() {
45 | return leftGroup() || left.beginsWithParen();
46 | }
47 |
48 | @Override
49 | public void print(Decompiler d, Output out) {
50 | final boolean leftGroup = leftGroup();
51 | final boolean rightGroup = rightGroup();
52 | if(leftGroup) out.print("(");
53 | left.print(d, out);
54 | if(leftGroup) out.print(")");
55 | out.print(" ");
56 | out.print(op);
57 | out.print(" ");
58 | if(rightGroup) out.print("(");
59 | right.print(d, out);
60 | if(rightGroup) out.print(")");
61 | }
62 |
63 | public String getOp() {
64 | return op;
65 | }
66 |
67 | private boolean leftGroup() {
68 | return precedence > left.precedence || (precedence == left.precedence && associativity == ASSOCIATIVITY_RIGHT);
69 | }
70 |
71 | private boolean rightGroup() {
72 | return precedence > right.precedence || (precedence == right.precedence && associativity == ASSOCIATIVITY_LEFT);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/ClosureExpression.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 | import unluac.decompile.target.TableTarget;
7 | import unluac.decompile.target.Target;
8 | import unluac.decompile.target.VariableTarget;
9 | import unluac.parse.LFunction;
10 | import unluac.parse.LUpvalue;
11 |
12 | public class ClosureExpression extends Expression {
13 |
14 | private final LFunction function;
15 | private int upvalueLine;
16 |
17 | public ClosureExpression(LFunction function, int upvalueLine) {
18 | super(PRECEDENCE_ATOMIC);
19 | this.function = function;
20 | this.upvalueLine = upvalueLine;
21 | }
22 |
23 | @Override
24 | public void walk(Walker w) {
25 | w.visitExpression(this);
26 | }
27 |
28 | public int getConstantIndex() {
29 | return -1;
30 | }
31 |
32 | @Override
33 | public boolean isClosure() {
34 | return true;
35 | }
36 |
37 | @Override
38 | public boolean isUngrouped() {
39 | return true;
40 | }
41 |
42 | @Override
43 | public boolean isUpvalueOf(int register) {
44 | /*
45 | if(function.header.version == 0x51) {
46 | return false; //TODO:
47 | }
48 | */
49 | for(int i = 0; i < function.upvalues.length; i++) {
50 | LUpvalue upvalue = function.upvalues[i];
51 | if(upvalue.instack && upvalue.idx == register) {
52 | return true;
53 | }
54 | }
55 | return false;
56 | }
57 |
58 | @Override
59 | public int closureUpvalueLine() {
60 | return upvalueLine;
61 | }
62 |
63 | @Override
64 | public void print(Decompiler outer, Output out) {
65 | Decompiler d = new Decompiler(function, outer.declList, upvalueLine);
66 | out.print("function");
67 | printMain(out, d, true);
68 | }
69 |
70 | @Override
71 | public void printClosure(Decompiler outer, Output out, Target name) {
72 | Decompiler d = new Decompiler(function, outer.declList, upvalueLine);
73 | out.print("function ");
74 | if(function.numParams >= 1 && d.declList[0].name.equals("self") && name instanceof TableTarget) {
75 | name.printMethod(outer, out);
76 | printMain(out, d, false);
77 | } else {
78 | name.print(outer, out, false);
79 | printMain(out, d, true);
80 | }
81 | }
82 |
83 | private void printMain(Output out, Decompiler d, boolean includeFirst) {
84 | out.print("(");
85 | int start = includeFirst ? 0 : 1;
86 | if(function.numParams > start) {
87 | new VariableTarget(d.declList[start]).print(d, out, false);
88 | for(int i = start + 1; i < function.numParams; i++) {
89 | out.print(", ");
90 | new VariableTarget(d.declList[i]).print(d, out, false);
91 | }
92 | }
93 | if(function.vararg != 0) {
94 | if(function.numParams > start) {
95 | out.print(", ...");
96 | } else {
97 | out.print("...");
98 | }
99 | }
100 | out.print(")");
101 | out.println();
102 | out.indent();
103 | Decompiler.State result = d.decompile();
104 | d.print(result, out);
105 | out.dedent();
106 | out.print("end");
107 | //out.println(); //This is an extra space for formatting
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/ConstantExpression.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Constant;
4 | import unluac.decompile.Decompiler;
5 | import unluac.decompile.Output;
6 | import unluac.decompile.Walker;
7 | import unluac.parse.LBoolean;
8 | import unluac.parse.LNil;
9 |
10 | public class ConstantExpression extends Expression {
11 |
12 | private final Constant constant;
13 | private final boolean identifier;
14 | private final int index;
15 | private final int line;
16 |
17 | public static ConstantExpression createNil(int line) {
18 | return new ConstantExpression(new Constant(LNil.NIL), false, -1, line);
19 | }
20 |
21 | public static ConstantExpression createBoolean(boolean v) {
22 | return new ConstantExpression(new Constant(v ? LBoolean.LTRUE : LBoolean.LFALSE), false, -1);
23 | }
24 |
25 | public static ConstantExpression createInteger(int i) {
26 | return new ConstantExpression(new Constant(i), false, -1);
27 | }
28 |
29 | public static ConstantExpression createDouble(double x) {
30 | return new ConstantExpression(new Constant(x), false, -1);
31 | }
32 |
33 | private static int getPrecedence(Constant constant) {
34 | if(constant.isNumber() && constant.isNegative()) {
35 | return PRECEDENCE_UNARY;
36 | } else {
37 | return PRECEDENCE_ATOMIC;
38 | }
39 | }
40 |
41 | public ConstantExpression(Constant constant, boolean identifier, int index) {
42 | this(constant, identifier, index, -1);
43 | }
44 |
45 | private ConstantExpression(Constant constant, boolean identifier, int index, int line) {
46 | super(getPrecedence(constant));
47 | this.constant = constant;
48 | this.identifier = identifier;
49 | this.index = index;
50 | this.line = line;
51 | }
52 |
53 | @Override
54 | public void walk(Walker w) {
55 | w.visitExpression(this);
56 | }
57 |
58 | @Override
59 | public int getConstantIndex() {
60 | return index;
61 | }
62 |
63 | @Override
64 | public int getConstantLine() {
65 | return line;
66 | }
67 |
68 | @Override
69 | public void print(Decompiler d, Output out) {
70 | constant.print(d, out, false);
71 | }
72 |
73 | @Override
74 | public void printBraced(Decompiler d, Output out) {
75 | constant.print(d, out, true);
76 | }
77 |
78 | @Override
79 | public boolean isConstant() {
80 | return true;
81 | }
82 |
83 | @Override
84 | public boolean isUngrouped() {
85 | return true;
86 | }
87 |
88 | @Override
89 | public boolean isNil() {
90 | return constant.isNil();
91 | }
92 |
93 | @Override
94 | public boolean isBoolean() {
95 | return constant.isBoolean();
96 | }
97 |
98 | @Override
99 | public boolean isInteger() {
100 | return constant.isInteger();
101 | }
102 |
103 | @Override
104 | public int asInteger() {
105 | return constant.asInteger();
106 | }
107 |
108 | @Override
109 | public boolean isString() {
110 | return constant.isString();
111 | }
112 |
113 | @Override
114 | public boolean isIdentifier() {
115 | return identifier;
116 | }
117 |
118 | @Override
119 | public String asName() {
120 | return constant.asName();
121 | }
122 |
123 | @Override
124 | public boolean isBrief() {
125 | return !constant.isString() || constant.asName().length() <= 10;
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/FunctionCall.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import java.util.ArrayList;
4 |
5 | import unluac.decompile.Decompiler;
6 | import unluac.decompile.Output;
7 | import unluac.decompile.Walker;
8 |
9 | public class FunctionCall extends Expression {
10 |
11 | private final Expression function;
12 | private final Expression[] arguments;
13 | private final boolean multiple;
14 |
15 | public FunctionCall(Expression function, Expression[] arguments, boolean multiple) {
16 | super(PRECEDENCE_ATOMIC);
17 | this.function = function;
18 | this.arguments = arguments;
19 | this.multiple = multiple;
20 | }
21 |
22 | @Override
23 | public void walk(Walker w) {
24 | w.visitExpression(this);
25 | function.walk(w);
26 | for(Expression expression : arguments) {
27 | expression.walk(w);
28 | }
29 | }
30 |
31 | @Override
32 | public int getConstantIndex() {
33 | int index = function.getConstantIndex();
34 | for(Expression argument : arguments) {
35 | index = Math.max(argument.getConstantIndex(), index);
36 | }
37 | return index;
38 | }
39 |
40 | @Override
41 | public boolean isMultiple() {
42 | return multiple;
43 | }
44 |
45 | @Override
46 | public void printMultiple(Decompiler d, Output out) {
47 | if(!multiple) {
48 | out.print("(");
49 | }
50 | print(d, out);
51 | if(!multiple) {
52 | out.print(")");
53 | }
54 | }
55 |
56 | private boolean isMethodCall() {
57 | return function.isMemberAccess() && arguments.length > 0 && function.getTable() == arguments[0];
58 | }
59 |
60 | @Override
61 | public boolean beginsWithParen() {
62 | if(isMethodCall()) {
63 | Expression obj = function.getTable();
64 | return obj.isUngrouped() || obj.beginsWithParen();
65 | } else {
66 | return function.isUngrouped() || function.beginsWithParen();
67 | }
68 | }
69 |
70 | @Override
71 | public void print(Decompiler d, Output out) {
72 | ArrayList args = new ArrayList(arguments.length);
73 | if(isMethodCall()) {
74 | Expression obj = function.getTable();
75 | if(obj.isUngrouped()) {
76 | out.print("(");
77 | obj.print(d, out);
78 | out.print(")");
79 | } else {
80 | obj.print(d, out);
81 | }
82 | out.print(":");
83 | out.print(function.getField());
84 | for(int i = 1; i < arguments.length; i++) {
85 | args.add(arguments[i]);
86 | }
87 | } else {
88 | if(function.isUngrouped()) {
89 | out.print("(");
90 | function.print(d, out);
91 | out.print(")");
92 | } else {
93 | function.print(d, out);
94 | }
95 | for(int i = 0; i < arguments.length; i++) {
96 | args.add(arguments[i]);
97 | }
98 | }
99 | out.print("(");
100 | Expression.printSequence(d, out, args, false, true);
101 | out.print(")");
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/GlobalExpression.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class GlobalExpression extends Expression {
8 |
9 | private final ConstantExpression name;
10 | private final int index;
11 |
12 | public GlobalExpression(ConstantExpression name, int index) {
13 | super(PRECEDENCE_ATOMIC);
14 | this.name = name;
15 | this.index = index;
16 | }
17 |
18 | @Override
19 | public void walk(Walker w) {
20 | w.visitExpression(this);
21 | name.walk(w);
22 | }
23 |
24 | @Override
25 | public int getConstantIndex() {
26 | return index;
27 | }
28 |
29 | @Override
30 | public boolean isDotChain() {
31 | return true;
32 | }
33 |
34 | @Override
35 | public void print(Decompiler d, Output out) {
36 | out.print(name.asName());
37 | }
38 |
39 | @Override
40 | public boolean isBrief() {
41 | return true;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/LocalVariable.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Declaration;
4 | import unluac.decompile.Decompiler;
5 | import unluac.decompile.Output;
6 | import unluac.decompile.Walker;
7 |
8 | public class LocalVariable extends Expression {
9 |
10 | private final Declaration decl;
11 |
12 | public LocalVariable(Declaration decl) {
13 | super(PRECEDENCE_ATOMIC);
14 | this.decl = decl;
15 | }
16 |
17 | @Override
18 | public void walk(Walker w) {
19 | w.visitExpression(this);
20 | }
21 |
22 | @Override
23 | public int getConstantIndex() {
24 | return -1;
25 | }
26 |
27 | @Override
28 | public boolean isDotChain() {
29 | return true;
30 | }
31 |
32 | @Override
33 | public void print(Decompiler d, Output out) {
34 | out.print(decl.name);
35 | }
36 |
37 | @Override
38 | public boolean isBrief() {
39 | return true;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/TableReference.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class TableReference extends Expression {
8 |
9 | private final Expression table;
10 | private final Expression index;
11 |
12 | public TableReference(Expression table, Expression index) {
13 | super(PRECEDENCE_ATOMIC);
14 | this.table = table;
15 | this.index = index;
16 | }
17 |
18 | @Override
19 | public void walk(Walker w) {
20 | w.visitExpression(this);
21 | table.walk(w);
22 | index.walk(w);
23 | }
24 |
25 | @Override
26 | public int getConstantIndex() {
27 | return Math.max(table.getConstantIndex(), index.getConstantIndex());
28 | }
29 |
30 | @Override
31 | public void print(Decompiler d, Output out) {
32 | boolean isGlobal = table.isEnvironmentTable(d) && index.isIdentifier();
33 | if(!isGlobal) {
34 | if(table.isUngrouped()) {
35 | out.print("(");
36 | table.print(d, out);
37 | out.print(")");
38 | }
39 | else
40 | {
41 | table.print(d, out);
42 | }
43 | }
44 | if(index.isIdentifier()) {
45 | if(!isGlobal) {
46 | out.print(".");
47 | }
48 | out.print(index.asName());
49 | } else {
50 | out.print("[");
51 | index.printBraced(d, out);
52 | out.print("]");
53 | }
54 | }
55 |
56 | @Override
57 | public boolean isDotChain() {
58 | return index.isIdentifier() && table.isDotChain();
59 | }
60 |
61 | @Override
62 | public boolean isMemberAccess() {
63 | return index.isIdentifier();
64 | }
65 |
66 | @Override
67 | public boolean beginsWithParen() {
68 | return table.isUngrouped() || table.beginsWithParen();
69 | }
70 |
71 | @Override
72 | public Expression getTable() {
73 | return table;
74 | }
75 |
76 | @Override
77 | public String getField() {
78 | return index.asName();
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/UnaryExpression.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class UnaryExpression extends Expression {
8 |
9 | private final String op;
10 | private final Expression expression;
11 |
12 | public UnaryExpression(String op, Expression expression, int precedence) {
13 | super(precedence);
14 | this.op = op;
15 | this.expression = expression;
16 | }
17 |
18 | @Override
19 | public void walk(Walker w) {
20 | w.visitExpression(this);
21 | expression.walk(w);
22 | }
23 |
24 | @Override
25 | public boolean isUngrouped() {
26 | return true;
27 | }
28 |
29 | @Override
30 | public int getConstantIndex() {
31 | return expression.getConstantIndex();
32 | }
33 |
34 | @Override
35 | public void print(Decompiler d, Output out) {
36 | out.print(op);
37 | if(precedence > expression.precedence) out.print("(");
38 | expression.print(d, out);
39 | if(precedence > expression.precedence) out.print(")");
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/UpvalueExpression.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class UpvalueExpression extends Expression {
8 |
9 | private final String name;
10 |
11 | public UpvalueExpression(String name) {
12 | super(PRECEDENCE_ATOMIC);
13 | this.name = name;
14 | }
15 |
16 | @Override
17 | public void walk(Walker w) {
18 | w.visitExpression(this);
19 | }
20 |
21 | @Override
22 | public int getConstantIndex() {
23 | return -1;
24 | }
25 |
26 | @Override
27 | public boolean isDotChain() {
28 | return true;
29 | }
30 |
31 | @Override
32 | public void print(Decompiler d, Output out) {
33 | out.print(name);
34 | }
35 |
36 | @Override
37 | public boolean isBrief() {
38 | return true;
39 | }
40 |
41 | @Override
42 | public boolean isEnvironmentTable(Decompiler d) {
43 | return d.getVersion().isEnvironmentTable(name);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/unluac/decompile/expression/Vararg.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.expression;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class Vararg extends Expression {
8 |
9 | private final boolean multiple;
10 |
11 | public Vararg(int length, boolean multiple) {
12 | super(PRECEDENCE_ATOMIC);
13 | this.multiple = multiple;
14 | }
15 |
16 | @Override
17 | public void walk(Walker w) {
18 | w.visitExpression(this);
19 | }
20 |
21 | @Override
22 | public int getConstantIndex() {
23 | return -1;
24 | }
25 |
26 | @Override
27 | public void print(Decompiler d, Output out) {
28 | //out.print("...");
29 | out.print(multiple ? "..." : "(...)");
30 | }
31 |
32 | @Override
33 | public void printMultiple(Decompiler d, Output out) {
34 | out.print(multiple ? "..." : "(...)");
35 | }
36 |
37 | @Override
38 | public boolean isMultiple() {
39 | return multiple;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/CallOperation.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.FunctionCall;
6 | import unluac.decompile.statement.FunctionCallStatement;
7 | import unluac.decompile.statement.Statement;
8 |
9 | public class CallOperation extends Operation {
10 |
11 | private FunctionCall call;
12 |
13 | public CallOperation(int line, FunctionCall call) {
14 | super(line);
15 | this.call = call;
16 | }
17 |
18 | @Override
19 | public Statement process(Registers r, Block block) {
20 | return new FunctionCallStatement(call);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/GlobalSet.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.ConstantExpression;
6 | import unluac.decompile.expression.Expression;
7 | import unluac.decompile.statement.Assignment;
8 | import unluac.decompile.statement.Statement;
9 | import unluac.decompile.target.GlobalTarget;
10 |
11 | public class GlobalSet extends Operation {
12 |
13 | private ConstantExpression global;
14 | private Expression value;
15 |
16 | public GlobalSet(int line, ConstantExpression global, Expression value) {
17 | super(line);
18 | this.global = global;
19 | this.value = value;
20 | }
21 |
22 | @Override
23 | public Statement process(Registers r, Block block) {
24 | return new Assignment(new GlobalTarget(global), value, line);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/LoadNil.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.ConstantExpression;
6 | import unluac.decompile.expression.Expression;
7 | import unluac.decompile.statement.Assignment;
8 | import unluac.decompile.statement.Statement;
9 |
10 | public class LoadNil extends Operation {
11 |
12 | public final int registerFirst;
13 | public final int registerLast;
14 |
15 | public LoadNil(int line, int registerFirst, int registerLast) {
16 | super(line);
17 | this.registerFirst = registerFirst;
18 | this.registerLast = registerLast;
19 | }
20 |
21 | @Override
22 | public Statement process(Registers r, Block block) {
23 | int count = 0;
24 | Assignment assignment = new Assignment();
25 | Expression nil = ConstantExpression.createNil(line);
26 | int scopeEnd = -1;
27 | for(int register = registerFirst; register <= registerLast; register++) {
28 | if(r.isAssignable(register, line)) {
29 | scopeEnd = r.getDeclaration(register, line).end;
30 | }
31 | }
32 | for(int register = registerFirst; register <= registerLast; register++) {
33 | r.setValue(register, line, nil);
34 | if(r.isAssignable(register, line) && r.getDeclaration(register, line).end == scopeEnd) {
35 | assignment.addLast(r.getTarget(register, line), nil, line);
36 | count++;
37 | }
38 | }
39 | if(count > 0) {
40 | return assignment;
41 | } else {
42 | return null;
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/MultipleRegisterSet.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.Expression;
6 | import unluac.decompile.statement.Assignment;
7 | import unluac.decompile.statement.Statement;
8 |
9 | public class MultipleRegisterSet extends Operation {
10 |
11 | public final int registerFirst;
12 | public final int registerLast;
13 | public final Expression value;
14 |
15 | public MultipleRegisterSet(int line, int registerFirst, int registerLast, Expression value) {
16 | super(line);
17 | this.registerFirst = registerFirst;
18 | this.registerLast = registerLast;
19 | this.value = value;
20 | }
21 |
22 | @Override
23 | public Statement process(Registers r, Block block) {
24 | int count = 0;
25 | Assignment assignment = new Assignment();
26 | for(int register = registerFirst; register <= registerLast; register++) {
27 | r.setValue(register, line, value);
28 | if(r.isAssignable(register, line)) {
29 | assignment.addLast(r.getTarget(register, line), value, line);
30 | count++;
31 | }
32 | }
33 | if(count > 0) {
34 | return assignment;
35 | } else {
36 | return null;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/Operation.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.statement.Statement;
6 |
7 | abstract public class Operation {
8 |
9 | public final int line;
10 |
11 | public Operation(int line) {
12 | this.line = line;
13 | }
14 |
15 | abstract public Statement process(Registers r, Block block);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/RegisterSet.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.Expression;
6 | import unluac.decompile.statement.Assignment;
7 | import unluac.decompile.statement.Statement;
8 |
9 | public class RegisterSet extends Operation {
10 |
11 | public final int register;
12 | public final Expression value;
13 |
14 | public RegisterSet(int line, int register, Expression value) {
15 | super(line);
16 | this.register = register;
17 | this.value = value;
18 | /*
19 | if(value.isMultiple()) {
20 | System.out.println("-- multiple @" + register);
21 | }
22 | */
23 | }
24 |
25 | @Override
26 | public Statement process(Registers r, Block block) {
27 | //System.out.println("-- processing register set " + register + "@" + line);
28 | r.setValue(register, line, value);
29 | /*
30 | if(value.isMultiple()) {
31 | System.out.println("-- process multiple @" + register);
32 | }
33 | */
34 | if(r.isAssignable(register, line)) {
35 | //System.out.println("-- assignment!");
36 | return new Assignment(r.getTarget(register, line), value, line);
37 | } else {
38 | return null;
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/ReturnOperation.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.Expression;
6 | import unluac.decompile.statement.Return;
7 | import unluac.decompile.statement.Statement;
8 |
9 | public class ReturnOperation extends Operation {
10 |
11 | private Expression[] values;
12 |
13 | public ReturnOperation(int line, Expression value) {
14 | super(line);
15 | values = new Expression[1];
16 | values[0] = value;
17 | }
18 |
19 | public ReturnOperation(int line, Expression[] values) {
20 | super(line);
21 | this.values = values;
22 | }
23 |
24 | @Override
25 | public Statement process(Registers r, Block block) {
26 | return new Return(values);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/TableSet.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.Expression;
6 | import unluac.decompile.expression.TableLiteral;
7 | import unluac.decompile.statement.Assignment;
8 | import unluac.decompile.statement.Statement;
9 | import unluac.decompile.target.TableTarget;
10 |
11 | public class TableSet extends Operation {
12 |
13 | private Expression table;
14 | private Expression index;
15 | private Expression value;
16 | private boolean isTable;
17 | private int timestamp;
18 |
19 | public TableSet(int line, Expression table, Expression index, Expression value, boolean isTable, int timestamp) {
20 | super(line);
21 | this.table = table;
22 | this.index = index;
23 | this.value = value;
24 | this.isTable = isTable;
25 | this.timestamp = timestamp;
26 | }
27 |
28 | @Override
29 | public Statement process(Registers r, Block block) {
30 | // .isTableLiteral() is sufficient when there is debugging info
31 | if(!r.isStrippedDefault && table.isTableLiteral() && (value.isMultiple() || table.isNewEntryAllowed())) {
32 | table.addEntry(new TableLiteral.Entry(index, value, !isTable, timestamp));
33 | return null;
34 | } else {
35 | return new Assignment(new TableTarget(table, index), value, line);
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/unluac/decompile/operation/UpvalueSet.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.operation;
2 |
3 | import unluac.decompile.Registers;
4 | import unluac.decompile.block.Block;
5 | import unluac.decompile.expression.Expression;
6 | import unluac.decompile.statement.Assignment;
7 | import unluac.decompile.statement.Statement;
8 | import unluac.decompile.target.UpvalueTarget;
9 |
10 | public class UpvalueSet extends Operation {
11 |
12 | private UpvalueTarget target;
13 | private Expression value;
14 |
15 | public UpvalueSet(int line, String upvalue, Expression value) {
16 | super(line);
17 | target = new UpvalueTarget(upvalue);
18 | this.value = value;
19 | }
20 |
21 | @Override
22 | public Statement process(Registers r, Block block) {
23 | return new Assignment(target, value, line);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/unluac/decompile/statement/Declare.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.statement;
2 |
3 | import java.util.List;
4 |
5 | import unluac.decompile.Declaration;
6 | import unluac.decompile.Decompiler;
7 | import unluac.decompile.Output;
8 | import unluac.decompile.Walker;
9 |
10 | public class Declare extends Statement {
11 |
12 | private final List decls;
13 |
14 | public Declare(List decls) {
15 | this.decls = decls;
16 | }
17 |
18 | @Override
19 | public void walk(Walker w) {
20 | w.visitStatement(this);
21 | }
22 |
23 | @Override
24 | public void print(Decompiler d, Output out) {
25 | out.print("local ");
26 | out.print(decls.get(0).name);
27 | for(int i = 1; i < decls.size(); i++) {
28 | out.print(", ");
29 | out.print(decls.get(i).name);
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/unluac/decompile/statement/FunctionCallStatement.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.statement;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 | import unluac.decompile.expression.FunctionCall;
7 |
8 | public class FunctionCallStatement extends Statement {
9 |
10 | private FunctionCall call;
11 |
12 | public FunctionCallStatement(FunctionCall call) {
13 | this.call = call;
14 | }
15 |
16 | @Override
17 | public void walk(Walker w) {
18 | w.visitStatement(this);
19 | call.walk(w);
20 | }
21 |
22 | @Override
23 | public void print(Decompiler d, Output out) {
24 | call.print(d, out);
25 | }
26 |
27 | @Override
28 | public boolean beginsWithParen() {
29 | return call.beginsWithParen();
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/unluac/decompile/statement/Label.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.statement;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class Label extends Statement {
8 |
9 | private String name;
10 |
11 | public Label(int line) {
12 | name = "lbl_" + line;
13 | }
14 |
15 | public void walk(Walker w) {
16 | w.visitStatement(this);
17 | }
18 |
19 | @Override
20 | public void print(Decompiler d, Output out) {
21 | out.print("::" + name + "::");
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/unluac/decompile/statement/Return.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.statement;
2 |
3 | import java.util.ArrayList;
4 |
5 | import unluac.decompile.Decompiler;
6 | import unluac.decompile.Output;
7 | import unluac.decompile.Walker;
8 | import unluac.decompile.expression.Expression;
9 |
10 | public class Return extends Statement {
11 |
12 | private Expression[] values;
13 |
14 | public Return() {
15 | values = new Expression[0];
16 | }
17 |
18 | public Return(Expression value) {
19 | values = new Expression[1];
20 | values[0] = value;
21 | }
22 |
23 | public Return(Expression[] values) {
24 | this.values = values;
25 | }
26 |
27 | public void walk(Walker w) {
28 | w.visitStatement(this);
29 | for(Expression expression : values) {
30 | expression.walk(w);
31 | }
32 | }
33 |
34 | @Override
35 | public void print(Decompiler d, Output out) {
36 | out.print("do ");
37 | printTail(d, out);
38 | out.print(" end");
39 | }
40 |
41 | @Override
42 | public void printTail(Decompiler d, Output out) {
43 | out.print("return");
44 | if(values.length > 0) {
45 | out.print(" ");
46 | ArrayList rtns = new ArrayList(values.length);
47 | for(Expression value : values) {
48 | rtns.add(value);
49 | }
50 | Expression.printSequence(d, out, rtns, false, true);
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/unluac/decompile/statement/Statement.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.statement;
2 |
3 | import java.util.List;
4 |
5 | import unluac.decompile.Decompiler;
6 | import unluac.decompile.Function;
7 | import unluac.decompile.Output;
8 | import unluac.decompile.Walker;
9 |
10 | abstract public class Statement {
11 |
12 | /**
13 | * Prints out a sequences of statements on separate lines. Correctly
14 | * informs the last statement that it is last in a block.
15 | */
16 | public static void printSequence(Decompiler d, Output out, List stmts) {
17 | int n = stmts.size();
18 | for(int i = 0; i < n; i++) {
19 | boolean last = (i + 1 == n);
20 | Statement stmt = stmts.get(i);
21 | if(stmt.beginsWithParen() && (i > 0 || d.getVersion().allowpreceedingsemicolon.get())) {
22 | out.print(";");
23 | }
24 | if(last) {
25 | stmt.printTail(d, out);
26 | } else {
27 | stmt.print(d, out);
28 | }
29 | if(!stmt.suppressNewline()) {
30 | out.println();
31 | }
32 | }
33 | }
34 |
35 | abstract public void print(Decompiler d, Output out);
36 |
37 | public void printTail(Decompiler d, Output out) {
38 | print(d, out);
39 | }
40 |
41 | public String comment;
42 |
43 | public void addComment(String comment) {
44 | this.comment = comment;
45 | }
46 |
47 | public abstract void walk(Walker w);
48 |
49 | public boolean beginsWithParen() {
50 | return false;
51 | }
52 |
53 | public boolean suppressNewline() {
54 | return false;
55 | }
56 |
57 | public boolean useConstant(Function f, int index) {
58 | return false;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/unluac/decompile/target/GlobalTarget.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.target;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 | import unluac.decompile.expression.ConstantExpression;
7 | import unluac.decompile.expression.Expression;
8 |
9 | public class GlobalTarget extends Target {
10 |
11 | private final Expression name;
12 |
13 | public GlobalTarget(ConstantExpression name) {
14 | this.name = name;
15 | }
16 |
17 | @Override
18 | public void walk(Walker w) {
19 | name.walk(w);
20 | }
21 |
22 | @Override
23 | public void print(Decompiler d, Output out, boolean declare) {
24 | out.print(name.asName());
25 | }
26 |
27 | @Override
28 | public void printMethod(Decompiler d, Output out) {
29 | throw new IllegalStateException();
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/unluac/decompile/target/TableTarget.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.target;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 | import unluac.decompile.expression.Expression;
7 | import unluac.decompile.expression.TableReference;
8 |
9 | public class TableTarget extends Target {
10 |
11 | private final Expression table;
12 | private final Expression index;
13 |
14 | public TableTarget(Expression table, Expression index) {
15 | this.table = table;
16 | this.index = index;
17 | }
18 |
19 | @Override
20 | public void walk(Walker w) {
21 | table.walk(w);
22 | index.walk(w);
23 | }
24 |
25 | @Override
26 | public void print(Decompiler d, Output out, boolean declare) {
27 | new TableReference(table, index).print(d, out);
28 | }
29 |
30 | @Override
31 | public void printMethod(Decompiler d, Output out) {
32 | table.print(d, out);
33 | out.print(":");
34 | out.print(index.asName());
35 | }
36 |
37 | @Override
38 | public boolean isFunctionName() {
39 | if(!index.isIdentifier()) {
40 | return false;
41 | }
42 | if(!table.isDotChain()) {
43 | return false;
44 | }
45 | return true;
46 | }
47 |
48 | @Override
49 | public boolean beginsWithParen() {
50 | return table.isUngrouped() || table.beginsWithParen();
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/unluac/decompile/target/Target.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.target;
2 |
3 | import unluac.decompile.Declaration;
4 | import unluac.decompile.Decompiler;
5 | import unluac.decompile.Output;
6 | import unluac.decompile.Walker;
7 |
8 | abstract public class Target {
9 |
10 | abstract public void walk(Walker w);
11 |
12 | abstract public void print(Decompiler d, Output out, boolean declare);
13 |
14 | abstract public void printMethod(Decompiler d, Output out);
15 |
16 | public boolean isDeclaration(Declaration decl) {
17 | return false;
18 | }
19 |
20 | public boolean isLocal() {
21 | return false;
22 | }
23 |
24 | public int getIndex() {
25 | throw new IllegalStateException();
26 | }
27 |
28 | public boolean isFunctionName() {
29 | return true;
30 | }
31 |
32 | public boolean beginsWithParen() {
33 | return false;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/unluac/decompile/target/UpvalueTarget.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.target;
2 |
3 | import unluac.decompile.Decompiler;
4 | import unluac.decompile.Output;
5 | import unluac.decompile.Walker;
6 |
7 | public class UpvalueTarget extends Target{
8 |
9 | private final String name;
10 |
11 | public UpvalueTarget(String name) {
12 | this.name = name;
13 | }
14 |
15 | @Override
16 | public void walk(Walker w) {}
17 |
18 | @Override
19 | public void print(Decompiler d, Output out, boolean declare) {
20 | out.print(name);
21 | }
22 |
23 | @Override
24 | public void printMethod(Decompiler d, Output out) {
25 | throw new IllegalStateException();
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/unluac/decompile/target/VariableTarget.java:
--------------------------------------------------------------------------------
1 | package unluac.decompile.target;
2 |
3 | import unluac.decompile.Declaration;
4 | import unluac.decompile.Decompiler;
5 | import unluac.decompile.Output;
6 | import unluac.decompile.Walker;
7 |
8 | public class VariableTarget extends Target {
9 |
10 | public final Declaration decl;
11 |
12 | public VariableTarget(Declaration decl) {
13 | this.decl = decl;
14 | }
15 |
16 | @Override
17 | public void walk(Walker w) {}
18 |
19 | @Override
20 | public void print(Decompiler d, Output out, boolean declare) {
21 | out.print(decl.name);
22 | if(declare && decl.tbc) {
23 | out.print(" ");
24 | }
25 | }
26 |
27 | @Override
28 | public void printMethod(Decompiler d, Output out) {
29 | throw new IllegalStateException();
30 | }
31 |
32 | @Override
33 | public boolean isDeclaration(Declaration decl) {
34 | return this.decl == decl;
35 | }
36 |
37 | @Override
38 | public boolean isLocal() {
39 | return true;
40 | }
41 |
42 | @Override
43 | public int getIndex() {
44 | return decl.register;
45 | }
46 |
47 | public boolean equals(Object obj) {
48 | if(obj instanceof VariableTarget) {
49 | VariableTarget t = (VariableTarget) obj;
50 | return decl == t.decl;
51 | } else {
52 | return false;
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/unluac/parse/BInteger.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.math.BigInteger;
4 | import java.util.ArrayList;
5 |
6 | public class BInteger extends BObject {
7 |
8 | private final BigInteger big;
9 | private final int n;
10 |
11 | private static BigInteger MAX_INT = null;
12 | private static BigInteger MIN_INT = null;
13 |
14 | public BInteger(BInteger b) {
15 | this.big = b.big;
16 | this.n = b.n;
17 | }
18 |
19 | public BInteger(int n) {
20 | this.big = null;
21 | this.n = n;
22 | }
23 |
24 | public BInteger(BigInteger big) {
25 | this.big = big;
26 | this.n = 0;
27 | if(MAX_INT == null) {
28 | MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
29 | MIN_INT = BigInteger.valueOf(Integer.MIN_VALUE);
30 | }
31 | }
32 |
33 | public int asInt() {
34 | if(big == null) {
35 | return n;
36 | } else if(big.compareTo(MAX_INT) > 0 || big.compareTo(MIN_INT) < 0) {
37 | throw new IllegalStateException("The size of an integer is outside the range that unluac can handle.");
38 | } else {
39 | return big.intValue();
40 | }
41 | }
42 |
43 | public byte[] littleEndianBytes(int size) {
44 | ArrayList bytes = new ArrayList();
45 | if(big == null) {
46 | if(size >= 1) bytes.add((byte)(n & 0xFF));
47 | if(size >= 2) bytes.add((byte)((n >>> 8) & 0xFF));
48 | if(size >= 3) bytes.add((byte)((n >>> 16) & 0xFF));
49 | if(size >= 4) bytes.add((byte)((n >>> 24) & 0xFF));
50 | } else {
51 | BigInteger n = big;
52 | boolean negate = false;
53 | if(n.signum() < 0) {
54 | n = n.negate();
55 | n = n.subtract(BigInteger.ONE);
56 | negate = true;
57 | }
58 | BigInteger b256 = BigInteger.valueOf(256);
59 | BigInteger b255 = BigInteger.valueOf(255);
60 | while(n.compareTo(b256) < 0 && size > 0) {
61 | int v = n.and(b255).intValue();
62 | if(negate) {
63 | v = ~v;
64 | }
65 | bytes.add((byte)v);
66 | n = n.divide(b256);
67 | size--;
68 | }
69 | }
70 | while(size > bytes.size()) bytes.add((byte)0);
71 | byte[] array = new byte[bytes.size()];
72 | for(int i = 0; i < bytes.size(); i++) {
73 | array[i] = bytes.get(i);
74 | }
75 | return array;
76 | }
77 |
78 | public byte[] compressedBytes() {
79 | BigInteger value = big;
80 | if(value == null) {
81 | value = BigInteger.valueOf(n);
82 | }
83 | if(value.compareTo(BigInteger.ZERO) == 0) {
84 | return new byte[] {0};
85 | }
86 | ArrayList bytes = new ArrayList((value.bitCount() + 6) / 7);
87 | BigInteger limit = BigInteger.valueOf(0x7F);
88 | while(value.compareTo(BigInteger.ZERO) > 0) {
89 | bytes.add((byte) value.and(limit).intValue());
90 | value = value.shiftRight(7);
91 | }
92 | byte[] array = new byte[bytes.size()];
93 | for(int i = 0; i < bytes.size(); i++) {
94 | array[i] = bytes.get(i);
95 | }
96 | return array;
97 | }
98 |
99 | public void iterate(Runnable thunk) {
100 | if(big == null) {
101 | int i = n;
102 | while(i-- != 0) {
103 | thunk.run();
104 | }
105 | } else {
106 | BigInteger i = big;
107 | while(i.signum() > 0) {
108 | thunk.run();
109 | i = i.subtract(BigInteger.ONE);
110 | }
111 | }
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/unluac/parse/BList.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.util.Iterator;
4 | import java.util.List;
5 |
6 | public class BList extends BObject {
7 |
8 | public final BInteger length;
9 | private final List values;
10 |
11 | public BList(BInteger length, List values) {
12 | this.length = length;
13 | this.values = values;
14 | }
15 |
16 | public T get(int index) {
17 | return values.get(index);
18 | }
19 |
20 | public Iterator iterator() {
21 | return values.iterator();
22 | }
23 |
24 | public T[] asArray(final T[] array) {
25 | length.iterate(new Runnable() {
26 |
27 | private int i = 0;
28 |
29 | @Override
30 | public void run() {
31 | array[i] = values.get(i);
32 | i++;
33 | }
34 |
35 | });
36 | return array;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/unluac/parse/BObject.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | abstract public class BObject {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/unluac/parse/BObjectType.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 | import java.util.ArrayList;
7 | import java.util.Iterator;
8 | import java.util.List;
9 |
10 | abstract public class BObjectType {
11 |
12 | abstract public T parse(ByteBuffer buffer, BHeader header);
13 |
14 | abstract public void write(OutputStream out, BHeader header, T object) throws IOException;
15 |
16 | public final BList parseList(final ByteBuffer buffer, final BHeader header) {
17 | BInteger length = header.integer.parse(buffer, header);
18 | final List values = new ArrayList();
19 | length.iterate(new Runnable() {
20 |
21 | @Override
22 | public void run() {
23 | values.add(parse(buffer, header));
24 | }
25 |
26 | });
27 | return new BList(length, values);
28 | }
29 |
30 | public final void writeList(OutputStream out, BHeader header, T[] array) throws IOException {
31 | header.integer.write(out, header, new BInteger(array.length));
32 | for(T object : array) {
33 | write(out, header, object);
34 | }
35 | }
36 |
37 | public final void writeList(OutputStream out, BHeader header, BList blist) throws IOException {
38 | header.integer.write(out, header, blist.length);
39 | Iterator it = blist.iterator();
40 | while(it.hasNext()) {
41 | write(out, header, it.next());
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/unluac/parse/LAbsLineInfo.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | public class LAbsLineInfo extends LObject {
4 |
5 | public final int pc;
6 | public final int line;
7 |
8 | public LAbsLineInfo(int pc, int line) {
9 | this.pc = pc;
10 | this.line = line;
11 | }
12 |
13 | @Override
14 | public boolean equals(Object o) {
15 | if(o instanceof LAbsLineInfo) {
16 | LAbsLineInfo other = (LAbsLineInfo) o;
17 | return pc == other.pc && line == other.line;
18 | } else {
19 | return false;
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/unluac/parse/LAbsLineInfoType.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 |
7 | public class LAbsLineInfoType extends BObjectType {
8 |
9 | @Override
10 | public LAbsLineInfo parse(ByteBuffer buffer, BHeader header) {
11 | int pc = header.integer.parse(buffer, header).asInt();
12 | int line = header.integer.parse(buffer, header).asInt();
13 | return new LAbsLineInfo(pc, line);
14 | }
15 |
16 | @Override
17 | public void write(OutputStream out, BHeader header, LAbsLineInfo object) throws IOException {
18 | header.integer.write(out, header, new BInteger(object.pc));
19 | header.integer.write(out, header, new BInteger(object.line));
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/unluac/parse/LBoolean.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | public class LBoolean extends LObject {
4 |
5 | public static final LBoolean LTRUE = new LBoolean(true);
6 | public static final LBoolean LFALSE = new LBoolean(false);
7 |
8 | private final boolean value;
9 |
10 | private LBoolean(boolean value) {
11 | this.value = value;
12 | }
13 |
14 | public boolean value() {
15 | return value;
16 | }
17 |
18 | public String toPrintString() {
19 | return Boolean.toString(value);
20 | }
21 |
22 | @Override
23 | public boolean equals(Object o) {
24 | return this == o;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/unluac/parse/LBooleanType.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 |
7 |
8 | public class LBooleanType extends BObjectType {
9 |
10 | @Override
11 | public LBoolean parse(ByteBuffer buffer, BHeader header) {
12 | int value = buffer.get();
13 | if((value & 0xFFFFFFFE) != 0) {
14 | throw new IllegalStateException();
15 | } else {
16 | LBoolean bool = value == 0 ? LBoolean.LFALSE : LBoolean.LTRUE;
17 | if(header.debug) {
18 | System.out.println("-- parsed " + bool);
19 | }
20 | return bool;
21 | }
22 | }
23 |
24 | @Override
25 | public void write(OutputStream out, BHeader header, LBoolean object) throws IOException {
26 | int value = object.value() ? 1 : 0;
27 | out.write(value);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/unluac/parse/LFunction.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | public class LFunction extends BObject {
4 |
5 | public BHeader header;
6 | public LString name;
7 | public int linedefined;
8 | public int lastlinedefined;
9 | public LFunction parent;
10 | public int[] code;
11 | public int[] lines;
12 | public LAbsLineInfo[] abslineinfo;
13 | public LLocal[] locals;
14 | public LObject[] constants;
15 | public LUpvalue[] upvalues;
16 | public LFunction[] functions;
17 | public int maximumStackSize;
18 | public int numUpvalues;
19 | public int numParams;
20 | public int vararg;
21 | public boolean stripped;
22 |
23 | public LFunction(BHeader header, LString name, int linedefined, int lastlinedefined, int[] code, int[] lines, LAbsLineInfo[] abslineinfo, LLocal[] locals, LObject[] constants, LUpvalue[] upvalues, LFunction[] functions, int maximumStackSize, int numUpValues, int numParams, int vararg) {
24 | this.header = header;
25 | this.name = name;
26 | this.linedefined = linedefined;
27 | this.lastlinedefined = lastlinedefined;
28 | this.code = code;
29 | this.lines = lines;
30 | this.abslineinfo = abslineinfo;
31 | this.locals = locals;
32 | this.constants = constants;
33 | this.upvalues = upvalues;
34 | this.functions = functions;
35 | this.maximumStackSize = maximumStackSize;
36 | this.numUpvalues = numUpValues;
37 | this.numParams = numParams;
38 | this.vararg = vararg;
39 | this.stripped = false;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/unluac/parse/LHeader.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import unluac.decompile.CodeExtract;
4 |
5 | public class LHeader extends BObject {
6 |
7 | public static enum LEndianness {
8 | BIG,
9 | LITTLE;
10 | }
11 |
12 | public final int format;
13 | public final LEndianness endianness;
14 | public final BIntegerType integer;
15 | public final BIntegerType sizeT;
16 | public final LBooleanType bool;
17 | public final LNumberType number;
18 | public final LNumberType linteger;
19 | public final LNumberType lfloat;
20 | public final LStringType string;
21 | public final LConstantType constant;
22 | public final LAbsLineInfoType abslineinfo;
23 | public final LLocalType local;
24 | public final LUpvalueType upvalue;
25 | public final LFunctionType function;
26 | public final CodeExtract extractor;
27 |
28 | public LHeader(int format, LEndianness endianness, BIntegerType integer, BIntegerType sizeT, LBooleanType bool, LNumberType number, LNumberType linteger, LNumberType lfloat, LStringType string, LConstantType constant, LAbsLineInfoType abslineinfo, LLocalType local, LUpvalueType upvalue, LFunctionType function, CodeExtract extractor) {
29 | this.format = format;
30 | this.endianness = endianness;
31 | this.integer = integer;
32 | this.sizeT = sizeT;
33 | this.bool = bool;
34 | this.number = number;
35 | this.linteger = linteger;
36 | this.lfloat = lfloat;
37 | this.string = string;
38 | this.constant = constant;
39 | this.abslineinfo = abslineinfo;
40 | this.local = local;
41 | this.upvalue = upvalue;
42 | this.function = function;
43 | this.extractor = extractor;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/unluac/parse/LLocal.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 |
4 | public class LLocal extends BObject {
5 |
6 | public final LString name;
7 | public final int start;
8 | public final int end;
9 |
10 | /* Used by the decompiler for annotation. */
11 | public boolean forLoop = false;
12 |
13 | public LLocal(LString name, BInteger start, BInteger end) {
14 | this.name = name;
15 | this.start = start.asInt();
16 | this.end = end.asInt();
17 | }
18 |
19 | public String toString() {
20 | return name.deref();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/unluac/parse/LLocalType.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 |
7 |
8 | public class LLocalType extends BObjectType {
9 |
10 | @Override
11 | public LLocal parse(ByteBuffer buffer, BHeader header) {
12 | LString name = header.string.parse(buffer, header);
13 | BInteger start = header.integer.parse(buffer, header);
14 | BInteger end = header.integer.parse(buffer, header);
15 | if(header.debug) {
16 | System.out.print("-- parsing local, name: ");
17 | System.out.print(name);
18 | System.out.print(" from " + start.asInt() + " to " + end.asInt());
19 | System.out.println();
20 | }
21 | return new LLocal(name, start, end);
22 | }
23 |
24 | @Override
25 | public void write(OutputStream out, BHeader header, LLocal object) throws IOException {
26 | header.string.write(out, header, object.name);
27 | header.integer.write(out, header, new BInteger(object.start));
28 | header.integer.write(out, header, new BInteger(object.end));
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/unluac/parse/LNil.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | public class LNil extends LObject{
4 |
5 | public static final LNil NIL = new LNil();
6 |
7 | private LNil() {
8 |
9 | }
10 |
11 | @Override
12 | public String toPrintString() {
13 | return "nil";
14 | }
15 |
16 | @Override
17 | public boolean equals(Object o) {
18 | return this == o;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/unluac/parse/LObject.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 |
4 | abstract public class LObject extends BObject {
5 |
6 | public String deref() {
7 | throw new IllegalStateException();
8 | }
9 |
10 | public String toPrintString() {
11 | throw new IllegalStateException();
12 | }
13 |
14 | abstract public boolean equals(Object o);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/unluac/parse/LSourceLines.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | public class LSourceLines {
6 |
7 | public static LSourceLines parse(ByteBuffer buffer) {
8 | int number = buffer.getInt();
9 | while(number-- > 0) {
10 | buffer.getInt();
11 | }
12 | return null;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/unluac/parse/LString.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import unluac.util.StringUtils;
4 |
5 | public class LString extends LObject {
6 |
7 | public final String value;
8 | public boolean islong;
9 |
10 | public LString(String value) {
11 | this.value = value;
12 | islong = false;
13 | }
14 |
15 | @Override
16 | public String deref() {
17 | return value;
18 | }
19 |
20 | @Override
21 | public String toPrintString() {
22 | String prefix = "";
23 | if(islong) prefix = "L";
24 | return prefix + StringUtils.toPrintString(value);
25 | }
26 |
27 | @Override
28 | public boolean equals(Object o) {
29 | if(o instanceof LString) {
30 | LString os = (LString) o;
31 | return os.value.equals(value) && os.islong == islong;
32 | }
33 | return false;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/unluac/parse/LUpvalue.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | public class LUpvalue extends BObject {
4 |
5 | public boolean instack;
6 | public int idx;
7 |
8 | public String name;
9 | public LString bname;
10 | public int kind;
11 |
12 | public boolean equals(Object obj) {
13 | if(obj instanceof LUpvalue) {
14 | LUpvalue upvalue = (LUpvalue) obj;
15 | if(!(instack == upvalue.instack && idx == upvalue.idx && kind == upvalue.kind)) {
16 | return false;
17 | }
18 | if(name == upvalue.name) {
19 | return true;
20 | }
21 | return name != null && name.equals(upvalue.name);
22 | } else {
23 | return false;
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/unluac/parse/LUpvalueType.java:
--------------------------------------------------------------------------------
1 | package unluac.parse;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 |
7 | import unluac.Version;
8 |
9 | public abstract class LUpvalueType extends BObjectType {
10 |
11 | public static LUpvalueType get(Version.UpvalueType type) {
12 | switch(type) {
13 | case LUA50: return new LUpvalueType50();
14 | case LUA54: return new LUpvalueType54();
15 | default: throw new IllegalStateException();
16 | }
17 | }
18 |
19 | }
20 |
21 | class LUpvalueType50 extends LUpvalueType {
22 |
23 | @Override
24 | public LUpvalue parse(ByteBuffer buffer, BHeader header) {
25 | LUpvalue upvalue = new LUpvalue();
26 | upvalue.instack = buffer.get() != 0;
27 | upvalue.idx = 0xFF & buffer.get();
28 | upvalue.kind = -1;
29 | return upvalue;
30 | }
31 |
32 | @Override
33 | public void write(OutputStream out, BHeader header, LUpvalue object) throws IOException {
34 | out.write((byte)(object.instack ? 1 : 0));
35 | out.write(object.idx);
36 | }
37 | }
38 |
39 | class LUpvalueType54 extends LUpvalueType {
40 |
41 | @Override
42 | public LUpvalue parse(ByteBuffer buffer, BHeader header) {
43 | LUpvalue upvalue = new LUpvalue();
44 | upvalue.instack = buffer.get() != 0;
45 | upvalue.idx = 0xFF & buffer.get();
46 | upvalue.kind = 0xFF & buffer.get();
47 | return upvalue;
48 | }
49 |
50 | @Override
51 | public void write(OutputStream out, BHeader header, LUpvalue object) throws IOException {
52 | out.write((byte)(object.instack ? 1 : 0));
53 | out.write(object.idx);
54 | out.write(object.kind);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/unluac/test/LuaC.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStreamReader;
6 |
7 | public class LuaC {
8 |
9 | public static void compile(LuaSpec spec, String in, String out) throws IOException {
10 | String luac = spec.getLuaCName();
11 | luac = System.getProperty(luac, luac);
12 | if(System.getProperty("os.name").contains("Windows")) {
13 | luac = luac + ".exe";
14 | }
15 | String[] args = spec.getArgs();
16 | String[] full = new String[4 + args.length];
17 | int i = 0;
18 | full[i++] = luac;
19 | for(String arg : args) {
20 | full[i++] = arg;
21 | }
22 | full[i++] = "-o";
23 | full[i++] = out;
24 | full[i++] = in;
25 | ProcessBuilder pb = new ProcessBuilder(full);
26 | pb.directory(null);
27 | Process p = pb.start();
28 | while(true) {
29 | try {
30 | if(p.waitFor() == 0) {
31 | return;
32 | } else {
33 | BufferedReader r = new BufferedReader(new InputStreamReader(p.getErrorStream()));
34 | String line = null;
35 | do {
36 | line = r.readLine();
37 | if(line != null) {
38 | System.err.println(line);
39 | }
40 | } while(line != null);
41 |
42 | throw new IOException("luac failed on file: " + in);
43 | }
44 | } catch(InterruptedException e ) {
45 |
46 | }
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/unluac/test/LuaSpec.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | public class LuaSpec {
4 |
5 | public enum NumberFormat {
6 | DEFAULT,
7 | FLOAT,
8 | INT32,
9 | INT64
10 | }
11 |
12 | public LuaSpec() {
13 | this.isDefault = true;
14 | this.version = 0;
15 | this.numberFormat = NumberFormat.DEFAULT;
16 | this.strip = false;
17 | }
18 |
19 | public LuaSpec(int version) {
20 | this.isDefault = false;
21 | this.version = version;
22 | this.numberFormat = NumberFormat.DEFAULT;
23 | this.strip = false;
24 | }
25 |
26 | public String id() {
27 | String id = "lua";
28 | id += Integer.toHexString(version);
29 | return id;
30 | }
31 |
32 | public void setNumberFormat(NumberFormat format) {
33 | this.numberFormat = format;
34 | }
35 |
36 | public void setStrip(boolean strip) {
37 | this.strip = strip;
38 | }
39 |
40 | public String getLuaCName() {
41 | return "luac" + getVersionString() + getNumberFormatString();
42 | }
43 |
44 | public String[] getArgs() {
45 | if(strip) {
46 | return new String[] {"-s"};
47 | } else {
48 | return new String[] {};
49 | }
50 | }
51 |
52 | public boolean compatible(String filename) {
53 | int version = 0;
54 | int underscore = filename.indexOf('_');
55 | if(underscore != -1) {
56 | String prefix = filename.substring(0, underscore);
57 | try {
58 | version = Integer.parseInt(prefix, 16);
59 | } catch(NumberFormatException e) {}
60 | }
61 | return version == 0 || this.version >= version;
62 | }
63 |
64 | private String getVersionString() {
65 | if(isDefault) {
66 | return "";
67 | } else {
68 | return Integer.toHexString(version);
69 | }
70 | }
71 |
72 | private String getNumberFormatString() {
73 | switch(numberFormat) {
74 | case DEFAULT:
75 | return "";
76 | case FLOAT:
77 | return "_float";
78 | case INT32:
79 | return "_int32";
80 | case INT64:
81 | return "_int64";
82 | default:
83 | throw new IllegalStateException();
84 | }
85 | }
86 |
87 | private boolean isDefault;
88 | private int version;
89 | private NumberFormat numberFormat;
90 | private boolean strip;
91 | }
92 |
--------------------------------------------------------------------------------
/src/unluac/test/RunExtendedTests.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.nio.file.FileSystem;
6 | import java.nio.file.FileSystems;
7 | import java.nio.file.Files;
8 | import java.nio.file.Path;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | public class RunExtendedTests {
13 |
14 | private static void gatherTests(Path base, Path folder, List files) throws IOException {
15 | for(Path file : Files.newDirectoryStream(folder, "*.lua")) {
16 | String relative = base.relativize(file).toString();
17 | files.add(relative.substring(0, relative.length() - 4));
18 | }
19 | for(Path dir : Files.newDirectoryStream(folder)) {
20 | if(Files.isDirectory(dir)) {
21 | gatherTests(base, dir, files);
22 | }
23 | }
24 | }
25 |
26 | public static void main(String[] args) throws IOException {
27 | FileSystem fs = FileSystems.getDefault();
28 | Path luatest = fs.getPath(args[0]);
29 | TestReport report = new TestReport();
30 | for(int version = 0x50; version <= 0x54; version++) {
31 | LuaSpec spec = new LuaSpec(version);
32 | UnluacSpec uspec = new UnluacSpec();
33 | System.out.println(spec.id());
34 | for(Path subfolder : Files.newDirectoryStream(luatest)) {
35 | if(Files.isDirectory(subfolder) && spec.compatible(subfolder.getFileName().toString())) {
36 | List files = new ArrayList();
37 | gatherTests(subfolder, subfolder, files);
38 | TestSuite suite = new TestSuite(subfolder.getFileName().toString(), subfolder.toString() + File.separator, files.toArray(new String[files.size()]));
39 | System.out.print("\t" + subfolder.getFileName().toString());
40 | suite.run(spec, uspec, report);
41 | System.out.println();
42 | }
43 | }
44 | }
45 | report.report(System.out);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/unluac/test/RunTest.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | import java.io.IOException;
4 |
5 | public class RunTest {
6 |
7 | public static void main(String[] args) throws IOException {
8 | LuaSpec spec = new LuaSpec(0x54);
9 | UnluacSpec uspec = new UnluacSpec();
10 | //uspec.disassemble = true;
11 | if(TestFiles.suite.run(spec, uspec, args[0])) {
12 | System.exit(0);
13 | } else {
14 | System.exit(1);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/unluac/test/RunTests.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | import java.io.IOException;
4 |
5 | public class RunTests {
6 |
7 | public static void main(String[] args) throws IOException {
8 | boolean result = true;
9 | TestReport report = new TestReport();
10 | for(int version = 0x50; version <= 0x54; version++) {
11 | LuaSpec spec = new LuaSpec(version);
12 | UnluacSpec uspec = new UnluacSpec();
13 | System.out.print("lua" + Integer.toHexString(version));
14 | result = result & TestFiles.suite.run(spec, uspec, report);
15 | System.out.println();
16 | }
17 | report.report(System.out);
18 | if(result) {
19 | System.exit(0);
20 | } else {
21 | System.exit(1);
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/unluac/test/TestReport.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | import java.io.PrintStream;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | public class TestReport {
8 |
9 | private int passed = 0;
10 | private int failed = 0;
11 | private int skipped = 0;
12 |
13 | private List failedTests = new ArrayList();
14 | private List skippedTests = new ArrayList();
15 |
16 | public void report(PrintStream out) {
17 | if(failed == 0 && skipped == 0) {
18 | out.println("All tests passed!");
19 | } else {
20 | for(String failed : failedTests) {
21 | out.println("Failed: " + failed);
22 | }
23 | for(String skipped : skippedTests) {
24 | out.println("Skipped: " + skipped);
25 | }
26 | out.println("Failed " + failed + " of " + (failed + passed) + " tests, skipped " + skipped + " tests.");
27 | }
28 | }
29 |
30 | public void result(String test, TestResult result) {
31 | switch(result) {
32 | case OK:
33 | passed++;
34 | break;
35 | case FAILED:
36 | failedTests.add(test);
37 | failed++;
38 | break;
39 | case SKIPPED:
40 | skippedTests.add(test);
41 | skipped++;
42 | break;
43 | default:
44 | throw new IllegalStateException();
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/unluac/test/TestResult.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | public enum TestResult {
4 |
5 | OK, SKIPPED, FAILED
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/unluac/test/UnluacSpec.java:
--------------------------------------------------------------------------------
1 | package unluac.test;
2 |
3 | import java.io.IOException;
4 |
5 | import unluac.Main;
6 |
7 | public class UnluacSpec {
8 |
9 | public UnluacSpec() {
10 | disassemble = false;
11 | }
12 |
13 | public void run(String in, String out) throws IOException {
14 | if(!disassemble) {
15 | Main.decompile(in, out);
16 | } else {
17 | Main.disassemble(in, out);
18 | }
19 | }
20 |
21 | public boolean disassemble;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/unluac/util/Stack.java:
--------------------------------------------------------------------------------
1 | package unluac.util;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 |
6 | public class Stack {
7 |
8 | private final ArrayList data;
9 |
10 | public Stack() {
11 | data = new ArrayList();
12 | }
13 |
14 | public boolean isEmpty() {
15 | return data.isEmpty();
16 | }
17 |
18 | public T peek() {
19 | return data.get(data.size() - 1);
20 | }
21 |
22 | public T peek(int i) {
23 | return data.get(data.size() - 1 - i);
24 | }
25 |
26 | public T pop() {
27 | return data.remove(data.size() - 1);
28 | }
29 |
30 | public void push(T item) {
31 | if (data.size() > 65536) {
32 | throw new IndexOutOfBoundsException("Trying to push more than 65536 items!");
33 | }
34 | data.add(item);
35 | }
36 |
37 | public int size() {
38 | return data.size();
39 | }
40 |
41 | public void reverse() {
42 | Collections.reverse(data);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/unluac/util/StringUtils.java:
--------------------------------------------------------------------------------
1 | package unluac.util;
2 |
3 | public class StringUtils {
4 |
5 | public static String toPrintString(String s) {
6 | if(s == null) return "\"\"";
7 | StringBuilder b = new StringBuilder();
8 | b.append('"');
9 | for(int i = 0; i < s.length(); i++) {
10 | char c = s.charAt(i);
11 | int ci = (int)c;
12 | if(c == '"') {
13 | b.append("\\\"");
14 | } else if(c == '\\') {
15 | b.append("\\\\");
16 | } else if(ci >= 32 && ci <= 126) {
17 | b.append(c);
18 | } else if(c == '\n') {
19 | b.append("\\n");
20 | } else if(c == '\t') {
21 | b.append("\\t");
22 | } else if(c == '\r') {
23 | b.append("\\r");
24 | } else if(c == '\b') {
25 | b.append("\\b");
26 | } else if(c == '\f') {
27 | b.append("\\f");
28 | } else if(ci == 11) {
29 | b.append("\\v");
30 | } else if(ci == 7) {
31 | b.append("\\a");
32 | } else {
33 | b.append(String.format("\\x%02x", ci));
34 | }
35 | }
36 | b.append('"');
37 | return b.toString();
38 | }
39 |
40 | public static String fromPrintString(String s) {
41 | if(s.charAt(0) != '"') throw new IllegalStateException("Bad string " + s);
42 | if(s.charAt(s.length() - 1) != '"') throw new IllegalStateException("Bad string " + s);
43 | StringBuilder b = new StringBuilder();
44 | for(int i = 1; i < s.length() - 1; /* nothing */) {
45 | char c = s.charAt(i++);
46 | if(c == '\\') {
47 | if(i < s.length() - 1) {
48 | c = s.charAt(i++);
49 | if(c == '"') {
50 | b.append('"');
51 | } else if(c == '\\') {
52 | b.append('\\');
53 | } else if(c == 'n') {
54 | b.append('\n');
55 | } else if(c == 't') {
56 | b.append('\t');
57 | } else if(c == 'r') {
58 | b.append('\r');
59 | } else if(c == 'b') {
60 | b.append('\b');
61 | } else if(c == 'f') {
62 | b.append('\f');
63 | } else if(c == 'v') {
64 | b.append((char) 11);
65 | } else if(c == 'a') {
66 | b.append((char) 7);
67 | } else if(c == 'x') {
68 | if(i + 1 < s.length() - 1) {
69 | String digits = s.substring(i, i + 2);
70 | i += 2;
71 | b.append((char) Integer.parseInt(digits, 16));
72 | } else {
73 | return null; // error
74 | }
75 | } else {
76 | return null; // error
77 | }
78 | } else {
79 | return null; // error
80 | }
81 | } else {
82 | b.append(c);
83 | }
84 | }
85 | return b.toString();
86 | }
87 |
88 | private StringUtils() {}
89 | }
90 |
--------------------------------------------------------------------------------
/test/src/51_adjust02.lua:
--------------------------------------------------------------------------------
1 | function f(...)
2 | return (g((...)))
3 | end
--------------------------------------------------------------------------------
/test/src/51_adjust03.lua:
--------------------------------------------------------------------------------
1 | function f(...)
2 | return (g(...))
3 | end
--------------------------------------------------------------------------------
/test/src/51_ellipsis.lua:
--------------------------------------------------------------------------------
1 | local a, b, c
2 | a = ...
3 | a, b = ...
4 | a, b = ..., 2
5 | a, b, c = 1, ...
6 | a, b, c = ...
7 |
--------------------------------------------------------------------------------
/test/src/51_ellipsis02.lua:
--------------------------------------------------------------------------------
1 | local x = 0
2 | function f(...)
3 | x = g() == a or ...
4 | end
5 |
--------------------------------------------------------------------------------
/test/src/51_expression.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = x % y % z
3 | a = (x % y) % z
4 | a = x % (y % z)
5 | a = x / y % z
6 | a = x * y % z
7 | a = x % y * z
8 | a = x % y / z
9 | a = x + y % z
10 | a = (x + y) % z
11 | a = x % y - z
12 | a = x % (y - z)
13 | a = x % y ^ z
14 | a = (x % y) ^ z
15 | a = x ^ y % z
16 | a = x ^ (y % z)
17 |
--------------------------------------------------------------------------------
/test/src/51_expression03.lua:
--------------------------------------------------------------------------------
1 | local x = 0
2 | local y = 0
3 |
4 | x = x % 5
5 | x = 5 % x
6 | x = x % "5"
7 | x = "5" % x
8 | x = x % y
9 |
--------------------------------------------------------------------------------
/test/src/51_expression2.lua:
--------------------------------------------------------------------------------
1 | local a, b
2 |
3 | a = (-1) ^ b
4 | a = (-0.0) ^ b
5 | a = 2 ^ b
6 |
--------------------------------------------------------------------------------
/test/src/51_method03.lua:
--------------------------------------------------------------------------------
1 | print((arg).x)
--------------------------------------------------------------------------------
/test/src/51_string03.lua:
--------------------------------------------------------------------------------
1 | print[==[
2 | lots of garbage to start so that unluac will attempt to decompile as long string
3 | lots of garbage to start so that unluac will attempt to decompile as long string
4 | lots of garbage to start so that unluac will attempt to decompile as long string
5 | lots of garbage to start so that unluac will attempt to decompile as long string
6 | lots of garbage to start so that unluac will attempt to decompile as long string
7 | lots of garbage to start so that unluac will attempt to decompile as long string
8 | lots of garbage to start so that unluac will attempt to decompile as long string
9 | lots of garbage to start so that unluac will attempt to decompile as long string
10 | lots of garbage to start so that unluac will attempt to decompile as long string
11 | lots of garbage to start so that unluac will attempt to decompile as long string
12 | lots of garbage to start so that unluac will attempt to decompile as long string
13 | lots of garbage to start so that unluac will attempt to decompile as long string
14 | lots of garbage to start so that unluac will attempt to decompile as long string
15 | lots of garbage to start so that unluac will attempt to decompile as long string
16 | lots of garbage to start so that unluac will attempt to decompile as long string
17 | lots of garbage to start so that unluac will attempt to decompile as long string
18 | lots of garbage to start so that unluac will attempt to decompile as long string
19 | (yes, very long)
20 | disallow this kind of pipe: ]]
21 | now, make the end fail to match the next pipe without actually
22 | containing it in the string]=]==]
23 |
24 | print[=[
25 | lots of garbage to start so that unluac will attempt to decompile as long string
26 | lots of garbage to start so that unluac will attempt to decompile as long string
27 | lots of garbage to start so that unluac will attempt to decompile as long string
28 | lots of garbage to start so that unluac will attempt to decompile as long string
29 | lots of garbage to start so that unluac will attempt to decompile as long string
30 | lots of garbage to start so that unluac will attempt to decompile as long string
31 | lots of garbage to start so that unluac will attempt to decompile as long string
32 | lots of garbage to start so that unluac will attempt to decompile as long string
33 | lots of garbage to start so that unluac will attempt to decompile as long string
34 | lots of garbage to start so that unluac will attempt to decompile as long string
35 | lots of garbage to start so that unluac will attempt to decompile as long string
36 | lots of garbage to start so that unluac will attempt to decompile as long string
37 | lots of garbage to start so that unluac will attempt to decompile as long string
38 | lots of garbage to start so that unluac will attempt to decompile as long string
39 | lots of garbage to start so that unluac will attempt to decompile as long string
40 | lots of garbage to start so that unluac will attempt to decompile as long string
41 | lots of garbage to start so that unluac will attempt to decompile as long string
42 | (yes, very long)
43 | same test but for the basic pipe end: ]]=]
--------------------------------------------------------------------------------
/test/src/52_goto01.lua:
--------------------------------------------------------------------------------
1 | for x = 1, 10 do
2 | for y = 1, 10 do
3 | print(x, y)
4 | if f(x, y) then
5 | print("guard")
6 | goto eof
7 | end
8 | end
9 | end
10 | ::eof::
11 |
--------------------------------------------------------------------------------
/test/src/52_goto02.lua:
--------------------------------------------------------------------------------
1 | for x = 1, 10 do
2 | for y = 1, 10 do
3 | print(x, y)
4 | if f(x, y) then
5 | goto eof
6 | end
7 | end
8 | end
9 | ::eof::
10 |
--------------------------------------------------------------------------------
/test/src/52_goto03.lua:
--------------------------------------------------------------------------------
1 | while "outer" do
2 | for k, v in pairs(t) do
3 | if x then
4 | if y then
5 | print("guard")
6 | goto out
7 | else
8 | print("else")
9 | end
10 | else
11 | goto out
12 | end
13 | end
14 | end
15 | ::out::
16 |
--------------------------------------------------------------------------------
/test/src/53_expression.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = (x | y) | z
3 | a = x | (y | z)
4 | a = x ~ y | z
5 | a = x | y ~ z
6 | a = (x ~ y) ~ z
7 | a = x ~ (y ~ z)
8 | a = x ~ y | z
9 | a = x | y ~ z
10 | a = x ~ y & z
11 | a = x & y ~ z
12 | a = (x & y) & z
13 | a = x & (y & z)
14 | a = x ~ y & z
15 | a = x & y ~ z
16 | a = x << y & z
17 | a = x & y << z
18 | a = x >> y & z
19 | a = x & y >> z
20 | a = (x << y) << z
21 | a = x << (y << z)
22 | a = x << y & z
23 | a = x & y << z
24 | a = x << y .. z
25 | a = x .. y << z
26 | a = (x >> y) >> z
27 | a = x >> (y >> z)
28 | a = x >> y & z
29 | a = x & y >> z
30 | a = x >> y .. z
31 | a = x .. y >> z
32 | a = (x >> y) << z
33 | a = x >> (y << z)
34 | a = (x << y) >> z
35 | a = x << (y >> z)
36 | a = (x // y) // z
37 | a = x // (y // z)
38 | a = x - y // z
39 | a = x // y - z
40 | a = x + y // z
41 | a = x // y + z
42 | a = (x // y) // z
43 | a = x // (y // z)
44 | a = (x // y) / z
45 | a = x // (y / z)
46 | a = (x / y) // z
47 | a = x / (y // z)
48 | a = (~x) ~ y
49 | a = ~(x ~ y)
50 |
--------------------------------------------------------------------------------
/test/src/53_expression02.lua:
--------------------------------------------------------------------------------
1 | local x = 0
2 | local y = 0
3 |
4 | x = x | 5
5 | x = 5 | x
6 | x = x | "5"
7 | x = x | y
8 | x = "5" | x
9 | x = x & 5
10 | x = 5 & x
11 | x = x & "5"
12 | x = x & y
13 | x = "5" ~ x
14 | x = x ~ 5
15 | x = 5 ~ x
16 | x = x ~ "5"
17 | x = "5" ~ x
18 | x = x ~ y
19 |
20 | x = x << 5
21 | x = x << (-5)
22 | x = 5 << x
23 | x = (-5) << x
24 | x = x >> 5
25 | x = x >> (-5)
26 | x = 5 >> x
27 | x = (-5) >> x
28 |
29 | x = x << "5"
30 | x = "5" << x
31 | x = x << y
32 | x = x >> "5"
33 | x = "5" >> x
34 | x = x >> y
35 |
--------------------------------------------------------------------------------
/test/src/54_tbc01.lua:
--------------------------------------------------------------------------------
1 | (function()
2 | local x = 5
3 | print(x)
4 | end)()
5 | (function()
6 | local x , y = 5, 6
7 | print(x)
8 | end)()
9 | (function()
10 | local y, x = 5, 6
11 | print(x)
12 | end)()
13 | (function()
14 | local x = 5
15 | local y = 6
16 | print(x)
17 | end)()
18 |
--------------------------------------------------------------------------------
/test/src/adjust01.lua:
--------------------------------------------------------------------------------
1 | f((g()))
--------------------------------------------------------------------------------
/test/src/adjust04.lua:
--------------------------------------------------------------------------------
1 | return f()
--------------------------------------------------------------------------------
/test/src/adjust05.lua:
--------------------------------------------------------------------------------
1 | for x in (pairs(t)) do
2 | print(x)
3 | end
--------------------------------------------------------------------------------
/test/src/adjust06.lua:
--------------------------------------------------------------------------------
1 | local t = {(f())}
2 | local s = {1, 2, 3, (g())}
3 |
4 | for i = 1, 10 do
5 | print(t[i], s[i])
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/always01.lua:
--------------------------------------------------------------------------------
1 | while true do
2 | local a = {feed()}
3 | if -a == 0 then break end
4 | process(a)
5 | end
6 |
--------------------------------------------------------------------------------
/test/src/always02.lua:
--------------------------------------------------------------------------------
1 | repeat
2 | f()
3 | until false
4 |
--------------------------------------------------------------------------------
/test/src/always03.lua:
--------------------------------------------------------------------------------
1 | while true do end
2 |
--------------------------------------------------------------------------------
/test/src/always04.lua:
--------------------------------------------------------------------------------
1 | function test1()
2 | repeat
3 | repeat
4 | break
5 | until true
6 | until false
7 | end
8 |
9 | function test2()
10 | while true do
11 | repeat
12 | break
13 | until true
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/test/src/assign.lua:
--------------------------------------------------------------------------------
1 | local a = 1
2 | local b = 2
3 | local c = 3
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign01.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = x or y
3 | a = x and y
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign02.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = w and x and y and z
3 | a = w or x or y or z
4 | a = w and x or y and z
5 | a = (w or x) and (y or z)
6 | a = (b and c or d and e) and (f and g or h and i) or (j and k or l and m) and (n and o or p and q)
7 |
--------------------------------------------------------------------------------
/test/src/booleanassign03.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = d and e and f and a and g and h and i
3 | a = d or e or f or a or g or h or i
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign04.lua:
--------------------------------------------------------------------------------
1 | x = a and b
2 | x = a or b
3 | x = a and b and c and d
4 | x = a or b or c or d
5 |
--------------------------------------------------------------------------------
/test/src/booleanassign05.lua:
--------------------------------------------------------------------------------
1 | local value = thing.a or thing.b or "default"
2 | print(value)
--------------------------------------------------------------------------------
/test/src/booleanassign06.lua:
--------------------------------------------------------------------------------
1 | if not thing.a and not thing.b then
2 | local value = "default"
3 | end
--------------------------------------------------------------------------------
/test/src/booleanassign07.lua:
--------------------------------------------------------------------------------
1 | if not thing.a and not thing.b then
2 | side_effects()
3 | local value = "default"
4 | end
--------------------------------------------------------------------------------
/test/src/booleanassign08.lua:
--------------------------------------------------------------------------------
1 | local value = "initial"
2 | print(value)
3 | value = thing.a or thing.b or "default"
4 | print(value)
--------------------------------------------------------------------------------
/test/src/booleanassign09.lua:
--------------------------------------------------------------------------------
1 | local result = a < b and not c
2 | print(result)
--------------------------------------------------------------------------------
/test/src/booleanassign10.lua:
--------------------------------------------------------------------------------
1 | local x
2 | if x == nil then
3 | x = (not y) or (z == w)
4 | end
5 | print(x)
--------------------------------------------------------------------------------
/test/src/booleanassign11.lua:
--------------------------------------------------------------------------------
1 | local a, b = "asdf", "qwer"
2 | local val = not (a and b)
3 | print(tostring(val))
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign12.lua:
--------------------------------------------------------------------------------
1 | local x = x or a == b
2 | x = true
3 |
4 | local y = x or a ~= b
5 | y = true
6 |
7 | local z = a == b or c == d
8 | z = true
9 |
--------------------------------------------------------------------------------
/test/src/booleanassign13.lua:
--------------------------------------------------------------------------------
1 | local a, b, c, d, e, g
2 | a = f() or a
3 | b = f() or b
4 | if e then
5 | d = f() or d
6 | e = f() or e
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/booleanassign14.lua:
--------------------------------------------------------------------------------
1 | local a, b, c, d, e, g
2 |
3 | a = g or a
4 | b = g or b
5 | if e then
6 | d = g or d
7 | e = g or e
8 | end
9 |
--------------------------------------------------------------------------------
/test/src/booleanassign15.lua:
--------------------------------------------------------------------------------
1 | local x = f()
2 | g = x or nil
3 |
--------------------------------------------------------------------------------
/test/src/booleanassign16.lua:
--------------------------------------------------------------------------------
1 | local a, b = f()
2 | local c = not a and 1 or b + 1
3 | print(c)
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign17.lua:
--------------------------------------------------------------------------------
1 | local x, y
2 | x = x and f(x,0,y and 1 or 2,"asdf") or 3
3 |
--------------------------------------------------------------------------------
/test/src/booleanassign18.lua:
--------------------------------------------------------------------------------
1 | local t, u, i = f()
2 | local x, y = t[i] or 1, u[i] or 2
3 | print(x, y)
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign19.lua:
--------------------------------------------------------------------------------
1 | local t, u, v, i = f()
2 | local x, y, z = t[i] or 1, u[i] or 2, v[i] or 3
3 | print(x, y, z)
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign20.lua:
--------------------------------------------------------------------------------
1 | local x, y = f()
2 | if not y then
3 | x, y = a, b
4 | end
5 | print(x, y)
6 |
--------------------------------------------------------------------------------
/test/src/booleanassign21.lua:
--------------------------------------------------------------------------------
1 | local x
2 | if a then
3 | print("if")
4 | if not x then
5 | x = b
6 | end
7 | else
8 | print("else")
9 | end
10 |
--------------------------------------------------------------------------------
/test/src/booleanassign22.lua:
--------------------------------------------------------------------------------
1 | local x
2 | if a then
3 | if not x then
4 | x = f()
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/booleanassign23.lua:
--------------------------------------------------------------------------------
1 | local a = x == 0 or {1, 2, 3}
2 | local b = x == 1 or {a = 1, b = 3, c = 3}
3 | print(a, b)
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign24.lua:
--------------------------------------------------------------------------------
1 | local upvalue = 0
2 | local a = x == 0 or function()
3 | print(upvalue)
4 | end
5 |
--------------------------------------------------------------------------------
/test/src/booleanassign25.lua:
--------------------------------------------------------------------------------
1 | local upvalue1 = 0
2 | function outer()
3 | local upvalue2 = 1
4 | local upvalue3 = 2
5 | local x = f()
6 | local a = x == 0 or function()
7 | print(upvalue1, upvalue2, upvalue3)
8 | end
9 | return a
10 | end
--------------------------------------------------------------------------------
/test/src/booleanassign26.lua:
--------------------------------------------------------------------------------
1 | local x = f()
2 | x = not x and 0 or t[x] or x
3 |
--------------------------------------------------------------------------------
/test/src/booleanassign27.lua:
--------------------------------------------------------------------------------
1 | local x, y
2 | x, y = x and x < 2 and x or nil, y and y < 3 and y or nil
3 | print(x,y)
4 |
--------------------------------------------------------------------------------
/test/src/booleanassign28.lua:
--------------------------------------------------------------------------------
1 | local x = a and (f() or c==0)
2 | print(x)
3 |
--------------------------------------------------------------------------------
/test/src/booleanexpression01.lua:
--------------------------------------------------------------------------------
1 | print(a or b)
2 | print(a and b)
3 |
--------------------------------------------------------------------------------
/test/src/booleanexpression02.lua:
--------------------------------------------------------------------------------
1 | print(a and b, a or b)
2 |
--------------------------------------------------------------------------------
/test/src/booleanexpression03.lua:
--------------------------------------------------------------------------------
1 | print(x == 0 or a.first and a.record.field == value)
--------------------------------------------------------------------------------
/test/src/booleanexpression04.lua:
--------------------------------------------------------------------------------
1 | print((not x) and (a == b) and (y < z))
--------------------------------------------------------------------------------
/test/src/booleanexpression05.lua:
--------------------------------------------------------------------------------
1 | print(a == b and (c == d or c == e) and f == g)
--------------------------------------------------------------------------------
/test/src/booleanexpression06.lua:
--------------------------------------------------------------------------------
1 | print(not a and b)
--------------------------------------------------------------------------------
/test/src/booleanexpression07.lua:
--------------------------------------------------------------------------------
1 | function obj.method(self, x)
2 | self = {name = "asdf"}
3 | self.field = setmetatable(x and table.copy(x) or {}, self)
4 | t[self.name] = self.field
5 | return self
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/booleanexpression08.lua:
--------------------------------------------------------------------------------
1 | if a and b or c(x == y or a or 5) and z then
2 | print("hello")
3 | end
4 |
--------------------------------------------------------------------------------
/test/src/booleanexpression09.lua:
--------------------------------------------------------------------------------
1 | for k, v in pairs(t) do
2 | if f() and g(a or b) then
3 | print("yes")
4 | else
5 | print("no")
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/booleanexpression10.lua:
--------------------------------------------------------------------------------
1 | print((x or {}).__tostring)
2 |
--------------------------------------------------------------------------------
/test/src/booleanmultiassign01.lua:
--------------------------------------------------------------------------------
1 | local a, b
2 | a, b = a and b, a or b
3 | a, b = a or b, a and b
4 | a, b = b and a, b or a
5 | a, b = b or a, b and a
6 | a, b = x and y, x or y
7 |
--------------------------------------------------------------------------------
/test/src/booleanmultiassign02.lua:
--------------------------------------------------------------------------------
1 | local q
2 | local n, t = f(), q or s[1]
3 | print(n, t)
4 |
--------------------------------------------------------------------------------
/test/src/booleanselfassign01.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = a or x
3 | a = a and x
4 | y = y or x
5 | y = y and x
6 |
--------------------------------------------------------------------------------
/test/src/break01.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | for i=1,10 do
3 | if a then
4 | print("okay")
5 | elseif b then
6 | print("b")
7 | break
8 | else
9 | print("c")
10 | break
11 | end
12 | end
13 | else
14 | print("else")
15 | end
16 | print("done")
17 |
--------------------------------------------------------------------------------
/test/src/break02.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | for i=1,10 do
3 | if a then
4 | print("okay")
5 | elseif b then
6 | print("b")
7 | break
8 | else
9 | break
10 | end
11 | end
12 | else
13 | print("else")
14 | end
15 | print("done")
16 |
--------------------------------------------------------------------------------
/test/src/break03.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | for i=1,10 do
3 | if a then
4 | print("okay")
5 | elseif b then
6 | break
7 | elseif c then
8 | dontbreak()
9 | elseif d then
10 | alsodontbreak()
11 | for k = 1, 10 do print("breakable loop") end
12 | else
13 | break
14 | end
15 | print("next")
16 | end
17 | else
18 | print("else")
19 | end
20 | print("done")
21 |
--------------------------------------------------------------------------------
/test/src/break04.lua:
--------------------------------------------------------------------------------
1 | local a, b = 5, 5
2 | while a < b do
3 | print("a")
4 | a, b = a / b * j, fmod(a, b) * k
5 | if b > j then
6 | print("b")
7 | if x == nil then
8 | break
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/test/src/break05.lua:
--------------------------------------------------------------------------------
1 | for k, v in iter() do
2 | if a then
3 | if b then
4 | return
5 | elseif c then
6 | print(c)
7 | elseif d then
8 | print(d)
9 | end
10 | end
11 | break
12 | end
13 |
--------------------------------------------------------------------------------
/test/src/break06.lua:
--------------------------------------------------------------------------------
1 | while x < 10 do
2 | if a == 1 then
3 | print(1)
4 | end
5 | if b == 1 then
6 | break
7 | end
8 | if c == 1 then
9 | print(1)
10 | else
11 | break
12 | end
13 | if a == 2 then
14 | print(2)
15 | end
16 | if b == 2 then
17 | break
18 | end
19 | if c == 2 then
20 | print(2)
21 | else
22 | break
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/test/src/break07.lua:
--------------------------------------------------------------------------------
1 | while x do
2 | if b then
3 | guard()
4 | if c then
5 | print("c")
6 | break
7 | end
8 | guard()
9 | else
10 | print("not b")
11 | break
12 | end
13 | guard()
14 | end
--------------------------------------------------------------------------------
/test/src/break08.lua:
--------------------------------------------------------------------------------
1 | for i = 1, 10 do
2 | if f(i) then
3 | break
4 | end
5 | if g(i) then
6 | h()
7 | else
8 | break
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/test/src/break09.lua:
--------------------------------------------------------------------------------
1 | for k, v in pairs(t) do
2 | if x then
3 | if y then
4 | print("guard")
5 | break
6 | else
7 | print("else")
8 | end
9 | else
10 | break
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test/src/break10.lua:
--------------------------------------------------------------------------------
1 | local a
2 | while x do
3 | a = b or c
4 | -- testset redirected by break
5 | break
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/close01.lua:
--------------------------------------------------------------------------------
1 | for _, v in pairs(t) do
2 | local x = f()
3 | if x then
4 | f(function() return v end)
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/close02.lua:
--------------------------------------------------------------------------------
1 | for _, v in pairs(t) do
2 | local x = f()
3 | if x then
4 | f(function() return v end)
5 | else
6 | g(function() return v end)
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/src/close03.lua:
--------------------------------------------------------------------------------
1 | for _, request in pairs(t) do
2 | local finished = false
3 | request:executeWithCallback(function() finished = true end)
4 | while not finished do Sleep() end
5 | -- CLOSE
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/close04.lua:
--------------------------------------------------------------------------------
1 | repeat
2 | local x = f()
3 | table.insert(t, function() return x end)
4 | until not x
5 |
--------------------------------------------------------------------------------
/test/src/closure.lua:
--------------------------------------------------------------------------------
1 | f = function(a, b)
2 | local c = a + b
3 | return c ^ 2
4 | end
5 | print(f(3, 4))
6 |
--------------------------------------------------------------------------------
/test/src/combinebassign01.lua:
--------------------------------------------------------------------------------
1 | local x
2 | x = x == nil or x
3 | print(x)
4 |
--------------------------------------------------------------------------------
/test/src/combinebassign02.lua:
--------------------------------------------------------------------------------
1 | local a, b
2 | a = b ~= nil and f(b) or "else"
3 |
4 | a = b == nil and f(b) or "else"
5 |
6 | a = (b ~= nil or f(b)) and "else"
7 |
8 | a = (b == nil or f(b)) and "else"
9 |
--------------------------------------------------------------------------------
/test/src/combinebassign03.lua:
--------------------------------------------------------------------------------
1 | local t, x
2 | if a then
3 | x = t[1] == "ref" and t[2]
4 | else
5 | print("else")
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/combinebassign04.lua:
--------------------------------------------------------------------------------
1 | local f, t
2 | do
3 | local x = t[2] == "sym" and f()
4 | if x then
5 | return 0
6 | end
7 | end
8 | return 1
9 |
--------------------------------------------------------------------------------
/test/src/combinebassign05.lua:
--------------------------------------------------------------------------------
1 | print("guard")
2 | local a, b, c
3 | local d =
4 | a.cond or
5 | (type(b) == "table" and b) or
6 | (type(b) == "string" and f(b, c or "str"))
7 |
--------------------------------------------------------------------------------
/test/src/combinebassign07.lua:
--------------------------------------------------------------------------------
1 | local a, b, c, d, e, f
2 | a = b == 0 and c or (d + e) * f
3 |
--------------------------------------------------------------------------------
/test/src/combinebexpression01.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = b < c or d < e or f
3 |
--------------------------------------------------------------------------------
/test/src/combinebexpression02.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = b or c or d == e
3 |
--------------------------------------------------------------------------------
/test/src/combinebexpression03.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = b or c == d or e
3 |
--------------------------------------------------------------------------------
/test/src/combinebexpression04.lua:
--------------------------------------------------------------------------------
1 | print(a or b or c == d)
2 | print(a or b == c or d)
3 | print(a and b == c or d)
4 | print(a or b == c and d)
5 | print(a or b ~= c or d)
6 | print(a == b or c or d)
7 | print(a < b and c or d)
8 | print(a ~= b or c and d)
9 | print(a == b and c and d)
10 |
--------------------------------------------------------------------------------
/test/src/combinebexpression05.lua:
--------------------------------------------------------------------------------
1 | local a, aa, b, bb = g()
2 |
3 | return (a == b) and f(aa, bb) or a < b
4 |
--------------------------------------------------------------------------------
/test/src/combinebexpression06.lua:
--------------------------------------------------------------------------------
1 | local a, aa, b, bb = g()
2 |
3 | return (a == b) and f(aa, bb) or a or b
4 |
--------------------------------------------------------------------------------
/test/src/combinebexpression07.lua:
--------------------------------------------------------------------------------
1 | local t, s
2 | function f(a, b)
3 | return (a == b and true) or t[a] and t[b] and t[a] == t[b]
4 | end
--------------------------------------------------------------------------------
/test/src/compare01.lua:
--------------------------------------------------------------------------------
1 | local x = f()
2 | if x < 5 then
3 | f()
4 | end
5 | if x < 5.0 then
6 | f()
7 | end
8 | if x < -5 then
9 | f()
10 | end
11 | if x < -5.0 then
12 | f()
13 | end
14 | if x > 5 then
15 | f()
16 | end
17 | if x > 5.0 then
18 | f()
19 | end
20 | if x > -5 then
21 | f()
22 | end
23 | if x > -5.0 then
24 | f()
25 | end
26 | if x <= 5 then
27 | f()
28 | end
29 | if x <= 5.0 then
30 | f()
31 | end
32 | if x <= -5 then
33 | f()
34 | end
35 | if x <= -5.0 then
36 | f()
37 | end
38 | if x >= 5 then
39 | f()
40 | end
41 | if x >= 5.0 then
42 | f()
43 | end
44 | if x >= -5 then
45 | f()
46 | end
47 | if x >= -5.0 then
48 | f()
49 | end
50 | if x == 5 then
51 | f()
52 | end
53 | if x == 5.0 then
54 | f()
55 | end
56 | if x == -5 then
57 | f()
58 | end
59 | if x == -5.0 then
60 | f()
61 | end
62 | if x == "5" then
63 | f()
64 | end
65 |
66 | if 5 < x then
67 | f()
68 | end
69 | if 5.0 < x then
70 | f()
71 | end
72 | if -5 < x then
73 | f()
74 | end
75 | if -5.0 < x then
76 | f()
77 | end
78 | if 5 > x then
79 | f()
80 | end
81 | if 5.0 > x then
82 | f()
83 | end
84 | if -5 > x then
85 | f()
86 | end
87 | if -5.0 > x then
88 | f()
89 | end
90 | if 5 <= x then
91 | f()
92 | end
93 | if 5.0 <= x then
94 | f()
95 | end
96 | if -5 <= x then
97 | f()
98 | end
99 | if -5.0 <= x then
100 | f()
101 | end
102 | if 5 >= x then
103 | f()
104 | end
105 | if 5.0 >= x then
106 | f()
107 | end
108 | if -5 >= x then
109 | f()
110 | end
111 | if -5.0 >= x then
112 | f()
113 | end
114 | if 5 == x then
115 | f()
116 | end
117 | if 5.0 == x then
118 | f()
119 | end
120 | if -5 == x then
121 | f()
122 | end
123 | if -5.0 == x then
124 | f()
125 | end
126 | if "5" == x then
127 | f()
128 | end
129 |
--------------------------------------------------------------------------------
/test/src/compareassign01.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = x < y
3 |
--------------------------------------------------------------------------------
/test/src/compareassign02.lua:
--------------------------------------------------------------------------------
1 | local x
2 | if not x then
3 | guard()
4 | x = g < 3
5 | end
6 |
--------------------------------------------------------------------------------
/test/src/compareexpression.lua:
--------------------------------------------------------------------------------
1 | print(x == y)
2 | print(x < y)
3 | print(x <= y)
4 |
--------------------------------------------------------------------------------
/test/src/compareexpression02.lua:
--------------------------------------------------------------------------------
1 | if x and y then
2 | return x < y
3 | end
4 | print("end")
5 |
--------------------------------------------------------------------------------
/test/src/compareorder01.lua:
--------------------------------------------------------------------------------
1 | if a < b then
2 | print("a < b")
3 | end
4 | if b > a then
5 | print("b > a")
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/compareorder02.lua:
--------------------------------------------------------------------------------
1 | -- In the case of two constants:
2 | -- comparison order is impossible to reproduce from bytecode
3 | -- this case seems unlikely to occur in production code though
4 | -- perhaps guess by the index of the constants?
5 | -- (that could work if both constants are fresh)
6 | if 1 < 2 then
7 | print("1 < 2")
8 | end
9 | if 2 > 1 then
10 | print("2 > 1")
11 | end
12 |
--------------------------------------------------------------------------------
/test/src/compareorder03.lua:
--------------------------------------------------------------------------------
1 | if a < 2 then
2 | print("a < 2")
3 | end
4 | if 2 > a then
5 | print("2 > a")
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/compareorder04.lua:
--------------------------------------------------------------------------------
1 | print("begin")
2 | if not (math.random(100) > chance) then
3 | print("then")
4 | end
5 | print("end")
--------------------------------------------------------------------------------
/test/src/compareorder05.lua:
--------------------------------------------------------------------------------
1 | print("begin")
2 | if math.random(100) <= chance then
3 | print("then")
4 | end
5 | print("end")
--------------------------------------------------------------------------------
/test/src/compareorder06.lua:
--------------------------------------------------------------------------------
1 | if f1() == "a" then
2 | g()
3 | end
4 | if "b" == f2() then
5 | g()
6 | end
7 | if f3() ~= "c" then
8 | g()
9 | end
10 | if "d" ~= f4() then
11 | g()
12 | end
13 |
--------------------------------------------------------------------------------
/test/src/compareorder07.lua:
--------------------------------------------------------------------------------
1 | if 1 == 1.0 then
2 | f()
3 | end
4 | if 2.0 == 2 then
5 | f()
6 | end
7 | if 3 < 3.0 then
8 | f()
9 | end
10 | if 4.0 < 4 then
11 | f()
12 | end
13 | if 5 > 5.0 then
14 | f()
15 | end
16 | if 6.0 > 6 then
17 | f()
18 | end
19 | if 7 <= 7.0 then
20 | f()
21 | end
22 | if 8.0 <= 8 then
23 | f()
24 | end
25 | if 9 >= 9.0 then
26 | f()
27 | end
28 | if 10.0 >= 10 then
29 | f()
30 | end
31 | if 11 ~= 11.0 then
32 | f()
33 | end
34 | if 12.0 ~= 12 then
35 | f()
36 | end
37 | if "13" == 13 then
38 | f()
39 | end
40 | if 14 == "14" then
41 | f()
42 | end
43 | if "15" == 15.0 then
44 | f()
45 | end
46 | if 16.0 == "16" then
47 | f()
48 | end
49 | if "17" ~= 17 then
50 | f()
51 | end
52 | if 18 ~= "18" then
53 | f()
54 | end
55 | if "19" ~= 19.0 then
56 | f()
57 | end
58 | if 20.0 ~= "20" then
59 | f()
60 | end
61 |
--------------------------------------------------------------------------------
/test/src/compareorder08.lua:
--------------------------------------------------------------------------------
1 | if left1("common1") == "common1" then
2 | f()
3 | end
4 | if "common2" == right2("common2") then
5 | f()
6 | end
7 | if left3("common3") < "common3" then
8 | f()
9 | end
10 | if "common4" > right4("common4") then
11 | f()
12 | end
13 | if "left5" == "right5" then
14 | f()
15 | end
16 |
--------------------------------------------------------------------------------
/test/src/complexassign01.lua:
--------------------------------------------------------------------------------
1 | if buffer then
2 | print("hello")
3 | end
4 | local single1 = 1
5 | local single2 = 2
6 | local single3 = 3
7 | if buffer then
8 | print("hello")
9 | end
10 | local single4 = 4
11 | local single5 = 5
12 | local single6 = 6
13 |
--------------------------------------------------------------------------------
/test/src/complexassign02.lua:
--------------------------------------------------------------------------------
1 | if buffer then
2 | print("hello")
3 | end
4 | local expr1 = a + b + c + d
5 | local expr2 = expr1 + a + b + c + d
6 | local expr3 = a + b + c + d + expr2
7 |
--------------------------------------------------------------------------------
/test/src/complexassign03.lua:
--------------------------------------------------------------------------------
1 | if buffer then
2 | print("hello")
3 | end
4 | local multi1a, multi1b, multi1c = 1, 2, 3
5 | local multi2a, multi2b, multi2c = multi_return()
6 | local multi3a, multi3b, multi3c = multi_return(x, y, z)
7 |
--------------------------------------------------------------------------------
/test/src/condition.lua:
--------------------------------------------------------------------------------
1 | if a == b and c == d then
2 | f()
3 | end
4 | if a == b or c == d then
5 | f()
6 | end
7 | if a < b then
8 | f()
9 | end
10 | if a <= b then
11 | f()
12 | end
13 | if not a then
14 | f()
15 | end
16 |
--------------------------------------------------------------------------------
/test/src/condition02.lua:
--------------------------------------------------------------------------------
1 | local a, b = f()
2 | local test = b == 0
3 | if a and ((test and not a.x) or (not test and not a.y)) then
4 | print(a)
5 | end
6 |
--------------------------------------------------------------------------------
/test/src/condition03.lua:
--------------------------------------------------------------------------------
1 | local a
2 | local b
3 | local c, d
4 | local e
5 | if x ~= a and not t[e] then
6 | local f = ((d == x) and c or x) - 1
7 | print("more")
8 | end
9 |
--------------------------------------------------------------------------------
/test/src/control01.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | while b do
3 | f()
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/test/src/control02.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | local x = 3
3 | if b then
4 | print(a, b)
5 | end
6 | print(x)
7 | end
--------------------------------------------------------------------------------
/test/src/control03.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | local x = 3
3 | if b then
4 | print(a, b)
5 | end
6 | end
--------------------------------------------------------------------------------
/test/src/control04.lua:
--------------------------------------------------------------------------------
1 | local y
2 | if x then
3 | while y do
4 | print("hello")
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/control05.lua:
--------------------------------------------------------------------------------
1 | for i = 1, 10 do
2 | local x = f()
3 | if a then
4 | local y = g()
5 | if b then
6 | print(b)
7 | end
8 | break
9 | end
10 | end
--------------------------------------------------------------------------------
/test/src/control06.lua:
--------------------------------------------------------------------------------
1 | for item in iter() do
2 | if complicated_condition() then
3 | f()
4 | if additional() then
5 | g()
6 | end
7 | break
8 | end
9 | end
--------------------------------------------------------------------------------
/test/src/control07.lua:
--------------------------------------------------------------------------------
1 | repeat
2 | repeat
3 | f()
4 | until b
5 | g()
6 | until a
--------------------------------------------------------------------------------
/test/src/declare.lua:
--------------------------------------------------------------------------------
1 | local a, b, c
2 | a = 1
3 | b = 2
4 | local d
5 | d = 3
6 | f()
7 | summon = function(bid, count)
8 | if type(bid) == "string" then
9 | bid = beings[bid].nid
10 | end
11 | local last_being
12 | for i = 1, count or 1 do
13 | last_being = Level.drop_being(bid, Level.empty_coord())
14 | end
15 | return last_being
16 | end
17 | f()
18 | --a, b = a and b, a or b
19 | f()
20 |
21 | --[[while a < c do
22 | if(a == b) then
23 | a = c
24 | else
25 | break
26 | end
27 | end]] --TODO
28 |
29 | --[[while a < c do
30 | if a==b then
31 | c = 3
32 | if c == b then
33 | d = 6
34 | end
35 | end
36 | end]] --FIXED!
37 |
38 | --[[if a==b then
39 | if c==d then
40 | a = 4
41 | if a == c then
42 | a, b = 2, 3
43 | end
44 | end
45 | else
46 | c = 6
47 | end]] --FIXED!
48 |
49 | --[[while a == b do
50 | if c == d then
51 | c = 6
52 | end
53 | break
54 | end]] --OKAY because compiles as
55 | --[[while a == b and c == d do
56 | c = 6
57 | break
58 | end]]
59 |
60 | a, b, c, d = b, c, d, a
61 | return f()
--------------------------------------------------------------------------------
/test/src/declare02.lua:
--------------------------------------------------------------------------------
1 | print("begin")
2 | local x, y, z
3 | print("begin")
4 | local a, b, c
5 | c = 4
6 | print(c)
7 | local d, e, f
8 | d = 8
9 | print(d)
--------------------------------------------------------------------------------
/test/src/declare03.lua:
--------------------------------------------------------------------------------
1 | print("begin")
2 | local x, y, z
--------------------------------------------------------------------------------
/test/src/declare04.lua:
--------------------------------------------------------------------------------
1 | local upvalue
2 | function f()
3 | local a, b
4 | upvalue = nil
5 | end
6 |
--------------------------------------------------------------------------------
/test/src/declare05.lua:
--------------------------------------------------------------------------------
1 | t["goto"] = function(x, y)
2 | if x then y() end
3 | end
4 |
--------------------------------------------------------------------------------
/test/src/doend01.lua:
--------------------------------------------------------------------------------
1 | do
2 | local a = 512
3 | print(a)
4 | end
5 | do
6 | local b = 255
7 | print(b)
8 | end
--------------------------------------------------------------------------------
/test/src/doend02.lua:
--------------------------------------------------------------------------------
1 | while x do
2 | local v, w = 0
3 | print(w, v)
4 | end
--------------------------------------------------------------------------------
/test/src/doend03.lua:
--------------------------------------------------------------------------------
1 | for x, y in pairs(t) do
2 | local v, w = 0
3 | print(w, v)
4 | end
--------------------------------------------------------------------------------
/test/src/doend04.lua:
--------------------------------------------------------------------------------
1 | for z=1,6 do
2 | local v, w = 0
3 | print(w, v, z)
4 | end
--------------------------------------------------------------------------------
/test/src/doend05.lua:
--------------------------------------------------------------------------------
1 | repeat
2 | local v, w = 0
3 | print(w, v)
4 | until x < 100
5 |
--------------------------------------------------------------------------------
/test/src/doend06.lua:
--------------------------------------------------------------------------------
1 | while true do
2 | local v, w = 0
3 | print(w, v)
4 | end
5 |
--------------------------------------------------------------------------------
/test/src/doend07.lua:
--------------------------------------------------------------------------------
1 | print("guard")
2 | local a
3 | do
4 | local b
5 | print("guard")
6 | b = f()
7 | a = b
8 | end
9 | return a
10 |
--------------------------------------------------------------------------------
/test/src/doend08.lua:
--------------------------------------------------------------------------------
1 | print("guard")
2 | local a
3 | do
4 | local b
5 | do
6 | local c
7 | print("guard")
8 | c = f()
9 | b = c
10 | end
11 | a = b
12 | end
13 | return a
14 |
--------------------------------------------------------------------------------
/test/src/ellipsis03.lua:
--------------------------------------------------------------------------------
1 | function f(...)
2 | return arg
3 | end
4 |
--------------------------------------------------------------------------------
/test/src/else01.lua:
--------------------------------------------------------------------------------
1 | if z == nil and w == nil then
2 | if x == y then
3 | result = true
4 | elseif x == z then
5 | print(z)
6 | if n then
7 | print(n)
8 | end
9 | else
10 | error()
11 | end
12 | else
13 | error()
14 | end
15 |
--------------------------------------------------------------------------------
/test/src/else02.lua:
--------------------------------------------------------------------------------
1 | for k, v in ipairs(t) do
2 | if f(k, v) then
3 | guard()
4 | if g(k, v) then
5 | guard()
6 | if h(k, v) then
7 | f2()
8 | else
9 | -- empty
10 | end
11 | else
12 | -- empty
13 | end
14 | else
15 | -- empty
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/test/src/else03.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | print("guard")
3 | if y then
4 | if z then
5 | print("z")
6 | else
7 | print("not z")
8 | end
9 | end
10 | elseif a then
11 | print("a")
12 | end
13 |
--------------------------------------------------------------------------------
/test/src/else04.lua:
--------------------------------------------------------------------------------
1 | local a
2 | if x then
3 | a = b or c
4 | -- testset redirected by else
5 | else
6 | print("else")
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/else05.lua:
--------------------------------------------------------------------------------
1 | local a
2 | if x then
3 | a = b or c + d
4 | -- testset redirected by else (with MMBIN*)
5 | else
6 | print("else")
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/else06.lua:
--------------------------------------------------------------------------------
1 | local x
2 | if test then
3 | print("guard")
4 | x = a or b
5 | -- redirect (5.4)
6 | else
7 | print("guard")
8 | x = c or d
9 | end
10 |
--------------------------------------------------------------------------------
/test/src/else07.lua:
--------------------------------------------------------------------------------
1 | local x
2 | if t then
3 | x = y or 3
4 | else
5 | x = (y == 0)
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/expression.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = x + y + z
3 | a = x + (y + z)
4 | a = x + y - z
5 | a = x - y + z
6 | a = x - y - z
7 | a = x - (y - z)
8 | a = x * y * z
9 | a = x * (y * z)
10 | a = x + y * z
11 | a = (z + y) / z
12 | a = x / (y + z)
13 | a = x ^ y ^ z
14 | a = (x ^ y) ^ z
15 | a = x .. y .. z
16 | a = (x .. y) .. z
17 |
--------------------------------------------------------------------------------
/test/src/expression02.lua:
--------------------------------------------------------------------------------
1 | local x = 0
2 | local y = 0
3 |
4 | x = x + 5
5 | x = x - 5
6 | x = 5 + x
7 | x = (-5) + x
8 | x = 5 - x
9 | x = (-5) - x
10 | x = x + "5"
11 | x = "5" + x
12 | x = x - "5"
13 | x = "5" - x
14 | x = x + y
15 | x = x - y
16 | x = x * 5
17 | x = 5 * x
18 | x = x * "5"
19 | x = "5" * x
20 | x = x * y
21 | x = x / 5
22 | x = 5 / x
23 | x = x / "5"
24 | x = "5" / x
25 | x = x / y
26 | x = x ^ 5
27 | x = 5 ^ x
28 | x = x ^ "5"
29 | x = "5" ^ x
30 | x = x ^ y
31 | x = x .. 5
32 | x = 5 .. x
33 | x = x .. "5"
34 | x = "5" .. x
35 | x = x .. y
36 |
--------------------------------------------------------------------------------
/test/src/final01.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | do return end
3 | print(x)
4 | end
--------------------------------------------------------------------------------
/test/src/final02.lua:
--------------------------------------------------------------------------------
1 | while x > 0 do
2 | do break end
3 | print(x)
4 | x = x - 1
5 | end
--------------------------------------------------------------------------------
/test/src/functioncall.lua:
--------------------------------------------------------------------------------
1 | local a, b, c
2 | a = f(1, 2, 3)
3 | a = f(x, y, z)
4 | a, b = f(1, 2, 3)
5 | a, b, c = 1, f(1, 2, 3)
6 | a, b, c = f(1, 2, 3), 1, 2
7 | a = f(g())
8 |
--------------------------------------------------------------------------------
/test/src/if01.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | if {} then
3 | print("x")
4 | end
5 | end
--------------------------------------------------------------------------------
/test/src/if02.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | for _, v in ipairs(mylist) do
3 | print(v)
4 | end
5 | if b then
6 | print("done")
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/src/if03.lua:
--------------------------------------------------------------------------------
1 | local t = {}
2 | do_work(t)
3 |
4 | if not t.x then
5 | t.x = f()
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/if04.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | print("separate")
3 | if x == y then
4 | -- empty
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/if05.lua:
--------------------------------------------------------------------------------
1 | local t = {}
2 | if a then
3 | t[1] = 0 -- a and b can't be combined
4 | if b then
5 | print("middle", t)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/if06.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | print("a")
3 | else
4 | local x
5 | if b then
6 | if c then
7 | -- empty
8 | else
9 | print("b,~c")
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test/src/if07.lua:
--------------------------------------------------------------------------------
1 | return function( self )
2 | local x = 0
3 | local z = false
4 | if a then
5 | if x == 1 then
6 | self.y = "1"
7 | elseif math.random(100) <= self.x then
8 | self.y = "2"
9 | end
10 | end
11 | z = false
12 | return self.y
13 | end
14 |
--------------------------------------------------------------------------------
/test/src/ifthen.lua:
--------------------------------------------------------------------------------
1 | local a, b
2 | if a then
3 | print(a)
4 | end
5 | if a == b then
6 | local c = a + b
7 | print(c ^ 2)
8 | end
9 | if a and b and x and y then
10 | print(a + x, b + y)
11 | end
12 | if a or b or x or y then
13 | print(a * x, b * y)
14 | end
15 | if (a or b) and (x or y) then
16 | print(a * x, b - y)
17 | end
18 |
--------------------------------------------------------------------------------
/test/src/ifthenelse.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | f()
3 | else
4 | g()
5 | end
6 | if b then
7 | f()
8 | if a then
9 | g()
10 | end
11 | else
12 | h()
13 | end
14 | if a then
15 | if b then
16 | f()
17 | else
18 | h()
19 | end
20 | g()
21 | end
22 |
--------------------------------------------------------------------------------
/test/src/inlineconstant01.lua:
--------------------------------------------------------------------------------
1 | ("string"):method();
2 | ("string")();
3 | (1234):method();
4 | (1234)();
5 | (nil):method();
6 | (nil)();
7 | (true):method();
8 | (true)();
9 |
--------------------------------------------------------------------------------
/test/src/inlinefunction01.lua:
--------------------------------------------------------------------------------
1 | (function() print "hello" end)()
--------------------------------------------------------------------------------
/test/src/inlinefunction02.lua:
--------------------------------------------------------------------------------
1 | -- yes, this doesn't work, but it is syntactically valid
2 | (function(self, s) print(s) end):p("hello")
3 |
--------------------------------------------------------------------------------
/test/src/literal.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = 5
3 | a = 2.5
4 | a = "hello"
5 | a = false
6 | a = true
7 | a = nil
8 |
--------------------------------------------------------------------------------
/test/src/literallist.lua:
--------------------------------------------------------------------------------
1 | x = {1,
2 | 2,
3 | 7,
4 | "frog",
5 | z,
6 | y * w,
7 | 99}
8 |
--------------------------------------------------------------------------------
/test/src/localbooleanassign.lua:
--------------------------------------------------------------------------------
1 | local armor = being.eq.armor
2 | local boots = being.eq.boots
3 | if not armor and not boots then
4 | being:msg( "You have no armor to fix! Nothing happens." )
5 | return
6 | end
7 | local damaged_armor = armor and armor:is_damaged()
8 | local damaged_boots = boots and boots:is_damaged()
9 | if not damaged_armor and not damaged_boots then
10 | being:msg( "You have no armor that needs fixing! Nothing happens." )
11 | return
12 | end
13 | ui.blink( YELLOW, 20 )
14 |
--------------------------------------------------------------------------------
/test/src/localfunction01.lua:
--------------------------------------------------------------------------------
1 | local function factorial(n)
2 | if n == 0 then
3 | return 1
4 | else
5 | return factorial(n - 1) * n
6 | end
7 | end
8 | print(factorial(10))
9 |
--------------------------------------------------------------------------------
/test/src/localfunction02.lua:
--------------------------------------------------------------------------------
1 | local factorial = function(n)
2 | if n == 0 then
3 | return 1
4 | else
5 | return factorial(n - 1) * n
6 | end
7 | end
8 | print(factorial(10))
9 |
--------------------------------------------------------------------------------
/test/src/localfunction03.lua:
--------------------------------------------------------------------------------
1 | local function factorial(n)
2 | return "not recursive"
3 | end
4 | print(factorial(10))
5 |
--------------------------------------------------------------------------------
/test/src/localfunction04.lua:
--------------------------------------------------------------------------------
1 | local factorial = function(n)
2 | return "not recursive"
3 | end
4 | print(factorial(10))
5 |
--------------------------------------------------------------------------------
/test/src/loop01.lua:
--------------------------------------------------------------------------------
1 | while true do
2 | print('first')
3 | if test then
4 | print('second')
5 | else
6 | print 'third'
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/src/loop02.lua:
--------------------------------------------------------------------------------
1 | while true do
2 | for k,v in pairs(next_table()) do
3 | if k == "end" then
4 | return
5 | else
6 | break
7 | end
8 | end
9 | end
--------------------------------------------------------------------------------
/test/src/loop03.lua:
--------------------------------------------------------------------------------
1 | while true do
2 | for k,v in pairs(next_table()) do
3 | if valid(k) then
4 | print("block")
5 | if k == "end" then
6 | return
7 | else
8 | break
9 | end
10 | end
11 | end
12 | end
--------------------------------------------------------------------------------
/test/src/loop04.lua:
--------------------------------------------------------------------------------
1 | local a
2 | for b = 1, 10 do
3 | for c = 1, 10 do
4 | if a then break end
5 | break
6 | end
7 | break
8 | end
9 |
--------------------------------------------------------------------------------
/test/src/method01.lua:
--------------------------------------------------------------------------------
1 | function class:method(x)
2 | self:other_method(x)
3 | end
--------------------------------------------------------------------------------
/test/src/method02.lua:
--------------------------------------------------------------------------------
1 | local x,y
2 | ;(x+y):print()
3 | ;("aeiou"):gsub(".",print)
4 | print((arg).x)
5 | x = (x+y).z
6 | y = ("asdf").gsub
7 | ;(-x):print()
8 | print()
9 | ;("aeiou").n = x
10 | ;({x=print}).x("hi")
--------------------------------------------------------------------------------
/test/src/multiassign.lua:
--------------------------------------------------------------------------------
1 | local a, b, c, d
2 | a, b = b, a
3 | a, b, c, d = b, c, d, a
4 |
--------------------------------------------------------------------------------
/test/src/multiassign02.lua:
--------------------------------------------------------------------------------
1 | function f(x)
2 | g, h = x
3 | i, j = x, nil
4 | end
5 |
--------------------------------------------------------------------------------
/test/src/multiassign03.lua:
--------------------------------------------------------------------------------
1 | function f(a, b, c)
2 | a, b, c = b + c
3 | return a, b, c
4 | end
5 |
6 | function f(a, b, c)
7 | a, b, c = b + c, nil
8 | return a, b, c
9 | end
10 |
11 | function f(a, b, c)
12 | a, b, c = b + c, nil, nil
13 | return a, b, c
14 | end
15 |
16 | function f(a, b, c, d)
17 | a, b, c, d = b + c, nil, nil
18 | return a, b, c, d
19 | end
20 |
--------------------------------------------------------------------------------
/test/src/multiassign04.lua:
--------------------------------------------------------------------------------
1 | local a, b, c = f()
2 | b, c = "", nil
3 |
--------------------------------------------------------------------------------
/test/src/multiassign05.lua:
--------------------------------------------------------------------------------
1 | local x, y
2 | x, t[1], t.field, t[x], t[x + 4], y = 1, 2, 3, 4, 5, 6
3 |
--------------------------------------------------------------------------------
/test/src/multiassign06.lua:
--------------------------------------------------------------------------------
1 | local a, b = t[1], t[2] or {}
2 |
--------------------------------------------------------------------------------
/test/src/multiliteraltarget.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = {f()}
3 |
--------------------------------------------------------------------------------
/test/src/nestedif.lua:
--------------------------------------------------------------------------------
1 | if x and y then
2 | f()
3 | if z then
4 | g()
5 | end
6 | end
7 | if x and y then
8 | if z then
9 | g()
10 | end
11 | f()
12 | end
13 | if x then
14 | f()
15 | if y then
16 | if z then
17 | g()
18 | end
19 | h()
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/test/src/nestedif02.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | print(a)
3 | if b then
4 | print(b)
5 | if c then
6 | print(c)
7 | else
8 | print(z)
9 | end
10 | else
11 | print(y)
12 | end
13 | else
14 | print(x)
15 | end
--------------------------------------------------------------------------------
/test/src/number01.lua:
--------------------------------------------------------------------------------
1 | local a
2 | a = 1
3 | a = 1.0
4 | a = -0
5 | a = -0.0
6 |
--------------------------------------------------------------------------------
/test/src/number02.lua:
--------------------------------------------------------------------------------
1 | print(0.0)
2 | print(-0.0)
3 |
--------------------------------------------------------------------------------
/test/src/number03.lua:
--------------------------------------------------------------------------------
1 | print(0.0/1.0)
2 | print(-0.0/1.0)
3 | print(0.0/0.0)
4 |
--------------------------------------------------------------------------------
/test/src/once01.lua:
--------------------------------------------------------------------------------
1 | print("guard")
2 | local a = 0
3 | repeat -- once
4 | local b = 1
5 | print("1")
6 | if a then
7 | print("2")
8 | break
9 | else
10 | print("3")
11 | end
12 | print("4")
13 | until true
14 | print("5")
15 | local following = 0
16 | print(following)
17 |
--------------------------------------------------------------------------------
/test/src/once02.lua:
--------------------------------------------------------------------------------
1 | local L1 = 0
2 | if a then
3 | print("A")
4 | end
5 | print("guard")
6 | repeat
7 | do break end
8 | print("x")
9 | L1 = 6
10 | until true
11 | print(L1)
12 |
--------------------------------------------------------------------------------
/test/src/once03.lua:
--------------------------------------------------------------------------------
1 | local x = 0
2 | repeat
3 | do break end
4 | -- unreachable code
5 | x = 1
6 | until true
7 | print("guard")
8 | repeat
9 | do break end
10 | -- unreachable code
11 | if cond() then
12 | x = 2
13 | end
14 | until true
15 | print("guard")
16 |
--------------------------------------------------------------------------------
/test/src/once04.lua:
--------------------------------------------------------------------------------
1 |
2 | for i = 1, 10 do
3 | local t = false
4 | repeat
5 | t = f3(i)
6 | if f4() then
7 | break
8 | else
9 | f1()
10 | end
11 | f2()
12 | until true
13 | if t then
14 | break
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/test/src/once05.lua:
--------------------------------------------------------------------------------
1 | for x = 1, 10 do
2 | repeat
3 | print("before")
4 | do break end
5 | print("after")
6 | until true
7 | end
--------------------------------------------------------------------------------
/test/src/repeat.lua:
--------------------------------------------------------------------------------
1 | repeat
2 | f()
3 | until a
4 | repeat
5 | if b then
6 | f()
7 | end
8 | until a
9 | repeat
10 | repeat
11 | f()
12 | until b
13 | g()
14 | until a
15 | repeat
16 | f()
17 | repeat
18 | g()
19 | until b
20 | until a
21 |
--------------------------------------------------------------------------------
/test/src/repeat02.lua:
--------------------------------------------------------------------------------
1 | if test then
2 | repeat
3 | -- nothing
4 | until attempt() == test
5 | end
6 |
--------------------------------------------------------------------------------
/test/src/repeat03.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | print("x")
3 | else
4 | repeat
5 | print("else")
6 | until test()
7 | end
8 | print("end")
9 |
--------------------------------------------------------------------------------
/test/src/report01_full.lua:
--------------------------------------------------------------------------------
1 | function myfunction(value)
2 | value = value==nil and true or value
3 | end
--------------------------------------------------------------------------------
/test/src/report01a.lua:
--------------------------------------------------------------------------------
1 | function myfunction(value)
2 | value = true or value
3 | end
--------------------------------------------------------------------------------
/test/src/report01b.lua:
--------------------------------------------------------------------------------
1 | function myfunction(value)
2 | value = true or 3
3 | end
--------------------------------------------------------------------------------
/test/src/report01c.lua:
--------------------------------------------------------------------------------
1 | function myfunction(value)
2 | value = x or value
3 | end
--------------------------------------------------------------------------------
/test/src/report01d.lua:
--------------------------------------------------------------------------------
1 | print(a == b or c or d)
--------------------------------------------------------------------------------
/test/src/report02.lua:
--------------------------------------------------------------------------------
1 | function report02(a, b)
2 | if a == 1 then
3 | if f(b) > 0 then
4 | -- do nothing
5 | end
6 | else
7 | return
8 | end
9 | end
--------------------------------------------------------------------------------
/test/src/report02a.lua:
--------------------------------------------------------------------------------
1 | local i = get()
2 | if i == "one" then
3 | if check1() then
4 | do1()
5 | end
6 | elseif i == "two" then
7 | if check2() then
8 | do2()
9 | else
10 | -- do nothing
11 | end
12 | else
13 | return
14 | end
--------------------------------------------------------------------------------
/test/src/report02b.lua:
--------------------------------------------------------------------------------
1 | local id = x
2 | if check() then
3 | local n = tonumber(string.sub(x, 6))
4 | id = player.episode[n].script or id
5 | end
--------------------------------------------------------------------------------
/test/src/report02c.lua:
--------------------------------------------------------------------------------
1 | if check() then
2 | do1()
3 | else
4 | end
--------------------------------------------------------------------------------
/test/src/report02d.lua:
--------------------------------------------------------------------------------
1 | function func()
2 | local x = f()
3 | if test(x) then
4 | end
5 | end
--------------------------------------------------------------------------------
/test/src/report02e.lua:
--------------------------------------------------------------------------------
1 | function report02e(input)
2 | local x = 1
3 | if test(x) then
4 | do1(x)
5 | else
6 | error("asdf")
7 | end
8 | print("blah")
9 | local y = 4
10 | while true do
11 | do1()
12 | if not check() then
13 | return
14 | end
15 | local z = getz()
16 | if test(z) then
17 | local data1, data2 = getdata()
18 | if data1 == "valid" then
19 | local data3 = getdata(data2)
20 | if data3 then
21 | print("valid data")
22 | end
23 | end
24 | break
25 | end
26 | end
27 | if test3() then
28 | do3()
29 | else
30 | error("asdf")
31 | end
32 | end
--------------------------------------------------------------------------------
/test/src/report03.lua:
--------------------------------------------------------------------------------
1 | function report03()
2 | local x = init()
3 | while true do
4 | local y = f(x)
5 | if y == 0 then
6 | break
7 | end
8 | x = next_x(x, y)
9 | if x == 0 then
10 | break
11 | end
12 | for i = x, 1, -1 do
13 | if i > g(x) or i < 1 then
14 | break
15 | end
16 | local z = h(g(x), y)
17 | if not (z == 4) then
18 | break
19 | end
20 | if z > 0 then
21 | finish()
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/test/src/report04.lua:
--------------------------------------------------------------------------------
1 | function a()
2 | repeat
3 | x = true
4 | until z == 0
5 | end
6 | function b()
7 | repeat
8 | x = true
9 | until z < 0
10 | end
11 | function c()
12 | repeat
13 | x = true
14 | until z <= 0
15 | end
16 |
--------------------------------------------------------------------------------
/test/src/report05.lua:
--------------------------------------------------------------------------------
1 | while y do
2 | y()
3 | do break end
4 | while z do
5 | z()
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/scope02.lua:
--------------------------------------------------------------------------------
1 | -- Compare with scope03.lua
2 | -- The only difference in the compiled output is the scope of local y.
3 |
4 | if x then
5 | local y = f()
6 | if y then
7 | print("y")
8 | else
9 | -- nothing
10 | end
11 | end
12 | print("done")
13 |
--------------------------------------------------------------------------------
/test/src/scope03.lua:
--------------------------------------------------------------------------------
1 | -- Compare with scope02.lua
2 | -- The only difference in the compiled output is the scope of local y.
3 |
4 | if x then
5 | local y = f()
6 | if y then
7 | print("y")
8 | end
9 | else
10 | -- nothing
11 | end
12 | print("done")
13 |
--------------------------------------------------------------------------------
/test/src/string01.lua:
--------------------------------------------------------------------------------
1 | print("line1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\nline1\r\nline2\r\nline3\r\nline4\r\n")
2 |
--------------------------------------------------------------------------------
/test/src/string02.lua:
--------------------------------------------------------------------------------
1 | print("nested long string [[support in Lua 5.1 [[ is ]] controlled by ]] LUA_COMPAT_LSTR\nnewlines\nare\nneeded\nto\ntrip\nthe\nunluac\nlong string\nheuristic")
2 |
--------------------------------------------------------------------------------
/test/src/string04.lua:
--------------------------------------------------------------------------------
1 | print"This is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nBreak 5.0 long string ]] with this"
2 |
3 | print"This is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nThis is a long multi-line string to trigger unluac's long string heuristic.\nBreak 5.0 long string end->]"
4 |
--------------------------------------------------------------------------------
/test/src/table01.lua:
--------------------------------------------------------------------------------
1 | local x
2 | x = {}
3 | x.first = 1
4 | x.second = 2
5 | x.third = 3
6 | y = {first = 1,
7 | second = 2,
8 | third = 3}
9 |
--------------------------------------------------------------------------------
/test/src/table02.lua:
--------------------------------------------------------------------------------
1 | if buffer then
2 | print("buffer")
3 | end
4 | local x = {table_elt = 6}
5 | local list = {1,
6 | 6,
7 | 3,
8 | 2,
9 | 6,
10 | 3,
11 | 2,
12 | 6,
13 | 6}
14 |
--------------------------------------------------------------------------------
/test/src/table06.lua:
--------------------------------------------------------------------------------
1 | local t = {["a"] = 1, ["b"] = 2, ["c"] = 3}
2 | local u = {[1] = 1, [2] = 2, [3] = 3}
3 | local v = {["a"] = 1, ["b"] = 2, ["c"] = 3, [1] = 1, [2] = 2, [3] = 3}
4 | local w = {[f()] = 1, [g()] = 2, [h()] = 3}
5 |
--------------------------------------------------------------------------------
/test/src/table07.lua:
--------------------------------------------------------------------------------
1 | local t = {f()}
2 | local s = {1, 2, 3, g()}
3 |
4 | for i = 1, 10 do
5 | print(t[i], s[i])
6 | end
7 |
--------------------------------------------------------------------------------
/test/src/unused01.lua:
--------------------------------------------------------------------------------
1 | while 1 do
2 | print("x")
3 | work()
4 | end
5 |
--------------------------------------------------------------------------------
/test/src/upvalue01.lua:
--------------------------------------------------------------------------------
1 | local upvalue1 = {}
2 | local upvalue2 = {}
3 | function f()
4 | local a = upvalue1.print
5 | local b = upvalue2.print
6 | local c = _ENV.print
7 | return print
8 | end
9 | function g()
10 | return _ENV.print
11 | end
12 | function f2(a)
13 | upvalue1.print = a
14 | upvalue2.print = a
15 | _ENV.print = a
16 | print = a
17 | end
18 |
--------------------------------------------------------------------------------
/test/src/upvalue02.lua:
--------------------------------------------------------------------------------
1 | function f()
2 | _ENV[1] = 0
3 | return _ENV[1]
4 | end
5 |
--------------------------------------------------------------------------------
/test/src/upvalue03.lua:
--------------------------------------------------------------------------------
1 | function f()
2 | a,b,c = g(),g(),g()
3 | end
4 |
--------------------------------------------------------------------------------
/test/src/upvalue04.lua:
--------------------------------------------------------------------------------
1 | if x then
2 | local upvalue = 0
3 | f = function()
4 | print(upvalue)
5 | upvalue = upvalue + 1
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/upvalue05.lua:
--------------------------------------------------------------------------------
1 | for k, v in pairs(t) do
2 | function v.__tostring()
3 | return k
4 | end
5 | end
6 |
7 | for k, v in pairs(t) do
8 | local x = v()
9 | function v.__tostring()
10 | return munge(k, x)
11 | end
12 | end
13 |
14 | for k, v in pairs(t) do
15 | local x = v()
16 | function v.__tostring()
17 | return k
18 | end
19 | end
20 |
21 | for k, v in pairs(t) do
22 | local x = v()
23 | print(x)
24 | end
25 |
26 | for k, v in pairs(t) do
27 | local x = v()
28 | local y = g(x)
29 | function v.__tostring()
30 | return munge(k, y)
31 | end
32 | end
33 |
34 |
35 | for i = 1, 1000 do
36 | t[i].__tostring = function()
37 | return i
38 | end
39 | end
40 |
41 | for i = 1, 1000 do
42 | local x = t[i].call()
43 | t[i].__tostring = function()
44 | return munge(i, x)
45 | end
46 | end
47 |
48 | for i = 1, 1000 do
49 | local x = t[i].call()
50 | t[i].__tostring = function()
51 | return i
52 | end
53 | end
54 |
55 | for i = 1, 1000 do
56 | local x = t[i].call()
57 | print(x)
58 | end
59 |
60 | for i = 1, 1000 do
61 | local x = t[i].call()
62 | local y = g(x)
63 | t[i].__tostring = function()
64 | return munge(i, y)
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/test/src/while.lua:
--------------------------------------------------------------------------------
1 | while a do
2 | f()
3 | end
4 | while a do
5 | if b then
6 | f()
7 | end
8 | end
9 | while a do
10 | while b do
11 | f()
12 | end
13 | g()
14 | end
15 | while a do
16 | f()
17 | while b do
18 | g()
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/test/src/while02.lua:
--------------------------------------------------------------------------------
1 | if elseredirect then
2 | if inner then
3 | local x = 1
4 | while x < 100 do
5 | print(x)
6 | x = x + 1
7 | end
8 | end
9 | else
10 | print("else")
11 | end
12 |
--------------------------------------------------------------------------------
/test/src/while03.lua:
--------------------------------------------------------------------------------
1 | if elseredirect then
2 | if inner then
3 | local x = 1
4 | while call(a or b) do
5 | print(x)
6 | x = x + 1
7 | end
8 | end
9 | else
10 | print("else")
11 | end
12 |
--------------------------------------------------------------------------------
/test/src/while04.lua:
--------------------------------------------------------------------------------
1 | local t = {}
2 |
3 | print("test 1")
4 |
5 | while true do
6 | t[1] = 0
7 | if f() then
8 | break
9 | end
10 | print("loop")
11 | end
12 |
13 | print("test 2")
14 |
15 | -- strange test
16 | -- for Lua 5.1, while f() is not usually to while true if not f() break
17 | -- This is because it doesn't have the 5.2-style if-break optimization
18 | -- To get 5.2-style if-break jump, we need to second target of the
19 | -- if to be redirected -- by putting a break after the if statement.
20 | while true do
21 | t[1] = 0
22 | if f() then
23 | end
24 | do break end
25 | print("loop")
26 | end
27 |
28 |
29 | print("test 3")
30 |
31 | while f() and {1, 2, 3} and g() do
32 | print("loop")
33 | end
34 |
35 | print("test 4")
36 |
37 | while f() and {a = 1, b = 2, c = 3} and g() do
38 | print("loop")
39 | end
40 |
--------------------------------------------------------------------------------
/test/src/while05.lua:
--------------------------------------------------------------------------------
1 | if a then
2 | print(1)
3 | end
4 | while b do
5 | print(2)
6 | end
7 | print(3)
8 |
--------------------------------------------------------------------------------
/test/src/while06.lua:
--------------------------------------------------------------------------------
1 | while a do
2 | if b then
3 | f()
4 | else
5 | break
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/test/src/while07.lua:
--------------------------------------------------------------------------------
1 | local x
2 | while test() do
3 | x = a or b + 1
4 | end
5 |
--------------------------------------------------------------------------------
/unluac.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------