local function D(D,R)return function(j)local Y=R(j.source,j.index)j.index=j.index+D return Y end end local function R(D)local R=D:s_int()local j={}for R=1,R,1 do local Y=D:s_ins()local f=bit.band(Y,63)local A=opcode_t[f]local P=opcode_m[f]local T={value=Y;op=f;A=bit.band(bit.rshift(Y,6),255)}if A=="\065\066\067"then T.B=bit.band(bit.rshift(Y,23),511)T.C=bit.band(bit.rshift(Y,14),511)T.is_KB=P.b=="\079\112\065\114\103\075"and T.B>255 T.is_KC=P.c=="\079\112\065\114\103\075"and T.C>255 elseif A=="\065\066\120"then T.Bx=bit.band(bit.rshift(Y,14),262143)T.is_K=P.b=="\079\112\065\114\103\075"elseif A=="\065\115\066\120"then T.sBx=bit.band(bit.rshift(Y,14),262143)-131071 end j[R]=T end return j end local function j(D)local R=D:s_int()local j={}for R=1,R,1 do local Y=stm_byte(D)local f if Y==1 then f=stm_byte(D)~=0 elseif Y==3 then f=D:s_num()elseif Y==4 then f=stm_lstring(D)end j[R]=f end return j end local function Y(D,R)local j=D:s_int()local Y={}for j=1,j,1 do Y[j]=stm_lua_func(D,R)end return Y end local function f(D)local R=D:s_int()local j={}for R=1,R,1 do j[R]=D:s_int()end return j end local function A(D)local R=D:s_int()local j={}for R=1,R,1 do j[R]={varname=stm_lstring(D);startpc=D:s_int();endpc=D:s_int()}end return j end local function P(D)local R=D:s_int()local j={}for R=1,R,1 do j[R]=stm_lstring(D)end return j end function stm_lua_func(D,T)local e={}local k=stm_lstring(D)or T e.source=k D:s_int()D:s_int()e.numupvals=stm_byte(D)e.numparams=stm_byte(D)stm_byte(D)stm_byte(D)e.code=R(D)e.const=j(D)e.subs=Y(D,k)e.lines=f(D)A(D)P(D)for D,R in ipairs(e.code)do if R.is_K then R.const=e.const[R.Bx+1]else if R.is_KB then R.const_B=e.const[R.B-255]end if R.is_KC then R.const_C=e.const[R.C-255]end end end return e end function stm_lua_bytecode(R)local j local Y local f local A local P local T local e local k={index=1,source=R}assert(stm_string(k,4)=="\027\076\117\097","\105\110\118\097\108\105\100 \076\117\097 \115\105\103\110\097\116\117\114\101")assert(stm_byte(k)==81,"\105\110\118\097\108\105\100 \076\117\097 \118\101\114\115\105\111\110")assert(stm_byte(k)==0,"\105\110\118\097\108\105\100 \076\117\097 \102\111\114\109\097\116")Y=stm_byte(k)~=0 f=stm_byte(k)A=stm_byte(k)P=stm_byte(k)T=stm_byte(k)e=stm_byte(k)~=0 j=Y and rd_int_le or rd_int_be k.s_int=cst_int_rdr(f,j)k.s_szt=cst_int_rdr(A,j)k.s_ins=cst_int_rdr(P,j)if e then k.s_num=cst_int_rdr(T,j)elseif float_types[T]then k.s_num=D(T,float_types[T][Y and"\108\105\116\116\108\101"or"\098\105\103"])else error("\117\110\115\117\112\112\111\114\116\101\100 \102\108\111\097\116 \115\105\122\101")end return stm_lua_func(k,"\064\118\105\114\116\117\097\108")end local function T(D,R)for j,Y in pairs(D)do if Y.index>=R then Y.value=Y.store[Y.index]Y.store=Y Y.index="\118\097\108\117\101"D[j]=nil end end end local function e(D,R,j)local Y=D[R]if not Y then Y={index=R,store=j}D[R]=Y end return Y end local function k(...)return select("\035",...),{...}end local function N(D,R)local j=D.source local Y=D.lines[D.pc-1]local f,A,P=R:match("\094\040\046-\041\058\040\037\100\043\041\058\037\115\043\040\046\043\041")local T="\037\115\058\037\105\058 \091\037\115\058\037\105\093 \037\115"Y=Y or"\048"f=f or"\063"A=A or"\048"P=P or R error(string.format(T,j,Y,f,A,P),0)end local function W(D)local R=D.code local j=D.subs local Y=D.env local f=D.upvals local A=D.varargs local P=-1 local N={}local W=D.stack local B=D.pc while true do local Z=R[B]local s=Z.op B=B+1 if s<19 then if s<9 then if s<4 then if s<2 then if s<1 then W[Z.A]=W[Z.B]else W[Z.A]=Z.const end elseif s>2 then for D=Z.A,Z.B,1 do W[D]=nil end else W[Z.A]=Z.B~=0 if Z.C~=0 then B=B+1 end end elseif s>4 then if s<7 then if s<6 then W[Z.A]=Y[Z.const]else local D if Z.is_KC then D=Z.const_C else D=W[Z.C]end W[Z.A]=W[Z.B][D]end elseif s>7 then local D=f[Z.B]D.store[D.index]=W[Z.A]else Y[Z.const]=W[Z.A]end else local D=f[Z.B]W[Z.A]=D.store[D.index]end elseif s>9 then if s<14 then if s<12 then if s<11 then W[Z.A]={}else local D=Z.A local R=Z.B local j if Z.is_KC then j=Z.const_C else j=W[Z.C]end W[D+1]=W[R]W[D]=W[R][j]end elseif s>12 then local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A]=D-R else local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A]=D+R end elseif s>14 then if s<17 then if s<16 then local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A]=D/R else local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A]=D%R end elseif s>17 then W[Z.A]=-W[Z.B]else local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A]=D^R end else local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A]=D*R end else local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end W[Z.A][D]=R end elseif s>19 then if s<29 then if s<24 then if s<22 then if s<21 then W[Z.A]=#W[Z.B]else local D=W[Z.B]for R=Z.B+1,Z.C,1 do D=D..W[R]end W[Z.A]=D end elseif s>22 then local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end if(D==R)~=(Z.A~=0)then B=B+1 end else B=B+Z.sBx end elseif s>24 then if s<27 then if s<26 then local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end if(D<=R)~=(Z.A~=0)then B=B+1 end else if not W[Z.A]==(Z.C~=0)then B=B+1 end end elseif s>27 then local D=Z.A local R=Z.B local j=Z.C local Y local f,A if R==0 then Y=P-D else Y=R-1 end f,A=k(W[D](unpack(W,D+1,D+Y)))if j==0 then P=(D+f)-1 else f=j-1 end for R=1,f,1 do W[(D+R)-1]=A[R]end else local D=Z.A local R=Z.B if not W[R]==(Z.C~=0)then B=B+1 else W[D]=W[R]end end else local D,R if Z.is_KB then D=Z.const_B else D=W[Z.B]end if Z.is_KC then R=Z.const_C else R=W[Z.C]end if(D<R)~=(Z.A~=0)then B=B+1 end end elseif s>29 then if s<34 then if s<32 then if s<31 then local D=Z.A local R=Z.B local j={}local Y if R==0 then Y=(P-D)+1 else Y=R-1 end for R=1,Y,1 do j[R]=W[(D+R)-1]end T(N,math.huge)return Y,j else local D=Z.A local R=W[D+2]local j=W[D]+R local Y=W[D+1]local f if R==math.abs(R)then f=j<=Y else f=j>=Y end if f then W[Z.A]=j W[Z.A+3]=j B=B+Z.sBx end end elseif s>32 then local D=Z.A local R=W[D]local j=W[D+1]local Y=W[D+2]local f=D+3 local A W[f+2]=Y W[f+1]=j W[f]=R A={R(j,Y)}for D=1,Z.C,1 do W[(f+D)-1]=A[D]end if W[f]~=nil then W[D+2]=W[f]else B=B+1 end else local D=Z.A local R,j,Y R=assert(tonumber(W[D]),"\096\102\111\114\096 \105\110\105\116\105\097\108 \118\097\108\117\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")j=assert(tonumber(W[D+1]),"\096\102\111\114\096 \108\105\109\105\116 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")Y=assert(tonumber(W[D+2]),"\096\102\111\114\096 \115\116\101\112 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")W[D]=R-Y W[D+1]=j W[D+2]=Y B=B+Z.sBx end elseif s>34 then if s<36 then T(N,Z.A)elseif s>36 then local D=Z.A local R=Z.B if R==0 then R=A.size P=(D+R)-1 end for R=1,R,1 do W[(D+R)-1]=A.list[R]end else local D=j[Z.Bx+1]local A=D.numupvals local P if A~=0 then P={}for D=1,A,1 do local j=R[(B+D)-1]if j.op==0 then P[D-1]=e(N,j.B,W)elseif j.op==4 then P[D-1]=f[j.B]end end B=B+A end W[Z.A]=wrap_lua_func(D,Y,P)end else local D=Z.A local R=Z.C local j=Z.B local Y=W[D]local f if j==0 then j=P-D end if R==0 then R=Z[B].value B=B+1 end f=(R-1)*FIELDS_PER_FLUSH for R=1,j,1 do Y[R+f]=W[D+R]end end else local D=Z.A local R=Z.B local j if R==0 then j=P-D else j=R-1 end T(N,math.huge)return k(W[D](unpack(W,D+1,D+j)))end else W[Z.A]=not W[Z.B]end D.pc=B end end function wrap_lua_func(D,R,j)local Y=D.code local f=D.subs local A=D.lines local P=D.source local T=D.numparams local function e(...)local D={}local e={}local B=0 local Z,s=k(...)local h local g,J,E for R=1,T,1 do D[R-1]=s[R]end if T<Z then B=Z-T for D=1,B,1 do e[D]=s[T+D]end end h={varargs={list=e;size=B};code=Y,subs=f;lines=A,source=P;env=R;upvals=j,stack=D,pc=1}g,J,E=pcall(W,h,...)if g then return unpack(E,1,J)else N(h,J)end return end return e end return function(D,R)return wrap_lua_func(stm_lua_bytecode(D),R or getfenv(0))end

