def makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise, public_exc, source_ref): # This helper executes the core re-formulation of "no_raise" blocks, which # are the "else" blocks of "try"/"except" statements. In order to limit the # execution, we use an indicator variable instead, which will signal that # the tried block executed up to the end. And then we make the else block be # a conditional statement checking that. assert no_raise is not None tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator") statements = mergeStatements((StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable.makeReference(provider), source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=no_raise.getSourceReference().atInternal()), handling), allow_none=True) handling = StatementsSequence(statements=statements, source_ref=source_ref) tried = (StatementTryExcept(tried=tried, handling=handling, public_exc=public_exc, source_ref=source_ref), StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_handler_indicator_variable.makeReference( provider), source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=no_raise, no_branch=None, source_ref=source_ref)) final = StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable.makeReference(provider), source_ref=source_ref.atInternal()), tolerant=False, source_ref=source_ref.atInternal()), return StatementsSequence(statements=(StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable.makeReference(provider), source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref.atInternal()), makeTryFinallyStatement( tried=tried, final=final, source_ref=source_ref)), source_ref=source_ref)
def makeTryFinallyExpression(expression, tried, final, source_ref): if type(tried) in (tuple, list): tried = StatementsSequence(statements=tried, source_ref=source_ref) if type(final) in (tuple, list): final = StatementsSequence(statements=final, source_ref=source_ref) if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) return ExpressionTryFinally(expression=expression, tried=tried, final=final, source_ref=source_ref)
def makeTryFinallyStatement(tried, final, source_ref): if type(tried) in (tuple, list): tried = StatementsSequence(statements=tried, source_ref=source_ref) if type(final) in (tuple, list): final = StatementsSequence(statements=final, source_ref=source_ref) if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) return StatementTryFinally(tried=tried, final=final, public_exc=False, source_ref=source_ref)
def makeReraiseExceptionStatement(source_ref): # TODO: Remove the statement sequence packaging and have users do it themselves # in factory functions instead. return StatementsSequence( statements=(StatementReraiseException(source_ref=source_ref), ), source_ref=source_ref)
def buildTryNode(provider, node, source_ref): # Note: This variant is used for Python3.3 or higher only, older stuff uses # the above ones, this one merges try/except with try/finally in the # "ast". We split it up again, as it's logically separated of course. # Shortcut missing try/finally. if not node.handlers: return _buildTryFinallyNode(provider, node, source_ref) if not node.finalbody: return buildTryExceptionNode( provider = provider, node = node, source_ref = source_ref ) return buildTryFinallyNode( provider = provider, build_tried = lambda : StatementsSequence( statements = mergeStatements( ( buildTryExceptionNode( provider = provider, node = node, source_ref = source_ref ), ) ), source_ref = source_ref ), node = node, source_ref = source_ref )
def makeStatementsSequenceFromStatement(statement): return StatementsSequence( statements = mergeStatements( (statement,) ), source_ref = statement.getSourceReference() )
def buildAssertNode(provider, node, source_ref): # Build assert statements. These are re-formulated as described in the # developer manual too. They end up as conditional statement with raises of # AssertionError exceptions. # Underlying assumption: # # Assert x, y is the same as: # if not x: # raise AssertionError, y # Therefore assert statements are really just conditional statements with a # static raise contained. # # Starting with CPython2.7, it is, which means the creation of the exception # object is no more delayed: # if not x: # raise AssertionError( y ) if Utils.python_version < 270 or node.msg is None: raise_statement = StatementRaiseException( exception_type = ExpressionBuiltinExceptionRef( exception_name = "AssertionError", source_ref = source_ref ), exception_value = buildNode( provider, node.msg, source_ref, True ), exception_trace = None, exception_cause = None, source_ref = source_ref ) else: raise_statement = StatementRaiseException( exception_type = ExpressionBuiltinMakeException( exception_name = "AssertionError", args = ( buildNode( provider, node.msg, source_ref, True ), ), source_ref = source_ref ), exception_value = None, exception_trace = None, exception_cause = None, source_ref = source_ref ) return StatementConditional( condition = ExpressionOperationNOT( operand = buildNode( provider, node.test, source_ref ), source_ref = source_ref ), yes_branch = StatementsSequence( statements = ( raise_statement, ), source_ref = source_ref ), no_branch = None, source_ref = source_ref )
def makeStatementsSequenceFromStatements(*statements): assert statements assert None not in statements return StatementsSequence( statements = statements, source_ref = statements[0].getSourceReference() )
def makeStatementsSequenceFromStatements(*statements): assert statements assert None not in statements statements = mergeStatements(statements, allow_none=False) return StatementsSequence(statements=statements, source_ref=statements[0].getSourceReference())
def makeReraiseExceptionStatement(source_ref): return StatementsSequence(statements=(StatementRaiseException( exception_type=None, exception_value=None, exception_trace=None, exception_cause=None, source_ref=source_ref), ), source_ref=source_ref)
def makeStatementsSequence(statements, allow_none, source_ref): if allow_none: statements = tuple(statement for statement in statements if statement is not None) if statements: return StatementsSequence(statements=statements, source_ref=source_ref) else: return None
def buildStatementsNode(provider, nodes, source_ref, frame = False): # We are not creating empty statement sequences. if nodes is None: return None # Build as list of statements, throw away empty ones, and remove useless # nesting. statements = buildNodeList(provider, nodes, source_ref, allow_none = True) statements = mergeStatements(statements) # We are not creating empty statement sequences. Might be empty, because # e.g. a global node generates not really a statement, or pass statements. if not statements: return None # In case of a frame is desired, build it instead. if frame: if provider.isExpressionFunctionBody(): parameters = provider.getParameters() arg_names = parameters.getCoArgNames() kw_only_count = parameters.getKwOnlyParameterCount() code_name = provider.getFunctionName() guard_mode = "generator" if provider.isGenerator() else "full" has_starlist = parameters.getStarListArgumentName() is not None has_stardict = parameters.getStarDictArgumentName() is not None if provider.isGenerator(): statements.insert( 0, StatementGeneratorEntry( source_ref = source_ref ) ) return StatementsFrame( statements = statements, guard_mode = guard_mode, var_names = arg_names, arg_count = len(arg_names), kw_only_count = kw_only_count, code_name = code_name, has_starlist = has_starlist, has_stardict = has_stardict, source_ref = source_ref ) else: return makeModuleFrame( module = provider, statements = statements, source_ref = source_ref ) else: return StatementsSequence( statements = statements, source_ref = source_ref )
def makeReraiseExceptionStatement(source_ref): return StatementsSequence( statements = ( StatementReraiseException( source_ref = source_ref ), ), source_ref = source_ref )
def makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise, source_ref): # This helper executes the core re-formulation of "no_raise" blocks, which # are the "else" blocks of "try"/"except" statements. In order to limit the # execution, we use an indicator variable instead, which will signal that # the tried block executed up to the end. And then we make the else block be # a conditional statement checking that. # Indicator variable, will end up with C bool type, and need not be released. tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator", temp_type="bool") statements = mergeStatements( ( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=no_raise.getSourceReference(), ), handling, ), allow_none=True, ) handling = StatementsSequence(statements=statements, source_ref=source_ref) return makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_handler_indicator_variable, source_ref=source_ref), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=no_raise, no_branch=None, source_ref=source_ref, ), )
def makeTryExceptNoRaise(provider, temp_scope, tried, handlers, no_raise, source_ref): # This helper executes the core re-formulation of "no_raise" blocks, which # are the "else" blocks of "try"/"except" statements. In order to limit the # execution, we use an indicator variable instead, which will signal that # the tried block executed up to the end. And then we make the else block be # a conditional statement checking that. # This is a separate function, so it can be re-used in other # re-formulations, e.g. with statements. assert no_raise is not None assert len(handlers) > 0 tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator") for handler in handlers: statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable.makeReference( provider), source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=no_raise.getSourceReference().atInternal()), handler.getExceptionBranch()) handler.setExceptionBranch( makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref)) statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable.makeReference(provider), source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), StatementTryExcept(tried=tried, handlers=handlers, source_ref=source_ref), StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_handler_indicator_variable. makeReference(provider), source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=no_raise, no_branch=None, source_ref=source_ref)) return StatementsSequence(statements=statements, source_ref=source_ref)
def makeStatementsSequenceOrStatement(statements, source_ref): """ Make a statement sequence, but only if more than one statement Useful for when we can unroll constructs already here, but are not sure if we actually did that. This avoids the branch or the pollution of doing it always. """ if len(statements) > 1: return StatementsSequence(statements=statements, source_ref=source_ref) else: return statements[0]
def makeTryExceptSingleHandlerNode(tried, exception_name, handler_body, public_exc, source_ref): if public_exc: statements = [ StatementPreserveFrameException( source_ref = source_ref.atInternal() ), StatementPublishException( source_ref = source_ref.atInternal() ) ] else: statements = [] statements.append( StatementConditional( condition = ExpressionComparisonExceptionMatch( left = ExpressionCaughtExceptionTypeRef( source_ref = source_ref ), right = ExpressionBuiltinExceptionRef( exception_name = exception_name, source_ref = source_ref ), source_ref = source_ref ), yes_branch = handler_body, no_branch = makeReraiseExceptionStatement( source_ref = source_ref ), source_ref = source_ref ) ) if Utils.python_version >= 300 and public_exc: statements = [ makeTryFinallyStatement( tried = statements, final = StatementRestoreFrameException( source_ref = source_ref.atInternal() ), source_ref = source_ref.atInternal() ) ] return StatementTryExcept( tried = tried, handling = StatementsSequence( statements = statements, source_ref = source_ref ), public_exc = public_exc, source_ref = source_ref )
def buildAssertNode(provider, node, source_ref): # Build assert statements. These are re-formulated as described in the # developer manual too. They end up as conditional statement with raises of # AssertionError exceptions. # Underlying assumption: # # Assert x, y is the same as: # if not x: # raise AssertionError, y # Therefore assert statements are really just conditional statements with a # static raise contained. # exception_value = buildNode(provider, node.msg, source_ref, True) if "no_asserts" in getPythonFlags(): return None if exception_value is not None and python_version > 272: exception_value = ExpressionMakeTuple( elements = (exception_value,), source_ref = source_ref ) raise_statement = StatementRaiseException( exception_type = ExpressionBuiltinExceptionRef( exception_name = "AssertionError", source_ref = source_ref ), exception_value = exception_value, exception_trace = None, exception_cause = None, source_ref = source_ref ) return StatementConditional( condition = ExpressionOperationNOT( operand = buildNode(provider, node.test, source_ref), source_ref = source_ref ), yes_branch = StatementsSequence( statements = ( raise_statement, ), source_ref = source_ref ), no_branch = None, source_ref = source_ref )
def buildAssignNode(provider, node, source_ref): assert len(node.targets) >= 1, source_ref # Evaluate the right hand side first, so it can get names provided # before the left hand side exists. source = buildNode(provider, node.value, source_ref) if len(node.targets) == 1: # Simple assignment case, one source, one target. return buildAssignmentStatements(provider=provider, node=node.targets[0], source=source, source_ref=source_ref) else: # Complex assignment case, one source, but multiple targets. We keep the # source in a temporary variable, and then assign from it multiple # times. temp_scope = provider.allocateTempScope("assign_unpack") tmp_source = provider.allocateTempVariable(temp_scope=temp_scope, name="assign_source") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_source.makeReference(provider), source_ref=source_ref), source=source, source_ref=source_ref) ] for target in node.targets: statements.append( buildAssignmentStatements( provider=provider, node=target, source=ExpressionTempVariableRef( variable=tmp_source.makeReference(provider), source_ref=source_ref), source_ref=source_ref)) statements.append( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_source.makeReference(provider), source_ref=source_ref), tolerant=False, source_ref=source_ref)) return StatementsSequence(statements=statements, source_ref=source_ref)
def buildTryNode(provider, node, source_ref): # Note: This variant is used for Python3.3 or higher only, older stuff uses the above # ones, this one merges try/except with try/finally in the "ast". We split it up # again, as it's logically separated of course. return StatementTryFinally(tried=StatementsSequence( statements=(buildTryExceptionNode(provider=provider, node=node, source_ref=source_ref), ), source_ref=source_ref), final=buildStatementsNode( provider=provider, nodes=node.finalbody, source_ref=source_ref), source_ref=source_ref)
def buildStatementsNode(provider, nodes, source_ref): # We are not creating empty statement sequences. if nodes is None: return None # Build as list of statements, throw away empty ones, and remove useless # nesting. statements = buildNodeList(provider, nodes, source_ref, allow_none=True) statements = mergeStatements(statements) # We are not creating empty statement sequences. Might be empty, because # e.g. a global node generates not really a statement, or pass statements. if not statements: return None else: return StatementsSequence(statements=statements, source_ref=source_ref)
def buildStatementsNode(provider, nodes, source_ref, code_object=None): # We are not creating empty statement sequences. if nodes is None: return None # Build as list of statements, throw away empty ones, and remove useless # nesting. statements = buildNodeList(provider, nodes, source_ref, allow_none=True) statements = mergeStatements(statements) # We are not creating empty statement sequences. Might be empty, because # e.g. a global node generates not really a statement, or pass statements. if not statements: return None # In case of a frame is desired, build it instead. if code_object: if provider.isExpressionGeneratorObjectBody(): # TODO: Could do this earlier and on the outside. statements.insert(0, StatementGeneratorEntry(source_ref=source_ref)) result = StatementsFrame(statements=statements, guard_mode="generator", code_object=code_object, source_ref=source_ref) elif provider.isExpressionCoroutineObjectBody(): # TODO: That might be wrong result = StatementsFrame(statements=statements, guard_mode="generator", code_object=code_object, source_ref=source_ref) elif provider.isExpressionFunctionBody() or \ provider.isExpressionClassBody(): result = StatementsFrame(statements=statements, guard_mode="full", code_object=code_object, source_ref=source_ref) else: result = makeModuleFrame(module=provider, statements=statements, source_ref=source_ref) else: result = StatementsSequence(statements=statements, source_ref=source_ref) return result
def buildAssignNode(provider, node, source_ref): assert len(node.targets) >= 1, source_ref # Evaluate the right hand side first, so it can get names provided # before the left hand side exists. source = buildNode(provider, node.value, source_ref) if len(node.targets) == 1: # Simple assignment case, one source, one target. return buildAssignmentStatements(provider=provider, node=node.targets[0], source=source, source_ref=source_ref) else: # Complex assignment case, one source, but multiple targets. We keep the source in # a temporary variable, and then assign from it multiple times. result = StatementTempBlock(source_ref=source_ref) tmp_source = result.getTempVariable("assign_source") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_source.makeReference(result), source_ref=source_ref), source=source, source_ref=source_ref) ] for target in node.targets: statements.append( buildAssignmentStatements( provider=provider, node=target, source=ExpressionTempVariableRef( variable=tmp_source.makeReference(result), source_ref=source_ref), source_ref=source_ref)) result.setBody( StatementsSequence(statements=statements, source_ref=source_ref)) return result
def buildStatementsNode(provider, nodes, source_ref, frame=False): # We are not creating empty statement sequences. if nodes is None: return None # Build as list of statements, throw away empty ones, and remove useless nesting. statements = buildNodeList(provider, nodes, source_ref, allow_none=True) statements = mergeStatements(statements) # We are not creating empty statement sequences. Might be empty, because e.g. a global # node generates not really a statement, or pass statements. if not statements: return None # In case of a frame is desired, build it instead. if frame: if provider.isExpressionFunctionBody(): arg_names = provider.getParameters().getCoArgNames() kw_only_count = provider.getParameters().getKwOnlyParameterCount() code_name = provider.getFunctionName() guard_mode = "generator" if provider.isGenerator() else "full" else: assert provider.isPythonModule() arg_names = () kw_only_count = 0 code_name = "<module>" if provider.isMainModule( ) else provider.getName() guard_mode = "once" return StatementsFrame(statements=statements, guard_mode=guard_mode, arg_names=arg_names, kw_only_count=kw_only_count, code_name=code_name, source_ref=source_ref) else: return StatementsSequence(statements=statements, source_ref=source_ref)
def _buildWithNode(provider, context_expr, assign_target, body, source_ref): with_source = buildNode(provider, context_expr, source_ref) temp_scope = provider.allocateTempScope("with") tmp_source_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="source") tmp_exit_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="exit") tmp_enter_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="enter") tmp_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="indicator") statements = (buildAssignmentStatements(provider=provider, node=assign_target, allow_none=True, source=ExpressionTempVariableRef( variable=tmp_enter_variable, source_ref=source_ref), source_ref=source_ref), body) with_body = makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref) if Options.isFullCompat() and with_body is not None: with_exit_source_ref = with_body.getStatements()[-1].\ getSourceReference() else: with_exit_source_ref = source_ref # The "__enter__" and "__exit__" were normal attribute lookups under # CPython2.6, but that changed with CPython2.7. if Utils.python_version < 270: attribute_lookup_class = ExpressionAttributeLookup else: attribute_lookup_class = ExpressionSpecialAttributeLookup statements = [ # First assign the with context to a temporary variable. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_source_variable, source_ref=source_ref), source=with_source, source_ref=source_ref), # Next, assign "__enter__" and "__exit__" attributes to temporary # variables. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_exit_variable, source_ref=source_ref), source=attribute_lookup_class(source=ExpressionTempVariableRef( variable=tmp_source_variable, source_ref=source_ref), attribute_name="__exit__", source_ref=source_ref), source_ref=source_ref), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_enter_variable, source_ref=source_ref), source=ExpressionCallEmpty(called=attribute_lookup_class( source=ExpressionTempVariableRef(variable=tmp_source_variable, source_ref=source_ref), attribute_name="__enter__", source_ref=source_ref), source_ref=source_ref), source_ref=source_ref), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), ] source_ref = source_ref.atInternal() statements += [ makeTryFinallyStatement( tried=makeTryExceptSingleHandlerNode( tried=with_body, exception_name="BaseException", handler_body=StatementsSequence( statements=( # Prevents final block from calling __exit__ as # well. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref), source=ExpressionConstantRef( constant=False, source_ref=source_ref), source_ref=source_ref), StatementConditional( condition=ExpressionCallNoKeywords( called=ExpressionTempVariableRef( variable=tmp_exit_variable, source_ref=source_ref), args=ExpressionMakeTuple( elements=( ExpressionCaughtExceptionTypeRef( source_ref=source_ref), ExpressionCaughtExceptionValueRef( source_ref=source_ref), ExpressionCaughtExceptionTracebackRef( source_ref=source_ref), ), source_ref=source_ref), source_ref=source_ref), no_branch=makeStatementsSequenceFromStatement( statement=StatementRaiseException( exception_type=None, exception_value=None, exception_trace=None, exception_cause=None, source_ref=source_ref)), yes_branch=None, source_ref=source_ref), ), source_ref=source_ref), public_exc=Utils.python_version >= 270, source_ref=source_ref), final=StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=StatementExpressionOnly( expression=ExpressionCallNoKeywords( called=ExpressionTempVariableRef( variable=tmp_exit_variable, source_ref=source_ref), args=ExpressionConstantRef(constant=(None, None, None), source_ref=source_ref), source_ref=with_exit_source_ref), source_ref=source_ref)), no_branch=None, source_ref=source_ref), source_ref=source_ref) ] return makeTryFinallyStatement( tried=statements, final=( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_source_variable, source_ref=source_ref), tolerant=True, source_ref=source_ref), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_enter_variable, source_ref=source_ref), tolerant=True, source_ref=source_ref), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_exit_variable, source_ref=source_ref), tolerant=True, source_ref=source_ref), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref), tolerant=True, source_ref=source_ref), ), source_ref=source_ref)
def _buildContractionBodyNode(provider, node, emit_class, start_value, container_tmp, outer_iter_ref, temp_scope, assign_provider, source_ref, function_body): if start_value is not None: statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp.makeReference(function_body), source_ref=source_ref), source=start_value, source_ref=source_ref.atInternal()) ] if assign_provider: tmp_variables = [] else: tmp_variables = [container_tmp] else: statements = [] tmp_variables = [] if hasattr(node, "elt"): if start_value is not None: current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp.makeReference(function_body), source_ref=source_ref), buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref) else: assert emit_class is ExpressionYield function_body.markAsGenerator() current_body = emit_class(buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref) else: assert emit_class is ExpressionDictOperationSet current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp.makeReference(function_body), source_ref=source_ref), key=buildNode( provider=function_body, node=node.key, source_ref=source_ref, ), value=buildNode( provider=function_body, node=node.value, source_ref=source_ref, ), source_ref=source_ref) current_body = StatementExpressionOnly(expression=current_body, source_ref=source_ref) for count, qual in enumerate(reversed(node.generators)): tmp_value_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="iter_value_%d" % count) tmp_variables.append(tmp_value_variable) # The first iterated value is to be calculated outside of the function # and will be given as a parameter "_iterated", the others are built # inside the function. if qual is node.generators[0]: def makeIteratorRef(): return outer_iter_ref.makeCloneAt(source_ref) tmp_iter_variable = None nested_statements = [] else: # First create the iterator and store it, next should be loop body value_iterator = ExpressionBuiltinIter1(value=buildNode( provider=function_body, node=qual.iter, source_ref=source_ref), source_ref=source_ref) tmp_iter_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="contraction_iter_%d" % count) tmp_variables.append(tmp_iter_variable) nested_statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference( function_body), source_ref=source_ref), source=value_iterator, source_ref=source_ref) ] def makeIteratorRef(): return ExpressionTempVariableRef( variable=tmp_iter_variable.makeReference(function_body), source_ref=source_ref) loop_statements = [ makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference( function_body), source_ref=source_ref), source=ExpressionBuiltinNext1(value=makeIteratorRef(), source_ref=source_ref), source_ref=source_ref)), exception_name="StopIteration", handler_body=makeStatementsSequenceFromStatement( statement=StatementBreakLoop( source_ref=source_ref.atInternal())), public_exc=False, source_ref=source_ref), buildAssignmentStatements( provider=provider if assign_provider else function_body, temp_provider=function_body, node=qual.target, source=ExpressionTempVariableRef( variable=tmp_value_variable.makeReference(function_body), source_ref=source_ref), source_ref=source_ref) ] conditions = buildNodeList(provider=function_body, nodes=qual.ifs, source_ref=source_ref) if len(conditions) == 1: loop_statements.append( StatementConditional( condition=conditions[0], yes_branch=makeStatementsSequenceFromStatement( statement=current_body), no_branch=None, source_ref=source_ref)) elif len(conditions) > 1: loop_statements.append( StatementConditional( condition=buildAndNode(provider=function_body, values=conditions, source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=current_body), no_branch=None, source_ref=source_ref)) else: loop_statements.append(current_body) nested_statements.append( StatementLoop(body=StatementsSequence( statements=mergeStatements(loop_statements), source_ref=source_ref), source_ref=source_ref)) if tmp_iter_variable is not None: nested_statements.append( StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference( function_body), source_ref=source_ref), tolerant=False, source_ref=source_ref)) current_body = StatementsSequence(statements=nested_statements, source_ref=source_ref) statements.append(current_body) statements = mergeStatements(statements) if emit_class is ExpressionYield: statements.insert(0, StatementGeneratorEntry(source_ref=source_ref)) del_statements = [] for tmp_variable in tmp_variables: del_statements.append( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable.makeReference(function_body), source_ref=source_ref), tolerant=True, source_ref=source_ref.atInternal())) return statements, del_statements
def _buildWithNode(provider, context_expr, assign_target, body, body_lineno, sync, source_ref): # Many details, pylint: disable=too-many-locals with_source = buildNode(provider, context_expr, source_ref) if Options.isFullCompat(): source_ref = with_source.getCompatibleSourceReference() temp_scope = provider.allocateTempScope("with") tmp_source_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "source" ) tmp_exit_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "exit" ) tmp_enter_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "enter" ) tmp_indicator_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "indicator" ) statements = ( buildAssignmentStatements( provider = provider, node = assign_target, allow_none = True, source = ExpressionTempVariableRef( variable = tmp_enter_variable, source_ref = source_ref ), source_ref = source_ref ), body ) with_body = makeStatementsSequence( statements = statements, allow_none = True, source_ref = source_ref ) if Options.isFullCompat(): if body: deepest = body while deepest.getVisitableNodes(): deepest = deepest.getVisitableNodes()[-1] body_lineno = deepest.getCompatibleSourceReference().getLineNumber() with_exit_source_ref = source_ref.atLineNumber(body_lineno) else: with_exit_source_ref = source_ref # The "__enter__" and "__exit__" were normal attribute lookups under # CPython2.6, but that changed with CPython2.7. if python_version < 270: attribute_lookup_class = ExpressionAttributeLookup else: attribute_lookup_class = ExpressionAttributeLookupSpecial enter_value = ExpressionCallEmpty( called = attribute_lookup_class( source = ExpressionTempVariableRef( variable = tmp_source_variable, source_ref = source_ref ), attribute_name = "__enter__" if sync else "__aenter__", source_ref = source_ref ), source_ref = source_ref ) exit_value_exception = ExpressionCallNoKeywords( called = ExpressionTempVariableRef( variable = tmp_exit_variable, source_ref = with_exit_source_ref ), args = ExpressionMakeTuple( elements = ( ExpressionCaughtExceptionTypeRef( source_ref = with_exit_source_ref ), ExpressionCaughtExceptionValueRef( source_ref = with_exit_source_ref ), ExpressionCaughtExceptionTracebackRef( source_ref = source_ref ), ), source_ref = source_ref ), source_ref = with_exit_source_ref ) exit_value_no_exception = ExpressionCallNoKeywords( called = ExpressionTempVariableRef( variable = tmp_exit_variable, source_ref = source_ref ), args = makeConstantRefNode( constant = (None, None, None), source_ref = source_ref ), source_ref = with_exit_source_ref ) # For "async with", await the entered value and exit value must be awaited. if not sync: enter_value = ExpressionAsyncWait( expression = enter_value, source_ref = source_ref ) exit_value_exception = ExpressionAsyncWait( expression = exit_value_exception, source_ref = source_ref ) exit_value_no_exception = ExpressionAsyncWait( expression = exit_value_no_exception, source_ref = source_ref ) statements = [ # First assign the with context to a temporary variable. StatementAssignmentVariable( variable = tmp_source_variable, source = with_source, source_ref = source_ref ) ] attribute_assignments = [ # Next, assign "__enter__" and "__exit__" attributes to temporary # variables. StatementAssignmentVariable( variable = tmp_exit_variable, source = attribute_lookup_class( source = ExpressionTempVariableRef( variable = tmp_source_variable, source_ref = source_ref ), attribute_name = "__exit__" if sync else "__aexit__", source_ref = source_ref ), source_ref = source_ref ), StatementAssignmentVariable( variable = tmp_enter_variable, source = enter_value, source_ref = source_ref ) ] if python_version >= 360 and sync: attribute_assignments.reverse() statements += attribute_assignments statements.append( StatementAssignmentVariable( variable = tmp_indicator_variable, source = makeConstantRefNode( constant = True, source_ref = source_ref ), source_ref = source_ref ) ) statements += [ makeTryFinallyStatement( provider = provider, tried = makeTryExceptSingleHandlerNodeWithPublish( provider = provider, tried = with_body, exception_name = "BaseException", handler_body = StatementsSequence( statements = ( # Prevents final block from calling __exit__ as # well. StatementAssignmentVariable( variable = tmp_indicator_variable, source = makeConstantRefNode( constant = False, source_ref = source_ref ), source_ref = source_ref ), makeConditionalStatement( condition = exit_value_exception, no_branch = makeReraiseExceptionStatement( source_ref = with_exit_source_ref ), yes_branch = None, source_ref = with_exit_source_ref ), ), source_ref = source_ref ), public_exc = python_version >= 270, source_ref = source_ref ), final = StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = tmp_indicator_variable, source_ref = source_ref ), right = makeConstantRefNode( constant = True, source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementExpressionOnly( expression = exit_value_no_exception, source_ref = source_ref ) ), no_branch = None, source_ref = source_ref ), source_ref = source_ref ) ] return makeTryFinallyStatement( provider = provider, tried = statements, final = ( StatementReleaseVariable( variable = tmp_source_variable, source_ref = with_exit_source_ref ), StatementReleaseVariable( variable = tmp_enter_variable, source_ref = with_exit_source_ref ), StatementReleaseVariable( variable = tmp_exit_variable, source_ref = with_exit_source_ref ), StatementReleaseVariable( variable = tmp_indicator_variable, source_ref = with_exit_source_ref ), ), source_ref = source_ref )
def buildListContractionNode(provider, node, source_ref): # List contractions are dealt with by general code. if Utils.python_version < 300: temp_scope = provider.allocateTempScope("listcontr") outer_iter_var = provider.allocateTempVariable(temp_scope=temp_scope, name="listcontr_iter") outer_iter_ref = ExpressionTempVariableRef( variable=outer_iter_var.makeReference(provider), source_ref=source_ref) container_tmp = provider.allocateTempVariable(temp_scope=temp_scope, name="listcontr_result") statements, del_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=ExpressionListOperationAppend, start_value=ExpressionConstantRef(constant=[], source_ref=source_ref), outer_iter_ref=outer_iter_ref, container_tmp=container_tmp, temp_scope=temp_scope, assign_provider=True, source_ref=source_ref, function_body=provider) statements.insert( 0, StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=outer_iter_var.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinIter1(value=buildNode( provider=provider, node=node.generators[0].iter, source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)) result = makeTryFinallyExpression(expression=ExpressionTempVariableRef( variable=container_tmp.makeReference(provider), source_ref=source_ref), tried=statements, final=del_statements, source_ref=source_ref) final = StatementsSequence(statements=( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp.makeReference(provider), source_ref=source_ref), tolerant=True, source_ref=source_ref), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=outer_iter_var.makeReference(provider), source_ref=source_ref), tolerant=True, source_ref=source_ref), ), source_ref=source_ref) wrapTryFinallyLater(node=result, final=final) return result return _buildContractionNode( provider=provider, node=node, name="<listcontraction>", emit_class=ExpressionListOperationAppend, start_value=ExpressionConstantRef(constant=[], source_ref=source_ref), # Note: For Python3, the list contractions no longer assign to the outer # scope. assign_provider=Utils.python_version < 300, source_ref=source_ref)
def buildPrintNode(provider, node, source_ref): # "print" statements, should only occur with Python2. def wrapValue(value): if value.isExpressionConstantRef(): str_value = value.getStrValue() if str_value is not None: return str_value return ExpressionBuiltinStr(value=value, source_ref=value.getSourceReference()) if node.dest is not None: temp_scope = provider.allocateTempScope("print") tmp_target_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="target") target_default_statement = StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), source=ExpressionImportModuleHard(module_name="sys", import_name="stdout", source_ref=source_ref), source_ref=source_ref) statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), source=buildNode(provider=provider, node=node.dest, source_ref=source_ref), source_ref=source_ref), StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=target_default_statement), no_branch=None, source_ref=source_ref) ] values = buildNodeList(provider=provider, nodes=node.values, source_ref=source_ref) values = [wrapValue(value) for value in values] if node.dest is not None: print_statements = [ StatementPrintValue(dest=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), value=value, source_ref=source_ref) for value in values ] if node.nl: print_statements.append( StatementPrintNewline(dest=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), source_ref=source_ref)) statements.append( makeTryFinallyStatement( tried=print_statements, final=StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), tolerant=False, source_ref=source_ref), source_ref=source_ref)) else: statements = [ StatementPrintValue(dest=None, value=value, source_ref=source_ref) for value in values ] if node.nl: statements.append( StatementPrintNewline(dest=None, source_ref=source_ref)) return StatementsSequence(statements=statements, source_ref=source_ref)
def _buildContractionBodyNode( provider, node, emit_class, start_value, container_tmp, iter_tmp, temp_scope, assign_provider, function_body, for_asyncgen, source_ref, ): # This uses lots of variables and branches. There is no good way # around that, and we deal with many cases, due to having generator # expressions sharing this code, pylint: disable=too-many-branches,too-many-locals # Note: The assign_provider is only to cover Python2 list contractions, # assigning one of the loop variables to the outside scope. tmp_variables = [] if emit_class is not ExpressionYield: tmp_variables.append(iter_tmp) if container_tmp is not None: tmp_variables.append(container_tmp) statements = [] # First assign the iterator if we are an outline. if assign_provider: statements.append( StatementAssignmentVariable( variable=iter_tmp, source=_makeIteratorCreation( provider=provider, qual=node.generators[0], for_asyncgen=False, source_ref=source_ref, ), source_ref=source_ref.atInternal(), )) if for_asyncgen and python_version >= 370 and node.generators[0].is_async: statements.append( StatementAssignmentVariable( variable=iter_tmp, source=ExpressionTempVariableRef(variable=iter_tmp, source_ref=source_ref), source_ref=source_ref, )) if start_value is not None: statements.append( StatementAssignmentVariable( variable=container_tmp, source=makeConstantRefNode(constant=start_value, source_ref=source_ref), source_ref=source_ref.atInternal(), )) if hasattr(node, "elt"): if start_value is not None: current_body = emit_class( ExpressionTempVariableRef(variable=container_tmp, source_ref=source_ref), buildNode( provider=function_body if not assign_provider else provider, node=node.elt, source_ref=source_ref, ), source_ref=source_ref, ) else: assert emit_class is ExpressionYield current_body = emit_class( buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref, ) else: current_body = emit_class( dict_arg=ExpressionTempVariableRef(variable=container_tmp, source_ref=source_ref), key=buildNode( provider=function_body if not assign_provider else provider, node=node.key, source_ref=source_ref, ), value=buildNode( provider=function_body if not assign_provider else provider, node=node.value, source_ref=source_ref, ), source_ref=source_ref, ) if current_body.isExpression(): current_body = StatementExpressionOnly(expression=current_body, source_ref=source_ref) for count, qual in enumerate(reversed(node.generators)): tmp_value_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="iter_value_%d" % count) tmp_variables.append(tmp_value_variable) # The first iterated value is to be calculated outside of the function # and will be given as a parameter "_iterated", the others are built # inside the function. if qual is node.generators[0]: iterator_ref = makeVariableRefNode(variable=iter_tmp, source_ref=source_ref) if for_asyncgen and python_version >= 370: iterator_ref = ExpressionYieldFromWaitable( expression=iterator_ref, source_ref=source_ref) tmp_iter_variable = None nested_statements = [] else: # First create the iterator and store it, next should be loop body value_iterator = _makeIteratorCreation( provider=provider if assign_provider else function_body, qual=qual, for_asyncgen=False, source_ref=source_ref, ) tmp_iter_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="contraction_iter_%d" % count) tmp_variables.append(tmp_iter_variable) nested_statements = [ StatementAssignmentVariable( variable=tmp_iter_variable, source=value_iterator, source_ref=source_ref, ) ] iterator_ref = ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref) loop_statements = [ makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_value_variable, source=_makeIteratorNext(iterator_ref=iterator_ref, qual=qual, source_ref=source_ref), source_ref=source_ref, ), exception_name=_getStopIterationName(qual), handler_body=StatementLoopBreak(source_ref=source_ref), source_ref=source_ref, ), buildAssignmentStatements( provider=provider if assign_provider else function_body, temp_provider=function_body, node=qual.target, source=ExpressionTempVariableRef(variable=tmp_value_variable, source_ref=source_ref), source_ref=source_ref, ), ] conditions = buildNodeList( provider=provider if assign_provider else function_body, nodes=qual.ifs, source_ref=source_ref, ) if len(conditions) >= 1: loop_statements.append( makeStatementConditional( condition=buildAndNode(values=conditions, source_ref=source_ref), yes_branch=current_body, no_branch=None, source_ref=source_ref, )) else: loop_statements.append(current_body) nested_statements.append( StatementLoop( body=StatementsSequence( statements=mergeStatements(loop_statements), source_ref=source_ref), source_ref=source_ref, )) if tmp_iter_variable is not None: nested_statements.append( StatementReleaseVariable(variable=tmp_iter_variable, source_ref=source_ref)) current_body = StatementsSequence(statements=mergeStatements( nested_statements, False), source_ref=source_ref) statements.append(current_body) statements = mergeStatements(statements) release_statements = [ StatementReleaseVariable(variable=tmp_variable, source_ref=source_ref) for tmp_variable in tmp_variables ] return statements, release_statements