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=R0912,R0914 if kind == "Name": variable_ref = detail return StatementAssignmentVariable( variable_ref = variable_ref, 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 = Utils.python_version >= 300 if use_sliceobj: return StatementAssignmentSubscript( expression = lookup_source, source = source, subscript = ExpressionSliceObject( lower = lower, upper = 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" ) statements = [ StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = source_iter_var, source_ref = source_ref ), source = ExpressionBuiltinIter1( value = source, source_ref = source_ref ), source_ref = source_ref ) ] 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 for element_index, element in enumerate(detail): element_var = element_vars[element_index] if starred_list_var is not None: if element[0] == "Starred": raiseSyntaxError( reason = "two starred expressions in assignment", col_offset = 0, source_ref = source_ref ) statements.insert( starred_index+2, StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = element_var, source_ref = source_ref ), 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_ref = ExpressionTargetTempVariableRef( variable = element_var, source_ref = source_ref ), source = ExpressionSpecialUnpack( value = ExpressionTempVariableRef( variable = source_iter_var, source_ref = source_ref ), count = element_index + 1, expected = len(detail), source_ref = source_ref ), source_ref = source_ref ) ) else: starred_index = element_index starred_list_var = element_var statements.append( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = element_var, source_ref = source_ref ), 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 ) ) # 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 ) ) final_statements = [] final_statements.append( StatementReleaseVariable( variable = source_iter_var, source_ref = source_ref ) ) # TODO: In that order, or reversed. 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( reason = "starred assignment target must be in a list or tuple", source_ref = source_ref, col_offset = 0 ) else: assert False, (kind, source_ref, detail)
def _buildInplaceAssignAttributeNode(provider, lookup_source, attribute_name, tmp_variable1, tmp_variable2, operator, expression, source_ref): # First assign the target value to a temporary variable. preserve_to_tmp = StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_variable1, source_ref = source_ref ), source = ExpressionAttributeLookup( source = lookup_source.makeClone(), attribute_name = attribute_name, source_ref = source_ref ), source_ref = source_ref ) # Second assign the in-place result to a temporary variable inplace_to_tmp = StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_variable2, source_ref = source_ref ), source = ExpressionOperationBinaryInplace( operator = operator, left = ExpressionTempVariableRef( variable = tmp_variable1, source_ref = source_ref ), right = expression, source_ref = source_ref ), source_ref = source_ref ) # Third, copy it over, if the reference values change, i.e. IsNot is true. copy_back_from_tmp = StatementConditional( condition = ExpressionComparisonIsNOT( left = ExpressionTempVariableRef( variable = tmp_variable1, source_ref = source_ref ), right = ExpressionTempVariableRef( variable = tmp_variable2, source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementAssignmentAttribute( expression = lookup_source.makeClone(), attribute_name = attribute_name, source = ExpressionTempVariableRef( variable = tmp_variable2, source_ref = source_ref ), source_ref = source_ref ) ), no_branch = None, source_ref = source_ref ) copy_back_from_tmp = makeTryFinallyStatement( provider = provider, tried = copy_back_from_tmp, final = StatementReleaseVariable( variable = tmp_variable2, source_ref = source_ref ), source_ref = source_ref ) return ( preserve_to_tmp, # making sure the above temporary variable is deleted in any case. makeTryFinallyStatement( provider = provider, tried = ( inplace_to_tmp, copy_back_from_tmp, ), final = StatementReleaseVariable( variable = tmp_variable1, source_ref = source_ref ), source_ref = source_ref ) )
def buildFunctionNode(provider, node, source_ref): # Functions have way too many details, pylint: disable=R0912,R0914 assert getKind(node) == "FunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags, _written_variables, _non_local_declarations, _global_declarations = \ detectFunctionBodyKind( nodes = function_statement_nodes ) outer_body, function_body, code_object = buildFunctionWithParsing( provider=provider, function_kind=function_kind, name=node.name, function_doc=function_doc, flags=flags, node=node, source_ref=source_ref) if function_kind == "Function": code_body = function_body elif function_kind == "Generator": code_body = ExpressionGeneratorObjectBody(provider=function_body, name=node.name, flags=flags, source_ref=source_ref) for variable in function_body.getVariables(): code_body.getVariableForReference(variable.getName()) else: assert False, function_kind if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement(statement=StatementReturn( expression=ExpressionMakeGeneratorObject( generator_ref=ExpressionFunctionRef( function_body=code_body, source_ref=source_ref), code_object=code_object, source_ref=source_ref), source_ref=source_ref))) decorators = buildNodeList(provider=provider, nodes=reversed(node.decorator_list), source_ref=source_ref) defaults = buildNodeList(provider=provider, nodes=node.args.defaults, source_ref=source_ref) kw_defaults = buildParameterKwDefaults(provider=provider, node=node, function_body=function_body, source_ref=source_ref) function_statements_body = buildFrameNode(provider=code_body, nodes=function_statement_nodes, code_object=code_object, source_ref=source_ref) if function_kind == "Function": # TODO: Generators might have to raise GeneratorExit instead. function_statements_body = _insertFinalReturnStatement( function_statements_body=function_statements_body, return_class=StatementReturn, source_ref=source_ref) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body) code_body.setBody(function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=outer_body, source_ref=source_ref), code_object=code_object, defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref) # Add the "staticmethod" decorator to __new__ methods if not provided. # CPython made these optional, but secretly applies them when it does # "class __new__". We add them earlier, so our optimization will see it. if node.name == "__new__" and \ provider.isExpressionClassBody(): for decorator in decorators: if decorator.isExpressionVariableRef() and \ decorator.getVariableName() == "staticmethod": break else: decorators.append( ExpressionBuiltinRef(builtin_name="staticmethod", source_ref=source_ref)) if python_version >= 360 and \ node.name == "__init_subclass__" and \ provider.isExpressionClassBody(): for decorator in decorators: if decorator.isExpressionVariableRef() and \ decorator.getVariableName() == "classmethod": break else: decorators.append( ExpressionBuiltinRef(builtin_name="classmethod", source_ref=source_ref)) decorated_function = function_creation for decorator in decorators: decorated_function = ExpressionCallNoKeywords( called=decorator, args=ExpressionMakeTuple(elements=(decorated_function, ), source_ref=source_ref), source_ref=decorator.getSourceReference()) result = StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef(variable_name=mangleName( node.name, provider), source_ref=source_ref), source=decorated_function, source_ref=source_ref) if python_version >= 340: function_body.qualname_setup = result.getTargetVariableRef() return result
def _buildContractionBodyNode(provider, node, emit_class, start_value, container_tmp, outer_iter_ref, temp_scope, assign_provider, source_ref, function_body): # This uses lots of variables and branches. There is no good way # around that, and we deal with many cases, due to having generator # expressions sharing this code, pylint: disable=R0912,R0914,R0915 if start_value is not None: statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp, source_ref=source_ref), source=start_value, source_ref=source_ref.atInternal()) ] if assign_provider: tmp_variables = [] else: tmp_variables = [container_tmp] else: statements = [] tmp_variables = [] if hasattr(node, "elt"): if start_value is not None: current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref), buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref) else: assert emit_class is ExpressionYield function_body.markAsGenerator() current_body = emit_class(buildNode(provider=function_body, node=node.elt, source_ref=source_ref), source_ref=source_ref) else: assert emit_class is ExpressionDictOperationSet current_body = emit_class(ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref), key=buildNode( provider=function_body, node=node.key, source_ref=source_ref, ), value=buildNode( provider=function_body, node=node.value, source_ref=source_ref, ), source_ref=source_ref) current_body = StatementExpressionOnly(expression=current_body, source_ref=source_ref) for count, qual in enumerate(reversed(node.generators)): tmp_value_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="iter_value_%d" % count) tmp_variables.append(tmp_value_variable) # The first iterated value is to be calculated outside of the function # and will be given as a parameter "_iterated", the others are built # inside the function. if qual is node.generators[0]: iterator_ref = outer_iter_ref.makeCloneAt(source_ref) tmp_iter_variable = None nested_statements = [] else: # First create the iterator and store it, next should be loop body value_iterator = ExpressionBuiltinIter1(value=buildNode( provider=function_body, node=qual.iter, source_ref=source_ref), source_ref=source_ref) tmp_iter_variable = function_body.allocateTempVariable( temp_scope=temp_scope, name="contraction_iter_%d" % count) tmp_variables.append(tmp_iter_variable) nested_statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref), source=value_iterator, source_ref=source_ref) ] iterator_ref = ExpressionTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref) loop_statements = [ makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable, source_ref=source_ref), source=ExpressionBuiltinNext1(value=iterator_ref, source_ref=source_ref), source_ref=source_ref)), exception_name="StopIteration", handler_body=makeStatementsSequenceFromStatement( statement=StatementBreakLoop( source_ref=source_ref.atInternal())), public_exc=False, source_ref=source_ref), buildAssignmentStatements( provider=provider if assign_provider else function_body, temp_provider=function_body, node=qual.target, source=ExpressionTempVariableRef(variable=tmp_value_variable, source_ref=source_ref), source_ref=source_ref) ] conditions = buildNodeList(provider=function_body, nodes=qual.ifs, source_ref=source_ref) if len(conditions) == 1: loop_statements.append( StatementConditional( condition=conditions[0], yes_branch=makeStatementsSequenceFromStatement( statement=current_body), no_branch=None, source_ref=source_ref)) elif len(conditions) > 1: loop_statements.append( StatementConditional( condition=buildAndNode(provider=function_body, values=conditions, source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=current_body), no_branch=None, source_ref=source_ref)) else: loop_statements.append(current_body) nested_statements.append( StatementLoop(body=StatementsSequence( statements=mergeStatements(loop_statements), source_ref=source_ref), source_ref=source_ref)) if tmp_iter_variable is not None: nested_statements.append( StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable, source_ref=source_ref), tolerant=False, source_ref=source_ref)) current_body = StatementsSequence(statements=nested_statements, source_ref=source_ref) statements.append(current_body) statements = mergeStatements(statements) if emit_class is ExpressionYield: statements.insert(0, StatementGeneratorEntry(source_ref=source_ref)) del_statements = [] for tmp_variable in tmp_variables: del_statements.append( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable, source_ref=source_ref), tolerant=True, source_ref=source_ref.atInternal())) return statements, del_statements
def 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_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator") statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator_variable.makeReference(provider), source_ref=source_ref), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), StatementBreakLoop(source_ref=source_ref)) else: statements = (StatementBreakLoop(source_ref=source_ref), ) # The loop body contains a conditional statement at the start that breaks # the loop if it fails. loop_body = makeStatementsSequence(statements=(StatementConditional( condition=buildNode(provider, node.test, source_ref), no_branch=StatementsSequence(statements=statements, source_ref=source_ref), yes_branch=None, source_ref=source_ref), buildStatementsNode( provider=provider, nodes=node.body, source_ref=source_ref)), allow_none=True, source_ref=source_ref) loop_statement = StatementLoop(body=loop_body, source_ref=source_ref) if else_block is None: return loop_statement else: statements = (StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator_variable.makeReference(provider), source_ref=source_ref), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref), loop_statement, StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_break_indicator_variable. makeReference(provider), source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=else_block, no_branch=None, source_ref=source_ref)) return StatementsSequence(statements=statements, source_ref=source_ref)
def onLeaveNode(self, node): if node.isStatementAssignmentVariableName(): variable_name = node.getVariableName() provider = node.provider # Classes always assign to locals dictionary except for closure # variables taken. if self._shouldUseLocalsDict(provider, variable_name): new_node = StatementLocalsDictOperationSet( locals_scope=provider.getFunctionLocalsScope(), variable_name=variable_name, value=node.subnode_source, source_ref=node.source_ref, ) else: variable = provider.getVariableForAssignment( variable_name=variable_name) new_node = StatementAssignmentVariable( variable=variable, source=node.subnode_source, source_ref=node.source_ref, ) variable.addVariableUser(provider) node.parent.replaceChild(node, new_node) del node.parent del node.provider elif node.isStatementDelVariableName(): variable_name = node.getVariableName() provider = node.provider if self._shouldUseLocalsDict(provider, variable_name): # Classes always assign to locals dictionary except for closure # variables taken. # TODO: This is losing the "tolerant" annotation. new_node = StatementLocalsDictOperationDel( locals_scope=provider.getFunctionLocalsScope(), variable_name=variable_name, source_ref=node.source_ref, ) else: variable = provider.getVariableForAssignment( variable_name=variable_name) new_node = StatementDelVariable( variable=variable, tolerant=node.tolerant, source_ref=node.source_ref, ) variable.addVariableUser(provider) parent = node.parent node.finalize() parent.replaceChild(node, new_node)
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" ) # 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: 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( 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=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( 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, ), 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 ), ), 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 buildExecNode(provider, node, source_ref): # "exec" statements, should only occur with Python2. # This is using many variables, due to the many details this is # dealing with. The locals and globals need to be dealt with in # temporary variables, and we need handling of indicators, so # that is just the complexity, pylint: disable=R0914 exec_globals = node.globals exec_locals = node.locals body = node.body orig_globals = exec_globals # Handle exec(a,b,c) to be same as exec a, b, c if exec_locals is None and exec_globals is None and \ getKind(body) == "Tuple": parts = body.elts body = parts[0] if len(parts) > 1: exec_globals = parts[1] if len(parts) > 2: exec_locals = parts[2] else: return StatementRaiseException( exception_type=ExpressionBuiltinExceptionRef( exception_name="TypeError", source_ref=source_ref), exception_value=ExpressionConstantRef(constant="""\ exec: arg 1 must be a string, file, or code object""", source_ref=source_ref), exception_trace=None, exception_cause=None, source_ref=source_ref) if provider.isExpressionFunctionBody(): provider.markAsExecContaining() if orig_globals is None: provider.markAsUnqualifiedExecContaining(source_ref) temp_scope = provider.allocateTempScope("exec") locals_value = buildNode(provider, exec_locals, source_ref, True) if locals_value is None: locals_value = ExpressionConstantRef(constant=None, source_ref=source_ref) globals_value = buildNode(provider, exec_globals, source_ref, True) if globals_value is None: globals_value = ExpressionConstantRef(constant=None, source_ref=source_ref) source_code = buildNode(provider, body, source_ref) source_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="exec_source") globals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="globals") locals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="locals") plain_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="plain") tried = ( # First evaluate the source code expressions. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=source_variable, source_ref=source_ref), source=source_code, source_ref=source_ref), # Assign globals and locals temporary the values given, then fix it # up, taking note in the "plain" temporary variable, if it was an # "exec" statement with None arguments, in which case the copy back # will be necessary. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), source=globals_value, source_ref=source_ref), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source=locals_value, source_ref=source_ref), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=plain_indicator_variable, source_ref=source_ref), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref), StatementConditional( condition=ExpressionComparisonIs(left=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), right=ExpressionConstantRef( constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), source=ExpressionBuiltinGlobals(source_ref=source_ref), source_ref=source_ref, ), StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source=_getLocalsClassNode(provider)( source_ref=source_ref), source_ref=source_ref, ), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=plain_indicator_variable, source_ref=source_ref), source=ExpressionConstantRef( constant=True, source_ref=source_ref), source_ref=source_ref, )), no_branch=None, source_ref=source_ref), ), no_branch=makeStatementsSequenceFromStatements( StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), source_ref=source_ref, )), no_branch=None, source_ref=source_ref)), source_ref=source_ref), # Source needs some special treatment for not done for "eval", if it's a # file object, then must be read. StatementConditional( condition=ExpressionBuiltinIsinstance( instance=ExpressionTempVariableRef(variable=source_variable, source_ref=source_ref), classes=ExpressionBuiltinAnonymousRef( builtin_name="file", source_ref=source_ref, ), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=source_variable, source_ref=source_ref), source=ExpressionCallEmpty( called=ExpressionAttributeLookup( source=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref), attribute_name="read", source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)), no_branch=None, source_ref=source_ref), makeTryFinallyStatement( provider=provider, tried=StatementExec(source_code=ExpressionTempVariableRef( variable=source_variable, source_ref=source_ref), globals_arg=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), locals_arg=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source_ref=source_ref), final=StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=plain_indicator_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=StatementLocalsDictSync( locals_arg=ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref, ), source_ref=source_ref.atInternal())), no_branch=None, source_ref=source_ref), source_ref=source_ref)) final = ( StatementReleaseVariable(variable=source_variable, source_ref=source_ref), StatementReleaseVariable(variable=globals_keeper_variable, source_ref=source_ref), StatementReleaseVariable(variable=locals_keeper_variable, source_ref=source_ref), StatementReleaseVariable(variable=plain_indicator_variable, source_ref=source_ref), ) return makeTryFinallyStatement(provider=provider, tried=tried, final=final, source_ref=source_ref)
def wrapEvalGlobalsAndLocals(provider, globals_node, locals_node, temp_scope, source_ref): """ Wrap the locals and globals arguments for "eval". This is called from the outside, and when the node tree already exists. """ globals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="globals") locals_keeper_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="locals") if locals_node is None: locals_node = ExpressionConstantRef(constant=None, source_ref=source_ref) if globals_node is None: globals_node = ExpressionConstantRef(constant=None, 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=ExpressionConstantRef(constant=None, source_ref=source_ref), source_ref=source_ref), expression_no=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), expression_yes=_getLocalsClassNode(provider)(source_ref=source_ref), source_ref=source_ref) pre_statements = [ # First assign globals and locals temporary the values given. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), source=globals_node, source_ref=source_ref, ), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source=locals_node, source_ref=source_ref, ), StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef(variable=locals_keeper_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref), source=locals_default, source_ref=source_ref, )), no_branch=None, source_ref=source_ref), StatementConditional( condition=ExpressionComparisonIs(left=ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), right=ExpressionConstantRef( constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref), source=ExpressionBuiltinGlobals(source_ref=source_ref), source_ref=source_ref, )), no_branch=None, source_ref=source_ref) ] return (ExpressionTempVariableRef( variable=globals_keeper_variable, source_ref=source_ref if globals_node is None else globals_node.getSourceReference()), ExpressionTempVariableRef( variable=locals_keeper_variable, source_ref=source_ref if locals_node is None else locals_node.getSourceReference()), makeStatementsSequence(pre_statements, False, source_ref), makeStatementsSequence(post_statements, False, source_ref))
def getListUnpackingHelper(): helper_name = "_unpack_list" result = ExpressionFunctionBody(provider=getInternalModule(), name=helper_name, doc=None, parameters=ParameterSpec( ps_name=helper_name, ps_normal_args=(), ps_list_star_arg="args", ps_dict_star_arg=None, ps_default_count=0, ps_kw_only_args=()), flags=set(), source_ref=internal_source_ref) 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, "keys") loop_body = makeStatementsSequenceFromStatements( makeTryExceptSingleHandlerNode( tried=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_item_variable, source_ref=internal_source_ref), 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), StatementExpressionOnly(expression=ExpressionListOperationExtend( 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)) args_variable = result.getVariableForAssignment(variable_name="args") final = ( 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_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable, source_ref=internal_source_ref), source=ExpressionBuiltinIter1(value=ExpressionVariableRef( variable_name="args", variable=args_variable, source_ref=internal_source_ref), source_ref=internal_source_ref), source_ref=internal_source_ref), StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_result_variable, source_ref=internal_source_ref), source=makeConstantRefNode(constant=[], source_ref=internal_source_ref), source_ref=internal_source_ref), StatementLoop(body=loop_body, source_ref=internal_source_ref), StatementReturn(expression=ExpressionTempVariableRef( variable=tmp_result_variable, 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 _buildInplaceAssignSliceNode( provider, lookup_source, lower, upper, tmp_variable1, tmp_variable2, tmp_variable3, tmp_variable4, operator, expression, source_ref, ): # Due to the 3 inputs, which we need to also put into temporary variables, # there are too many variables here, but they are needed. # pylint: disable=too-many-locals # First assign the target value, lower and upper to temporary variables. copy_to_tmp = StatementAssignmentVariable(variable=tmp_variable1, source=lookup_source, source_ref=source_ref) final_statements = [ StatementReleaseVariable(variable=tmp_variable1, source_ref=source_ref) ] statements = [] if lower is not None: statements.append( StatementAssignmentVariable(variable=tmp_variable2, source=lower, source_ref=source_ref)) final_statements.append( StatementReleaseVariable(variable=tmp_variable2, source_ref=source_ref)) lower_ref1 = ExpressionTempVariableRef(variable=tmp_variable2, source_ref=source_ref) lower_ref2 = ExpressionTempVariableRef(variable=tmp_variable2, source_ref=source_ref) else: assert tmp_variable2 is None lower_ref1 = lower_ref2 = None if upper is not None: statements.append( StatementAssignmentVariable(variable=tmp_variable3, source=upper, source_ref=source_ref)) final_statements.append( StatementReleaseVariable(variable=tmp_variable3, source_ref=source_ref)) upper_ref1 = ExpressionTempVariableRef(variable=tmp_variable3, source_ref=source_ref) upper_ref2 = ExpressionTempVariableRef(variable=tmp_variable3, source_ref=source_ref) else: assert tmp_variable3 is None upper_ref1 = upper_ref2 = None use_sliceobj = python_version >= 0x300 # Second assign the in-place result over the original value. if use_sliceobj: statements += ( StatementAssignmentVariable( variable=tmp_variable4, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref), subscript=makeExpressionBuiltinSlice( start=lower_ref2, stop=upper_ref2, step=None, source_ref=source_ref, ), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_variable4, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef(variable=tmp_variable4, source_ref=source_ref), right=expression, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentSubscript( subscribed=ExpressionTempVariableRef(variable=tmp_variable1, source_ref=source_ref), subscript=makeExpressionBuiltinSlice(start=lower_ref1, stop=upper_ref1, step=None, source_ref=source_ref), source=ExpressionTempVariableRef(variable=tmp_variable4, source_ref=source_ref), source_ref=source_ref, ), ) else: statements += ( StatementAssignmentVariable( variable=tmp_variable4, source=ExpressionSliceLookup( expression=ExpressionTempVariableRef( variable=tmp_variable1, source_ref=source_ref), lower=lower_ref2, upper=upper_ref2, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_variable4, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef(variable=tmp_variable4, source_ref=source_ref), right=expression, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentSlice( expression=ExpressionTempVariableRef(variable=tmp_variable1, source_ref=source_ref), lower=lower_ref1, upper=upper_ref1, source=ExpressionTempVariableRef(variable=tmp_variable4, source_ref=source_ref), source_ref=source_ref, ), ) final_statements.append( StatementReleaseVariable(variable=tmp_variable4, source_ref=source_ref)) return ( copy_to_tmp, makeTryFinallyStatement( provider=provider, tried=statements, final=final_statements, source_ref=source_ref, ), )
def _buildInplaceAssignSubscriptNode( provider, subscribed, subscript, tmp_variable1, tmp_variable2, tmp_variable3, operator, expression, source_ref, ): # First assign the subscribed value to a temporary variable. preserve_to_tmp1 = StatementAssignmentVariable(variable=tmp_variable1, source=subscribed, source_ref=source_ref) # Second assign the subscript value to a temporary variable statements = ( StatementAssignmentVariable(variable=tmp_variable2, source=subscript, source_ref=source_ref), StatementAssignmentVariable( variable=tmp_variable3, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef(variable=tmp_variable1, source_ref=source_ref), subscript=ExpressionTempVariableRef(variable=tmp_variable2, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_variable3, source=makeExpressionOperationBinaryInplace( operator=operator, left=ExpressionTempVariableRef(variable=tmp_variable3, source_ref=source_ref), right=expression, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentSubscript( subscribed=ExpressionTempVariableRef(variable=tmp_variable1, source_ref=source_ref), subscript=ExpressionTempVariableRef(variable=tmp_variable2, source_ref=source_ref), source=ExpressionTempVariableRef(variable=tmp_variable3, source_ref=source_ref), source_ref=source_ref, ), ) return ( preserve_to_tmp1, makeTryFinallyStatement( provider=provider, tried=statements, final=( StatementReleaseVariable(variable=tmp_variable1, source_ref=source_ref), StatementReleaseVariable(variable=tmp_variable2, source_ref=source_ref), StatementReleaseVariable(variable=tmp_variable3, source_ref=source_ref), ), source_ref=source_ref, ), )
def buildAsyncFunctionNode(provider, node, source_ref): # We are creating a function here that creates coroutine objects, with # many details each, pylint: disable=R0914 assert getKind(node) == "AsyncFunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) creator_function_body, _, code_object = buildFunctionWithParsing( provider = provider, function_kind = "Coroutine", name = node.name, flags = set(), function_doc = function_doc, node = node, source_ref = source_ref ) function_body = ExpressionCoroutineObjectBody( provider = creator_function_body, name = node.name, flags = set(), source_ref = source_ref ) decorators = buildNodeList( provider = provider, nodes = reversed(node.decorator_list), source_ref = source_ref ) defaults = buildNodeList( provider = provider, nodes = node.args.defaults, source_ref = source_ref ) function_statements_body = buildFrameNode( provider = function_body, nodes = function_statement_nodes, code_object = code_object, source_ref = source_ref ) function_statements_body = _insertFinalReturnStatement( function_statements_body = function_statements_body, return_class = StatementGeneratorReturn, source_ref = source_ref ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement = function_statements_body ) function_body.setBody( function_statements_body ) annotations = buildParameterAnnotations(provider, node, source_ref) kw_defaults = buildParameterKwDefaults( provider = provider, node = node, function_body = creator_function_body, source_ref = source_ref ) creator_function_body.setBody( makeStatementsSequenceFromStatement( statement = StatementReturn( expression = ExpressionMakeCoroutineObject( coroutine_ref = ExpressionFunctionRef( function_body = function_body, source_ref = source_ref ), code_object = code_object, source_ref = source_ref ), source_ref = source_ref ) ) ) function_creation = ExpressionFunctionCreation( function_ref = ExpressionFunctionRef( function_body = creator_function_body, source_ref = source_ref ), code_object = code_object, defaults = defaults, kw_defaults = kw_defaults, annotations = annotations, source_ref = source_ref ) decorated_function = function_creation for decorator in decorators: decorated_function = ExpressionCallNoKeywords( called = decorator, args = ExpressionMakeTuple( elements = (decorated_function,), source_ref = source_ref ), source_ref = decorator.getSourceReference() ) result = StatementAssignmentVariable( variable_ref = ExpressionTargetVariableRef( variable_name = mangleName(node.name, provider), source_ref = source_ref ), source = decorated_function, source_ref = source_ref ) function_body.qualname_setup = result.getTargetVariableRef() return result
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(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 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( subscribed=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 >= 0x300 if use_sliceobj: return StatementAssignmentSubscript( subscribed=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 < 0x390 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 >= 0x370: 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 buildImportFromNode(provider, node, source_ref): # "from .. import .." statements. This may trigger a star import, or multiple names # being looked up from the given module variable name. module_name = node.module if node.module is not None else "" level = node.level # Importing from "__future__" module may enable flags. if module_name == "__future__": if not provider.isPythonModule() and not source_ref.isExecReference(): SyntaxErrors.raiseSyntaxError( reason= "from __future__ imports must occur at the beginning of the file", col_offset=8 if Utils.python_version >= 300 or not Options.isFullCompat() else None, source_ref=source_ref) for import_desc in node.names: object_name, _local_name = import_desc.name, import_desc.asname enableFutureFeature(object_name=object_name, future_spec=source_ref.getFutureSpec(), source_ref=source_ref) # Remember it for checks to be applied once module is complete. node.source_ref = source_ref _future_import_nodes.append(node) target_names = [] import_names = [] for import_desc in node.names: object_name, local_name = import_desc.name, import_desc.asname if object_name == "*": target_names.append(None) else: target_names.append( local_name if local_name is not None else object_name) import_names.append(object_name) if None in target_names: # More than "*" is a syntax error in Python, need not care about this at # all, it's only allowed value for import list in this case. assert target_names == [None] # Python3 made this a syntax error unfortunately. if not provider.isPythonModule() and Utils.python_version >= 300: SyntaxErrors.raiseSyntaxError( "import * only allowed at module level", provider.getSourceReference()) if provider.isExpressionFunctionBody(): provider.markAsStarImportContaining() return StatementImportStar(module_import=ExpressionImportModule( module_name=module_name, import_list=("*", ), level=level, source_ref=source_ref), source_ref=source_ref) else: import_nodes = [] for target_name, import_name in zip(target_names, import_names): import_nodes.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name=target_name, source_ref=source_ref), source=ExpressionImportName(module=ExpressionImportModule( module_name=module_name, import_list=import_names, level=level, source_ref=source_ref), import_name=import_name, source_ref=source_ref), source_ref=source_ref)) # Note: Each import is sequential. It can succeed, and the failure of a later one is # not changing one. We can therefore have a sequence of imports that only import one # thing therefore. return StatementsSequence(statements=import_nodes, 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_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=ExpressionTypeCheck( cls=ExpressionTempVariableRef(variable=tmp_item_variable, 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 buildParseTree(provider, source_code, source_ref, is_module): # Workaround: ast.parse cannot cope with some situations where a file is not terminated # by a new line. if not source_code.endswith("\n"): source_code = source_code + "\n" body = ast.parse(source_code, source_ref.getFilename()) assert getKind(body) == "Module" line_offset = source_ref.getLineNumber() - 1 if line_offset > 0: for created_node in ast.walk(body): if hasattr(created_node, "lineno"): created_node.lineno += line_offset body, doc = extractDocFromBody(body) result = buildStatementsNode(provider=provider, nodes=body, source_ref=source_ref, frame=is_module) # Check if a __future__ imports really were at the beginning of the file. for node in body: if node in _future_import_nodes: _future_import_nodes.remove(node) else: if _future_import_nodes: SyntaxErrors.raiseSyntaxError( reason= "from __future__ imports must occur at the beginning of the file", col_offset=1 if Utils.python_version >= 300 or not Options.isFullCompat() else None, source_ref=_future_import_nodes[0].source_ref) internal_source_ref = source_ref.atInternal() statements = [] if is_module: statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__doc__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=doc, source_ref=internal_source_ref), source_ref=internal_source_ref)) statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__file__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=source_ref.getFilename(), source_ref=internal_source_ref), source_ref=internal_source_ref)) if provider.isPythonPackage(): # TODO: __package__ is not set here, but automatically, which makes it invisible # though statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__path__", source_ref=internal_source_ref), source=ExpressionConstantRef( constant=[Utils.dirname(source_ref.getFilename())], source_ref=internal_source_ref), source_ref=internal_source_ref)) if Utils.python_version >= 300: statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__cached__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=None, source_ref=internal_source_ref), source_ref=internal_source_ref)) if Utils.python_version >= 330: # For Python3.3, it's set for both packages and non-packages. statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__package__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=provider.getPackage(), source_ref=internal_source_ref), source_ref=internal_source_ref)) if Utils.python_version >= 330 and not provider.isMainModule(): # Set initialzing at the beginning to True statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__initializing__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=True, source_ref=internal_source_ref), source_ref=internal_source_ref)) # Now the module body if there is any at all. if result is not None: statements.extend(result.getStatements()) if Utils.python_version >= 330 and not provider.isMainModule(): # Set initialzing at the beginning to True statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__initializing__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=False, source_ref=internal_source_ref), source_ref=internal_source_ref)) if result is None: result = makeStatementsSequence(statements=statements, source_ref=internal_source_ref, allow_none=False) else: result.setStatements(statements) return result
def buildForLoopNode(provider, node, source_ref): # The for loop is re-formulated according to developer manual. An iterator # is created, and looped until it gives StopIteration. The else block is # taken if a for loop exits normally, i.e. because of iterator # exhaustion. We do this by introducing an indicator variable. source = buildNode(provider, node.iter, source_ref) temp_scope = provider.allocateTempScope("for_loop") tmp_iter_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="for_iterator") tmp_value_variable = provider.allocateTempVariable(temp_scope=temp_scope, name="iter_value") else_block = buildStatementsNode( provider=provider, nodes=node.orelse if node.orelse else None, source_ref=source_ref) if else_block is not None: tmp_break_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="break_indicator") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator_variable.makeReference( provider), source_ref=source_ref), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref) ] else: statements = [] statements.append(StatementBreakLoop(source_ref=source_ref.atInternal())) handler_body = makeStatementsSequence(statements=statements, allow_none=False, source_ref=source_ref) statements = (makeTryExceptSingleHandlerNode( tried=makeStatementsSequenceFromStatement( statement=StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinNext1(value=ExpressionTempVariableRef( variable=tmp_iter_variable.makeReference(provider), source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)), exception_name="StopIteration", handler_body=handler_body, source_ref=source_ref), buildAssignmentStatements( provider=provider, node=node.target, source=ExpressionTempVariableRef( variable=tmp_value_variable.makeReference(provider), source_ref=source_ref), source_ref=source_ref)) statements += (buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref), ) loop_body = makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref) if else_block is not None: statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_break_indicator_variable.makeReference( provider), source_ref=source_ref), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=source_ref) ] else: statements = [] cleanup_statements = ( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_value_variable.makeReference(provider), source_ref=source_ref), tolerant=True, source_ref=source_ref.atInternal()), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference(provider), source_ref=source_ref), tolerant=False, source_ref=source_ref.atInternal())) statements += [ # First create the iterator and store it. StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_iter_variable.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinIter1( value=source, source_ref=source.getSourceReference()), source_ref=source_ref), StatementTryFinally(tried=makeStatementsSequenceFromStatement( statement=StatementLoop(body=loop_body, source_ref=source_ref)), final=StatementsSequence( statements=cleanup_statements, source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal()) ] if else_block is not None: statements += [ StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_break_indicator_variable.makeReference( provider), source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=else_block, no_branch=None, source_ref=source_ref) ] return StatementsSequence(statements=statements, source_ref=source_ref)
def buildPrintNode(provider, node, source_ref): # "print" statements, should only occur with Python2. if node.dest is not None: temp_scope = provider.allocateTempScope("print") tmp_target_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="target") target_default_statement = StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), source=ExpressionImportModuleHard(module_name="sys", import_name="stdout", source_ref=source_ref), source_ref=source_ref) statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), source=buildNode(provider=provider, node=node.dest, source_ref=source_ref), source_ref=source_ref), StatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=None, source_ref=source_ref), source_ref=source_ref), yes_branch=makeStatementsSequenceFromStatement( statement=target_default_statement), no_branch=None, source_ref=source_ref) ] values = buildNodeList(provider=provider, nodes=node.values, source_ref=source_ref) if node.dest is not None: print_statements = [ StatementPrintValue(dest=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), value=value, source_ref=source_ref) for value in values ] if node.nl: print_statements.append( StatementPrintNewline(dest=ExpressionTempVariableRef( variable=tmp_target_variable, source_ref=source_ref), source_ref=source_ref)) statements.append( makeTryFinallyStatement(provider=provider, tried=print_statements, final=StatementReleaseVariable( variable=tmp_target_variable, source_ref=source_ref), source_ref=source_ref)) else: statements = [ StatementPrintValue(dest=None, value=value, source_ref=source_ref) for value in values ] if node.nl: statements.append( StatementPrintNewline(dest=None, source_ref=source_ref)) return makeStatementsSequenceFromStatements(*statements)
def buildAsyncFunctionNode(provider, node, source_ref): # We are creating a function here that creates coroutine objects, with # many details each, pylint: disable=R0914 assert getKind(node) == "AsyncFunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) _function_kind, flags, _written_variables, _non_local_declarations, _global_declarations = \ detectFunctionBodyKind( nodes = function_statement_nodes ) creator_function_body, _, code_object = buildFunctionWithParsing( provider=provider, function_kind="Coroutine", name=node.name, flags=(), function_doc=function_doc, node=node, source_ref=source_ref) function_body = ExpressionCoroutineObjectBody( provider=creator_function_body, name=node.name, flags=flags, source_ref=source_ref) decorators = buildNodeList(provider=provider, nodes=reversed(node.decorator_list), source_ref=source_ref) defaults = buildNodeList(provider=provider, nodes=node.args.defaults, source_ref=source_ref) function_statements_body = buildFrameNode(provider=function_body, nodes=function_statement_nodes, code_object=code_object, source_ref=source_ref) function_statements_body = _insertFinalReturnStatement( function_statements_body=function_statements_body, return_class=StatementGeneratorReturn, source_ref=source_ref) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement=function_statements_body) function_body.setBody(function_statements_body) annotations = buildParameterAnnotations(provider, node, source_ref) kw_defaults = buildParameterKwDefaults(provider=provider, node=node, function_body=creator_function_body, source_ref=source_ref) creator_function_body.setBody( makeStatementsSequenceFromStatement( statement=StatementReturn(expression=ExpressionMakeCoroutineObject( coroutine_ref=ExpressionFunctionRef( function_body=function_body, source_ref=source_ref), code_object=code_object, source_ref=source_ref), source_ref=source_ref))) function_creation = ExpressionFunctionCreation( function_ref=ExpressionFunctionRef(function_body=creator_function_body, source_ref=source_ref), code_object=code_object, defaults=defaults, kw_defaults=kw_defaults, annotations=annotations, source_ref=source_ref) decorated_function = function_creation for decorator in decorators: decorated_function = ExpressionCallNoKeywords( called=decorator, args=ExpressionMakeTuple(elements=(decorated_function, ), source_ref=source_ref), source_ref=decorator.getSourceReference()) result = StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef(variable_name=mangleName( node.name, provider), source_ref=source_ref), source=decorated_function, source_ref=source_ref) function_body.qualname_setup = result.getTargetVariableRef() return result
def convertFunctionCallToOutline(provider, function_ref, values): # This has got to have pretty man details, pylint: disable=too-many-locals function_body = function_ref.getFunctionBody() call_source_ref = function_ref.getSourceReference() function_source_ref = function_body.getSourceReference() outline_body = ExpressionOutlineBody(provider=provider, name="inline", source_ref=function_source_ref) clone = function_body.getBody().makeClone() temp_scope = outline_body.getOutlineTempScope() translation = {} for variable in function_body.getLocalVariables(): # TODO: Later we should be able to do that too. assert variable.isSharedTechnically() is False new_variable = outline_body.allocateTempVariable( temp_scope=temp_scope, name=variable.getName()) # TODO: Lets update all at once maybe, it would take less visits. updateVariableUsage(clone, old_variable=variable, new_variable=new_variable) translation[variable.getName()] = new_variable statements = [] if function_body.isExpressionClassBody(): argument_names = () else: argument_names = function_body.getParameters().getParameterNames() assert len(argument_names) == len(values), (argument_names, values) for argument_name, value in zip(argument_names, values): statements.append( StatementAssignmentVariable( variable=translation[argument_name], source=value, source_ref=call_source_ref, )) body = makeStatementsSequence(statements=(statements, clone), allow_none=False, source_ref=function_source_ref) auto_releases = function_body.getFunctionVariablesWithAutoReleases() if auto_releases: releases = [ StatementReleaseVariable(variable=variable, source_ref=function_source_ref) for variable in auto_releases ] body = makeTryFinallyStatement( provider=outline_body, tried=body, final=releases, source_ref=function_source_ref, ) outline_body.setBody(body) return outline_body
def buildImportFromNode(provider, node, source_ref): # "from .. import .." statements. This may trigger a star import, or # multiple names being looked up from the given module variable name. # This is pretty complex, pylint: disable=too-many-branches,too-many-locals module_name = node.module if node.module is not None else "" level = node.level # Use default level under some circumstances. if level == -1: level = None elif level == 0 and not _future_specs[-1].isAbsoluteImport(): level = None if level is not None: level = makeConstantRefNode(level, source_ref, True) # Importing from "__future__" module may enable flags to the parser, # that we need to know about, handle that. if module_name == "__future__": _handleFutureImport(provider, node, source_ref) target_names = [] import_names = [] # Mapping imported "fromlist" to assigned "fromlist" if any, handling the # star case as well. for import_desc in node.names: object_name, local_name = import_desc.name, import_desc.asname if object_name == '*': target_names.append(None) assert local_name is None else: target_names.append( local_name if local_name is not None else object_name) import_names.append(object_name) # Star imports get special treatment. if None in target_names: # More than "*" is a syntax error in Python, need not care about this at # all, it's only allowed value for import list in this case. assert target_names == [None] # Python3 made it so that these can only occur on the module level, # so this a syntax error if not there. For Python2 it is OK to # occur everywhere though. if not provider.isCompiledPythonModule() and python_version >= 300: raiseSyntaxError("import * only allowed at module level", source_ref.atColumnNumber(node.col_offset)) if provider.isCompiledPythonModule(): import_globals = ExpressionBuiltinGlobals(source_ref) import_locals = ExpressionBuiltinGlobals(source_ref) else: import_globals = ExpressionBuiltinGlobals(source_ref) import_locals = makeConstantRefNode({}, source_ref, True) return StatementImportStar(module_import=ExpressionBuiltinImport( name=makeConstantRefNode(module_name, source_ref, True), globals_arg=import_globals, locals_arg=import_locals, fromlist=makeConstantRefNode(('*', ), source_ref, True), level=level, source_ref=source_ref), source_ref=source_ref) else: def makeImportName(import_name): if module_name == "__future__": # Make "__future__" imports tie hard immediately, they cannot be # any other way. return ExpressionImportModuleHard(module_name="__future__", import_name=import_name, source_ref=source_ref) else: # Refer to be module, or a clone of the reference if need be. return ExpressionImportName(module=imported_from_module, import_name=import_name, source_ref=source_ref) imported_from_module = ExpressionBuiltinImport( name=makeConstantRefNode(module_name, source_ref, True), globals_arg=ExpressionBuiltinGlobals(source_ref), locals_arg=makeConstantRefNode(None, source_ref, True), fromlist=makeConstantRefNode(tuple(import_names), source_ref, True), level=level, source_ref=source_ref) # If we have multiple names to import, consider each. multi_names = len(target_names) > 1 statements = [] if multi_names: tmp_import_from = provider.allocateTempVariable( temp_scope=provider.allocateTempScope("import_from"), name="module") statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_import_from, source_ref=source_ref), source=imported_from_module, source_ref=source_ref)) imported_from_module = ExpressionTempVariableRef( variable=tmp_import_from, source_ref=source_ref) import_statements = [] first = True for target_name, import_name in zip(target_names, import_names): # Make a clone of the variable reference, if we are going to use # another one. if not first: imported_from_module = imported_from_module.makeClone() first = False import_statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name=mangleName(target_name, provider), source_ref=source_ref), source=makeImportName(import_name=import_name, ), source_ref=source_ref)) # Release the temporary module value as well. if multi_names: statements.append( makeTryFinallyStatement(provider=provider, tried=import_statements, final=(StatementReleaseVariable( variable=tmp_import_from, source_ref=source_ref), ), source_ref=source_ref)) else: statements.extend(import_statements) # Note: Each import is sequential. It can succeed, and the failure of a # later one is not undoing previous ones. We can therefore have a # sequence of imports that each only import one thing therefore. return StatementsSequence(statements=mergeStatements(statements), source_ref=source_ref)
def buildParseTree(provider, source_code, source_ref, is_module, is_main): # There are a bunch of branches here, mostly to deal with version # differences for module default variables. body = parseSourceCodeToAst(source_code=source_code, filename=source_ref.getFilename(), line_offset=source_ref.getLineNumber() - 1) body, doc = extractDocFromBody(body) result = buildStatementsNode(provider=provider, nodes=body, source_ref=source_ref) checkFutureImportsOnlyAtStart(body) internal_source_ref = source_ref.atInternal() statements = [] if is_module: # Add import of "site" module of main programs visibly in the node tree, # so recursion and optimization can pick it up, checking its effects. if is_main and "no_site" not in Options.getPythonFlags(): for path_imported_name in getPthImportedPackages(): statements.append( StatementExpressionOnly(expression=ExpressionImportModule( module_name=path_imported_name, import_list=(), level=0, source_ref=source_ref, ), source_ref=source_ref)) statements.append( StatementExpressionOnly(expression=ExpressionImportModule( module_name="site", import_list=(), level=0, source_ref=source_ref, ), source_ref=source_ref)) statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__doc__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=doc, source_ref=internal_source_ref, user_provided=True), source_ref=internal_source_ref)) statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__file__", source_ref=internal_source_ref), source=ExpressionModuleFileAttributeRef( source_ref=internal_source_ref, ), source_ref=internal_source_ref)) if provider.isCompiledPythonPackage(): # This assigns "__path__" value. statements.append(createPathAssignment(internal_source_ref)) if python_version >= 300: statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__cached__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=None, source_ref=internal_source_ref, user_provided=True), source_ref=internal_source_ref)) if python_version >= 330: # For Python3.3, it's set for both packages and non-packages. statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__package__", source_ref=internal_source_ref), source=ExpressionConstantRef( constant=provider.getFullName() if provider.isCompiledPythonPackage() else provider.getPackage(), source_ref=internal_source_ref, user_provided=True), source_ref=internal_source_ref)) needs__initializing__ = not provider.isMainModule() and \ (python_version >= 330 and python_version < 340) if needs__initializing__: # Set "__initializing__" at the beginning to True statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__initializing__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=True, source_ref=internal_source_ref, user_provided=True), source_ref=internal_source_ref)) # Now the module body if there is any at all. if result is not None: statements.extend(result.getStatements()) if needs__initializing__: # Set "__initializing__" at the end to False statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetVariableRef( variable_name="__initializing__", source_ref=internal_source_ref), source=ExpressionConstantRef(constant=False, source_ref=internal_source_ref, user_provided=True), source_ref=internal_source_ref)) if is_module: return makeModuleFrame(module=provider, statements=statements, source_ref=source_ref) else: assert False
def buildListContractionNode(provider, node, source_ref): # List contractions are dealt with by general code. if Utils.python_version < 300: temp_scope = provider.allocateTempScope("listcontr") outer_iter_var = provider.allocateTempVariable(temp_scope=temp_scope, name="listcontr_iter") outer_iter_ref = ExpressionTempVariableRef(variable=outer_iter_var, source_ref=source_ref) container_tmp = provider.allocateTempVariable(temp_scope=temp_scope, name="listcontr_result") statements, del_statements = _buildContractionBodyNode( provider=provider, node=node, emit_class=ExpressionListOperationAppend, start_value=ExpressionConstantRef(constant=[], source_ref=source_ref), outer_iter_ref=outer_iter_ref, container_tmp=container_tmp, temp_scope=temp_scope, assign_provider=True, source_ref=source_ref, function_body=provider) statements.insert( 0, StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=outer_iter_var, source_ref=source_ref), source=ExpressionBuiltinIter1(value=buildNode( provider=provider, node=node.generators[0].iter, source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)) result = makeTryFinallyExpression(expression=ExpressionTempVariableRef( variable=container_tmp, source_ref=source_ref), tried=statements, final=del_statements, source_ref=source_ref) final = StatementsSequence(statements=( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=container_tmp, source_ref=source_ref), tolerant=True, source_ref=source_ref), StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=outer_iter_var, source_ref=source_ref), tolerant=True, source_ref=source_ref), ), source_ref=source_ref) wrapTryFinallyLater(node=result, final=final) return result return _buildContractionNode( provider=provider, node=node, name="<listcontraction>", emit_class=ExpressionListOperationAppend, start_value=ExpressionConstantRef(constant=[], source_ref=source_ref), # Note: For Python3, the list contractions no longer assign to the outer # scope. assign_provider=Utils.python_version < 300, source_ref=source_ref)
def _buildInplaceAssignSliceNode(provider, lookup_source, lower, upper, tmp_variable1, tmp_variable2, tmp_variable3, operator, expression, source_ref): # First assign the target value, lower and upper to temporary variables. statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable1.makeReference(provider), source_ref=source_ref), source=lookup_source, source_ref=source_ref) ] if lower is not None: statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable2.makeReference(provider), source_ref=source_ref), source=lower, source_ref=source_ref)) lower_ref1 = ExpressionTempVariableRef( variable=tmp_variable2.makeReference(provider), source_ref=source_ref) lower_ref2 = ExpressionTempVariableRef( variable=tmp_variable2.makeReference(provider), source_ref=source_ref) else: assert tmp_variable2 is None lower_ref1 = lower_ref2 = None if upper is not None: statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_variable3.makeReference(provider), source_ref=source_ref), source=upper, source_ref=source_ref)) upper_ref1 = ExpressionTempVariableRef( variable=tmp_variable3.makeReference(provider), source_ref=source_ref) upper_ref2 = ExpressionTempVariableRef( variable=tmp_variable3.makeReference(provider), source_ref=source_ref) else: assert tmp_variable3 is None upper_ref1 = upper_ref2 = None # Second assign the inplace result over the original value. statements.append( StatementAssignmentSlice( expression=ExpressionTempVariableRef( variable=tmp_variable1.makeReference(provider), source_ref=source_ref), lower=lower_ref1, upper=upper_ref1, source=ExpressionOperationBinaryInplace( operator=operator, left=ExpressionSliceLookup( expression=ExpressionTempVariableRef( variable=tmp_variable1.makeReference(provider), source_ref=source_ref), lower=lower_ref2, upper=upper_ref2, source_ref=source_ref), right=expression, source_ref=source_ref), source_ref=source_ref)) return statements
def buildAssignNode(provider, node, source_ref): assert len(node.targets) >= 1, source_ref # Evaluate the right hand side first, so it can get names provided # before the left hand side exists. source = buildNode(provider, node.value, source_ref) if len(node.targets) == 1: # Simple assignment case, one source, one target. return buildAssignmentStatements( provider = provider, node = node.targets[0], source = source, source_ref = source_ref ) else: # Complex assignment case, one source, but multiple targets. We keep the # source in a temporary variable, and then assign from it multiple # times. temp_scope = provider.allocateTempScope("assign_unpack") tmp_source = provider.allocateTempVariable( temp_scope = temp_scope, name = "assign_source" ) statements = [ StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_source, source_ref = source_ref ), source = source, source_ref = source_ref ) ] for target in node.targets: statements.append( buildAssignmentStatements( provider = provider, node = target, source = ExpressionTempVariableRef( variable = tmp_source, source_ref = source_ref ), source_ref = source_ref ) ) return makeTryFinallyStatement( provider = provider, tried = statements, final = StatementReleaseVariable( variable = tmp_source, source_ref = source_ref ), 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, pylint: disable=R0914 if kind == "Name": variable_ref = detail return StatementAssignmentVariable(variable_ref=variable_ref, 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 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") statements = [ StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=source_iter_var.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinIter1(value=source, source_ref=source_ref), source_ref=source_ref) ] element_vars = [ provider.allocateTempVariable(temp_scope=temp_scope, name="element_%d" % (element_index + 1)) for element_index in range(len(detail)) ] starred = False for element_index, element in enumerate(detail): element_var = element_vars[element_index] if element[0] != "Starred": statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=element_var.makeReference(provider), source_ref=source_ref), source=ExpressionSpecialUnpack( value=ExpressionTempVariableRef( variable=source_iter_var.makeReference( provider), source_ref=source_ref), count=element_index + 1, source_ref=source_ref), source_ref=source_ref)) else: starred = True statements.append( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=element_var.makeReference(provider), source_ref=source_ref), source=ExpressionBuiltinList( value=ExpressionTempVariableRef( variable=source_iter_var.makeReference( provider), source_ref=source_ref), source_ref=source_ref), source_ref=source_ref)) if not starred: statements.append( StatementSpecialUnpackCheck(iterator=ExpressionTempVariableRef( variable=source_iter_var.makeReference(provider), source_ref=source_ref), count=len(detail), source_ref=source_ref)) 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.makeReference(provider), source_ref=source_ref), source_ref=source_ref)) final_statements = [] final_statements.append( StatementDelVariable(variable_ref=ExpressionTargetTempVariableRef( variable=source_iter_var.makeReference(provider), source_ref=source_ref), tolerant=True, source_ref=source_ref)) # TODO: In that order, or reversed. for element_var in element_vars: final_statements.append( StatementDelVariable( variable_ref=ExpressionTargetTempVariableRef( variable=element_var.makeReference(provider), source_ref=source_ref), tolerant=True, source_ref=source_ref)) return StatementTryFinally( tried=StatementsSequence(statements=statements, source_ref=source_ref), final=StatementsSequence(statements=final_statements, source_ref=source_ref), source_ref=source_ref) else: assert False, (kind, source_ref, detail)
def buildFunctionNode(provider, node, source_ref): # Functions have way too many details, pylint: disable=R0912,R0914 assert getKind(node) == "FunctionDef" function_statement_nodes, function_doc = extractDocFromBody(node) function_kind, flags, _written_variables, _non_local_declarations, _global_declarations = \ detectFunctionBodyKind( nodes = function_statement_nodes ) outer_body, function_body, code_object = buildFunctionWithParsing( provider = provider, function_kind = function_kind, name = node.name, function_doc = function_doc, flags = flags, node = node, source_ref = source_ref ) if function_kind == "Function": code_body = function_body elif function_kind == "Generator": code_body = ExpressionGeneratorObjectBody( provider = function_body, name = node.name, flags = flags, source_ref = source_ref ) for variable in function_body.getVariables(): code_body.getVariableForReference(variable.getName()) else: assert False, function_kind if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement( statement = StatementReturn( expression = ExpressionMakeGeneratorObject( generator_ref = ExpressionFunctionRef( function_body = code_body, source_ref = source_ref ), code_object = code_object, source_ref = source_ref ), source_ref = source_ref ) ) ) decorators = buildNodeList( provider = provider, nodes = reversed(node.decorator_list), source_ref = source_ref ) defaults = buildNodeList( provider = provider, nodes = node.args.defaults, source_ref = source_ref ) kw_defaults = buildParameterKwDefaults( provider = provider, node = node, function_body = function_body, source_ref = source_ref ) function_statements_body = buildFrameNode( provider = code_body, nodes = function_statement_nodes, code_object = code_object, source_ref = source_ref ) if function_kind == "Function": # TODO: Generators might have to raise GeneratorExit instead. function_statements_body = _insertFinalReturnStatement( function_statements_body = function_statements_body, return_class = StatementReturn, source_ref = source_ref ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement = function_statements_body ) code_body.setBody( function_statements_body ) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref = ExpressionFunctionRef( function_body = outer_body, source_ref = source_ref ), code_object = code_object, defaults = defaults, kw_defaults = kw_defaults, annotations = annotations, source_ref = source_ref ) # Add the "staticmethod" decorator to __new__ methods if not provided. # CPython made these optional, but secretly applies them when it does # "class __new__". We add them earlier, so our optimization will see it. if node.name == "__new__" and \ provider.isExpressionClassBody(): for decorator in decorators: if decorator.isExpressionVariableRef() and \ decorator.getVariableName() == "staticmethod": break else: decorators.append( ExpressionBuiltinRef( builtin_name = "staticmethod", source_ref = source_ref ) ) if python_version >= 360 and \ node.name == "__init_subclass__" and \ provider.isExpressionClassBody(): for decorator in decorators: if decorator.isExpressionVariableRef() and \ decorator.getVariableName() == "classmethod": break else: decorators.append( ExpressionBuiltinRef( builtin_name = "classmethod", source_ref = source_ref ) ) decorated_function = function_creation for decorator in decorators: decorated_function = ExpressionCallNoKeywords( called = decorator, args = ExpressionMakeTuple( elements = (decorated_function,), source_ref = source_ref ), source_ref = decorator.getSourceReference() ) result = StatementAssignmentVariable( variable_ref = ExpressionTargetVariableRef( variable_name = mangleName(node.name, provider), source_ref = source_ref ), source = decorated_function, source_ref = source_ref ) if python_version >= 340: function_body.qualname_setup = result.getTargetVariableRef() return result
def buildLambdaNode(provider, node, source_ref): # Many details to deal with, pylint: disable=R0914 assert getKind(node) == "Lambda" function_kind, flags, _written_variables, _non_local_declarations, _global_declarations = \ detectFunctionBodyKind( nodes = (node.body,) ) outer_body, function_body, code_object = buildFunctionWithParsing( provider = provider, function_kind = function_kind, name = "<lambda>", function_doc = None, flags = flags, node = node, source_ref = source_ref ) if function_kind == "Function": code_body = function_body else: code_body = ExpressionGeneratorObjectBody( provider = function_body, name = "<lambda>", flags = set(), source_ref = source_ref ) if function_kind == "Generator": function_body.setBody( makeStatementsSequenceFromStatement( statement = StatementReturn( expression = ExpressionMakeGeneratorObject( generator_ref = ExpressionFunctionRef( function_body = code_body, source_ref = source_ref ), code_object = code_object, source_ref = source_ref ), source_ref = source_ref ) ) ) defaults = buildNodeList(provider, node.args.defaults, source_ref) kw_defaults = buildParameterKwDefaults( provider = provider, node = node, function_body = function_body, source_ref = source_ref ) body = buildNode( provider = code_body, node = node.body, source_ref = source_ref, ) if function_kind == "Generator": if python_version < 270: tmp_return_value = code_body.allocateTempVariable( temp_scope = None, name = "yield_return" ) statements = ( StatementAssignmentVariable( variable_ref = ExpressionTargetTempVariableRef( variable = tmp_return_value, source_ref = source_ref, ), source = body, source_ref = source_ref ), StatementConditional( condition = ExpressionComparisonIsNOT( left = ExpressionTempVariableRef( variable = tmp_return_value, source_ref = source_ref, ), right = ExpressionConstantNoneRef( source_ref = source_ref ), source_ref = source_ref ), yes_branch = makeStatementsSequenceFromStatement( statement = StatementExpressionOnly( expression = ExpressionYield( expression = ExpressionTempVariableRef( variable = tmp_return_value, source_ref = source_ref, ), source_ref = source_ref ), source_ref = source_ref ) ), no_branch = None, source_ref = source_ref ) ) body = makeTryFinallyStatement( provider = provider, tried = statements, final = StatementReleaseVariable( variable = tmp_return_value, source_ref = source_ref ), source_ref = source_ref ) else: body = StatementExpressionOnly( expression = body, source_ref = source_ref ) else: body = StatementReturn( expression = body, source_ref = source_ref ) body = StatementsFrame( statements = mergeStatements( (body,) ), code_object = code_object, guard_mode = "generator" if function_kind == "Generator" else "full", source_ref = body.getSourceReference() ) body = makeStatementsSequenceFromStatement( statement = body, ) code_body.setBody(body) annotations = buildParameterAnnotations(provider, node, source_ref) return ExpressionFunctionCreation( function_ref = ExpressionFunctionRef( function_body = outer_body, source_ref = source_ref ), code_object = code_object, defaults = defaults, kw_defaults = kw_defaults, annotations = annotations, source_ref = source_ref )
def buildFunctionNode(provider, node, source_ref): assert getKind(node) == "FunctionDef" function_statements, function_doc = extractDocFromBody(node) function_body = ExpressionFunctionBody( provider = provider, name = node.name, doc = function_doc, parameters = buildParameterSpec(provider, node.name, node, source_ref), is_class = False, source_ref = source_ref ) decorators = buildNodeList( provider = provider, nodes = reversed(node.decorator_list), source_ref = source_ref ) defaults = buildNodeList( provider = provider, nodes = node.args.defaults, source_ref = source_ref ) kw_defaults = buildParameterKwDefaults( provider, node, function_body, source_ref ) function_statements_body = buildStatementsNode( provider = function_body, nodes = function_statements, frame = True, source_ref = source_ref ) if function_body.isGenerator(): # TODO: raise generator exit? pass elif function_statements_body is None: function_statements_body = makeStatementsSequenceFromStatement( statement = StatementReturn( expression = ExpressionConstantRef( constant = None, user_provided = True, source_ref = source_ref ), source_ref = source_ref ) ) elif not function_statements_body.isStatementAborting(): function_statements_body.setStatements( function_statements_body.getStatements() + ( StatementReturn( expression = ExpressionConstantRef( constant = None, user_provided = True, source_ref = source_ref ), source_ref = source_ref ), ) ) if function_statements_body.isStatementsFrame(): function_statements_body = makeStatementsSequenceFromStatement( statement = function_statements_body ) function_body.setBody( function_statements_body ) annotations = buildParameterAnnotations(provider, node, source_ref) function_creation = ExpressionFunctionCreation( function_ref = ExpressionFunctionRef( function_body, source_ref = source_ref ), defaults = defaults, kw_defaults = kw_defaults, annotations = annotations, source_ref = source_ref ) # Add the staticmethod decorator to __new__ methods if not provided. # CPython made these optional, but applies them to every class __new__. We # add them early, so our optimization will see it. if node.name == "__new__" and not decorators and \ provider.isExpressionFunctionBody() and provider.isClassDictCreation(): decorators = ( ExpressionBuiltinRef( builtin_name = "staticmethod", source_ref = source_ref ), ) decorated_function = function_creation for decorator in decorators: decorated_function = ExpressionCallNoKeywords( called = decorator, args = ExpressionMakeTuple( elements = (decorated_function,), source_ref = source_ref ), source_ref = decorator.getSourceReference() ) result = StatementAssignmentVariable( variable_ref = ExpressionTargetVariableRef( variable_name = mangleName(node.name, provider), source_ref = source_ref ), source = decorated_function, source_ref = source_ref ) if Utils.python_version >= 340: function_body.qualname_setup = result.getTargetVariableRef() return result
def onLeaveNode(self, node): if node.isStatementAssignmentVariableName(): variable_name = node.getVariableName() provider = node.provider # Classes always assign to locals dictionary except for closure # variables taken. if self._shouldUseLocalsDict(provider, variable_name): if node.subnode_source.isExpressionOperationInplace(): temp_scope = provider.allocateTempScope("class_inplace") tmp_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="value") statements = mergeStatements(statements=( StatementAssignmentVariable( variable=tmp_variable, source=node.subnode_source.getLeft(), source_ref=node.source_ref, ), makeTryFinallyStatement( provider=provider, tried=( StatementAssignmentVariable( variable=tmp_variable, source=makeExpressionOperationBinaryInplace( left=ExpressionTempVariableRef( variable=tmp_variable, source_ref=node.source_ref, ), right=node.subnode_source.getRight(), operator=node.subnode_source. getOperator(), source_ref=node.source_ref, ), source_ref=node.source_ref, ), StatementLocalsDictOperationSet( locals_scope=provider. getFunctionLocalsScope(), variable_name=variable_name, value=ExpressionTempVariableRef( variable=tmp_variable, source_ref=node.source_ref, ), source_ref=node.source_ref, ), ), final=StatementReleaseVariable( variable=tmp_variable, source_ref=node.source_ref), source_ref=node.source_ref, ), )) node.parent.replaceStatement(node, statements) else: new_node = StatementLocalsDictOperationSet( locals_scope=provider.getFunctionLocalsScope(), variable_name=variable_name, value=node.subnode_source, source_ref=node.source_ref, ) node.parent.replaceChild(node, new_node) else: variable = provider.getVariableForAssignment( variable_name=variable_name) new_node = StatementAssignmentVariable( variable=variable, source=node.subnode_source, source_ref=node.source_ref, ) variable.addVariableUser(provider) node.parent.replaceChild(node, new_node) del node.parent del node.provider elif node.isStatementDelVariableName(): variable_name = node.getVariableName() provider = node.provider if self._shouldUseLocalsDict(provider, variable_name): # Classes always assign to locals dictionary except for closure # variables taken. new_node = StatementLocalsDictOperationDel( locals_scope=provider.getFunctionLocalsScope(), variable_name=variable_name, tolerant=node.tolerant, source_ref=node.source_ref, ) else: variable = provider.getVariableForAssignment( variable_name=variable_name) new_node = StatementDelVariable( variable=variable, tolerant=node.tolerant, source_ref=node.source_ref, ) variable.addVariableUser(provider) parent = node.parent node.finalize() parent.replaceChild(node, new_node)