local function cst_flt_rdr(len, func)
	return function(S)
		local flt = func(S.source, S.index)
		S.index = S.index + len

		return flt
	end
end

local function stm_instructions(S)
	local size = S:s_int()
	local code = {}

	for i = 1, size do
		local ins = S:s_ins()
		local op = bit.band(ins, 0x3F)
		local args = opcode_t[op]
		local mode = opcode_m[op]
		local data = {value = ins, op = op, A = bit.band(bit.rshift(ins, 6), 0xFF)}

		if args == 'ABC' then
			data.B = bit.band(bit.rshift(ins, 23), 0x1FF)
			data.C = bit.band(bit.rshift(ins, 14), 0x1FF)
			data.is_KB = mode.b == 'OpArgK' and data.B > 0xFF -- post process optimization
			data.is_KC = mode.c == 'OpArgK' and data.C > 0xFF
		elseif args == 'ABx' then
			data.Bx = bit.band(bit.rshift(ins, 14), 0x3FFFF)
			data.is_K = mode.b == 'OpArgK'
		elseif args == 'AsBx' then
			data.sBx = bit.band(bit.rshift(ins, 14), 0x3FFFF) - 131071
		end

		code[i] = data
	end

	return code
end

local function stm_constants(S)
	local size = S:s_int()
	local consts = {}

	for i = 1, size do
		local tt = stm_byte(S)
		local k

		if tt == 1 then
			k = stm_byte(S) ~= 0
		elseif tt == 3 then
			k = S:s_num()
		elseif tt == 4 then
			k = stm_lstring(S)
		end

		consts[i] = k -- offset +1 during instruction decode
	end

	return consts
