def makeValueComparisonReturn(left, right, comparator): yield StatementAssignmentVariable( variable=tmp_variable, source=_makeComparisonNode( left=left, right=right, comparator=comparator, source_ref=source_ref ), source_ref=source_ref, ) yield makeStatementConditional( condition=ExpressionOperationNOT( operand=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), yes_branch=StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, )
def makeValueComparisonReturn(left, right, comparator): yield StatementAssignmentVariable( variable=tmp_variable, source=_makeComparisonNode( left=left, right=right, comparator=comparator, source_ref=source_ref ), source_ref=source_ref, ) yield makeStatementConditional( condition=ExpressionOperationNot( operand=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), yes_branch=StatementReturn( expression=ExpressionTempVariableRef( variable=tmp_variable, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, )
def _makeTryExceptSingleHandlerNode(provider, public_exc, tried, exception_name, handler_body, source_ref): # No need to create this in the first place if nothing is tried. if tried is None: return None if public_exc: preserver_id = provider.allocatePreserverId() handling = [ StatementPreserveFrameException(preserver_id=preserver_id, source_ref=source_ref), StatementPublishException(source_ref=source_ref), ] else: handling = [] if not handler_body.isStatementsSequence(): handler_body = makeStatementsSequenceFromStatement( statement=handler_body) if not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(statement=tried) handling.append( makeStatementConditional( 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 python_version >= 0x300 and public_exc: handling = (makeTryFinallyStatement( provider=provider, tried=handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal(), ), ) handling = makeStatementsSequenceFromStatements(*handling) return StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, 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 buildConditionNode(provider, node, source_ref): # Conditional statements may have one or two branches. We will never see an # "elif", because that's already dealt with by module "ast", which turns it # into nested conditional statements. return makeStatementConditional( condition=buildNode(provider, node.test, source_ref), yes_branch=buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref), no_branch=buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, 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. # 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 makeStatementConditional( condition=ExpressionOperationNot( operand=buildNode(provider, node.test, source_ref), source_ref=source_ref ), yes_branch=raise_statement, no_branch=None, source_ref=source_ref, )
def buildAssertNode(provider, node, source_ref): # Build assert statements. These are re-formulated as described in the # developer manual too. They end up as conditional statement with raises of # AssertionError exceptions. # Underlying assumption: # # Assert x, y is the same as: # if not x: # raise AssertionError, y # Therefore assert statements are really just conditional statements with a # static raise contained. # exception_value = buildNode(provider, node.msg, source_ref, True) if "no_asserts" in getPythonFlags(): return None if exception_value is not None and python_version > 272: exception_value = ExpressionMakeTuple( elements=(exception_value,), source_ref=source_ref ) raise_statement = StatementRaiseException( exception_type=ExpressionBuiltinExceptionRef( exception_name="AssertionError", source_ref=source_ref ), exception_value=exception_value, exception_trace=None, exception_cause=None, source_ref=source_ref, ) return makeStatementConditional( condition=ExpressionOperationNOT( operand=buildNode(provider, node.test, source_ref), source_ref=source_ref ), yes_branch=raise_statement, no_branch=None, source_ref=source_ref, )
def buildClassNode3(provider, node, source_ref): # Many variables, due to the huge re-formulation that is going on here, # which just has the complexity and optimization checks: # pylint: disable=I0021,too-many-branches,too-many-locals,too-many-statements # This function is the Python3 special case with special re-formulation as # according to developer manual. class_statement_nodes, class_doc = extractDocFromBody(node) # We need a scope for the temporary variables, and they might be closured. temp_scope = provider.allocateTempScope(name="class_creation") tmp_class_decl_dict = provider.allocateTempVariable( temp_scope=temp_scope, name="class_decl_dict" ) tmp_metaclass = provider.allocateTempVariable( temp_scope=temp_scope, name="metaclass" ) tmp_prepared = provider.allocateTempVariable(temp_scope=temp_scope, name="prepared") class_creation_function = ExpressionClassBody( provider=provider, name=node.name, doc=class_doc, source_ref=source_ref ) class_variable = class_creation_function.getVariableForAssignment("__class__") class_variable_ref = ExpressionVariableRef( variable=class_variable, source_ref=source_ref ) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_argcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=class_creation_function, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) source_ref_orig = source_ref if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref locals_scope = class_creation_function.getFunctionLocalsScope() statements = [ StatementSetLocals( locals_scope=locals_scope, new_locals=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref ), source_ref=source_ref, ), StatementAssignmentVariableName( provider=class_creation_function, variable_name="__module__", source=makeConstantRefNode( constant=provider.getParentModule().getFullName(), source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=class_creation_function, variable_name="__doc__", source=makeConstantRefNode( constant=class_doc, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ) ) # The "__qualname__" attribute is new in Python 3.3. if python_version >= 300: qualname = class_creation_function.getFunctionQualname() if python_version < 340: qualname_ref = makeConstantRefNode( constant=qualname, source_ref=source_ref, user_provided=True ) else: qualname_ref = ExpressionFunctionQualnameRef( function_body=class_creation_function, source_ref=source_ref ) statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__qualname__", value=qualname_ref, source_ref=source_ref, ) ) if python_version >= 340: qualname_assign = statements[-1] if python_version >= 360 and class_creation_function.needsAnnotationsDictionary(): statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__annotations__", value=makeConstantRefNode( constant={}, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ) ) statements.append(body) if node.bases: tmp_bases = provider.allocateTempVariable(temp_scope=temp_scope, name="bases") if python_version >= 370: tmp_bases_orig = provider.allocateTempVariable( temp_scope=temp_scope, name="bases_orig" ) def makeBasesRef(): return ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref) else: def makeBasesRef(): return makeConstantRefNode(constant=(), source_ref=source_ref) if python_version >= 370 and node.bases: statements.append( makeStatementConditional( condition=makeComparisonExpression( comparator="NotEq", left=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), right=ExpressionTempVariableRef( variable=tmp_bases_orig, source_ref=source_ref ), source_ref=source_ref, ), yes_branch=StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__orig_bases__", value=ExpressionTempVariableRef( variable=tmp_bases_orig, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ) ) statements += [ StatementAssignmentVariable( variable=class_variable, source=makeExpressionCall( called=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), args=makeSequenceCreationOrConstant( sequence_kind="tuple", elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), makeBasesRef(), ExpressionBuiltinLocalsRef( locals_scope=locals_scope, source_ref=source_ref ), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), StatementReturn(expression=class_variable_ref, source_ref=source_ref), ] body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=class_creation_function, tried=mergeStatements(statements, True), final=StatementReleaseLocals( locals_scope=locals_scope, source_ref=source_ref ), source_ref=source_ref, ) ) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. class_creation_function.setBody(body) # The class body is basically a function that implicitly, at the end # returns its created class and cannot have other return statements # contained. decorated_body = class_creation_function for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): decorated_body = makeExpressionCall( called=decorator, args=ExpressionMakeTuple(elements=(decorated_body,), source_ref=source_ref), kw=None, source_ref=decorator.getSourceReference(), ) if node.keywords and node.keywords[-1].arg is None: keywords = node.keywords[:-1] else: keywords = node.keywords statements = [] if node.bases: statements.append( StatementAssignmentVariable( variable=tmp_bases if python_version < 370 else tmp_bases_orig, source=buildTupleCreationNode( provider=provider, elements=node.bases, source_ref=source_ref ), source_ref=source_ref, ) ) if python_version >= 370: bases_conversion = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getClassBasesMroConversionHelper(), source_ref=source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=( ExpressionTempVariableRef( variable=tmp_bases_orig, source_ref=source_ref ), ), source_ref=source_ref, ) statements.append( StatementAssignmentVariable( variable=tmp_bases, source=bases_conversion, source_ref=source_ref ) ) statements.append( StatementAssignmentVariable( variable=tmp_class_decl_dict, source=makeDictCreationOrConstant2( keys=[keyword.arg for keyword in keywords], values=[ buildNode(provider, keyword.value, source_ref) for keyword in keywords ], source_ref=source_ref, ), source_ref=source_ref, ) ) if node.keywords and node.keywords[-1].arg is None: statements.append( StatementDictOperationUpdate( dict_arg=ExpressionVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), value=buildNode(provider, node.keywords[-1].value, source_ref), source_ref=source_ref, ) ) # Check if there are bases, and if there are, go with the type of the # first base class as a metaclass unless it was specified in the class # decl dict of course. if node.bases: unspecified_metaclass_expression = ExpressionBuiltinType1( value=ExpressionSubscriptLookup( subscribed=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), subscript=makeConstantRefNode( constant=0, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ) # Might become empty behind our back during conversion, therefore make the # check at run time for 3.7 or higher. if python_version >= 370: unspecified_metaclass_expression = ExpressionConditional( condition=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref ), expression_yes=unspecified_metaclass_expression, expression_no=makeExpressionBuiltinRef( builtin_name="type", source_ref=source_ref ), source_ref=source_ref, ) else: unspecified_metaclass_expression = makeExpressionBuiltinRef( builtin_name="type", source_ref=source_ref ) call_prepare = StatementAssignmentVariable( variable=tmp_prepared, source=makeExpressionCall( called=ExpressionAttributeLookup( source=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), attribute_name="__prepare__", source_ref=source_ref, ), args=ExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True ), makeBasesRef(), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) if python_version >= 360: call_prepare = makeStatementsSequenceFromStatements( call_prepare, makeStatementConditional( condition=ExpressionAttributeCheck( object_arg=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref ), attribute_name="__getitem__", source_ref=source_ref, ), yes_branch=None, no_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="TypeError", template="%s.__prepare__() must return a mapping, not %s", template_args=( ExpressionBuiltinGetattr( object_arg=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), name=makeConstantRefNode( constant="__name__", source_ref=source_ref ), default=makeConstantRefNode( constant="<metaclass>", source_ref=source_ref ), source_ref=source_ref, ), ExpressionAttributeLookup( source=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref ), source_ref=source_ref, ), attribute_name="__name__", source_ref=source_ref, ), ), source_ref=source_ref, ).asStatement(), source_ref=source_ref, ), ) statements += [ StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionSelectMetaclass( metaclass=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=unspecified_metaclass_expression, source_ref=source_ref, ), bases=makeBasesRef(), source_ref=source_ref, ), source_ref=source_ref_orig, ), makeStatementConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), source_ref=source_ref, ), no_branch=None, yes_branch=StatementDictOperationRemove( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref ), key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionAttributeCheck( object_arg=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref ), attribute_name="__prepare__", source_ref=source_ref, ), yes_branch=call_prepare, no_branch=StatementAssignmentVariable( variable=tmp_prepared, source=makeConstantRefNode( constant={}, source_ref=source_ref, user_provided=True ), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_body, source_ref=source_ref, ), ] if python_version >= 340: class_creation_function.qualname_setup = node.name, qualname_assign final = [tmp_class_decl_dict, tmp_metaclass, tmp_prepared] if node.bases: final.insert(0, tmp_bases) if python_version >= 370: final.insert(0, tmp_bases_orig) return makeTryFinallyStatement( provider=provider, tried=statements, final=tuple( StatementReleaseVariable(variable=variable, source_ref=source_ref) for variable in final ), source_ref=source_ref, )
def wrapEvalBuiltin(source, globals_arg, locals_arg, source_ref): provider = node.getParentVariableProvider() outline_body = ExpressionOutlineBody( provider=node.getParentVariableProvider(), name="eval_call", source_ref=source_ref, ) globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( provider=provider, globals_node=globals_arg, locals_node=locals_arg, temp_scope=outline_body.getOutlineTempScope(), source_ref=source_ref, ) # The wrapping should not relocate to the "source_ref". assert ( globals_arg is None or globals_ref.getSourceReference() == globals_arg.getSourceReference() ) assert ( locals_arg is None or locals_ref.getSourceReference() == locals_arg.getSourceReference() ) source_variable = outline_body.allocateTempVariable( temp_scope=None, name="source" ) final.setStatements( final.getStatements() + ( StatementDelVariable( variable=source_variable, tolerant=True, source_ref=source_ref ), ) ) strip_choice = makeConstantRefNode(constant=(" \t",), source_ref=source_ref) if python_version >= 300: strip_choice = ExpressionConditional( condition=ExpressionComparisonIs( left=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), source_ref=source_ref, ), right=makeExpressionBuiltinRef( builtin_name="bytes", source_ref=source_ref ), source_ref=source_ref, ), expression_yes=makeConstantRefNode( constant=(b" \t",), source_ref=source_ref ), expression_no=strip_choice, source_ref=source_ref, ) # Source needs some special treatment for eval, if it's a string, it # must be stripped. string_fixup = StatementAssignmentVariable( variable=source_variable, source=makeExpressionCall( called=ExpressionAttributeLookup( source=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), attribute_name="strip", source_ref=source_ref, ), args=strip_choice, # This is a tuple kw=None, source_ref=source_ref, ), source_ref=source_ref, ) acceptable_builtin_types = [ ExpressionBuiltinAnonymousRef(builtin_name="code", source_ref=source_ref) ] if python_version >= 270: acceptable_builtin_types.append( makeExpressionBuiltinRef( builtin_name="memoryview", source_ref=source_ref ) ) statements = ( StatementAssignmentVariable( variable=source_variable, source=source, source_ref=source_ref ), makeStatementConditional( condition=ExpressionOperationNOT( operand=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), classes=makeSequenceCreationOrConstant( sequence_kind="tuple", elements=acceptable_builtin_types, source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ), yes_branch=string_fixup, no_branch=None, source_ref=source_ref, ), StatementReturn( expression=ExpressionBuiltinEval( source_code=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref ), globals_arg=globals_ref, locals_arg=locals_ref, source_ref=source_ref, ), source_ref=source_ref, ), ) tried = makeStatementsSequence( statements=(tried,) + statements, allow_none=False, source_ref=source_ref ) outline_body.setBody( makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=outline_body, tried=tried, final=final, source_ref=source_ref, ) ) ) return outline_body
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=too-many-locals 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=tmp_break_indicator, 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 = ExpressionYieldFromWaitable( expression=ExpressionAsyncNext( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) statements = ( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_value_variable, 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=tmp_break_indicator, 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 = ExpressionYieldFromWaitable( expression=ExpressionAsyncIter( value=source, source_ref=source.getSourceReference() ), source_ref=source.getSourceReference(), ) statements += [ # First create the iterator and store it. StatementAssignmentVariable( variable=tmp_iter_variable, 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 += [ makeStatementConditional( 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 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 wrapEvalBuiltin(source, globals_arg, locals_arg, source_ref): provider = node.getParentVariableProvider() outline_body = ExpressionOutlineBody( provider=node.getParentVariableProvider(), name="eval_call", source_ref=source_ref, ) globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( provider=provider, globals_node=globals_arg, locals_node=locals_arg, temp_scope=outline_body.getOutlineTempScope(), source_ref=source_ref, ) # The wrapping should not relocate to the "source_ref". assert (globals_arg is None or globals_ref.getSourceReference() == globals_arg.getSourceReference()) assert (locals_arg is None or locals_ref.getSourceReference() == locals_arg.getSourceReference()) source_variable = outline_body.allocateTempVariable(temp_scope=None, name="source") final.setStatements(final.getStatements() + (StatementDelVariable( variable=source_variable, tolerant=True, source_ref=source_ref), )) strip_choice = makeConstantRefNode(constant=(" \t", ), source_ref=source_ref) if python_version >= 300: strip_choice = ExpressionConditional( condition=ExpressionComparisonIs( left=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref), source_ref=source_ref, ), right=makeExpressionBuiltinRef(builtin_name="bytes", source_ref=source_ref), source_ref=source_ref, ), expression_yes=makeConstantRefNode(constant=(b" \t", ), source_ref=source_ref), expression_no=strip_choice, source_ref=source_ref, ) # Source needs some special treatment for eval, if it's a string, it # must be stripped. string_fixup = StatementAssignmentVariable( variable=source_variable, source=makeExpressionCall( called=ExpressionAttributeLookup( source=ExpressionTempVariableRef(variable=source_variable, source_ref=source_ref), attribute_name="strip", source_ref=source_ref, ), args=strip_choice, # This is a tuple kw=None, source_ref=source_ref, ), source_ref=source_ref, ) acceptable_builtin_types = [ ExpressionBuiltinAnonymousRef(builtin_name="code", source_ref=source_ref) ] if python_version >= 270: acceptable_builtin_types.append( makeExpressionBuiltinRef(builtin_name="memoryview", source_ref=source_ref)) statements = ( StatementAssignmentVariable(variable=source_variable, source=source, source_ref=source_ref), makeStatementConditional( condition=ExpressionOperationNOT( operand=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref), classes=makeSequenceCreationOrConstant( sequence_kind="tuple", elements=acceptable_builtin_types, source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ), yes_branch=string_fixup, no_branch=None, source_ref=source_ref, ), StatementReturn( expression=ExpressionBuiltinEval( source_code=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref), globals_arg=globals_ref, locals_arg=locals_ref, source_ref=source_ref, ), source_ref=source_ref, ), ) tried = makeStatementsSequence(statements=(tried, ) + statements, allow_none=False, source_ref=source_ref) outline_body.setBody( makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=outline_body, tried=tried, final=final, source_ref=source_ref, ))) return outline_body
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=makeExpressionBuiltinLocals(provider=provider, source_ref=source_ref), source_ref=source_ref, ) pre_statements = [ # First assign globals and locals temporary the values given. StatementAssignmentVariable(variable=globals_keeper_variable, source=globals_node, source_ref=source_ref), StatementAssignmentVariable(variable=locals_keeper_variable, source=locals_node, source_ref=source_ref), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef(variable=locals_keeper_variable, source_ref=source_ref), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementAssignmentVariable( variable=locals_keeper_variable, source=locals_default, source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementAssignmentVariable( variable=globals_keeper_variable, 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 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=tmp_break_indicator, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), StatementLoopBreak(source_ref=source_ref), ) else: statements = (StatementLoopBreak(source_ref=source_ref),) pushBuildContext("loop_body") loop_statements = buildStatementsNode( provider=provider, nodes=node.body, source_ref=source_ref ) popBuildContext() # The loop body contains a conditional statement at the start that breaks # the loop if it fails. loop_body = makeStatementsSequence( statements=( makeStatementConditional( condition=ExpressionOperationNOT( operand=buildNode(provider, node.test, source_ref), source_ref=source_ref, ), yes_branch=StatementsSequence( statements=statements, source_ref=source_ref ), no_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=tmp_break_indicator, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ), loop_statement, makeStatementConditional( 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 StatementsSequence( statements=mergeStatements(statements, False), source_ref=source_ref )
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=tmp_target_variable, source=ExpressionImportModuleNameHard( module_name="sys", import_name="stdout", source_ref=source_ref ), source_ref=source_ref, ) statements = [ StatementAssignmentVariable( variable=tmp_target_variable, source=buildNode( provider=provider, node=node.dest, source_ref=source_ref ), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=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 buildAssignmentStatementsFromDecoded(provider, kind, detail, source, source_ref): # This is using many variable names on purpose, so as to give names to the # unpacked detail values, and has many branches due to the many cases # dealt with, pylint: disable=too-many-branches,too-many-locals,too-many-statements if kind == "Name": return StatementAssignmentVariableName( provider=provider, variable_name=detail, source=source, source_ref=source_ref, ) elif kind == "Attribute": lookup_source, attribute_name = detail return StatementAssignmentAttribute( expression=lookup_source, attribute_name=attribute_name, source=source, source_ref=source_ref, ) elif kind == "Subscript": subscribed, subscript = detail return StatementAssignmentSubscript( expression=subscribed, subscript=subscript, source=source, source_ref=source_ref, ) elif kind == "Slice": lookup_source, lower, upper = detail # For Python3 there is no slicing operation, this is always done # with subscript using a slice object. For Python2, it is only done # if no "step" is provided. use_sliceobj = python_version >= 300 if use_sliceobj: return StatementAssignmentSubscript( expression=lookup_source, source=source, subscript=ExpressionBuiltinSlice( start=lower, stop=upper, step=None, source_ref=source_ref ), source_ref=source_ref, ) else: return StatementAssignmentSlice( expression=lookup_source, lower=lower, upper=upper, source=source, source_ref=source_ref, ) elif kind == "Tuple": temp_scope = provider.allocateTempScope("tuple_unpack") source_iter_var = provider.allocateTempVariable( temp_scope=temp_scope, name="source_iter" ) element_vars = [ provider.allocateTempVariable( temp_scope=temp_scope, name="element_%d" % (element_index + 1) ) for element_index in range(len(detail)) ] starred_list_var = None starred_index = None statements = [] for element_index, element in enumerate(detail): if element[0] == "Starred": if starred_index is not None: raiseSyntaxError( "two starred expressions in assignment", source_ref.atColumnNumber(0), ) starred_index = element_index for element_index, element in enumerate(detail): element_var = element_vars[element_index] if starred_list_var is not None: statements.insert( starred_index + 1, StatementAssignmentVariable( variable=element_var, source=ExpressionListOperationPop( list_arg=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), ) elif element[0] != "Starred": statements.append( StatementAssignmentVariable( variable=element_var, source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref ), count=element_index + 1, expected=starred_index or len(detail), starred=starred_index is not None, source_ref=source_ref, ), source_ref=source_ref, ) ) else: assert starred_index == element_index starred_list_var = element_var statements.append( StatementAssignmentVariable( variable=element_var, source=ExpressionBuiltinList( value=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ) if starred_list_var is None: statements.append( StatementSpecialUnpackCheck( iterator=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref ), count=len(detail), source_ref=source_ref, ) ) else: statements.insert( starred_index + 1, makeStatementConditional( condition=makeComparisonExpression( comparator="Lt", left=ExpressionBuiltinLen( value=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref ), source_ref=source_ref, ), right=makeConstantRefNode( constant=len(statements) - starred_index - 1, source_ref=source_ref, ), source_ref=source_ref, ), yes_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="ValueError", template="""\ not enough values to unpack (expected at least %d, got %%d)""" % (len(statements) - 1), template_args=makeBinaryOperationNode( operator="Add", left=ExpressionBuiltinLen( value=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref ), source_ref=source_ref, ), right=makeConstantRefNode( constant=starred_index, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ).asStatement(), no_branch=None, source_ref=source_ref, ), ) if python_version >= 370: iter_creation_class = ExpressionBuiltinIterForUnpack else: iter_creation_class = ExpressionBuiltinIter1 statements = [ StatementAssignmentVariable( variable=source_iter_var, source=iter_creation_class(value=source, source_ref=source_ref), source_ref=source_ref, ), makeTryFinallyStatement( provider=provider, tried=statements, final=( StatementReleaseVariable( variable=source_iter_var, source_ref=source_ref ), ), source_ref=source_ref, ), ] # When all is done, copy over to the actual assignment targets, starred # or not makes no difference here anymore. for element_index, element in enumerate(detail): if element[0] == "Starred": element = element[1] element_var = element_vars[element_index] statements.append( buildAssignmentStatementsFromDecoded( provider=provider, kind=element[0], detail=element[1], source=ExpressionTempVariableRef( variable=element_var, source_ref=source_ref ), source_ref=source_ref, ) ) # Need to release temporary variables right after successful # usage. statements.append( StatementDelVariable( variable=element_var, tolerant=True, source_ref=source_ref ) ) final_statements = [] for element_var in element_vars: final_statements.append( StatementReleaseVariable(variable=element_var, source_ref=source_ref) ) return makeTryFinallyStatement( provider=provider, tried=statements, final=final_statements, source_ref=source_ref, ) elif kind == "Starred": raiseSyntaxError( "starred assignment target must be in a list or tuple", source_ref.atColumnNumber(0), ) else: assert False, (kind, source_ref, detail)
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,too-many-statements # 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: assert emit_class is StatementDictOperationSet current_body = StatementDictOperationSet( 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 _buildWithNode(provider, context_expr, assign_target, body, sync, source_ref): # Many details, pylint: disable=too-many-branches,too-many-locals with_source = buildNode(provider, context_expr, source_ref) if python_version < 0x380 and Options.is_fullcompat: 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" ) # Indicator variable, will end up with C bool type, and need not be released. tmp_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="indicator", temp_type="bool" ) 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 body and python_version < 0x3A0: deepest = body while deepest.getVisitableNodes(): deepest = deepest.getVisitableNodes()[-1] if python_version < 0x370: body_lineno = deepest.getCompatibleSourceReference().getLineNumber() else: body_lineno = deepest.getSourceReference().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 < 0x270: attribute_lookup_maker = makeExpressionAttributeLookup else: attribute_lookup_maker = ExpressionAttributeLookupSpecial enter_value = ExpressionCallEmpty( called=attribute_lookup_maker( expression=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=makeExpressionMakeTuple( 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: exit_value_exception = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitExit( expression=exit_value_exception, source_ref=source_ref ), source_ref=source_ref, ) exit_value_no_exception = ExpressionYieldFromWaitable( ExpressionAsyncWaitExit( expression=exit_value_no_exception, source_ref=source_ref ), source_ref=source_ref, ) # First assign the with context to a temporary variable. statements = [ StatementAssignmentVariable( variable=tmp_source_variable, source=with_source, source_ref=source_ref ) ] # Before 3.9, __aenter__ is immediately awaited, after we first do __aexit__ lookup. if not sync and python_version < 0x390: enter_value = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitEnter( expression=enter_value, source_ref=source_ref ), source_ref=source_ref, ) attribute_enter_assignment = StatementAssignmentVariable( variable=tmp_enter_variable, source=enter_value, source_ref=source_ref ) attribute_exit_assignment = StatementAssignmentVariable( variable=tmp_exit_variable, source=attribute_lookup_maker( expression=ExpressionTempVariableRef( variable=tmp_source_variable, source_ref=source_ref ), attribute_name="__exit__" if sync else "__aexit__", source_ref=source_ref, ), source_ref=source_ref, ) # Next, assign "__enter__" and "__exit__" attributes to temporary variables, and # depending on Python versions switch the order of these lookups and the order of # awaiting enter. # Normal "with" statements are enter, exit ordered after 3.6, and "async with" # are since 3.9, and since 3.9 the enter is not awaited, until an exit is present. if python_version >= 0x390 and not sync: enter_await_statement = StatementAssignmentVariable( variable=tmp_enter_variable, source=ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitEnter( expression=ExpressionTempVariableRef( variable=tmp_enter_variable, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ) attribute_assignments = ( attribute_enter_assignment, attribute_exit_assignment, enter_await_statement, ) elif python_version >= 0x360 and sync: attribute_assignments = (attribute_enter_assignment, attribute_exit_assignment) else: attribute_assignments = (attribute_exit_assignment, attribute_enter_assignment) statements.extend(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, ), makeStatementConditional( 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 >= 0x270, source_ref=source_ref, ), final=makeStatementConditional( 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=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 ), ), 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. tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator" ) statements = mergeStatements( ( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(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 = ( 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, ), ) final = StatementReleaseVariable( variable=tmp_handler_indicator_variable, source_ref=source_ref.atInternal() ) return makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref.atInternal(), ), makeTryFinallyStatement( provider=provider, tried=tried, final=final, source_ref=source_ref ), )
def getClassBasesMroConversionHelper(): helper_name = "_mro_entries_conversion" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("bases",), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ), ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "list") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "base") args_variable = result.getVariableForAssignment(variable_name="bases") non_type_case = makeStatementConditional( condition=ExpressionAttributeCheck( object_arg=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionListOperationExtend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=makeExpressionCall( called=ExpressionAttributeLookup( source=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), args=ExpressionMakeTuple( elements=( ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), ), source_ref=internal_source_ref, ), kw=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), no_branch=StatementListOperationAppend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) type_case = StatementListOperationAppend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), value=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ) loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), makeStatementConditional( condition=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref ), classes=makeConstantRefNode( constant=type, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), yes_branch=type_case, no_branch=non_type_case, source_ref=internal_source_ref, ), ) final = ( StatementReleaseVariable( variable=args_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_result_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_iter_variable, source_ref=internal_source_ref ), StatementReleaseVariable( variable=tmp_item_variable, source_ref=internal_source_ref ), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=[], source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionBuiltinTuple( value=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setBody( makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, ) ) ) return result
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=tmp_target_variable, source=makeExpressionImportModuleNameHard(module_name="sys", import_name="stdout", source_ref=source_ref), source_ref=source_ref, ) statements = [ StatementAssignmentVariable( variable=tmp_target_variable, source=buildNode(provider=provider, node=node.dest, source_ref=source_ref), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=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, 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=too-many-locals 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: # Indicator variable, will end up with C bool type, and need not be released. tmp_break_indicator = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator", temp_type="bool") statements = [ StatementAssignmentVariable( variable=tmp_break_indicator, 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 = ExpressionYieldFromWaitable( expression=ExpressionAsyncNext( value=ExpressionTempVariableRef(variable=tmp_iter_variable, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ) statements = ( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable(variable=tmp_value_variable, 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=tmp_break_indicator, 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 = ExpressionYieldFromWaitable( expression=ExpressionAsyncIter( value=source, source_ref=source.getSourceReference()), source_ref=source.getSourceReference(), ) statements += ( # First create the iterator and store it. StatementAssignmentVariable(variable=tmp_iter_variable, source=iter_source, source_ref=source_ref), makeTryFinallyStatement( provider=provider, tried=StatementLoop(loop_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.append( makeStatementConditional( 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, )) 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=too-many-locals exec_globals = node.globals exec_locals = node.locals body = node.body # 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, ) 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=source_variable, 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=globals_keeper_variable, source=globals_value, source_ref=source_ref, ), StatementAssignmentVariable(variable=locals_keeper_variable, source=locals_value, source_ref=source_ref), StatementAssignmentVariable( variable=plain_indicator_variable, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ), makeStatementConditional( 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=globals_keeper_variable, source=ExpressionBuiltinGlobals(source_ref=source_ref), source_ref=source_ref, ), makeStatementConditional( 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=locals_keeper_variable, source=makeExpressionBuiltinLocals( provider=provider, source_ref=source_ref), source_ref=source_ref, ), StatementAssignmentVariable( variable=plain_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), ), no_branch=None, source_ref=source_ref, ), ), no_branch=makeStatementsSequenceFromStatements( makeStatementConditional( 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=locals_keeper_variable, 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, ), 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=makeStatementConditional( 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=StatementLocalsDictSync( locals_arg=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source_ref=source_ref, ), 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 buildLambdaNode(provider, node, source_ref): # Many details to deal with, pylint: disable=too-many-locals assert getKind(node) == "Lambda" function_kind, flags = detectFunctionBodyKind(nodes=(node.body,)) outer_body, function_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name="<lambda>", function_doc=None, flags=flags, node=node, source_ref=source_ref, ) if function_kind == "Function": code_body = function_body else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name="<lambda>", code_object=code_object, flags=set(), source_ref=source_ref, ) code_body.qualname_provider = provider if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ) ) ) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults( provider=provider, node=node, function_body=function_body, source_ref=source_ref ) body = buildNode(provider=code_body, node=node.body, source_ref=source_ref) if function_kind == "Generator": if python_version < 270: tmp_return_value = code_body.allocateTempVariable( temp_scope=None, name="yield_return" ) statements = ( StatementAssignmentVariable( variable=tmp_return_value, source=body, source_ref=source_ref ), makeStatementConditional( condition=ExpressionComparisonIsNOT( left=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref ), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionYield( expression=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref ), source_ref=source_ref, ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), ) body = makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable( variable=tmp_return_value, source_ref=source_ref ), source_ref=source_ref, ) else: body = StatementExpressionOnly(expression=body, source_ref=source_ref) else: body = StatementReturn(expression=body, source_ref=source_ref) if function_kind == "Generator": frame_class = StatementsFrameGenerator else: frame_class = StatementsFrameFunction body = frame_class( statements=mergeStatements((body,)), code_object=code_object, source_ref=body.getSourceReference(), ) body = makeStatementsSequenceFromStatement(statement=body) code_body.setBody(body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=outer_body, source_ref=source_ref ), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, )
def buildAssignmentStatementsFromDecoded(provider, kind, detail, source, source_ref): # This is using many variable names on purpose, so as to give names to the # unpacked detail values, and has many branches due to the many cases # dealt with, pylint: disable=too-many-branches,too-many-locals,too-many-statements if kind == "Name": return StatementAssignmentVariableName( provider=provider, variable_name=detail, source=source, source_ref=source_ref, ) elif kind == "Attribute": lookup_source, attribute_name = detail return StatementAssignmentAttribute( expression=lookup_source, attribute_name=mangleName(attribute_name, provider), source=source, source_ref=source_ref, ) elif kind == "Subscript": subscribed, subscript = detail return StatementAssignmentSubscript( expression=subscribed, subscript=subscript, source=source, source_ref=source_ref, ) elif kind == "Slice": lookup_source, lower, upper = detail # For Python3 there is no slicing operation, this is always done # with subscript using a slice object. For Python2, it is only done # if no "step" is provided. use_sliceobj = python_version >= 300 if use_sliceobj: return StatementAssignmentSubscript( expression=lookup_source, source=source, subscript=makeExpressionBuiltinSlice(start=lower, stop=upper, step=None, source_ref=source_ref), source_ref=source_ref, ) else: return StatementAssignmentSlice( expression=lookup_source, lower=lower, upper=upper, source=source, source_ref=source_ref, ) elif kind == "Tuple": temp_scope = provider.allocateTempScope("tuple_unpack") source_iter_var = provider.allocateTempVariable(temp_scope=temp_scope, name="source_iter") element_vars = [ provider.allocateTempVariable(temp_scope=temp_scope, name="element_%d" % (element_index + 1)) for element_index in range(len(detail)) ] starred_list_var = None starred_index = None statements = [] for element_index, element in enumerate(detail): if element[0] == "Starred": if starred_index is not None: raiseSyntaxError( "two starred expressions in assignment" if python_version < 390 else "multiple starred expressions in assignment", source_ref.atColumnNumber(0), ) starred_index = element_index for element_index, element in enumerate(detail): element_var = element_vars[element_index] if starred_list_var is not None: statements.insert( starred_index + 1, StatementAssignmentVariable( variable=element_var, source=ExpressionListOperationPop( list_arg=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), ) elif element[0] != "Starred": statements.append( StatementAssignmentVariable( variable=element_var, source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref), count=element_index + 1, expected=starred_index or len(detail), starred=starred_index is not None, source_ref=source_ref, ), source_ref=source_ref, )) else: assert starred_index == element_index starred_list_var = element_var statements.append( StatementAssignmentVariable( variable=element_var, source=ExpressionBuiltinList( value=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, )) if starred_list_var is None: statements.append( StatementSpecialUnpackCheck( iterator=ExpressionTempVariableRef( variable=source_iter_var, source_ref=source_ref), count=len(detail), source_ref=source_ref, )) else: statements.insert( starred_index + 1, makeStatementConditional( condition=makeComparisonExpression( comparator="Lt", left=ExpressionBuiltinLen( value=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref), source_ref=source_ref, ), right=makeConstantRefNode( constant=len(statements) - starred_index - 1, source_ref=source_ref, ), source_ref=source_ref, ), yes_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="ValueError", template="""\ not enough values to unpack (expected at least %d, got %%d)""" % (len(statements) - 1), template_args=makeBinaryOperationNode( operator="Add", left=ExpressionBuiltinLen( value=ExpressionTempVariableRef( variable=starred_list_var, source_ref=source_ref), source_ref=source_ref, ), right=makeConstantRefNode(constant=starred_index, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ).asStatement(), no_branch=None, source_ref=source_ref, ), ) if python_version >= 370: iter_creation_class = ExpressionBuiltinIterForUnpack else: iter_creation_class = ExpressionBuiltinIter1 statements = [ StatementAssignmentVariable( variable=source_iter_var, source=iter_creation_class(value=source, source_ref=source_ref), source_ref=source_ref, ), makeTryFinallyStatement( provider=provider, tried=statements, final=(StatementReleaseVariable(variable=source_iter_var, source_ref=source_ref), ), source_ref=source_ref, ), ] # When all is done, copy over to the actual assignment targets, starred # or not makes no difference here anymore. for element_index, element in enumerate(detail): if element[0] == "Starred": element = element[1] element_var = element_vars[element_index] statements.append( buildAssignmentStatementsFromDecoded( provider=provider, kind=element[0], detail=element[1], source=ExpressionTempVariableRef(variable=element_var, source_ref=source_ref), source_ref=source_ref, )) # Need to release temporary variables right after successful # usage. statements.append( StatementDelVariable(variable=element_var, tolerant=True, source_ref=source_ref)) final_statements = [] for element_var in element_vars: final_statements.append( StatementReleaseVariable(variable=element_var, source_ref=source_ref)) return makeTryFinallyStatement( provider=provider, tried=statements, final=final_statements, source_ref=source_ref, ) elif kind == "Starred": raiseSyntaxError( "starred assignment target must be in a list or tuple", source_ref.atColumnNumber(0), ) else: assert False, (kind, source_ref, detail)
def getClassBasesMroConversionHelper(): helper_name = "_mro_entries_conversion" result = makeInternalHelperFunctionBody( name=helper_name, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=("bases", ), ps_pos_only_args=(), ps_list_star_arg=None, ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=(), ), inline_const_args=False, # TODO: Allow this. ) temp_scope = None tmp_result_variable = result.allocateTempVariable(temp_scope, "list") tmp_iter_variable = result.allocateTempVariable(temp_scope, "iter") tmp_item_variable = result.allocateTempVariable(temp_scope, "base") args_variable = result.getVariableForAssignment(variable_name="bases") non_type_case = makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionListOperationExtend( list_arg=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), value=makeExpressionCall( called=ExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), attribute_name="__mro_entries__", source_ref=internal_source_ref, ), args=makeExpressionMakeTuple( elements=(ExpressionVariableRef( variable=args_variable, source_ref=internal_source_ref), ), source_ref=internal_source_ref, ), kw=None, source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), no_branch=StatementListOperationAppend( list_arg=ExpressionTempVariableRef(variable=tmp_result_variable, source_ref=internal_source_ref), value=ExpressionTempVariableRef(variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ) type_case = StatementListOperationAppend( list_arg=ExpressionTempVariableRef(variable=tmp_result_variable, source_ref=internal_source_ref), value=ExpressionTempVariableRef(variable=tmp_item_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ) loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable=tmp_item_variable, source=ExpressionBuiltinNext1( value=ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), exception_name="StopIteration", handler_body=StatementLoopBreak(source_ref=internal_source_ref), source_ref=internal_source_ref, ), makeStatementConditional( condition=ExpressionConditionalAnd( left=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), classes=makeConstantRefNode( constant=type, source_ref=internal_source_ref), source_ref=internal_source_ref, ), right=ExpressionBuiltinIssubclass( cls=ExpressionTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), classes=makeConstantRefNode( constant=type, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), yes_branch=type_case, no_branch=non_type_case, source_ref=internal_source_ref, ), ) final = ( StatementReleaseVariable(variable=args_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_result_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_iter_variable, source_ref=internal_source_ref), StatementReleaseVariable(variable=tmp_item_variable, source_ref=internal_source_ref), ) tried = makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_iter_variable, source=ExpressionBuiltinIter1( value=ExpressionVariableRef(variable=args_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), StatementAssignmentVariable( variable=tmp_result_variable, source=makeConstantRefNode(constant=[], source_ref=internal_source_ref), source_ref=internal_source_ref, ), StatementLoop(loop_body=loop_body, source_ref=internal_source_ref), StatementReturn( expression=ExpressionBuiltinTuple( value=ExpressionTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), source_ref=internal_source_ref, ), source_ref=internal_source_ref, ), ) result.setChild( "body", makeStatementsSequenceFromStatement( makeTryFinallyStatement( provider=result, tried=tried, final=final, source_ref=internal_source_ref, )), ) return result
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 = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitEnter( expression=enter_value, source_ref=source_ref ), source_ref=source_ref, ) exit_value_exception = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitExit( expression=exit_value_exception, source_ref=source_ref ), source_ref=source_ref, ) exit_value_no_exception = ExpressionYieldFromWaitable( ExpressionAsyncWaitExit( expression=exit_value_no_exception, source_ref=source_ref ), 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, ), makeStatementConditional( 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=makeStatementConditional( 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=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 _makeTryExceptSingleHandlerNode( provider, public_exc, tried, exception_name, handler_body, source_ref ): # No need to create this in the first place if nothing is tried. if tried is None: return None if public_exc: preserver_id = provider.allocatePreserverId() handling = [ StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref ), StatementPublishException(source_ref=source_ref), ] else: handling = [] if not handler_body.isStatementsSequence(): handler_body = makeStatementsSequenceFromStatement(statement=handler_body) if not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(statement=tried) handling.append( makeStatementConditional( 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 python_version >= 300 and public_exc: handling = ( makeTryFinallyStatement( provider=provider, tried=handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), source_ref=source_ref.atInternal(), ), ) handling = makeStatementsSequenceFromStatements(*handling) return StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, 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 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 < 0x300: 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 < 0x300: 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 < 0x300: exception_handling.setChild( "statements", ( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal(), ), StatementPublishException( source_ref=source_ref.atInternal()), ) + exception_handling.subnode_statements, ) 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 buildClassNode3(provider, node, source_ref): # Many variables, due to the huge re-formulation that is going on here, # which just has the complexity and optimization checks: # pylint: disable=I0021,too-many-branches,too-many-locals,too-many-statements # This function is the Python3 special case with special re-formulation as # according to developer manual. class_statement_nodes, class_doc = extractDocFromBody(node) # We need a scope for the temporary variables, and they might be closured. temp_scope = provider.allocateTempScope(name="class_creation") tmp_class_decl_dict = provider.allocateTempVariable(temp_scope=temp_scope, name="class_decl_dict") tmp_metaclass = provider.allocateTempVariable(temp_scope=temp_scope, name="metaclass") tmp_prepared = provider.allocateTempVariable(temp_scope=temp_scope, name="prepared") class_creation_function = ExpressionClassBody(provider=provider, name=node.name, doc=class_doc, source_ref=source_ref) class_locals_scope = class_creation_function.getLocalsScope() # Only local variable, for provision to methods. class_variable = class_locals_scope.getLocalVariable( owner=class_creation_function, variable_name="__class__") class_locals_scope.registerProvidedVariable(class_variable) class_variable_ref = ExpressionVariableRef(variable=class_variable, source_ref=source_ref) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_freevars=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=class_creation_function, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) source_ref_orig = source_ref if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref locals_scope = class_creation_function.getLocalsScope() statements = [ StatementSetLocals( locals_scope=locals_scope, new_locals=ExpressionTempVariableRef(variable=tmp_prepared, source_ref=source_ref), source_ref=source_ref, ), StatementAssignmentVariableName( provider=class_creation_function, variable_name="__module__", source=ExpressionModuleAttributeNameRef( variable=provider.getParentModule().getVariableForReference( "__name__"), source_ref=source_ref, ), source_ref=source_ref, ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=class_creation_function, variable_name="__doc__", source=makeConstantRefNode(constant=class_doc, source_ref=source_ref, user_provided=True), source_ref=source_ref, )) # The "__qualname__" attribute is new in Python3. qualname = class_creation_function.getFunctionQualname() if python_version < 0x340: qualname_ref = makeConstantRefNode(constant=qualname, source_ref=source_ref, user_provided=True) else: qualname_ref = ExpressionFunctionQualnameRef( function_body=class_creation_function, source_ref=source_ref) statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__qualname__", value=qualname_ref, source_ref=source_ref, )) if python_version >= 0x340: qualname_assign = statements[-1] if python_version >= 0x360 and class_creation_function.needsAnnotationsDictionary( ): statements.append( StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__annotations__", value=makeConstantRefNode(constant={}, source_ref=source_ref, user_provided=True), source_ref=source_ref, )) statements.append(body) if node.bases: tmp_bases = provider.allocateTempVariable(temp_scope=temp_scope, name="bases") if python_version >= 0x370: tmp_bases_orig = provider.allocateTempVariable( temp_scope=temp_scope, name="bases_orig") def makeBasesRef(): return ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref) else: def makeBasesRef(): return makeConstantRefNode(constant=(), source_ref=source_ref) if python_version >= 0x370 and node.bases: statements.append( makeStatementConditional( condition=makeComparisonExpression( comparator="NotEq", left=ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), right=ExpressionTempVariableRef(variable=tmp_bases_orig, source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementLocalsDictOperationSet( locals_scope=locals_scope, variable_name="__orig_bases__", value=ExpressionTempVariableRef(variable=tmp_bases_orig, source_ref=source_ref), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, )) statements += ( StatementAssignmentVariable( variable=class_variable, source=makeExpressionCall( called=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), args=makeExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), makeBasesRef(), ExpressionBuiltinLocalsRef(locals_scope=locals_scope, source_ref=source_ref), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef(variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), StatementReturn(expression=class_variable_ref, source_ref=source_ref), ) body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=class_creation_function, tried=mergeStatements(statements, True), final=StatementReleaseLocals(locals_scope=locals_scope, source_ref=source_ref), source_ref=source_ref, )) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. class_creation_function.setChild("body", body) # The class body is basically a function that implicitly, at the end # returns its created class and cannot have other return statements # contained. decorated_body = class_creation_function for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): decorated_body = makeExpressionCall( called=decorator, args=makeExpressionMakeTuple(elements=(decorated_body, ), source_ref=source_ref), kw=None, source_ref=decorator.getSourceReference(), ) if node.keywords and node.keywords[-1].arg is None: keywords = node.keywords[:-1] else: keywords = node.keywords statements = [] if node.bases: statements.append( StatementAssignmentVariable( variable=tmp_bases if python_version < 0x370 else tmp_bases_orig, source=_buildBasesTupleCreationNode(provider=provider, elements=node.bases, source_ref=source_ref), source_ref=source_ref, )) if python_version >= 0x370: bases_conversion = ExpressionFunctionCall( function=ExpressionFunctionCreation( function_ref=ExpressionFunctionRef( function_body=getClassBasesMroConversionHelper(), source_ref=source_ref, ), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref, ), values=(ExpressionTempVariableRef(variable=tmp_bases_orig, source_ref=source_ref), ), source_ref=source_ref, ) statements.append( StatementAssignmentVariable(variable=tmp_bases, source=bases_conversion, source_ref=source_ref)) statements.append( StatementAssignmentVariable( variable=tmp_class_decl_dict, source=makeDictCreationOrConstant2( keys=[keyword.arg for keyword in keywords], values=[ buildNode(provider, keyword.value, source_ref) for keyword in keywords ], source_ref=source_ref, ), source_ref=source_ref, )) if node.keywords and node.keywords[-1].arg is None: statements.append( StatementDictOperationUpdate( dict_arg=ExpressionVariableRef(variable=tmp_class_decl_dict, source_ref=source_ref), value=buildNode(provider, node.keywords[-1].value, source_ref), source_ref=source_ref, )) # Check if there are bases, and if there are, go with the type of the # first base class as a metaclass unless it was specified in the class # decl dict of course. if node.bases: unspecified_metaclass_expression = ExpressionBuiltinType1( value=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), subscript=makeConstantRefNode(constant=0, source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ) # Might become empty behind our back during conversion, therefore make the # check at run time for 3.7 or higher. if python_version >= 0x370: unspecified_metaclass_expression = ExpressionConditional( condition=ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), expression_yes=unspecified_metaclass_expression, expression_no=makeExpressionBuiltinTypeRef( builtin_name="type", source_ref=source_ref), source_ref=source_ref, ) else: unspecified_metaclass_expression = makeExpressionBuiltinTypeRef( builtin_name="type", source_ref=source_ref) call_prepare = StatementAssignmentVariable( variable=tmp_prepared, source=makeExpressionCall( called=ExpressionAttributeLookup( expression=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), attribute_name="__prepare__", source_ref=source_ref, ), args=makeExpressionMakeTuple( elements=( makeConstantRefNode(constant=node.name, source_ref=source_ref, user_provided=True), makeBasesRef(), ), source_ref=source_ref, ), kw=ExpressionTempVariableRef(variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ) if python_version >= 0x364: call_prepare = makeStatementsSequenceFromStatements( call_prepare, makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref), attribute_name="__getitem__", source_ref=source_ref, ), yes_branch=None, no_branch=makeRaiseExceptionExpressionFromTemplate( exception_type="TypeError", template="%s.__prepare__() must return a mapping, not %s", template_args=( ExpressionBuiltinGetattr( expression=ExpressionTempVariableRef( variable=tmp_metaclass, source_ref=source_ref), name=makeConstantRefNode(constant="__name__", source_ref=source_ref), default=makeConstantRefNode(constant="<metaclass>", source_ref=source_ref), source_ref=source_ref, ), ExpressionAttributeLookup( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_prepared, source_ref=source_ref), source_ref=source_ref, ), attribute_name="__name__", source_ref=source_ref, ), ), source_ref=source_ref, ).asStatement(), source_ref=source_ref, ), ) statements += ( StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionSelectMetaclass( metaclass=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), key=makeConstantRefNode( constant="metaclass", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=unspecified_metaclass_expression, source_ref=source_ref, ), bases=makeBasesRef(), source_ref=source_ref, ), source_ref=source_ref_orig, ), makeStatementConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode(constant="metaclass", source_ref=source_ref, user_provided=True), dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), source_ref=source_ref, ), no_branch=None, yes_branch=StatementDictOperationRemove( dict_arg=ExpressionTempVariableRef( variable=tmp_class_decl_dict, source_ref=source_ref), key=makeConstantRefNode(constant="metaclass", source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ), makeStatementConditional( condition=ExpressionAttributeCheck( expression=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), attribute_name="__prepare__", source_ref=source_ref, ), yes_branch=call_prepare, no_branch=StatementAssignmentVariable( variable=tmp_prepared, source=makeConstantRefNode(constant={}, source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=decorated_body, source_ref=source_ref, ), ) if python_version >= 0x340: class_creation_function.qualname_setup = node.name, qualname_assign final = [tmp_class_decl_dict, tmp_metaclass, tmp_prepared] if node.bases: final.insert(0, tmp_bases) if python_version >= 0x370: final.insert(0, tmp_bases_orig) return makeTryFinallyStatement( provider=provider, tried=statements, final=tuple( StatementReleaseVariable(variable=variable, source_ref=source_ref) for variable in final), source_ref=source_ref, )
def buildLambdaNode(provider, node, source_ref): # Many details to deal with, pylint: disable=too-many-locals assert getKind(node) == "Lambda" function_kind, flags = detectFunctionBodyKind(nodes=(node.body, )) outer_body, function_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name="<lambda>", function_doc=None, flags=flags, node=node, source_ref=source_ref, ) if function_kind == "Function": code_body = function_body else: code_body = ExpressionGeneratorObjectBody( provider=function_body, name="<lambda>", code_object=code_object, flags=set(), source_ref=source_ref, ) code_body.qualname_provider = provider if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement(statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ))) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults(provider=provider, node=node, function_body=function_body, source_ref=source_ref) body = buildNode(provider=code_body, node=node.body, source_ref=source_ref) if function_kind == "Generator": if python_version < 270: tmp_return_value = code_body.allocateTempVariable( temp_scope=None, name="yield_return") statements = ( StatementAssignmentVariable(variable=tmp_return_value, source=body, source_ref=source_ref), makeStatementConditional( condition=ExpressionComparisonIsNOT( left=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref), right=ExpressionConstantNoneRef(source_ref=source_ref), source_ref=source_ref, ), yes_branch=StatementExpressionOnly( expression=ExpressionYield( expression=ExpressionTempVariableRef( variable=tmp_return_value, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), no_branch=None, source_ref=source_ref, ), ) body = makeTryFinallyStatement( provider=provider, tried=statements, final=StatementReleaseVariable(variable=tmp_return_value, source_ref=source_ref), source_ref=source_ref, ) else: body = StatementExpressionOnly(expression=body, source_ref=source_ref) else: body = StatementReturn(expression=body, source_ref=source_ref) if function_kind == "Generator": frame_class = StatementsFrameGenerator else: frame_class = StatementsFrameFunction body = frame_class( statements=mergeStatements((body, )), code_object=code_object, source_ref=body.getSourceReference(), ) body = makeStatementsSequenceFromStatement(statement=body) code_body.setBody(body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=outer_body, source_ref=source_ref), defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref, )
def _buildWithNode(provider, context_expr, assign_target, body, sync, source_ref): # Many details, pylint: disable=too-many-locals with_source = buildNode(provider, context_expr, source_ref) if python_version < 380 and 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 body: deepest = body while deepest.getVisitableNodes(): deepest = deepest.getVisitableNodes()[-1] if python_version < 370: body_lineno = deepest.getCompatibleSourceReference().getLineNumber( ) else: body_lineno = deepest.getSourceReference().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 = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitEnter(expression=enter_value, source_ref=source_ref), source_ref=source_ref, ) exit_value_exception = ExpressionYieldFromWaitable( expression=ExpressionAsyncWaitExit(expression=exit_value_exception, source_ref=source_ref), source_ref=source_ref, ) exit_value_no_exception = ExpressionYieldFromWaitable( ExpressionAsyncWaitExit(expression=exit_value_no_exception, source_ref=source_ref), 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, ), makeStatementConditional( 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=makeStatementConditional( 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=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 buildMatchNode(provider, node, source_ref): """Python3.10 or higher, match statements.""" subject_node = buildNode(provider, node.subject, source_ref) temp_scope = provider.allocateTempScope("match_statement") # The value matched against, must be released in the end. tmp_subject = provider.allocateTempVariable(temp_scope, "subject") # Indicator variable, will end up with C bool type, and need not be released. tmp_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="indicator", temp_type="bool") cases = [] for case in node.cases: cases.append( _buildCase( provider=provider, case=case, tmp_subject=tmp_subject, source_ref=source_ref, )) case_statements = [] for case in cases: conditions, assignments, guard, branch_code = case # Set indicator variable at end of branch code, unless it's last branch # where there would be no usage of it. if case is not cases[-1]: branch_code = makeStatementsSequence( statements=( branch_code, StatementAssignmentVariable( variable=tmp_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), ), allow_none=True, source_ref=source_ref, ) if guard is not None: branch_code = makeStatementConditional( condition=guard, yes_branch=branch_code, no_branch=None, source_ref=source_ref, ) del guard branch_code = makeStatementsSequence( statements=(assignments, branch_code), allow_none=True, source_ref=source_ref, ) del assignments if conditions is not None: branch_code = makeStatementConditional( condition=makeAndNode(values=conditions, source_ref=source_ref), yes_branch=branch_code, no_branch=None, source_ref=source_ref, ) del conditions if case is not cases[0]: statement = makeStatementConditional( condition=makeComparisonExpression( comparator="Is", left=ExpressionTempVariableRef( variable=tmp_indicator_variable, source_ref=source_ref), right=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=source_ref, ), yes_branch=branch_code, no_branch=None, source_ref=source_ref, )