Example #1
0
def type_to_ir1(expr_type: ir2.ExprType):
    if isinstance(expr_type, ir2.BoolType):
        return ir1.BoolType()
    elif isinstance(expr_type, ir2.IntType):
        return ir1.IntType()
    elif isinstance(expr_type, ir2.TypeType):
        return ir1.TypeType()
    elif isinstance(expr_type, ir2.BottomType):
        return ir1.BottomType()
    elif isinstance(expr_type, ir2.ListType):
        return ir1.ListType(elem_type=type_to_ir1(expr_type.elem_type))
    elif isinstance(expr_type, ir2.SetType):
        return ir1.ListType(elem_type=type_to_ir1(expr_type.elem_type))
    elif isinstance(expr_type, ir2.FunctionType):
        return ir1.FunctionType(
            argtypes=[type_to_ir1(arg) for arg in expr_type.argtypes],
            returns=type_to_ir1(expr_type.returns))
    elif isinstance(expr_type, ir2.CustomType):
        return ir1.CustomType(name=expr_type.name,
                              arg_types=[
                                  ir1.CustomTypeArgDecl(name=arg.name,
                                                        expr_type=type_to_ir1(
                                                            arg.expr_type))
                                  for arg in expr_type.arg_types
                              ])
    else:
        raise NotImplementedError('Unexpected type: %s' %
                                  str(expr_type.__class__))
Example #2
0
 def __init__(self, identifier_generator: Iterator[str]):
     self.identifier_generator = identifier_generator
     self.is_error_fun_ref = self.new_var(ir1.FunctionType(
         argtypes=[ir1.ErrorOrVoidType()], returns=ir1.BoolType()),
                                          is_global_function=True)
     self.function_defns = [self._create_is_error_fun_defn()]
     self.obfuscated_identifiers_by_identifier: Dict[
         str, str] = defaultdict(lambda: self.new_id())
