Example #1
0
def analyze_tree(tree, category):

    if isinstance(tree, list):
        subtrees = [analyze_tree(subtree, category) for subtree in tree]
        return If(eparse('True'), subtrees, [])

    elif isinstance(tree, dict):
        if len(tree) != 1:
            raise ValueError('len(dict) != 1')
        rule, subtree = tree.items()[0]
        r = analyze_rule(rule)
        if isinstance(r, AST):
            test = r
            return If(test, [analyze_tree(subtree, category)], [])
        else:
            dueling_category_check(category, r)
            category = r
            return analyze_tree(subtree, category)

    else:
        rule = tree
        r = analyze_rule(rule)
        if isinstance(r, AST):
            test = r
            if category is None:
                raise ValueError('bottomed out without category')
            return If(test, [Return(Str(category))], [])
        else:
            dueling_category_check(category, r)
            category = r
            return Return(Str(category))
Example #2
0
    def body_helper(self, body):
        from ast import expr, Return

        # place return in the last expression of body
        if isinstance(body, expr):
            body = [Return(body)]
        elif isinstance(body, list) and not isinstance(body[-1], Return):
            body[-1] = Return(body[-1])

        return body
Example #3
0
 def _if_pattern(self, pattern):
     self.imported.add('re')
     # fix known ietf regex use
     pattern = pattern.replace('\\p{N}\\p{L}', '\\w')
     return [
         If(
             test=UnaryOp(
                 op=Not(),
                 operand=Call(
                     func=Attribute(
                         value=Name(id='re', ctx=Load()),
                         attr='match',
                         ctx=Load(),
                     ),
                     args=[
                         Constant(value=pattern, kind=None),
                         Name(id='value', ctx=Load()),
                         Attribute(
                             value=Name(id='re', ctx=Load()),
                             attr='UNICODE',
                             ctx=Load(),
                         ),
                     ],
                     keywords=[],
                 ),
             ),
             body=[
                 Return(value=Constant(value=False, kind=None), ),
             ],
             orelse=[],
         ),
     ]
Example #4
0
    def visit_let(self, letexp: Expr):
        # To properly account for scoping and ensure that the entire node produces an expression,
        # we translate the let binding as a function that we call with the value we intend to bind.
        # Yes, this is somewhat ugly.
        """
        let var = value in body
        =======================
        def let_thunk(var):
            return body
        let_thunk(value)
        """
        bind_body, bind_defs = self.visit(letexp.body)

        func_name = self.generate_function_name("_let_func")
        binding_func = self.create_def(func_name,
                                       [self.get_var_name(letexp.var)],
                                       bind_defs + [Return(bind_body)])

        # we call the binding func with the intended value for the bound variable

        # special case: if the value is a function literal, we must ensure it can be
        # recursive by naming it after the var
        if isinstance(letexp.value, Function):
            value_def, value_name = self.convert_func_node(
                letexp.value, letexp.var)
            return (
                self.create_call(func_name, [Name(value_name, Load())]),
                [value_def, binding_func],
            )

        value_body, value_defs = self.visit(letexp.value)
        value_defs.append(binding_func)
        binding_call = self.create_call(func_name, [value_body])
        return (binding_call, value_defs)
Example #5
0
 def _if_gt(value):
     if value >= 0:
         comparators = [Constant(value=value, kind=None)]
     else:
         comparators = [
             UnaryOp(
                 op=USub(),
                 operand=Constant(value=abs(value), kind=None),
             ),
         ]
     return [
         If(
             test=Compare(
                 left=Call(
                     func=Name(id='int', ctx=Load()),
                     args=[Name(id='value', ctx=Load())],
                     keywords=[],
                 ),
                 ops=[Gt()],
                 comparators=comparators,
             ),
             body=[
                 Return(value=Constant(value=False, kind=None), ),
             ],
             orelse=[],
         )
     ]
