Пример #1
0
 def _get_stmt_ops(self):
     if not self._body:
         return []
     start = _get_ops(self._start)
     end = _get_ops(self._end)
     st = start[-1][-1]
     et = end[-1][-1]
     if st is not IntType:
         co = IntType().coerce_ops(st)
         if co is None:
             raise TypeError("invalid type for loop range: %s" % st)
         start += co
     if et is not IntType:
         co = IntType().coerce_ops(et)
         if co is None:
             raise TypeError("invalid type for loop range: %s" % et)
         end += co
     body = []
     for s in self._body:
         body.extend(s._get_stmt_ops())
     ops = start + end
     ops.append(
         opcode("initfor", self._var._name, None, -2 * IntType.stacksize),
         )
     ops.append(
         opcode("loop", len(body))
         )
     ops.extend(body)
     return ops
Пример #2
0
def _get_ops(expr):
    from Opioid2D.public.Vector import Vector
    from Opioid2D.public.Sprite import Sprite
    from Opioid2D.public.opivm.compiler import O2DCode
    
    if isinstance(expr, Expr):
        return expr._get_expr_ops()
    elif isinstance(expr, bool):
        return [
            opcode("consti", int(expr), BoolType, BoolType.stacksize)
            ]
    elif isinstance(expr, tuple):
        if len(expr) == 2:
            for x in expr:
                if isinstance(x, Expr):
                    return BuildVec(*expr)._get_expr_ops()
            return [
                opcode("constv", expr, VectorValue, VectorValue.stacksize)
                ]
        else:
            raise TypeError("can't use tuple of size %i as a constant" % len(expr))
    elif isinstance(expr, Vector):
        return [
            opcode("constv", expr, VectorValue, VectorValue.stacksize)
            ]
    elif isinstance(expr, Sprite):
        const_type = SpriteType
    else:
        try:
            const_type = _typemap[type(expr)]
        except KeyError:
            raise TypeError("can't use the constant %r in o2d expressions" % expr)
    return [
        opcode("const"+const_type.typecode, expr, const_type, const_type.stacksize)
        ]
Пример #3
0
    def __call__(self, func):
        retvalue = self.opts.get("retvalue", None)
        if retvalue is opitypes.VectorType:
            retvalue = opitypes.VectorValue
        fargs = inspect.getargs(func.func_code)[0]
        args = [VarRef(arg, typ) for arg, typ in zip(fargs, self.types)]
        code = func.func_code
        names = code.co_names
        dct = {}
        dct.update(func.func_globals)
        for n in names:
            if n in opiexpr.__all__:
                dct[n] = getattr(opiexpr, n)
            elif n not in func.func_globals:
                dct[n] = VarRef(n)

        dct["Return"] = opiexpr.Return(retvalue)

        newfunc = new.function(code,
                               dct,
                               func.func_name,
                               closure=func.func_closure)
        #args = dict((arg,VarRef(arg,typ)) for arg,typ in zip(args,self.types))
        statements = newfunc(*args)
        ops = []
        for a in reversed(args):
            ops.append(
                opcode("setvar" + a._type.varcode, a._name, None,
                       -a._type.stacksize))
        for s in statements:
            try:
                ops.extend(s._get_stmt_ops())
            except:
                t, v, tb = sys.exc_info()
                for l in traceback.format_list(s._tb):
                    sys.stderr.write(l)
                for l in traceback.format_exception_only(t, v):
                    sys.stderr.write(l)
                tb = None
                raise
                return
        if not ops or ops[-1][0] != "exit":
            if retvalue is not None:
                ops.extend(opiexpr._get_ops(retvalue.default))
            ops.append(opcode("exit"))
        cc = CompilerFrame()
        cc.stack = sum(a._type.stacksize for a in args)
        cc.max_stack = cc.stack
        cc.debugout = self.opts.get("debugout", False)
        for op in ops:
            cc.compile(op)
        if cc.debugout:
            print "max. stack usage: %i bytes" % cc.max_stack
            print cc.__dict__
        code = O2DCode(cc)
        code.retvalue = retvalue
        code.argspec = self.types
        return code
