local function l(l,g)return function(c)local N=g(c.source,c.index)c.index=c.index+l return N end end local function g(l)local g=l:s_int()local c={}for g=1,g,1 do local N=l:s_ins()local I=bit.band(N,63)local Y=OPCODE_T[I]local o=OPCODE_M[I]local h={value=N;op=OPCODE_RM[I],A=bit.band(bit.rshift(N,6),255)}if Y=="\065\066\067"then h.B=bit.band(bit.rshift(N,23),511)h.C=bit.band(bit.rshift(N,14),511)h.is_KB=o.b=="\079\112\065\114\103\075"and h.B>255 h.is_KC=o.c=="\079\112\065\114\103\075"and h.C>255 elseif Y=="\065\066\120"then h.Bx=bit.band(bit.rshift(N,14),262143)h.is_K=o.b=="\079\112\065\114\103\075"elseif Y=="\065\115\066\120"then h.sBx=bit.band(bit.rshift(N,14),262143)-131071 end c[g]=h end return c end local function c(l)local g=l:s_int()local c={}for g=1,g,1 do local N=stm_byte(l)local I if N==1 then I=stm_byte(l)~=0 elseif N==3 then I=l:s_num()elseif N==4 then I=stm_lstring(l)end c[g]=I end return c end local function N(l,g)local c=l:s_int()local N={}for c=1,c,1 do N[c]=stm_lua_func(l,g)end return N end local function I(l)local g=l:s_int()local c={}for g=1,g,1 do c[g]=l:s_int()end return c end local function Y(l)local g=l:s_int()local c={}for g=1,g,1 do c[g]={varname=stm_lstring(l);startpc=l:s_int();endpc=l:s_int()}end return c end local function o(l)local g=l:s_int()local c={}for g=1,g,1 do c[g]=stm_lstring(l)end return c end function stm_lua_func(l,h)local m={}local K=stm_lstring(l)or h m.source=K l:s_int()l:s_int()m.numupvals=stm_byte(l)m.numparams=stm_byte(l)stm_byte(l)stm_byte(l)m.code=g(l)m.const=c(l)m.subs=N(l,K)m.lines=I(l)Y(l)o(l)for l,g in ipairs(m.code)do if g.is_K then g.const=m.const[g.Bx+1]else if g.is_KB then g.const_B=m.const[g.B-255]end if g.is_KC then g.const_C=m.const[g.C-255]end end end return m end function stm_lua_bytecode(g)local c local N local I local Y local o local h local m local K={index=1;source=g}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")N=stm_byte(K)~=0 I=stm_byte(K)Y=stm_byte(K)o=stm_byte(K)h=stm_byte(K)m=stm_byte(K)~=0 c=N and rd_int_le or rd_int_be K.s_int=cst_int_rdr(I,c)K.s_szt=cst_int_rdr(Y,c)K.s_ins=cst_int_rdr(o,c)if m then K.s_num=cst_int_rdr(h,c)elseif float_types[h]then K.s_num=l(h,float_types[h][N 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 h(l,g)for c,N in pairs(l)do if N.index>=g then N.value=N.store[N.index]N.store=N N.index="\118\097\108\117\101"l[c]=nil end end end local function m(l,g,c)local N=l[g]if not N then N={index=g,store=c}l[g]=N end return N end local function K(...)return select("\035",...),{...}end local function U(l,g)local c=l.source local N=l.lines[l.pc-1]local I,Y,o=string.match(g or"","\094\040\046-\041\058\040\037\100\043\041\058\037\115\043\040\046\043\041")local h="\037\115\058\037\105\058 \091\037\115\058\037\105\093 \037\115"N=N or"\048"I=I or"\063"Y=Y or"\048"o=o or g or""error(string.format(h,c,N,I,Y,o),0)end local function r(l)local g=l.code local c=l.subs local N=l.env local I=l.upvals local Y=l.varargs local o=-1 local U={}local r=l.stack local M=l.pc while true do local R=g[M]local z=R.op M=M+1 if z<18 then if z<8 then if z<3 then if z<1 then for l=R.A,R.B,1 do r[l]=nil end elseif z>1 then local l=I[R.B]r[R.A]=l.store[l.index]else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A]=l+g end elseif z>3 then if z<6 then if z>4 then local l=R.A local g=R.B local c if R.is_KC then c=R.const_C else c=r[R.C]end r[l+1]=r[g]r[l]=r[g][c]else r[R.A]=N[R.const]end elseif z>6 then local l if R.is_KC then l=R.const_C else l=r[R.C]end r[R.A]=r[R.B][l]else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A]=l-g end else r[R.A]=r[R.B]end elseif z>8 then if z<13 then if z<10 then N[R.const]=r[R.A]elseif z>10 then if z<12 then local l=R.A local g=R.B local c=R.C local N local I,Y if g==0 then N=o-l else N=g-1 end I,Y=K(r[l](unpack(r,l+1,l+N)))if c==0 then o=(l+I)-1 else I=c-1 end for g=1,I,1 do r[(l+g)-1]=Y[g]end else local l=I[R.B]l.store[l.index]=r[R.A]end else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A]=l*g end elseif z>13 then if z<16 then if z>14 then local l=R.A local g=R.B local c if g==0 then c=o-l else c=g-1 end h(U,0)return K(r[l](unpack(r,l+1,l+c)))else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A][l]=g end elseif z>16 then r[R.A]={}else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A]=l/g end else r[R.A]=R.const end else local l=R.A local g=r[l+2]local c=r[l]+g local N=r[l+1]local I if g==math.abs(g)then I=c<=N else I=c>=N end if I then r[R.A]=c r[R.A+3]=c M=M+R.sBx end end elseif z>18 then if z<28 then if z<23 then if z<20 then r[R.A]=#r[R.B]elseif z>20 then if z<22 then local l=R.A local g=R.B local c={}local N if g==0 then N=(o-l)+1 else N=g-1 end for g=1,N,1 do c[g]=r[(l+g)-1]end h(U,0)return N,c else local l=r[R.B]for g=R.B+1,R.C,1 do l=l..r[g]end r[R.A]=l end else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A]=l%g end elseif z>23 then if z<26 then if z>24 then h(U,R.A)else local l,c if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then c=R.const_C else c=r[R.C]end if(l==c)==(R.A~=0)then M=M+g[M].sBx end M=M+1 end elseif z>26 then local l,c if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then c=R.const_C else c=r[R.C]end if(l<c)==(R.A~=0)then M=M+g[M].sBx end M=M+1 else local l,g if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then g=R.const_C else g=r[R.C]end r[R.A]=l^g end else r[R.A]=R.B~=0 if R.C~=0 then M=M+1 end end elseif z>28 then if z<33 then if z<30 then local l,c if R.is_KB then l=R.const_B else l=r[R.B]end if R.is_KC then c=R.const_C else c=r[R.C]end if(l<=c)==(R.A~=0)then M=M+g[M].sBx end M=M+1 elseif z>30 then if z<32 then local l=c[R.Bx+1]local Y=l.numupvals local o if Y~=0 then o={}for l=1,Y,1 do local c=g[(M+l)-1]if c.op==OPCODE_RM[0]then o[l-1]=m(U,c.B,r)elseif c.op==OPCODE_RM[4]then o[l-1]=I[c.B]end end M=M+Y end r[R.A]=wrap_lua_func(l,N,o)else local l=R.A local g=R.B if not r[g]==(R.C~=0)then M=M+1 else r[l]=r[g]end end else r[R.A]=-r[R.B]end elseif z>33 then if z<36 then if z>34 then local l=R.A local g=R.B if g==0 then g=Y.size o=(l+g)-1 end for g=1,g,1 do r[(l+g)-1]=Y.list[g]end else local l=R.A local g,c,N g=assert(tonumber(r[l]),"\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")c=assert(tonumber(r[l+1]),"\096\102\111\114\096 \108\105\109\105\116 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")N=assert(tonumber(r[l+2]),"\096\102\111\114\096 \115\116\101\112 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")r[l]=g-N r[l+1]=c r[l+2]=N M=M+R.sBx end elseif z>36 then local l=R.A local g=R.C local c=R.B local N=r[l]local I if c==0 then c=o-l end if g==0 then g=R[M].value M=M+1 end I=(g-1)*FIELDS_PER_FLUSH for g=1,c,1 do N[g+I]=r[l+g]end else r[R.A]=not r[R.B]end else if not r[R.A]==(R.C~=0)then M=M+1 end end else local l=R.A local g=r[l]local c=r[l+1]local N=r[l+2]local I=l+3 local Y if not N and(not c and type(g)=="\116\097\098\108\101")then local I=pcall(getmetatable,g)local Y=I and not pcall(setmetatable,g,getmetatable(g))or not I local o=I and getmetatable(g)if not(table.isfrozen and table.isfrozen(g))and(Y and not o)then warn("\091\070\105\079\110\101\093\058 \084\104\101 \116\097\098\108\101 \104\097\115 \097 \109\101\116\097\116\097\098\108\101 \098\117\116\115 \105\116\'\115 \104\105\100\100\101\110\044 \095\095\105\116\101\114 \097\110\100 \095\095\099\097\108\108 \119\111\110\'\116 \119\111\114\107 \105\110 \102\111\114\108\111\111\112\046")end if not(type(o)=="\116\097\098\108\101"and rawget(o,"\095\095\099\097\108\108"))then g,c,N=type(o)=="\116\097\098\108\101"and rawget(o,"\095\095\105\116\101\114")or next,g,nil r[l],r[l+1],r[l+2]=g,c,N end end r[I+2]=N r[I+1]=c r[I]=g Y={g(c,N)}for l=1,R.C,1 do r[(I+l)-1]=Y[l]end if r[I]~=nil then r[l+2]=r[I]else M=M+1 end end else M=M+R.sBx end l.pc=M end end function wrap_lua_func(l,g,c)local N=l.code local I=l.subs local Y=l.lines local o=l.source local h=l.numparams local function m(...)local l={}local m={}local M=0 local R,z=K(...)local G local Q,f,e for g=1,h,1 do l[g-1]=z[g]end if h<R then M=R-h for l=1,M,1 do m[l]=z[h+l]end end G={varargs={list=m,size=M};code=N,subs=I,lines=Y,source=o;env=g;upvals=c,stack=l;pc=1}Q,f,e=pcall(r,G,...)if Q then return unpack(e,1,f)else U(G,f)end return end return m end return function(l,g)return wrap_lua_func(stm_lua_bytecode(l),g or{})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 = OPCODE_RM[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 = string.match(err or '', '^(.-):(%d+):%s+(.+)')
	local fmt = '%s:%i: [%s:%i] %s'

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

	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 < 18 then
			if op < 8 then
				if op < 3 then
					if op < 1 then
						--[[LOADNIL]]
						for i = inst.A, inst.B do stack[i] = nil end
					elseif op > 1 then
						--[[GETUPVAL]]
						local uv = upvs[inst.B]

						stack[inst.A] = uv.store[uv.index]
					else
						--[[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 > 3 then
					if op < 6 then
						if op > 4 then
							--[[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]
						else
							--[[GETGLOBAL]]
							stack[inst.A] = env[inst.const]
						end
					elseif op > 6 then
						--[[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]
					else
						--[[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
					end
				else --[[MOVE]]
					stack[inst.A] = stack[inst.B]
				end
			elseif op > 8 then
				if op < 13 then
					if op < 10 then
						--[[SETGLOBAL]]
						env[inst.const] = stack[inst.A]
					elseif op > 10 then
						if op < 12 then
							--[[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
							--[[SETUPVAL]]
							local uv = upvs[inst.B]

							uv.store[uv.index] = stack[inst.A]
						end
					else
						--[[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
				elseif op > 13 then
					if op < 16 then
						if op > 14 then
							--[[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, 0)
							return wrap_lua_variadic(stack[A](unpack(stack, A + 1, A + params)))
						else
							--[[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 > 16 then
						--[[NEWTABLE]]
						stack[inst.A] = {}
					else
						--[[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
					end
				else
					--[[LOADK]]
					stack[inst.A] = inst.const
				end
			else
				--[[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 > 18 then
			if op < 28 then
				if op < 23 then
					if op < 20 then
						--[[LEN]]
						stack[inst.A] = #stack[inst.B]
					elseif op > 20 then
						if op < 22 then
							--[[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, 0)
							return size, vals
						else
							--[[CONCAT]]
							local str = stack[inst.B]

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

							stack[inst.A] = str
						end
					else
						--[[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 > 23 then
					if op < 26 then
						if op > 24 then
							--[[CLOSE]]
							close_lua_upvalues(openupvs, inst.A)
						else
							--[[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 + code[pc].sBx end

							pc = pc + 1
						end
					elseif op > 26 then
						--[[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 + code[pc].sBx end

						pc = pc + 1
					else
						--[[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
					--[[LOADBOOL]]
					stack[inst.A] = inst.B ~= 0

					if inst.C ~= 0 then pc = pc + 1 end
				end
			elseif op > 28 then
				if op < 33 then
					if op < 30 then
						--[[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 + code[pc].sBx end

						pc = pc + 1
					elseif op > 30 then
						if op < 32 then
							--[[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 == OPCODE_RM[0] then -- @MOVE
										uvlist[i - 1] = open_lua_upvalue(openupvs, pseudo.B, stack)
									elseif pseudo.op == OPCODE_RM[4] then -- @GETUPVAL
										uvlist[i - 1] = upvs[pseudo.B]
									end
								end

								pc = pc + nups
							end

							stack[inst.A] = wrap_lua_func(sub, env, uvlist)
						else
							--[[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
						--[[UNM]]
						stack[inst.A] = -stack[inst.B]
					end
				elseif op > 33 then
					if op < 36 then
						if op > 34 then
							--[[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
							--[[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 > 36 then
						--[[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
					else
						--[[NOT]]
						stack[inst.A] = not stack[inst.B]
					end
				else
					--[[TEST]]
					if (not stack[inst.A]) == (inst.C ~= 0) then pc = pc + 1 end
				end
			else
				--[[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

				-- === Luau compatibility - General iteration begin ===
				-- // ccuser44 added support for generic iteration
				-- (Please don't use general iteration in vanilla Lua code)
				if not index and not state and type(func) == "table" then
					-- Hacky check to see if __metatable is locked
					local canGetMt = pcall(getmetatable, func)
					local isMtLocked = canGetMt and not pcall(setmetatable, func, getmetatable(func)) or not canGetMt
					local metatable = canGetMt and getmetatable(func)

					if not (table.isfrozen and table.isfrozen(func)) and isMtLocked and not metatable then
						warn("[FiOne]: The table has a metatable buts it's hidden, __iter and __call won't work in forloop.")
					end

					if not (type(metatable) == "table" and rawget(metatable, "__call")) then
						func, state, index = (type(metatable) == "table" and rawget(metatable, "__iter") or next), func, nil
						stack[A], stack[A + 1], stack[A + 2] = func, state, index
					end
				end
				-- === Luau compatibility - General iteration end ===

				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
			end
		else
			--[[JMP]]
			pc = pc + inst.sBx
		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 {})
end
