示例#1
0
def buildFunctionNode(provider, node, source_ref):
    # Functions have way too many details, pylint: disable=R0912,R0914

    assert getKind(node) == "FunctionDef"

    function_statement_nodes, function_doc = extractDocFromBody(node)

    function_kind, flags, _written_variables, _non_local_declarations, _global_declarations = \
      detectFunctionBodyKind(
        nodes = function_statement_nodes
    )

    outer_body, function_body, code_object = buildFunctionWithParsing(
        provider=provider,
        function_kind=function_kind,
        name=node.name,
        function_doc=function_doc,
        flags=flags,
        node=node,
        source_ref=source_ref)

    if function_kind == "Function":
        code_body = function_body
    elif function_kind == "Generator":
        code_body = ExpressionGeneratorObjectBody(provider=function_body,
                                                  name=node.name,
                                                  flags=flags,
                                                  source_ref=source_ref)

        for variable in function_body.getVariables():
            code_body.getVariableForReference(variable.getName())
    else:
        assert False, function_kind

    if function_kind == "Generator":
        function_body.setBody(
            makeStatementsSequenceFromStatement(statement=StatementReturn(
                expression=ExpressionMakeGeneratorObject(
                    generator_ref=ExpressionFunctionRef(
                        function_body=code_body, source_ref=source_ref),
                    code_object=code_object,
                    source_ref=source_ref),
                source_ref=source_ref)))

    decorators = buildNodeList(provider=provider,
                               nodes=reversed(node.decorator_list),
                               source_ref=source_ref)

    defaults = buildNodeList(provider=provider,
                             nodes=node.args.defaults,
                             source_ref=source_ref)

    kw_defaults = buildParameterKwDefaults(provider=provider,
                                           node=node,
                                           function_body=function_body,
                                           source_ref=source_ref)

    function_statements_body = buildFrameNode(provider=code_body,
                                              nodes=function_statement_nodes,
                                              code_object=code_object,
                                              source_ref=source_ref)

    if function_kind == "Function":
        # TODO: Generators might have to raise GeneratorExit instead.
        function_statements_body = _insertFinalReturnStatement(
            function_statements_body=function_statements_body,
            return_class=StatementReturn,
            source_ref=source_ref)

    if function_statements_body.isStatementsFrame():
        function_statements_body = makeStatementsSequenceFromStatement(
            statement=function_statements_body)

    code_body.setBody(function_statements_body)

    annotations = buildParameterAnnotations(provider, node, source_ref)

    function_creation = ExpressionFunctionCreation(
        function_ref=ExpressionFunctionRef(function_body=outer_body,
                                           source_ref=source_ref),
        code_object=code_object,
        defaults=defaults,
        kw_defaults=kw_defaults,
        annotations=annotations,
        source_ref=source_ref)

    # Add the "staticmethod" decorator to __new__ methods if not provided.

    # CPython made these optional, but secretly applies them when it does
    # "class __new__".  We add them earlier, so our optimization will see it.
    if node.name == "__new__" and \
       provider.isExpressionClassBody():

        for decorator in decorators:
            if decorator.isExpressionVariableRef() and \
               decorator.getVariableName() == "staticmethod":
                break
        else:
            decorators.append(
                ExpressionBuiltinRef(builtin_name="staticmethod",
                                     source_ref=source_ref))

    if python_version >= 360 and \
       node.name == "__init_subclass__" and \
       provider.isExpressionClassBody():

        for decorator in decorators:
            if decorator.isExpressionVariableRef() and \
               decorator.getVariableName() == "classmethod":
                break
        else:
            decorators.append(
                ExpressionBuiltinRef(builtin_name="classmethod",
                                     source_ref=source_ref))

    decorated_function = function_creation
    for decorator in decorators:
        decorated_function = ExpressionCallNoKeywords(
            called=decorator,
            args=ExpressionMakeTuple(elements=(decorated_function, ),
                                     source_ref=source_ref),
            source_ref=decorator.getSourceReference())

    result = StatementAssignmentVariable(
        variable_ref=ExpressionTargetVariableRef(variable_name=mangleName(
            node.name, provider),
                                                 source_ref=source_ref),
        source=decorated_function,
        source_ref=source_ref)

    if python_version >= 340:
        function_body.qualname_setup = result.getTargetVariableRef()

    return result