end

local function stm_subfuncs(S, src)
	local size = S:s_int()
	local sub = {}

	for i = 1, size do
		sub[i] = stm_lua_func(S, src) -- offset +1 in CLOSURE
	end

	return sub
end

local function stm_lineinfo(S)
	local size = S:s_int()
	local lines = {}

	for i = 1, size do lines[i] = S:s_int() end

	return lines
end

local function stm_locvars(S)
	local size = S:s_int()
	local locvars = {}

	for i = 1, size do locvars[i] = {varname = stm_lstring(S), startpc = S:s_int(), endpc = S:s_int()} end

	return locvars
end

local function stm_upvals(S)
	local size = S:s_int()
	local upvals = {}

	for i = 1, size do upvals[i] = stm_lstring(S) end

	return upvals
end

function stm_lua_func(S, psrc)
	local proto = {}
	local src = stm_lstring(S) or psrc -- source is propagated

	proto.source = src -- source name

	S:s_int() -- line defined
	S:s_int() -- last line defined

	proto.numupvals = stm_byte(S) -- num upvalues
	proto.numparams = stm_byte(S) -- num params

	stm_byte(S) -- vararg flag
	stm_byte(S) -- max stack size

	proto.code = stm_instructions(S)
	proto.const = stm_constants(S)
	proto.subs = stm_subfuncs(S, src)
	proto.lines = stm_lineinfo(S)

	stm_locvars(S)
	stm_upvals(S)

	-- post process optimization
	for _, v in ipairs(proto.code) do
		if v.is_K then
			v.const = proto.const[v.Bx + 1] -- offset for 1 based index
		else
			if v.is_KB then v.const_B = proto.const[v.B - 0xFF] end

			if v.is_KC then v.const_C = proto.const[v.C - 0xFF] end
		end
	end

	return proto
