Skip to content

Commit b35fa0e

Browse files
authored
Merge pull request #236 from Vortex-scripts/master
Full support of LuaU's if else expression.
2 parents 3d9c58d + f34b6a2 commit b35fa0e

6 files changed

Lines changed: 109 additions & 4 deletions

File tree

src/prometheus/ast.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,12 @@ function Ast.NopStatement()
148148
}
149149
end
150150

151-
function Ast.IfElseExpression(condition, true_value, false_value)
151+
function Ast.IfElseExpression(condition, true_value, elseifs, false_value)
152152
return {
153153
kind = AstKind.IfElseExpression,
154154
condition = condition,
155155
true_value = true_value,
156+
elseifs = elseifs,
156157
false_value = false_value
157158
}
158159
end

src/prometheus/compiler/expressions.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ handlers[AstKind.AndExpression] = requireExpression("and");
2828
handlers[AstKind.TableConstructorExpression] = requireExpression("table_constructor");
2929
handlers[AstKind.FunctionLiteralExpression] = requireExpression("function_literal");
3030
handlers[AstKind.VarargExpression] = requireExpression("vararg");
31+
handlers[AstKind.IfElseExpression] = requireExpression("if_else");
3132

3233
-- Binary ops share one handler
3334
local binaryHandler = requireExpression("binary");
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
-- This Script is Part of the Prometheus Obfuscator by levno-710
2+
--
3+
-- if_else.lua
4+
--
5+
-- This Script contains the statement handler for the IfElseExpression.
6+
7+
local Ast = require("prometheus.ast");
8+
9+
return function(self, expression, funcDepth, numReturns)
10+
local scope = self.activeBlock.scope;
11+
local posState = self.registers[self.POS_REGISTER];
12+
self.registers[self.POS_REGISTER] = self.VAR_REGISTER;
13+
14+
local regs = {};
15+
for i = 1, numReturns do
16+
regs[i] = self:allocRegister();
17+
if i ~= 1 then
18+
self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
19+
end
20+
end
21+
22+
local resReg = regs[1];
23+
local tmpReg;
24+
25+
if posState then
26+
tmpReg = self:allocRegister(false);
27+
self:addStatement(self:copyRegisters(scope, {tmpReg}, {self.POS_REGISTER}), {tmpReg}, {self.POS_REGISTER}, false);
28+
end
29+
30+
local conditionReg = self:compileExpression(expression.condition, funcDepth, 1)[1];
31+
32+
local finalBlock = self:createBlock();
33+
local nextBlock = self:createBlock();
34+
local innerBlock = self:createBlock();
35+
36+
self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, conditionReg), Ast.NumberExpression(innerBlock.id)), Ast.NumberExpression(nextBlock.id))), {self.POS_REGISTER}, {conditionReg}, false);
37+
self:freeRegister(conditionReg, false);
38+
39+
self:setActiveBlock(innerBlock);
40+
scope = innerBlock.scope;
41+
42+
local trueReg = self:compileExpression(expression.true_value, funcDepth, 1)[1];
43+
self:addStatement(self:copyRegisters(scope, {resReg}, {trueReg}), {resReg}, {trueReg}, false);
44+
self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(finalBlock.id)), {self.POS_REGISTER}, {}, false);
45+
46+
for _, elif in ipairs(expression.elseifs) do
47+
self:setActiveBlock(nextBlock);
48+
conditionReg = self:compileExpression(elif.condition, funcDepth, 1)[1];
49+
local elifBlock = self:createBlock();
50+
nextBlock = self:createBlock();
51+
local elifScope = self.activeBlock.scope;
52+
53+
self:addStatement(self:setRegister(elifScope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(elifScope, conditionReg), Ast.NumberExpression(elifBlock.id)), Ast.NumberExpression(nextBlock.id))), {self.POS_REGISTER}, {conditionReg}, false);
54+
self:freeRegister(conditionReg, false);
55+
56+
self:setActiveBlock(elifBlock);
57+
elifScope = elifBlock.scope;
58+
local valueReg = self:compileExpression(elif.value, funcDepth, 1)[1];
59+
self:addStatement(self:copyRegisters(elifScope, {resReg}, {valueReg}), {resReg}, {valueReg}, false);
60+
self:addStatement(self:setRegister(elifScope, self.POS_REGISTER, Ast.NumberExpression(finalBlock.id)), {self.POS_REGISTER}, {}, false);
61+
end
62+
63+
self:setActiveBlock(nextBlock);
64+
scope = self.activeBlock.scope;
65+
local falseReg = self:compileExpression(expression.false_value, funcDepth, 1)[1];
66+
self:addStatement(self:copyRegisters(scope, {resReg}, {falseReg}), {resReg}, {falseReg}, false);
67+
self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(finalBlock.id)), {self.POS_REGISTER}, {}, false);
68+
69+
self.registers[self.POS_REGISTER] = posState;
70+
71+
self:setActiveBlock(finalBlock);
72+
scope = finalBlock.scope;
73+
74+
if tmpReg then
75+
self:addStatement(self:copyRegisters(scope, {self.POS_REGISTER}, {tmpReg}), {self.POS_REGISTER}, {tmpReg}, false);
76+
self:freeRegister(tmpReg, false);
77+
end
78+
79+
return regs;
80+
end

