From 31f3c0484c94c6bd7b676178dff21d453b6ad659 Mon Sep 17 00:00:00 2001 From: bksahu Date: Wed, 4 Sep 2019 23:08:27 +0530 Subject: [PATCH] Minor fix --- Developer_Manual.rst | 37 +++++++++++++++++-- nuitka/build/include/nuitka/helpers.h | 3 ++ nuitka/build/static_src/HelpersBuiltin.c | 8 ++++- nuitka/codegen/BuiltinCodes.py | 5 +-- nuitka/codegen/Contexts.py | 1 + nuitka/nodes/BuiltinAllNodes.py | 2 ++ nuitka/nodes/BuiltinAnyNodes.py | 2 ++ nuitka/nodes/BuiltinZipNodes.py | 38 ++++++++++++++++++-- nuitka/nodes/ExceptionNodes.py | 2 ++ nuitka/nodes/ExpressionBases.py | 3 ++ nuitka/optimizations/OptimizeBuiltinCalls.py | 36 ++++++++++--------- tests/basics/BuiltinsTest.py | 2 +- 12 files changed, 112 insertions(+), 27 deletions(-) diff --git a/Developer_Manual.rst b/Developer_Manual.rst index 7221db910f..8e02a5b82c 100644 --- a/Developer_Manual.rst +++ b/Developer_Manual.rst @@ -2654,9 +2654,10 @@ Builtin ``zip`` for Python2 tmp_iter_3 = iter(tmp_arg3) except TypeError: raise TypeError("zip argument #3 must support iteration") - ... # could be more + ... + tmp_result = [] try: while 1: @@ -2669,10 +2670,42 @@ Builtin ``zip`` for Python2 ) ) except StopIteration: - pass + break return tmp_result +Builtin ``zip`` for Python3 ++++++++++++++++++++++++++++ + + +.. code-block:: python + + for x, y, z in zip(a, b, c): + ... + +.. code-block:: python + + def _zip_gen_object(a, b, c, ...): + ... + # See Python2 + ... + + # could be more + ... + while 1: + yield ( + next(tmp_iter_1), + next(tmp_iter_2), + next(tmp_iter_3), + ... + ) + except StopIteration: + break + + for x, y, z in _zip_gen_object(a, b, c): + ... + + Builtin ``map`` for Python2 +++++++++++++++++++++++++++ diff --git a/nuitka/build/include/nuitka/helpers.h b/nuitka/build/include/nuitka/helpers.h index 6be4cad8f3..0f8af09eb0 100644 --- a/nuitka/build/include/nuitka/helpers.h +++ b/nuitka/build/include/nuitka/helpers.h @@ -263,6 +263,9 @@ extern PyObject *BUILTIN_SUPER(PyObject *type, PyObject *object); // For built-in built-in all() functionality. extern PyObject *BUILTIN_ALL(PyObject *value); +// For built-in built-in zip() functionality. +extern PyObject *BUILTIN_ZIP(PyObject *value); + // The patched isinstance() functionality used for the built-in. extern int Nuitka_IsInstance(PyObject *inst, PyObject *cls); diff --git a/nuitka/build/static_src/HelpersBuiltin.c b/nuitka/build/static_src/HelpersBuiltin.c index 043e27e369..f47c00698d 100644 --- a/nuitka/build/static_src/HelpersBuiltin.c +++ b/nuitka/build/static_src/HelpersBuiltin.c @@ -24,6 +24,12 @@ * **/ +// This file is included from another C file, help IDEs to still parse it on +// its own. +#ifdef __IDE_ONLY__ +#include "nuitka/prelude.h" +#endif + static PyObject *CALL_BUILTIN_KW_ARGS(PyObject *callable, PyObject **args, char const **arg_names, int max_args) { int i = 0; @@ -262,7 +268,7 @@ NUITKA_DEFINE_BUILTIN(zip) PyObject *BUILTIN_ZIP(PyObject *value) { NUITKA_ASSIGN_BUILTIN(zip); - return CALL_FUNCTION_WITH_SINGLE_ARG(NUITKA_ACCESS_BUILTIN(zip), value); + return CALL_FUNCTION_WITH_POSARGS(NUITKA_ACCESS_BUILTIN(zip), value); } diff --git a/nuitka/codegen/BuiltinCodes.py b/nuitka/codegen/BuiltinCodes.py index fd0d21f84f..646c7109ab 100644 --- a/nuitka/codegen/BuiltinCodes.py +++ b/nuitka/codegen/BuiltinCodes.py @@ -439,14 +439,11 @@ def generateBuiltinZipCode(to_name, expression, emit, context): getTupleCreationCode( to_name=tmp_zip_args_name, - elements=expression.getValue(), + elements=expression.getValues(), emit=emit, context=context, ) - # TODO: Create BUILTIN_ZIP that passes args to - # CALL_FUNCTION_WITH_POSARGS of builtin zip. - with withObjectCodeTemporaryAssignment( to_name, "zip_value", expression, emit, context ) as value_name: diff --git a/nuitka/codegen/Contexts.py b/nuitka/codegen/Contexts.py index 38611e4aa7..13acecd089 100644 --- a/nuitka/codegen/Contexts.py +++ b/nuitka/codegen/Contexts.py @@ -637,6 +637,7 @@ def _getConstantDefaultPopulation(): # Meta path based loader. "read", "rb", + "zip", ] if python_version >= 300: diff --git a/nuitka/nodes/BuiltinAllNodes.py b/nuitka/nodes/BuiltinAllNodes.py index 092e7c93c6..2f70df9b2f 100644 --- a/nuitka/nodes/BuiltinAllNodes.py +++ b/nuitka/nodes/BuiltinAllNodes.py @@ -54,6 +54,8 @@ def computeExpression(self, trace_collection): value = self.getValue() shape = value.getTypeShape() if shape.hasShapeSlotIter() is False: + trace_collection.onExceptionRaiseExit(TypeError) + return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="all", diff --git a/nuitka/nodes/BuiltinAnyNodes.py b/nuitka/nodes/BuiltinAnyNodes.py index 975af0778f..47f320adb8 100644 --- a/nuitka/nodes/BuiltinAnyNodes.py +++ b/nuitka/nodes/BuiltinAnyNodes.py @@ -49,6 +49,8 @@ def computeExpression(self, trace_collection): value = self.getValue() shape = value.getTypeShape() if shape.hasShapeSlotIter() is False: + trace_collection.onExceptionRaiseExit(TypeError) + return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="any", diff --git a/nuitka/nodes/BuiltinZipNodes.py b/nuitka/nodes/BuiltinZipNodes.py index cff396e469..ad455cdf43 100644 --- a/nuitka/nodes/BuiltinZipNodes.py +++ b/nuitka/nodes/BuiltinZipNodes.py @@ -22,10 +22,14 @@ from nuitka.specs import BuiltinParameterSpecs from .ExpressionBases import ExpressionChildHavingBase +from .FunctionNodes import ExpressionFunctionRef +from .GeneratorNodes import ( + ExpressionGeneratorObjectBody, + ExpressionMakeGeneratorObject, + StatementGeneratorReturnNone, +) from .NodeMakingHelpers import ( - makeConstantReplacementNode, makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue, - wrapExpressionWithNodeSideEffects, ) @@ -64,3 +68,33 @@ def computeExpression(self, trace_collection): # TODO: We should have an iteration handle. # Length and values might be possible to predict # if every argument iteration handle is capable of it. + + def computeExpressionIter1(self, iter_node, trace_collection): + statements = [] + # TODO: Put re-formulation, ideally shared with Python2 + # zip here, with yield instead of appending to a list + # needs no list temporary variable of course. + + provider = self.getParentVariableProvider() + + generator_body = ExpressionGeneratorObjectBody( + provider=provider, + name="builtin_zip", + code_object=provider.getCodeObject(), + flags=set(), + source_ref=self.source_ref, + ) + + # Code generation expects this to be there. + statements.append(StatementGeneratorReturnNone(source_ref=self.source_ref)) + + generator_body.setBody() + + result = ExpressionMakeGeneratorObject( + generator_ref=ExpressionFunctionRef( + function_body=generator_body, source_ref=self.source_ref + ), + source_ref=self.source_ref, + ) + + return result, "new_expression", "Lowered zip built-in to generator." diff --git a/nuitka/nodes/ExceptionNodes.py b/nuitka/nodes/ExceptionNodes.py index 5d6690e93c..1e64481a42 100644 --- a/nuitka/nodes/ExceptionNodes.py +++ b/nuitka/nodes/ExceptionNodes.py @@ -231,6 +231,8 @@ def willRaiseException(self, exception_type): return exception_type is BaseException def computeExpression(self, trace_collection): + trace_collection.onExceptionRaiseExit(BaseException) + return self, None, None def computeExpressionDrop(self, statement, trace_collection): diff --git a/nuitka/nodes/ExpressionBases.py b/nuitka/nodes/ExpressionBases.py index 05edfa1638..35e090de87 100644 --- a/nuitka/nodes/ExpressionBases.py +++ b/nuitka/nodes/ExpressionBases.py @@ -518,6 +518,9 @@ def computeExpressionIter1(self, iter_node, trace_collection): shape = self.getTypeShape() if shape.hasShapeSlotIter() is False: + # Any exception TypeError will be raised. + trace_collection.onExceptionRaiseExit(BaseException) + return makeRaiseTypeErrorExceptionReplacementFromTemplateAndValue( template="'%s' object is not iterable", operation="iter", diff --git a/nuitka/optimizations/OptimizeBuiltinCalls.py b/nuitka/optimizations/OptimizeBuiltinCalls.py index 80941e6cc5..6891ab3f31 100644 --- a/nuitka/optimizations/OptimizeBuiltinCalls.py +++ b/nuitka/optimizations/OptimizeBuiltinCalls.py @@ -1046,26 +1046,25 @@ def wrapZipBuiltin(call_args, source_ref): ] # Try creating iterators of all zip arguments. + + # TODO: Use class derived from + # ExpressionBuiltinIter1 that takes "i" as an + # argument, and raises exceptions with the proper + # message directly. + statements += [ makeTryExceptSingleHandlerNode( - tried=makeStatementsSequence( - statements=[ - StatementAssignmentVariable( - variable=zip_iter_variable, - source=ExpressionBuiltinIter1( - value=ExpressionTempVariableRef( - variable=zip_arg_variable, source_ref=source_ref - ), - source_ref=source_ref, + tried=makeStatementsSequenceFromStatement( + StatementAssignmentVariable( + variable=zip_iter_variable, + source=ExpressionBuiltinIter1( + value=ExpressionTempVariableRef( + variable=zip_arg_variable, source_ref=source_ref ), source_ref=source_ref, - ) - for i, zip_iter_variable, zip_arg_variable in zip( - range(len(call_args)), zip_iter_variables, zip_arg_variables - ) - ], - allow_none=False, - source_ref=source_ref, + ), + source_ref=source_ref, + ) ), exception_name="TypeError", handler_body=StatementRaiseException( @@ -1082,6 +1081,9 @@ def wrapZipBuiltin(call_args, source_ref): ), source_ref=source_ref, ) + for i, zip_iter_variable, zip_arg_variable in zip( + range(len(call_args)), zip_iter_variables, zip_arg_variables + ) ] tmp_result = outline_body.allocateTempVariable( @@ -1504,7 +1506,6 @@ def divmod_extractor(node): "staticmethod": staticmethod_extractor, "classmethod": classmethod_extractor, "divmod": divmod_extractor, - "zip": zip3_extractor, } if python_version < 300: @@ -1524,6 +1525,7 @@ def divmod_extractor(node): # The Python3 range is really an xrange, use that. _dispatch_dict["range"] = xrange_extractor + _dispatch_dict["zip"] = zip3_extractor def check(): diff --git a/tests/basics/BuiltinsTest.py b/tests/basics/BuiltinsTest.py index e705ad0048..504ebb941d 100644 --- a/tests/basics/BuiltinsTest.py +++ b/tests/basics/BuiltinsTest.py @@ -628,4 +628,4 @@ def __complex__(self): zip(1, "String") except TypeError as e: print(e) -# print(zip()) +print(zip())