Exemple #1
0
import ast
from ast import Assign, Load, Module, Name, Print, Store

node_map = {
    'Assignment': dict(pynode='Assign',
                       mappers={'targets': 'node', 'value': 'expr'},
                       types={'left': 'list'},
                       args={'ctx': ast.Store(lineno=0, col_offset=0)}),

    'Echo': dict(pynode='Print',
                 mappers={'values': 'nodes'},
                 types={'left': list},
                 args={'nl': True, 'ctx': ast.Load(lineno=0, col_offset=0)}),

    'Variable': dict(pynode='Name',
                     mappers={'id': 'name'},
                     types={'left': 'var'},
                     args={'ctx': ast.Store(lineno=0, col_offset=0)}),
    }

body = []


def eval_node(phpnode, ctx=None):

    node_type, el = phpnode.generic()
    mapdef = node_map[node_type]
    py_ast_class = getattr(ast, mapdef['pynode'])
    instance = py_ast_class(lineno=0, col_offset=0,
                            **mapdef.get('args', {}))
    if ctx:
Exemple #2
0
 def assign(self, expr: ast.expr) -> ast.Name:
     """Give *expr* a name."""
     name = self.variable()
     self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr))
     return ast.Name(name, ast.Load())
Exemple #3
0
            other = Decimal(other)
        quotient, remainder = super(Decimal, other).__divmod__(self)
        return Decimal(quotient), Decimal(remainder)

    def __pow__(self, power, modulo=None, context=None):
        if isinstance(power, (int, float)):
            power = Decimal(power)
        return Decimal(super(Decimal, self).__pow__(power, modulo))

    def __rpow__(self, other, context=None):
        if isinstance(other, (int, float)):
            other = Decimal(other)
        return Decimal(super(Decimal, other).__pow__(self))


TYPE_STORE = type(ast.Store())
TYPE_LOAD = type(ast.Load())
TYPE_DEL = type(ast.Del())
TYPE_EXPR = type(ast.Expr())


class BadSyntax(Exception):
    pass


