stmt_inferrer.py 文件源码

python
阅读 19 收藏 0 点赞 0 评论 0

项目:Typpete 作者: caterinaurban 项目源码 文件源码
def _infer_func_def(node, context, solver):
    """Infer the type for a function definition"""
    if is_stub(node) or has_type_var(node, solver):
        return_annotation = node.returns
        args_annotations = []
        for arg in node.args.args:
            args_annotations.append(arg.annotation)
        defaults_count = len(node.args.defaults)
        if hasattr(node, "method_type"):  # check if the node contains the manually added method flag
            if node.method_type not in context.builtin_methods:
                context.builtin_methods[node.method_type] = {}
            context.builtin_methods[node.method_type][node.name] = AnnotatedFunction(args_annotations,
                                                                                     return_annotation,
                                                                                     defaults_count)
        else:
            context.set_type(node.name, AnnotatedFunction(args_annotations, return_annotation, defaults_count))
        return solver.z3_types.none

    func_context, args_types = _init_func_context(node, node.args.args, context, solver)
    result_type = context.get_type(node.name)
    result_type.args_count = len(node.args.args)
    context.set_type(node.name, result_type)
    context.add_func_ast(node.name, node)

    if hasattr(node.args, "defaults"):
        # Use the default args to infer the function parameters
        _infer_args_defaults(args_types, node.args.defaults, context, solver)
        defaults_len = len(node.args.defaults)
    else:
        defaults_len = 0

    if node.returns:
        return_type = solver.resolve_annotation(node.returns)
        if inference_config["ignore_fully_annotated_function"] and is_annotated(node)\
                or isinstance(node.body[0], ast.Expr) and isinstance(node.body[0].value, ast.Ellipsis):
            # Ignore the body if it has return annotation and one of the following conditions:
            # The configuration flag for doing so is set
            # The body begins with ellipsis
            body_type = return_type
        else:
            body_type = _infer_body(node.body, func_context, node.lineno, solver)
        solver.add(body_type == return_type,
                   fail_message="Return type annotation in line {}".format(node.lineno))
    else:
        body_type = _infer_body(node.body, func_context, node.lineno, solver)
        return_type = solver.new_z3_const("return")
        solver.add(solver.z3_types.subtype(body_type, return_type),
                   fail_message="Return type in line {}".format(node.lineno))
        # Putting higher weight for this soft constraint to give it higher priority over soft-constraint
        # added by inheritance covariance/contravariance return type
        solver.optimize.add_soft(body_type == return_type, weight=2)
    func_type = solver.z3_types.funcs[len(args_types)]((defaults_len,) + args_types + (return_type,))
    solver.add(result_type == func_type,
               fail_message="Function definition in line {}".format(node.lineno))
    return solver.z3_types.none
评论列表
文章目录


问题


面经


文章

微信
公众号

扫码关注公众号