Пример #4
0
 def __call__(self, func):
     retvalue = self.opts.get("retvalue", None)
     if retvalue is opitypes.VectorType:
         retvalue = opitypes.VectorValue
     fargs = inspect.getargs(func.func_code)[0]
     args = [VarRef(arg,typ) for arg,typ in zip(fargs,self.types)]
     code = func.func_code
     names = code.co_names
     dct = {}
     dct.update(func.func_globals)
     for n in names:
         if n in opiexpr.__all__:
             dct[n] = getattr(opiexpr, n)
         elif n not in func.func_globals:
             dct[n] = VarRef(n)
             
     dct["Return"] = opiexpr.Return(retvalue)
                             
     newfunc = new.function(code, dct, func.func_name, closure=func.func_closure)
     #args = dict((arg,VarRef(arg,typ)) for arg,typ in zip(args,self.types))
     statements = newfunc(*args)
     ops = []
     for a in reversed(args):
         ops.append(
             opcode("setvar"+a._type.varcode, a._name, None, -a._type.stacksize)
             )            
     for s in statements:
         try:
             ops.extend(s._get_stmt_ops())
         except:
             t,v,tb = sys.exc_info()
             for l in traceback.format_list(s._tb):
                 sys.stderr.write(l)
             for l in traceback.format_exception_only(t,v):
                 sys.stderr.write(l)
             tb = None
             raise
             return
     if not ops or ops[-1][0] != "exit":
         if retvalue is not None:
             ops.extend(opiexpr._get_ops(retvalue.default))
         ops.append(opcode("exit"))
     cc = CompilerFrame()
     cc.stack = sum(a._type.stacksize for a in args)
     cc.max_stack = cc.stack
     cc.debugout = self.opts.get("debugout", False)
     for op in ops:
         cc.compile(op)
     if cc.debugout:
         print "max. stack usage: %i bytes" % cc.max_stack
         print cc.__dict__
     code = O2DCode(cc)
     code.retvalue = retvalue
     code.argspec = self.types
     return code
Пример #5
0
 def coercion_ops(self, t):
     if t is VectorValue:
         from Opioid2D.public.opivm.opcodes import opcode
         return [
             opcode("vec2p",
                    None,
                    VectorType,
                    stack=VectorType.stacksize - VectorValue.stacksize),
         ]
Пример #6
0
 def _get_stmt_ops(self):
     ops = _get_ops(self.cond)
     if self.parent is not None:
         return self.parent._get_stmt_ops()
     elses = []
     for t in self.elses:
         elses.extend(t._get_stmt_ops())
     then = []
     for t in self.then:
         then.extend(t._get_stmt_ops())
     if elses:
         then.append(
             opcode("jump", len(elses))
             )
     ops.append(
         opcode("ifjump", len(then), None, -BoolType.stacksize)
         )
     ops.extend(then)
     ops.extend(elses)
     return ops
Пример #7
0
 def _get_ops(self, expr=False):
     code = self._code
     # push params
     ops = []
     stack = 0
     argsize = 0
     for typ,arg in zip(code.argspec, self._args):
         argsize += typ.stacksize
         argops = _get_ops(arg)
         t = argops[-1][-1]
         if t is not typ:
             co = typ().coercion_ops(t)
             if co is None:
                 raise TypeError("invalid argument for vmcall (expected %s got %s)" % (typ, t))
             argops.extend(co)
         ops.extend(argops)            
     # vmcall opcodes
     stack = -argsize
     rt = code.retvalue
     if rt:
         rtstack = rt.stacksize
         stack += rt.stacksize
     else:
         rtstack = 0
     ops.append(
         opcode("consti", rtstack, stack=IntType.stacksize)
         )
     ops.append(
         opcode("constp", code, None, stack=SpriteType.stacksize)
         )
     ops.append(
         opcode("vmcall", argsize, rt, stack-IntType.stacksize-SpriteType.stacksize)
         )
     # pop result
     if not expr and rt:
         ops.append(
             opcode("pop", rtstack, None, -rtstack)
             )
     return ops