BINOP_TABLE: Dict[Any, Callable[[Any, Any], Any]] = {
    _ast.Add: lambda a, b: a + b,
    _ast.BitAnd: lambda a, b: a & b,
    _ast.BitOr: lambda a, b: a | b,
    _ast.BitXor: lambda a, b: a ^ b,
    _ast.Div: lambda a, b: a / b,
Exemple #4
0
def translate_to_tptv1(parsed_model, data_batch, hypers):
    parsed_model = u.replace_hypers(parsed_model, hypers)
    parsed_model = AssignmentAndFunctionInliner().visit(parsed_model)
    input_dependents = get_input_dependent_vars(parsed_model)

    idx_var_name = "input_idx"
    idx_var = ast.Name(idx_var_name, ast.Load())
    input_number = len(data_batch['instances'])
    range_expr = ast.Num(input_number)

    input_vars = set()
    output_vars = set()
    var_decls = []
    input_stmts = []
    general_stmts = []
    output_stmts = []
    for stmt in parsed_model.body:
        if isinstance(stmt, ast.Assign) and is_input_declaration(stmt.value):
            input_vars.add(get_var_name(stmt.targets[0]))
            var_decls.append(stmt)
        elif isinstance(stmt, ast.Assign) and is_output_declaration(
                stmt.value):
            output_vars.add(get_var_name(stmt.targets[0]))
            var_decls.append(stmt)
        elif isinstance(stmt, ast.Assign) and is_var_declaration(stmt.value):
            var_decls.append(stmt)
        elif ast_uses_varset(stmt, input_dependents):
            input_stmts.append(
                add_input_indices(stmt, input_dependents, idx_var))
        elif ast_uses_varset(stmt, output_vars):
            output_stmts.append(stmt)
        else:
            general_stmts.append(stmt)

    input_init = []
    output_observation = []
    for input_idx, instance in enumerate(data_batch['instances']):
        for var_name, val in instance.iteritems():
            if var_name in input_vars:
                input_init.extend(
                    generate_io_stmt(input_idx, var_name, val,
                                     "set_to_constant"))
            elif var_name in output_vars:
                output_observation.extend(
                    generate_io_stmt(input_idx, var_name, val,
                                     "observe_value"))

    extended_var_decls = []
    for var_decl in var_decls:
        # If input-dependent, extend dimension by one
        if get_var_name(var_decl.targets[0]) in input_dependents:
            new_decl = copy.deepcopy(var_decl)
            if isinstance(new_decl.value, ast.Subscript):
                new_decl.value = extend_subscript_for_input(
                    new_decl.value, ast.Num(input_number))
            else:
                new_decl.value = ast.Subscript(
                    new_decl.value, ast.Index(ast.Num(input_number)),
                    ast.Load())
            extended_var_decls.append(new_decl)
        else:
            extended_var_decls.append(var_decl)

    input_loop = ast.For(
        ast.Name(idx_var_name, ast.Store()),
        ast.Call(ast.Name("range", ast.Load()), [range_expr], [], None, None),
        input_stmts, [])
    parsed_model.body = general_stmts + extended_var_decls + input_init + [
        input_loop
    ] + output_stmts + output_observation
    ast.fix_missing_locations(parsed_model)

    return parsed_model
Exemple #5
0
def ex_lvalue(name):
    """A variable load expression."""
    return ast.Name(name, ast.Store())
Exemple #6
0
def multiphase_expand(tree,
                      *,
                      filename,
                      self_module,
                      dexpander=None,
                      _optimize=-1):
    """Macro-expand an AST in multiple phases, controlled by `with phase[n]`.

    Primarily meant to be called with `tree` the AST of a module that
    uses macros, but works with any `tree` that has a `body` attribute,
    where that `body` is a `list` of statement AST nodes.

    At each phase `k >= 1`, we inject a temporary module into `sys.modules`, so that
    the next phase can import macros from it, using the self-macro-import syntax.

    Once phase `k = 0` is reached and the code has been macro-expanded, the temporary
    entry is deleted from `sys.modules`.

    `filename`:         Full path to the `.py` file being compiled.

    `self_module`:      Absolute dotted module name of the module being compiled.
                        Used for temporarily injecting the temporary, higher-phase
                        modules into `sys.modules`, as well as resolving `__self__`
                        in self-macro-imports (`from __self__ import macros, ...`).

    `dexpander`:        The `DialectExpander` instance to use for dialect AST transforms.
                        If not provided, dialect processing is skipped.

    `_optimize`:        Passed on to Python's built-in `compile` function, when compiling
                        the temporary higher-phase modules. Has no effect on the final result.

    Return value is the final phase-0 `tree`, after macro expansion.
    """
    n = detect_highest_phase(tree)
    debug = isdebug(tree)
    c, CS = setcolor, ColorScheme

    # If this module is already in `sys.modules` (e.g. created by Python's
    # import system as a blank module instance, to be filled in by an exec
    # after compilation is done), record the original module object, so we
    # can reinstate it once we're done.
    if self_module in sys.modules:
        original_module = sys.modules[self_module]
    else:
        original_module = None

    if debug:
        print(
            f"{c(CS.HEADING)}**Multi-phase compiling module {c(CS.TREEID)}'{self_module}' ({c(CS.SOURCEFILENAME)}{filename}{c(CS.TREEID)}){c()}",
            file=sys.stderr)

    # Inject temporary module into `sys.modules`.
    #
    # Note that if the module already exists in `sys.modules`, its entry will be overwritten.
    # We don't touch the parent module (if any), so that if it already refers to an old (but
    # phase-0, fully compiled) version of this one, the reference won't be clobbered with one
    # pointing to the temporary module.
    #
    # We must inject the temporary module only once, to keep the already compiled higher-phase
    # stuff available in the module's namespace while the next phase is being compiled.
    # (This matters when there are at least 3 phases, see `demo/let.py`.)
    module = compiler.create_module(dotted_name=self_module,
                                    filename=filename,
                                    update_parent=False)

    for k in range(n, -1, -1):  # phase 0 is what a regular compile would do
        if debug:
            print(
                f"{c(CS.HEADING)}**AST for {c(CS.ATTENTION)}PHASE {k}{c(CS.HEADING)} of module {c(CS.TREEID)}'{self_module}' ({c(CS.SOURCEFILENAME)}{filename}{c(CS.TREEID)}){c()}",
                file=sys.stderr)

        phase_k_tree = extract_phase(tree, phase=k)
        if phase_k_tree.body:
            # inject `__phase__ = k` for introspection (at run time of the phase being compiled now)
            tgt = ast.Name(id="__phase__",
                           ctx=ast.Store(),
                           lineno=1,
                           col_offset=1)
            val = ast.Constant(value=k, lineno=1, col_offset=13)
            assignment = ast.Assign(targets=[tgt],
                                    value=val,
                                    lineno=1,
                                    col_offset=1)

            if getdocstring(phase_k_tree.body):
                docstring, *body = phase_k_tree.body
                phase_k_tree.body = [docstring, assignment] + body
            else:  # no docstring
                phase_k_tree.body = [assignment] + phase_k_tree.body

            if debug:
                print(unparse_with_fallbacks(phase_k_tree,
                                             debug=True,
                                             color=True),
                      file=sys.stderr)

            # Once we hit the final phase, no more temporary modules - let the import system take over.
            if k == 0:
                expansion = compiler.singlephase_expand(
                    phase_k_tree,
                    filename=filename,
                    self_module=self_module,
                    dexpander=dexpander)
                break

            # Compile the current tree, and run it in the namespace of the temporary module. This
            # gives us the temporary higher-phase module, which allows us to compile the next phase.
            # At intermediate phases, some definitions overwrite previous ones - this is ok.
            compiler.run(phase_k_tree, module)

    # restore `sys.modules` to how it was before we began the multi-phase compile for this module
    if original_module:
        sys.modules[self_module] = original_module
    else:
        try:
            del sys.modules[self_module]
        except KeyError:
            pass

    return expansion
Exemple #7
0
    def gen_unpack_wrapper(self, node, target, ctx='store'):
        """Helper function to protect tuple unpacks.

        node: used to copy the locations for the new nodes.
        target: is the tuple which must be protected.
        ctx: Defines the context of the returned temporary node.

        It returns a tuple with two element.

        Element 1: Is a temporary name node which must be used to
                   replace the target.
                   The context (store, param) is defined
                   by the 'ctx' parameter..

        Element 2: Is a try .. finally where the body performs the
                   protected tuple unpack of the temporary variable
                   into the original target.
        """

        # Generate a tmp name to replace the tuple with.
        tmp_name = self.gen_tmp_name()

        # Generates an expressions which protects the unpack.
        # converter looks like 'wrapper(tmp_name)'.
        # 'wrapper' takes care to protect sequence unpacking with _getiter_.
        converter = self.protect_unpack_sequence(
            target, ast.Name(tmp_name, ast.Load()))

        # Assign the expression to the original names.
        # Cleanup the temporary variable.
        # Generates:
        # try:
        #     # converter is 'wrapper(tmp_name)'
        #     arg = converter
        # finally:
        #     del tmp_arg
        try_body = [ast.Assign(targets=[target], value=converter)]
        finalbody = [self.gen_del_stmt(tmp_name)]

        if IS_PY2:
            cleanup = ast.TryFinally(body=try_body, finalbody=finalbody)
        else:
            cleanup = ast.Try(body=try_body,
                              finalbody=finalbody,
                              handlers=[],
                              orelse=[])

        if ctx == 'store':
            ctx = ast.Store()
        elif ctx == 'param':
            ctx = ast.Param()
        else:  # pragma: no cover
            # Only store and param are defined ctx.
            raise NotImplementedError(
                'Unsupported context type: "{name}".'.format(name=type(ctx)), )

        # This node is used to catch the tuple in a tmp variable.
        tmp_target = ast.Name(tmp_name, ctx)

        copy_locations(tmp_target, node)
        copy_locations(cleanup, node)

        return (tmp_target, cleanup)
Exemple #8
0
async def meval(code, globs, **kwargs):
    # Note to self: please don't set globals here as they will be lost.
    # Don't clutter locals
    locs = {}
    # Restore globals later
    globs = globs.copy()
    # This code saves __name__ and __package into a kwarg passed to the func.
    # It is set before the users code runs to make sure relative imports work
    global_args = "_globs"
    while global_args in globs.keys():
        # Make sure there's no name collision, just keep prepending _s
        global_args = "_" + global_args
    kwargs[global_args] = {}
    for glob in ["__name__", "__package__"]:
        # Copy data to args we are sending
        kwargs[global_args][glob] = globs[glob]

    root = ast.parse(code, "exec")
    code = root.body

    ret_name = "_ret"
    ok = False
    while True:
        if ret_name in globs.keys():
            ret_name = "_" + ret_name
            continue
        for node in ast.walk(root):
            if isinstance(node, ast.Name) and node.id == ret_name:
                ret_name = "_" + ret_name
                break
            ok = True
        if ok:
            break

    if not code:
        return None

    if not any(isinstance(node, ast.Return) for node in code):
        for i in range(len(code)):
            if isinstance(code[i], ast.Expr):
                if (i == len(code) - 1
                        or not isinstance(code[i].value, ast.Call)):
                    code[i] = ast.copy_location(
                        ast.Expr(
                            ast.Call(func=ast.Attribute(value=ast.Name(
                                id=ret_name, ctx=ast.Load()),
                                                        attr="append",
                                                        ctx=ast.Load()),
                                     args=[code[i].value],
                                     keywords=[])), code[-1])
    else:
        for node in code:
            if isinstance(node, ast.Return):
                node.value = ast.List(elts=[node.value], ctx=ast.Load())

    code.append(
        ast.copy_location(
            ast.Return(value=ast.Name(id=ret_name, ctx=ast.Load())), code[-1]))

    # globals().update(**<global_args>)
    glob_copy = ast.Expr(
        ast.Call(
            func=ast.Attribute(value=ast.Call(func=ast.Name(id="globals",
                                                            ctx=ast.Load()),
                                              args=[],
                                              keywords=[]),
                               attr="update",
                               ctx=ast.Load()),
            args=[],
            keywords=[
                ast.keyword(arg=None,
                            value=ast.Name(id=global_args, ctx=ast.Load()))
            ]))
    ast.fix_missing_locations(glob_copy)
    code.insert(0, glob_copy)
    ret_decl = ast.Assign(targets=[ast.Name(id=ret_name, ctx=ast.Store())],
                          value=ast.List(elts=[], ctx=ast.Load()))
    ast.fix_missing_locations(ret_decl)
    code.insert(1, ret_decl)
    args = []
    for a in list(map(lambda x: ast.arg(x, None), kwargs.keys())):
        ast.fix_missing_locations(a)
        args += [a]
    args = ast.arguments(args=[],
                         vararg=None,
                         kwonlyargs=args,
                         kwarg=None,
                         defaults=[],
                         kw_defaults=[None for i in range(len(args))])
    args.posonlyargs = []
    fun = ast.AsyncFunctionDef(name="tmp",
                               args=args,
                               body=code,
                               decorator_list=[],
                               returns=None)
    ast.fix_missing_locations(fun)
    mod = ast.parse("")
    mod.body = [fun]
    comp = compile(mod, "<string>", "exec")

    exec(comp, {}, locs)

    r = await locs["tmp"](**kwargs)
    for i in range(len(r)):
        if hasattr(r[i], "__await__"):
            r[i] = await r[i]  # workaround for 3.5
    i = 0
    while i < len(r) - 1:
        if r[i] is None:
            del r[i]
        else:
            i += 1
    if len(r) == 1:
        [r] = r
    elif not r:
        r = None
    return r
    def visit_FunctionDef(self, node):
        node.parent = self.fundef
        self.fundef = node

        if len(
                list(
                    filter(
                        lambda n: isinstance(n, ast.Name) and n.id is
                        'rep_fun', node.decorator_list))) > 0:
            self.recs.append(node.name)

        self.generic_visit(node)

        r_args = {}

        for arg in node.args.args:
            arg_name = arg.arg
            try:
                if self.fundef.locals[arg_name] > 1:
                    r_args[arg_name] = self.freshName('x')
                # self.fundef.locals[arg_name] += 1
            except KeyError as e:
                pass

        # generate code to pre-initialize staged vars
        # we stage all vars that are written to more than once
        inits = [ast.Assign(targets=[ast.Name(id=id, ctx=ast.Store())],
                    value=ast.Call(
                        func=ast.Name(id='_var', ctx=ast.Load()),
                        args=[],
                        keywords=[])) \
                    for id in node.locals if node.locals[id] > 1]

        a_nodes = [ast.Expr(
                    ast.Call(
                        func=ast.Name(id='_assign', ctx=ast.Load()),
                        args=[ast.Name(id=arg,ctx=ast.Load()), ast.Name(id=r_args[arg],ctx=ast.Load())],
                        keywords=[])) \
                    for arg in r_args]

        new_node = ast.FunctionDef(
            name=node.name,
            args=ast.arguments(args=[
                ast.arg(arg=r_args[arg.arg], annotation=None)
                if arg.arg in r_args else arg for arg in node.args.args
            ],
                               vararg=None,
                               kwonlyargs=[],
                               kwarg=None,
                               defaults=[],
                               kw_defaults=[]),  # node.args,
            body=[
                ast.Try(body=inits + a_nodes + node.body,
                        handlers=[
                            ast.ExceptHandler(
                                type=ast.Name(id='NonLocalReturnValue',
                                              ctx=ast.Load()),
                                name='r',
                                body=[
                                    ast.Return(value=ast.Attribute(
                                        value=ast.Name(id='r', ctx=ast.Load()),
                                        attr='value',
                                        ctx=ast.Load()))
                                ])
                        ],
                        orelse=[],
                        finalbody=[])
            ],
            decorator_list=list(
                filter(
                    lambda n: isinstance(n, ast.Name) and n.id != 'lms' and n.
                    id != 'rep_fun', node.decorator_list)))
        ast.copy_location(new_node, node)
        ast.fix_missing_locations(new_node)
        self.fundef = node.parent
        return new_node
Exemple #10
0
    def visit_FunctionDef(self, node):
        after_nodes = []

        if self.curprim is None:
            self.curprim = self.pdp
            self.curchild = -1
            if isinstance(node.decorator_list[0], ast.Call):
                self.module_name = node.decorator_list[0].func.value.id
            else:
                self.module_name = node.decorator_list[0].value.id
            # Strip decorator
            del node.decorator_list[0]

            oldchild = self.curchild
            oldprim = self.curprim

        else:
            if len(node.decorator_list) == 0:
                return self.generic_visit(node)
            dec = node.decorator_list[0]
            if isinstance(dec, ast.Call):
                decname = astparser.rname(dec.func.attr)
            else:
                decname = astparser.rname(dec.attr)

            if decname in [
                    'map', 'async_map', 'reduce', 'async_reduce', 'consume',
                    'async_consume', 'tasklet', 'async_tasklet', 'iterate',
                    'loop', 'conditional'
            ]:
                self.curchild += 1

                oldchild = self.curchild
                oldprim = self.curprim
                self.curprim = self.curprim.children[self.curchild]
                self.curchild = -1

                if isinstance(self.curprim, astnodes._MapNode):
                    newnode = \
                        _copy_location(ast.For(target=ast.Tuple(ctx=ast.Store(),
                                                    elts=[ast.Name(id=name, ctx=ast.Store()) for name in self.curprim.params]),
                                                    iter=ast.parse('%s.ndrange(%s)' % (self.module_name, self.curprim.range.pystr())).body[0].value,
                                                    body=node.body, orelse=[]),
                                            node)
                    node = newnode
                elif isinstance(self.curprim, astnodes._ConsumeNode):
                    stream = self.curprim.stream
                    if isinstance(self.curprim.stream, ast.AST):
                        stream = unparse(self.curprim.stream)
                    if '[' not in stream:
                        stream += '[0]'

                    newnode = \
                        _copy_location(ast.While(
                            test=ast.parse('len(%s) > 0' % stream).body[0].value,
                                           body=node.body, orelse=[]),
                                       node)
                    node = newnode
                    node.body.insert(
                        0,
                        _copy_location(
                            ast.parse('%s = %s.popleft()' % (str(
                                self.curprim.params[0]), stream)).body[0],
                            node))

                elif isinstance(self.curprim, astnodes._TaskletNode):
                    # Strip decorator
                    del node.decorator_list[0]

                    newnode = \
                        _copy_location(ast.parse('if True: pass').body[0], node)
                    newnode.body = node.body
                    newnode = ast.fix_missing_locations(newnode)
                    node = newnode
                elif isinstance(self.curprim, astnodes._ReduceNode):
                    in_memlet = self.curprim.inputs['input']
                    out_memlet = self.curprim.outputs['output']
                    # Create reduction call
                    params = [unparse(p) for p in node.decorator_list[0].args]
                    params.extend([
                        unparse(kp) for kp in node.decorator_list[0].keywords
                    ])
                    reduction = ast.parse(
                        '%s.simulator.simulate_reduce(%s, %s)' %
                        (self.module_name, node.name,
                         ', '.join(params))).body[0]
                    reduction = _copy_location(reduction, node)
                    reduction = ast.increment_lineno(reduction,
                                                     len(node.body) + 1)
                    reduction = ast.fix_missing_locations(reduction)

                    # Strip decorator
                    del node.decorator_list[0]

                    after_nodes.append(reduction)
                elif isinstance(self.curprim, astnodes._IterateNode):
                    newnode = \
                        _copy_location(ast.For(target=ast.Tuple(ctx=ast.Store(),
                                                    elts=[ast.Name(id=name, ctx=ast.Store()) for name in self.curprim.params]),
                                                    iter=ast.parse('%s.ndrange(%s)' % (self.module_name, self.curprim.range.pystr())).body[0].value,
                                                    body=node.body, orelse=[]),
                                            node)
                    newnode = ast.fix_missing_locations(newnode)
                    node = newnode
                elif isinstance(self.curprim, astnodes._LoopNode):
                    newnode = \
                        _copy_location(ast.While(test=node.decorator_list[0].args[0],
                                                    body=node.body, orelse=[]),
                                            node)
                    newnode = ast.fix_missing_locations(newnode)
                    node = newnode
                else:
                    raise RuntimeError('Unimplemented primitive %s' % decname)
            else:
                return self.generic_visit(node)

        newbody = []
        end_stmts = []
        substitute_stmts = []
        # Incrementally build new body from original body
        for stmt in node.body:
            if isinstance(stmt, ast.Expr):
                res, append, prepend = self.VisitTopLevelExpr(stmt)
                if res is not None:
                    newbody.append(res)
                if append is not None:
                    end_stmts.extend(append)
                if prepend is not None:
                    substitute_stmts.extend(prepend)
            else:
                subnodes = self.visit(stmt)
                if subnodes is not None:
                    if isinstance(subnodes, list):
                        newbody.extend(subnodes)
                    else:
                        newbody.append(subnodes)
        node.body = newbody + end_stmts

        self.curchild = oldchild
        self.curprim = oldprim

        substitute_stmts.append(node)
        if len(after_nodes) > 0:
            return substitute_stmts + after_nodes
        return substitute_stmts
Exemple #11
0
    def VisitTopLevelExpr(self, node):
        # DaCe memlet expression
        if isinstance(node.value, ast.BinOp):
            rhs = node.value.right
            lhs = node.value.left
            arrays = self.curprim.arrays()

            if isinstance(node.value.op, ast.LShift):
                # Dynamic access. Emit nothing and load memory on encounter
                if isinstance(rhs, ast.Call) and ast.literal_eval(
                        rhs.args[0]) == -1:
                    array_name = rhs.func.id
                    stripped_subscript = '%s[:]' % (array_name)
                    self.storeOnAssignment[node.value.left.id] = \
                        ast.parse(stripped_subscript).body[0].value
                    return None, None, None

                if isinstance(rhs, ast.Subscript) and isinstance(
                        rhs.value, ast.Call):

                    # Dynamic access. Emit nothing and load memory on encounter
                    if ast.literal_eval(rhs.value.args[0]) == -1:
                        array_name = rhs.value.func.id
                        stripped_subscript = '%s[%s]' % (array_name,
                                                         unparse(rhs.slice))
                        self.storeOnAssignment[node.value.left.id] = \
                            ast.parse(stripped_subscript).body[0].value
                        return None, None, None

                    rhs = ast.Subscript(
                        value=rhs.value.func, ctx=ast.Load(), slice=rhs.slice)

                result = _copy_location(
                    ast.Assign(targets=[node.value.left], value=rhs), node)
                result.targets[0].ctx = ast.Store()
                return result, None, None
            # END of "a << b"
            elif isinstance(node.value.op, ast.RShift):
                # If the memlet refers to a sub-array (view), also add an expression to initialize it
                init_expr = None
                result = None
                prefix = []

                if isinstance(rhs, ast.Subscript):
                    # Index subscript expression ("tmp >> b(1, sum)[i,j,k,l]")
                    if isinstance(rhs.value, ast.Call):
                        # Only match expressions with possible write-conflict resolution, such as "A(...)[...]"
                        array_name = rhs.value.func.id
                        stripped_subscript = '%s[%s]' % (array_name,
                                                         unparse(rhs.slice))

                        # WCR initialization with identity value
                        if len(rhs.value.args) >= 3:
                            prefix.append(
                                _copy_location(
                                    ast.parse(
                                        '%s = %s' %
                                        (stripped_subscript,
                                         unparse(rhs.value.args[2]))).body[0],
                                    node))

                        # Dynamic access. Emit nothing and store memory on assignment
                        if ast.literal_eval(rhs.value.args[0]) == -1:
                            if len(rhs.value.args) >= 2:
                                self.accumOnAssignment[node.value.left.id] = \
                                    (stripped_subscript, rhs.value.args[1])
                            else:
                                self.storeOnAssignment[node.value.left.id] = \
                                    ast.parse(stripped_subscript).body[0].value
                            return init_expr, None, prefix

                        # Make sure WCR function exists
                        if len(rhs.value.args) >= 2:
                            result = ast.parse(
                                '%s = (%s)(%s, %s)' %
                                (stripped_subscript, unparse(
                                    rhs.value.args[1]), stripped_subscript,
                                 node.value.left.id)).body[0]
                            result = _copy_location(result, node)
                        else:
                            result = ast.parse(
                                '%s = %s' % (stripped_subscript,
                                             node.value.left.id)).body[0]
                            result = _copy_location(result, node)
                    else:
                        array_name = rhs.value.id

                    if not isinstance(rhs.slice, ast.Index):
                        init_expr = _copy_location(
                            ast.Assign(
                                targets=[
                                    ast.Name(
                                        id=node.value.left.id, ctx=ast.Store())
                                ],
                                value=ast.Subscript(
                                    value=ast.Name(
                                        id=array_name, ctx=ast.Load()),
                                    slice=rhs.slice,
                                    ctx=ast.Load())), node)
                elif not isinstance(rhs, ast.Subscript):
                    if isinstance(rhs, ast.Call):
                        array_name = rhs.func
                    else:
                        array_name = rhs

                    lhs_name = lhs.id

                    # In case of "tmp >> array", write "array[:]"
                    if node.value.left.id in self.curprim.transients:
                        init_expr = None
                    # If reading from a single stream ("b << stream")
                    elif (array_name.id in arrays
                          and isinstance(arrays[array_name.id], data.Stream)):
                        if arrays[array_name.id].shape == [1]:
                            init_expr = _copy_location(
                                ast.parse('{v} = {q}[0]'.format(
                                    v=lhs_name, q=array_name.id)).body[0],
                                node)
                        return init_expr, None, []
                    else:
                        init_expr = _copy_location(
                            ast.Assign(
                                targets=[
                                    ast.Name(id=lhs_name, ctx=ast.Store())
                                ],
                                value=ast.Subscript(
                                    value=ast.Name(
                                        id=array_name.id, ctx=ast.Load()),
                                    slice=ast.Slice(
                                        lower=None, upper=None, step=None),
                                    ctx=ast.Load())), node)

                    # If we are setting a stream's sink
                    if lhs_name in arrays and isinstance(
                            arrays[lhs_name], data.Stream):
                        result = ast.parse(
                            '{arr}[0:len({q}[0])] = list({q}[0])'.format(
                                arr=rhs.id, q=lhs.id)).body[0]
                        result = _copy_location(result, node)

                    # If WCR function exists
                    elif isinstance(rhs, ast.Call) and len(rhs.args) >= 2:
                        # WCR initialization with identity value
                        if len(rhs.args) >= 3:
                            prefix.append(
                                _copy_location(
                                    ast.parse('%s[:] = %s' %
                                              (array_name.id,
                                               unparse(rhs.args[2]))).body[0],
                                    node))

                        # Dynamic access. Emit nothing and store memory on assignment
                        if ast.literal_eval(rhs.args[0]) == -1:
                            self.accumOnAssignment[lhs.id] = (array_name.id,
                                                              rhs.args[1])
                            return init_expr, None, prefix

                        result = ast.parse(
                            '%s[:] = (%s)(%s[:], %s)' %
                            (array_name.id, unparse(rhs.args[1]),
                             array_name.id, node.value.left.id)).body[0]
                        result = _copy_location(result, node)

                    else:
                        result = _copy_location(
                            ast.Assign(
                                targets=[
                                    ast.Subscript(
                                        value=ast.Name(
                                            id=array_name.id, ctx=ast.Load()),
                                        slice=ast.Slice(
                                            lower=None, upper=None, step=None),
                                        ctx=ast.Store())
                                ],
                                value=node.value.left), node)

                if result is None:
                    result = _copy_location(
                        ast.Assign(
                            targets=[node.value.right], value=node.value.left),
                        node)
                result.targets[0].ctx = ast.Store()
                return init_expr, [result], prefix
            # END of "a >> b"

        return self.generic_visit(node), [], None
    def instantiateFunction(self, filename, lineNumber, memberDictionary,
                            file_text):
        """Instantiate a function instance."""

        memberDictionary = {
            k: v
            for k, v in memberDictionary.iteritems()
            if not isinstance(v, Exceptions.PyforaNameError)
        }

        objectOrNone = self.moduleLevelObject(filename, lineNumber)
        if objectOrNone is not None:
            return objectOrNone

        sourceAst = PyAstUtil.pyAstFromText(file_text)
        functionAst = PyAstUtil.functionDefOrLambdaOrWithBlockAtLineNumber(
            sourceAst, lineNumber)

        outputLocals = {}
        globalScope = {}
        globalScope.update(memberDictionary)
        self.importModuleMagicVariables(globalScope, filename)

        if isinstance(functionAst, ast.Lambda):
            expr = ast.FunctionDef()
            expr.name = '__pyfora_lambda_builder__'
            expr.args = ast.arguments()
            expr.args.args = []
            expr.args.defaults = []
            expr.args.vararg = None
            expr.args.kwarg = None

            expr.decorator_list = []
            expr.lineno = functionAst.lineno - 1
            expr.col_offset = functionAst.col_offset

            return_statement = ast.Return(functionAst)
            expr.body = [return_statement]

            expr = updatePyAstMemberChains(ast.Module([expr],
                                                      lineno=1,
                                                      col_offset=0),
                                           globalScope,
                                           isClassContext=True)

            code = compile(expr, filename, 'exec')

            exec code in globalScope, outputLocals

            return list(outputLocals.values())[0]()

        elif isinstance(functionAst, ast.With):
            expr = ast.FunctionDef()
            expr.name = '__pyfora_with_block_as_function__'
            expr.args = ast.arguments()
            expr.args.args = []
            expr.args.defaults = []
            expr.args.vararg = None
            expr.args.kwarg = None

            expr.decorator_list = []

            #make sure we copy the list - if we use the existing one, we will mess up the
            #cached copy!
            expr.body = list(functionAst.body)
            expr.lineno = functionAst.lineno - 1
            expr.col_offset = functionAst.col_offset

            bound_variables = PyAstFreeVariableAnalyses.collectBoundValuesInScope(
                expr)

            return_dict_list_src = "[" + ",".join(
                "'%s'" % k for k in bound_variables) + "]"
            return_dict_expr_src = "{{k: __locals[k] for k in {return_dict_list_src} if k in __locals}}".format(
                return_dict_list_src=return_dict_list_src)
            return_dict_expr_src = "(lambda __locals: {return_dict_expr_src})(dict(locals()))".format(
                return_dict_expr_src=return_dict_expr_src)

            return_dict_expr = ast.parse(return_dict_expr_src).body[0].value

            return_statement = ast.Return(
                ast.Tuple(
                    [return_dict_expr,
                     ast.Num(0), ast.Num(0)], ast.Load()))

            return_statement_exception = ast.Return(
                ast.Tuple([
                    return_dict_expr,
                    ast.Call(
                        ast.Name("__pyfora_get_exception_traceback__",
                                 ast.Load()), [], [], None, None),
                    ast.Name("__pyfora_exception_var__", ast.Load())
                ], ast.Load()))

            expr.body.append(return_statement)

            handler = ast.ExceptHandler(
                None, ast.Name("__pyfora_exception_var__", ast.Store()),
                [return_statement_exception])

            #now wrap in a try-catch block
            curBody = list(expr.body)
            expr.body = [ast.TryExcept(curBody, [handler], [])]

            #for every incoming variable 'x' that's also assigned to, create a dummy '__pyfora_var_guard_x' that actually
            #takes the value in from the surrounding scope, and immediately assign it
            for var in memberDictionary:
                if var in bound_variables:
                    newVar = "__pyfora_var_guard_" + var

                    var_copy_expr = ast.Assign(
                        targets=[ast.Name(var, ast.Store())],
                        value=ast.Name(newVar, ast.Load()))

                    globalScope[newVar] = globalScope[var]
                    del globalScope[var]

                    expr.body = [var_copy_expr] + expr.body

            expr = updatePyAstMemberChains(expr,
                                           globalScope,
                                           isClassContext=True)

            ast.fix_missing_locations(expr)

            def extractTrace():
                return sys.exc_info()[2]

            globalScope['__pyfora_get_exception_traceback__'] = extractTrace

            code = compile(ast.Module([expr]), filename, 'exec')

            exec code in globalScope, outputLocals
            assert len(outputLocals) == 1
            return list(outputLocals.values())[0]
        else:
            functionAst = updatePyAstMemberChains(ast.Module([functionAst],
                                                             lineno=1,
                                                             col_offset=0),
                                                  globalScope,
                                                  isClassContext=False)

            code = compile(functionAst, filename, 'exec')

            exec code in globalScope, outputLocals
            assert len(outputLocals) == 1
            return list(outputLocals.values())[0]
Exemple #13
0
 def visit_Return(self, node):
     return ast.Assign([ast.Name(f"__magma_ssa_return_value", ast.Store())],
                       node.value)
Exemple #14
0
 def visit_Return(self, node):
     self.counter += 1
     name = f"__magma_ssa_return_value_{self.counter}"
     return ast.Assign([ast.Name(name, ast.Store())], node.value)
Exemple #15
0
 def visit_Expr(self, node):
     'Change last expression into an assignment'
     return ast.Assign([ast.Name('result', ast.Store())],
                       self.generic_visit(node.value))
Exemple #16
0
    def _store_ex_dict(self, node: ex_ast.ExDict):
        node.ctx = self.ctx
        for each in node.values:
            self.visit(each)

    visit_Name = _store_simply
    visit_Subscript = _store_simply
    visit_Attribute = _store_simply
    visit_Tuple = _store_recursively
    visit_List = _store_recursively
    visit_ExDict = _store_ex_dict
    visit_Starred = _store_recursively


_fix_store = ExprContextFixer(ast.Store()).visit
_fix_del = ExprContextFixer(ast.Del()).visit


class Loc:

    def __matmul__(self, other: t.Union[ast.AST, Tokenizer]):
        return {
            'lineno': other.lineno,
            'col_offset':
                other.col_offset if hasattr(other, 'col_offset') else other.colno
        }


class LocatedError(Exception):
Exemple #17
0
 def _makeAttrAssign(name, attr, value, lineno=1, indent=""):
     name = ast.Name(id=name, lineno=lineno, col_offset=len(indent), ctx=ast.Load())
     attr = ast.Attribute(attr=attr, value=name, lineno=lineno, col_offset = len(f"{indent}{name}."), ctx=ast.Store())
     value = ast.Name(id=value, lineno=lineno, col_offset=len(f"{indent}{name}.{attr} = "), ctx=ast.Load())
     assign = ast.Assign(targets=[attr], value=value, lineno=lineno, col_offset=len(f"{indent}{name}.{attr} "))
     return assign
Exemple #18
0
def _translate_all_expression_to_a_module(
        generator_exp: ast.GeneratorExp, generated_function_name: str,
        name_to_value: Mapping[str, Any]) -> ast.Module:
    """
    Generate the AST of the module to trace an all quantifier on an generator expression.

    :param generator_exp: generator expression to be translated
    :param generated_function_name: UUID of the tracing function to be used in the code
    :param name_to_value:
        mapping of all resolved values to the variable names
        (passed as arguments to the function so that the generation can access them)
    :return: translation to a module
    """
    assert generated_function_name not in name_to_value
    assert not hasattr(builtins, generated_function_name)

    # Collect all the names involved in the generation
    relevant_names = _collect_stored_names(
        generator.target for generator in generator_exp.generators)

    assert generated_function_name not in relevant_names

    # Work backwards, from the most-inner block outwards

    result_id = 'icontract_tracing_all_result_{}'.format(uuid.uuid4().hex)
    result_assignment = ast.Assign(
        targets=[ast.Name(id=result_id, ctx=ast.Store())],
        value=generator_exp.elt)

    exceptional_return = ast.Return(
        ast.Tuple(elts=[
            ast.Name(id=result_id, ctx=ast.Load()),
            ast.Tuple(elts=[
                ast.Tuple(elts=[
                    ast.Constant(value=relevant_name, kind=None),
                    ast.Name(id=relevant_name, ctx=ast.Load())
                ],
                          ctx=ast.Load()) for relevant_name in relevant_names
            ],
                      ctx=ast.Load())
        ],
                  ctx=ast.Load()))

    # While happy return shall not be executed, we add it here for robustness in case
    # future refactorings forget to check for that edge case.
    happy_return = ast.Return(
        ast.Tuple(elts=[
            ast.Name(id=result_id, ctx=ast.Load()),
            ast.Constant(value=None, kind=None)
        ],
                  ctx=ast.Load()))

    critical_if: If = ast.If(test=ast.Name(id=result_id, ctx=ast.Load()),
                             body=[ast.Pass()],
                             orelse=[exceptional_return])

    # Previous inner block to be added as body to the next outer block
    block = None  # type: Optional[List[ast.stmt]]
    for i, comprehension in enumerate(reversed(generator_exp.generators)):
        if i == 0:
            # This is the inner-most comprehension.
            block = [result_assignment, critical_if]
        assert block is not None

        for condition in reversed(comprehension.ifs):
            block = [ast.If(test=condition, body=block, orelse=[])]

        if not comprehension.is_async:
            block = [
                ast.For(target=comprehension.target,
                        iter=comprehension.iter,
                        body=block,
                        orelse=[])
            ]
        else:
            block = [
                ast.AsyncFor(target=comprehension.target,
                             iter=comprehension.iter,
                             body=block,
                             orelse=[])
            ]

    assert block is not None

    block.append(happy_return)

    # Now we are ready to generate the function.

    is_async = any(comprehension.is_async
                   for comprehension in generator_exp.generators)

    args = [
        ast.arg(arg=name, annotation=None)
        for name in sorted(name_to_value.keys())
    ]

    if sys.version_info < (3, 5):
        raise NotImplementedError(
            "Python versions below 3.5 not supported, got: {}".format(
                sys.version_info))

    if not is_async:
        if sys.version_info < (3, 8):
            func_def_node = ast.FunctionDef(
                name=generated_function_name,
                args=ast.arguments(args=args,
                                   kwonlyargs=[],
                                   kw_defaults=[],
                                   defaults=[],
                                   vararg=None,
                                   kwarg=None),
                decorator_list=[],
                body=block
            )  # type: Union[ast.FunctionDef, ast.AsyncFunctionDef]

            module_node = ast.Module(body=[func_def_node])
        else:
            func_def_node = ast.FunctionDef(name=generated_function_name,
                                            args=ast.arguments(args=args,
                                                               posonlyargs=[],
                                                               kwonlyargs=[],
                                                               kw_defaults=[],
                                                               defaults=[],
                                                               vararg=None,
                                                               kwarg=None),
                                            decorator_list=[],
                                            body=block)

            module_node = ast.Module(body=[func_def_node], type_ignores=[])
    else:
        if sys.version_info < (3, 8):
            async_func_def_node = ast.AsyncFunctionDef(
                name=generated_function_name,
                args=ast.arguments(args=args,
                                   kwonlyargs=[],
                                   kw_defaults=[],
                                   defaults=[],
                                   vararg=None,
                                   kwarg=None),
                decorator_list=[],
                body=block)

            module_node = ast.Module(body=[async_func_def_node])
        else:
            async_func_def_node = ast.AsyncFunctionDef(
                name=generated_function_name,
                args=ast.arguments(args=args,
                                   posonlyargs=[],
                                   kwonlyargs=[],
                                   kw_defaults=[],
                                   defaults=[],
                                   vararg=None,
                                   kwarg=None),
                decorator_list=[],
                body=block)

            module_node = ast.Module(body=[async_func_def_node],
                                     type_ignores=[])

    ast.fix_missing_locations(module_node)

    return module_node
Exemple #19
0
    def visit_Assert(self, assert_):
        """Return the AST statements to replace the ast.Assert instance.

        This rewrites the test of an assertion to provide
        intermediate values and replace it with an if statement which
        raises an assertion error with a detailed explanation in case
        the expression is false.

        """
        if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1:
            from _pytest.warning_types import PytestAssertRewriteWarning
            import warnings

            warnings.warn_explicit(
                PytestAssertRewriteWarning(
                    "assertion is always true, perhaps remove parentheses?"),
                category=None,
                filename=str(self.module_path),
                lineno=assert_.lineno,
            )

        self.statements = []
        self.variables = []
        self.variable_counter = itertools.count()
        self.stack = []
        self.on_failure = []
        self.push_format_context()
        # Rewrite assert into a bunch of statements.
        top_condition, explanation = self.visit(assert_.test)
        # If in a test module, check if directly asserting None, in order to warn [Issue #3191]
        if self.module_path is not None:
            self.statements.append(
                self.warn_about_none_ast(top_condition,
                                         module_path=self.module_path,
                                         lineno=assert_.lineno))
        # Create failure message.
        body = self.on_failure
        negation = ast.UnaryOp(ast.Not(), top_condition)
        self.statements.append(ast.If(negation, body, []))
        if assert_.msg:
            assertmsg = self.helper("_format_assertmsg", assert_.msg)
            explanation = "\n>assert " + explanation
        else:
            assertmsg = ast.Str("")
            explanation = "assert " + explanation
        template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
        msg = self.pop_format_context(template)
        fmt = self.helper("_format_explanation", msg)
        err_name = ast.Name("AssertionError", ast.Load())
        exc = ast.Call(err_name, [fmt], [])
        raise_ = ast.Raise(exc, None)

        body.append(raise_)
        # Clear temporary variables by setting them to None.
        if self.variables:
            variables = [
                ast.Name(name, ast.Store()) for name in self.variables
            ]
            clear = ast.Assign(variables, _NameConstant(None))
            self.statements.append(clear)
        # Fix line numbers.
        for stmt in self.statements:
            set_location(stmt, assert_.lineno, assert_.col_offset)
        return self.statements
Exemple #20
0
def execute_code_block(compiler, block, example_globals, script_vars,
                       gallery_conf):
    """Executes the code block of the example file"""
    blabel, bcontent, lineno = block
    # If example is not suitable to run, skip executing its blocks
    if not script_vars['execute_script'] or blabel == 'text':
        return ''

    cwd = os.getcwd()
    # Redirect output to stdout and
    orig_stdout, orig_stderr = sys.stdout, sys.stderr
    src_file = script_vars['src_file']

    # First cd in the original example dir, so that any file
    # created by the example get created in this directory

    captured_std = StringIO()
    os.chdir(os.path.dirname(src_file))

    sys_path = copy.deepcopy(sys.path)
    sys.path.append(os.getcwd())
    sys.stdout = sys.stderr = LoggingTee(captured_std, logger, src_file)

    try:
        dont_inherit = 1
        if sys.version_info >= (3, 8):
            ast_Module = partial(ast.Module, type_ignores=[])
        else:
            ast_Module = ast.Module
        code_ast = ast_Module([bcontent])
        code_ast = compile(bcontent, src_file, 'exec',
                           ast.PyCF_ONLY_AST | compiler.flags, dont_inherit)
        ast.increment_lineno(code_ast, lineno - 1)
        # capture output if last line is expression
        is_last_expr = False
        if len(code_ast.body) and isinstance(code_ast.body[-1], ast.Expr):
            is_last_expr = True
            last_val = code_ast.body.pop().value
            # exec body minus last expression
            _, mem_body = _memory_usage(
                _exec_once(compiler(code_ast, src_file, 'exec'),
                           example_globals), gallery_conf)
            # exec last expression, made into assignment
            body = [
                ast.Assign(targets=[ast.Name(id='___', ctx=ast.Store())],
                           value=last_val)
            ]
            last_val_ast = ast_Module(body=body)
            ast.fix_missing_locations(last_val_ast)
            _, mem_last = _memory_usage(
                _exec_once(compiler(last_val_ast, src_file, 'exec'),
                           example_globals), gallery_conf)
            # capture the assigned variable
            ___ = example_globals['___']
            mem_max = max(mem_body, mem_last)
        else:
            _, mem_max = _memory_usage(
                _exec_once(compiler(code_ast, src_file, 'exec'),
                           example_globals), gallery_conf)
        script_vars['memory_delta'].append(mem_max)
    except Exception:
        sys.stdout.flush()
        sys.stderr.flush()
        sys.stdout, sys.stderr = orig_stdout, orig_stderr
        except_rst = handle_exception(sys.exc_info(), src_file, script_vars,
                                      gallery_conf)
        code_output = u"\n{0}\n\n\n\n".format(except_rst)
        # still call this even though we won't use the images so that
        # figures are closed
        save_figures(block, script_vars, gallery_conf)
    else:
        sys.stdout.flush()
        sys.stderr.flush()
        sys.stdout, orig_stderr = orig_stdout, orig_stderr
        sys.path = sys_path
        os.chdir(cwd)

        last_repr = None
        repr_meth = None
        if gallery_conf['capture_repr'] != () and is_last_expr:
            for meth in gallery_conf['capture_repr']:
                try:
                    last_repr = getattr(___, meth)()
                    # for case when last statement is print()
                    if last_repr is None or last_repr == 'None':
                        repr_meth = None
                    else:
                        repr_meth = meth
                except Exception:
                    pass
                else:
                    if isinstance(last_repr, str):
                        break
        captured_std = captured_std.getvalue().expandtabs()
        # normal string output
        if repr_meth in ['__repr__', '__str__'] and last_repr:
            captured_std = u"{0}\n{1}".format(captured_std, last_repr)
        if captured_std and not captured_std.isspace():
            captured_std = CODE_OUTPUT.format(indent(captured_std, u' ' * 4))
        else:
            captured_std = ''
        images_rst = save_figures(block, script_vars, gallery_conf)
        # give html output its own header
        if repr_meth == '_repr_html_':
            captured_html = html_header.format(indent(last_repr, u' ' * 8))
        else:
            captured_html = ''
        code_output = u"\n{0}\n\n{1}\n{2}\n\n".format(images_rst, captured_std,
                                                      captured_html)

    finally:
        os.chdir(cwd)
        sys.path = sys_path
        sys.stdout, sys.stderr = orig_stdout, orig_stderr

    return code_output
Exemple #21
0
    def _compile_directive_call_assets(self, el, options):
        """ This special 't-call' tag can be used in order to aggregate/minify javascript and css assets"""
        if len(el):
            raise SyntaxError("t-call-assets cannot contain children nodes")

        # nodes = self._get_asset(xmlid, options, css=css, js=js, debug=values.get('debug'), async=async, values=values)
        #
        # for index, (tagName, t_attrs, content) in enumerate(nodes):
        #     if index:
        #         append('\n        ')
        #     append('<')
        #     append(tagName)
        #
        #     self._post_processing_att(tagName, t_attrs, options)
        #     for name, value in t_attrs.items():
        #         if value or isinstance(value, string_types)):
        #             append(u' ')
        #             append(name)
        #             append(u'="')
        #             append(escape(pycompat.to_text((value)))
        #             append(u'"')
        #
        #     if not content and tagName in self._void_elements:
        #         append('/>')
        #     else:
        #         append('>')
        #         if content:
        #           append(content)
        #         append('</')
        #         append(tagName)
        #         append('>')
        #
        space = el.getprevious() is not None and el.getprevious(
        ).tail or el.getparent().text
        sep = u'\n' + space.rsplit('\n').pop()
        return [
            ast.Assign(
                targets=[ast.Name(id='nodes', ctx=ast.Store())],
                value=ast.Call(
                    func=ast.Attribute(value=ast.Name(id='self',
                                                      ctx=ast.Load()),
                                       attr='_get_asset',
                                       ctx=ast.Load()),
                    args=[
                        ast.Str(el.get('t-call-assets')),
                        ast.Name(id='options', ctx=ast.Load()),
                    ],
                    keywords=[
                        ast.keyword('css',
                                    self._get_attr_bool(el.get('t-css',
                                                               True))),
                        ast.keyword('js',
                                    self._get_attr_bool(el.get('t-js', True))),
                        ast.keyword(
                            'debug',
                            ast.Call(func=ast.Attribute(value=ast.Name(
                                id='values', ctx=ast.Load()),
                                                        attr='get',
                                                        ctx=ast.Load()),
                                     args=[ast.Str('debug')],
                                     keywords=[],
                                     starargs=None,
                                     kwargs=None)),
                        ast.keyword(
                            'async',
                            self._get_attr_bool(el.get('async', False))),
                        ast.keyword('values',
                                    ast.Name(id='values', ctx=ast.Load())),
                    ],
                    starargs=None,
                    kwargs=None)),
            ast.For(
                target=ast.Tuple(elts=[
                    ast.Name(id='index', ctx=ast.Store()),
                    ast.Tuple(elts=[
                        ast.Name(id='tagName', ctx=ast.Store()),
                        ast.Name(id='t_attrs', ctx=ast.Store()),
                        ast.Name(id='content', ctx=ast.Store())
                    ],
                              ctx=ast.Store())
                ],
                                 ctx=ast.Store()),
                iter=ast.Call(func=ast.Name(id='enumerate', ctx=ast.Load()),
                              args=[ast.Name(id='nodes', ctx=ast.Load())],
                              keywords=[],
                              starargs=None,
                              kwargs=None),
                body=[
                    ast.If(test=ast.Name(id='index', ctx=ast.Load()),
                           body=[self._append(ast.Str(sep))],
                           orelse=[]),
                    self._append(ast.Str(u'<')),
                    self._append(ast.Name(id='tagName', ctx=ast.Load())),
                ] + self._append_attributes() + [
                    ast.If(test=ast.BoolOp(
                        op=ast.And(),
                        values=[
                            ast.UnaryOp(ast.Not(),
                                        ast.Name(id='content', ctx=ast.Load()),
                                        lineno=0,
                                        col_offset=0),
                            ast.Compare(
                                left=ast.Name(id='tagName', ctx=ast.Load()),
                                ops=[ast.In()],
                                comparators=[
                                    ast.Attribute(value=ast.Name(
                                        id='self', ctx=ast.Load()),
                                                  attr='_void_elements',
                                                  ctx=ast.Load())
                                ]),
                        ]),
                           body=[self._append(ast.Str(u'/>'))],
                           orelse=[
                               self._append(ast.Str(u'>')),
                               ast.If(test=ast.Name(id='content',
                                                    ctx=ast.Load()),
                                      body=[
                                          self._append(
                                              ast.Name(id='content',
                                                       ctx=ast.Load()))
                                      ],
                                      orelse=[]),
                               self._append(ast.Str(u'</')),
                               self._append(
                                   ast.Name(id='tagName', ctx=ast.Load())),
                               self._append(ast.Str(u'>')),
                           ])
                ],
                orelse=[])
        ]
Exemple #22
0
 def test_assign_multiple_slice(self):
     self.v.visit(
         ast.Assign([
             ast.Subscript(ast_load('foo'), ast.Slice(), ast.Store()),
             ast_store('bar'),
         ], ast.Str('test')))
Exemple #23
0
def name(v, store=False):
    return ast.Name(id=v, ctx=ast.Load() if not store else ast.Store(), lineno=1, col_offset=0)
Exemple #24
0
import ast

from anoky.expansion.expansion_context import ExpansionContext
from anoky.macros.macro import Macro
from anoky.special_forms.special_form import SpecialForm

macrostore_init_code = [
    # import anoky.module as __anoky__
    ast.Import([ast.alias(name="anoky.module", asname="__aky__")]),
    # __macros__ = {}  (and for id macros and special forms)
    ast.Assign(targets=[ast.Name(id="__macros__", ctx=ast.Store())],
               value=ast.Dict([], [])),
    ast.Assign(targets=[ast.Name(id="__id_macros__", ctx=ast.Store())],
               value=ast.Dict([], [])),
    ast.Assign(targets=[ast.Name(id="__special_forms__", ctx=ast.Store())],
               value=ast.Dict([], []))
]


def generate_macro_store_code(mac_name, mac:Macro):

    # __macros__[mac_name]
    store_as_code = ast.Subscript(value=ast.Name(id="__macros__", ctx=ast.Load()),
                                  slice=ast.Index(ast.Str(mac_name)),
                                  ctx=ast.Store())

    # ~~RHS~~
    #macro_gen_code =

    raise NotImplementedError()
Exemple #25
0
def res_python_setup(res: Property) -> Tuple[Callable[[EntityFixup], object], str]:
    variables = {}
    variable_order = []
    code = None
    result_var = None
    for child in res:
        if child.name.startswith('$'):
            if child.value.casefold() not in FUNC_GLOBALS:
                raise Exception('Invalid variable type! ({})'.format(child.value))
            variables[child.name[1:]] = child.value.casefold()
            variable_order.append(child.name[1:])
        elif child.name == 'op':
            code = child.value
        elif child.name == 'resultvar':
            result_var = child.value
        else:
            raise Exception('Invalid key "{}"'.format(child.real_name))
    if not code:
        raise Exception('No operation specified!')
    if not result_var:
        raise Exception('No destination specified!')

    for name in variables:
        if name.startswith('_'):
            raise Exception('"{}" is not permitted as a variable name!'.format(name))

    # Allow $ in the variable names..
    code = code.replace('$', '')

    # Now process the code to convert it into a function taking variables
    # and returning them.
    # We also need to whitelist operations for security.

    expression = ast.parse(
        code,
        '<bee2_op>',
        mode='eval',
    ).body

    Checker(variable_order).visit(expression)

    # For each variable, do
    # var = func(_fixup['var'])
    statements: List[ast.AST] = [
        ast.Assign(
            targets=[ast.Name(id=var_name, ctx=ast.Store())],
            value=ast.Call(
                func=ast.Name(id=variables[var_name], ctx=ast.Load()),
                args=[
                    ast.Subscript(
                        value=ast.Name(id='_fixup', ctx=ast.Load()),
                        slice=ast.Index(value=ast.Str(s=var_name)),
                        ctx=ast.Load(),
                    ),
                ],
                keywords=[],
                starargs=None,
                kwargs=None,
            )
        )
        for line_num, var_name in enumerate(
            variable_order, start=1,
        )
    ]
    # The last statement returns the target expression.
    statements.append(ast.Return(expression, lineno=len(variable_order)+1, col_offset=0))

    args = ast.arguments(
        vararg=None, 
        kwonlyargs=[], 
        kw_defaults=[], 
        kwarg=None, 
        defaults=[],
    )
    # Py 3.8+, make it pos-only.
    if 'posonlyargs' in args._fields:
        args.posonlyargs = [ast.arg('_fixup', None)]
        args.args = []
    else:  # Just make it a regular arg.
        args.args = [ast.arg('_fixup', None)]

    func = ast.Module([
            ast.FunctionDef(
                name='_bee2_generated_func',
                args=args,
                body=statements,
                decorator_list=[],
            ),
        ],
        lineno=1,
        col_offset=0,
    )
    # Python 3.8 also
    if 'type_ignores' in func._fields:
        func.type_ignores = []

    # Fill in lineno and col_offset
    ast.fix_missing_locations(func)

    ns: Dict[str, Any] = {}
    eval(compile(func, '<bee2_op>', mode='exec'), FUNC_GLOBALS, ns)
    compiled_func = ns['_bee2_generated_func']
    compiled_func.__name__ = '<bee2_func>'
    return compiled_func, result_var
Exemple #26
0
def generate_idmacro_store_code(idmac_name, idmac:Macro):

    store_as_code = ast.Subscript(value=ast.Name(id="__id_macros__", ctx=ast.Load()),
                                  slice=ast.Index(ast.Str(idmac_name)),
                                  ctx=ast.Store())
Exemple #27
0
    def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
        """Return the AST statements to replace the ast.Assert instance.

        This rewrites the test of an assertion to provide
        intermediate values and replace it with an if statement which
        raises an assertion error with a detailed explanation in case
        the expression is false.
        """
        if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1:
            from _pytest.warning_types import PytestAssertRewriteWarning
            import warnings

            # TODO: This assert should not be needed.
            assert self.module_path is not None
            warnings.warn_explicit(
                PytestAssertRewriteWarning(
                    "assertion is always true, perhaps remove parentheses?"
                ),
                category=None,
                filename=os.fspath(self.module_path),
                lineno=assert_.lineno,
            )

        self.statements: List[ast.stmt] = []
        self.variables: List[str] = []
        self.variable_counter = itertools.count()

        if self.enable_assertion_pass_hook:
            self.format_variables: List[str] = []

        self.stack: List[Dict[str, ast.expr]] = []
        self.expl_stmts: List[ast.stmt] = []
        self.push_format_context()
        # Rewrite assert into a bunch of statements.
        top_condition, explanation = self.visit(assert_.test)

        negation = ast.UnaryOp(ast.Not(), top_condition)

        if self.enable_assertion_pass_hook:  # Experimental pytest_assertion_pass hook
            msg = self.pop_format_context(ast.Str(explanation))

            # Failed
            if assert_.msg:
                assertmsg = self.helper("_format_assertmsg", assert_.msg)
                gluestr = "\n>assert "
            else:
                assertmsg = ast.Str("")
                gluestr = "assert "
            err_explanation = ast.BinOp(ast.Str(gluestr), ast.Add(), msg)
            err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation)
            err_name = ast.Name("AssertionError", ast.Load())
            fmt = self.helper("_format_explanation", err_msg)
            exc = ast.Call(err_name, [fmt], [])
            raise_ = ast.Raise(exc, None)
            statements_fail = []
            statements_fail.extend(self.expl_stmts)
            statements_fail.append(raise_)

            # Passed
            fmt_pass = self.helper("_format_explanation", msg)
            orig = self._assert_expr_to_lineno()[assert_.lineno]
            hook_call_pass = ast.Expr(
                self.helper(
                    "_call_assertion_pass",
                    ast.Num(assert_.lineno),
                    ast.Str(orig),
                    fmt_pass,
                )
            )
            # If any hooks implement assert_pass hook
            hook_impl_test = ast.If(
                self.helper("_check_if_assertion_pass_impl"),
                self.expl_stmts + [hook_call_pass],
                [],
            )
            statements_pass = [hook_impl_test]

            # Test for assertion condition
            main_test = ast.If(negation, statements_fail, statements_pass)
            self.statements.append(main_test)
            if self.format_variables:
                variables = [
                    ast.Name(name, ast.Store()) for name in self.format_variables
                ]
                clear_format = ast.Assign(variables, ast.NameConstant(None))
                self.statements.append(clear_format)

        else:  # Original assertion rewriting
            # Create failure message.
            body = self.expl_stmts
            self.statements.append(ast.If(negation, body, []))
            if assert_.msg:
                assertmsg = self.helper("_format_assertmsg", assert_.msg)
                explanation = "\n>assert " + explanation
            else:
                assertmsg = ast.Str("")
                explanation = "assert " + explanation
            template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
            msg = self.pop_format_context(template)
            fmt = self.helper("_format_explanation", msg)
            err_name = ast.Name("AssertionError", ast.Load())
            exc = ast.Call(err_name, [fmt], [])
            raise_ = ast.Raise(exc, None)

            body.append(raise_)

        # Clear temporary variables by setting them to None.
        if self.variables:
            variables = [ast.Name(name, ast.Store()) for name in self.variables]
            clear = ast.Assign(variables, ast.NameConstant(None))
            self.statements.append(clear)
        # Fix line numbers.
        for stmt in self.statements:
            set_location(stmt, assert_.lineno, assert_.col_offset)
        return self.statements