Example #6
0
    def visit_match(self, match: Expr):
        """For matches, we wrap the entire expression in a thunk
        because it is easiest to implement them using if statements.
        For each clause, we generate a function that checks if the
        pattern matches. If yes, we call a function that assigns
        the variables appropriately and invokes the clause body."""
        data, defs = self.visit(match.data)
        data_var = self.generate_var_name("_match_data")

        # must ensure the data clause is executed exactly once
        thunk_body = [Assign([Name(data_var, Store())], data)]
        for clause in match.clauses:
            check_expr = self.create_match_check(clause.lhs,
                                                 Name(data_var, Load()))
            body_def, body_name = self.create_match_clause_body(
                clause.lhs, clause.rhs)
            defs.append(body_def)

            # equiv: if check(data): return body(data)
            thunk_body.append(
                ast.If(check_expr, [
                    Return(
                        self.create_call(body_name, [Name(data_var, Load())]))
                ], []))

        # finally if nothing matches we have a failed assert (should never happen)
        thunk_body.append(
            ast.Assert(NameConstant(False), Str("Match was not exhaustive")))

        thunk_name = self.generate_function_name("_match_thunk")
        thunk_def = self.create_def(thunk_name, [], defs + thunk_body)
        return (self.create_call(thunk_name, []), [thunk_def])
Example #7
0
def getter(item):
    """Construct the getter function.

    partof: #SPC-asts.getter
    """
    func_name = f"{item.var}_getter"
    self_arg = arg(arg="self", annotation=None)
    func_args = arguments(
        args=[self_arg],
        kwonlyargs=[],
        vararg=None,
        kwarg=None,
        defaults=[],
        kw_defaults=[],
    )
    inst_var = Attribute(value=Name(id="self", ctx=ast.Load()),
                         attr=f"_{item.var}",
                         ctx=ast.Load())
    ret_stmt = Return(value=inst_var)
    func_node = FunctionDef(name=func_name,
                            args=func_args,
                            body=[ret_stmt],
                            decorator_list=[],
                            returns=None)
    mod_node = Module(body=[func_node])
    return ast_to_func(mod_node, func_name)
def getLambdaMethod(methodname, body, args_node, file, id):  # methodname = _lambda_0
    global lambdaID
    fullbody = []
    fullbody.extend(getTracers(file, args_node, id))
    fullbody.append(getScopeTracer(file, methodname, id))
    fullbody.append(
        Return(
            value=Call(
                func=Name(id='eval', ctx=Load()),
                args=[
                    Constant(value=to_source(body), kind=None),
                    Call(
                        func=Name(id='locals', ctx=Load()),
                        args=[],
                        keywords=[]),
                    Name(id=methodname + '_locals', ctx=Load())],
                keywords=[]
            )
        )
    )
    return FunctionDef(
        name=methodname + '_return',
        args=args_node,
        body=fullbody,
        decorator_list=[],
        returns=None,
        type_comment=None)
Example #9
0
def make_function(name, args):
    my_args = arguments(
        args=[arg(arg="self", annotation=None)] + [
            # XXX for arrays the name is '' (empty string)
            # which would end up being nothing in the generated
            # source file.
            arg(arg=my_arg or "arg", annotation=None) for my_arg in args
        ],
        defaults=[],
        vararg=None,
        kwonlyargs=[],
        kw_defaults=[],
        kwarg=None,
    )
    my_body = [
        Return(value=Call(
            func=Attribute(
                value=Attribute(
                    value=Attribute(value=Name(id="self"), attr="_contract"),
                    attr="functions",
                ),
                attr=name,
            ),
            args=[Name(id=my_arg or "arg") for my_arg in args],
            keywords=[],
        ))
    ]

    return FunctionDef(name=name,
                       args=my_args,
                       body=my_body,
                       decorator_list=[])
Example #10
0
    def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef:
        self.generic_visit(node)

        if len(node.body) and isinstance(node.body[-1], Expr):
            node.body[-1] = Return(value=node.body[-1].value)
            fix_missing_locations(node.body[-1])

        return node