end

function stm_lua_bytecode(src)
	-- func reader
	local rdr_func

	-- header flags
	local little
	local size_int
	local size_szt
	local size_ins
	local size_num
	local flag_int

	-- stream object
	local stream = {
		-- data
		index = 1,
		source = src,
	}

	assert(stm_string(stream, 4) == '\27Lua', 'invalid Lua signature')
	assert(stm_byte(stream) == 0x51, 'invalid Lua version')
	assert(stm_byte(stream) == 0, 'invalid Lua format')

	little = stm_byte(stream) ~= 0
	size_int = stm_byte(stream)
	size_szt = stm_byte(stream)
	size_ins = stm_byte(stream)
	size_num = stm_byte(stream)
	flag_int = stm_byte(stream) ~= 0

	rdr_func = little and rd_int_le or rd_int_be
	stream.s_int = cst_int_rdr(size_int, rdr_func)
	stream.s_szt = cst_int_rdr(size_szt, rdr_func)
	stream.s_ins = cst_int_rdr(size_ins, rdr_func)

	if flag_int then
		stream.s_num = cst_int_rdr(size_num, rdr_func)
	elseif float_types[size_num] then
		stream.s_num = cst_flt_rdr(size_num, float_types[size_num][little and 'little' or 'big'])
	else
		error('unsupported float size')
	end

	return stm_lua_func(stream, '@virtual')
end

local function close_lua_upvalues(list, index)
	for i, uv in pairs(list) do
		if uv.index >= index then
			uv.value = uv.store[uv.index] -- store value
			uv.store = uv
			uv.index = 'value' -- self reference
			list[i] = nil
		end
	end
end

local function open_lua_upvalue(list, index, stack)
	local prev = list[index]

	if not prev then
		prev = {index = index, store = stack}
		list[index] = prev
	end

	return prev
end

local function wrap_lua_variadic(...) return select('#', ...), {...} end

local function on_lua_error(exst, err)
	local src = exst.source
	local line = exst.lines[exst.pc - 1]
	local psrc, pline, pmsg = err:match('^(.-):(%d+):%s+(.+)')
	local fmt = '%s:%i: [%s:%i] %s'

	line = line or '0'
	psrc = psrc or '?'
	pline = pline or '0'
	pmsg = pmsg or err

	error(string.format(fmt, src, line, psrc, pline, pmsg), 0)
end

