1# Python bindings for Yasm: Pyrex input file for expr.h
2#
3#  Copyright (C) 2006  Michael Urman, Peter Johnson
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
18# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24# POSSIBILITY OF SUCH DAMAGE.
25
26cdef extern from *:
27    # Defined as a macro, so not automatically brought in by pyxelator
28    cdef yasm_expr *yasm_expr_simplify(yasm_expr *e, int calc_bc_dist)
29
30import operator
31__op = {}
32for ops, operation in [
33    ((operator.__add__, operator.add, '+'), YASM_EXPR_ADD),
34    ((operator.__and__, operator.and_, '&'), YASM_EXPR_AND),
35    ((operator.__div__, operator.div, '/'), YASM_EXPR_SIGNDIV),
36    ((operator.__floordiv__, operator.floordiv, '//'), YASM_EXPR_SIGNDIV),
37    ((operator.__ge__, operator.ge, '>='), YASM_EXPR_GE),
38    ((operator.__gt__, operator.gt, '>'), YASM_EXPR_GT),
39    ((operator.__inv__, operator.inv, '~'), YASM_EXPR_NOT),
40    ((operator.__invert__, operator.invert), YASM_EXPR_NOT),
41    ((operator.__le__, operator.le, '<='), YASM_EXPR_LE),
42    ((operator.__lt__, operator.lt, '<'), YASM_EXPR_LT),
43    ((operator.__mod__, operator.mod, '%'), YASM_EXPR_SIGNMOD),
44    ((operator.__mul__, operator.mul, '*'), YASM_EXPR_MUL),
45    ((operator.__neg__, operator.neg), YASM_EXPR_NEG),
46    ((operator.__not__, operator.not_, 'not'), YASM_EXPR_LNOT),
47    ((operator.__or__, operator.or_, '|'), YASM_EXPR_OR),
48    ((operator.__sub__, operator.sub, '-'), YASM_EXPR_SUB),
49    ((operator.__xor__, operator.xor, '^'), YASM_EXPR_XOR),
50    ]:
51    for op in ops:
52        __op[op] = operation
53
54del operator, op, ops, operation
55
56cdef object __make_expression(yasm_expr *expr):
57    return Expression(__pass_voidp(expr, Expression))
58
59cdef class Expression:
60    cdef yasm_expr *expr
61
62    def __cinit__(self, op, *args, **kwargs):
63        self.expr = NULL
64
65        if isinstance(op, Expression):
66            self.expr = yasm_expr_copy((<Expression>op).expr)
67            return
68        if PyCObject_Check(op):
69            self.expr = <yasm_expr *>__get_voidp(op, Expression)
70            return
71
72        cdef size_t numargs
73        cdef unsigned long line
74
75        op = __op.get(op, op)
76        numargs = len(args)
77        line = kwargs.get('line', 0)
78
79        if numargs == 0 or numargs > 2:
80            raise NotImplementedError
81        elif numargs == 2:
82            self.expr = yasm_expr_create(op, self.__new_item(args[0]),
83                                         self.__new_item(args[1]), line)
84        else:
85            self.expr = yasm_expr_create(op, self.__new_item(args[0]), NULL,
86                                         line)
87
88    cdef yasm_expr__item* __new_item(self, value) except NULL:
89        cdef yasm_expr__item *retval
90        if isinstance(value, Expression):
91            return yasm_expr_expr(yasm_expr_copy((<Expression>value).expr))
92        #elif isinstance(value, Symbol):
93        #    return yasm_expr_sym((<Symbol>value).sym)
94        #elif isinstance(value, Register):
95        #    return yasm_expr_reg((<Register>value).reg)
96        elif isinstance(value, FloatNum):
97            return yasm_expr_float(yasm_floatnum_copy((<FloatNum>value).flt))
98        elif isinstance(value, IntNum):
99            return yasm_expr_int(yasm_intnum_copy((<IntNum>value).intn))
100        else:
101            try:
102                intnum = IntNum(value)
103            except:
104                raise ValueError("Invalid item value type '%s'" % type(value))
105            else:
106                retval = yasm_expr_int((<IntNum>intnum).intn)
107                (<IntNum>intnum).intn = NULL
108                return retval
109
110    def __dealloc__(self):
111        if self.expr != NULL: yasm_expr_destroy(self.expr)
112
113    def simplify(self, calc_bc_dist=False):
114        self.expr = yasm_expr_simplify(self.expr, calc_bc_dist)
115
116    def extract_segoff(self):
117        cdef yasm_expr *retval
118        retval = yasm_expr_extract_segoff(&self.expr)
119        if retval == NULL:
120            raise ValueError("not a SEG:OFF expression")
121        return __make_expression(retval)
122
123    def extract_wrt(self):
124        cdef yasm_expr *retval
125        retval = yasm_expr_extract_wrt(&self.expr)
126        if retval == NULL:
127            raise ValueError("not a WRT expression")
128        return __make_expression(retval)
129
130    def get_intnum(self, calc_bc_dist=False):
131        cdef yasm_intnum *retval
132        retval = yasm_expr_get_intnum(&self.expr, calc_bc_dist)
133        if retval == NULL:
134            raise ValueError("not an intnum expression")
135        return __make_intnum(yasm_intnum_copy(retval))
136
137