Example #11
0
 def add_implicit_bare_return(tree, **kw):
     if type(tree) in (FunctionDef, AsyncFunctionDef):
         if type(tree.body[-1]) is not Return:
             tree.body.append(
                 Return(
                     value=None,  # bare "return"
                     lineno=tree.lineno,
                     col_offset=tree.col_offset))
     return tree
    def handle_when(self, when, *others):
        test, body = when.get_source_expressions()
        if others:
            if others[0].__class__.__name__ == "When":
                orelse = [self.handle_when(*others)]
            else:
                # Can we ever have other expressions after the default?
                orelse = [
                    Return(value=self.build_expression(others[0]), **self.file)
                ]
        else:
            orelse = []

        return If(
            test=self.build_expression(test),
            body=[Return(value=self.build_expression(body), **self.file)],
            orelse=orelse,
            **self.file,
        )
Example #13
0
def _make_call_meth(body, return_type, param_names):
    """
    Construct a `__call__` method from the provided `body`

    :param body: The body, probably from a FunctionDef.body
    :type body: ```List[AST]```

    :param return_type: The return type of the parent symbol (probably class). Used to fill in `__call__` return.
    :type return_type: ```Optional[str]```

    :param param_names: Container of AST `id`s to match for rename
    :type param_names: ```Optional[Iterator[str]]```

    :return: Internal function for `__call__`
    :rtype: ```FunctionDef```
    """
    body_len = len(body)
    return_ = (ast.fix_missing_locations(
        RewriteName(param_names).visit(
            Return(get_value(ast.parse(return_type[3:-3]).body[0]),
                   expr=None))) if return_type is not None
               and len(return_type) > 6 and return_type.startswith("```")
               and return_type.endswith("```") else None)
    if body_len:
        if isinstance(body[0], Expr):
            doc_str = get_value(body[0].value)
            if isinstance(doc_str, str) and body_len > 0:
                body = (body[1:] if body_len > 1 else ([
                    set_value(doc_str.replace(":cvar", ":param"))
                    if return_ is None else return_
                ] if body_len == 1 else body))
    #         elif not isinstance(body[0], Return) and return_ is not None:
    #             body.append(return_)
    # elif return_ is not None:
    #     body = [return_]

    return FunctionDef(args=arguments(
        args=[set_arg("self")],
        defaults=[],
        kw_defaults=[],
        kwarg=None,
        kwonlyargs=[],
        posonlyargs=[],
        vararg=None,
        arg=None,
    ),
                       body=body,
                       decorator_list=[],
                       name="__call__",
                       returns=None,
                       arguments_args=None,
                       identifier_name=None,
                       stmt=None,
                       lineno=None,
                       **maybe_type_comment)
Example #14
0
        def insert_returns(body):
            if isinstance(body[-1], Expr):
                body[-1] = Return(body[-1].value)
                fix_missing_locations(body[-1])

            if isinstance(body[-1], If):
                insert_returns(body[-1].body)
                insert_returns(body[-1].orelse)

            if isinstance(body[-1], With):
                insert_returns(body[-1].body)
Example #15
0
    def visit_Return(self, node):
        existing_node = self.generic_visit(node)
        value = existing_node.value
        if value is None:
            return existing_node

        return [Assign(targets=[Name(id=RESULT_NAME, ctx=Store())],
                       value=value),
                self._create_context_call('return_value',
                                          [Name(id=RESULT_NAME, ctx=Load()),
                                           Num(n=existing_node.lineno)]),
                Return(value=Name(id=RESULT_NAME, ctx=Load()))]
