def buildDictionaryUnpackingArgs(provider, keys, values, source_ref): result = [] for key, value in zip(keys, values): # TODO: We could be a lot cleverer about the dictionaries for non-starred # arguments, but lets get this to work first. if key is None: result.append(buildNode(provider, value, source_ref), ) elif type(key) is str: result.append( ExpressionMakeDict(pairs=(ExpressionKeyValuePair( key=ExpressionConstantRef(constant=key, source_ref=source_ref), value=buildNode(provider, value, source_ref), source_ref=source_ref), ), source_ref=source_ref)) else: result.append( ExpressionMakeDict(pairs=(ExpressionKeyValuePair( key=buildNode(provider, key, source_ref), value=buildNode(provider, value, source_ref), source_ref=source_ref), ), source_ref=source_ref)) return result
def makeDictCreationOrConstant(keys, values, source_ref): # Create dictionary node. Tries to avoid it for constant values that are not # mutable. assert len(keys) == len(values) for key, value in zip(keys, values): if not key.isExpressionConstantRef() or not key.isKnownToBeHashable(): constant = False break if not value.isExpressionConstantRef(): constant = False break else: constant = True # Note: This would happen in optimization instead, but lets just do it # immediately to save some time. if constant: # Unless told otherwise, create the dictionary in its full size, so # that no growing occurs and the constant becomes as similar as possible # before being marshaled. result = makeConstantRefNode( constant = Constants.createConstantDict( keys = [ key.getConstant() for key in keys ], values = [ value.getConstant() for value in values ] ), user_provided = True, source_ref = source_ref ) else: result = ExpressionMakeDict( pairs = [ ExpressionKeyValuePair( key = key, value = value, source_ref = key.getSourceReference() ) for key, value in zip(keys, values) ], source_ref = source_ref ) if values: result.setCompatibleSourceReference( source_ref = values[-1].getCompatibleSourceReference() ) return result
def computeExpression(self, constraint_collection): pos_arg = self.getPositionalArgument() pairs = self.getNamedArgumentPairs() if pos_arg is None: new_node = ExpressionMakeDict(pairs=self.getNamedArgumentPairs(), source_ref=self.source_ref) # This cannot raise anymore than its arguments, as the keys will # be known as hashable, due to being Python parameters before. return ( new_node, "new_expression", "Replace 'dict' built-in call dictionary creation from arguments." ) pos_iteration_length = pos_arg.getIterationLength() if pos_iteration_length == 0: new_node = ExpressionMakeDict(pairs=self.getNamedArgumentPairs(), source_ref=self.source_ref) # Maintain potential side effects from the positional arguments. new_node = wrapExpressionWithNodeSideEffects( old_node=ExpressionBuiltinIter1(value=pos_arg, source_ref=self.source_ref), new_node=new_node) # Just in case, the iteration may do that. if pos_arg.mayRaiseExceptionIter(BaseException): constraint_collection.onExceptionRaiseExit(BaseException) return ( new_node, "new_expression", "Replace 'dict' built-in call dictionary creation from arguments." ) if pos_iteration_length is not None and \ pos_iteration_length + len(pairs) < 256 and \ self.hasOnlyConstantArguments(): if pos_arg is not None: pos_args = (pos_arg, ) else: pos_args = None return constraint_collection.getCompileTimeComputationResult( node=self, computation=lambda: builtin_dict_spec.simulateCall( (pos_args, self.getNamedArgumentPairs())), description="Replace 'dict' call with constant arguments.") else: constraint_collection.onExceptionRaiseExit(BaseException) return self, None, None
def buildDictionaryUnpacking(provider, node, source_ref): helper_args = [] for key, value in zip(node.keys, node.values): # TODO: We could be a lot cleverer about the dictionaries for non-starred # arguments, but lets get this to work first. if key is None: helper_args.append(buildNode(provider, value, source_ref), ) else: helper_args.append( ExpressionMakeDict( pairs=(ExpressionKeyValuePair( key=buildNode(provider, key, source_ref), value=buildNode(provider, value, source_ref), source_ref=source_ref), ), source_ref=source_ref, lazy_order=False, )) result = ExpressionFunctionCall( function=ExpressionFunctionCreation(function_ref=ExpressionFunctionRef( function_body=getDictUnpackingHelper(), source_ref=source_ref), defaults=(), kw_defaults=None, annotations=None, source_ref=source_ref), values=(ExpressionMakeTuple(helper_args, source_ref), ), source_ref=source_ref, ) result.setCompatibleSourceReference( helper_args[-1].getCompatibleSourceReference()) return result
def computeExpression(self, constraint_collection): pos_arg = self.getPositionalArgument() if self.hasOnlyConstantArguments(): if pos_arg is not None: pos_args = (pos_arg, ) elif python_version >= 340: # Doing this here, because calling dict built-in apparently # mutates existing dictionaries in Python 3.4 result = {} for pair in reversed(self.getNamedArgumentPairs()): arg_name = pair.getKey().getCompileTimeConstant() arg_value = pair.getValue().getCompileTimeConstant() result[arg_name] = arg_value new_node = makeConstantReplacementNode(constant=result, node=self) return new_node, "new_expression", "Replace 'dict' built-in call with constant arguments." else: pos_args = None return constraint_collection.getCompileTimeComputationResult( node=self, computation=lambda: builtin_dict_spec.simulateCall( (pos_args, self.getNamedArgumentPairs())), description="Replace 'dict' call with constant arguments.") elif pos_arg is None: new_node = ExpressionMakeDict(pairs=self.getNamedArgumentPairs(), lazy_order=False, source_ref=self.source_ref) # This cannot raise anymore than its arguments, as the keys will # be known as hashable, due to being Python parameters before. return ( new_node, "new_expression", "Replace 'dict' built-in call dictionary creation from arguments." ) elif pos_arg.getIterationLength() == 0: new_node = ExpressionMakeDict(pairs=self.getNamedArgumentPairs(), lazy_order=False, source_ref=self.source_ref) # Maintain potential side effects from the positional arguments. new_node = wrapExpressionWithNodeSideEffects( old_node=ExpressionBuiltinIter1(value=pos_arg, source_ref=self.source_ref), new_node=new_node) # Just in case, the iteration may do that. if pos_arg.mayRaiseExceptionIter(BaseException): constraint_collection.onExceptionRaiseExit(BaseException) return ( new_node, "new_expression", "Replace 'dict' built-in call dictionary creation from arguments." ) else: constraint_collection.onExceptionRaiseExit(BaseException) return self, None, None