Exemplo n.º 1
0
        def build_mk_func():
            nonlocal mk_fn_flag
            sub_a = sub.sc.output
            ins = []
            frees = list(sub_a.syms_free)

            # get all cell names from bound variables
            cells = [n for n, sym in sub_a.syms_bound.items() if sym.ty is SymType.cell]

            if frees:  # handle closure conversions
                if not PY35:
                    mk_fn_flag |= I.MK_FN_HAS_CLOSURE

                for n in frees:
                    if n in analysed.syms_bound:
                        var_type = I.CellVar
                    else:
                        var_type = I.FreeVar
                    ins.append(I.LOAD_CLOSURE(n, var_type))
                ins.append(I.BUILD_TUPLE(len(frees)))

            # create code object of subroutine
            instructions = sub.build()
            py_code = make_code_obj(
                name, filename, line, doc, args, frees, cells, instructions
            )
            ins.extend(
                [
                    I.LOAD_CONST(py_code),
                    I.LOAD_CONST(name),
                    I.MAKE_CLOSURE(mk_fn_flag)
                    if PY35 and frees
                    else I.MAKE_FUNCTION(mk_fn_flag),
                ]
            )

            # if not anonymous function,
            # we shall assign the function to a variable
            if not anonymous:
                fn_sym = analysed.syms_bound.get(name)
                if not fn_sym:
                    store = I.STORE_GLOBAL(name)
                elif fn_sym.ty is SymType.bound:
                    store = I.STORE_FAST(name)
                elif fn_sym.ty is SymType.cell:
                    store = I.STORE_DEREF(name, I.CellVar)
                else:
                    raise ValueError
                ins.extend([I.DUP(), store])

            return ins
Exemplo n.º 2
0
def make_code_obj(
    name: str,
    filename: str,
    lineno: int,
    doc: str,
    args: List[str],
    frees: List[str],
    cells: List[str],
    instructions: List[BC.Instr],
):
    """Create code object from given metadata and instructions
    """
    if not instructions:
        instructions.append(I.LOAD_CONST(None))
    instructions.append(I.RETURN_VALUE())
    instructions = list(merge_labels(instructions))

    bc_code = BC.Bytecode(instructions)
    bc_code.name = name
    bc_code.filename = filename
    bc_code.first_lineno = lineno
    bc_code.docstring = doc
    bc_code.argnames.extend(args)
    bc_code.argcount = len(bc_code.argnames)
    bc_code.freevars.extend(frees)
    bc_code.cellvars.extend(cells)
    stack_size = bc_code.compute_stacksize()

    c_code = bc_code.to_concrete_bytecode()
    c_code.flags = BC.flags.infer_flags(c_code)
    py_code = c_code.to_code(stacksize=stack_size)
    return py_code
Exemplo n.º 3
0
    def new(self, ty, *args):
        """
        Basically, it's
            new(ty, *args) ==
                this = ty(*args, {})
                this['.t'] = ty
        This is efficient and avoids redundant
        register allocation, hence I'm quite proud
        of this idea :)
        """
        yield self.eval(ty)

        # build this object
        self << (lambda: [I.DUP()])

        yield self.eval_all(args)
        n = len(args) + 1

        # initialize this object
        self << (
            lambda: [
                I.BUILD_MAP(0),
                I.CALL_FUNCTION(n),
                I.DUP(),
                I.ROT3(),
                I.LOAD_CONST(RECORD_TYPE_FIELD),
                I.STORE_SUBSCR(),
            ]
        )
Exemplo n.º 4
0
    def for_in(self, n: str, seq, body):
        label_end = _new_unique_label("end.loop")
        label_iter = _new_unique_label("iter.loop")

        yield self.eval(seq)
        self << (lambda: [I.GET_ITER(), label_iter, I.FOR_ITER(label_end)])

        self._bind(n, bound=False)
        yield self.eval(body)
        self << (
            lambda: [
                I.POP_TOP(),
                I.JUMP_ABSOLUTE(label_iter),
                label_end,
                I.LOAD_CONST(None),
            ]
        )
Exemplo n.º 5
0
    def loop(self, cond, body):
        """
        Note, the value of `body` in the last iteration will be returned.
        e.g.,
            z = 2
            f = while z < 5 {
                z += z
                z
            }
        The value of `f` is 8
        """
        label_setup = _new_unique_label("while.setup")
        label_end = _new_unique_label("while.end")

        self << (lambda: [I.LOAD_CONST(None), label_setup])
        yield self.eval(cond)
        self << (lambda: [I.POP_JUMP_IF_FALSE(label_end), I.POP_TOP()])
        yield self.eval(body)
        self << (lambda: [I.JUMP_ABSOLUTE(label_setup), label_end])
Exemplo n.º 6
0
 def ret(self, v):
     yield self.eval(v)
     self << (lambda: [I.RETURN_VALUE(), I.LOAD_CONST(None)])
Exemplo n.º 7
0
 def set_item(self, base, item, val):
     yield self.eval(val)
     yield self.eval(base)
     yield self.eval(item)
     self << (lambda: [I.STORE_SUBSCR(), I.LOAD_CONST(None)])
Exemplo n.º 8
0
 def set_attr(self, base, n: str, val):
     yield self.eval(val)
     yield self.eval(base)
     self << (lambda: [I.STORE_ATTR(n), I.LOAD_CONST(None)])
Exemplo n.º 9
0
 def assign(self, n: str, v):
     yield self.eval(v)
     self._bind(n, False)
     self << (lambda: [I.LOAD_CONST(None)])
Exemplo n.º 10
0
 def assign_star(self, n: str, v):
     yield self.eval(v)
     self._bind(n, True)
     self << (lambda: [I.LOAD_CONST(None)])
Exemplo n.º 11
0
 def build():
     return [I.LOAD_CONST(value)]