Example #3
0
def try_except_stmt_to_ir1(try_except_stmt: ir2.TryExcept,
                           then_stmts: List[ir2.Stmt], writer: StmtWriter):
    # try:
    #   x = f()
    #   y = g()
    # except MyError as e:
    #   y = e.x
    #   if b:
    #     return 5
    # z = y + 3
    # return z
    #
    # Becomes:
    #
    # def then_fun(y):
    #   z = y + 3
    #   return z
    #
    # def except_fun(e, b):
    #   y = e.x
    #   if b:
    #     return 5
    #   x0, err0 = then_fun(y)
    #   b0 = is_error(err0)
    #   if b0:
    #     return None, err0
    #   return x0, None
    #
    # x, f_err = f()
    # f_b = is_error(f_err)
    # if f_b:
    #   b0 = is_instance_of_MyError(f_err)
    #   if b0:
    #     e = f_err  # type: MyError
    #     res, err = except_fun(...)
    #     return res, err
    #   return None, f_err
    # y, g_err = g()
    # g_b = is_error(g_err)
    # if g_b:
    #   b0 = is_instance_of_MyError(g_err)
    #   if b0:
    #     e = g_err  # type: MyError
    #     res, err = except_fun(...)
    #     return res, err
    #   return None, g_err
    # res, err = then_fun()
    # return res, err

    if then_stmts:
        then_stmts_writer = StmtWriter(writer.fun_writer,
                                       writer.current_fun_name,
                                       writer.current_fun_args,
                                       writer.current_fun_return_type,
                                       writer.try_except_contexts)
        stmts_to_ir1(then_stmts, then_stmts_writer)

        then_fun_forwarded_vars = get_unique_free_variables_in_stmts(
            then_stmts_writer.stmts)
        if not then_fun_forwarded_vars:
            then_fun_forwarded_vars = [
                _select_arbitrary_forwarded_arg(writer.current_fun_args)
            ]

        then_fun_defn = ir1.FunctionDefn(
            name=writer.new_id(),
            description=
            '(meta)function wrapping the code after a try-except statement from the function %s'
            % writer.current_fun_name,
            args=[
                ir1.FunctionArgDecl(expr_type=var.expr_type, name=var.name)
                for var in then_fun_forwarded_vars
            ],
            body=then_stmts_writer.stmts,
            return_type=writer.current_fun_return_type)
        writer.write_function(then_fun_defn)

        then_fun_ref = ir1.VarReference(expr_type=ir1.FunctionType(
            argtypes=[arg.expr_type for arg in then_fun_defn.args],
            returns=then_fun_defn.return_type),
                                        name=then_fun_defn.name,
                                        is_global_function=True,
                                        is_function_that_may_throw=True)
        then_fun_call_expr = ir1.FunctionCall(fun=then_fun_ref,
                                              args=then_fun_forwarded_vars)
    else:
        then_fun_call_expr = None

    except_stmts_writer = StmtWriter(writer.fun_writer,
                                     writer.current_fun_name,
                                     writer.current_fun_args,
                                     writer.current_fun_return_type,
                                     writer.try_except_contexts)
    stmts_to_ir1(try_except_stmt.except_body, except_stmts_writer)
    if then_fun_call_expr and not get_return_type(
            try_except_stmt.except_body).always_returns:
        except_stmts_writer.write_stmt(
            ir1.ReturnStmt(
                result=except_stmts_writer.
                new_var_for_expr_with_error_checking(then_fun_call_expr),
                error=None))

    except_fun_forwarded_vars = get_unique_free_variables_in_stmts(
        except_stmts_writer.stmts)
    if not except_fun_forwarded_vars:
        except_fun_forwarded_vars = [
            _select_arbitrary_forwarded_arg(writer.current_fun_args)
        ]

    except_fun_defn = ir1.FunctionDefn(
        name=writer.new_id(),
        description=
        '(meta)function wrapping the code in an except block from the function %s'
        % writer.current_fun_name,
        args=[
            ir1.FunctionArgDecl(expr_type=var.expr_type, name=var.name)
            for var in except_fun_forwarded_vars
        ],
        body=except_stmts_writer.stmts,
        return_type=writer.current_fun_return_type)
    writer.write_function(except_fun_defn)

    except_fun_ref = ir1.VarReference(expr_type=ir1.FunctionType(
        argtypes=[arg.expr_type for arg in except_fun_defn.args],
        returns=except_fun_defn.return_type),
                                      name=except_fun_defn.name,
                                      is_global_function=True,
                                      is_function_that_may_throw=True)
    except_fun_call_expr = ir1.FunctionCall(fun=except_fun_ref,
                                            args=except_fun_forwarded_vars)

    with writer.enter_try_except_context(
            TryExceptContext(
                type_to_ir1(try_except_stmt.caught_exception_type),
                try_except_stmt.caught_exception_name, except_fun_call_expr)):
        stmts_to_ir1(try_except_stmt.try_body, writer)

    if then_fun_call_expr and not get_return_type(
            try_except_stmt.try_body).always_returns:
        writer.write_stmt(
            ir1.ReturnStmt(result=writer.new_var_for_expr_with_error_checking(
                then_fun_call_expr),
                           error=None))