示例#2
0
def buildLambdaNode(provider, node, source_ref):
    # Many details to deal with, pylint: disable=R0914

    assert getKind(node) == "Lambda"

    function_kind, flags, _written_variables, _non_local_declarations, _global_declarations = \
      detectFunctionBodyKind(
        nodes = (node.body,)
    )

    outer_body, function_body, code_object = buildFunctionWithParsing(
        provider=provider,
        function_kind=function_kind,
        name="<lambda>",
        function_doc=None,
        flags=flags,
        node=node,
        source_ref=source_ref)

    if function_kind == "Function":
        code_body = function_body
    else:
        code_body = ExpressionGeneratorObjectBody(provider=function_body,
                                                  name="<lambda>",
                                                  flags=set(),
                                                  source_ref=source_ref)

    if function_kind == "Generator":
        function_body.setBody(
            makeStatementsSequenceFromStatement(statement=StatementReturn(
                expression=ExpressionMakeGeneratorObject(
                    generator_ref=ExpressionFunctionRef(
                        function_body=code_body, source_ref=source_ref),
                    code_object=code_object,
                    source_ref=source_ref),
                source_ref=source_ref)))

    defaults = buildNodeList(provider, node.args.defaults, source_ref)
    kw_defaults = buildParameterKwDefaults(provider=provider,
                                           node=node,
                                           function_body=function_body,
                                           source_ref=source_ref)

    body = buildNode(
        provider=code_body,
        node=node.body,
        source_ref=source_ref,
    )

    if function_kind == "Generator":
        if python_version < 270:
            tmp_return_value = code_body.allocateTempVariable(
                temp_scope=None, name="yield_return")

            statements = (StatementAssignmentVariable(
                variable_ref=ExpressionTargetTempVariableRef(
                    variable=tmp_return_value,
                    source_ref=source_ref,
                ),
                source=body,
                source_ref=source_ref),
                          StatementConditional(
                              condition=ExpressionComparisonIsNOT(
                                  left=ExpressionTempVariableRef(
                                      variable=tmp_return_value,
                                      source_ref=source_ref,
                                  ),
                                  right=ExpressionConstantRef(
                                      constant=None, source_ref=source_ref),
                                  source_ref=source_ref),
                              yes_branch=makeStatementsSequenceFromStatement(
                                  statement=StatementExpressionOnly(
                                      expression=ExpressionYield(
                                          expression=ExpressionTempVariableRef(
                                              variable=tmp_return_value,
                                              source_ref=source_ref,
                                          ),
                                          source_ref=source_ref),
                                      source_ref=source_ref)),
                              no_branch=None,
                              source_ref=source_ref))
            body = makeTryFinallyStatement(provider=provider,
                                           tried=statements,
                                           final=StatementReleaseVariable(
                                               variable=tmp_return_value,
                                               source_ref=source_ref),
                                           source_ref=source_ref)
        else:
            body = StatementExpressionOnly(expression=body,
                                           source_ref=source_ref)
    else:
        body = StatementReturn(expression=body, source_ref=source_ref)

    body = StatementsFrame(
        statements=mergeStatements((body, )),
        code_object=code_object,
        guard_mode="generator" if function_kind == "Generator" else "full",
        source_ref=body.getSourceReference())

    body = makeStatementsSequenceFromStatement(statement=body, )

    code_body.setBody(body)

    annotations = buildParameterAnnotations(provider, node, source_ref)

    return ExpressionFunctionCreation(function_ref=ExpressionFunctionRef(
        function_body=outer_body, source_ref=source_ref),
                                      code_object=code_object,
                                      defaults=defaults,
                                      kw_defaults=kw_defaults,
                                      annotations=annotations,
                                      source_ref=source_ref)
