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.makeReference(provider), 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.makeReference(provider), 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.makeReference(provider), source_ref = source_ref ), source = attribute_lookup_class( expression = ExpressionTempVariableRef( variable = tmp_source_variable.makeReference(provider), source_ref = source_ref ), attribute_name = "__exit__", source_ref = source_ref ), source_ref = source_ref ), StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_enter_variable.makeReference( provider ), source_ref = source_ref ), source = ExpressionCallEmpty( called = attribute_lookup_class( expression = ExpressionTempVariableRef( variable = tmp_source_variable.makeReference( provider ), 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.makeReference(provider), 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.\ makeReference(provider), 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.\ makeReference(provider), 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.makeReference( provider ), 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.\ makeReference(provider), 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.makeReference(provider), source_ref = source_ref ), tolerant = True, source_ref = source_ref ), StatementDelVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_enter_variable.makeReference(provider), source_ref = source_ref ), tolerant = True, source_ref = source_ref ), StatementDelVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_exit_variable.makeReference(provider), source_ref = source_ref ), tolerant = True, source_ref = source_ref ), StatementDelVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_indicator_variable.makeReference(provider), source_ref = source_ref ), tolerant = True, source_ref = source_ref ), ), source_ref = source_ref )
def buildWhileLoopNode(provider, node, source_ref): # The while loop is re-formulated according to developer manual. The # condition becomes an early condition to break the loop. The else block is # taken if a while loop exits normally, i.e. because of condition not being # true. We do this by introducing an indicator variable. else_block = buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref) if else_block is not None: temp_scope = provider.allocateTempScope("while_loop") tmp_break_indicator = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator") statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), StatementBreakLoop(source_ref=source_ref)) else: statements = (StatementBreakLoop(source_ref=source_ref), ) pushBuildContext("loop_body") pushIndicatorVariable(None) loop_statements = buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref) popIndicatorVariable() popBuildContext() # The loop body contains a conditional statement at the start that breaks # the loop if it fails. loop_body = makeStatementsSequence(statements=(StatementConditional( condition=buildNode(provider, node.test, source_ref), no_branch=StatementsSequence(statements=statements, source_ref=source_ref), yes_branch=None, source_ref=source_ref), loop_statements), allow_none=True, source_ref=source_ref) loop_statement = StatementLoop(body=loop_body, source_ref=source_ref) if else_block is None: return loop_statement else: statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref), loop_statement, StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=else_block, no_branch=None, source_ref=source_ref)) statements = (makeTryFinallyStatement(tried=statements, final=StatementReleaseVariable( variable=tmp_break_indicator, tolerant=False, source_ref=source_ref), source_ref=source_ref), ) return StatementsSequence(statements=statements, source_ref=source_ref)
def _buildInplaceAssignAttributeNode(lookup_source, attribute_name, tmp_variable1, tmp_variable2, operator, expression, source_ref): # First assign the target value to a temporary variable. preserve_to_tmp = StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef(variable=tmp_variable1, source_ref=source_ref), source=ExpressionAttributeLookup( source=lookup_source.makeCloneAt(source_ref), attribute_name=attribute_name, source_ref=source_ref), source_ref=source_ref) # Second assign the in-place result to a temporary variable inplace_to_tmp = StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef(variable=tmp_variable2, source_ref=source_ref), source=ExpressionOperationBinaryInplace(operator=operator, left=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref), right=expression, source_ref=source_ref), source_ref=source_ref) # Third, copy it over, if the reference values change, i.e. IsNot is true. copy_back_from_tmp = StatementConditional( condition=ExpressionComparisonIsNOT( left=ExpressionTempVariableRef(variable=tmp_variable1, source_ref=source_ref), right=ExpressionTempVariableRef(variable=tmp_variable2, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=StatementAssignmentAttribute( expression=lookup_source.makeCloneAt(source_ref), attribute_name=attribute_name, source=ExpressionTempVariableRef(variable=tmp_variable2, source_ref=source_ref), source_ref=source_ref)), no_branch=None, source_ref=source_ref) copy_back_from_tmp = makeTryFinallyStatement( tried=copy_back_from_tmp, final=StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable2, source_ref=source_ref), tolerant=False, source_ref=source_ref), source_ref=source_ref) return ( preserve_to_tmp, # making sure the above temporary variable is deleted in any case. makeTryFinallyStatement( tried=( inplace_to_tmp, copy_back_from_tmp, ), final=StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable1, source_ref=source_ref), tolerant=False, source_ref=source_ref), source_ref=source_ref))
def _buildForLoopNode(provider, node, sync, source_ref): # The for loop is re-formulated according to developer manual. An iterator # is created, and looped until it gives StopIteration. The else block is # taken if a for loop exits normally, i.e. because of iterator # exhaustion. We do this by introducing an indicator variable. # We handle async and sync both here, leading to cases, pylint: disable=R0914 source = buildNode(provider, node.iter, source_ref) # Temporary variables, we need one for the iterator, and one for the current # value. temp_scope = provider.allocateTempScope("for_loop") tmp_iter_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="for_iterator") tmp_value_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="iter_value") else_block = buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref) if else_block is not None: tmp_break_indicator = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref), source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref) ] else: statements = [] statements.append(StatementLoopBreak(source_ref=source_ref)) handler_body = makeStatementsSequence(statements=statements, allow_none=False, source_ref=source_ref) if sync: next_node = ExpressionBuiltinNext1(value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref), source_ref=source_ref) else: next_node = ExpressionAsyncNext(value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref), source_ref=source_ref) statements = (makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable, source_ref=source_ref), source=next_node, source_ref=source_ref), exception_name="StopIteration" if sync else "StopAsyncIteration", handler_body=handler_body, source_ref=source_ref), buildAssignmentStatements(provider=provider, node=node.target, source=ExpressionTempVariableRef( variable=tmp_value_variable, source_ref=source_ref), source_ref=source_ref)) pushBuildContext("loop_body") statements += (buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref), ) popBuildContext() loop_body = makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref) cleanup_statements = [ StatementReleaseVariable(variable=tmp_value_variable, source_ref=source_ref), StatementReleaseVariable(variable=tmp_iter_variable, source_ref=source_ref) ] if else_block is not None: statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator, source_ref=source_ref), source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref) ] else: statements = [] if sync: iter_source = ExpressionBuiltinIter1( value=source, source_ref=source.getSourceReference()) else: iter_source = ExpressionAsyncIter( value=source, source_ref=source.getSourceReference()) statements += [ # First create the iterator and store it. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref), source=iter_source, source_ref=source_ref), makeTryFinallyStatement(provider=provider, tried=StatementLoop(body=loop_body, source_ref=source_ref), final=StatementsSequence( statements=cleanup_statements, source_ref=source_ref), source_ref=source_ref) ] if else_block is not None: statements += [ StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef(variable=tmp_break_indicator, source_ref=source_ref), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=else_block, no_branch=None, source_ref=source_ref) ] statements = (makeTryFinallyStatement(provider=provider, tried=statements, final=StatementReleaseVariable( variable=tmp_break_indicator, source_ref=source_ref), source_ref=source_ref), ) return makeStatementsSequenceFromStatements(*statements)
def buildExecNode(provider, node, source_ref): # "exec" statements, should only occur with Python2. # This is using many variables, due to the many details this is # dealing with. The locals and globals need to be dealt with in # temporary variables, and we need handling of indicators, so # that is just the complexity, pylint: disable=R0914 exec_globals = node.globals exec_locals = node.locals body = node.body orig_globals = exec_globals # Handle exec(a,b,c) to be same as exec a, b, c if exec_locals is None and exec_globals is None and \ getKind(body) == "Tuple": parts = body.elts body = parts[0] if len(parts) > 1: exec_globals = parts[1] if len(parts) > 2: exec_locals = parts[2] else: return StatementRaiseException( exception_type = ExpressionBuiltinExceptionRef( exception_name = "TypeError", source_ref = source_ref ), exception_value = makeConstantRefNode( constant = """\ exec: arg 1 must be a string, file, or code object""", source_ref = source_ref ), exception_trace = None, exception_cause = None, source_ref = source_ref ) if not provider.isCompiledPythonModule(): provider.markAsExecContaining() if orig_globals is None: provider.markAsUnqualifiedExecContaining(source_ref) temp_scope = provider.allocateTempScope("exec") locals_value = buildNode(provider, exec_locals, source_ref, True) if locals_value is None: locals_value = ExpressionConstantNoneRef( source_ref = source_ref ) globals_value = buildNode(provider, exec_globals, source_ref, True) if globals_value is None: globals_value = ExpressionConstantNoneRef( source_ref = source_ref ) source_code = buildNode(provider, body, source_ref) source_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "exec_source" ) globals_keeper_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "globals" ) locals_keeper_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "locals" ) plain_indicator_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "plain" ) tried = ( # First evaluate the source code expressions. StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = source_variable, source_ref = source_ref ), source = source_code, source_ref = source_ref ), # Assign globals and locals temporary the values given, then fix it # up, taking note in the "plain" temporary variable, if it was an # "exec" statement with None arguments, in which case the copy back # will be necessary. StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), source = globals_value, source_ref = source_ref ), StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), source = locals_value, source_ref = source_ref ), StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = plain_indicator_variable, source_ref = source_ref ), source = makeConstantRefNode( constant = False, source_ref = source_ref ), source_ref = source_ref ), StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), source = ExpressionBuiltinGlobals( source_ref = source_ref ), source_ref = source_ref, ), StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), source = _getLocalsClassNode(provider)( source_ref = source_ref ), source_ref = source_ref, ), StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = plain_indicator_variable, source_ref = source_ref ), source = makeConstantRefNode( constant = True, source_ref = source_ref ), source_ref = source_ref, ) ), no_branch = None, source_ref = source_ref ), ), no_branch = makeStatementsSequenceFromStatements( StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), source = ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), source_ref = source_ref, ) ), no_branch = None, source_ref = source_ref ) ), source_ref = source_ref ), # Source needs some special treatment for not done for "eval", if it's a # file object, then must be read. StatementConditional( condition = ExpressionBuiltinIsinstance( instance = ExpressionTempVariableRef( variable = source_variable, source_ref = source_ref ), classes = ExpressionBuiltinAnonymousRef( builtin_name = "file", source_ref = source_ref, ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = source_variable, source_ref = source_ref ), source = ExpressionCallEmpty( called = ExpressionAttributeLookup( source = ExpressionTempVariableRef( variable = source_variable, source_ref = source_ref ), attribute_name = "read", source_ref = source_ref ), source_ref = source_ref ), source_ref = source_ref ) ), no_branch = None, source_ref = source_ref ), makeTryFinallyStatement( provider = provider, tried = StatementExec( source_code = ExpressionTempVariableRef( variable = source_variable, source_ref = source_ref ), globals_arg = ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), locals_arg = ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), source_ref = source_ref ), final = StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = plain_indicator_variable, source_ref = source_ref ), right = makeConstantRefNode( constant = True, source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementLocalsDictSync( locals_arg = ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref, ), source_ref = source_ref.atInternal() ) ), no_branch = None, source_ref = source_ref ), source_ref = source_ref ) ) final = ( StatementReleaseVariable( variable = source_variable, source_ref = source_ref ), StatementReleaseVariable( variable = globals_keeper_variable, source_ref = source_ref ), StatementReleaseVariable( variable = locals_keeper_variable, source_ref = source_ref ), StatementReleaseVariable( variable = plain_indicator_variable, source_ref = source_ref ), ) return makeTryFinallyStatement( provider = provider, tried = tried, final = final, source_ref = source_ref )
def wrapEvalGlobalsAndLocals(provider, globals_node, locals_node, temp_scope, source_ref): """ Wrap the locals and globals arguments for "eval". This is called from the outside, and when the node tree already exists. """ globals_keeper_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "globals" ) locals_keeper_variable = provider.allocateTempVariable( temp_scope = temp_scope, name = "locals" ) if locals_node is None: locals_node = ExpressionConstantNoneRef( source_ref = source_ref ) if globals_node is None: globals_node = ExpressionConstantNoneRef( source_ref = source_ref ) post_statements = [] if provider.isExpressionClassBody(): post_statements.append( StatementLocalsDictSync( locals_arg = ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref, ), source_ref = source_ref.atInternal() ) ) post_statements += [ StatementReleaseVariable( variable = globals_keeper_variable, source_ref = source_ref ), StatementReleaseVariable( variable = locals_keeper_variable, source_ref = source_ref ) ] # The locals default is dependent on exec_mode, globals or locals. locals_default = ExpressionConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), expression_no = ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), expression_yes = _getLocalsClassNode(provider)( source_ref = source_ref ), source_ref = source_ref ) pre_statements = [ # First assign globals and locals temporary the values given. StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), source = globals_node, source_ref = source_ref, ), StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), source = locals_node, source_ref = source_ref, ), StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref ), source = locals_default, source_ref = source_ref, ) ), no_branch = None, source_ref = source_ref ), StatementConditional( condition = ExpressionComparisonIs( left = ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref ), source = ExpressionBuiltinGlobals( source_ref = source_ref ), source_ref = source_ref, ) ), no_branch = None, source_ref = source_ref ) ] return ( ExpressionTempVariableRef( variable = globals_keeper_variable, source_ref = source_ref if globals_node is None else globals_node.getSourceReference() ), ExpressionTempVariableRef( variable = locals_keeper_variable, source_ref = source_ref if locals_node is None else locals_node.getSourceReference() ), makeStatementsSequence(pre_statements, False, source_ref), makeStatementsSequence(post_statements, False, source_ref) )
def buildLambdaNode(provider, node, source_ref): # Many details to deal with 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>", 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=ExpressionConstantNoneRef( 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 _buildContractionBodyNode(provider, node, emit_class, start_value, container_tmp, outer_iter_ref, temp_scope, assign_provider, source_ref, function_body): # 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=R0912,R0914,R0915 if start_value is not None: statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp, 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, 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, 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]: iterator_ref = 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, source_ref=source_ref), source=value_iterator, source_ref=source_ref) ] iterator_ref = ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref) loop_statements = [ makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable, source_ref=source_ref), source=ExpressionBuiltinNext1(value=iterator_ref, 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, 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, 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, source_ref=source_ref), tolerant=True, source_ref=source_ref.atInternal())) return statements, del_statements
def buildPrintNode(provider, node, source_ref): # "print" statements, should only occur with Python2. 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) 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(provider=provider, tried=print_statements, final=StatementReleaseVariable( variable=tmp_target_variable, 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 makeStatementsSequenceFromStatements(*statements)
def buildForLoopNode(provider, node, source_ref): # The for loop is re-formulated according to developer manual. An iterator # is created, and looped until it gives StopIteration. The else block is # taken if a for loop exits normally, i.e. because of iterator # exhaustion. We do this by introducing an indicator variable. source = buildNode(provider, node.iter, source_ref) temp_scope = provider.allocateTempScope("for_loop") tmp_iter_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="for_iterator") tmp_value_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="iter_value") else_block = buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref) if else_block is not None: tmp_break_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator_variable.makeReference( provider), source_ref=source_ref), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref) ] else: statements = [] statements.append(StatementBreakLoop(source_ref=source_ref.atInternal())) handler_body = makeStatementsSequence(statements=statements, allow_none=False, source_ref=source_ref) statements = (makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinNext1(value=ExpressionTempVariableRef( variable=tmp_iter_variable.makeReference(provider), source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)), exception_name="StopIteration", handler_body=handler_body, source_ref=source_ref), buildAssignmentStatements( provider=provider, node=node.target, source=ExpressionTempVariableRef( variable=tmp_value_variable.makeReference(provider), source_ref=source_ref), source_ref=source_ref)) statements += (buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref), ) loop_body = makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref) if else_block is not None: statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator_variable.makeReference( provider), source_ref=source_ref), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref) ] else: statements = [] cleanup_statements = ( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference(provider), source_ref=source_ref), tolerant=True, source_ref=source_ref.atInternal()), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference(provider), source_ref=source_ref), tolerant=False, source_ref=source_ref.atInternal())) statements += [ # First create the iterator and store it. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinIter1( value=source, source_ref=source.getSourceReference()), source_ref=source_ref), StatementTryFinally(tried=makeStatementsSequenceFromStatement( statement=StatementLoop(body=loop_body, source_ref=source_ref)), final=StatementsSequence( statements=cleanup_statements, source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal()) ] if else_block is not None: statements += [ StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_break_indicator_variable.makeReference( provider), source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=else_block, no_branch=None, source_ref=source_ref) ] return StatementsSequence(statements=statements, source_ref=source_ref)
def makeTryExceptNoRaise( 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. 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 result = StatementTempBlock( source_ref = source_ref ) tmp_handler_indicator_variable = result.getTempVariable( "unhandled_indicator" ) for handler in handlers: handler.setExceptionBranch( makeStatementsSequence( statements = ( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_handler_indicator_variable.makeReference( result ), source_ref = source_ref.atInternal() ), source = ExpressionConstantRef( constant = False, source_ref = source_ref ), source_ref = no_raise.getSourceReference().atInternal() ), handler.getExceptionBranch() ), allow_none = True, source_ref = source_ref ) ) result.setBody( StatementsSequence( statements = ( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_handler_indicator_variable.makeReference( result ), 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( result ), 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 ) ), source_ref = source_ref ) ) return result
def buildTryExceptionNode(provider, node, source_ref): # Try/except nodes. Re-formulated as described in the developer # manual. Exception handlers made the assignment to variables explicit. Same # for the "del" as done for Python3. Also catches always work a tuple of # exception types and hides away that they may be built or not. # Many variables and branches, due to the re-formulation that is going on # here, which just has the complexity, pylint: disable=R0912,R0914 tried = buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref) handlers = [] for handler in node.handlers: exception_expression, exception_assign, exception_block = ( handler.type, handler.name, handler.body) if exception_assign is None: statements = [ buildStatementsNode(provider=provider, nodes=exception_block, source_ref=source_ref) ] elif python_version < 300: statements = [ buildAssignmentStatements( provider=provider, node=exception_assign, source=ExpressionCaughtExceptionValueRef( source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal()), buildStatementsNode(provider=provider, nodes=exception_block, source_ref=source_ref) ] else: # Python3 requires temporary assignment of exception assignment. target_info = decodeAssignTarget( provider=provider, node=exception_assign, source_ref=source_ref, ) kind, detail = target_info assert kind == "Name", kind kind = "Name_Exception" statements = [ buildAssignmentStatements( provider=provider, node=exception_assign, source=ExpressionCaughtExceptionValueRef( source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal()), makeTryFinallyStatement(provider=provider, tried=buildStatementsNode( provider=provider, nodes=exception_block, source_ref=source_ref), final=buildDeleteStatementFromDecoded( kind=kind, detail=detail, source_ref=source_ref), source_ref=source_ref) ] handler_body = makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref) exception_types = buildNode(provider=provider, node=exception_expression, source_ref=source_ref, allow_none=True) # The exception types should be a tuple, so as to be most general. if exception_types is None: if handler is not node.handlers[-1]: SyntaxErrors.raiseSyntaxError( reason="default 'except:' must be last", source_ref=source_ref.atLineNumber( handler.lineno - 1 if Options.isFullCompat() else handler.lineno)) handlers.append(( exception_types, handler_body, )) # Re-raise by default exception_handling = makeReraiseExceptionStatement(source_ref=source_ref) for exception_type, handler in reversed(handlers): if exception_type is None: # A default handler was given, so use that indeed. exception_handling = handler else: exception_handling = StatementsSequence( statements=(StatementConditional( condition=ExpressionComparisonExceptionMatch( left=ExpressionCaughtExceptionTypeRef( source_ref=exception_type.source_ref), right=exception_type, source_ref=exception_type.source_ref), yes_branch=handler, no_branch=exception_handling, source_ref=exception_type.source_ref), ), source_ref=exception_type.source_ref) if exception_handling is None: # For Python3, we need not publish at all, if all we do is to revert # that immediately. For Python2, the publish may release previously # published exception, which has side effects potentially. if python_version < 300: exception_handling = StatementsSequence( statements=( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal()), StatementPublishException( source_ref=source_ref.atInternal()), ), source_ref=source_ref.atInternal()) else: if python_version < 300: exception_handling.setStatements(( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal()), StatementPublishException(source_ref=source_ref.atInternal()), ) + exception_handling.getStatements()) else: preserver_id = provider.allocatePreserverId() exception_handling = makeStatementsSequenceFromStatements( StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), StatementPublishException(source_ref=source_ref.atInternal()), makeTryFinallyStatement( provider=provider, tried=exception_handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), source_ref=source_ref), ) no_raise = buildStatementsNode(provider=provider, nodes=node.orelse, source_ref=source_ref) if no_raise is None: if tried is None: return None return StatementTry(tried=tried, except_handler=exception_handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref) else: if tried is None: return no_raise return makeTryExceptNoRaise( provider=provider, temp_scope=provider.allocateTempScope("try_except"), handling=exception_handling, tried=tried, no_raise=no_raise, source_ref=source_ref)
def _buildContractionBodyNode(provider, node, emit_class, start_value, container_tmp, iter_tmp, temp_scope, assign_provider, function_body, 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 assign_provider: tmp_variables.append(iter_tmp) if container_tmp is not None: tmp_variables.append(container_tmp) # First assign the iterator if we are an outline. if assign_provider: statements = [ 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.atInternal()) ] else: statements = [] if start_value is not None: statements.append( StatementAssignmentVariable(variable=container_tmp, source=start_value, 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, 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: assert emit_class is StatementDictOperationSet current_body = StatementDictOperationSet( dict_arg=ExpressionTempVariableRef(variable=container_tmp, 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) 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) 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=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=ExpressionBuiltinNext1(value=iterator_ref, source_ref=source_ref), source_ref=source_ref), exception_name="StopIteration", handler_body=StatementLoopBreak( source_ref=source_ref.atInternal()), 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=function_body, nodes=qual.ifs, source_ref=source_ref) if len(conditions) >= 1: loop_statements.append( StatementConditional( condition=buildAndNode(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( 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
def buildTryFinallyNode(provider, build_tried, node, source_ref): if Utils.python_version < 300: # Prevent "continue" statements in the final blocks pushBuildContext("finally") final = buildStatementsNode(provider=provider, nodes=node.finalbody, source_ref=source_ref) popBuildContext() return StatementTryFinally( tried=build_tried(), final=final, public_exc=Utils.python_version >= 300, # TODO: Use below code source_ref=source_ref) else: temp_scope = provider.allocateTempScope("try_finally") tmp_indicator_var = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator") pushIndicatorVariable(tmp_indicator_var) statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_var, source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref.atInternal()), build_tried(), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_var, source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref.atInternal())) # Prevent "continue" statements in the final blocks pushBuildContext("finally") final = buildStatementsNode(provider=provider, nodes=node.finalbody, source_ref=source_ref) popBuildContext() popIndicatorVariable() tried = StatementsSequence(statements=mergeStatements(statements, allow_none=True), source_ref=source_ref) prelude = StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_indicator_var, source_ref=source_ref.atInternal()), right=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref), yes_branch=StatementsSequence( statements=(StatementPreserveFrameException( source_ref=source_ref.atInternal()), StatementPublishException( source_ref=source_ref.atInternal())), source_ref=source_ref.atInternal()), no_branch=None, source_ref=source_ref.atInternal()) postlude = (StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_indicator_var, source_ref=source_ref.atInternal()), right=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref), yes_branch=StatementsSequence(statements=( StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_var, source_ref=source_ref.atInternal()), tolerant=False, source_ref=source_ref.atInternal()), StatementReraiseFrameException( source_ref=source_ref.atInternal()), ), source_ref=source_ref.atInternal()), no_branch=StatementsSequence(statements=(StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_indicator_var, source_ref=source_ref.atInternal()), tolerant=False, source_ref=source_ref.atInternal()), ), source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal()), ) final = StatementsSequence(statements=mergeStatements(( prelude, makeTryFinallyStatement(tried=final, final=postlude, source_ref=source_ref.atInternal()), )), source_ref=source_ref.atInternal()) return StatementTryFinally(tried=tried, final=final, public_exc=True, source_ref=source_ref)
def _buildContractionNode(provider, node, name, emit_class, start_value, assign_provider, 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. There is no good way around that, and we deal with many # cases, due to having generator expressions sharing this code, # pylint: disable=R0912,R0914 # Note: The assign_provider is only to cover Python2 list contractions, assigning one # of the loop variables to the outside scope. assert provider.isParentVariableProvider(), provider function_body = ExpressionFunctionBody( provider=provider, name=name, doc=None, parameters=make_contraction_parameters, source_ref=source_ref) temp_block = StatementTempBlock(source_ref=source_ref) if start_value is not None: container_tmp = temp_block.getTempVariable("result") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp.makeReference(temp_block), source_ref=source_ref), source=start_value, source_ref=source_ref.atInternal()) ] else: statements = [] if hasattr(node, "elt"): if start_value is not None: current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp.makeReference(temp_block), 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(temp_block), 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 qual in reversed(node.generators): nested_temp_block = StatementTempBlock(source_ref=source_ref) tmp_iter_variable = nested_temp_block.getTempVariable( "contraction_iter") tmp_value_variable = nested_temp_block.getTempVariable("iter_value") # The first iterated value is to be calculated outside of the function and # will be given as a parameter "_iterated". if qual is node.generators[0]: value_iterator = ExpressionVariableRef(variable_name="__iterator", source_ref=source_ref) else: value_iterator = ExpressionBuiltinIter1(value=buildNode( provider=function_body, node=qual.iter, source_ref=source_ref), source_ref=source_ref) # First create the iterator and store it, next should be loop body nested_statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference( nested_temp_block), source_ref=source_ref), source=value_iterator, source_ref=source_ref) ] loop_statements = [ makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference( nested_temp_block), source_ref=source_ref), source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable.makeReference( nested_temp_block), source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)), exception_name="StopIteration", handler_body=makeStatementsSequenceFromStatement( statement=StatementBreakLoop( source_ref=source_ref.atInternal())), source_ref=source_ref), buildAssignmentStatements( provider=provider if assign_provider else function_body, node=qual.target, source=ExpressionTempVariableRef( variable=tmp_value_variable.makeReference( nested_temp_block), 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=loop_statements, source_ref=source_ref), source_ref=source_ref)) nested_temp_block.setBody( StatementsSequence(statements=nested_statements, source_ref=source_ref)) current_body = nested_temp_block statements.append(current_body) if start_value is not None: statements.append( StatementReturn(expression=ExpressionTempVariableRef( variable=container_tmp.makeReference(temp_block), source_ref=source_ref), source_ref=source_ref)) temp_block.setBody( StatementsSequence(statements=statements, source_ref=source_ref)) function_body.setBody( StatementsFrame(statements=[temp_block], guard_mode="pass_through" if emit_class is not ExpressionYield else "generator", arg_names=(), kw_only_count=0, code_name="contraction", source_ref=source_ref)) return ExpressionFunctionCall(function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=function_body, source_ref=source_ref), 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)