-- This Script is Part of the Prometheus Obfuscator by levno-710 -- -- for_in_statement.lua -- -- This Script contains the statement handler for the ForInStatement local Ast = require("prometheus.ast"); return function(self, statement, funcDepth) local scope = self.activeBlock.scope; local expressionsLength = #statement.expressions; local exprregs = {}; for i, expr in ipairs(statement.expressions) do if(i == expressionsLength and expressionsLength < 3) then local regs = self:compileExpression(expr, funcDepth, 4 - expressionsLength); for i = 1, 4 - expressionsLength do table.insert(exprregs, regs[i]); end else if i <= 3 then table.insert(exprregs, self:compileExpression(expr, funcDepth, 1)[1]) else self:freeRegister(self:compileExpression(expr, funcDepth, 1)[1], false); end end end for i, reg in ipairs(exprregs) do if reg and self.registers[reg] ~= self.VAR_REGISTER and reg ~= self.POS_REGISTER and reg ~= self.RETURN_REGISTER then self.registers[reg] = self.VAR_REGISTER; else exprregs[i] = self:allocRegister(true); self:addStatement(self:copyRegisters(scope, {exprregs[i]}, {reg}), {exprregs[i]}, {reg}, false); end end local checkBlock = self:createBlock(); local bodyBlock = self:createBlock(); local finalBlock = self:createBlock(); statement.__start_block = checkBlock; statement.__final_block = finalBlock; self:addStatement(self:setPos(scope, checkBlock.id), {self.POS_REGISTER}, {}, false); self:setActiveBlock(checkBlock); local scope = self.activeBlock.scope; local varRegs = {}; for i, id in ipairs(statement.ids) do varRegs[i] = self:getVarRegister(statement.scope, id, funcDepth) end self:addStatement(Ast.AssignmentStatement({ self:registerAssignment(scope, exprregs[3]), varRegs[2] and self:registerAssignment(scope, varRegs[2]), }, { Ast.FunctionCallExpression(self:register(scope, exprregs[1]), { self:register(scope, exprregs[2]), self:register(scope, exprregs[3]), }) }), {exprregs[3], varRegs[2]}, {exprregs[1], exprregs[2], exprregs[3]}, true); self:addStatement(Ast.AssignmentStatement({ self:posAssignment(scope) }, { Ast.OrExpression(Ast.AndExpression(self:register(scope, exprregs[3]), Ast.NumberExpression(bodyBlock.id)), Ast.NumberExpression(finalBlock.id)) }), {self.POS_REGISTER}, {exprregs[3]}, false); self:setActiveBlock(bodyBlock); local scope = self.activeBlock.scope; self:addStatement(self:copyRegisters(scope, {varRegs[1]}, {exprregs[3]}), {varRegs[1]}, {exprregs[3]}, false); for i=3, #varRegs do self:addStatement(self:setRegister(scope, varRegs[i], Ast.NilExpression()), {varRegs[i]}, {}, false); end for i, id in ipairs(statement.ids) do if(self:isUpvalue(statement.scope, id)) then local varreg = varRegs[i]; local tmpReg = self:allocRegister(false); scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction); self:addStatement(self:setRegister(scope, tmpReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {})), {tmpReg}, {}, false); self:addStatement(self:setUpvalueMember(scope, self:register(scope, tmpReg), self:register(scope, varreg)), {}, {tmpReg, varreg}, true); self:addStatement(self:copyRegisters(scope, {varreg}, {tmpReg}), {varreg}, {tmpReg}, false); self:freeRegister(tmpReg, false); end end self:compileBlock(statement.body, funcDepth); self:addStatement(self:setPos(scope, checkBlock.id), {self.POS_REGISTER}, {}, false); self:setActiveBlock(finalBlock); for i, _ in ipairs(exprregs) do self:freeRegister(exprregs[i], true) end end;