Пример #8
0
 def _get_expr_ops(self):
     ops = _get_ops(self._a)
     vt = ops[-1][-1]
     if vt is VectorType:
         rt = VectorValue
     elif vt is VectorValue:
         ops.extend(VectorType().coercion_ops(VectorValue))
         vt = VectorType
         rt = VectorValue
     else:
         rt = vt
     ops.append(
         opcode("op_"+self._op+vt.typecode, None, rt, rt.stacksize-vt.stacksize)
         )
     return ops
Пример #9
0
    def _get_expr_ops(self):
        a = _get_ops(self._a)
        b = _get_ops(self._b)
        a_type = a[-1][-1]
        b_type = b[-1][-1]
        if a_type is VectorValue:
            a.extend(VectorType().coercion_ops(VectorValue))
            a_type = VectorType
        if b_type is VectorValue:
            b.extend(VectorType().coercion_ops(VectorValue))
            b_type = VectorType
        if b_type is VectorType and a_type is not VectorType:
            a_type,b_type = b_type,a_type
            a,b = b,a
            
        codes = a_type.typecode + b_type.typecode
        op = self._op
        opmap = _opmap[op]
        try:
            coercions = opmap[codes]
        except KeyError:
                raise TypeError("invalid types %s and %s for operator %r" % (a_type,b_type,op))
        if coercions is not None:            
            coertype = _tcodemap[coercions[0]]
            if coertype is not a_type:
                a.extend(coertype().coercion_ops(a_type))
                a_type = coertype
            coertype = _tcodemap[coercions[1]]
            if coertype is not b_type:
                b.extend(coertype().coercion_ops(b_type))
                b_type = coertype
                
        typecode = a_type.typecode + b_type.typecode

        rt = self._get_returntype(a_type)
        if rt is VectorType:
            rt = VectorValue

        stack = -2 * a_type.stacksize + rt.stacksize
        ops = a + b
        ops.append(
            opcode("op_"+self._op+typecode, None, rt, stack)
            )
        return ops
Пример #10
0
 def _get_stmt_ops(self):
     if isinstance(self._target, PropertyOp):
         self._target._set(self._value)
         return self._target._get_stmt_ops()
     elif isinstance(self._target, VarRef):
         ops = _get_ops(self._value)
         vt = ops[-1][-1]
         if self._target._type is None:
             self._target._type = vt
         elif vt is not self._target._type:
             co = self._target._type().coercion_ops(vt)
             if co is None:
                 raise Exception("cannot convert %s to %s" % (vt, self._target._type))
             ops.extend(co)
         ops.append(
             opcode("setvar"+self._target._type.varcode, self._target._name, None, -self._target._type.stacksize)
             )
         return ops
     raise Exception("assignment to invalid target")
Пример #11
0
 def _get_stmt_ops(self):
     value = self._value
     if typ is None and value is not None:
         raise TypeError("function can't return any values")
     if typ is not None and value is None:
         raise TypeError("function must return a value")            
     ops = []
     if value is not None:
         ops.extend(_get_ops(value))
     if typ is not None:
         rt = ops[-1][-1]
         if rt is not typ:
             co = typ().coercion_ops(rt)
             if co is None:
                 raise TypeError("can't return a value of type %s" % rt)
             ops.extend(co)
     ops.append(
         opcode("exit")
         )
     return ops
Пример #12
0
 def coercion_ops(self, t):
     if t is VectorValue:
         from Opioid2D.public.opivm.opcodes import opcode
         return [
             opcode("vec2p", None, VectorType, stack=VectorType.stacksize-VectorValue.stacksize),
             ]
Пример #13
0
 def _get_expr_ops(self):
     if self._type is None:
         raise SyntaxError("uninitialized variable: %s" % self._name)
     return [
         opcode("pushvar"+self._type.varcode, self._name, self._type, self._type.stacksize)
         ]
