luapy (7) lua function call

小编 2026-06-29 阅读:1431 评论:0
load and call from lua_stack import LuaStack from lua_type import LuaType from lua_value impor...
  1. load and call
from lua_stack import LuaStack
from lua_type import LuaType
from lua_value import LuaValue
from arith_op import ArithOp
from arithmetic import Arithmetic
from cmp_op import CmpOp
from compare import Compare
from lua_table import LuaTable
from binary_chunk import BinaryChunk
from closure import Closure
from opcode import Instruction
from opcode import OpCode
from thread_state import ThreadStatus


class LuaState:
    def __init__(self):
        self.stack = LuaStack()

    # ...

    # vm
    def get_pc(self):
        return self.stack.pc

    def add_pc(self, n):
        self.stack.pc += n

    def fetch(self):
        code = self.stack.closure.proto.get_code()[self.stack.pc]
        self.stack.pc += 1
        return code

    def get_const(self, idx):
        self.stack.push(self.stack.closure.proto.get_constants()[idx])

    def get_rk(self, rk):
        if rk > 0xff:   # constant
            self.get_const(rk & 0xff)
        else:           # register
            self.push_value(rk + 1)

    # ...

    def load(self, chunk):
        bc = BinaryChunk(chunk)
        proto = bc.undump()
        closure = Closure(proto)
        self.stack.push(closure)
        return ThreadStatus.OK

    def call(self, nargs, nresults):
        val = self.stack.get(-(nargs+1))
        if isinstance(val, Closure):
            print(\'call %s<%d,%d>\' % (val.proto.get_source(), val.proto.get_line_defined(),
                                      val.proto.get_last_line_defined()))
            self.call_lua_closure(nargs, nresults, val)
        else:
            raise Exception(\'not function\')

    def call_lua_closure(self, nargs, nresults, c):
        nregs = c.proto.get_max_stack_size()
        nparams = c.proto.get_num_params()
        is_vararg = c.proto.get_is_vararg()

        # create new lua stack
        new_stack = LuaStack()
        new_stack.closure = c

        # pass args, pop func
        func_and_args = self.stack.popn(nargs+1)
        new_stack.pushn(func_and_args[1:], nparams)
        if nargs > nparams and is_vararg:
            new_stack.varargs = func_and_args[nparams+1:]

        # run closure
        self.push_lua_stack(new_stack)
        self.set_top(nregs)
        self.run_lua_closure()
        self.pop_lua_stack()

        # return results
        if nresults != 0:
            results = new_stack.popn(new_stack.top() - nregs)
            self.stack.check(len(results))
            self.stack.pushn(results, nresults)

    def run_lua_closure(self):
        while True:
            pc = self.get_pc() + 1
            inst = Instruction(self.fetch())
            inst.execute(self)
            print(\'[%02d] %-12s \' % (pc, inst.op_name()), end=\'\')
            self.print_stack()
            if inst.op_code() == OpCode.RETURN:
                break

    def push_lua_stack(self, s):
        s.caller = self.stack
        self.stack = s

    def pop_lua_stack(self):
        s = self.stack
        self.stack = s.caller
        s.caller = None

    def register_count(self):
        return self.stack.closure.proto.get_max_stack_size()

    def load_vararg(self, n):
        if n < 0:
            n = len(self.stack.varargs)

        self.stack.check(n)
        self.stack.pushn(self.stack.varargs, n)

    def load_proto(self, idx):
        proto = self.stack.closure.proto.get_protos()[idx]
        c = Closure(proto)
        self.stack.push(c)

  1. instructions
# R(A)[(C-1)*LFIELDS_PER_FLUSH+i] := R(A+i), 1 <= i <= B
def setlist(inst, vm):
    a, b, c = inst.a_b_c()
    a += 1
    c = c - 1 if c > 0 else inst.ax(vm.fetch())

    is_zero = b == 0
    if is_zero:
        b = vm.to_integer(-1) - a - 1
        vm.pop(1)

    vm.check_stack(1)
    idx = c * LFIELDS_PER_FLUSH
    for i in range(1, b+1):
        idx += 1
        vm.push_value(a+i)
        vm.set_i(a, idx)

    if is_zero:
        for i in range(vm.register_count() + 1, vm.get_top()+1):
            idx += 1
            vm.push_value(i)
            vm.set_i(a, idx)
        vm.set_top(vm.register_count())


# R(A+1) := R(B); R(A) := R(B)[RK(C)]
def luaself(inst, vm):
    a, b, c = inst.a_b_c()
    a += 1
    b += 1
    vm.copy(b, a+1)
    vm.get_rk(c)
    vm.get_table(b)
    vm.replace(a)


# R(A) := closure(KPROTO[Bx])
def closure(inst, vm):
    a, bx = inst.a_bx()
    a += 1
    vm.load_proto(bx)
    vm.replace(a)


def vararg(inst, vm):
    a, b, _ = inst.a_b_c()
    a += 1
    if b != 1:
        vm.load_vararg(b-1)
        pop_results(a, b, vm)


def tailcall(inst, vm):
    a, b, _ = inst.a_b_c()
    a += 1
    c = 0
    nargs = push_func_and_args(a, b, vm)
    vm.call(nargs, c-1)
    pop_results(a, c, vm)


def call(inst, vm):
    a, b, c = inst.a_b_c()
    a += 1
    nargs = push_func_and_args(a, b, vm)
    vm.call(nargs, c-1)
    pop_results(a, c, vm)


def luaret(inst, vm):
    a, b, _ = inst.a_b_c()
    a += 1
    if b == 1:
        pass
    elif b > 1:
        vm.check_stack(b-1)
        for i in range(a, a+b-1):
            vm.push_value(i)
    else:
        fix_stack(a, vm)


def push_func_and_args(a, b, vm):
    if b >= 1:
        vm.check_stack(b)
        for i in range(a, a+b):
            vm.push_value(i)
        return b-1
    else:
        fix_stack(a, vm)
        return vm.get_top() - vm.register_count() - 1


def fix_stack(a, vm):
    x = vm.to_integer(-1)
    vm.pop(1)

    vm.check_stack(x-a)
    for i in range(a, x):
        vm.push_value(i)
    vm.rotate(vm.register_count()+1, x-a)


def pop_results(a, c, vm):
    if c == 1:
        pass
    elif c > 1:
        for i in range(a+c-2, a-1, -1):
            vm.replace(i)
    else:
        vm.check_stack(1)
        vm.push_integer(a)


op_codes = [
    #      T  A  B       C       mode   name        action
    OpCode(0, 1, OpArgR, OpArgN, IABC,  \"MOVE    \", move),      # R(A) := R(B)
    OpCode(0, 1, OpArgK, OpArgN, IABx,  \"LOADK   \", loadk),     # R(A) := Kst(Bx)
    OpCode(0, 1, OpArgN, OpArgN, IABx,  \"LOADKX  \", loadkx),    # R(A) := Kst(extra arg)
    OpCode(0, 1, OpArgU, OpArgU, IABC,  \"LOADBOOL\", loadbool),  # R(A) := (bool)B; if (C) pc++
    OpCode(0, 1, OpArgU, OpArgN, IABC,  \"LOADNIL \", loadnil),   # R(A), R(A+1), ..., R(A+B) := nil
    OpCode(0, 1, OpArgU, OpArgN, IABC,  \"GETUPVAL\", None),      # R(A) := UpValue[B]
    OpCode(0, 1, OpArgU, OpArgK, IABC,  \"GETTABUP\", None),      # R(A) := UpValue[B][RK(C)]
    OpCode(0, 1, OpArgR, OpArgK, IABC,  \"GETTABLE\", gettable),  # R(A) := R(B)[RK(C)]
    OpCode(0, 0, OpArgK, OpArgK, IABC,  \"SETTABUP\", None),      # UpValue[A][RK(B)] := RK(C)
    OpCode(0, 0, OpArgU, OpArgN, IABC,  \"SETUPVAL\", None),      # UpValue[B] := R(A)
    OpCode(0, 0, OpArgK, OpArgK, IABC,  \"SETTABLE\", settable),  # R(A)[RK(B)] := RK(C)
    OpCode(0, 1, OpArgU, OpArgU, IABC,  \"NEWTABLE\", newtable),  # R(A) := {} (size = B,C)
    OpCode(0, 1, OpArgR, OpArgK, IABC,  \"SELF    \", luaself),   # R(A+1) := R(B); R(A) := R(B)[RK(C)]
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"ADD     \", add),       # R(A) := RK(B) + RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"SUB     \", sub),       # R(A) := RK(B) - RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"MUL     \", mul),       # R(A) := RK(B) * RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"MOD     \", mod),       # R(A) := RK(B) % RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"POW     \", luapow),    # R(A) := RK(B) ^ RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"DIV     \", div),       # R(A) := RK(B) / RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"IDIV    \", idiv),      # R(A) := RK(B) // RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"BAND    \", band),      # R(A) := RK(B) & RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"BOR     \", bor),       # R(A) := RK(B) | RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"BXOR    \", bxor),      # R(A) := RK(B) ~ RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"SHL     \", shl),       # R(A) := RK(B) << RK(C)
    OpCode(0, 1, OpArgK, OpArgK, IABC,  \"SHR     \", shr),       # R(A) := RK(B) >> RK(C)
    OpCode(0, 1, OpArgR, OpArgN, IABC,  \"UNM     \", unm),       # R(A) := -R(B)
    OpCode(0, 1, OpArgR, OpArgN, IABC,  \"BNOT    \", bnot),      # R(A) := ~R(B)
    OpCode(0, 1, OpArgR, OpArgN, IABC,  \"NOT     \", luanot),    # R(A) := not R(B)
    OpCode(0, 1, OpArgR, OpArgN, IABC,  \"LEN     \", length),    # R(A) := length of R(B)
    OpCode(0, 1, OpArgR, OpArgR, IABC,  \"CONCAT  \", concat),    # R(A) := R(B).. ... ..R(C)
    OpCode(0, 0, OpArgR, OpArgN, IAsBx, \"JMP     \", jmp),       # pc+=sBx; if (A) close all upvalues >= R(A - 1)
    OpCode(1, 0, OpArgK, OpArgK, IABC,  \"EQ      \", eq),        # if ((RK(B) == RK(C)) ~= A) then pc++
    OpCode(1, 0, OpArgK, OpArgK, IABC,  \"LT      \", lt),        # if ((RK(B) <  RK(C)) ~= A) then pc++
    OpCode(1, 0, OpArgK, OpArgK, IABC,  \"LE      \", le),        # if ((RK(B) <= RK(C)) ~= A) then pc++
    OpCode(1, 0, OpArgN, OpArgU, IABC,  \"TEST    \", test),      # if not (R(A) <=> C) then pc++
    OpCode(1, 1, OpArgR, OpArgU, IABC,  \"TESTSET \", testset),   # if (R(B) <=> C) then R(A) := R(B) else pc++
    OpCode(0, 1, OpArgU, OpArgU, IABC,  \"CALL    \", call),      # R(A), ...,R(A+C-2) := R(A)(R(A+1), ...,R(A+B-1))
    OpCode(0, 1, OpArgU, OpArgU, IABC,  \"TAILCALL\", tailcall),  # return R(A)(R(A+1), ... ,R(A+B-1))
    OpCode(0, 0, OpArgU, OpArgN, IABC,  \"RETURN  \", luaret),    # return R(A), ... ,R(A+B-2)
    OpCode(0, 1, OpArgR, OpArgN, IAsBx, \"FORLOOP \", forloop),   # R(A)+=R(A+2); if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
    OpCode(0, 1, OpArgR, OpArgN, IAsBx, \"FORPREP \", forprep),   # R(A)-=R(A+2); pc+=sBx
    OpCode(0, 0, OpArgN, OpArgU, IABC,  \"TFORCALL\", None),      # R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
    OpCode(0, 1, OpArgR, OpArgN@font-face {
				font-family: "autolinktags";
				src: url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.woff2") format("woff2"),
				url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.woff") format("woff"),
				url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.ttf") format("truetype");
				font-weight:normal;
				font-style:normal;
			}.tagslink::after { content:"\e613"; margin:2px 0 0 0px; font-size:12px; font-family:"autolinktags"; display:inline-block; vertical-align:top; }															
版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
标签列表