Example #16
0
 def visit_Return(self, node: ast.Return):
     with fast.location_of(node):
         node.value = fast.Call(
             func=self._emitter_ast(),
             args=[TraceEvent.after_return.to_ast(), self._get_copy_id_ast(node.value)],
             keywords=fast.kwargs(
                 ret=self._make_tuple_event_for(
                     self.visit(node.value),
                     TraceEvent.before_return,
                     orig_node_id=id(node.value),
                 ),
             ),
         )
     return node
    def __init__(self, function):
        expression = function(None)
        if getattr(expression, "copy", None):
            expression = expression.copy()
        func_code = getattr(function, "__code__", None) or function.func_code
        self.file = {
            "lineno": func_code.co_firstlineno,
            "filename": func_code.co_filename,
            "col_offset": 0,
            "ctx": Load(),
        }
        self.file_store = dict(self.file, ctx=Store())
        self.expression = expression
        body = self.build_expression(expression)
        if isinstance(body, list):
            pass
        elif not isinstance(body, stmt):
            body = [Return(value=body, **self.file)]
        else:
            body = [body]

        self.ast = Module(
            body=[
                FunctionDef(
                    name=func_code.co_name,
                    args=arguments(
                        args=[arg(arg="self", annotation=None)
                              ],  # function.func_code.co_varnames
                        defaults=[],
                        vararg=None,
                        kwarg=None,
                        kwonlyargs=[],
                        kw_defaults=[],
                        posonlyargs=[],
                    ),
                    kwarg=[],
                    kw_defaults=[],
                    vararg=[],
                    kwonlyargs=[],
                    body=body,
                    decorator_list=[],
                ),
            ],
            type_ignores=[],
            **self.file,
        )
        fix_missing_locations(self.ast)
        self.code = compile(self.ast,
                            mode="exec",
                            filename=self.file["filename"])
Example #18
0
    def convert_func_node(self, func: Function, name_var=None):
        """Converts the given Relay function into a Python function, with
        special for named functions (locally or globally)"""
        if name_var is None:
            func_name = self.generate_function_name("_anon_func")
        if isinstance(name_var, GlobalVar):
            func_name = str(name_var.name_hint)
        if isinstance(name_var, Var):
            func_name = self.get_var_name(name_var)

        var_names = [self.get_var_name(var) for var in func.params]
        body, defs = self.visit(func.body)
        ret = self.create_def(func_name, var_names, defs + [Return(body)])
        return (ret, func_name)
Example #19
0
 def visit_ref_write(self, write: Expr):
     """For writing refs, we wrap the update in a thunk
     (returning an empty tuple to match Relay's semantics)
     that we execute at the right time. This ensures such assignments
     can be properly nested, since assignments are statements
     in Python but expressions in Relay"""
     ref, ref_defs = self.visit(write.ref)
     val, val_defs = self.visit(write.value)
     thunk_name = self.generate_function_name('_ref_write_thunk')
     thunk = self.create_def(
         thunk_name, [], ref_defs + val_defs + [
             Assign([ast.Attribute(ref, 'value', Store())], val),
             Return(self.create_call('_container.tuple_object', []))
         ])
     return (self.create_call(thunk_name, []), [thunk])
Example #20
0
		def visit_Return(self,node:ast.Return):
			if self.hot == None or (not self.hotHasReturnCheck and self.funcNames[self.hot] not in self.exitpatterns): return node
			# print("Assign: ",self.funcNames[self.hot])
			sin = [
				Assign(targets=[Name(id='_dbg_ret_var', ctx=Store())], value=node.value),
				Return(value=Name(id='_dbg_ret_var', ctx=Load()))
			]
			if self.hotHasReturnCheck:
				expattern = self.funcparams[self.hot]
				sin.insert(1,Expr(value=Call(func=Name(id='_dbgExit', ctx=Load()), args=[Name(id=pn+'_dbg_str_var_'+str(self.hot),ctx=Load()) for pn in expattern]+[Name(id='_dbg_ret_var', ctx=Load())], keywords=[])))
			if self.funcNames[self.hot] in self.exitpatterns:
				expattern = self.exitpatterns[self.funcNames[self.hot]]
				sin.insert(1,Expr(value=Call(func=Name(id='_dbgExit_'+self.funcNames[self.hot],ctx=Load()), args=[Name(id=pn+'_dbg_str_var_'+str(self.hot),ctx=Load()) for pn in expattern]+[Name(id='_dbg_ret_var', ctx=Load())], keywords=[])))
			for s in sin:
				ast.copy_location(s, node)
				ast.fix_missing_locations(s)
			return sin