Пример #14
0
 def _get_expr_ops(self):
     return [
         opcode("lastvec", None, VectorValue, VectorValue.stacksize),
         ]
Пример #15
0
    def _get_ops(self, expr):
        target_ops = _get_ops(self._target)
        tt = target_ops[-1][-1]
        if tt is VectorValue:
            target_ops.extend(VectorType().coercion_ops(VectorValue))
        if self._value is not None:
            if expr:
                raise SyntaxError("illegal property assignment in an expression")
            try:
                tt = target_ops[-1][-1]
                rt = tt.props[self._name]
            except KeyError:
                raise AttributeError("%s object has no property called %r" % (tt, self._name))
            ops =_get_ops(self._value)
            vt = ops[-1][-1]
            if vt is not rt:
                co = rt().coercion_ops(vt)
                if co is None:
                    raise TypeError("cannot assign %s to property %s.%s (requires %s)" % (vt, tt, self._name, rt))
                vt = co[-1][-1]
                ops.extend(co)
            ops.extend(target_ops)
            code = "setprop"
            if tt is VectorType:
                code += "v"
            ops.append(
                opcode(code, (tt,self._name), None, -vt.stacksize-tt.stacksize)
                )
            if type(self._target) is VarRef and self._target._type is VectorValue:
                ops.extend(
                    AssignOp(self._target, LastVec())._get_stmt_ops(),
                    )
        elif self._args is not None:
            ops = []
            try:
                tt = target_ops[-1][-1]
                ol_lst = tt.methods[self._name]
#                at,rt = tt.methods[self._name]
            except KeyError:
                raise AttributeError("%s object has no method called %r" % (tt, self._name))
            
            for ol_idx, (at,rt) in enumerate(ol_lst):
                if len(self._args) != len(at):
                    continue
                stack = 0
                argops = []
                for a,t in zip(self._args,at):
                    argops.extend(_get_ops(a))
                    argt = argops[-1][-1]
                    if argt is not t:
                        co = t().coercion_ops(argt)
                        if co is None:
                            break
                        argops.extend(co)
                    stack -= t.stacksize
                else:
                    break
            else:
                argtypes = []
                for a in self._args:
                    argt = _get_ops(a)[-1][-1]
                    argtypes.append(argt)
                arglist = ", ".join(str(a) for a in argtypes)
                raise TypeError("cannot call %s.%s with parameters (%s)" % (tt,self._name,argtypes))
                
            ops.extend(argops)
                
##            ops.append(
##                opcode("args", len(self._args), None, stack)
##                )
            if rt is None:
                rtstack = 0
            else:
                rtstack = rt.stacksize
            ops.extend(target_ops)
            code = "metcall"
            if tt is VectorType:
                code += "v"
            ops.append(
                opcode(code, (tt,self._name,ol_idx), rt, rtstack-tt.stacksize-stack)
                )
            if type(self._target) is VarRef and self._target._type is VectorValue:
                ops.extend(
                    AssignOp(self._target, LastVec())._get_stmt_ops(),
                    )            
            if not expr and rt is not None:
                ops.append(
                    opcode("pop", rt.stacksize, None, -rt.stacksize)
                    )
        else:
            ops = target_ops
            try:
                tt = ops[-1][-1]
                rt = tt.props[self._name]
            except KeyError:
                raise AttributeError("%s object has no property called %r" % (tt, self._name))
            if not expr:
                return []
            code = "getprop"
            if tt is VectorType:
                code += "v"
            ops.append(
                opcode(code, (tt,self._name), rt, rt.stacksize-tt.stacksize)
                )
        return ops
Пример #16
0
 def _get_expr_ops(self):
     return [
         opcode("i2f", None, FloatType, FloatType.stacksize-IntType.stacksize)
         ]
Пример #17
0
 def _get_expr_ops(self):
     return [
         opcode("f2i", None, IntType, IntType.stacksize-FloatType.stacksize)
         ]