src/prometheus/parser.lua

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,23 @@ function Parser:expressionLiteral(scope)
946946
local condition = self:expression(scope);
947947
expect(self, TokenKind.Keyword, "then");
948948
local true_value = self:expression(scope);
949+
950+
local elseifs = {}
951+
while(consume(self, TokenKind.Keyword, "elseif")) do
952+
local elseif_condition = self:expression(scope);
953+
expect(self, TokenKind.Keyword, "then");
954+
local elseif_value = self:expression(scope);
955+
956+
table.insert(elseifs, {
957+
condition = elseif_condition,
958+
value = elseif_value
959+
});
960+
end
961+
949962
expect(self, TokenKind.Keyword, "else");
950963
local false_value = self:expression(scope);
951964

952-
return Ast.IfElseExpression(condition, true_value, false_value);
965+
return Ast.IfElseExpression(condition, true_value, elseifs, false_value);
953966
end
954967
end
955968

src/prometheus/unparser.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,12 @@ function Unparser:unparseExpression(expression, tabbing)
688688
push(self:unparseExpression(expression.condition));
689689
push(" then ");
690690
push(self:unparseExpression(expression.true_value));
691+
for _, elseifexp in pairs(expression.elseifs) do
692+
push(" elseif ");
693+
push(self:unparseExpression(elseifexp.condition));
694+
push(" then ");
695+
push(self:unparseExpression(elseifexp.value));
696+
end
691697
push(" else ");
692698
push(self:unparseExpression(expression.false_value));
693699
return joinParts(parts);

src/prometheus/visitast.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,12 @@ function visitExpression(expression, previsit, postvisit, data)
238238
end
239239
if(expression.kind == AstKind.IfElseExpression) then
240240
expression.condition = visitExpression(expression.condition, previsit, postvisit, data);
241-
expression.true_expr = visitExpression(expression.true_expr, previsit, postvisit, data);
242-
expression.false_expr = visitExpression(expression.false_expr, previsit, postvisit, data);
241+
expression.true_value = visitExpression(expression.true_value, previsit, postvisit, data);
242+
for i, elif in pairs(expression.elseifs) do
243+
elif.condition = visitExpression(elif.condition, previsit, postvisit, data);
244+
elif.value = visitExpression(elif.value, previsit, postvisit, data);
245+
end
246+
expression.false_value = visitExpression(expression.false_value, previsit, postvisit, data);
243247
end
244248

245249
if(type(postvisit) == "function") then

0 commit comments

Comments
 (0)