Example #21
0
def test():
    """
    Test Function 
    """
    stmt = Program([
        Function("f", [], [
            For("i", 1, 10, 1, [
                Assign("x", IntValue(3)),
                Assign("x", IntValue(4)),
                IfThenElse(BoolValue(True), []),
                While(BoolValue(True), [Return(IntValue(3))]),
                Assign("x", IntValue(5))
            ])
        ]),
        Function("g", [], [Assign("x", IntValue(3))]),
        Assign("x", IntValue(1))
    ])
    nodes, edges = gen_cfg_main(stmt)
    gen_dot(nodes, edges)
Example #22
0
def _tco_transform_return(tree, *, known_ecs, transform_retexpr, **kw):
    if type(tree) is Return:
        non = q[None]
        non = copy_location(non, tree)
        value = tree.value or non  # return --> return None  (bare return has value=None in the AST)
        if not isec(value, known_ecs):
            return Return(value=transform_retexpr(value, known_ecs))
        else:
            # An ec call already escapes, so the return is redundant.
            #
            # If someone writes "return ec(...)" in a "with continuations" block,
            # this cleans up the code, since eliminating the "return" allows us
            # to omit a redundant "let".
            return Expr(value=value)  # return ec(...) --> ec(...)
    elif isec(tree, known_ecs):  # TCO the arg of an ec(...) call
        if len(tree.args) > 1:
            assert False, "expected exactly one argument for escape continuation"  # pragma: no cover
        tree.args[0] = transform_retexpr(tree.args[0], known_ecs)
    return tree
Example #23
0
    def create_match_clause_body(self, pattern: Pattern, body: Expr):
        """Given a match clause pattern and a clause body,
        generates a Python function that when called with an ADT
        that matches the pattern, returns the result of evaluating
        the clause body. This function returns a function definition
        and the name of the generated function."""

        def collect_var_assignments(pat, val):
            """This helper function ensures that the pattern is used to
            properly assign all subfields of the given AST for use
            in the clause body

            E.g., for PatternConstructor(A, PatternVar(v), PatternWildcard(),
            PatternConstructor(B, PatternVar(w)))
            we would want to have
            v = a.fields[0]
            w = a.fields[2].fields[0]
            """
            if isinstance(pat, relay.PatternWildcard):
                return []
            if isinstance(pat, relay.PatternVar):
                return [Assign([self.include_var(pat.var, assign=True)], val)]
            # constructor pattern: assign each field of the value
            # based on subpatterns
            assignments = []
            for i in range(len(pat.patterns)):
                # we want the assignments for val.fields[i]
                field = ast.Subscript(
                    ast.Attribute(val, "fields", Load()), ast.Index(Num(i)), Load()
                )
                assignments += collect_var_assignments(pat.patterns[i], field)
            return assignments

        func_name = self.generate_function_name("_match_clause_body")
        arg_name = self.generate_var_name("_match_clause_body")

        clause_body, defs = self.visit(body)
        assignments = collect_var_assignments(pattern, Name(arg_name, Load()))

        func_def = self.create_def(
            func_name, [arg_name], defs + assignments + [Return(clause_body)]
        )
        return (func_def, func_name)
Example #24
0
    def _union(self, node):
        values = []
        generated = []

        for union in node:
            for what, sub in union.items():
                if ':' in what:
                    if what in generated:
                        # only generate any imported function once
                        continue
                    generated.append(what)
                    name = what
                    yield self._type(what, name, sub)
                else:
                    # this is a build_in type (and my have been refined)
                    # therefore generate one function per type
                    name = self._unique(what)
                    yield self._function(name, self._type(what, what, sub))

                values += [
                    UnaryOp(
                        op=Not(),
                        operand=Call(
                            func=Name(id=self._python_name(name), ctx=Load()),
                            args=[Name(id='value', ctx=Load())],
                            keywords=[],
                        ),
                    ),
                ]

        yield [
            If(
                test=BoolOp(
                    op=And(),
                    values=values,
                ),
                body=[
                    Return(value=Constant(value=False, kind=None), ),
                ],
                orelse=[],
            ),
        ]