Example #4
0
def deconstructed_list_comprehension_expr_to_ir1(list_var: ir2.VarReference,
                                                 loop_var: ir1.VarReference,
                                                 result_elem_expr: ir1.Expr,
                                                 writer: StmtWriter):
    # [f(x, y) * 2
    #  for x in l]
    #
    # Becomes:
    #
    # def g(x, y):
    #   return f(x, y) * 2  # (in fact, this will be converted further)
    #
    # [g(x, y)
    #  for x in l]

    result_elem_type = type_to_ir1(result_elem_expr.expr_type)
    helper_fun_writer = StmtWriter(
        writer.fun_writer,
        current_fun_name=writer.current_fun_name,
        current_fun_args=writer.current_fun_args,
        current_fun_return_type=result_elem_type,
        # We can't forward the try_except_contexts here because the return type is different,
        # but it's ok because a list comprehension can't contain "raise" statements (while
        # of course it can throw indirectly).
        try_except_contexts=[])
    helper_fun_writer.write_stmt(
        ir1.ReturnStmt(result=expr_to_ir1(result_elem_expr, helper_fun_writer),
                       error=None))
    forwarded_vars = get_unique_free_variables_in_stmts(
        helper_fun_writer.stmts)
    if not forwarded_vars:
        if writer.current_fun_args:
            forwarded_vars = [
                _select_arbitrary_forwarded_arg(writer.current_fun_args)
            ]
        else:
            forwarded_vars = [
                writer.new_var_for_expr(expr=ir1.AtomicTypeLiteral('void'))
            ]

    helper_fun_name = writer.new_id()
    writer.write_function(
        ir1.FunctionDefn(
            name=helper_fun_name,
            description=
            '(meta)function wrapping the result expression in a list/set comprehension from the function %s'
            % writer.current_fun_name,
            args=[
                ir1.FunctionArgDecl(expr_type=var.expr_type, name=var.name)
                for var in forwarded_vars
            ],
            body=helper_fun_writer.stmts,
            return_type=result_elem_type))

    helper_fun_call = ir1.FunctionCall(fun=ir1.VarReference(
        name=helper_fun_name,
        expr_type=ir1.FunctionType(
            argtypes=[var.expr_type for var in forwarded_vars],
            returns=result_elem_type),
        is_global_function=True,
        is_function_that_may_throw=True),
                                       args=forwarded_vars)
    return writer.new_var_for_expr_with_error_checking(
        ir1.ListComprehensionExpr(list_var=list_var,
                                  loop_var=var_reference_to_ir1(
                                      loop_var, writer),
                                  result_elem_expr=helper_fun_call))
Example #5
0
def match_expr_to_ir1(match_expr: ir2.MatchExpr, writer: StmtWriter):
    matched_vars = [
        expr_to_ir1(expr, writer) for expr in match_expr.matched_exprs
    ]

    match_cases = []
    for match_case in match_expr.match_cases:
        match_case_writer = StmtWriter(writer.fun_writer,
                                       writer.current_fun_name,
                                       writer.current_fun_args,
                                       type_to_ir1(match_expr.expr_type),
                                       writer.try_except_contexts)
        match_case_var = expr_to_ir1(match_case.expr, match_case_writer)
        match_case_writer.write_stmt(
            ir1.ReturnStmt(result=match_case_var, error=None))

        forwarded_vars = get_unique_free_variables_in_stmts(
            match_case_writer.stmts)

        if not forwarded_vars:
            forwarded_vars = [
                _select_arbitrary_forwarded_arg(writer.current_fun_args)
            ]

        match_fun_name = writer.new_id()
        arg_decls = [
            ir1.FunctionArgDecl(expr_type=var.expr_type, name=var.name)
            for var in forwarded_vars
        ]
        writer.write_function(
            ir1.FunctionDefn(
                name=match_fun_name,
                description=
                '(meta)function wrapping the code in a branch of a match expression from the function %s'
                % writer.current_fun_name,
                args=arg_decls,
                body=match_case_writer.stmts,
                return_type=match_case_var.expr_type))
        match_fun_ref = ir1.VarReference(expr_type=ir1.FunctionType(
            argtypes=[var.expr_type for var in forwarded_vars],
            returns=match_case_var.expr_type),
                                         name=match_fun_name,
                                         is_global_function=True,
                                         is_function_that_may_throw=True)

        match_cases.append(
            ir1.MatchCase(
                type_patterns=[
                    type_pattern_expr_to_ir1(type_pattern, writer)
                    for type_pattern in match_case.type_patterns
                ],
                matched_var_names=[
                    writer.obfuscate_identifier(var_name)
                    for var_name in match_case.matched_var_names
                ],
                matched_variadic_var_names=[
                    writer.obfuscate_identifier(var_name)
                    for var_name in match_case.matched_variadic_var_names
                ],
                expr=ir1.FunctionCall(fun=match_fun_ref, args=forwarded_vars)))

    return writer.new_var_for_expr_with_error_checking(
        ir1.MatchExpr(matched_vars, match_cases))