luapy (4) lua operator

1)operator(arithmetic, compare)

from enum import Enum, unique


@unique
class ArithOp(Enum):
    ADD = 0    # +
    SUB = 1    # -
    MUL = 2    # *
    MOD = 3    # %
    POW = 4    # ^
    DIV = 5    # /
    IDIV = 6   # //
    BAND = 7   # &
    BOR = 8    # |
    BXOR = 9   # ~
    SHL = 10   # <<
    SHR = 11   # >>
    UNM = 12   # -
    BNOT = 13  # ~

from enum import Enum, unique


@unique
class CmpOp(Enum):
    EQ = 0    # ==
    LT = 1    # <
    LE = 2    # <=

2)lua state

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


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

    def get_top(self):
        return self.stack.top()

    # ...

    def arith(self, op):
        b = self.stack.pop()
        a = self.stack.pop() if (op != ArithOp.UNM and op != ArithOp.BNOT) else b
        result = Arithmetic.arith(a, op, b)
        assert(result is not None)
        self.stack.push(result)

    def len(self, idx):
        val = self.stack.get(idx)
        assert(val is not None)
        self.stack.push(len(val))

    def concat(self, n):
        if n == 0:
            self.stack.push('')
        elif n >= 2:
            for i in range(1, n):
                assert(self.is_string(-1) and self.is_string(-2))
                s2 = self.to_string(-1)
                s1 = self.to_string(-2)
                self.stack.pop()
                self.stack.pop()
                self.stack.push(s1+s2)

    def compare(self, idx1, op, idx2):
        if not self.stack.is_valid(idx1) or not self.stack.is_valid(idx2):
            return False

        a = self.stack.get(idx1)
        b = self.stack.get(idx2)

        if op == CmpOp.EQ:
            return Compare.eq(a, b)
        elif op == CmpOp.LT:
            return Compare.lt(a, b)
        elif op == CmpOp.LE:
            return Compare.le(a, b)

3)arithmetic

from collections import namedtuple
from lua_value import LuaValue
from arith_op import ArithOp


def add(a, b):
    return a + b


def sub(a, b):
    return a - b


def mul(a, b):
    return a * b


def mod(a, b):
    return a % b


def div(a, b):
    return a / b


def fdiv(a, b):
    return a // b


def band(a, b):
    return a & b


def bor(a, b):
    return a | b


def bxor(a, b):
    return a ^ b


def shl(a, b):
    if b >= 0:
        return a << b
    return a >> (-b)


def shr(a, b):
    if b >= 0:
        return a >> b
    return a << (-b)


def unm(a, b):
    return -a + (b-b)


def bnot(a, b):
    return ~a + (b-b)


class Arithmetic:
    operator = namedtuple('operator', ['integer_func', 'float_func'])
    operators = {
        ArithOp.ADD:  operator(add,  add),
        ArithOp.SUB:  operator(sub,  sub),
        ArithOp.MUL:  operator(mul,  mul),
        ArithOp.MOD:  operator(mod,  mod),
        ArithOp.POW:  operator(None, pow),
        ArithOp.DIV:  operator(None, div),
        ArithOp.IDIV: operator(fdiv, fdiv),
        ArithOp.BAND: operator(band, None),
        ArithOp.BOR:  operator(bor,  None),
        ArithOp.BXOR: operator(bxor, None),
        ArithOp.SHL:  operator(shl,  None),
        ArithOp.SHR:  operator(shr,  None),
        ArithOp.UNM:  operator(unm,  unm),
        ArithOp.BNOT: operator(bnot, None)
    }

    @staticmethod
    def arith(a, op, b):
        integer_func = Arithmetic.operators[op].integer_func
        float_func = Arithmetic.operators[op].float_func

        if float_func is None:
            x = LuaValue.to_integer(a)
            if x:
                y = LuaValue.to_integer(b)
                if y:
                    return integer_func(x, y)
        else:
            if integer_func is not None:
                if isinstance(a, int) and isinstance(b, int):
                    return integer_func(int(a), int(b))
            x = LuaValue.to_float(a)
            if x:
                y = LuaValue.to_float(b)
                if y:
                    return float_func(x, y)

        return None

4)compare


class Compare:
    @staticmethod
    def eq(a, b):
        if a is None:
            return b is None
        if isinstance(a, bool) or isinstance(a, str):
            return a == b
        if isinstance(a, int):
            if isinstance(b, int):
                return a == b
            elif isinstance(b, float):
                return float(a) == b
            else:
                return False
        if isinstance(a, float):
            if isinstance(b, float):
                return a == b
            elif isinstance(b, int):
                return a == float(b)
            else:
                return False

    @staticmethod
    def lt(a, b):
        if isinstance(a, str) and isinstance(b, str):
            return a < b
        if isinstance(a, int):
            if isinstance(b, int):
                return a < b
            elif isinstance(b, float):
                return float(a) < b
        if isinstance(a, float):
            if isinstance(b, float):
                return a < b
            elif isinstance(b, int):
                return a < float(b)

        raise Exception('Comparison Error')

    @staticmethod
    def le(a, b):
        if isinstance(a, str) and isinstance(b, str):
            return a <= b
        if isinstance(a, int):
            if isinstance(b, int):
                return a <= b
            elif isinstance(b, float):
                return float(a) <= b
        if isinstance(a, float):
            if isinstance(b, float):
                return a <= b
            elif isinstance(b, int):
                return a <= float(b)

        raise Exception('Comparison Error')

5)test

from lua_state import LuaState
from arith_op import ArithOp
from cmp_op import CmpOp


def main():
    ls = LuaState()

    ls.push_integer(1)
    ls.push_string('2.0')
    ls.push_string('3.0')
    ls.push_number(4.0)
    ls.dump()

    ls.arith(ArithOp.ADD)
    ls.dump()
    ls.arith(ArithOp.BNOT)
    ls.dump()

    ls.len(2)
    ls.dump()
    ls.concat(3)
    ls.dump()
    ls.push_boolean(ls.compare(1, CmpOp.EQ, 2))
    ls.dump()

    ls.push_number(2)
    ls.push_number(2)
    ls.dump()
    ls.arith(ArithOp.POW)
    ls.dump()

    ls.push_number(3.0)
    ls.push_boolean(ls.compare(4, CmpOp.LT, 5))
    ls.dump()

    ls.push_string('hello')
    ls.push_string('world')
    ls.push_boolean(ls.compare(7, CmpOp.LE, 8))
    ls.dump()


if __name__ == '__main__':
    main()

result:

[1]["2.0"]["3.0"][4]
[1]["2.0"][7]
[1]["2.0"][-8]
[1]["2.0"][-8][3]
[1]["2.0-83"]
[1]["2.0-83"][false]
[1]["2.0-83"][false][2][2]
[1]["2.0-83"][false][4]
[1]["2.0-83"][false][4][3][false]
[1]["2.0-83"][false][4][3][false]["hello"]["world"][true]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值