Example #25
0
 def transform_tailstmt(tree):
     # TODO: For/AsyncFor/While?
     if type(tree) is If:
         tree.body[-1] = transform_tailstmt(tree.body[-1])
         if tree.orelse:
             tree.orelse[-1] = transform_tailstmt(tree.orelse[-1])
     elif type(tree) in (With, AsyncWith):
         tree.body[-1] = transform_tailstmt(tree.body[-1])
     elif type(tree) is Try:
         # We don't care about finalbody; typically used for unwinding only.
         if tree.orelse:  # tail position is in else clause if present
             tree.orelse[-1] = transform_tailstmt(tree.orelse[-1])
         else:  # tail position is in the body of the "try"
             tree.body[-1] = transform_tailstmt(tree.body[-1])
         # additionally, tail position is in each "except" handler
         for handler in tree.handlers:
             handler.body[-1] = transform_tailstmt(handler.body[-1])
     elif type(tree) is Expr:
         tree = Return(value=tree.value)
     return tree
Example #26
0
 def _if_digit():
     return [
         If(
             test=UnaryOp(
                 op=Not(),
                 operand=Call(
                     func=Attribute(
                         value=Name(id='value', ctx=Load()),
                         attr='isdigit',
                         ctx=Load(),
                     ),
                     args=[],
                     keywords=[],
                 ),
             ),
             body=[
                 Return(value=Constant(value=False, kind=None), ),
             ],
             orelse=[],
         )
     ]
Example #27
0
def define_replace_method(methodname, args, body):
    """
    This generates an ast for a generic function that takes a list parameters
    and returns a generic body
    used to construct something like this

        def <methodname>(<arges>):
            return Module(body=<body>)

    The args parameters are like this :
        [ Name(id='<argname>', ctx=Param()), .... ]
    """

    return Module(  # top module
        body=[
            FunctionDef(  # new function
                name=methodname,
                args=arguments(args=args, vararg=None, kwarg=None,
                               defaults=[]),
                body=[Return(value=body)],
                decorator_list=[])  # module2
        ])  # module
def getLocalsFunction(var_name):  # _lambda_0
    return FunctionDef(
        name=var_name,
        args=arguments(
            posonlyargs=[],
            args=[arg(arg='locls', annotation=None, type_comment=None)],
            vararg=None,
            kwonlyargs=[],
            kw_defaults=[],
            kwarg=None,
            defaults=[]),
        body=[
            Global(names=[var_name + '_locals']),
            Assign(
                targets=[Name(id=var_name + '_locals', ctx=Store())],
                value=Name(id='locls', ctx=Load()),
                type_comment=None),
            Return(value=Name(id=var_name + '_return', ctx=Load()))
        ],
        decorator_list=[],
        returns=None,
        type_comment=None)
Example #29
0
 def _if_length(self, minimum, maximum):
     return [
         If(
             test=Compare(
                 left=Constant(value=int(minimum), kind=None),
                 ops=[
                     Gt(),
                     Gt(),
                 ],
                 comparators=[
                     Call(
                         func=Name(id='len', ctx=Load()),
                         args=[Name(id='value', ctx=Load())],
                         keywords=[],
                     ),
                     Constant(value=int(maximum), kind=None),
                 ],
             ),
             body=[
                 Return(value=Constant(value=False, kind=None), ),
             ],
             orelse=[],
         ),
     ]
Example #30
0
 def visit_Return(self, n: Return):
     """
     * Decrement the depth before exiting. We have to save the returned value into a temporary,
       and only then decrement; otherwise, if the return value itself is a Call, we lose the
       depth.
     """
     var = Assign([Name(self._RETURN_VAR, Store())], n.value)
     n.value = Name(self._RETURN_VAR, Load())
     return self._fix_location_all(
         [
             var,
             self._make_print(
                 [
                     self._parse_fstring(
                         colored(f"return {{{self._RETURN_VAR}}}",
                                 self.RETURN_COLOR))
                 ],
                 "< ",
             ),
             self._decrement_depth(),
             n,
         ],
         n,
     )