def buildGeneratorExpressionNode(provider, node, source_ref):
    # Generator expressions are dealt with by general code.

    assert getKind(node) == "GeneratorExp"

    function_body = ExpressionOutlineBody(provider=provider,
                                          name="genexpr",
                                          source_ref=source_ref)

    iter_tmp = function_body.allocateTempVariable(temp_scope=None, name=".0")

    parent_module = provider.getParentModule()

    code_object = CodeObjectSpec(
        co_name="<genexpr>",
        co_kind="Generator",
        co_varnames=(".0", ),
        co_argcount=1,
        co_kwonlyargcount=0,
        co_has_starlist=False,
        co_has_stardict=False,
        co_filename=parent_module.getRunTimeFilename(),
        co_lineno=source_ref.getLineNumber(),
        future_spec=parent_module.getFutureSpec())

    code_body = ExpressionGeneratorObjectBody(provider=provider,
                                              name="<genexpr>",
                                              flags=set(),
                                              source_ref=source_ref)

    function_body.setBody(
        makeStatementsSequenceFromStatements(
            StatementAssignmentVariable(variable=iter_tmp,
                                        source=ExpressionBuiltinIter1(
                                            value=buildNode(
                                                provider=provider,
                                                node=node.generators[0].iter,
                                                source_ref=source_ref),
                                            source_ref=source_ref),
                                        source_ref=source_ref),
            makeTryFinallyStatement(
                provider=function_body,
                tried=StatementReturn(expression=ExpressionMakeGeneratorObject(
                    generator_ref=ExpressionFunctionRef(
                        function_body=code_body, source_ref=source_ref),
                    code_object=code_object,
                    source_ref=source_ref),
                                      source_ref=source_ref),
                final=StatementReleaseVariable(variable=iter_tmp,
                                               source_ref=source_ref),
                source_ref=source_ref)))

    statements, release_statements = _buildContractionBodyNode(
        function_body=code_body,
        provider=provider,
        node=node,
        emit_class=ExpressionYield,
        iter_tmp=iter_tmp,
        temp_scope=None,
        start_value=None,
        container_tmp=None,
        assign_provider=False,
        source_ref=source_ref,
    )

    statements = (makeTryFinallyStatement(
        provider=function_body,
        tried=statements,
        final=release_statements,
        source_ref=source_ref.atInternal()), )

    code_body.setBody(
        makeStatementsSequenceFromStatement(statement=StatementsFrameGenerator(
            statements=mergeStatements(statements, False),
            code_object=code_object,
            source_ref=source_ref)))

    return function_body
示例#4
0
def _buildContractionNode(provider, node, name, emit_class, start_value,
                          source_ref):
    # The contraction nodes are reformulated to function bodies, with loops as
    # described in the developer manual. They use a lot of temporary names,
    # nested blocks, etc. and so a lot of variable names.

    # TODO: No function ought to be necessary.
    function_body = ExpressionFunctionBody(provider=provider,
                                           name=name,
                                           doc=None,
                                           parameters=ParameterSpec(
                                               ps_name=name,
                                               ps_normal_args=(".0", ),
                                               ps_list_star_arg=None,
                                               ps_dict_star_arg=None,
                                               ps_default_count=0,
                                               ps_kw_only_args=()),
                                           flags=set(),
                                           source_ref=source_ref)

    iter_tmp = function_body.getVariableForAssignment(variable_name=".0")
    assert iter_tmp.isParameterVariable()

    code_object = CodeObjectSpec(
        co_name=name,
        co_kind="Generator" if emit_class is ExpressionYield else "Function",
        co_varnames=function_body.getParameters().getParameterNames(),
        co_argcount=len(function_body.getParameters().getParameterNames()),
        co_kwonlyargcount=0,
        co_has_starlist=False,
        co_has_stardict=False,
    )

    if emit_class is ExpressionYield:
        code_body = ExpressionGeneratorObjectBody(provider=function_body,
                                                  name="<genexpr>",
                                                  flags=set(),
                                                  source_ref=source_ref)

        iter_tmp = code_body.getVariableForReference(variable_name=".0")
        assert iter_tmp.isLocalVariable()

        function_body.setBody(
            makeStatementsSequenceFromStatement(statement=StatementReturn(
                expression=ExpressionMakeGeneratorObject(
                    generator_ref=ExpressionFunctionRef(
                        function_body=code_body, source_ref=source_ref),
                    code_object=code_object,
                    source_ref=source_ref),
                source_ref=source_ref)))
    else:
        code_body = function_body

    if start_value is not None:
        container_tmp = code_body.allocateTempVariable(
            temp_scope=None, name="contraction_result")
    else:
        container_tmp = None

    statements, release_statements = _buildContractionBodyNode(
        function_body=code_body,
        provider=provider,
        node=node,
        emit_class=emit_class,
        iter_tmp=iter_tmp,
        temp_scope=None,
        start_value=start_value,
        container_tmp=container_tmp,
        assign_provider=False,
        source_ref=source_ref,
    )

    if start_value is not None:
        statements.append(
            StatementReturn(expression=ExpressionTempVariableRef(
                variable=container_tmp, source_ref=source_ref),
                            source_ref=source_ref))

    statements = (makeTryFinallyStatement(
        provider=function_body,
        tried=statements,
        final=release_statements,
        source_ref=source_ref.atInternal()), )

    if emit_class is ExpressionYield:
        guard_mode = "generator"
    else:
        guard_mode = "full"

    code_body.setBody(
        makeStatementsSequenceFromStatement(statement=StatementsFrame(
            statements=mergeStatements(statements, False),
            guard_mode=guard_mode,
            code_object=code_object,
            source_ref=source_ref)))

    return ExpressionFunctionCall(function=ExpressionFunctionCreation(
        function_ref=ExpressionFunctionRef(function_body=function_body,
                                           source_ref=source_ref),
        code_object=code_object,
        defaults=(),
        kw_defaults=None,
        annotations=None,
        source_ref=source_ref),
                                  values=(ExpressionBuiltinIter1(
                                      value=buildNode(
                                          provider=provider,
                                          node=node.generators[0].iter,
                                          source_ref=source_ref),
                                      source_ref=source_ref), ),
                                  source_ref=source_ref)
