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 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 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 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 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 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 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 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 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 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 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 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 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 Utils.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: target_info = decodeAssignTarget( provider = provider, node = exception_assign, source_ref = source_ref, ) # We didn't allow None, therefore it cannot be None, and # the unpack is safe: pylint: disable=W0633 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( 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, ) ) # Reraise 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 indead. 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 ) prelude = ( StatementPreserveFrameException( source_ref = source_ref.atInternal() ), StatementPublishException( source_ref = source_ref.atInternal() ) ) 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 Utils.python_version < 300: exception_handling = StatementsSequence( statements = prelude, source_ref = source_ref.atInternal() ) public_exc = True else: public_exc = False else: public_exc = True if Utils.python_version < 300: exception_handling.setStatements( prelude + exception_handling.getStatements() ) else: exception_handling = StatementsSequence( statements = prelude + ( makeTryFinallyStatement( tried = exception_handling, final = StatementRestoreFrameException( source_ref = source_ref.atInternal() ), source_ref = source_ref ), ), source_ref = source_ref.atInternal() ) no_raise = buildStatementsNode( provider = provider, nodes = node.orelse, source_ref = source_ref ) if no_raise is None: return StatementTryExcept( tried = tried, handling = exception_handling, public_exc = public_exc, source_ref = source_ref ) else: return makeTryExceptNoRaise( provider = provider, temp_scope = provider.allocateTempScope("try_except"), handling = exception_handling, tried = tried, public_exc = public_exc, no_raise = no_raise, source_ref = source_ref )
def buildLambdaNode(provider, node, source_ref): assert getKind( node ) == "Lambda" parameters = buildParameterSpec( "<lambda>", node, source_ref ) function_body = ExpressionFunctionBody( provider = provider, name = "<lambda>", doc = None, parameters = parameters, 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 = function_body, node = node.body, source_ref = source_ref, ) if function_body.isGenerator(): if Utils.python_version < 270: tmp_return_value = function_body.allocateTempVariable( temp_scope = None, name = "yield_return" ) statements = ( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_return_value.makeReference( function_body ), source_ref = source_ref, ), source = body, source_ref = source_ref ), StatementConditional( condition = ExpressionComparisonIsNOT( left = ExpressionTempVariableRef( variable = tmp_return_value.makeReference( function_body ), source_ref = source_ref, ), right = ExpressionConstantRef( constant = None, source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementExpressionOnly( expression = ExpressionYield( expression = ExpressionTempVariableRef( variable = tmp_return_value.makeReference( function_body ), source_ref = source_ref, ), source_ref = source_ref ), source_ref = source_ref ) ), no_branch = None, source_ref = source_ref ) ) body = StatementsSequence( statements = statements, 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,) ), guard_mode = "generator" if function_body.isGenerator() else "full", var_names = parameters.getCoArgNames(), arg_count = parameters.getArgumentCount(), kw_only_count = parameters.getKwOnlyParameterCount(), has_starlist = parameters.getStarListArgumentName() is not None, has_stardict = parameters.getStarDictArgumentName() is not None, code_name = "<lambda>", source_ref = body.getSourceReference() ) function_body.setBody(body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref = ExpressionFunctionRef( function_body = function_body, source_ref = source_ref ), defaults = defaults, kw_defaults = kw_defaults, annotations = annotations, 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
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 _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 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 makeTryFinallyStatement(provider, tried, final, source_ref, public_exc = False): # Complex handling, due to the many variants, pylint: disable=R0912,R0914 if type(tried) in (tuple, list): tried = makeStatementsSequenceFromStatements( *tried ) if type(final) in (tuple, list): final = StatementsSequence( statements = mergeStatements(final, False), 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) if tried is None: return final if final is None: return tried if provider is not None: tried.parent = provider final.parent = provider assert tried is not None, source_ref assert final is not None, source_ref if isDebug(): final2 = final.makeClone() final2.parent = provider import nuitka.TreeXML if nuitka.TreeXML.Element is not None: f1 = final.asXml() f2 = final2.asXml() def compare(a, b): for c1, c2 in zip(a, b): compare(c1, c2) assert a.attrib == b.attrib, (a.attrib, b.attrib) compare(f1, f2) if tried.mayRaiseException(BaseException): except_handler = final.makeClone() except_handler = getStatementsAppended( statement_sequence = except_handler, statements = makeReraiseExceptionStatement( source_ref = source_ref ) ) if public_exc: preserver_id = provider.allocatePreserverId() except_handler = getStatementsPrepended( statement_sequence = except_handler, statements = ( StatementPreserveFrameException( preserver_id = preserver_id, source_ref = source_ref.atInternal() ), StatementPublishException( source_ref = source_ref ) ) ) except_handler = makeTryFinallyStatement( provider = provider, tried = except_handler, final = StatementRestoreFrameException( preserver_id = preserver_id, source_ref = source_ref.atInternal() ), public_exc = False, source_ref = source_ref, ) except_handler = makeStatementsSequenceFromStatement( statement = except_handler ) except_handler.parent = provider else: except_handler = None if tried.mayBreak(): break_handler = getStatementsAppended( statement_sequence = final.makeClone(), statements = StatementLoopBreak( source_ref = source_ref ) ) break_handler.parent = provider else: break_handler = None if tried.mayContinue(): continue_handler = getStatementsAppended( statement_sequence = final.makeClone(), statements = StatementLoopContinue( source_ref = source_ref ) ) continue_handler.parent = provider else: continue_handler = None if tried.mayReturn(): return_handler = getStatementsAppended( statement_sequence = final.makeClone(), statements = StatementReturn( expression = ExpressionReturnedValueRef( source_ref = source_ref ), source_ref = source_ref ) ) else: return_handler = None result = StatementTry( tried = tried, except_handler = except_handler, break_handler = break_handler, continue_handler = continue_handler, return_handler = return_handler, source_ref = source_ref ) if result.isStatementAborting(): return result else: return makeStatementsSequence( statements = ( result, final ), allow_none = False, source_ref = source_ref )
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 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=too-many-branches,too-many-locals 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( provider=provider, 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]: raiseSyntaxError( "default 'except:' must be last", source_ref.atLineNumber(handler.lineno).atColumnNumber( handler.col_offset ), ) 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=( makeStatementConditional( 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, 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 makeTryFinallyStatement(provider, tried, final, source_ref, public_exc=False): # Complex handling, due to the many variants, pylint: disable=too-many-branches if type(tried) in (tuple, list): if tried: tried = makeStatementsSequenceFromStatements(*tried) else: tried = None if type(final) in (tuple, list): if final: final = StatementsSequence( statements=mergeStatements(final, False), source_ref=source_ref ) else: final = None if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) # Trivial case, nothing tried needs only do the final stuff. if tried is None: return final # Trivial case, nothing final needs nothing but the tried stuff. if final is None: return tried # Parent them to us already. if provider is not None: tried.parent = provider final.parent = provider # TODO: Currently it's not possible anymore to get at XML for all codes # during the building phase. So this error catcher cannot work currently. if False and isDebug(): _checkCloning(final, provider) def getFinal(): # Make a clone of "final" only if necessary. if hasattr(getFinal, "used"): return final.makeClone() else: getFinal.used = True return final if tried.mayRaiseException(BaseException): except_handler = getStatementsAppended( statement_sequence=getFinal(), statements=makeReraiseExceptionStatement(source_ref=source_ref), ) if public_exc: preserver_id = provider.allocatePreserverId() except_handler = getStatementsPrepended( statement_sequence=except_handler, statements=( StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), StatementPublishException(source_ref=source_ref), ), ) except_handler = makeTryFinallyStatement( provider=provider, tried=except_handler, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), public_exc=False, source_ref=source_ref, ) except_handler = makeStatementsSequenceFromStatement( statement=except_handler ) else: except_handler = None if tried.mayBreak(): break_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementLoopBreak(source_ref=source_ref), ) else: break_handler = None if tried.mayContinue(): continue_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementLoopContinue(source_ref=source_ref), ) else: continue_handler = None if tried.mayReturn(): return_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementReturn( expression=ExpressionReturnedValueRef(source_ref=source_ref), source_ref=source_ref, ), ) else: return_handler = None result = StatementTry( tried=tried, except_handler=except_handler, break_handler=break_handler, continue_handler=continue_handler, return_handler=return_handler, source_ref=source_ref, ) if result.isStatementAborting(): return result else: return makeStatementsSequence( statements=(result, getFinal()), allow_none=False, source_ref=source_ref )