Exemple #28
0
def node():
    """Get an ast.Assign node of 'x = 1'."""
    return ast.Assign(targets=[ast.Name(id='x', ctx=ast.Store())],
                      value=ast.Num(n=1))
Exemple #29
0
    def visit_Assign(self, node):
        assert (len(node.targets) == 1)
        self.generic_visit(node)

        decorated = isinstance(node.value, ast.Call) and isinstance(
            node.value.func, ast.Attribute) and isinstance(node.value.func.value, ast.Name) \
                    and node.value.func.value.id == 'ti'

        is_static_assign = False

        if decorated:
            attr = node.value.func
            if attr.attr == 'static':
                is_static_assign = True
            else:
                pass  # eg. x = ti.cast(xx) will reach here, but they're not decorators, so no raising errors here

        if is_static_assign:
            return node

        if isinstance(node.targets[0], ast.Tuple):
            targets = node.targets[0].elts

            # Create
            stmts = []

            holder = self.parse_stmt('__tmp_tuple = ti.expr_init_list(0, '
                                     f'{len(targets)})')
            holder.value.args[0] = node.value

            stmts.append(holder)

            def tuple_indexed(i):
                indexing = self.parse_stmt('__tmp_tuple[0]')
                self.set_subscript_index(indexing.value,
                                         self.parse_expr("{}".format(i)))
                return indexing.value

            for i, target in enumerate(targets):
                is_local = isinstance(target, ast.Name)
                if is_local and self.is_creation(target.id):
                    var_name = target.id
                    target.ctx = ast.Store()
                    # Create
                    init = ast.Attribute(value=ast.Name(id='ti',
                                                        ctx=ast.Load()),
                                         attr='expr_init',
                                         ctx=ast.Load())
                    rhs = ast.Call(
                        func=init,
                        args=[tuple_indexed(i)],
                        keywords=[],
                    )
                    self.create_variable(var_name)
                    stmts.append(ast.Assign(targets=[target], value=rhs))
                else:
                    # Assign
                    target.ctx = ast.Load()
                    func = ast.Attribute(value=target,
                                         attr='assign',
                                         ctx=ast.Load())
                    call = ast.Call(func=func,
                                    args=[tuple_indexed(i)],
                                    keywords=[])
                    stmts.append(ast.Expr(value=call))

            for stmt in stmts:
                ast.copy_location(stmt, node)
            stmts.append(self.parse_stmt('del __tmp_tuple'))
            return self.make_single_statement(stmts)
        else:
            is_local = isinstance(node.targets[0], ast.Name)
            if is_local and self.is_creation(node.targets[0].id):
                var_name = node.targets[0].id
                # Create
                init = ast.Attribute(value=ast.Name(id='ti', ctx=ast.Load()),
                                     attr='expr_init',
                                     ctx=ast.Load())
                rhs = ast.Call(
                    func=init,
                    args=[node.value],
                    keywords=[],
                )
                self.create_variable(var_name)
                return ast.copy_location(
                    ast.Assign(targets=node.targets, value=rhs), node)
            else:
                # Assign
                node.targets[0].ctx = ast.Load()
                func = ast.Attribute(value=node.targets[0],
                                     attr='assign',
                                     ctx=ast.Load())
                call = ast.Call(func=func, args=[node.value], keywords=[])
                return ast.copy_location(ast.Expr(value=call), node)
Exemple #30
0
def p_target(t):
    '''target : IDENTIFIER'''
    identifier = ast.Name(t[1], ast.Store())
    identifier.lineno = t.lineno(1)
    identifier.col_offset = -1  # XXX
    t[0] = [identifier]