local function exec_lua_func(exst)
	-- localize for easy lookup
	local code = exst.code
	local subs = exst.subs
	local env = exst.env
	local upvs = exst.upvals
	local vargs = exst.varargs

	-- state variables
	local stktop = -1
	local openupvs = {}
	local stack = exst.stack
	local pc = exst.pc

	while true do
		local inst = code[pc]
		local op = inst.op
		pc = pc + 1

		if op < 19 then
			if op < 9 then
				if op < 4 then
					if op < 2 then
						if op < 1 then
							--[[0 MOVE]]
							stack[inst.A] = stack[inst.B]
						else
							--[[1 LOADK]]
							stack[inst.A] = inst.const
						end
					elseif op > 2 then
						--[[3 LOADNIL]]
						for i = inst.A, inst.B do stack[i] = nil end
					else
						--[[2 LOADBOOL]]
						stack[inst.A] = inst.B ~= 0

						if inst.C ~= 0 then pc = pc + 1 end
					end
				elseif op > 4 then
					if op < 7 then
						if op < 6 then
							--[[5 GETGLOBAL]]
							stack[inst.A] = env[inst.const]
						else
							--[[6 GETTABLE]]
							local index

							if inst.is_KC then
								index = inst.const_C
							else
								index = stack[inst.C]
							end

							stack[inst.A] = stack[inst.B][index]
						end
					elseif op > 7 then
						--[[8 SETUPVAL]]
						local uv = upvs[inst.B]

						uv.store[uv.index] = stack[inst.A]
					else
						--[[7 SETGLOBAL]]
						env[inst.const] = stack[inst.A]
					end
				else
					--[[4 GETUPVAL]]
					local uv = upvs[inst.B]

					stack[inst.A] = uv.store[uv.index]
				end
			elseif op > 9 then
				if op < 14 then
					if op < 12 then
						if op < 11 then
							--[[10 NEWTABLE]]
							stack[inst.A] = {}
						else
							--[[11 SELF]]
							local A = inst.A
							local B = inst.B
							local index

							if inst.is_KC then
								index = inst.const_C
							else
								index = stack[inst.C]
							end

							stack[A + 1] = stack[B]
							stack[A] = stack[B][index]
						end
					elseif op > 12 then
						--[[13 SUB]]
						local lhs, rhs

						if inst.is_KB then
							lhs = inst.const_B
						else
							lhs = stack[inst.B]
						end

						if inst.is_KC then
							rhs = inst.const_C
						else
							rhs = stack[inst.C]
						end

						stack[inst.A] = lhs - rhs
					else
						--[[12 ADD]]
						local lhs, rhs

						if inst.is_KB then
							lhs = inst.const_B
						else
							lhs = stack[inst.B]
						end

						if inst.is_KC then
							rhs = inst.const_C
						else
							rhs = stack[inst.C]
						end

						stack[inst.A] = lhs + rhs
					end
				elseif op > 14 then
					if op < 17 then
						if op < 16 then
							--[[15 DIV]]
							local lhs, rhs

							if inst.is_KB then
								lhs = inst.const_B
							else
								lhs = stack[inst.B]
							end

							if inst.is_KC then
								rhs = inst.const_C
							else
								rhs = stack[inst.C]
							end

							stack[inst.A] = lhs / rhs
						else
							--[[16 MOD]]
							local lhs, rhs

							if inst.is_KB then
								lhs = inst.const_B
							else
								lhs = stack[inst.B]
							end

							if inst.is_KC then
								rhs = inst.const_C
							else
								rhs = stack[inst.C]
							end

							stack[inst.A] = lhs % rhs
						end
					elseif op > 17 then
						--[[18 UNM]]
						stack[inst.A] = -stack[inst.B]
					else
						--[[17 POW]]
						local lhs, rhs

						if inst.is_KB then
							lhs = inst.const_B
						else
							lhs = stack[inst.B]
						end

						if inst.is_KC then
							rhs = inst.const_C
						else
							rhs = stack[inst.C]
						end

						stack[inst.A] = lhs ^ rhs
					end
				else
					--[[14 MUL]]
					local lhs, rhs

					if inst.is_KB then
						lhs = inst.const_B
					else
						lhs = stack[inst.B]
					end

					if inst.is_KC then
						rhs = inst.const_C
					else
						rhs = stack[inst.C]
					end

					stack[inst.A] = lhs * rhs
				end
			else
				--[[9 SETTABLE]]
				local index, value

				if inst.is_KB then
					index = inst.const_B
				else
					index = stack[inst.B]
				end

				if inst.is_KC then
					value = inst.const_C
				else
					value = stack[inst.C]
				end

				stack[inst.A][index] = value
			end
		elseif op > 19 then
			if op < 29 then
				if op < 24 then
					if op < 22 then
						if op < 21 then
							--[[20 LEN]]
							stack[inst.A] = #stack[inst.B]
						else
							--[[21 CONCAT]]
							local str = stack[inst.B]

							for i = inst.B + 1, inst.C do str = str .. stack[i] end

							stack[inst.A] = str
						end
					elseif op > 22 then
						--[[23 EQ]]
						local lhs, rhs

						if inst.is_KB then
							lhs = inst.const_B
						else
							lhs = stack[inst.B]
						end

						if inst.is_KC then
							rhs = inst.const_C
						else
							rhs = stack[inst.C]
						end

						if (lhs == rhs) ~= (inst.A ~= 0) then pc = pc + 1 end
					else
						--[[22 JMP]]
						pc = pc + inst.sBx
					end
				elseif op > 24 then
					if op < 27 then
						if op < 26 then
							--[[25 LE]]
							local lhs, rhs

							if inst.is_KB then
								lhs = inst.const_B
							else
								lhs = stack[inst.B]
							end

							if inst.is_KC then
								rhs = inst.const_C
							else
								rhs = stack[inst.C]
							end

							if (lhs <= rhs) ~= (inst.A ~= 0) then pc = pc + 1 end
						else
							--[[26 TEST]]
							if (not stack[inst.A]) == (inst.C ~= 0) then pc = pc + 1 end
						end
					elseif op > 27 then
						--[[28 CALL]]
						local A = inst.A
						local B = inst.B
						local C = inst.C
						local params
						local sz_vals, l_vals

						if B == 0 then
							params = stktop - A
						else
							params = B - 1
						end

						sz_vals, l_vals = wrap_lua_variadic(stack[A](unpack(stack, A + 1, A + params)))

						if C == 0 then
							stktop = A + sz_vals - 1
						else
							sz_vals = C - 1
						end

						for i = 1, sz_vals do stack[A + i - 1] = l_vals[i] end
					else
						--[[27 TESTSET]]
						local A = inst.A
						local B = inst.B

						if (not stack[B]) == (inst.C ~= 0) then
							pc = pc + 1
						else
							stack[A] = stack[B]
						end
					end
				else
					--[[24 LT]]
					local lhs, rhs

					if inst.is_KB then
						lhs = inst.const_B
					else
						lhs = stack[inst.B]
					end

					if inst.is_KC then
						rhs = inst.const_C
					else
						rhs = stack[inst.C]
					end

					if (lhs < rhs) ~= (inst.A ~= 0) then pc = pc + 1 end
				end
			elseif op > 29 then
				if op < 34 then
					if op < 32 then
						if op < 31 then
							--[[30 RETURN]]
							local A = inst.A
							local B = inst.B
							local vals = {}
							local size

							if B == 0 then
								size = stktop - A + 1
							else
								size = B - 1
							end

							for i = 1, size do vals[i] = stack[A + i - 1] end

							close_lua_upvalues(openupvs, math.huge)
							return size, vals
						else
							--[[31 FORLOOP]]
							local A = inst.A
							local step = stack[A + 2]
							local index = stack[A] + step
							local limit = stack[A + 1]
							local loops

							if step == math.abs(step) then
								loops = index <= limit
							else
								loops = index >= limit
							end

							if loops then
								stack[inst.A] = index
								stack[inst.A + 3] = index
								pc = pc + inst.sBx
							end
						end
					elseif op > 32 then
						--[[33 TFORLOOP]]
						local A = inst.A
						local func = stack[A]
						local state = stack[A + 1]
						local index = stack[A + 2]
						local base = A + 3
						local vals

						stack[base + 2] = index
						stack[base + 1] = state
						stack[base] = func

						vals = {func(state, index)}

						for i = 1, inst.C do stack[base + i - 1] = vals[i] end

						if stack[base] ~= nil then
							stack[A + 2] = stack[base]
						else
							pc = pc + 1
						end
					else
						--[[32 FORPREP]]
						local A = inst.A
						local init, limit, step

						init = assert(tonumber(stack[A]), '`for` initial value must be a number')
						limit = assert(tonumber(stack[A + 1]), '`for` limit must be a number')
						step = assert(tonumber(stack[A + 2]), '`for` step must be a number')

						stack[A] = init - step
						stack[A + 1] = limit
						stack[A + 2] = step

						pc = pc + inst.sBx
					end
				elseif op > 34 then
					if op < 36 then
						--[[35 CLOSE]]
						close_lua_upvalues(openupvs, inst.A)
					elseif op > 36 then
						--[[37 VARARG]]
						local A = inst.A
						local size = inst.B

						if size == 0 then
							size = vargs.size
							stktop = A + size - 1
						end

						for i = 1, size do stack[A + i - 1] = vargs.list[i] end
					else
						--[[36 CLOSURE]]
						local sub = subs[inst.Bx + 1] -- offset for 1 based index
						local nups = sub.numupvals
						local uvlist

						if nups ~= 0 then
							uvlist = {}

							for i = 1, nups do
								local pseudo = code[pc + i - 1]

								if pseudo.op == 0 then -- @MOVE
									uvlist[i - 1] = open_lua_upvalue(openupvs, pseudo.B, stack)
								elseif pseudo.op == 4 then -- @GETUPVAL
									uvlist[i - 1] = upvs[pseudo.B]
								end
							end

							pc = pc + nups
						end

						stack[inst.A] = wrap_lua_func(sub, env, uvlist)
					end
				else
					--[[34 SETLIST]]
					local A = inst.A
					local C = inst.C
					local size = inst.B
					local tab = stack[A]
					local offset

					if size == 0 then size = stktop - A end

					if C == 0 then
						C = inst[pc].value
						pc = pc + 1
					end

					offset = (C - 1) * FIELDS_PER_FLUSH

					for i = 1, size do tab[i + offset] = stack[A + i] end
				end
			else
				--[[29 TAILCALL]]
				local A = inst.A
				local B = inst.B
				local params

				if B == 0 then
					params = stktop - A
				else
					params = B - 1
				end

				close_lua_upvalues(openupvs, math.huge)
				return wrap_lua_variadic(stack[A](unpack(stack, A + 1, A + params)))
			end
		else
			--[[19 NOT]]
			stack[inst.A] = not stack[inst.B]
		end

		exst.pc = pc
	end
end

function wrap_lua_func(state, env, upvals)
	local st_code = state.code
	local st_subs = state.subs
	local st_lines = state.lines
	local st_source = state.source
	local st_numparams = state.numparams

	local function exec_wrap(...)
		local stack = {}
		local varargs = {}
		local sizevarg = 0
		local sz_args, l_args = wrap_lua_variadic(...)

		local exst
		local ok, err, vals

		for i = 1, st_numparams do stack[i - 1] = l_args[i] end

		if st_numparams < sz_args then
			sizevarg = sz_args - st_numparams
			for i = 1, sizevarg do varargs[i] = l_args[st_numparams + i] end
		end

		exst = {
			varargs = {list = varargs, size = sizevarg},
			code = st_code,
			subs = st_subs,
			lines = st_lines,
			source = st_source,
			env = env,
			upvals = upvals,
			stack = stack,
			pc = 1,
		}

		ok, err, vals = pcall(exec_lua_func, exst, ...)

		if ok then
			return unpack(vals, 1, err)
		else
			on_lua_error(exst, err)
		end

		return -- explicit "return nothing"
	end

	return exec_wrap
end

return function(BCode, Env)
	return wrap_lua_func(stm_lua_bytecode(BCode), Env or getfenv(0))
end