示例#5
0
def buildLambdaNode(provider, node, source_ref):
    # Many details to deal with, pylint: disable=too-many-locals

    assert getKind(node) == "Lambda"

    function_kind, flags = detectFunctionBodyKind(nodes=(node.body,))

    outer_body, function_body, code_object = buildFunctionWithParsing(
        provider=provider,
        function_kind=function_kind,
        name="<lambda>",
        function_doc=None,
        flags=flags,
        node=node,
        source_ref=source_ref,
    )

    if function_kind == "Function":
        code_body = function_body
    else:
        code_body = ExpressionGeneratorObjectBody(
            provider=function_body,
            name="<lambda>",
            code_object=code_object,
            flags=None,
            auto_release=None,
            source_ref=source_ref,
        )
        code_body.qualname_provider = provider

    if function_kind == "Generator":
        function_body.setChild(
            "body",
            makeStatementsSequenceFromStatement(
                statement=StatementReturn(
                    expression=ExpressionMakeGeneratorObject(
                        generator_ref=ExpressionFunctionRef(
                            function_body=code_body, source_ref=source_ref
                        ),
                        source_ref=source_ref,
                    ),
                    source_ref=source_ref,
                )
            ),
        )

    defaults = buildNodeList(provider, node.args.defaults, source_ref)
    kw_defaults = buildParameterKwDefaults(
        provider=provider, node=node, function_body=function_body, source_ref=source_ref
    )

    body = buildNode(provider=code_body, node=node.body, source_ref=source_ref)

    if function_kind == "Generator":
        if python_version < 0x270:
            tmp_return_value = code_body.allocateTempVariable(
                temp_scope=None, name="yield_return"
            )

            statements = (
                StatementAssignmentVariable(
                    variable=tmp_return_value, source=body, source_ref=source_ref
                ),
                makeStatementConditional(
                    condition=ExpressionComparisonIsNot(
                        left=ExpressionTempVariableRef(
                            variable=tmp_return_value, source_ref=source_ref
                        ),
                        right=ExpressionConstantNoneRef(source_ref=source_ref),
                        source_ref=source_ref,
                    ),
                    yes_branch=StatementExpressionOnly(
                        expression=ExpressionYield(
                            expression=ExpressionTempVariableRef(
                                variable=tmp_return_value, source_ref=source_ref
                            ),
                            source_ref=source_ref,
                        ),
                        source_ref=source_ref,
                    ),
                    no_branch=None,
                    source_ref=source_ref,
                ),
            )
            body = makeTryFinallyStatement(
                provider=provider,
                tried=statements,
                final=StatementReleaseVariable(
                    variable=tmp_return_value, source_ref=source_ref
                ),
                source_ref=source_ref,
            )
        else:
            body = StatementExpressionOnly(expression=body, source_ref=source_ref)
    else:
        body = StatementReturn(expression=body, source_ref=source_ref)

    if function_kind == "Generator":
        frame_class = StatementsFrameGenerator
    else:
        frame_class = StatementsFrameFunction

    body = frame_class(
        statements=mergeStatements((body,)),
        code_object=code_object,
        source_ref=body.getSourceReference(),
    )

    body = makeStatementsSequenceFromStatement(statement=body)

    code_body.setChild("body", body)

    annotations = buildParameterAnnotations(provider, node, source_ref)

    return ExpressionFunctionCreation(
        function_ref=ExpressionFunctionRef(
            function_body=outer_body, source_ref=source_ref
        ),
        defaults=defaults,
        kw_defaults=kw_defaults,
        annotations=annotations,
        source_ref=source_ref,
    )