Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Cython / Compiler / ExprNodes.py
blob74e1004fd4b4a812a6b841ab26c78bff86bbd6ff
2 # Parse tree nodes for expressions
5 import cython
6 cython.declare(error=object, warning=object, warn_once=object, InternalError=object,
7 CompileError=object, UtilityCode=object, TempitaUtilityCode=object,
8 StringEncoding=object, operator=object,
9 Naming=object, Nodes=object, PyrexTypes=object, py_object_type=object,
10 list_type=object, tuple_type=object, set_type=object, dict_type=object,
11 unicode_type=object, str_type=object, bytes_type=object, type_type=object,
12 Builtin=object, Symtab=object, Utils=object, find_coercion_error=object,
13 debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object,
14 bytearray_type=object, slice_type=object)
16 import sys
17 import copy
18 import operator
20 from Errors import error, warning, warn_once, InternalError, CompileError
21 from Errors import hold_errors, release_errors, held_errors, report_error
22 from Code import UtilityCode, TempitaUtilityCode
23 import StringEncoding
24 import Naming
25 import Nodes
26 from Nodes import Node
27 import PyrexTypes
28 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
29 unspecified_type
30 import TypeSlots
31 from Builtin import list_type, tuple_type, set_type, dict_type, type_type, \
32 unicode_type, str_type, bytes_type, bytearray_type, basestring_type, slice_type
33 import Builtin
34 import Symtab
35 from Cython import Utils
36 from Annotate import AnnotationItem
37 from Cython.Compiler import Future
38 from Cython.Debugging import print_call_chain
39 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
40 debug_coercion
42 try:
43 from __builtin__ import basestring
44 except ImportError:
45 basestring = str # Python 3
47 try:
48 from builtins import bytes
49 except ImportError:
50 bytes = str # Python 2
53 class NotConstant(object):
54 _obj = None
56 def __new__(cls):
57 if NotConstant._obj is None:
58 NotConstant._obj = super(NotConstant, cls).__new__(cls)
60 return NotConstant._obj
62 def __repr__(self):
63 return "<NOT CONSTANT>"
65 not_a_constant = NotConstant()
66 constant_value_not_set = object()
68 # error messages when coercing from key[0] to key[1]
69 coercion_error_dict = {
70 # string related errors
71 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
72 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
73 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects only support coercion to Py_UNICODE*.",
74 (Builtin.unicode_type, PyrexTypes.c_uchar_ptr_type) : "Unicode objects only support coercion to Py_UNICODE*.",
75 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
76 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
77 (Builtin.bytes_type, Builtin.basestring_type) : "Cannot convert 'bytes' object to basestring implicitly. This is not portable to Py3.",
78 (Builtin.bytes_type, PyrexTypes.c_py_unicode_ptr_type) : "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.",
79 (Builtin.basestring_type, Builtin.bytes_type) : "Cannot convert 'basestring' object to bytes implicitly. This is not portable.",
80 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
81 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
82 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
83 (Builtin.str_type, PyrexTypes.c_uchar_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
84 (Builtin.str_type, PyrexTypes.c_py_unicode_ptr_type) : "'str' objects do not support coercion to C types (use 'unicode'?).",
85 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
86 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
89 def find_coercion_error(type_tuple, default, env):
90 err = coercion_error_dict.get(type_tuple)
91 if err is None:
92 return default
93 elif ((PyrexTypes.c_char_ptr_type in type_tuple or PyrexTypes.c_uchar_ptr_type in type_tuple)
94 and env.directives['c_string_encoding']):
95 if type_tuple[1].is_pyobject:
96 return default
97 elif env.directives['c_string_encoding'] in ('ascii', 'default'):
98 return default
99 else:
100 return "'%s' objects do not support coercion to C types with non-ascii or non-default c_string_encoding" % type_tuple[0].name
101 else:
102 return err
105 def default_str_type(env):
106 return {
107 'bytes': bytes_type,
108 'bytearray': bytearray_type,
109 'str': str_type,
110 'unicode': unicode_type
111 }.get(env.directives['c_string_type'])
114 def check_negative_indices(*nodes):
116 Raise a warning on nodes that are known to have negative numeric values.
117 Used to find (potential) bugs inside of "wraparound=False" sections.
119 for node in nodes:
120 if (node is None
121 or not isinstance(node.constant_result, (int, float, long))):
122 continue
123 if node.constant_result < 0:
124 warning(node.pos,
125 "the result of using negative indices inside of "
126 "code sections marked as 'wraparound=False' is "
127 "undefined", level=1)
130 def infer_sequence_item_type(env, seq_node, index_node=None, seq_type=None):
131 if not seq_node.is_sequence_constructor:
132 if seq_type is None:
133 seq_type = seq_node.infer_type(env)
134 if seq_type is tuple_type:
135 # tuples are immutable => we can safely follow assignments
136 if seq_node.cf_state and len(seq_node.cf_state) == 1:
137 try:
138 seq_node = seq_node.cf_state[0].rhs
139 except AttributeError:
140 pass
141 if seq_node is not None and seq_node.is_sequence_constructor:
142 if index_node is not None and index_node.has_constant_result():
143 try:
144 item = seq_node.args[index_node.constant_result]
145 except (ValueError, TypeError, IndexError):
146 pass
147 else:
148 return item.infer_type(env)
149 # if we're lucky, all items have the same type
150 item_types = set([item.infer_type(env) for item in seq_node.args])
151 if len(item_types) == 1:
152 return item_types.pop()
153 return None
156 class ExprNode(Node):
157 # subexprs [string] Class var holding names of subexpr node attrs
158 # type PyrexType Type of the result
159 # result_code string Code fragment
160 # result_ctype string C type of result_code if different from type
161 # is_temp boolean Result is in a temporary variable
162 # is_sequence_constructor
163 # boolean Is a list or tuple constructor expression
164 # is_starred boolean Is a starred expression (e.g. '*a')
165 # saved_subexpr_nodes
166 # [ExprNode or [ExprNode or None] or None]
167 # Cached result of subexpr_nodes()
168 # use_managed_ref boolean use ref-counted temps/assignments/etc.
169 # result_is_used boolean indicates that the result will be dropped and the
170 # result_code/temp_result can safely be set to None
172 result_ctype = None
173 type = None
174 temp_code = None
175 old_temp = None # error checker for multiple frees etc.
176 use_managed_ref = True # can be set by optimisation transforms
177 result_is_used = True
179 # The Analyse Expressions phase for expressions is split
180 # into two sub-phases:
182 # Analyse Types
183 # Determines the result type of the expression based
184 # on the types of its sub-expressions, and inserts
185 # coercion nodes into the expression tree where needed.
186 # Marks nodes which will need to have temporary variables
187 # allocated.
189 # Allocate Temps
190 # Allocates temporary variables where needed, and fills
191 # in the result_code field of each node.
193 # ExprNode provides some convenience routines which
194 # perform both of the above phases. These should only
195 # be called from statement nodes, and only when no
196 # coercion nodes need to be added around the expression
197 # being analysed. In that case, the above two phases
198 # should be invoked separately.
200 # Framework code in ExprNode provides much of the common
201 # processing for the various phases. It makes use of the
202 # 'subexprs' class attribute of ExprNodes, which should
203 # contain a list of the names of attributes which can
204 # hold sub-nodes or sequences of sub-nodes.
206 # The framework makes use of a number of abstract methods.
207 # Their responsibilities are as follows.
209 # Declaration Analysis phase
211 # analyse_target_declaration
212 # Called during the Analyse Declarations phase to analyse
213 # the LHS of an assignment or argument of a del statement.
214 # Nodes which cannot be the LHS of an assignment need not
215 # implement it.
217 # Expression Analysis phase
219 # analyse_types
220 # - Call analyse_types on all sub-expressions.
221 # - Check operand types, and wrap coercion nodes around
222 # sub-expressions where needed.
223 # - Set the type of this node.
224 # - If a temporary variable will be required for the
225 # result, set the is_temp flag of this node.
227 # analyse_target_types
228 # Called during the Analyse Types phase to analyse
229 # the LHS of an assignment or argument of a del
230 # statement. Similar responsibilities to analyse_types.
232 # target_code
233 # Called by the default implementation of allocate_target_temps.
234 # Should return a C lvalue for assigning to the node. The default
235 # implementation calls calculate_result_code.
237 # check_const
238 # - Check that this node and its subnodes form a
239 # legal constant expression. If so, do nothing,
240 # otherwise call not_const.
242 # The default implementation of check_const
243 # assumes that the expression is not constant.
245 # check_const_addr
246 # - Same as check_const, except check that the
247 # expression is a C lvalue whose address is
248 # constant. Otherwise, call addr_not_const.
250 # The default implementation of calc_const_addr
251 # assumes that the expression is not a constant
252 # lvalue.
254 # Code Generation phase
256 # generate_evaluation_code
257 # - Call generate_evaluation_code for sub-expressions.
258 # - Perform the functions of generate_result_code
259 # (see below).
260 # - If result is temporary, call generate_disposal_code
261 # on all sub-expressions.
263 # A default implementation of generate_evaluation_code
264 # is provided which uses the following abstract methods:
266 # generate_result_code
267 # - Generate any C statements necessary to calculate
268 # the result of this node from the results of its
269 # sub-expressions.
271 # calculate_result_code
272 # - Should return a C code fragment evaluating to the
273 # result. This is only called when the result is not
274 # a temporary.
276 # generate_assignment_code
277 # Called on the LHS of an assignment.
278 # - Call generate_evaluation_code for sub-expressions.
279 # - Generate code to perform the assignment.
280 # - If the assignment absorbed a reference, call
281 # generate_post_assignment_code on the RHS,
282 # otherwise call generate_disposal_code on it.
284 # generate_deletion_code
285 # Called on an argument of a del statement.
286 # - Call generate_evaluation_code for sub-expressions.
287 # - Generate code to perform the deletion.
288 # - Call generate_disposal_code on all sub-expressions.
292 is_sequence_constructor = 0
293 is_string_literal = 0
294 is_attribute = 0
295 is_subscript = 0
297 saved_subexpr_nodes = None
298 is_temp = 0
299 is_target = 0
300 is_starred = 0
302 constant_result = constant_value_not_set
304 # whether this node with a memoryview type should be broadcast
305 memslice_broadcast = False
307 child_attrs = property(fget=operator.attrgetter('subexprs'))
309 def not_implemented(self, method_name):
310 print_call_chain(method_name, "not implemented") ###
311 raise InternalError(
312 "%s.%s not implemented" %
313 (self.__class__.__name__, method_name))
315 def is_lvalue(self):
316 return 0
318 def is_addressable(self):
319 return self.is_lvalue() and not self.type.is_memoryviewslice
321 def is_ephemeral(self):
322 # An ephemeral node is one whose result is in
323 # a Python temporary and we suspect there are no
324 # other references to it. Certain operations are
325 # disallowed on such values, since they are
326 # likely to result in a dangling pointer.
327 return self.type.is_pyobject and self.is_temp
329 def subexpr_nodes(self):
330 # Extract a list of subexpression nodes based
331 # on the contents of the subexprs class attribute.
332 nodes = []
333 for name in self.subexprs:
334 item = getattr(self, name)
335 if item is not None:
336 if type(item) is list:
337 nodes.extend(item)
338 else:
339 nodes.append(item)
340 return nodes
342 def result(self):
343 if self.is_temp:
344 return self.temp_code
345 else:
346 return self.calculate_result_code()
348 def result_as(self, type = None):
349 # Return the result code cast to the specified C type.
350 if (self.is_temp and self.type.is_pyobject and
351 type != py_object_type):
352 # Allocated temporaries are always PyObject *, which may not
353 # reflect the actual type (e.g. an extension type)
354 return typecast(type, py_object_type, self.result())
355 return typecast(type, self.ctype(), self.result())
357 def py_result(self):
358 # Return the result code cast to PyObject *.
359 return self.result_as(py_object_type)
361 def ctype(self):
362 # Return the native C type of the result (i.e. the
363 # C type of the result_code expression).
364 return self.result_ctype or self.type
366 def get_constant_c_result_code(self):
367 # Return the constant value of this node as a result code
368 # string, or None if the node is not constant. This method
369 # can be called when the constant result code is required
370 # before the code generation phase.
372 # The return value is a string that can represent a simple C
373 # value, a constant C name or a constant C expression. If the
374 # node type depends on Python code, this must return None.
375 return None
377 def calculate_constant_result(self):
378 # Calculate the constant compile time result value of this
379 # expression and store it in ``self.constant_result``. Does
380 # nothing by default, thus leaving ``self.constant_result``
381 # unknown. If valid, the result can be an arbitrary Python
382 # value.
384 # This must only be called when it is assured that all
385 # sub-expressions have a valid constant_result value. The
386 # ConstantFolding transform will do this.
387 pass
389 def has_constant_result(self):
390 return self.constant_result is not constant_value_not_set and \
391 self.constant_result is not not_a_constant
393 def compile_time_value(self, denv):
394 # Return value of compile-time expression, or report error.
395 error(self.pos, "Invalid compile-time expression")
397 def compile_time_value_error(self, e):
398 error(self.pos, "Error in compile-time expression: %s: %s" % (
399 e.__class__.__name__, e))
401 # ------------- Declaration Analysis ----------------
403 def analyse_target_declaration(self, env):
404 error(self.pos, "Cannot assign to or delete this")
406 # ------------- Expression Analysis ----------------
408 def analyse_const_expression(self, env):
409 # Called during the analyse_declarations phase of a
410 # constant expression. Analyses the expression's type,
411 # checks whether it is a legal const expression,
412 # and determines its value.
413 node = self.analyse_types(env)
414 node.check_const()
415 return node
417 def analyse_expressions(self, env):
418 # Convenience routine performing both the Type
419 # Analysis and Temp Allocation phases for a whole
420 # expression.
421 return self.analyse_types(env)
423 def analyse_target_expression(self, env, rhs):
424 # Convenience routine performing both the Type
425 # Analysis and Temp Allocation phases for the LHS of
426 # an assignment.
427 return self.analyse_target_types(env)
429 def analyse_boolean_expression(self, env):
430 # Analyse expression and coerce to a boolean.
431 node = self.analyse_types(env)
432 bool = node.coerce_to_boolean(env)
433 return bool
435 def analyse_temp_boolean_expression(self, env):
436 # Analyse boolean expression and coerce result into
437 # a temporary. This is used when a branch is to be
438 # performed on the result and we won't have an
439 # opportunity to ensure disposal code is executed
440 # afterwards. By forcing the result into a temporary,
441 # we ensure that all disposal has been done by the
442 # time we get the result.
443 node = self.analyse_types(env)
444 return node.coerce_to_boolean(env).coerce_to_simple(env)
446 # --------------- Type Inference -----------------
448 def type_dependencies(self, env):
449 # Returns the list of entries whose types must be determined
450 # before the type of self can be inferred.
451 if hasattr(self, 'type') and self.type is not None:
452 return ()
453 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
455 def infer_type(self, env):
456 # Attempt to deduce the type of self.
457 # Differs from analyse_types as it avoids unnecessary
458 # analysis of subexpressions, but can assume everything
459 # in self.type_dependencies() has been resolved.
460 if hasattr(self, 'type') and self.type is not None:
461 return self.type
462 elif hasattr(self, 'entry') and self.entry is not None:
463 return self.entry.type
464 else:
465 self.not_implemented("infer_type")
467 def nonlocally_immutable(self):
468 # Returns whether this variable is a safe reference, i.e.
469 # can't be modified as part of globals or closures.
470 return self.is_literal or self.is_temp or self.type.is_array or self.type.is_cfunction
472 # --------------- Type Analysis ------------------
474 def analyse_as_module(self, env):
475 # If this node can be interpreted as a reference to a
476 # cimported module, return its scope, else None.
477 return None
479 def analyse_as_type(self, env):
480 # If this node can be interpreted as a reference to a
481 # type, return that type, else None.
482 return None
484 def analyse_as_extension_type(self, env):
485 # If this node can be interpreted as a reference to an
486 # extension type or builtin type, return its type, else None.
487 return None
489 def analyse_types(self, env):
490 self.not_implemented("analyse_types")
492 def analyse_target_types(self, env):
493 return self.analyse_types(env)
495 def nogil_check(self, env):
496 # By default, any expression based on Python objects is
497 # prevented in nogil environments. Subtypes must override
498 # this if they can work without the GIL.
499 if self.type and self.type.is_pyobject:
500 self.gil_error()
502 def gil_assignment_check(self, env):
503 if env.nogil and self.type.is_pyobject:
504 error(self.pos, "Assignment of Python object not allowed without gil")
506 def check_const(self):
507 self.not_const()
508 return False
510 def not_const(self):
511 error(self.pos, "Not allowed in a constant expression")
513 def check_const_addr(self):
514 self.addr_not_const()
515 return False
517 def addr_not_const(self):
518 error(self.pos, "Address is not constant")
520 # ----------------- Result Allocation -----------------
522 def result_in_temp(self):
523 # Return true if result is in a temporary owned by
524 # this node or one of its subexpressions. Overridden
525 # by certain nodes which can share the result of
526 # a subnode.
527 return self.is_temp
529 def target_code(self):
530 # Return code fragment for use as LHS of a C assignment.
531 return self.calculate_result_code()
533 def calculate_result_code(self):
534 self.not_implemented("calculate_result_code")
536 # def release_target_temp(self, env):
537 # # Release temporaries used by LHS of an assignment.
538 # self.release_subexpr_temps(env)
540 def allocate_temp_result(self, code):
541 if self.temp_code:
542 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
543 type = self.type
544 if not type.is_void:
545 if type.is_pyobject:
546 type = PyrexTypes.py_object_type
547 self.temp_code = code.funcstate.allocate_temp(
548 type, manage_ref=self.use_managed_ref)
549 else:
550 self.temp_code = None
552 def release_temp_result(self, code):
553 if not self.temp_code:
554 if not self.result_is_used:
555 # not used anyway, so ignore if not set up
556 return
557 if self.old_temp:
558 raise RuntimeError("temp %s released multiple times in %s" % (
559 self.old_temp, self.__class__.__name__))
560 else:
561 raise RuntimeError("no temp, but release requested in %s" % (
562 self.__class__.__name__))
563 code.funcstate.release_temp(self.temp_code)
564 self.old_temp = self.temp_code
565 self.temp_code = None
567 # ---------------- Code Generation -----------------
569 def make_owned_reference(self, code):
571 If result is a pyobject, make sure we own a reference to it.
572 If the result is in a temp, it is already a new reference.
574 if self.type.is_pyobject and not self.result_in_temp():
575 code.put_incref(self.result(), self.ctype())
577 def make_owned_memoryviewslice(self, code):
579 Make sure we own the reference to this memoryview slice.
581 if not self.result_in_temp():
582 code.put_incref_memoryviewslice(self.result(),
583 have_gil=self.in_nogil_context)
585 def generate_evaluation_code(self, code):
586 # Generate code to evaluate this node and
587 # its sub-expressions, and dispose of any
588 # temporary results of its sub-expressions.
589 self.generate_subexpr_evaluation_code(code)
591 code.mark_pos(self.pos)
592 if self.is_temp:
593 self.allocate_temp_result(code)
595 self.generate_result_code(code)
596 if self.is_temp:
597 # If we are temp we do not need to wait until this node is disposed
598 # before disposing children.
599 self.generate_subexpr_disposal_code(code)
600 self.free_subexpr_temps(code)
602 def generate_subexpr_evaluation_code(self, code):
603 for node in self.subexpr_nodes():
604 node.generate_evaluation_code(code)
606 def generate_result_code(self, code):
607 self.not_implemented("generate_result_code")
609 def generate_disposal_code(self, code):
610 if self.is_temp:
611 if self.result():
612 if self.type.is_pyobject:
613 code.put_decref_clear(self.result(), self.ctype())
614 elif self.type.is_memoryviewslice:
615 code.put_xdecref_memoryviewslice(
616 self.result(), have_gil=not self.in_nogil_context)
617 else:
618 # Already done if self.is_temp
619 self.generate_subexpr_disposal_code(code)
621 def generate_subexpr_disposal_code(self, code):
622 # Generate code to dispose of temporary results
623 # of all sub-expressions.
624 for node in self.subexpr_nodes():
625 node.generate_disposal_code(code)
627 def generate_post_assignment_code(self, code):
628 if self.is_temp:
629 if self.type.is_pyobject:
630 code.putln("%s = 0;" % self.result())
631 elif self.type.is_memoryviewslice:
632 code.putln("%s.memview = NULL;" % self.result())
633 code.putln("%s.data = NULL;" % self.result())
634 else:
635 self.generate_subexpr_disposal_code(code)
637 def generate_assignment_code(self, rhs, code):
638 # Stub method for nodes which are not legal as
639 # the LHS of an assignment. An error will have
640 # been reported earlier.
641 pass
643 def generate_deletion_code(self, code, ignore_nonexisting=False):
644 # Stub method for nodes that are not legal as
645 # the argument of a del statement. An error
646 # will have been reported earlier.
647 pass
649 def free_temps(self, code):
650 if self.is_temp:
651 if not self.type.is_void:
652 self.release_temp_result(code)
653 else:
654 self.free_subexpr_temps(code)
656 def free_subexpr_temps(self, code):
657 for sub in self.subexpr_nodes():
658 sub.free_temps(code)
660 def generate_function_definitions(self, env, code):
661 pass
663 # ---------------- Annotation ---------------------
665 def annotate(self, code):
666 for node in self.subexpr_nodes():
667 node.annotate(code)
669 # ----------------- Coercion ----------------------
671 def coerce_to(self, dst_type, env):
672 # Coerce the result so that it can be assigned to
673 # something of type dst_type. If processing is necessary,
674 # wraps this node in a coercion node and returns that.
675 # Otherwise, returns this node unchanged.
677 # This method is called during the analyse_expressions
678 # phase of the src_node's processing.
680 # Note that subclasses that override this (especially
681 # ConstNodes) must not (re-)set their own .type attribute
682 # here. Since expression nodes may turn up in different
683 # places in the tree (e.g. inside of CloneNodes in cascaded
684 # assignments), this method must return a new node instance
685 # if it changes the type.
687 src = self
688 src_type = self.type
690 if self.check_for_coercion_error(dst_type, env):
691 return self
693 if dst_type.is_reference and not src_type.is_reference:
694 dst_type = dst_type.ref_base_type
696 if src_type.is_const:
697 src_type = src_type.const_base_type
699 if src_type.is_fused or dst_type.is_fused:
700 # See if we are coercing a fused function to a pointer to a
701 # specialized function
702 if (src_type.is_cfunction and not dst_type.is_fused and
703 dst_type.is_ptr and dst_type.base_type.is_cfunction):
705 dst_type = dst_type.base_type
707 for signature in src_type.get_all_specialized_function_types():
708 if signature.same_as(dst_type):
709 src.type = signature
710 src.entry = src.type.entry
711 src.entry.used = True
712 return self
714 if src_type.is_fused:
715 error(self.pos, "Type is not specialized")
716 else:
717 error(self.pos, "Cannot coerce to a type that is not specialized")
719 self.type = error_type
720 return self
722 if self.coercion_type is not None:
723 # This is purely for error checking purposes!
724 node = NameNode(self.pos, name='', type=self.coercion_type)
725 node.coerce_to(dst_type, env)
727 if dst_type.is_memoryviewslice:
728 import MemoryView
729 if not src.type.is_memoryviewslice:
730 if src.type.is_pyobject:
731 src = CoerceToMemViewSliceNode(src, dst_type, env)
732 elif src.type.is_array:
733 src = CythonArrayNode.from_carray(src, env).coerce_to(
734 dst_type, env)
735 elif not src_type.is_error:
736 error(self.pos,
737 "Cannot convert '%s' to memoryviewslice" %
738 (src_type,))
739 elif not MemoryView.src_conforms_to_dst(
740 src.type, dst_type, broadcast=self.memslice_broadcast):
741 if src.type.dtype.same_as(dst_type.dtype):
742 msg = "Memoryview '%s' not conformable to memoryview '%s'."
743 tup = src.type, dst_type
744 else:
745 msg = "Different base types for memoryviews (%s, %s)"
746 tup = src.type.dtype, dst_type.dtype
748 error(self.pos, msg % tup)
750 elif dst_type.is_pyobject:
751 if not src.type.is_pyobject:
752 if dst_type is bytes_type and src.type.is_int:
753 src = CoerceIntToBytesNode(src, env)
754 else:
755 src = CoerceToPyTypeNode(src, env, type=dst_type)
756 if not src.type.subtype_of(dst_type):
757 if src.constant_result is not None:
758 src = PyTypeTestNode(src, dst_type, env)
759 elif src.type.is_pyobject:
760 src = CoerceFromPyTypeNode(dst_type, src, env)
761 elif (dst_type.is_complex
762 and src_type != dst_type
763 and dst_type.assignable_from(src_type)):
764 src = CoerceToComplexNode(src, dst_type, env)
765 else: # neither src nor dst are py types
766 # Added the string comparison, since for c types that
767 # is enough, but Cython gets confused when the types are
768 # in different pxi files.
769 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
770 self.fail_assignment(dst_type)
771 return src
773 def fail_assignment(self, dst_type):
774 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
776 def check_for_coercion_error(self, dst_type, env, fail=False, default=None):
777 if fail and not default:
778 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
779 message = find_coercion_error((self.type, dst_type), default, env)
780 if message is not None:
781 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
782 return True
783 if fail:
784 self.fail_assignment(dst_type)
785 return True
786 return False
788 def coerce_to_pyobject(self, env):
789 return self.coerce_to(PyrexTypes.py_object_type, env)
791 def coerce_to_boolean(self, env):
792 # Coerce result to something acceptable as
793 # a boolean value.
795 # if it's constant, calculate the result now
796 if self.has_constant_result():
797 bool_value = bool(self.constant_result)
798 return BoolNode(self.pos, value=bool_value,
799 constant_result=bool_value)
801 type = self.type
802 if type.is_enum or type.is_error:
803 return self
804 elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float:
805 return CoerceToBooleanNode(self, env)
806 else:
807 error(self.pos, "Type '%s' not acceptable as a boolean" % type)
808 return self
810 def coerce_to_integer(self, env):
811 # If not already some C integer type, coerce to longint.
812 if self.type.is_int:
813 return self
814 else:
815 return self.coerce_to(PyrexTypes.c_long_type, env)
817 def coerce_to_temp(self, env):
818 # Ensure that the result is in a temporary.
819 if self.result_in_temp():
820 return self
821 else:
822 return CoerceToTempNode(self, env)
824 def coerce_to_simple(self, env):
825 # Ensure that the result is simple (see is_simple).
826 if self.is_simple():
827 return self
828 else:
829 return self.coerce_to_temp(env)
831 def is_simple(self):
832 # A node is simple if its result is something that can
833 # be referred to without performing any operations, e.g.
834 # a constant, local var, C global var, struct member
835 # reference, or temporary.
836 return self.result_in_temp()
838 def may_be_none(self):
839 if self.type and not (self.type.is_pyobject or
840 self.type.is_memoryviewslice):
841 return False
842 if self.has_constant_result():
843 return self.constant_result is not None
844 return True
846 def as_cython_attribute(self):
847 return None
849 def as_none_safe_node(self, message, error="PyExc_TypeError", format_args=()):
850 # Wraps the node in a NoneCheckNode if it is not known to be
851 # not-None (e.g. because it is a Python literal).
852 if self.may_be_none():
853 return NoneCheckNode(self, error, message, format_args)
854 else:
855 return self
857 @classmethod
858 def from_node(cls, node, **kwargs):
859 """Instantiate this node class from another node, properly
860 copying over all attributes that one would forget otherwise.
862 attributes = "cf_state cf_maybe_null cf_is_null constant_result".split()
863 for attr_name in attributes:
864 if attr_name in kwargs:
865 continue
866 try:
867 value = getattr(node, attr_name)
868 except AttributeError:
869 pass
870 else:
871 kwargs[attr_name] = value
872 return cls(node.pos, **kwargs)
875 class AtomicExprNode(ExprNode):
876 # Abstract base class for expression nodes which have
877 # no sub-expressions.
879 subexprs = []
881 # Override to optimize -- we know we have no children
882 def generate_subexpr_evaluation_code(self, code):
883 pass
884 def generate_subexpr_disposal_code(self, code):
885 pass
887 class PyConstNode(AtomicExprNode):
888 # Abstract base class for constant Python values.
890 is_literal = 1
891 type = py_object_type
893 def is_simple(self):
894 return 1
896 def may_be_none(self):
897 return False
899 def analyse_types(self, env):
900 return self
902 def calculate_result_code(self):
903 return self.value
905 def generate_result_code(self, code):
906 pass
909 class NoneNode(PyConstNode):
910 # The constant value None
912 is_none = 1
913 value = "Py_None"
915 constant_result = None
917 nogil_check = None
919 def compile_time_value(self, denv):
920 return None
922 def may_be_none(self):
923 return True
926 class EllipsisNode(PyConstNode):
927 # '...' in a subscript list.
929 value = "Py_Ellipsis"
931 constant_result = Ellipsis
933 def compile_time_value(self, denv):
934 return Ellipsis
937 class ConstNode(AtomicExprNode):
938 # Abstract base type for literal constant nodes.
940 # value string C code fragment
942 is_literal = 1
943 nogil_check = None
945 def is_simple(self):
946 return 1
948 def nonlocally_immutable(self):
949 return 1
951 def may_be_none(self):
952 return False
954 def analyse_types(self, env):
955 return self # Types are held in class variables
957 def check_const(self):
958 return True
960 def get_constant_c_result_code(self):
961 return self.calculate_result_code()
963 def calculate_result_code(self):
964 return str(self.value)
966 def generate_result_code(self, code):
967 pass
970 class BoolNode(ConstNode):
971 type = PyrexTypes.c_bint_type
972 # The constant value True or False
974 def calculate_constant_result(self):
975 self.constant_result = self.value
977 def compile_time_value(self, denv):
978 return self.value
980 def calculate_result_code(self):
981 if self.type.is_pyobject:
982 return self.value and 'Py_True' or 'Py_False'
983 else:
984 return str(int(self.value))
986 def coerce_to(self, dst_type, env):
987 if dst_type.is_pyobject and self.type.is_int:
988 return BoolNode(
989 self.pos, value=self.value,
990 constant_result=self.constant_result,
991 type=Builtin.bool_type)
992 if dst_type.is_int and self.type.is_pyobject:
993 return BoolNode(
994 self.pos, value=self.value,
995 constant_result=self.constant_result,
996 type=PyrexTypes.c_bint_type)
997 return ConstNode.coerce_to(self, dst_type, env)
1000 class NullNode(ConstNode):
1001 type = PyrexTypes.c_null_ptr_type
1002 value = "NULL"
1003 constant_result = 0
1005 def get_constant_c_result_code(self):
1006 return self.value
1009 class CharNode(ConstNode):
1010 type = PyrexTypes.c_char_type
1012 def calculate_constant_result(self):
1013 self.constant_result = ord(self.value)
1015 def compile_time_value(self, denv):
1016 return ord(self.value)
1018 def calculate_result_code(self):
1019 return "'%s'" % StringEncoding.escape_char(self.value)
1022 class IntNode(ConstNode):
1024 # unsigned "" or "U"
1025 # longness "" or "L" or "LL"
1026 # is_c_literal True/False/None creator considers this a C integer literal
1028 unsigned = ""
1029 longness = ""
1030 is_c_literal = None # unknown
1032 def __init__(self, pos, **kwds):
1033 ExprNode.__init__(self, pos, **kwds)
1034 if 'type' not in kwds:
1035 self.type = self.find_suitable_type_for_value()
1037 def find_suitable_type_for_value(self):
1038 if self.constant_result is constant_value_not_set:
1039 try:
1040 self.calculate_constant_result()
1041 except ValueError:
1042 pass
1043 # we ignore 'is_c_literal = True' and instead map signed 32bit
1044 # integers as C long values
1045 if self.is_c_literal or \
1046 self.constant_result in (constant_value_not_set, not_a_constant) or \
1047 self.unsigned or self.longness == 'LL':
1048 # clearly a C literal
1049 rank = (self.longness == 'LL') and 2 or 1
1050 suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsigned, rank, "int"]
1051 if self.type:
1052 suitable_type = PyrexTypes.widest_numeric_type(suitable_type, self.type)
1053 else:
1054 # C literal or Python literal - split at 32bit boundary
1055 if -2**31 <= self.constant_result < 2**31:
1056 if self.type and self.type.is_int:
1057 suitable_type = self.type
1058 else:
1059 suitable_type = PyrexTypes.c_long_type
1060 else:
1061 suitable_type = PyrexTypes.py_object_type
1062 return suitable_type
1064 def coerce_to(self, dst_type, env):
1065 if self.type is dst_type:
1066 return self
1067 elif dst_type.is_float:
1068 if self.has_constant_result():
1069 return FloatNode(self.pos, value='%d.0' % int(self.constant_result), type=dst_type,
1070 constant_result=float(self.constant_result))
1071 else:
1072 return FloatNode(self.pos, value=self.value, type=dst_type,
1073 constant_result=not_a_constant)
1074 if dst_type.is_numeric and not dst_type.is_complex:
1075 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
1076 type = dst_type, is_c_literal = True,
1077 unsigned=self.unsigned, longness=self.longness)
1078 return node
1079 elif dst_type.is_pyobject:
1080 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
1081 type = PyrexTypes.py_object_type, is_c_literal = False,
1082 unsigned=self.unsigned, longness=self.longness)
1083 else:
1084 # FIXME: not setting the type here to keep it working with
1085 # complex numbers. Should they be special cased?
1086 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
1087 unsigned=self.unsigned, longness=self.longness)
1088 # We still need to perform normal coerce_to processing on the
1089 # result, because we might be coercing to an extension type,
1090 # in which case a type test node will be needed.
1091 return ConstNode.coerce_to(node, dst_type, env)
1093 def coerce_to_boolean(self, env):
1094 return IntNode(
1095 self.pos, value=self.value,
1096 constant_result=self.constant_result,
1097 type=PyrexTypes.c_bint_type,
1098 unsigned=self.unsigned, longness=self.longness)
1100 def generate_evaluation_code(self, code):
1101 if self.type.is_pyobject:
1102 # pre-allocate a Python version of the number
1103 plain_integer_string = str(Utils.str_to_number(self.value))
1104 self.result_code = code.get_py_int(plain_integer_string, self.longness)
1105 else:
1106 self.result_code = self.get_constant_c_result_code()
1108 def get_constant_c_result_code(self):
1109 return self.value_as_c_integer_string() + self.unsigned + self.longness
1111 def value_as_c_integer_string(self):
1112 value = self.value
1113 if len(value) > 2:
1114 # convert C-incompatible Py3 oct/bin notations
1115 if value[1] in 'oO':
1116 value = value[0] + value[2:] # '0o123' => '0123'
1117 elif value[1] in 'bB':
1118 value = int(value[2:], 2)
1119 return str(value)
1121 def calculate_result_code(self):
1122 return self.result_code
1124 def calculate_constant_result(self):
1125 self.constant_result = Utils.str_to_number(self.value)
1127 def compile_time_value(self, denv):
1128 return Utils.str_to_number(self.value)
1131 class FloatNode(ConstNode):
1132 type = PyrexTypes.c_double_type
1134 def calculate_constant_result(self):
1135 self.constant_result = float(self.value)
1137 def compile_time_value(self, denv):
1138 return float(self.value)
1140 def coerce_to(self, dst_type, env):
1141 if dst_type.is_pyobject and self.type.is_float:
1142 return FloatNode(
1143 self.pos, value=self.value,
1144 constant_result=self.constant_result,
1145 type=Builtin.float_type)
1146 if dst_type.is_float and self.type.is_pyobject:
1147 return FloatNode(
1148 self.pos, value=self.value,
1149 constant_result=self.constant_result,
1150 type=dst_type)
1151 return ConstNode.coerce_to(self, dst_type, env)
1153 def calculate_result_code(self):
1154 return self.result_code
1156 def get_constant_c_result_code(self):
1157 strval = self.value
1158 assert isinstance(strval, (str, unicode))
1159 cmpval = repr(float(strval))
1160 if cmpval == 'nan':
1161 return "(Py_HUGE_VAL * 0)"
1162 elif cmpval == 'inf':
1163 return "Py_HUGE_VAL"
1164 elif cmpval == '-inf':
1165 return "(-Py_HUGE_VAL)"
1166 else:
1167 return strval
1169 def generate_evaluation_code(self, code):
1170 c_value = self.get_constant_c_result_code()
1171 if self.type.is_pyobject:
1172 self.result_code = code.get_py_float(self.value, c_value)
1173 else:
1174 self.result_code = c_value
1177 class BytesNode(ConstNode):
1178 # A char* or bytes literal
1180 # value BytesLiteral
1182 is_string_literal = True
1183 # start off as Python 'bytes' to support len() in O(1)
1184 type = bytes_type
1186 def calculate_constant_result(self):
1187 self.constant_result = self.value
1189 def as_sliced_node(self, start, stop, step=None):
1190 value = StringEncoding.BytesLiteral(self.value[start:stop:step])
1191 value.encoding = self.value.encoding
1192 return BytesNode(
1193 self.pos, value=value, constant_result=value)
1195 def compile_time_value(self, denv):
1196 return self.value
1198 def analyse_as_type(self, env):
1199 type = PyrexTypes.parse_basic_type(self.value)
1200 if type is not None:
1201 return type
1202 from TreeFragment import TreeFragment
1203 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
1204 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
1205 sizeof_node = declaration.root.stats[0].expr
1206 sizeof_node = sizeof_node.analyse_types(env)
1207 if isinstance(sizeof_node, SizeofTypeNode):
1208 return sizeof_node.arg_type
1210 def can_coerce_to_char_literal(self):
1211 return len(self.value) == 1
1213 def coerce_to_boolean(self, env):
1214 # This is special because testing a C char* for truth directly
1215 # would yield the wrong result.
1216 bool_value = bool(self.value)
1217 return BoolNode(self.pos, value=bool_value, constant_result=bool_value)
1219 def coerce_to(self, dst_type, env):
1220 if self.type == dst_type:
1221 return self
1222 if dst_type.is_int:
1223 if not self.can_coerce_to_char_literal():
1224 error(self.pos, "Only single-character string literals can be coerced into ints.")
1225 return self
1226 if dst_type.is_unicode_char:
1227 error(self.pos, "Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead.")
1228 return self
1229 return CharNode(self.pos, value=self.value,
1230 constant_result=ord(self.value))
1232 node = BytesNode(self.pos, value=self.value,
1233 constant_result=self.constant_result)
1234 if dst_type.is_pyobject:
1235 if dst_type in (py_object_type, Builtin.bytes_type):
1236 node.type = Builtin.bytes_type
1237 else:
1238 self.check_for_coercion_error(dst_type, env, fail=True)
1239 return node
1240 elif dst_type == PyrexTypes.c_char_ptr_type:
1241 node.type = dst_type
1242 return node
1243 elif dst_type == PyrexTypes.c_uchar_ptr_type:
1244 node.type = PyrexTypes.c_char_ptr_type
1245 return CastNode(node, PyrexTypes.c_uchar_ptr_type)
1246 elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
1247 node.type = dst_type
1248 return node
1250 # We still need to perform normal coerce_to processing on the
1251 # result, because we might be coercing to an extension type,
1252 # in which case a type test node will be needed.
1253 return ConstNode.coerce_to(node, dst_type, env)
1255 def generate_evaluation_code(self, code):
1256 if self.type.is_pyobject:
1257 self.result_code = code.get_py_string_const(self.value)
1258 else:
1259 self.result_code = code.get_string_const(self.value)
1261 def get_constant_c_result_code(self):
1262 return None # FIXME
1264 def calculate_result_code(self):
1265 return self.result_code
1268 class UnicodeNode(ConstNode):
1269 # A Py_UNICODE* or unicode literal
1271 # value EncodedString
1272 # bytes_value BytesLiteral the literal parsed as bytes string
1273 # ('-3' unicode literals only)
1275 is_string_literal = True
1276 bytes_value = None
1277 type = unicode_type
1279 def calculate_constant_result(self):
1280 self.constant_result = self.value
1282 def as_sliced_node(self, start, stop, step=None):
1283 if StringEncoding.string_contains_surrogates(self.value[:stop]):
1284 # this is unsafe as it may give different results
1285 # in different runtimes
1286 return None
1287 value = StringEncoding.EncodedString(self.value[start:stop:step])
1288 value.encoding = self.value.encoding
1289 if self.bytes_value is not None:
1290 bytes_value = StringEncoding.BytesLiteral(
1291 self.bytes_value[start:stop:step])
1292 bytes_value.encoding = self.bytes_value.encoding
1293 else:
1294 bytes_value = None
1295 return UnicodeNode(
1296 self.pos, value=value, bytes_value=bytes_value,
1297 constant_result=value)
1299 def coerce_to(self, dst_type, env):
1300 if dst_type is self.type:
1301 pass
1302 elif dst_type.is_unicode_char:
1303 if not self.can_coerce_to_char_literal():
1304 error(self.pos,
1305 "Only single-character Unicode string literals or "
1306 "surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.")
1307 return self
1308 int_value = ord(self.value)
1309 return IntNode(self.pos, type=dst_type, value=str(int_value),
1310 constant_result=int_value)
1311 elif not dst_type.is_pyobject:
1312 if dst_type.is_string and self.bytes_value is not None:
1313 # special case: '-3' enforced unicode literal used in a
1314 # C char* context
1315 return BytesNode(self.pos, value=self.bytes_value
1316 ).coerce_to(dst_type, env)
1317 if dst_type.is_pyunicode_ptr:
1318 node = UnicodeNode(self.pos, value=self.value)
1319 node.type = dst_type
1320 return node
1321 error(self.pos,
1322 "Unicode literals do not support coercion to C types other "
1323 "than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* "
1324 "(for strings).")
1325 elif dst_type not in (py_object_type, Builtin.basestring_type):
1326 self.check_for_coercion_error(dst_type, env, fail=True)
1327 return self
1329 def can_coerce_to_char_literal(self):
1330 return len(self.value) == 1
1331 ## or (len(self.value) == 2
1332 ## and (0xD800 <= self.value[0] <= 0xDBFF)
1333 ## and (0xDC00 <= self.value[1] <= 0xDFFF))
1335 def coerce_to_boolean(self, env):
1336 bool_value = bool(self.value)
1337 return BoolNode(self.pos, value=bool_value, constant_result=bool_value)
1339 def contains_surrogates(self):
1340 return StringEncoding.string_contains_surrogates(self.value)
1342 def generate_evaluation_code(self, code):
1343 if self.type.is_pyobject:
1344 if self.contains_surrogates():
1345 # surrogates are not really portable and cannot be
1346 # decoded by the UTF-8 codec in Py3.3
1347 self.result_code = code.get_py_const(py_object_type, 'ustring')
1348 data_cname = code.get_pyunicode_ptr_const(self.value)
1349 code = code.get_cached_constants_writer()
1350 code.mark_pos(self.pos)
1351 code.putln(
1352 "%s = PyUnicode_FromUnicode(%s, (sizeof(%s) / sizeof(Py_UNICODE))-1); %s" % (
1353 self.result_code,
1354 data_cname,
1355 data_cname,
1356 code.error_goto_if_null(self.result_code, self.pos)))
1357 code.putln("#if CYTHON_PEP393_ENABLED")
1358 code.put_error_if_neg(
1359 self.pos, "PyUnicode_READY(%s)" % self.result_code)
1360 code.putln("#endif")
1361 else:
1362 self.result_code = code.get_py_string_const(self.value)
1363 else:
1364 self.result_code = code.get_pyunicode_ptr_const(self.value)
1366 def calculate_result_code(self):
1367 return self.result_code
1369 def compile_time_value(self, env):
1370 return self.value
1373 class StringNode(PyConstNode):
1374 # A Python str object, i.e. a byte string in Python 2.x and a
1375 # unicode string in Python 3.x
1377 # value BytesLiteral (or EncodedString with ASCII content)
1378 # unicode_value EncodedString or None
1379 # is_identifier boolean
1381 type = str_type
1382 is_string_literal = True
1383 is_identifier = None
1384 unicode_value = None
1386 def calculate_constant_result(self):
1387 if self.unicode_value is not None:
1388 # only the Unicode value is portable across Py2/3
1389 self.constant_result = self.unicode_value
1391 def as_sliced_node(self, start, stop, step=None):
1392 value = type(self.value)(self.value[start:stop:step])
1393 value.encoding = self.value.encoding
1394 if self.unicode_value is not None:
1395 if StringEncoding.string_contains_surrogates(self.unicode_value[:stop]):
1396 # this is unsafe as it may give different results in different runtimes
1397 return None
1398 unicode_value = StringEncoding.EncodedString(
1399 self.unicode_value[start:stop:step])
1400 else:
1401 unicode_value = None
1402 return StringNode(
1403 self.pos, value=value, unicode_value=unicode_value,
1404 constant_result=value, is_identifier=self.is_identifier)
1406 def coerce_to(self, dst_type, env):
1407 if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
1408 # if dst_type is Builtin.bytes_type:
1409 # # special case: bytes = 'str literal'
1410 # return BytesNode(self.pos, value=self.value)
1411 if not dst_type.is_pyobject:
1412 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
1413 if dst_type is not Builtin.basestring_type:
1414 self.check_for_coercion_error(dst_type, env, fail=True)
1415 return self
1417 def can_coerce_to_char_literal(self):
1418 return not self.is_identifier and len(self.value) == 1
1420 def generate_evaluation_code(self, code):
1421 self.result_code = code.get_py_string_const(
1422 self.value, identifier=self.is_identifier, is_str=True,
1423 unicode_value=self.unicode_value)
1425 def get_constant_c_result_code(self):
1426 return None
1428 def calculate_result_code(self):
1429 return self.result_code
1431 def compile_time_value(self, env):
1432 return self.value
1435 class IdentifierStringNode(StringNode):
1436 # A special str value that represents an identifier (bytes in Py2,
1437 # unicode in Py3).
1438 is_identifier = True
1441 class ImagNode(AtomicExprNode):
1442 # Imaginary number literal
1444 # value float imaginary part
1446 type = PyrexTypes.c_double_complex_type
1448 def calculate_constant_result(self):
1449 self.constant_result = complex(0.0, self.value)
1451 def compile_time_value(self, denv):
1452 return complex(0.0, self.value)
1454 def analyse_types(self, env):
1455 self.type.create_declaration_utility_code(env)
1456 return self
1458 def may_be_none(self):
1459 return False
1461 def coerce_to(self, dst_type, env):
1462 if self.type is dst_type:
1463 return self
1464 node = ImagNode(self.pos, value=self.value)
1465 if dst_type.is_pyobject:
1466 node.is_temp = 1
1467 node.type = PyrexTypes.py_object_type
1468 # We still need to perform normal coerce_to processing on the
1469 # result, because we might be coercing to an extension type,
1470 # in which case a type test node will be needed.
1471 return AtomicExprNode.coerce_to(node, dst_type, env)
1473 gil_message = "Constructing complex number"
1475 def calculate_result_code(self):
1476 if self.type.is_pyobject:
1477 return self.result()
1478 else:
1479 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1481 def generate_result_code(self, code):
1482 if self.type.is_pyobject:
1483 code.putln(
1484 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1485 self.result(),
1486 float(self.value),
1487 code.error_goto_if_null(self.result(), self.pos)))
1488 code.put_gotref(self.py_result())
1491 class NewExprNode(AtomicExprNode):
1493 # C++ new statement
1495 # cppclass node c++ class to create
1497 type = None
1499 def infer_type(self, env):
1500 type = self.cppclass.analyse_as_type(env)
1501 if type is None or not type.is_cpp_class:
1502 error(self.pos, "new operator can only be applied to a C++ class")
1503 self.type = error_type
1504 return
1505 self.cpp_check(env)
1506 constructor = type.scope.lookup(u'<init>')
1507 if constructor is None:
1508 func_type = PyrexTypes.CFuncType(type, [], exception_check='+')
1509 type.scope.declare_cfunction(u'<init>', func_type, self.pos)
1510 constructor = type.scope.lookup(u'<init>')
1511 self.class_type = type
1512 self.entry = constructor
1513 self.type = constructor.type
1514 return self.type
1516 def analyse_types(self, env):
1517 if self.type is None:
1518 self.infer_type(env)
1519 return self
1521 def may_be_none(self):
1522 return False
1524 def generate_result_code(self, code):
1525 pass
1527 def calculate_result_code(self):
1528 return "new " + self.class_type.declaration_code("")
1531 class NameNode(AtomicExprNode):
1532 # Reference to a local or global variable name.
1534 # name string Python name of the variable
1535 # entry Entry Symbol table entry
1536 # type_entry Entry For extension type names, the original type entry
1537 # cf_is_null boolean Is uninitialized before this node
1538 # cf_maybe_null boolean Maybe uninitialized before this node
1539 # allow_null boolean Don't raise UnboundLocalError
1540 # nogil boolean Whether it is used in a nogil context
1542 is_name = True
1543 is_cython_module = False
1544 cython_attribute = None
1545 lhs_of_first_assignment = False # TODO: remove me
1546 is_used_as_rvalue = 0
1547 entry = None
1548 type_entry = None
1549 cf_maybe_null = True
1550 cf_is_null = False
1551 allow_null = False
1552 nogil = False
1553 inferred_type = None
1555 def as_cython_attribute(self):
1556 return self.cython_attribute
1558 def type_dependencies(self, env):
1559 if self.entry is None:
1560 self.entry = env.lookup(self.name)
1561 if self.entry is not None and self.entry.type.is_unspecified:
1562 return (self,)
1563 else:
1564 return ()
1566 def infer_type(self, env):
1567 if self.entry is None:
1568 self.entry = env.lookup(self.name)
1569 if self.entry is None or self.entry.type is unspecified_type:
1570 if self.inferred_type is not None:
1571 return self.inferred_type
1572 return py_object_type
1573 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1574 self.name == self.entry.type.name:
1575 # Unfortunately the type attribute of type objects
1576 # is used for the pointer to the type they represent.
1577 return type_type
1578 elif self.entry.type.is_cfunction:
1579 if self.entry.scope.is_builtin_scope:
1580 # special case: optimised builtin functions must be treated as Python objects
1581 return py_object_type
1582 else:
1583 # special case: referring to a C function must return its pointer
1584 return PyrexTypes.CPtrType(self.entry.type)
1585 else:
1586 # If entry is inferred as pyobject it's safe to use local
1587 # NameNode's inferred_type.
1588 if self.entry.type.is_pyobject and self.inferred_type:
1589 # Overflow may happen if integer
1590 if not (self.inferred_type.is_int and self.entry.might_overflow):
1591 return self.inferred_type
1592 return self.entry.type
1594 def compile_time_value(self, denv):
1595 try:
1596 return denv.lookup(self.name)
1597 except KeyError:
1598 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1600 def get_constant_c_result_code(self):
1601 if not self.entry or self.entry.type.is_pyobject:
1602 return None
1603 return self.entry.cname
1605 def coerce_to(self, dst_type, env):
1606 # If coercing to a generic pyobject and this is a builtin
1607 # C function with a Python equivalent, manufacture a NameNode
1608 # referring to the Python builtin.
1609 #print "NameNode.coerce_to:", self.name, dst_type ###
1610 if dst_type is py_object_type:
1611 entry = self.entry
1612 if entry and entry.is_cfunction:
1613 var_entry = entry.as_variable
1614 if var_entry:
1615 if var_entry.is_builtin and var_entry.is_const:
1616 var_entry = env.declare_builtin(var_entry.name, self.pos)
1617 node = NameNode(self.pos, name = self.name)
1618 node.entry = var_entry
1619 node.analyse_rvalue_entry(env)
1620 return node
1622 return super(NameNode, self).coerce_to(dst_type, env)
1624 def analyse_as_module(self, env):
1625 # Try to interpret this as a reference to a cimported module.
1626 # Returns the module scope, or None.
1627 entry = self.entry
1628 if not entry:
1629 entry = env.lookup(self.name)
1630 if entry and entry.as_module:
1631 return entry.as_module
1632 return None
1634 def analyse_as_type(self, env):
1635 if self.cython_attribute:
1636 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1637 else:
1638 type = PyrexTypes.parse_basic_type(self.name)
1639 if type:
1640 return type
1641 entry = self.entry
1642 if not entry:
1643 entry = env.lookup(self.name)
1644 if entry and entry.is_type:
1645 return entry.type
1646 else:
1647 return None
1649 def analyse_as_extension_type(self, env):
1650 # Try to interpret this as a reference to an extension type.
1651 # Returns the extension type, or None.
1652 entry = self.entry
1653 if not entry:
1654 entry = env.lookup(self.name)
1655 if entry and entry.is_type:
1656 if entry.type.is_extension_type or entry.type.is_builtin_type:
1657 return entry.type
1658 return None
1660 def analyse_target_declaration(self, env):
1661 if not self.entry:
1662 self.entry = env.lookup_here(self.name)
1663 if not self.entry:
1664 if env.directives['warn.undeclared']:
1665 warning(self.pos, "implicit declaration of '%s'" % self.name, 1)
1666 if env.directives['infer_types'] != False:
1667 type = unspecified_type
1668 else:
1669 type = py_object_type
1670 self.entry = env.declare_var(self.name, type, self.pos)
1671 if self.entry.is_declared_generic:
1672 self.result_ctype = py_object_type
1674 def analyse_types(self, env):
1675 self.initialized_check = env.directives['initializedcheck']
1676 if self.entry is None:
1677 self.entry = env.lookup(self.name)
1678 if not self.entry:
1679 self.entry = env.declare_builtin(self.name, self.pos)
1680 if not self.entry:
1681 self.type = PyrexTypes.error_type
1682 return self
1683 entry = self.entry
1684 if entry:
1685 entry.used = 1
1686 if entry.type.is_buffer:
1687 import Buffer
1688 Buffer.used_buffer_aux_vars(entry)
1689 self.analyse_rvalue_entry(env)
1690 return self
1692 def analyse_target_types(self, env):
1693 self.analyse_entry(env, is_target=True)
1695 if (not self.is_lvalue() and self.entry.is_cfunction and
1696 self.entry.fused_cfunction and self.entry.as_variable):
1697 # We need this for the fused 'def' TreeFragment
1698 self.entry = self.entry.as_variable
1699 self.type = self.entry.type
1701 if self.type.is_const:
1702 error(self.pos, "Assignment to const '%s'" % self.name)
1703 if self.type.is_reference:
1704 error(self.pos, "Assignment to reference '%s'" % self.name)
1705 if not self.is_lvalue():
1706 error(self.pos, "Assignment to non-lvalue '%s'"
1707 % self.name)
1708 self.type = PyrexTypes.error_type
1709 self.entry.used = 1
1710 if self.entry.type.is_buffer:
1711 import Buffer
1712 Buffer.used_buffer_aux_vars(self.entry)
1713 return self
1715 def analyse_rvalue_entry(self, env):
1716 #print "NameNode.analyse_rvalue_entry:", self.name ###
1717 #print "Entry:", self.entry.__dict__ ###
1718 self.analyse_entry(env)
1719 entry = self.entry
1721 if entry.is_declared_generic:
1722 self.result_ctype = py_object_type
1724 if entry.is_pyglobal or entry.is_builtin:
1725 if entry.is_builtin and entry.is_const:
1726 self.is_temp = 0
1727 else:
1728 self.is_temp = 1
1730 self.is_used_as_rvalue = 1
1731 elif entry.type.is_memoryviewslice:
1732 self.is_temp = False
1733 self.is_used_as_rvalue = True
1734 self.use_managed_ref = True
1735 return self
1737 def nogil_check(self, env):
1738 self.nogil = True
1739 if self.is_used_as_rvalue:
1740 entry = self.entry
1741 if entry.is_builtin:
1742 if not entry.is_const: # cached builtins are ok
1743 self.gil_error()
1744 elif entry.is_pyglobal:
1745 self.gil_error()
1746 elif self.entry.type.is_memoryviewslice:
1747 if self.cf_is_null or self.cf_maybe_null:
1748 import MemoryView
1749 MemoryView.err_if_nogil_initialized_check(self.pos, env)
1751 gil_message = "Accessing Python global or builtin"
1753 def analyse_entry(self, env, is_target=False):
1754 #print "NameNode.analyse_entry:", self.name ###
1755 self.check_identifier_kind()
1756 entry = self.entry
1757 type = entry.type
1758 if (not is_target and type.is_pyobject and self.inferred_type and
1759 self.inferred_type.is_builtin_type):
1760 # assume that type inference is smarter than the static entry
1761 type = self.inferred_type
1762 self.type = type
1764 def check_identifier_kind(self):
1765 # Check that this is an appropriate kind of name for use in an
1766 # expression. Also finds the variable entry associated with
1767 # an extension type.
1768 entry = self.entry
1769 if entry.is_type and entry.type.is_extension_type:
1770 self.type_entry = entry
1771 if not (entry.is_const or entry.is_variable
1772 or entry.is_builtin or entry.is_cfunction
1773 or entry.is_cpp_class):
1774 if self.entry.as_variable:
1775 self.entry = self.entry.as_variable
1776 else:
1777 error(self.pos,
1778 "'%s' is not a constant, variable or function identifier" % self.name)
1780 def is_simple(self):
1781 # If it's not a C variable, it'll be in a temp.
1782 return 1
1784 def may_be_none(self):
1785 if self.cf_state and self.type and (self.type.is_pyobject or
1786 self.type.is_memoryviewslice):
1787 # gard against infinite recursion on self-dependencies
1788 if getattr(self, '_none_checking', False):
1789 # self-dependency - either this node receives a None
1790 # value from *another* node, or it can not reference
1791 # None at this point => safe to assume "not None"
1792 return False
1793 self._none_checking = True
1794 # evaluate control flow state to see if there were any
1795 # potential None values assigned to the node so far
1796 may_be_none = False
1797 for assignment in self.cf_state:
1798 if assignment.rhs.may_be_none():
1799 may_be_none = True
1800 break
1801 del self._none_checking
1802 return may_be_none
1803 return super(NameNode, self).may_be_none()
1805 def nonlocally_immutable(self):
1806 if ExprNode.nonlocally_immutable(self):
1807 return True
1808 entry = self.entry
1809 if not entry or entry.in_closure:
1810 return False
1811 return entry.is_local or entry.is_arg or entry.is_builtin or entry.is_readonly
1813 def calculate_target_results(self, env):
1814 pass
1816 def check_const(self):
1817 entry = self.entry
1818 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1819 self.not_const()
1820 return False
1821 return True
1823 def check_const_addr(self):
1824 entry = self.entry
1825 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1826 self.addr_not_const()
1827 return False
1828 return True
1830 def is_lvalue(self):
1831 return self.entry.is_variable and \
1832 not self.entry.type.is_array and \
1833 not self.entry.is_readonly
1835 def is_addressable(self):
1836 return self.entry.is_variable and not self.type.is_memoryviewslice
1838 def is_ephemeral(self):
1839 # Name nodes are never ephemeral, even if the
1840 # result is in a temporary.
1841 return 0
1843 def calculate_result_code(self):
1844 entry = self.entry
1845 if not entry:
1846 return "<error>" # There was an error earlier
1847 return entry.cname
1849 def generate_result_code(self, code):
1850 assert hasattr(self, 'entry')
1851 entry = self.entry
1852 if entry is None:
1853 return # There was an error earlier
1854 if entry.is_builtin and entry.is_const:
1855 return # Lookup already cached
1856 elif entry.is_pyclass_attr:
1857 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1858 interned_cname = code.intern_identifier(self.entry.name)
1859 if entry.is_builtin:
1860 namespace = Naming.builtins_cname
1861 else: # entry.is_pyglobal
1862 namespace = entry.scope.namespace_cname
1863 if not self.cf_is_null:
1864 code.putln(
1865 '%s = PyObject_GetItem(%s, %s);' % (
1866 self.result(),
1867 namespace,
1868 interned_cname))
1869 code.putln('if (unlikely(!%s)) {' % self.result())
1870 code.putln('PyErr_Clear();')
1871 code.globalstate.use_utility_code(
1872 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
1873 code.putln(
1874 '%s = __Pyx_GetModuleGlobalName(%s);' % (
1875 self.result(),
1876 interned_cname))
1877 if not self.cf_is_null:
1878 code.putln("}")
1879 code.putln(code.error_goto_if_null(self.result(), self.pos))
1880 code.put_gotref(self.py_result())
1882 elif entry.is_builtin:
1883 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1884 interned_cname = code.intern_identifier(self.entry.name)
1885 code.globalstate.use_utility_code(
1886 UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c"))
1887 code.putln(
1888 '%s = __Pyx_GetBuiltinName(%s); %s' % (
1889 self.result(),
1890 interned_cname,
1891 code.error_goto_if_null(self.result(), self.pos)))
1892 code.put_gotref(self.py_result())
1894 elif entry.is_pyglobal:
1895 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1896 interned_cname = code.intern_identifier(self.entry.name)
1897 if entry.scope.is_module_scope:
1898 code.globalstate.use_utility_code(
1899 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
1900 code.putln(
1901 '%s = __Pyx_GetModuleGlobalName(%s); %s' % (
1902 self.result(),
1903 interned_cname,
1904 code.error_goto_if_null(self.result(), self.pos)))
1905 else:
1906 # FIXME: is_pyglobal is also used for class namespace
1907 code.globalstate.use_utility_code(
1908 UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"))
1909 code.putln(
1910 '%s = __Pyx_GetNameInClass(%s, %s); %s' % (
1911 self.result(),
1912 entry.scope.namespace_cname,
1913 interned_cname,
1914 code.error_goto_if_null(self.result(), self.pos)))
1915 code.put_gotref(self.py_result())
1917 elif entry.is_local or entry.in_closure or entry.from_closure or entry.type.is_memoryviewslice:
1918 # Raise UnboundLocalError for objects and memoryviewslices
1919 raise_unbound = (
1920 (self.cf_maybe_null or self.cf_is_null) and not self.allow_null)
1921 null_code = entry.type.check_for_null_code(entry.cname)
1923 memslice_check = entry.type.is_memoryviewslice and self.initialized_check
1925 if null_code and raise_unbound and (entry.type.is_pyobject or memslice_check):
1926 code.put_error_if_unbound(self.pos, entry, self.in_nogil_context)
1928 def generate_assignment_code(self, rhs, code):
1929 #print "NameNode.generate_assignment_code:", self.name ###
1930 entry = self.entry
1931 if entry is None:
1932 return # There was an error earlier
1934 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1935 and not self.lhs_of_first_assignment and not rhs.in_module_scope):
1936 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1938 # is_pyglobal seems to be True for module level-globals only.
1939 # We use this to access class->tp_dict if necessary.
1940 if entry.is_pyglobal:
1941 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1942 interned_cname = code.intern_identifier(self.entry.name)
1943 namespace = self.entry.scope.namespace_cname
1944 if entry.is_member:
1945 # if the entry is a member we have to cheat: SetAttr does not work
1946 # on types, so we create a descriptor which is then added to tp_dict
1947 setter = 'PyDict_SetItem'
1948 namespace = '%s->tp_dict' % namespace
1949 elif entry.scope.is_module_scope:
1950 setter = 'PyDict_SetItem'
1951 namespace = Naming.moddict_cname
1952 elif entry.is_pyclass_attr:
1953 setter = 'PyObject_SetItem'
1954 else:
1955 assert False, repr(entry)
1956 code.put_error_if_neg(
1957 self.pos,
1958 '%s(%s, %s, %s)' % (
1959 setter,
1960 namespace,
1961 interned_cname,
1962 rhs.py_result()))
1963 if debug_disposal_code:
1964 print("NameNode.generate_assignment_code:")
1965 print("...generating disposal code for %s" % rhs)
1966 rhs.generate_disposal_code(code)
1967 rhs.free_temps(code)
1968 if entry.is_member:
1969 # in Py2.6+, we need to invalidate the method cache
1970 code.putln("PyType_Modified(%s);" %
1971 entry.scope.parent_type.typeptr_cname)
1972 else:
1973 if self.type.is_memoryviewslice:
1974 self.generate_acquire_memoryviewslice(rhs, code)
1976 elif self.type.is_buffer:
1977 # Generate code for doing the buffer release/acquisition.
1978 # This might raise an exception in which case the assignment (done
1979 # below) will not happen.
1981 # The reason this is not in a typetest-like node is because the
1982 # variables that the acquired buffer info is stored to is allocated
1983 # per entry and coupled with it.
1984 self.generate_acquire_buffer(rhs, code)
1985 assigned = False
1986 if self.type.is_pyobject:
1987 #print "NameNode.generate_assignment_code: to", self.name ###
1988 #print "...from", rhs ###
1989 #print "...LHS type", self.type, "ctype", self.ctype() ###
1990 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1991 if self.use_managed_ref:
1992 rhs.make_owned_reference(code)
1993 is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure
1994 if is_external_ref:
1995 if not self.cf_is_null:
1996 if self.cf_maybe_null:
1997 code.put_xgotref(self.py_result())
1998 else:
1999 code.put_gotref(self.py_result())
2000 assigned = True
2001 if entry.is_cglobal:
2002 code.put_decref_set(
2003 self.result(), rhs.result_as(self.ctype()))
2004 else:
2005 if not self.cf_is_null:
2006 if self.cf_maybe_null:
2007 code.put_xdecref_set(
2008 self.result(), rhs.result_as(self.ctype()))
2009 else:
2010 code.put_decref_set(
2011 self.result(), rhs.result_as(self.ctype()))
2012 else:
2013 assigned = False
2014 if is_external_ref:
2015 code.put_giveref(rhs.py_result())
2016 if not self.type.is_memoryviewslice:
2017 if not assigned:
2018 code.putln('%s = %s;' % (
2019 self.result(), rhs.result_as(self.ctype())))
2020 if debug_disposal_code:
2021 print("NameNode.generate_assignment_code:")
2022 print("...generating post-assignment code for %s" % rhs)
2023 rhs.generate_post_assignment_code(code)
2024 elif rhs.result_in_temp():
2025 rhs.generate_post_assignment_code(code)
2027 rhs.free_temps(code)
2029 def generate_acquire_memoryviewslice(self, rhs, code):
2031 Slices, coercions from objects, return values etc are new references.
2032 We have a borrowed reference in case of dst = src
2034 import MemoryView
2036 MemoryView.put_acquire_memoryviewslice(
2037 lhs_cname=self.result(),
2038 lhs_type=self.type,
2039 lhs_pos=self.pos,
2040 rhs=rhs,
2041 code=code,
2042 have_gil=not self.in_nogil_context,
2043 first_assignment=self.cf_is_null)
2045 def generate_acquire_buffer(self, rhs, code):
2046 # rhstmp is only used in case the rhs is a complicated expression leading to
2047 # the object, to avoid repeating the same C expression for every reference
2048 # to the rhs. It does NOT hold a reference.
2049 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
2050 if pretty_rhs:
2051 rhstmp = rhs.result_as(self.ctype())
2052 else:
2053 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
2054 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
2056 import Buffer
2057 Buffer.put_assign_to_buffer(self.result(), rhstmp, self.entry,
2058 is_initialized=not self.lhs_of_first_assignment,
2059 pos=self.pos, code=code)
2061 if not pretty_rhs:
2062 code.putln("%s = 0;" % rhstmp)
2063 code.funcstate.release_temp(rhstmp)
2065 def generate_deletion_code(self, code, ignore_nonexisting=False):
2066 if self.entry is None:
2067 return # There was an error earlier
2068 elif self.entry.is_pyclass_attr:
2069 namespace = self.entry.scope.namespace_cname
2070 interned_cname = code.intern_identifier(self.entry.name)
2071 if ignore_nonexisting:
2072 key_error_code = 'PyErr_Clear(); else'
2073 else:
2074 # minor hack: fake a NameError on KeyError
2075 key_error_code = (
2076 '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\' is not defined", "%s"); }' %
2077 self.entry.name)
2078 code.putln(
2079 'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {'
2080 ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s'
2081 ' %s '
2082 '}' % (namespace, interned_cname,
2083 key_error_code,
2084 code.error_goto(self.pos)))
2085 elif self.entry.is_pyglobal:
2086 code.globalstate.use_utility_code(
2087 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"))
2088 interned_cname = code.intern_identifier(self.entry.name)
2089 del_code = '__Pyx_PyObject_DelAttrStr(%s, %s)' % (
2090 Naming.module_cname, interned_cname)
2091 if ignore_nonexisting:
2092 code.putln('if (unlikely(%s < 0)) { if (likely(PyErr_ExceptionMatches(PyExc_AttributeError))) PyErr_Clear(); else %s }' % (
2093 del_code,
2094 code.error_goto(self.pos)))
2095 else:
2096 code.put_error_if_neg(self.pos, del_code)
2097 elif self.entry.type.is_pyobject or self.entry.type.is_memoryviewslice:
2098 if not self.cf_is_null:
2099 if self.cf_maybe_null and not ignore_nonexisting:
2100 code.put_error_if_unbound(self.pos, self.entry)
2102 if self.entry.type.is_pyobject:
2103 if self.entry.in_closure:
2104 # generator
2105 if ignore_nonexisting and self.cf_maybe_null:
2106 code.put_xgotref(self.result())
2107 else:
2108 code.put_gotref(self.result())
2109 if ignore_nonexisting and self.cf_maybe_null:
2110 code.put_xdecref(self.result(), self.ctype())
2111 else:
2112 code.put_decref(self.result(), self.ctype())
2113 code.putln('%s = NULL;' % self.result())
2114 else:
2115 code.put_xdecref_memoryviewslice(self.entry.cname,
2116 have_gil=not self.nogil)
2117 else:
2118 error(self.pos, "Deletion of C names not supported")
2120 def annotate(self, code):
2121 if hasattr(self, 'is_called') and self.is_called:
2122 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
2123 if self.type.is_pyobject:
2124 style, text = 'py_call', 'python function (%s)'
2125 else:
2126 style, text = 'c_call', 'c function (%s)'
2127 code.annotate(pos, AnnotationItem(style, text % self.type, size=len(self.name)))
2129 class BackquoteNode(ExprNode):
2130 # `expr`
2132 # arg ExprNode
2134 type = py_object_type
2136 subexprs = ['arg']
2138 def analyse_types(self, env):
2139 self.arg = self.arg.analyse_types(env)
2140 self.arg = self.arg.coerce_to_pyobject(env)
2141 self.is_temp = 1
2142 return self
2144 gil_message = "Backquote expression"
2146 def calculate_constant_result(self):
2147 self.constant_result = repr(self.arg.constant_result)
2149 def generate_result_code(self, code):
2150 code.putln(
2151 "%s = PyObject_Repr(%s); %s" % (
2152 self.result(),
2153 self.arg.py_result(),
2154 code.error_goto_if_null(self.result(), self.pos)))
2155 code.put_gotref(self.py_result())
2158 class ImportNode(ExprNode):
2159 # Used as part of import statement implementation.
2160 # Implements result =
2161 # __import__(module_name, globals(), None, name_list, level)
2163 # module_name StringNode dotted name of module. Empty module
2164 # name means importing the parent package according
2165 # to level
2166 # name_list ListNode or None list of names to be imported
2167 # level int relative import level:
2168 # -1: attempt both relative import and absolute import;
2169 # 0: absolute import;
2170 # >0: the number of parent directories to search
2171 # relative to the current module.
2172 # None: decide the level according to language level and
2173 # directives
2175 type = py_object_type
2177 subexprs = ['module_name', 'name_list']
2179 def analyse_types(self, env):
2180 if self.level is None:
2181 if (env.directives['py2_import'] or
2182 Future.absolute_import not in env.global_scope().context.future_directives):
2183 self.level = -1
2184 else:
2185 self.level = 0
2186 module_name = self.module_name.analyse_types(env)
2187 self.module_name = module_name.coerce_to_pyobject(env)
2188 if self.name_list:
2189 name_list = self.name_list.analyse_types(env)
2190 self.name_list = name_list.coerce_to_pyobject(env)
2191 self.is_temp = 1
2192 env.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c"))
2193 return self
2195 gil_message = "Python import"
2197 def generate_result_code(self, code):
2198 if self.name_list:
2199 name_list_code = self.name_list.py_result()
2200 else:
2201 name_list_code = "0"
2202 code.putln(
2203 "%s = __Pyx_Import(%s, %s, %d); %s" % (
2204 self.result(),
2205 self.module_name.py_result(),
2206 name_list_code,
2207 self.level,
2208 code.error_goto_if_null(self.result(), self.pos)))
2209 code.put_gotref(self.py_result())
2212 class IteratorNode(ExprNode):
2213 # Used as part of for statement implementation.
2215 # Implements result = iter(sequence)
2217 # sequence ExprNode
2219 type = py_object_type
2220 iter_func_ptr = None
2221 counter_cname = None
2222 cpp_iterator_cname = None
2223 reversed = False # currently only used for list/tuple types (see Optimize.py)
2225 subexprs = ['sequence']
2227 def analyse_types(self, env):
2228 self.sequence = self.sequence.analyse_types(env)
2229 if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \
2230 not self.sequence.type.is_string:
2231 # C array iteration will be transformed later on
2232 self.type = self.sequence.type
2233 elif self.sequence.type.is_cpp_class:
2234 self.analyse_cpp_types(env)
2235 else:
2236 self.sequence = self.sequence.coerce_to_pyobject(env)
2237 if self.sequence.type is list_type or \
2238 self.sequence.type is tuple_type:
2239 self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable")
2240 self.is_temp = 1
2241 return self
2243 gil_message = "Iterating over Python object"
2245 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
2246 PyrexTypes.py_object_type, [
2247 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None),
2250 def type_dependencies(self, env):
2251 return self.sequence.type_dependencies(env)
2253 def infer_type(self, env):
2254 sequence_type = self.sequence.infer_type(env)
2255 if sequence_type.is_array or sequence_type.is_ptr:
2256 return sequence_type
2257 elif sequence_type.is_cpp_class:
2258 begin = sequence_type.scope.lookup("begin")
2259 if begin is not None:
2260 return begin.type.return_type
2261 elif sequence_type.is_pyobject:
2262 return sequence_type
2263 return py_object_type
2265 def analyse_cpp_types(self, env):
2266 sequence_type = self.sequence.type
2267 if sequence_type.is_ptr:
2268 sequence_type = sequence_type.base_type
2269 begin = sequence_type.scope.lookup("begin")
2270 end = sequence_type.scope.lookup("end")
2271 if (begin is None
2272 or not begin.type.is_cfunction
2273 or begin.type.args):
2274 error(self.pos, "missing begin() on %s" % self.sequence.type)
2275 self.type = error_type
2276 return
2277 if (end is None
2278 or not end.type.is_cfunction
2279 or end.type.args):
2280 error(self.pos, "missing end() on %s" % self.sequence.type)
2281 self.type = error_type
2282 return
2283 iter_type = begin.type.return_type
2284 if iter_type.is_cpp_class:
2285 if env.lookup_operator_for_types(
2286 self.pos,
2287 "!=",
2288 [iter_type, end.type.return_type]) is None:
2289 error(self.pos, "missing operator!= on result of begin() on %s" % self.sequence.type)
2290 self.type = error_type
2291 return
2292 if env.lookup_operator_for_types(self.pos, '++', [iter_type]) is None:
2293 error(self.pos, "missing operator++ on result of begin() on %s" % self.sequence.type)
2294 self.type = error_type
2295 return
2296 if env.lookup_operator_for_types(self.pos, '*', [iter_type]) is None:
2297 error(self.pos, "missing operator* on result of begin() on %s" % self.sequence.type)
2298 self.type = error_type
2299 return
2300 self.type = iter_type
2301 elif iter_type.is_ptr:
2302 if not (iter_type == end.type.return_type):
2303 error(self.pos, "incompatible types for begin() and end()")
2304 self.type = iter_type
2305 else:
2306 error(self.pos, "result type of begin() on %s must be a C++ class or pointer" % self.sequence.type)
2307 self.type = error_type
2308 return
2310 def generate_result_code(self, code):
2311 sequence_type = self.sequence.type
2312 if sequence_type.is_cpp_class:
2313 if self.sequence.is_name:
2314 # safe: C++ won't allow you to reassign to class references
2315 begin_func = "%s.begin" % self.sequence.result()
2316 else:
2317 sequence_type = PyrexTypes.c_ptr_type(sequence_type)
2318 self.cpp_iterator_cname = code.funcstate.allocate_temp(sequence_type, manage_ref=False)
2319 code.putln("%s = &%s;" % (self.cpp_iterator_cname, self.sequence.result()))
2320 begin_func = "%s->begin" % self.cpp_iterator_cname
2321 # TODO: Limit scope.
2322 code.putln("%s = %s();" % (self.result(), begin_func))
2323 return
2324 if sequence_type.is_array or sequence_type.is_ptr:
2325 raise InternalError("for in carray slice not transformed")
2326 is_builtin_sequence = sequence_type is list_type or \
2327 sequence_type is tuple_type
2328 if not is_builtin_sequence:
2329 # reversed() not currently optimised (see Optimize.py)
2330 assert not self.reversed, "internal error: reversed() only implemented for list/tuple objects"
2331 self.may_be_a_sequence = not sequence_type.is_builtin_type
2332 if self.may_be_a_sequence:
2333 code.putln(
2334 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
2335 self.sequence.py_result(),
2336 self.sequence.py_result()))
2337 if is_builtin_sequence or self.may_be_a_sequence:
2338 self.counter_cname = code.funcstate.allocate_temp(
2339 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2340 if self.reversed:
2341 if sequence_type is list_type:
2342 init_value = 'PyList_GET_SIZE(%s) - 1' % self.result()
2343 else:
2344 init_value = 'PyTuple_GET_SIZE(%s) - 1' % self.result()
2345 else:
2346 init_value = '0'
2347 code.putln(
2348 "%s = %s; __Pyx_INCREF(%s); %s = %s;" % (
2349 self.result(),
2350 self.sequence.py_result(),
2351 self.result(),
2352 self.counter_cname,
2353 init_value
2355 if not is_builtin_sequence:
2356 self.iter_func_ptr = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False)
2357 if self.may_be_a_sequence:
2358 code.putln("%s = NULL;" % self.iter_func_ptr)
2359 code.putln("} else {")
2360 code.put("%s = -1; " % self.counter_cname)
2361 code.putln("%s = PyObject_GetIter(%s); %s" % (
2362 self.result(),
2363 self.sequence.py_result(),
2364 code.error_goto_if_null(self.result(), self.pos)))
2365 code.put_gotref(self.py_result())
2366 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % (self.iter_func_ptr, self.py_result()))
2367 if self.may_be_a_sequence:
2368 code.putln("}")
2370 def generate_next_sequence_item(self, test_name, result_name, code):
2371 assert self.counter_cname, "internal error: counter_cname temp not prepared"
2372 final_size = 'Py%s_GET_SIZE(%s)' % (test_name, self.py_result())
2373 if self.sequence.is_sequence_constructor:
2374 item_count = len(self.sequence.args)
2375 if self.sequence.mult_factor is None:
2376 final_size = item_count
2377 elif isinstance(self.sequence.mult_factor.constant_result, (int, long)):
2378 final_size = item_count * self.sequence.mult_factor.constant_result
2379 code.putln("if (%s >= %s) break;" % (self.counter_cname, final_size))
2380 if self.reversed:
2381 inc_dec = '--'
2382 else:
2383 inc_dec = '++'
2384 code.putln("#if CYTHON_COMPILING_IN_CPYTHON")
2385 code.putln(
2386 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s; %s" % (
2387 result_name,
2388 test_name,
2389 self.py_result(),
2390 self.counter_cname,
2391 result_name,
2392 self.counter_cname,
2393 inc_dec,
2394 # use the error label to avoid C compiler warnings if we only use it below
2395 code.error_goto_if_neg('0', self.pos)
2397 code.putln("#else")
2398 code.putln(
2399 "%s = PySequence_ITEM(%s, %s); %s%s; %s" % (
2400 result_name,
2401 self.py_result(),
2402 self.counter_cname,
2403 self.counter_cname,
2404 inc_dec,
2405 code.error_goto_if_null(result_name, self.pos)))
2406 code.putln("#endif")
2408 def generate_iter_next_result_code(self, result_name, code):
2409 sequence_type = self.sequence.type
2410 if self.reversed:
2411 code.putln("if (%s < 0) break;" % self.counter_cname)
2412 if sequence_type.is_cpp_class:
2413 if self.cpp_iterator_cname:
2414 end_func = "%s->end" % self.cpp_iterator_cname
2415 else:
2416 end_func = "%s.end" % self.sequence.result()
2417 # TODO: Cache end() call?
2418 code.putln("if (!(%s != %s())) break;" % (
2419 self.result(),
2420 end_func))
2421 code.putln("%s = *%s;" % (
2422 result_name,
2423 self.result()))
2424 code.putln("++%s;" % self.result())
2425 return
2426 elif sequence_type is list_type:
2427 self.generate_next_sequence_item('List', result_name, code)
2428 return
2429 elif sequence_type is tuple_type:
2430 self.generate_next_sequence_item('Tuple', result_name, code)
2431 return
2433 if self.may_be_a_sequence:
2434 for test_name in ('List', 'Tuple'):
2435 code.putln("if (!%s && Py%s_CheckExact(%s)) {" % (
2436 self.iter_func_ptr, test_name, self.py_result()))
2437 self.generate_next_sequence_item(test_name, result_name, code)
2438 code.put("} else ")
2440 code.putln("{")
2441 code.putln(
2442 "%s = %s(%s);" % (
2443 result_name,
2444 self.iter_func_ptr,
2445 self.py_result()))
2446 code.putln("if (unlikely(!%s)) {" % result_name)
2447 code.putln("PyObject* exc_type = PyErr_Occurred();")
2448 code.putln("if (exc_type) {")
2449 code.putln("if (likely(exc_type == PyExc_StopIteration ||"
2450 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();")
2451 code.putln("else %s" % code.error_goto(self.pos))
2452 code.putln("}")
2453 code.putln("break;")
2454 code.putln("}")
2455 code.put_gotref(result_name)
2456 code.putln("}")
2458 def free_temps(self, code):
2459 if self.counter_cname:
2460 code.funcstate.release_temp(self.counter_cname)
2461 if self.iter_func_ptr:
2462 code.funcstate.release_temp(self.iter_func_ptr)
2463 self.iter_func_ptr = None
2464 if self.cpp_iterator_cname:
2465 code.funcstate.release_temp(self.cpp_iterator_cname)
2466 ExprNode.free_temps(self, code)
2469 class NextNode(AtomicExprNode):
2470 # Used as part of for statement implementation.
2471 # Implements result = iterator.next()
2472 # Created during analyse_types phase.
2473 # The iterator is not owned by this node.
2475 # iterator IteratorNode
2477 def __init__(self, iterator):
2478 AtomicExprNode.__init__(self, iterator.pos)
2479 self.iterator = iterator
2481 def type_dependencies(self, env):
2482 return self.iterator.type_dependencies(env)
2484 def infer_type(self, env, iterator_type = None):
2485 if iterator_type is None:
2486 iterator_type = self.iterator.infer_type(env)
2487 if iterator_type.is_ptr or iterator_type.is_array:
2488 return iterator_type.base_type
2489 elif iterator_type.is_cpp_class:
2490 item_type = env.lookup_operator_for_types(self.pos, "*", [iterator_type]).type.return_type
2491 if item_type.is_reference:
2492 item_type = item_type.ref_base_type
2493 if item_type.is_const:
2494 item_type = item_type.const_base_type
2495 return item_type
2496 else:
2497 # Avoid duplication of complicated logic.
2498 fake_index_node = IndexNode(
2499 self.pos,
2500 base=self.iterator.sequence,
2501 index=IntNode(self.pos, value='PY_SSIZE_T_MAX',
2502 type=PyrexTypes.c_py_ssize_t_type))
2503 return fake_index_node.infer_type(env)
2505 def analyse_types(self, env):
2506 self.type = self.infer_type(env, self.iterator.type)
2507 self.is_temp = 1
2508 return self
2510 def generate_result_code(self, code):
2511 self.iterator.generate_iter_next_result_code(self.result(), code)
2514 class WithExitCallNode(ExprNode):
2515 # The __exit__() call of a 'with' statement. Used in both the
2516 # except and finally clauses.
2518 # with_stat WithStatNode the surrounding 'with' statement
2519 # args TupleNode or ResultStatNode the exception info tuple
2521 subexprs = ['args']
2522 test_if_run = True
2524 def analyse_types(self, env):
2525 self.args = self.args.analyse_types(env)
2526 self.type = PyrexTypes.c_bint_type
2527 self.is_temp = True
2528 return self
2530 def generate_evaluation_code(self, code):
2531 if self.test_if_run:
2532 # call only if it was not already called (and decref-cleared)
2533 code.putln("if (%s) {" % self.with_stat.exit_var)
2535 self.args.generate_evaluation_code(code)
2536 result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
2538 code.mark_pos(self.pos)
2539 code.globalstate.use_utility_code(UtilityCode.load_cached(
2540 "PyObjectCall", "ObjectHandling.c"))
2541 code.putln("%s = __Pyx_PyObject_Call(%s, %s, NULL);" % (
2542 result_var,
2543 self.with_stat.exit_var,
2544 self.args.result()))
2545 code.put_decref_clear(self.with_stat.exit_var, type=py_object_type)
2546 self.args.generate_disposal_code(code)
2547 self.args.free_temps(code)
2549 code.putln(code.error_goto_if_null(result_var, self.pos))
2550 code.put_gotref(result_var)
2551 if self.result_is_used:
2552 self.allocate_temp_result(code)
2553 code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var))
2554 code.put_decref_clear(result_var, type=py_object_type)
2555 if self.result_is_used:
2556 code.put_error_if_neg(self.pos, self.result())
2557 code.funcstate.release_temp(result_var)
2558 if self.test_if_run:
2559 code.putln("}")
2562 class ExcValueNode(AtomicExprNode):
2563 # Node created during analyse_types phase
2564 # of an ExceptClauseNode to fetch the current
2565 # exception value.
2567 type = py_object_type
2569 def __init__(self, pos):
2570 ExprNode.__init__(self, pos)
2572 def set_var(self, var):
2573 self.var = var
2575 def calculate_result_code(self):
2576 return self.var
2578 def generate_result_code(self, code):
2579 pass
2581 def analyse_types(self, env):
2582 return self
2585 class TempNode(ExprNode):
2586 # Node created during analyse_types phase
2587 # of some nodes to hold a temporary value.
2589 # Note: One must call "allocate" and "release" on
2590 # the node during code generation to get/release the temp.
2591 # This is because the temp result is often used outside of
2592 # the regular cycle.
2594 subexprs = []
2596 def __init__(self, pos, type, env=None):
2597 ExprNode.__init__(self, pos)
2598 self.type = type
2599 if type.is_pyobject:
2600 self.result_ctype = py_object_type
2601 self.is_temp = 1
2603 def analyse_types(self, env):
2604 return self
2606 def analyse_target_declaration(self, env):
2607 pass
2609 def generate_result_code(self, code):
2610 pass
2612 def allocate(self, code):
2613 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
2615 def release(self, code):
2616 code.funcstate.release_temp(self.temp_cname)
2617 self.temp_cname = None
2619 def result(self):
2620 try:
2621 return self.temp_cname
2622 except:
2623 assert False, "Remember to call allocate/release on TempNode"
2624 raise
2626 # Do not participate in normal temp alloc/dealloc:
2627 def allocate_temp_result(self, code):
2628 pass
2630 def release_temp_result(self, code):
2631 pass
2633 class PyTempNode(TempNode):
2634 # TempNode holding a Python value.
2636 def __init__(self, pos, env):
2637 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
2639 class RawCNameExprNode(ExprNode):
2640 subexprs = []
2642 def __init__(self, pos, type=None, cname=None):
2643 ExprNode.__init__(self, pos, type=type)
2644 if cname is not None:
2645 self.cname = cname
2647 def analyse_types(self, env):
2648 return self
2650 def set_cname(self, cname):
2651 self.cname = cname
2653 def result(self):
2654 return self.cname
2656 def generate_result_code(self, code):
2657 pass
2660 #-------------------------------------------------------------------
2662 # Parallel nodes (cython.parallel.thread(savailable|id))
2664 #-------------------------------------------------------------------
2666 class ParallelThreadsAvailableNode(AtomicExprNode):
2668 Note: this is disabled and not a valid directive at this moment
2670 Implements cython.parallel.threadsavailable(). If we are called from the
2671 sequential part of the application, we need to call omp_get_max_threads(),
2672 and in the parallel part we can just call omp_get_num_threads()
2675 type = PyrexTypes.c_int_type
2677 def analyse_types(self, env):
2678 self.is_temp = True
2679 # env.add_include_file("omp.h")
2680 return self
2682 def generate_result_code(self, code):
2683 code.putln("#ifdef _OPENMP")
2684 code.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" %
2685 self.temp_code)
2686 code.putln("else %s = omp_get_num_threads();" % self.temp_code)
2687 code.putln("#else")
2688 code.putln("%s = 1;" % self.temp_code)
2689 code.putln("#endif")
2691 def result(self):
2692 return self.temp_code
2695 class ParallelThreadIdNode(AtomicExprNode): #, Nodes.ParallelNode):
2697 Implements cython.parallel.threadid()
2700 type = PyrexTypes.c_int_type
2702 def analyse_types(self, env):
2703 self.is_temp = True
2704 # env.add_include_file("omp.h")
2705 return self
2707 def generate_result_code(self, code):
2708 code.putln("#ifdef _OPENMP")
2709 code.putln("%s = omp_get_thread_num();" % self.temp_code)
2710 code.putln("#else")
2711 code.putln("%s = 0;" % self.temp_code)
2712 code.putln("#endif")
2714 def result(self):
2715 return self.temp_code
2718 #-------------------------------------------------------------------
2720 # Trailer nodes
2722 #-------------------------------------------------------------------
2724 class IndexNode(ExprNode):
2725 # Sequence indexing.
2727 # base ExprNode
2728 # index ExprNode
2729 # indices [ExprNode]
2730 # type_indices [PyrexType]
2731 # is_buffer_access boolean Whether this is a buffer access.
2733 # indices is used on buffer access, index on non-buffer access.
2734 # The former contains a clean list of index parameters, the
2735 # latter whatever Python object is needed for index access.
2737 # is_fused_index boolean Whether the index is used to specialize a
2738 # c(p)def function
2740 subexprs = ['base', 'index', 'indices']
2741 indices = None
2742 type_indices = None
2744 is_subscript = True
2745 is_fused_index = False
2747 # Whether we're assigning to a buffer (in that case it needs to be
2748 # writable)
2749 writable_needed = False
2751 # Whether we are indexing or slicing a memoryviewslice
2752 memslice_index = False
2753 memslice_slice = False
2754 is_memslice_copy = False
2755 memslice_ellipsis_noop = False
2756 warned_untyped_idx = False
2757 # set by SingleAssignmentNode after analyse_types()
2758 is_memslice_scalar_assignment = False
2760 def __init__(self, pos, index, **kw):
2761 ExprNode.__init__(self, pos, index=index, **kw)
2762 self._index = index
2764 def calculate_constant_result(self):
2765 self.constant_result = \
2766 self.base.constant_result[self.index.constant_result]
2768 def compile_time_value(self, denv):
2769 base = self.base.compile_time_value(denv)
2770 index = self.index.compile_time_value(denv)
2771 try:
2772 return base[index]
2773 except Exception, e:
2774 self.compile_time_value_error(e)
2776 def is_ephemeral(self):
2777 return self.base.is_ephemeral()
2779 def is_simple(self):
2780 if self.is_buffer_access or self.memslice_index:
2781 return False
2782 elif self.memslice_slice:
2783 return True
2785 base = self.base
2786 return (base.is_simple() and self.index.is_simple()
2787 and base.type and (base.type.is_ptr or base.type.is_array))
2789 def may_be_none(self):
2790 base_type = self.base.type
2791 if base_type:
2792 if base_type.is_string:
2793 return False
2794 if isinstance(self.index, SliceNode):
2795 # slicing!
2796 if base_type in (bytes_type, str_type, unicode_type,
2797 basestring_type, list_type, tuple_type):
2798 return False
2799 return ExprNode.may_be_none(self)
2801 def analyse_target_declaration(self, env):
2802 pass
2804 def analyse_as_type(self, env):
2805 base_type = self.base.analyse_as_type(env)
2806 if base_type and not base_type.is_pyobject:
2807 if base_type.is_cpp_class:
2808 if isinstance(self.index, TupleNode):
2809 template_values = self.index.args
2810 else:
2811 template_values = [self.index]
2812 import Nodes
2813 type_node = Nodes.TemplatedTypeNode(
2814 pos = self.pos,
2815 positional_args = template_values,
2816 keyword_args = None)
2817 return type_node.analyse(env, base_type = base_type)
2818 else:
2819 index = self.index.compile_time_value(env)
2820 if index is not None:
2821 return PyrexTypes.CArrayType(base_type, int(index))
2822 error(self.pos, "Array size must be a compile time constant")
2823 return None
2825 def type_dependencies(self, env):
2826 return self.base.type_dependencies(env) + self.index.type_dependencies(env)
2828 def infer_type(self, env):
2829 base_type = self.base.infer_type(env)
2830 if isinstance(self.index, SliceNode):
2831 # slicing!
2832 if base_type.is_string:
2833 # sliced C strings must coerce to Python
2834 return bytes_type
2835 elif base_type.is_pyunicode_ptr:
2836 # sliced Py_UNICODE* strings must coerce to Python
2837 return unicode_type
2838 elif base_type in (unicode_type, bytes_type, str_type,
2839 bytearray_type, list_type, tuple_type):
2840 # slicing these returns the same type
2841 return base_type
2842 else:
2843 # TODO: Handle buffers (hopefully without too much redundancy).
2844 return py_object_type
2846 index_type = self.index.infer_type(env)
2847 if index_type and index_type.is_int or isinstance(self.index, IntNode):
2848 # indexing!
2849 if base_type is unicode_type:
2850 # Py_UCS4 will automatically coerce to a unicode string
2851 # if required, so this is safe. We only infer Py_UCS4
2852 # when the index is a C integer type. Otherwise, we may
2853 # need to use normal Python item access, in which case
2854 # it's faster to return the one-char unicode string than
2855 # to receive it, throw it away, and potentially rebuild it
2856 # on a subsequent PyObject coercion.
2857 return PyrexTypes.c_py_ucs4_type
2858 elif base_type is str_type:
2859 # always returns str - Py2: bytes, Py3: unicode
2860 return base_type
2861 elif base_type is bytearray_type:
2862 return PyrexTypes.c_uchar_type
2863 elif isinstance(self.base, BytesNode):
2864 #if env.global_scope().context.language_level >= 3:
2865 # # inferring 'char' can be made to work in Python 3 mode
2866 # return PyrexTypes.c_char_type
2867 # Py2/3 return different types on indexing bytes objects
2868 return py_object_type
2869 elif base_type in (tuple_type, list_type):
2870 # if base is a literal, take a look at its values
2871 item_type = infer_sequence_item_type(
2872 env, self.base, self.index, seq_type=base_type)
2873 if item_type is not None:
2874 return item_type
2875 elif base_type.is_ptr or base_type.is_array:
2876 return base_type.base_type
2878 if base_type.is_cpp_class:
2879 class FakeOperand:
2880 def __init__(self, **kwds):
2881 self.__dict__.update(kwds)
2882 operands = [
2883 FakeOperand(pos=self.pos, type=base_type),
2884 FakeOperand(pos=self.pos, type=index_type),
2886 index_func = env.lookup_operator('[]', operands)
2887 if index_func is not None:
2888 return index_func.type.return_type
2890 # may be slicing or indexing, we don't know
2891 if base_type in (unicode_type, str_type):
2892 # these types always returns their own type on Python indexing/slicing
2893 return base_type
2894 else:
2895 # TODO: Handle buffers (hopefully without too much redundancy).
2896 return py_object_type
2898 def analyse_types(self, env):
2899 return self.analyse_base_and_index_types(env, getting=True)
2901 def analyse_target_types(self, env):
2902 node = self.analyse_base_and_index_types(env, setting=True)
2903 if node.type.is_const:
2904 error(self.pos, "Assignment to const dereference")
2905 if not node.is_lvalue():
2906 error(self.pos, "Assignment to non-lvalue of type '%s'" % node.type)
2907 return node
2909 def analyse_base_and_index_types(self, env, getting=False, setting=False,
2910 analyse_base=True):
2911 # Note: This might be cleaned up by having IndexNode
2912 # parsed in a saner way and only construct the tuple if
2913 # needed.
2915 # Note that this function must leave IndexNode in a cloneable state.
2916 # For buffers, self.index is packed out on the initial analysis, and
2917 # when cloning self.indices is copied.
2918 self.is_buffer_access = False
2920 # a[...] = b
2921 self.is_memslice_copy = False
2922 # incomplete indexing, Ellipsis indexing or slicing
2923 self.memslice_slice = False
2924 # integer indexing
2925 self.memslice_index = False
2927 if analyse_base:
2928 self.base = self.base.analyse_types(env)
2930 if self.base.type.is_error:
2931 # Do not visit child tree if base is undeclared to avoid confusing
2932 # error messages
2933 self.type = PyrexTypes.error_type
2934 return self
2936 is_slice = isinstance(self.index, SliceNode)
2938 if not env.directives['wraparound']:
2939 if is_slice:
2940 check_negative_indices(self.index.start, self.index.stop)
2941 else:
2942 check_negative_indices(self.index)
2944 # Potentially overflowing index value.
2945 if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value):
2946 self.index = self.index.coerce_to_pyobject(env)
2948 is_memslice = self.base.type.is_memoryviewslice
2950 # Handle the case where base is a literal char* (and we expect a string, not an int)
2951 if not is_memslice and (isinstance(self.base, BytesNode) or is_slice):
2952 if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array):
2953 self.base = self.base.coerce_to_pyobject(env)
2955 skip_child_analysis = False
2956 buffer_access = False
2958 if self.indices:
2959 indices = self.indices
2960 elif isinstance(self.index, TupleNode):
2961 indices = self.index.args
2962 else:
2963 indices = [self.index]
2965 if (is_memslice and not self.indices and
2966 isinstance(self.index, EllipsisNode)):
2967 # Memoryviewslice copying
2968 self.is_memslice_copy = True
2970 elif is_memslice:
2971 # memoryviewslice indexing or slicing
2972 import MemoryView
2974 skip_child_analysis = True
2975 newaxes = [newaxis for newaxis in indices if newaxis.is_none]
2976 have_slices, indices = MemoryView.unellipsify(indices,
2977 newaxes,
2978 self.base.type.ndim)
2980 self.memslice_index = (not newaxes and
2981 len(indices) == self.base.type.ndim)
2982 axes = []
2984 index_type = PyrexTypes.c_py_ssize_t_type
2985 new_indices = []
2987 if len(indices) - len(newaxes) > self.base.type.ndim:
2988 self.type = error_type
2989 error(indices[self.base.type.ndim].pos,
2990 "Too many indices specified for type %s" %
2991 self.base.type)
2992 return self
2994 axis_idx = 0
2995 for i, index in enumerate(indices[:]):
2996 index = index.analyse_types(env)
2997 if not index.is_none:
2998 access, packing = self.base.type.axes[axis_idx]
2999 axis_idx += 1
3001 if isinstance(index, SliceNode):
3002 self.memslice_slice = True
3003 if index.step.is_none:
3004 axes.append((access, packing))
3005 else:
3006 axes.append((access, 'strided'))
3008 # Coerce start, stop and step to temps of the right type
3009 for attr in ('start', 'stop', 'step'):
3010 value = getattr(index, attr)
3011 if not value.is_none:
3012 value = value.coerce_to(index_type, env)
3013 #value = value.coerce_to_temp(env)
3014 setattr(index, attr, value)
3015 new_indices.append(value)
3017 elif index.is_none:
3018 self.memslice_slice = True
3019 new_indices.append(index)
3020 axes.append(('direct', 'strided'))
3022 elif index.type.is_int or index.type.is_pyobject:
3023 if index.type.is_pyobject and not self.warned_untyped_idx:
3024 warning(index.pos, "Index should be typed for more "
3025 "efficient access", level=2)
3026 IndexNode.warned_untyped_idx = True
3028 self.memslice_index = True
3029 index = index.coerce_to(index_type, env)
3030 indices[i] = index
3031 new_indices.append(index)
3033 else:
3034 self.type = error_type
3035 error(index.pos, "Invalid index for memoryview specified")
3036 return self
3038 self.memslice_index = self.memslice_index and not self.memslice_slice
3039 self.original_indices = indices
3040 # All indices with all start/stop/step for slices.
3041 # We need to keep this around
3042 self.indices = new_indices
3043 self.env = env
3045 elif self.base.type.is_buffer:
3046 # Buffer indexing
3047 if len(indices) == self.base.type.ndim:
3048 buffer_access = True
3049 skip_child_analysis = True
3050 for x in indices:
3051 x = x.analyse_types(env)
3052 if not x.type.is_int:
3053 buffer_access = False
3055 if buffer_access and not self.base.type.is_memoryviewslice:
3056 assert hasattr(self.base, "entry") # Must be a NameNode-like node
3058 # On cloning, indices is cloned. Otherwise, unpack index into indices
3059 assert not (buffer_access and isinstance(self.index, CloneNode))
3061 self.nogil = env.nogil
3063 if buffer_access or self.memslice_index:
3064 #if self.base.type.is_memoryviewslice and not self.base.is_name:
3065 # self.base = self.base.coerce_to_temp(env)
3066 self.base = self.base.coerce_to_simple(env)
3068 self.indices = indices
3069 self.index = None
3070 self.type = self.base.type.dtype
3071 self.is_buffer_access = True
3072 self.buffer_type = self.base.type #self.base.entry.type
3074 if getting and self.type.is_pyobject:
3075 self.is_temp = True
3077 if setting and self.base.type.is_memoryviewslice:
3078 self.base.type.writable_needed = True
3079 elif setting:
3080 if not self.base.entry.type.writable:
3081 error(self.pos, "Writing to readonly buffer")
3082 else:
3083 self.writable_needed = True
3084 if self.base.type.is_buffer:
3085 self.base.entry.buffer_aux.writable_needed = True
3087 elif self.is_memslice_copy:
3088 self.type = self.base.type
3089 if getting:
3090 self.memslice_ellipsis_noop = True
3091 else:
3092 self.memslice_broadcast = True
3094 elif self.memslice_slice:
3095 self.index = None
3096 self.is_temp = True
3097 self.use_managed_ref = True
3099 if not MemoryView.validate_axes(self.pos, axes):
3100 self.type = error_type
3101 return self
3103 self.type = PyrexTypes.MemoryViewSliceType(
3104 self.base.type.dtype, axes)
3106 if (self.base.type.is_memoryviewslice and not
3107 self.base.is_name and not
3108 self.base.result_in_temp()):
3109 self.base = self.base.coerce_to_temp(env)
3111 if setting:
3112 self.memslice_broadcast = True
3114 else:
3115 base_type = self.base.type
3117 if not base_type.is_cfunction:
3118 if isinstance(self.index, TupleNode):
3119 self.index = self.index.analyse_types(
3120 env, skip_children=skip_child_analysis)
3121 elif not skip_child_analysis:
3122 self.index = self.index.analyse_types(env)
3123 self.original_index_type = self.index.type
3125 if base_type.is_unicode_char:
3126 # we infer Py_UNICODE/Py_UCS4 for unicode strings in some
3127 # cases, but indexing must still work for them
3128 if setting:
3129 warning(self.pos, "cannot assign to Unicode string index", level=1)
3130 elif self.index.constant_result in (0, -1):
3131 # uchar[0] => uchar
3132 return self.base
3133 self.base = self.base.coerce_to_pyobject(env)
3134 base_type = self.base.type
3135 if base_type.is_pyobject:
3136 if self.index.type.is_int and base_type is not dict_type:
3137 if (getting
3138 and (base_type in (list_type, tuple_type, bytearray_type))
3139 and (not self.index.type.signed
3140 or not env.directives['wraparound']
3141 or (isinstance(self.index, IntNode) and
3142 self.index.has_constant_result() and self.index.constant_result >= 0))
3143 and not env.directives['boundscheck']):
3144 self.is_temp = 0
3145 else:
3146 self.is_temp = 1
3147 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
3148 self.original_index_type.create_to_py_utility_code(env)
3149 else:
3150 self.index = self.index.coerce_to_pyobject(env)
3151 self.is_temp = 1
3152 if self.index.type.is_int and base_type is unicode_type:
3153 # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string
3154 # if required, so this is fast and safe
3155 self.type = PyrexTypes.c_py_ucs4_type
3156 elif self.index.type.is_int and base_type is bytearray_type:
3157 if setting:
3158 self.type = PyrexTypes.c_uchar_type
3159 else:
3160 # not using 'uchar' to enable fast and safe error reporting as '-1'
3161 self.type = PyrexTypes.c_int_type
3162 elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type):
3163 self.type = base_type
3164 else:
3165 item_type = None
3166 if base_type in (list_type, tuple_type) and self.index.type.is_int:
3167 item_type = infer_sequence_item_type(
3168 env, self.base, self.index, seq_type=base_type)
3169 if item_type is None:
3170 item_type = py_object_type
3171 self.type = item_type
3172 if base_type in (list_type, tuple_type, dict_type):
3173 # do the None check explicitly (not in a helper) to allow optimising it away
3174 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable")
3175 else:
3176 if base_type.is_ptr or base_type.is_array:
3177 self.type = base_type.base_type
3178 if is_slice:
3179 self.type = base_type
3180 elif self.index.type.is_pyobject:
3181 self.index = self.index.coerce_to(
3182 PyrexTypes.c_py_ssize_t_type, env)
3183 elif not self.index.type.is_int:
3184 error(self.pos,
3185 "Invalid index type '%s'" %
3186 self.index.type)
3187 elif base_type.is_cpp_class:
3188 function = env.lookup_operator("[]", [self.base, self.index])
3189 if function is None:
3190 error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type))
3191 self.type = PyrexTypes.error_type
3192 self.result_code = "<error>"
3193 return self
3194 func_type = function.type
3195 if func_type.is_ptr:
3196 func_type = func_type.base_type
3197 self.index = self.index.coerce_to(func_type.args[0].type, env)
3198 self.type = func_type.return_type
3199 if setting and not func_type.return_type.is_reference:
3200 error(self.pos, "Can't set non-reference result '%s'" % self.type)
3201 elif base_type.is_cfunction:
3202 if base_type.is_fused:
3203 self.parse_indexed_fused_cdef(env)
3204 else:
3205 self.type_indices = self.parse_index_as_types(env)
3206 if base_type.templates is None:
3207 error(self.pos, "Can only parameterize template functions.")
3208 elif len(base_type.templates) != len(self.type_indices):
3209 error(self.pos, "Wrong number of template arguments: expected %s, got %s" % (
3210 (len(base_type.templates), len(self.type_indices))))
3211 self.type = base_type.specialize(dict(zip(base_type.templates, self.type_indices)))
3212 else:
3213 error(self.pos,
3214 "Attempting to index non-array type '%s'" %
3215 base_type)
3216 self.type = PyrexTypes.error_type
3218 self.wrap_in_nonecheck_node(env, getting)
3219 return self
3221 def wrap_in_nonecheck_node(self, env, getting):
3222 if not env.directives['nonecheck'] or not self.base.may_be_none():
3223 return
3225 if self.base.type.is_memoryviewslice:
3226 if self.is_memslice_copy and not getting:
3227 msg = "Cannot assign to None memoryview slice"
3228 elif self.memslice_slice:
3229 msg = "Cannot slice None memoryview slice"
3230 else:
3231 msg = "Cannot index None memoryview slice"
3232 else:
3233 msg = "'NoneType' object is not subscriptable"
3235 self.base = self.base.as_none_safe_node(msg)
3237 def parse_index_as_types(self, env, required=True):
3238 if isinstance(self.index, TupleNode):
3239 indices = self.index.args
3240 else:
3241 indices = [self.index]
3242 type_indices = []
3243 for index in indices:
3244 type_indices.append(index.analyse_as_type(env))
3245 if type_indices[-1] is None:
3246 if required:
3247 error(index.pos, "not parsable as a type")
3248 return None
3249 return type_indices
3251 def parse_indexed_fused_cdef(self, env):
3253 Interpret fused_cdef_func[specific_type1, ...]
3255 Note that if this method is called, we are an indexed cdef function
3256 with fused argument types, and this IndexNode will be replaced by the
3257 NameNode with specific entry just after analysis of expressions by
3258 AnalyseExpressionsTransform.
3260 self.type = PyrexTypes.error_type
3262 self.is_fused_index = True
3264 base_type = self.base.type
3265 specific_types = []
3266 positions = []
3268 if self.index.is_name or self.index.is_attribute:
3269 positions.append(self.index.pos)
3270 elif isinstance(self.index, TupleNode):
3271 for arg in self.index.args:
3272 positions.append(arg.pos)
3273 specific_types = self.parse_index_as_types(env, required=False)
3275 if specific_types is None:
3276 self.index = self.index.analyse_types(env)
3278 if not self.base.entry.as_variable:
3279 error(self.pos, "Can only index fused functions with types")
3280 else:
3281 # A cpdef function indexed with Python objects
3282 self.base.entry = self.entry = self.base.entry.as_variable
3283 self.base.type = self.type = self.entry.type
3285 self.base.is_temp = True
3286 self.is_temp = True
3288 self.entry.used = True
3290 self.is_fused_index = False
3291 return
3293 for i, type in enumerate(specific_types):
3294 specific_types[i] = type.specialize_fused(env)
3296 fused_types = base_type.get_fused_types()
3297 if len(specific_types) > len(fused_types):
3298 return error(self.pos, "Too many types specified")
3299 elif len(specific_types) < len(fused_types):
3300 t = fused_types[len(specific_types)]
3301 return error(self.pos, "Not enough types specified to specialize "
3302 "the function, %s is still fused" % t)
3304 # See if our index types form valid specializations
3305 for pos, specific_type, fused_type in zip(positions,
3306 specific_types,
3307 fused_types):
3308 if not Utils.any([specific_type.same_as(t)
3309 for t in fused_type.types]):
3310 return error(pos, "Type not in fused type")
3312 if specific_type is None or specific_type.is_error:
3313 return
3315 fused_to_specific = dict(zip(fused_types, specific_types))
3316 type = base_type.specialize(fused_to_specific)
3318 if type.is_fused:
3319 # Only partially specific, this is invalid
3320 error(self.pos,
3321 "Index operation makes function only partially specific")
3322 else:
3323 # Fully specific, find the signature with the specialized entry
3324 for signature in self.base.type.get_all_specialized_function_types():
3325 if type.same_as(signature):
3326 self.type = signature
3328 if self.base.is_attribute:
3329 # Pretend to be a normal attribute, for cdef extension
3330 # methods
3331 self.entry = signature.entry
3332 self.is_attribute = True
3333 self.obj = self.base.obj
3335 self.type.entry.used = True
3336 self.base.type = signature
3337 self.base.entry = signature.entry
3339 break
3340 else:
3341 # This is a bug
3342 raise InternalError("Couldn't find the right signature")
3344 gil_message = "Indexing Python object"
3346 def nogil_check(self, env):
3347 if self.is_buffer_access or self.memslice_index or self.memslice_slice:
3348 if not self.memslice_slice and env.directives['boundscheck']:
3349 # error(self.pos, "Cannot check buffer index bounds without gil; "
3350 # "use boundscheck(False) directive")
3351 warning(self.pos, "Use boundscheck(False) for faster access",
3352 level=1)
3353 if self.type.is_pyobject:
3354 error(self.pos, "Cannot access buffer with object dtype without gil")
3355 return
3356 super(IndexNode, self).nogil_check(env)
3359 def check_const_addr(self):
3360 return self.base.check_const_addr() and self.index.check_const()
3362 def is_lvalue(self):
3363 # NOTE: references currently have both is_reference and is_ptr
3364 # set. Since pointers and references have different lvalue
3365 # rules, we must be careful to separate the two.
3366 if self.type.is_reference:
3367 if self.type.ref_base_type.is_array:
3368 # fixed-sized arrays aren't l-values
3369 return False
3370 elif self.type.is_ptr:
3371 # non-const pointers can always be reassigned
3372 return True
3373 elif self.type.is_array:
3374 # fixed-sized arrays aren't l-values
3375 return False
3376 # Just about everything else returned by the index operator
3377 # can be an lvalue.
3378 return True
3380 def calculate_result_code(self):
3381 if self.is_buffer_access:
3382 return "(*%s)" % self.buffer_ptr_code
3383 elif self.is_memslice_copy:
3384 return self.base.result()
3385 elif self.base.type in (list_type, tuple_type, bytearray_type):
3386 if self.base.type is list_type:
3387 index_code = "PyList_GET_ITEM(%s, %s)"
3388 elif self.base.type is tuple_type:
3389 index_code = "PyTuple_GET_ITEM(%s, %s)"
3390 elif self.base.type is bytearray_type:
3391 index_code = "((unsigned char)(PyByteArray_AS_STRING(%s)[%s]))"
3392 else:
3393 assert False, "unexpected base type in indexing: %s" % self.base.type
3394 elif self.base.type.is_cfunction:
3395 return "%s<%s>" % (
3396 self.base.result(),
3397 ",".join([param.declaration_code("") for param in self.type_indices]))
3398 else:
3399 if (self.type.is_ptr or self.type.is_array) and self.type == self.base.type:
3400 error(self.pos, "Invalid use of pointer slice")
3401 return
3402 index_code = "(%s[%s])"
3403 return index_code % (self.base.result(), self.index.result())
3405 def extra_index_params(self, code):
3406 if self.index.type.is_int:
3407 is_list = self.base.type is list_type
3408 wraparound = (
3409 bool(code.globalstate.directives['wraparound']) and
3410 self.original_index_type.signed and
3411 not (isinstance(self.index.constant_result, (int, long))
3412 and self.index.constant_result >= 0))
3413 boundscheck = bool(code.globalstate.directives['boundscheck'])
3414 return ", %s, %d, %s, %d, %d, %d" % (
3415 self.original_index_type.declaration_code(""),
3416 self.original_index_type.signed and 1 or 0,
3417 self.original_index_type.to_py_function,
3418 is_list, wraparound, boundscheck)
3419 else:
3420 return ""
3422 def generate_subexpr_evaluation_code(self, code):
3423 self.base.generate_evaluation_code(code)
3424 if self.type_indices is not None:
3425 pass
3426 elif self.indices is None:
3427 self.index.generate_evaluation_code(code)
3428 else:
3429 for i in self.indices:
3430 i.generate_evaluation_code(code)
3432 def generate_subexpr_disposal_code(self, code):
3433 self.base.generate_disposal_code(code)
3434 if self.type_indices is not None:
3435 pass
3436 elif self.indices is None:
3437 self.index.generate_disposal_code(code)
3438 else:
3439 for i in self.indices:
3440 i.generate_disposal_code(code)
3442 def free_subexpr_temps(self, code):
3443 self.base.free_temps(code)
3444 if self.indices is None:
3445 self.index.free_temps(code)
3446 else:
3447 for i in self.indices:
3448 i.free_temps(code)
3450 def generate_result_code(self, code):
3451 if self.is_buffer_access or self.memslice_index:
3452 buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code)
3453 if self.type.is_pyobject:
3454 # is_temp is True, so must pull out value and incref it.
3455 # NOTE: object temporary results for nodes are declared
3456 # as PyObject *, so we need a cast
3457 code.putln("%s = (PyObject *) *%s;" % (self.temp_code,
3458 self.buffer_ptr_code))
3459 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.temp_code)
3461 elif self.memslice_slice:
3462 self.put_memoryviewslice_slice_code(code)
3464 elif self.is_temp:
3465 if self.type.is_pyobject:
3466 error_value = 'NULL'
3467 if self.index.type.is_int:
3468 if self.base.type is list_type:
3469 function = "__Pyx_GetItemInt_List"
3470 elif self.base.type is tuple_type:
3471 function = "__Pyx_GetItemInt_Tuple"
3472 else:
3473 function = "__Pyx_GetItemInt"
3474 code.globalstate.use_utility_code(
3475 TempitaUtilityCode.load_cached("GetItemInt", "ObjectHandling.c"))
3476 else:
3477 if self.base.type is dict_type:
3478 function = "__Pyx_PyDict_GetItem"
3479 code.globalstate.use_utility_code(
3480 UtilityCode.load_cached("DictGetItem", "ObjectHandling.c"))
3481 else:
3482 function = "PyObject_GetItem"
3483 elif self.type.is_unicode_char and self.base.type is unicode_type:
3484 assert self.index.type.is_int
3485 function = "__Pyx_GetItemInt_Unicode"
3486 error_value = '(Py_UCS4)-1'
3487 code.globalstate.use_utility_code(
3488 UtilityCode.load_cached("GetItemIntUnicode", "StringTools.c"))
3489 elif self.base.type is bytearray_type:
3490 assert self.index.type.is_int
3491 assert self.type.is_int
3492 function = "__Pyx_GetItemInt_ByteArray"
3493 error_value = '-1'
3494 code.globalstate.use_utility_code(
3495 UtilityCode.load_cached("GetItemIntByteArray", "StringTools.c"))
3496 else:
3497 assert False, "unexpected type %s and base type %s for indexing" % (
3498 self.type, self.base.type)
3500 if self.index.type.is_int:
3501 index_code = self.index.result()
3502 else:
3503 index_code = self.index.py_result()
3505 code.putln(
3506 "%s = %s(%s, %s%s); if (unlikely(%s == %s)) %s;" % (
3507 self.result(),
3508 function,
3509 self.base.py_result(),
3510 index_code,
3511 self.extra_index_params(code),
3512 self.result(),
3513 error_value,
3514 code.error_goto(self.pos)))
3515 if self.type.is_pyobject:
3516 code.put_gotref(self.py_result())
3518 def generate_setitem_code(self, value_code, code):
3519 if self.index.type.is_int:
3520 if self.base.type is bytearray_type:
3521 code.globalstate.use_utility_code(
3522 UtilityCode.load_cached("SetItemIntByteArray", "StringTools.c"))
3523 function = "__Pyx_SetItemInt_ByteArray"
3524 else:
3525 code.globalstate.use_utility_code(
3526 UtilityCode.load_cached("SetItemInt", "ObjectHandling.c"))
3527 function = "__Pyx_SetItemInt"
3528 index_code = self.index.result()
3529 else:
3530 index_code = self.index.py_result()
3531 if self.base.type is dict_type:
3532 function = "PyDict_SetItem"
3533 # It would seem that we could specialized lists/tuples, but that
3534 # shouldn't happen here.
3535 # Both PyList_SetItem() and PyTuple_SetItem() take a Py_ssize_t as
3536 # index instead of an object, and bad conversion here would give
3537 # the wrong exception. Also, tuples are supposed to be immutable,
3538 # and raise a TypeError when trying to set their entries
3539 # (PyTuple_SetItem() is for creating new tuples from scratch).
3540 else:
3541 function = "PyObject_SetItem"
3542 code.putln(
3543 "if (unlikely(%s(%s, %s, %s%s) < 0)) %s" % (
3544 function,
3545 self.base.py_result(),
3546 index_code,
3547 value_code,
3548 self.extra_index_params(code),
3549 code.error_goto(self.pos)))
3551 def generate_buffer_setitem_code(self, rhs, code, op=""):
3552 # Used from generate_assignment_code and InPlaceAssignmentNode
3553 buffer_entry, ptrexpr = self.buffer_lookup_code(code)
3555 if self.buffer_type.dtype.is_pyobject:
3556 # Must manage refcounts. Decref what is already there
3557 # and incref what we put in.
3558 ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type,
3559 manage_ref=False)
3560 rhs_code = rhs.result()
3561 code.putln("%s = %s;" % (ptr, ptrexpr))
3562 code.put_gotref("*%s" % ptr)
3563 code.putln("__Pyx_INCREF(%s); __Pyx_DECREF(*%s);" % (
3564 rhs_code, ptr))
3565 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
3566 code.put_giveref("*%s" % ptr)
3567 code.funcstate.release_temp(ptr)
3568 else:
3569 # Simple case
3570 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
3572 def generate_assignment_code(self, rhs, code):
3573 generate_evaluation_code = (self.is_memslice_scalar_assignment or
3574 self.memslice_slice)
3575 if generate_evaluation_code:
3576 self.generate_evaluation_code(code)
3577 else:
3578 self.generate_subexpr_evaluation_code(code)
3580 if self.is_buffer_access or self.memslice_index:
3581 self.generate_buffer_setitem_code(rhs, code)
3582 elif self.is_memslice_scalar_assignment:
3583 self.generate_memoryviewslice_assign_scalar_code(rhs, code)
3584 elif self.memslice_slice or self.is_memslice_copy:
3585 self.generate_memoryviewslice_setslice_code(rhs, code)
3586 elif self.type.is_pyobject:
3587 self.generate_setitem_code(rhs.py_result(), code)
3588 elif self.base.type is bytearray_type:
3589 value_code = self._check_byte_value(code, rhs)
3590 self.generate_setitem_code(value_code, code)
3591 else:
3592 code.putln(
3593 "%s = %s;" % (
3594 self.result(), rhs.result()))
3596 if generate_evaluation_code:
3597 self.generate_disposal_code(code)
3598 else:
3599 self.generate_subexpr_disposal_code(code)
3600 self.free_subexpr_temps(code)
3602 rhs.generate_disposal_code(code)
3603 rhs.free_temps(code)
3605 def _check_byte_value(self, code, rhs):
3606 # TODO: should we do this generally on downcasts, or just here?
3607 assert rhs.type.is_int, repr(rhs.type)
3608 value_code = rhs.result()
3609 if rhs.has_constant_result():
3610 if 0 <= rhs.constant_result < 256:
3611 return value_code
3612 needs_cast = True # make at least the C compiler happy
3613 warning(rhs.pos,
3614 "value outside of range(0, 256)"
3615 " when assigning to byte: %s" % rhs.constant_result,
3616 level=1)
3617 else:
3618 needs_cast = rhs.type != PyrexTypes.c_uchar_type
3620 if not self.nogil:
3621 conditions = []
3622 if rhs.is_literal or rhs.type.signed:
3623 conditions.append('%s < 0' % value_code)
3624 if (rhs.is_literal or not
3625 (rhs.is_temp and rhs.type in (
3626 PyrexTypes.c_uchar_type, PyrexTypes.c_char_type,
3627 PyrexTypes.c_schar_type))):
3628 conditions.append('%s > 255' % value_code)
3629 if conditions:
3630 code.putln("if (unlikely(%s)) {" % ' || '.join(conditions))
3631 code.putln(
3632 'PyErr_SetString(PyExc_ValueError,'
3633 ' "byte must be in range(0, 256)"); %s' %
3634 code.error_goto(self.pos))
3635 code.putln("}")
3637 if needs_cast:
3638 value_code = '((unsigned char)%s)' % value_code
3639 return value_code
3641 def generate_deletion_code(self, code, ignore_nonexisting=False):
3642 self.generate_subexpr_evaluation_code(code)
3643 #if self.type.is_pyobject:
3644 if self.index.type.is_int:
3645 function = "__Pyx_DelItemInt"
3646 index_code = self.index.result()
3647 code.globalstate.use_utility_code(
3648 UtilityCode.load_cached("DelItemInt", "ObjectHandling.c"))
3649 else:
3650 index_code = self.index.py_result()
3651 if self.base.type is dict_type:
3652 function = "PyDict_DelItem"
3653 else:
3654 function = "PyObject_DelItem"
3655 code.putln(
3656 "if (%s(%s, %s%s) < 0) %s" % (
3657 function,
3658 self.base.py_result(),
3659 index_code,
3660 self.extra_index_params(code),
3661 code.error_goto(self.pos)))
3662 self.generate_subexpr_disposal_code(code)
3663 self.free_subexpr_temps(code)
3665 def buffer_entry(self):
3666 import Buffer, MemoryView
3668 base = self.base
3669 if self.base.is_nonecheck:
3670 base = base.arg
3672 if base.is_name:
3673 entry = base.entry
3674 else:
3675 # SimpleCallNode is_simple is not consistent with coerce_to_simple
3676 assert base.is_simple() or base.is_temp
3677 cname = base.result()
3678 entry = Symtab.Entry(cname, cname, self.base.type, self.base.pos)
3680 if entry.type.is_buffer:
3681 buffer_entry = Buffer.BufferEntry(entry)
3682 else:
3683 buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry)
3685 return buffer_entry
3687 def buffer_lookup_code(self, code):
3688 "ndarray[1, 2, 3] and memslice[1, 2, 3]"
3689 # Assign indices to temps
3690 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False)
3691 for i in self.indices]
3693 for temp, index in zip(index_temps, self.indices):
3694 code.putln("%s = %s;" % (temp, index.result()))
3696 # Generate buffer access code using these temps
3697 import Buffer
3698 buffer_entry = self.buffer_entry()
3699 if buffer_entry.type.is_buffer:
3700 negative_indices = buffer_entry.type.negative_indices
3701 else:
3702 negative_indices = Buffer.buffer_defaults['negative_indices']
3704 return buffer_entry, Buffer.put_buffer_lookup_code(
3705 entry=buffer_entry,
3706 index_signeds=[i.type.signed for i in self.indices],
3707 index_cnames=index_temps,
3708 directives=code.globalstate.directives,
3709 pos=self.pos, code=code,
3710 negative_indices=negative_indices,
3711 in_nogil_context=self.in_nogil_context)
3713 def put_memoryviewslice_slice_code(self, code):
3714 "memslice[:]"
3715 buffer_entry = self.buffer_entry()
3716 have_gil = not self.in_nogil_context
3718 if sys.version_info < (3,):
3719 def next_(it):
3720 return it.next()
3721 else:
3722 next_ = next
3724 have_slices = False
3725 it = iter(self.indices)
3726 for index in self.original_indices:
3727 is_slice = isinstance(index, SliceNode)
3728 have_slices = have_slices or is_slice
3729 if is_slice:
3730 if not index.start.is_none:
3731 index.start = next_(it)
3732 if not index.stop.is_none:
3733 index.stop = next_(it)
3734 if not index.step.is_none:
3735 index.step = next_(it)
3736 else:
3737 next_(it)
3739 assert not list(it)
3741 buffer_entry.generate_buffer_slice_code(code, self.original_indices,
3742 self.result(),
3743 have_gil=have_gil,
3744 have_slices=have_slices,
3745 directives=code.globalstate.directives)
3747 def generate_memoryviewslice_setslice_code(self, rhs, code):
3748 "memslice1[...] = memslice2 or memslice1[:] = memslice2"
3749 import MemoryView
3750 MemoryView.copy_broadcast_memview_src_to_dst(rhs, self, code)
3752 def generate_memoryviewslice_assign_scalar_code(self, rhs, code):
3753 "memslice1[...] = 0.0 or memslice1[:] = 0.0"
3754 import MemoryView
3755 MemoryView.assign_scalar(self, rhs, code)
3758 class SliceIndexNode(ExprNode):
3759 # 2-element slice indexing
3761 # base ExprNode
3762 # start ExprNode or None
3763 # stop ExprNode or None
3764 # slice ExprNode or None constant slice object
3766 subexprs = ['base', 'start', 'stop', 'slice']
3768 slice = None
3770 def infer_type(self, env):
3771 base_type = self.base.infer_type(env)
3772 if base_type.is_string or base_type.is_cpp_class:
3773 return bytes_type
3774 elif base_type.is_pyunicode_ptr:
3775 return unicode_type
3776 elif base_type in (bytes_type, str_type, unicode_type,
3777 basestring_type, list_type, tuple_type):
3778 return base_type
3779 elif base_type.is_ptr or base_type.is_array:
3780 return PyrexTypes.c_array_type(base_type.base_type, None)
3781 return py_object_type
3783 def may_be_none(self):
3784 base_type = self.base.type
3785 if base_type:
3786 if base_type.is_string:
3787 return False
3788 if base_type in (bytes_type, str_type, unicode_type,
3789 basestring_type, list_type, tuple_type):
3790 return False
3791 return ExprNode.may_be_none(self)
3793 def calculate_constant_result(self):
3794 if self.start is None:
3795 start = None
3796 else:
3797 start = self.start.constant_result
3798 if self.stop is None:
3799 stop = None
3800 else:
3801 stop = self.stop.constant_result
3802 self.constant_result = self.base.constant_result[start:stop]
3804 def compile_time_value(self, denv):
3805 base = self.base.compile_time_value(denv)
3806 if self.start is None:
3807 start = 0
3808 else:
3809 start = self.start.compile_time_value(denv)
3810 if self.stop is None:
3811 stop = None
3812 else:
3813 stop = self.stop.compile_time_value(denv)
3814 try:
3815 return base[start:stop]
3816 except Exception, e:
3817 self.compile_time_value_error(e)
3819 def analyse_target_declaration(self, env):
3820 pass
3822 def analyse_target_types(self, env):
3823 node = self.analyse_types(env, getting=False)
3824 # when assigning, we must accept any Python type
3825 if node.type.is_pyobject:
3826 node.type = py_object_type
3827 return node
3829 def analyse_types(self, env, getting=True):
3830 self.base = self.base.analyse_types(env)
3832 if self.base.type.is_memoryviewslice:
3833 none_node = NoneNode(self.pos)
3834 index = SliceNode(self.pos,
3835 start=self.start or none_node,
3836 stop=self.stop or none_node,
3837 step=none_node)
3838 index_node = IndexNode(self.pos, index, base=self.base)
3839 return index_node.analyse_base_and_index_types(
3840 env, getting=getting, setting=not getting,
3841 analyse_base=False)
3843 if self.start:
3844 self.start = self.start.analyse_types(env)
3845 if self.stop:
3846 self.stop = self.stop.analyse_types(env)
3848 if not env.directives['wraparound']:
3849 check_negative_indices(self.start, self.stop)
3851 base_type = self.base.type
3852 if base_type.is_string or base_type.is_cpp_string:
3853 self.type = default_str_type(env)
3854 elif base_type.is_pyunicode_ptr:
3855 self.type = unicode_type
3856 elif base_type.is_ptr:
3857 self.type = base_type
3858 elif base_type.is_array:
3859 # we need a ptr type here instead of an array type, as
3860 # array types can result in invalid type casts in the C
3861 # code
3862 self.type = PyrexTypes.CPtrType(base_type.base_type)
3863 else:
3864 self.base = self.base.coerce_to_pyobject(env)
3865 self.type = py_object_type
3866 if base_type.is_builtin_type:
3867 # slicing builtin types returns something of the same type
3868 self.type = base_type
3869 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable")
3871 if self.type is py_object_type:
3872 if (not self.start or self.start.is_literal) and \
3873 (not self.stop or self.stop.is_literal):
3874 # cache the constant slice object, in case we need it
3875 none_node = NoneNode(self.pos)
3876 self.slice = SliceNode(
3877 self.pos,
3878 start=copy.deepcopy(self.start or none_node),
3879 stop=copy.deepcopy(self.stop or none_node),
3880 step=none_node
3881 ).analyse_types(env)
3882 else:
3883 c_int = PyrexTypes.c_py_ssize_t_type
3884 if self.start:
3885 self.start = self.start.coerce_to(c_int, env)
3886 if self.stop:
3887 self.stop = self.stop.coerce_to(c_int, env)
3888 self.is_temp = 1
3889 return self
3891 nogil_check = Node.gil_error
3892 gil_message = "Slicing Python object"
3894 get_slice_utility_code = TempitaUtilityCode.load(
3895 "SliceObject", "ObjectHandling.c", context={'access': 'Get'})
3897 set_slice_utility_code = TempitaUtilityCode.load(
3898 "SliceObject", "ObjectHandling.c", context={'access': 'Set'})
3900 def coerce_to(self, dst_type, env):
3901 if ((self.base.type.is_string or self.base.type.is_cpp_string)
3902 and dst_type in (bytes_type, bytearray_type, str_type, unicode_type)):
3903 if (dst_type not in (bytes_type, bytearray_type)
3904 and not env.directives['c_string_encoding']):
3905 error(self.pos,
3906 "default encoding required for conversion from '%s' to '%s'" %
3907 (self.base.type, dst_type))
3908 self.type = dst_type
3909 return super(SliceIndexNode, self).coerce_to(dst_type, env)
3911 def generate_result_code(self, code):
3912 if not self.type.is_pyobject:
3913 error(self.pos,
3914 "Slicing is not currently supported for '%s'." % self.type)
3915 return
3917 base_result = self.base.result()
3918 result = self.result()
3919 start_code = self.start_code()
3920 stop_code = self.stop_code()
3921 if self.base.type.is_string:
3922 base_result = self.base.result()
3923 if self.base.type != PyrexTypes.c_char_ptr_type:
3924 base_result = '((const char*)%s)' % base_result
3925 if self.type is bytearray_type:
3926 type_name = 'ByteArray'
3927 else:
3928 type_name = self.type.name.title()
3929 if self.stop is None:
3930 code.putln(
3931 "%s = __Pyx_Py%s_FromString(%s + %s); %s" % (
3932 result,
3933 type_name,
3934 base_result,
3935 start_code,
3936 code.error_goto_if_null(result, self.pos)))
3937 else:
3938 code.putln(
3939 "%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" % (
3940 result,
3941 type_name,
3942 base_result,
3943 start_code,
3944 stop_code,
3945 start_code,
3946 code.error_goto_if_null(result, self.pos)))
3947 elif self.base.type.is_pyunicode_ptr:
3948 base_result = self.base.result()
3949 if self.base.type != PyrexTypes.c_py_unicode_ptr_type:
3950 base_result = '((const Py_UNICODE*)%s)' % base_result
3951 if self.stop is None:
3952 code.putln(
3953 "%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % (
3954 result,
3955 base_result,
3956 start_code,
3957 code.error_goto_if_null(result, self.pos)))
3958 else:
3959 code.putln(
3960 "%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s); %s" % (
3961 result,
3962 base_result,
3963 start_code,
3964 stop_code,
3965 start_code,
3966 code.error_goto_if_null(result, self.pos)))
3968 elif self.base.type is unicode_type:
3969 code.globalstate.use_utility_code(
3970 UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c"))
3971 code.putln(
3972 "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % (
3973 result,
3974 base_result,
3975 start_code,
3976 stop_code,
3977 code.error_goto_if_null(result, self.pos)))
3978 elif self.type is py_object_type:
3979 code.globalstate.use_utility_code(self.get_slice_utility_code)
3980 (has_c_start, has_c_stop, c_start, c_stop,
3981 py_start, py_stop, py_slice) = self.get_slice_config()
3982 code.putln(
3983 "%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d); %s" % (
3984 result,
3985 self.base.py_result(),
3986 c_start, c_stop,
3987 py_start, py_stop, py_slice,
3988 has_c_start, has_c_stop,
3989 bool(code.globalstate.directives['wraparound']),
3990 code.error_goto_if_null(result, self.pos)))
3991 else:
3992 if self.base.type is list_type:
3993 code.globalstate.use_utility_code(
3994 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c"))
3995 cfunc = '__Pyx_PyList_GetSlice'
3996 elif self.base.type is tuple_type:
3997 code.globalstate.use_utility_code(
3998 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c"))
3999 cfunc = '__Pyx_PyTuple_GetSlice'
4000 else:
4001 cfunc = '__Pyx_PySequence_GetSlice'
4002 code.putln(
4003 "%s = %s(%s, %s, %s); %s" % (
4004 result,
4005 cfunc,
4006 self.base.py_result(),
4007 start_code,
4008 stop_code,
4009 code.error_goto_if_null(result, self.pos)))
4010 code.put_gotref(self.py_result())
4012 def generate_assignment_code(self, rhs, code):
4013 self.generate_subexpr_evaluation_code(code)
4014 if self.type.is_pyobject:
4015 code.globalstate.use_utility_code(self.set_slice_utility_code)
4016 (has_c_start, has_c_stop, c_start, c_stop,
4017 py_start, py_stop, py_slice) = self.get_slice_config()
4018 code.put_error_if_neg(self.pos,
4019 "__Pyx_PyObject_SetSlice(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)" % (
4020 self.base.py_result(),
4021 rhs.py_result(),
4022 c_start, c_stop,
4023 py_start, py_stop, py_slice,
4024 has_c_start, has_c_stop,
4025 bool(code.globalstate.directives['wraparound'])))
4026 else:
4027 start_offset = ''
4028 if self.start:
4029 start_offset = self.start_code()
4030 if start_offset == '0':
4031 start_offset = ''
4032 else:
4033 start_offset += '+'
4034 if rhs.type.is_array:
4035 array_length = rhs.type.size
4036 self.generate_slice_guard_code(code, array_length)
4037 else:
4038 error(self.pos,
4039 "Slice assignments from pointers are not yet supported.")
4040 # FIXME: fix the array size according to start/stop
4041 array_length = self.base.type.size
4042 for i in range(array_length):
4043 code.putln("%s[%s%s] = %s[%d];" % (
4044 self.base.result(), start_offset, i,
4045 rhs.result(), i))
4046 self.generate_subexpr_disposal_code(code)
4047 self.free_subexpr_temps(code)
4048 rhs.generate_disposal_code(code)
4049 rhs.free_temps(code)
4051 def generate_deletion_code(self, code, ignore_nonexisting=False):
4052 if not self.base.type.is_pyobject:
4053 error(self.pos,
4054 "Deleting slices is only supported for Python types, not '%s'." % self.type)
4055 return
4056 self.generate_subexpr_evaluation_code(code)
4057 code.globalstate.use_utility_code(self.set_slice_utility_code)
4058 (has_c_start, has_c_stop, c_start, c_stop,
4059 py_start, py_stop, py_slice) = self.get_slice_config()
4060 code.put_error_if_neg(self.pos,
4061 "__Pyx_PyObject_DelSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d)" % (
4062 self.base.py_result(),
4063 c_start, c_stop,
4064 py_start, py_stop, py_slice,
4065 has_c_start, has_c_stop,
4066 bool(code.globalstate.directives['wraparound'])))
4067 self.generate_subexpr_disposal_code(code)
4068 self.free_subexpr_temps(code)
4070 def get_slice_config(self):
4071 has_c_start, c_start, py_start = False, '0', 'NULL'
4072 if self.start:
4073 has_c_start = not self.start.type.is_pyobject
4074 if has_c_start:
4075 c_start = self.start.result()
4076 else:
4077 py_start = '&%s' % self.start.py_result()
4078 has_c_stop, c_stop, py_stop = False, '0', 'NULL'
4079 if self.stop:
4080 has_c_stop = not self.stop.type.is_pyobject
4081 if has_c_stop:
4082 c_stop = self.stop.result()
4083 else:
4084 py_stop = '&%s' % self.stop.py_result()
4085 py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL'
4086 return (has_c_start, has_c_stop, c_start, c_stop,
4087 py_start, py_stop, py_slice)
4089 def generate_slice_guard_code(self, code, target_size):
4090 if not self.base.type.is_array:
4091 return
4092 slice_size = self.base.type.size
4093 start = stop = None
4094 if self.stop:
4095 stop = self.stop.result()
4096 try:
4097 stop = int(stop)
4098 if stop < 0:
4099 slice_size = self.base.type.size + stop
4100 else:
4101 slice_size = stop
4102 stop = None
4103 except ValueError:
4104 pass
4105 if self.start:
4106 start = self.start.result()
4107 try:
4108 start = int(start)
4109 if start < 0:
4110 start = self.base.type.size + start
4111 slice_size -= start
4112 start = None
4113 except ValueError:
4114 pass
4115 check = None
4116 if slice_size < 0:
4117 if target_size > 0:
4118 error(self.pos, "Assignment to empty slice.")
4119 elif start is None and stop is None:
4120 # we know the exact slice length
4121 if target_size != slice_size:
4122 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
4123 slice_size, target_size))
4124 elif start is not None:
4125 if stop is None:
4126 stop = slice_size
4127 check = "(%s)-(%s)" % (stop, start)
4128 else: # stop is not None:
4129 check = stop
4130 if check:
4131 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
4132 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%" CYTHON_FORMAT_SSIZE_T "d, got %%" CYTHON_FORMAT_SSIZE_T "d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
4133 target_size, check))
4134 code.putln(code.error_goto(self.pos))
4135 code.putln("}")
4137 def start_code(self):
4138 if self.start:
4139 return self.start.result()
4140 else:
4141 return "0"
4143 def stop_code(self):
4144 if self.stop:
4145 return self.stop.result()
4146 elif self.base.type.is_array:
4147 return self.base.type.size
4148 else:
4149 return "PY_SSIZE_T_MAX"
4151 def calculate_result_code(self):
4152 # self.result() is not used, but this method must exist
4153 return "<unused>"
4156 class SliceNode(ExprNode):
4157 # start:stop:step in subscript list
4159 # start ExprNode
4160 # stop ExprNode
4161 # step ExprNode
4163 subexprs = ['start', 'stop', 'step']
4165 type = slice_type
4166 is_temp = 1
4168 def calculate_constant_result(self):
4169 self.constant_result = slice(
4170 self.start.constant_result,
4171 self.stop.constant_result,
4172 self.step.constant_result)
4174 def compile_time_value(self, denv):
4175 start = self.start.compile_time_value(denv)
4176 stop = self.stop.compile_time_value(denv)
4177 step = self.step.compile_time_value(denv)
4178 try:
4179 return slice(start, stop, step)
4180 except Exception, e:
4181 self.compile_time_value_error(e)
4183 def may_be_none(self):
4184 return False
4186 def analyse_types(self, env):
4187 start = self.start.analyse_types(env)
4188 stop = self.stop.analyse_types(env)
4189 step = self.step.analyse_types(env)
4190 self.start = start.coerce_to_pyobject(env)
4191 self.stop = stop.coerce_to_pyobject(env)
4192 self.step = step.coerce_to_pyobject(env)
4193 if self.start.is_literal and self.stop.is_literal and self.step.is_literal:
4194 self.is_literal = True
4195 self.is_temp = False
4196 return self
4198 gil_message = "Constructing Python slice object"
4200 def calculate_result_code(self):
4201 return self.result_code
4203 def generate_result_code(self, code):
4204 if self.is_literal:
4205 self.result_code = code.get_py_const(py_object_type, 'slice', cleanup_level=2)
4206 code = code.get_cached_constants_writer()
4207 code.mark_pos(self.pos)
4209 code.putln(
4210 "%s = PySlice_New(%s, %s, %s); %s" % (
4211 self.result(),
4212 self.start.py_result(),
4213 self.stop.py_result(),
4214 self.step.py_result(),
4215 code.error_goto_if_null(self.result(), self.pos)))
4216 code.put_gotref(self.py_result())
4217 if self.is_literal:
4218 code.put_giveref(self.py_result())
4220 def __deepcopy__(self, memo):
4222 There is a copy bug in python 2.4 for slice objects.
4224 return SliceNode(
4225 self.pos,
4226 start=copy.deepcopy(self.start, memo),
4227 stop=copy.deepcopy(self.stop, memo),
4228 step=copy.deepcopy(self.step, memo),
4229 is_temp=self.is_temp,
4230 is_literal=self.is_literal,
4231 constant_result=self.constant_result)
4234 class CallNode(ExprNode):
4236 # allow overriding the default 'may_be_none' behaviour
4237 may_return_none = None
4239 def infer_type(self, env):
4240 function = self.function
4241 func_type = function.infer_type(env)
4242 if isinstance(function, NewExprNode):
4243 # note: needs call to infer_type() above
4244 return PyrexTypes.CPtrType(function.class_type)
4245 if func_type is py_object_type:
4246 # function might have lied for safety => try to find better type
4247 entry = getattr(function, 'entry', None)
4248 if entry is not None:
4249 func_type = entry.type or func_type
4250 if func_type.is_ptr:
4251 func_type = func_type.base_type
4252 if func_type.is_cfunction:
4253 return func_type.return_type
4254 elif func_type is type_type:
4255 if function.is_name and function.entry and function.entry.type:
4256 result_type = function.entry.type
4257 if result_type.is_extension_type:
4258 return result_type
4259 elif result_type.is_builtin_type:
4260 if function.entry.name == 'float':
4261 return PyrexTypes.c_double_type
4262 elif function.entry.name in Builtin.types_that_construct_their_instance:
4263 return result_type
4264 return py_object_type
4266 def type_dependencies(self, env):
4267 # TODO: Update when Danilo's C++ code merged in to handle the
4268 # the case of function overloading.
4269 return self.function.type_dependencies(env)
4271 def is_simple(self):
4272 # C function calls could be considered simple, but they may
4273 # have side-effects that may hit when multiple operations must
4274 # be effected in order, e.g. when constructing the argument
4275 # sequence for a function call or comparing values.
4276 return False
4278 def may_be_none(self):
4279 if self.may_return_none is not None:
4280 return self.may_return_none
4281 func_type = self.function.type
4282 if func_type is type_type and self.function.is_name:
4283 entry = self.function.entry
4284 if entry.type.is_extension_type:
4285 return False
4286 if (entry.type.is_builtin_type and
4287 entry.name in Builtin.types_that_construct_their_instance):
4288 return False
4289 return ExprNode.may_be_none(self)
4291 def analyse_as_type_constructor(self, env):
4292 type = self.function.analyse_as_type(env)
4293 if type and type.is_struct_or_union:
4294 args, kwds = self.explicit_args_kwds()
4295 items = []
4296 for arg, member in zip(args, type.scope.var_entries):
4297 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
4298 if kwds:
4299 items += kwds.key_value_pairs
4300 self.key_value_pairs = items
4301 self.__class__ = DictNode
4302 self.analyse_types(env) # FIXME
4303 self.coerce_to(type, env)
4304 return True
4305 elif type and type.is_cpp_class:
4306 self.args = [ arg.analyse_types(env) for arg in self.args ]
4307 constructor = type.scope.lookup("<init>")
4308 self.function = RawCNameExprNode(self.function.pos, constructor.type)
4309 self.function.entry = constructor
4310 self.function.set_cname(type.declaration_code(""))
4311 self.analyse_c_function_call(env)
4312 self.type = type
4313 return True
4315 def is_lvalue(self):
4316 return self.type.is_reference
4318 def nogil_check(self, env):
4319 func_type = self.function_type()
4320 if func_type.is_pyobject:
4321 self.gil_error()
4322 elif not getattr(func_type, 'nogil', False):
4323 self.gil_error()
4325 gil_message = "Calling gil-requiring function"
4328 class SimpleCallNode(CallNode):
4329 # Function call without keyword, * or ** args.
4331 # function ExprNode
4332 # args [ExprNode]
4333 # arg_tuple ExprNode or None used internally
4334 # self ExprNode or None used internally
4335 # coerced_self ExprNode or None used internally
4336 # wrapper_call bool used internally
4337 # has_optional_args bool used internally
4338 # nogil bool used internally
4340 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
4342 self = None
4343 coerced_self = None
4344 arg_tuple = None
4345 wrapper_call = False
4346 has_optional_args = False
4347 nogil = False
4348 analysed = False
4350 def compile_time_value(self, denv):
4351 function = self.function.compile_time_value(denv)
4352 args = [arg.compile_time_value(denv) for arg in self.args]
4353 try:
4354 return function(*args)
4355 except Exception, e:
4356 self.compile_time_value_error(e)
4358 def analyse_as_type(self, env):
4359 attr = self.function.as_cython_attribute()
4360 if attr == 'pointer':
4361 if len(self.args) != 1:
4362 error(self.args.pos, "only one type allowed.")
4363 else:
4364 type = self.args[0].analyse_as_type(env)
4365 if not type:
4366 error(self.args[0].pos, "Unknown type")
4367 else:
4368 return PyrexTypes.CPtrType(type)
4370 def explicit_args_kwds(self):
4371 return self.args, None
4373 def analyse_types(self, env):
4374 if self.analyse_as_type_constructor(env):
4375 return self
4376 if self.analysed:
4377 return self
4378 self.analysed = True
4379 self.function.is_called = 1
4380 self.function = self.function.analyse_types(env)
4381 function = self.function
4383 if function.is_attribute and function.entry and function.entry.is_cmethod:
4384 # Take ownership of the object from which the attribute
4385 # was obtained, because we need to pass it as 'self'.
4386 self.self = function.obj
4387 function.obj = CloneNode(self.self)
4389 func_type = self.function_type()
4390 if func_type.is_pyobject:
4391 self.arg_tuple = TupleNode(self.pos, args = self.args)
4392 self.arg_tuple = self.arg_tuple.analyse_types(env)
4393 self.args = None
4394 if func_type is Builtin.type_type and function.is_name and \
4395 function.entry and \
4396 function.entry.is_builtin and \
4397 function.entry.name in Builtin.types_that_construct_their_instance:
4398 # calling a builtin type that returns a specific object type
4399 if function.entry.name == 'float':
4400 # the following will come true later on in a transform
4401 self.type = PyrexTypes.c_double_type
4402 self.result_ctype = PyrexTypes.c_double_type
4403 else:
4404 self.type = Builtin.builtin_types[function.entry.name]
4405 self.result_ctype = py_object_type
4406 self.may_return_none = False
4407 elif function.is_name and function.type_entry:
4408 # We are calling an extension type constructor. As
4409 # long as we do not support __new__(), the result type
4410 # is clear
4411 self.type = function.type_entry.type
4412 self.result_ctype = py_object_type
4413 self.may_return_none = False
4414 else:
4415 self.type = py_object_type
4416 self.is_temp = 1
4417 else:
4418 self.args = [ arg.analyse_types(env) for arg in self.args ]
4419 self.analyse_c_function_call(env)
4420 return self
4422 def function_type(self):
4423 # Return the type of the function being called, coercing a function
4424 # pointer to a function if necessary. If the function has fused
4425 # arguments, return the specific type.
4426 func_type = self.function.type
4428 if func_type.is_ptr:
4429 func_type = func_type.base_type
4431 return func_type
4433 def analyse_c_function_call(self, env):
4434 if self.function.type is error_type:
4435 self.type = error_type
4436 return
4438 if self.self:
4439 args = [self.self] + self.args
4440 else:
4441 args = self.args
4443 if self.function.type.is_cpp_class:
4444 overloaded_entry = self.function.type.scope.lookup("operator()")
4445 if overloaded_entry is None:
4446 self.type = PyrexTypes.error_type
4447 self.result_code = "<error>"
4448 return
4449 elif hasattr(self.function, 'entry'):
4450 overloaded_entry = self.function.entry
4451 elif (isinstance(self.function, IndexNode) and
4452 self.function.is_fused_index):
4453 overloaded_entry = self.function.type.entry
4454 else:
4455 overloaded_entry = None
4457 if overloaded_entry:
4458 if self.function.type.is_fused:
4459 functypes = self.function.type.get_all_specialized_function_types()
4460 alternatives = [f.entry for f in functypes]
4461 else:
4462 alternatives = overloaded_entry.all_alternatives()
4464 entry = PyrexTypes.best_match(args, alternatives, self.pos, env)
4466 if not entry:
4467 self.type = PyrexTypes.error_type
4468 self.result_code = "<error>"
4469 return
4471 entry.used = True
4472 self.function.entry = entry
4473 self.function.type = entry.type
4474 func_type = self.function_type()
4475 else:
4476 entry = None
4477 func_type = self.function_type()
4478 if not func_type.is_cfunction:
4479 error(self.pos, "Calling non-function type '%s'" % func_type)
4480 self.type = PyrexTypes.error_type
4481 self.result_code = "<error>"
4482 return
4484 # Check no. of args
4485 max_nargs = len(func_type.args)
4486 expected_nargs = max_nargs - func_type.optional_arg_count
4487 actual_nargs = len(args)
4488 if func_type.optional_arg_count and expected_nargs != actual_nargs:
4489 self.has_optional_args = 1
4490 self.is_temp = 1
4492 # check 'self' argument
4493 if entry and entry.is_cmethod and func_type.args:
4494 formal_arg = func_type.args[0]
4495 arg = args[0]
4496 if formal_arg.not_none:
4497 if self.self:
4498 self.self = self.self.as_none_safe_node(
4499 "'NoneType' object has no attribute '%s'",
4500 error='PyExc_AttributeError',
4501 format_args=[entry.name])
4502 else:
4503 # unbound method
4504 arg = arg.as_none_safe_node(
4505 "descriptor '%s' requires a '%s' object but received a 'NoneType'",
4506 format_args=[entry.name, formal_arg.type.name])
4507 if self.self:
4508 if formal_arg.accept_builtin_subtypes:
4509 arg = CMethodSelfCloneNode(self.self)
4510 else:
4511 arg = CloneNode(self.self)
4512 arg = self.coerced_self = arg.coerce_to(formal_arg.type, env)
4513 elif formal_arg.type.is_builtin_type:
4514 # special case: unbound methods of builtins accept subtypes
4515 arg = arg.coerce_to(formal_arg.type, env)
4516 if arg.type.is_builtin_type and isinstance(arg, PyTypeTestNode):
4517 arg.exact_builtin_type = False
4518 args[0] = arg
4520 # Coerce arguments
4521 some_args_in_temps = False
4522 for i in xrange(min(max_nargs, actual_nargs)):
4523 formal_arg = func_type.args[i]
4524 formal_type = formal_arg.type
4525 arg = args[i].coerce_to(formal_type, env)
4526 if formal_arg.not_none:
4527 # C methods must do the None checks at *call* time
4528 arg = arg.as_none_safe_node(
4529 "cannot pass None into a C function argument that is declared 'not None'")
4530 if arg.is_temp:
4531 if i > 0:
4532 # first argument in temp doesn't impact subsequent arguments
4533 some_args_in_temps = True
4534 elif arg.type.is_pyobject and not env.nogil:
4535 if i == 0 and self.self is not None:
4536 # a method's cloned "self" argument is ok
4537 pass
4538 elif arg.nonlocally_immutable():
4539 # plain local variables are ok
4540 pass
4541 else:
4542 # we do not safely own the argument's reference,
4543 # but we must make sure it cannot be collected
4544 # before we return from the function, so we create
4545 # an owned temp reference to it
4546 if i > 0: # first argument doesn't matter
4547 some_args_in_temps = True
4548 arg = arg.coerce_to_temp(env)
4549 args[i] = arg
4551 # handle additional varargs parameters
4552 for i in xrange(max_nargs, actual_nargs):
4553 arg = args[i]
4554 if arg.type.is_pyobject:
4555 arg_ctype = arg.type.default_coerced_ctype()
4556 if arg_ctype is None:
4557 error(self.args[i].pos,
4558 "Python object cannot be passed as a varargs parameter")
4559 else:
4560 args[i] = arg = arg.coerce_to(arg_ctype, env)
4561 if arg.is_temp and i > 0:
4562 some_args_in_temps = True
4564 if some_args_in_temps:
4565 # if some args are temps and others are not, they may get
4566 # constructed in the wrong order (temps first) => make
4567 # sure they are either all temps or all not temps (except
4568 # for the last argument, which is evaluated last in any
4569 # case)
4570 for i in xrange(actual_nargs-1):
4571 if i == 0 and self.self is not None:
4572 continue # self is ok
4573 arg = args[i]
4574 if arg.nonlocally_immutable():
4575 # locals, C functions, unassignable types are safe.
4576 pass
4577 elif arg.type.is_cpp_class:
4578 # Assignment has side effects, avoid.
4579 pass
4580 elif env.nogil and arg.type.is_pyobject:
4581 # can't copy a Python reference into a temp in nogil
4582 # env (this is safe: a construction would fail in
4583 # nogil anyway)
4584 pass
4585 else:
4586 #self.args[i] = arg.coerce_to_temp(env)
4587 # instead: issue a warning
4588 if i > 0 or i == 1 and self.self is not None: # skip first arg
4589 warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0)
4590 break
4592 self.args[:] = args
4594 # Calc result type and code fragment
4595 if isinstance(self.function, NewExprNode):
4596 self.type = PyrexTypes.CPtrType(self.function.class_type)
4597 else:
4598 self.type = func_type.return_type
4600 if self.function.is_name or self.function.is_attribute:
4601 if self.function.entry and self.function.entry.utility_code:
4602 self.is_temp = 1 # currently doesn't work for self.calculate_result_code()
4604 if self.type.is_pyobject:
4605 self.result_ctype = py_object_type
4606 self.is_temp = 1
4607 elif func_type.exception_value is not None \
4608 or func_type.exception_check:
4609 self.is_temp = 1
4610 elif self.type.is_memoryviewslice:
4611 self.is_temp = 1
4612 # func_type.exception_check = True
4614 # Called in 'nogil' context?
4615 self.nogil = env.nogil
4616 if (self.nogil and
4617 func_type.exception_check and
4618 func_type.exception_check != '+'):
4619 env.use_utility_code(pyerr_occurred_withgil_utility_code)
4620 # C++ exception handler
4621 if func_type.exception_check == '+':
4622 if func_type.exception_value is None:
4623 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp"))
4625 def calculate_result_code(self):
4626 return self.c_call_code()
4628 def c_call_code(self):
4629 func_type = self.function_type()
4630 if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
4631 return "<error>"
4632 formal_args = func_type.args
4633 arg_list_code = []
4634 args = list(zip(formal_args, self.args))
4635 max_nargs = len(func_type.args)
4636 expected_nargs = max_nargs - func_type.optional_arg_count
4637 actual_nargs = len(self.args)
4638 for formal_arg, actual_arg in args[:expected_nargs]:
4639 arg_code = actual_arg.result_as(formal_arg.type)
4640 arg_list_code.append(arg_code)
4642 if func_type.is_overridable:
4643 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
4645 if func_type.optional_arg_count:
4646 if expected_nargs == actual_nargs:
4647 optional_args = 'NULL'
4648 else:
4649 optional_args = "&%s" % self.opt_arg_struct
4650 arg_list_code.append(optional_args)
4652 for actual_arg in self.args[len(formal_args):]:
4653 arg_list_code.append(actual_arg.result())
4655 result = "%s(%s)" % (self.function.result(), ', '.join(arg_list_code))
4656 return result
4658 def generate_result_code(self, code):
4659 func_type = self.function_type()
4660 if self.function.is_name or self.function.is_attribute:
4661 if self.function.entry and self.function.entry.utility_code:
4662 code.globalstate.use_utility_code(self.function.entry.utility_code)
4663 if func_type.is_pyobject:
4664 arg_code = self.arg_tuple.py_result()
4665 code.globalstate.use_utility_code(UtilityCode.load_cached(
4666 "PyObjectCall", "ObjectHandling.c"))
4667 code.putln(
4668 "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % (
4669 self.result(),
4670 self.function.py_result(),
4671 arg_code,
4672 code.error_goto_if_null(self.result(), self.pos)))
4673 code.put_gotref(self.py_result())
4674 elif func_type.is_cfunction:
4675 if self.has_optional_args:
4676 actual_nargs = len(self.args)
4677 expected_nargs = len(func_type.args) - func_type.optional_arg_count
4678 self.opt_arg_struct = code.funcstate.allocate_temp(
4679 func_type.op_arg_struct.base_type, manage_ref=True)
4680 code.putln("%s.%s = %s;" % (
4681 self.opt_arg_struct,
4682 Naming.pyrex_prefix + "n",
4683 len(self.args) - expected_nargs))
4684 args = list(zip(func_type.args, self.args))
4685 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
4686 code.putln("%s.%s = %s;" % (
4687 self.opt_arg_struct,
4688 func_type.opt_arg_cname(formal_arg.name),
4689 actual_arg.result_as(formal_arg.type)))
4690 exc_checks = []
4691 if self.type.is_pyobject and self.is_temp:
4692 exc_checks.append("!%s" % self.result())
4693 elif self.type.is_memoryviewslice:
4694 assert self.is_temp
4695 exc_checks.append(self.type.error_condition(self.result()))
4696 else:
4697 exc_val = func_type.exception_value
4698 exc_check = func_type.exception_check
4699 if exc_val is not None:
4700 exc_checks.append("%s == %s" % (self.result(), exc_val))
4701 if exc_check:
4702 if self.nogil:
4703 exc_checks.append("__Pyx_ErrOccurredWithGIL()")
4704 else:
4705 exc_checks.append("PyErr_Occurred()")
4706 if self.is_temp or exc_checks:
4707 rhs = self.c_call_code()
4708 if self.result():
4709 lhs = "%s = " % self.result()
4710 if self.is_temp and self.type.is_pyobject:
4711 #return_type = self.type # func_type.return_type
4712 #print "SimpleCallNode.generate_result_code: casting", rhs, \
4713 # "from", return_type, "to pyobject" ###
4714 rhs = typecast(py_object_type, self.type, rhs)
4715 else:
4716 lhs = ""
4717 if func_type.exception_check == '+':
4718 if func_type.exception_value is None:
4719 raise_py_exception = "__Pyx_CppExn2PyErr();"
4720 elif func_type.exception_value.type.is_pyobject:
4721 raise_py_exception = 'try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
4722 func_type.exception_value.entry.cname,
4723 func_type.exception_value.entry.cname)
4724 else:
4725 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.");' % func_type.exception_value.entry.cname
4726 code.putln("try {")
4727 code.putln("%s%s;" % (lhs, rhs))
4728 code.putln("} catch(...) {")
4729 if self.nogil:
4730 code.put_ensure_gil(declare_gilstate=True)
4731 code.putln(raise_py_exception)
4732 if self.nogil:
4733 code.put_release_ensured_gil()
4734 code.putln(code.error_goto(self.pos))
4735 code.putln("}")
4736 else:
4737 if exc_checks:
4738 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
4739 else:
4740 goto_error = ""
4741 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
4742 if self.type.is_pyobject and self.result():
4743 code.put_gotref(self.py_result())
4744 if self.has_optional_args:
4745 code.funcstate.release_temp(self.opt_arg_struct)
4748 class InlinedDefNodeCallNode(CallNode):
4749 # Inline call to defnode
4751 # function PyCFunctionNode
4752 # function_name NameNode
4753 # args [ExprNode]
4755 subexprs = ['args', 'function_name']
4756 is_temp = 1
4757 type = py_object_type
4758 function = None
4759 function_name = None
4761 def can_be_inlined(self):
4762 func_type= self.function.def_node
4763 if func_type.star_arg or func_type.starstar_arg:
4764 return False
4765 if len(func_type.args) != len(self.args):
4766 return False
4767 return True
4769 def analyse_types(self, env):
4770 self.function_name = self.function_name.analyse_types(env)
4772 self.args = [ arg.analyse_types(env) for arg in self.args ]
4773 func_type = self.function.def_node
4774 actual_nargs = len(self.args)
4776 # Coerce arguments
4777 some_args_in_temps = False
4778 for i in xrange(actual_nargs):
4779 formal_type = func_type.args[i].type
4780 arg = self.args[i].coerce_to(formal_type, env)
4781 if arg.is_temp:
4782 if i > 0:
4783 # first argument in temp doesn't impact subsequent arguments
4784 some_args_in_temps = True
4785 elif arg.type.is_pyobject and not env.nogil:
4786 if arg.nonlocally_immutable():
4787 # plain local variables are ok
4788 pass
4789 else:
4790 # we do not safely own the argument's reference,
4791 # but we must make sure it cannot be collected
4792 # before we return from the function, so we create
4793 # an owned temp reference to it
4794 if i > 0: # first argument doesn't matter
4795 some_args_in_temps = True
4796 arg = arg.coerce_to_temp(env)
4797 self.args[i] = arg
4799 if some_args_in_temps:
4800 # if some args are temps and others are not, they may get
4801 # constructed in the wrong order (temps first) => make
4802 # sure they are either all temps or all not temps (except
4803 # for the last argument, which is evaluated last in any
4804 # case)
4805 for i in xrange(actual_nargs-1):
4806 arg = self.args[i]
4807 if arg.nonlocally_immutable():
4808 # locals, C functions, unassignable types are safe.
4809 pass
4810 elif arg.type.is_cpp_class:
4811 # Assignment has side effects, avoid.
4812 pass
4813 elif env.nogil and arg.type.is_pyobject:
4814 # can't copy a Python reference into a temp in nogil
4815 # env (this is safe: a construction would fail in
4816 # nogil anyway)
4817 pass
4818 else:
4819 #self.args[i] = arg.coerce_to_temp(env)
4820 # instead: issue a warning
4821 if i > 0:
4822 warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0)
4823 break
4824 return self
4826 def generate_result_code(self, code):
4827 arg_code = [self.function_name.py_result()]
4828 func_type = self.function.def_node
4829 for arg, proto_arg in zip(self.args, func_type.args):
4830 if arg.type.is_pyobject:
4831 arg_code.append(arg.result_as(proto_arg.type))
4832 else:
4833 arg_code.append(arg.result())
4834 arg_code = ', '.join(arg_code)
4835 code.putln(
4836 "%s = %s(%s); %s" % (
4837 self.result(),
4838 self.function.def_node.entry.pyfunc_cname,
4839 arg_code,
4840 code.error_goto_if_null(self.result(), self.pos)))
4841 code.put_gotref(self.py_result())
4844 class PythonCapiFunctionNode(ExprNode):
4845 subexprs = []
4847 def __init__(self, pos, py_name, cname, func_type, utility_code = None):
4848 ExprNode.__init__(self, pos, name=py_name, cname=cname,
4849 type=func_type, utility_code=utility_code)
4851 def analyse_types(self, env):
4852 return self
4854 def generate_result_code(self, code):
4855 if self.utility_code:
4856 code.globalstate.use_utility_code(self.utility_code)
4858 def calculate_result_code(self):
4859 return self.cname
4862 class PythonCapiCallNode(SimpleCallNode):
4863 # Python C-API Function call (only created in transforms)
4865 # By default, we assume that the call never returns None, as this
4866 # is true for most C-API functions in CPython. If this does not
4867 # apply to a call, set the following to True (or None to inherit
4868 # the default behaviour).
4869 may_return_none = False
4871 def __init__(self, pos, function_name, func_type,
4872 utility_code = None, py_name=None, **kwargs):
4873 self.type = func_type.return_type
4874 self.result_ctype = self.type
4875 self.function = PythonCapiFunctionNode(
4876 pos, py_name, function_name, func_type,
4877 utility_code = utility_code)
4878 # call this last so that we can override the constructed
4879 # attributes above with explicit keyword arguments if required
4880 SimpleCallNode.__init__(self, pos, **kwargs)
4883 class GeneralCallNode(CallNode):
4884 # General Python function call, including keyword,
4885 # * and ** arguments.
4887 # function ExprNode
4888 # positional_args ExprNode Tuple of positional arguments
4889 # keyword_args ExprNode or None Dict of keyword arguments
4891 type = py_object_type
4893 subexprs = ['function', 'positional_args', 'keyword_args']
4895 nogil_check = Node.gil_error
4897 def compile_time_value(self, denv):
4898 function = self.function.compile_time_value(denv)
4899 positional_args = self.positional_args.compile_time_value(denv)
4900 keyword_args = self.keyword_args.compile_time_value(denv)
4901 try:
4902 return function(*positional_args, **keyword_args)
4903 except Exception, e:
4904 self.compile_time_value_error(e)
4906 def explicit_args_kwds(self):
4907 if (self.keyword_args and not isinstance(self.keyword_args, DictNode) or
4908 not isinstance(self.positional_args, TupleNode)):
4909 raise CompileError(self.pos,
4910 'Compile-time keyword arguments must be explicit.')
4911 return self.positional_args.args, self.keyword_args
4913 def analyse_types(self, env):
4914 if self.analyse_as_type_constructor(env):
4915 return self
4916 self.function = self.function.analyse_types(env)
4917 if not self.function.type.is_pyobject:
4918 if self.function.type.is_error:
4919 self.type = error_type
4920 return self
4921 if hasattr(self.function, 'entry'):
4922 node = self.map_to_simple_call_node()
4923 if node is not None and node is not self:
4924 return node.analyse_types(env)
4925 elif self.function.entry.as_variable:
4926 self.function = self.function.coerce_to_pyobject(env)
4927 elif node is self:
4928 error(self.pos,
4929 "Non-trivial keyword arguments and starred "
4930 "arguments not allowed in cdef functions.")
4931 else:
4932 # error was already reported
4933 pass
4934 else:
4935 self.function = self.function.coerce_to_pyobject(env)
4936 if self.keyword_args:
4937 self.keyword_args = self.keyword_args.analyse_types(env)
4938 self.positional_args = self.positional_args.analyse_types(env)
4939 self.positional_args = \
4940 self.positional_args.coerce_to_pyobject(env)
4941 function = self.function
4942 if function.is_name and function.type_entry:
4943 # We are calling an extension type constructor. As long
4944 # as we do not support __new__(), the result type is clear
4945 self.type = function.type_entry.type
4946 self.result_ctype = py_object_type
4947 self.may_return_none = False
4948 else:
4949 self.type = py_object_type
4950 self.is_temp = 1
4951 return self
4953 def map_to_simple_call_node(self):
4955 Tries to map keyword arguments to declared positional arguments.
4956 Returns self to try a Python call, None to report an error
4957 or a SimpleCallNode if the mapping succeeds.
4959 if not isinstance(self.positional_args, TupleNode):
4960 # has starred argument
4961 return self
4962 if not isinstance(self.keyword_args, DictNode):
4963 # keywords come from arbitrary expression => nothing to do here
4964 return self
4965 function = self.function
4966 entry = getattr(function, 'entry', None)
4967 if not entry:
4968 return self
4969 function_type = entry.type
4970 if function_type.is_ptr:
4971 function_type = function_type.base_type
4972 if not function_type.is_cfunction:
4973 return self
4975 pos_args = self.positional_args.args
4976 kwargs = self.keyword_args
4977 declared_args = function_type.args
4978 if entry.is_cmethod:
4979 declared_args = declared_args[1:] # skip 'self'
4981 if len(pos_args) > len(declared_args):
4982 error(self.pos, "function call got too many positional arguments, "
4983 "expected %d, got %s" % (len(declared_args),
4984 len(pos_args)))
4985 return None
4987 matched_args = set([ arg.name for arg in declared_args[:len(pos_args)]
4988 if arg.name ])
4989 unmatched_args = declared_args[len(pos_args):]
4990 matched_kwargs_count = 0
4991 args = list(pos_args)
4993 # check for duplicate keywords
4994 seen = set(matched_args)
4995 has_errors = False
4996 for arg in kwargs.key_value_pairs:
4997 name = arg.key.value
4998 if name in seen:
4999 error(arg.pos, "argument '%s' passed twice" % name)
5000 has_errors = True
5001 # continue to report more errors if there are any
5002 seen.add(name)
5004 # match keywords that are passed in order
5005 for decl_arg, arg in zip(unmatched_args, kwargs.key_value_pairs):
5006 name = arg.key.value
5007 if decl_arg.name == name:
5008 matched_args.add(name)
5009 matched_kwargs_count += 1
5010 args.append(arg.value)
5011 else:
5012 break
5014 # match keyword arguments that are passed out-of-order, but keep
5015 # the evaluation of non-simple arguments in order by moving them
5016 # into temps
5017 from Cython.Compiler.UtilNodes import EvalWithTempExprNode, LetRefNode
5018 temps = []
5019 if len(kwargs.key_value_pairs) > matched_kwargs_count:
5020 unmatched_args = declared_args[len(args):]
5021 keywords = dict([ (arg.key.value, (i+len(pos_args), arg))
5022 for i, arg in enumerate(kwargs.key_value_pairs) ])
5023 first_missing_keyword = None
5024 for decl_arg in unmatched_args:
5025 name = decl_arg.name
5026 if name not in keywords:
5027 # missing keyword argument => either done or error
5028 if not first_missing_keyword:
5029 first_missing_keyword = name
5030 continue
5031 elif first_missing_keyword:
5032 if entry.as_variable:
5033 # we might be able to convert the function to a Python
5034 # object, which then allows full calling semantics
5035 # with default values in gaps - currently, we only
5036 # support optional arguments at the end
5037 return self
5038 # wasn't the last keyword => gaps are not supported
5039 error(self.pos, "C function call is missing "
5040 "argument '%s'" % first_missing_keyword)
5041 return None
5042 pos, arg = keywords[name]
5043 matched_args.add(name)
5044 matched_kwargs_count += 1
5045 if arg.value.is_simple():
5046 args.append(arg.value)
5047 else:
5048 temp = LetRefNode(arg.value)
5049 assert temp.is_simple()
5050 args.append(temp)
5051 temps.append((pos, temp))
5053 if temps:
5054 # may have to move preceding non-simple args into temps
5055 final_args = []
5056 new_temps = []
5057 first_temp_arg = temps[0][-1]
5058 for arg_value in args:
5059 if arg_value is first_temp_arg:
5060 break # done
5061 if arg_value.is_simple():
5062 final_args.append(arg_value)
5063 else:
5064 temp = LetRefNode(arg_value)
5065 new_temps.append(temp)
5066 final_args.append(temp)
5067 if new_temps:
5068 args = final_args
5069 temps = new_temps + [ arg for i,arg in sorted(temps) ]
5071 # check for unexpected keywords
5072 for arg in kwargs.key_value_pairs:
5073 name = arg.key.value
5074 if name not in matched_args:
5075 has_errors = True
5076 error(arg.pos,
5077 "C function got unexpected keyword argument '%s'" %
5078 name)
5080 if has_errors:
5081 # error was reported already
5082 return None
5084 # all keywords mapped to positional arguments
5085 # if we are missing arguments, SimpleCallNode will figure it out
5086 node = SimpleCallNode(self.pos, function=function, args=args)
5087 for temp in temps[::-1]:
5088 node = EvalWithTempExprNode(temp, node)
5089 return node
5091 def generate_result_code(self, code):
5092 if self.type.is_error: return
5093 if self.keyword_args:
5094 kwargs = self.keyword_args.py_result()
5095 else:
5096 kwargs = 'NULL'
5097 code.globalstate.use_utility_code(UtilityCode.load_cached(
5098 "PyObjectCall", "ObjectHandling.c"))
5099 code.putln(
5100 "%s = __Pyx_PyObject_Call(%s, %s, %s); %s" % (
5101 self.result(),
5102 self.function.py_result(),
5103 self.positional_args.py_result(),
5104 kwargs,
5105 code.error_goto_if_null(self.result(), self.pos)))
5106 code.put_gotref(self.py_result())
5109 class AsTupleNode(ExprNode):
5110 # Convert argument to tuple. Used for normalising
5111 # the * argument of a function call.
5113 # arg ExprNode
5115 subexprs = ['arg']
5117 def calculate_constant_result(self):
5118 self.constant_result = tuple(self.arg.constant_result)
5120 def compile_time_value(self, denv):
5121 arg = self.arg.compile_time_value(denv)
5122 try:
5123 return tuple(arg)
5124 except Exception, e:
5125 self.compile_time_value_error(e)
5127 def analyse_types(self, env):
5128 self.arg = self.arg.analyse_types(env)
5129 self.arg = self.arg.coerce_to_pyobject(env)
5130 self.type = tuple_type
5131 self.is_temp = 1
5132 return self
5134 def may_be_none(self):
5135 return False
5137 nogil_check = Node.gil_error
5138 gil_message = "Constructing Python tuple"
5140 def generate_result_code(self, code):
5141 code.putln(
5142 "%s = PySequence_Tuple(%s); %s" % (
5143 self.result(),
5144 self.arg.py_result(),
5145 code.error_goto_if_null(self.result(), self.pos)))
5146 code.put_gotref(self.py_result())
5149 class AttributeNode(ExprNode):
5150 # obj.attribute
5152 # obj ExprNode
5153 # attribute string
5154 # needs_none_check boolean Used if obj is an extension type.
5155 # If set to True, it is known that the type is not None.
5157 # Used internally:
5159 # is_py_attr boolean Is a Python getattr operation
5160 # member string C name of struct member
5161 # is_called boolean Function call is being done on result
5162 # entry Entry Symbol table entry of attribute
5164 is_attribute = 1
5165 subexprs = ['obj']
5167 type = PyrexTypes.error_type
5168 entry = None
5169 is_called = 0
5170 needs_none_check = True
5171 is_memslice_transpose = False
5172 is_special_lookup = False
5174 def as_cython_attribute(self):
5175 if (isinstance(self.obj, NameNode) and
5176 self.obj.is_cython_module and not
5177 self.attribute == u"parallel"):
5178 return self.attribute
5180 cy = self.obj.as_cython_attribute()
5181 if cy:
5182 return "%s.%s" % (cy, self.attribute)
5183 return None
5185 def coerce_to(self, dst_type, env):
5186 # If coercing to a generic pyobject and this is a cpdef function
5187 # we can create the corresponding attribute
5188 if dst_type is py_object_type:
5189 entry = self.entry
5190 if entry and entry.is_cfunction and entry.as_variable:
5191 # must be a cpdef function
5192 self.is_temp = 1
5193 self.entry = entry.as_variable
5194 self.analyse_as_python_attribute(env)
5195 return self
5196 return ExprNode.coerce_to(self, dst_type, env)
5198 def calculate_constant_result(self):
5199 attr = self.attribute
5200 if attr.startswith("__") and attr.endswith("__"):
5201 return
5202 self.constant_result = getattr(self.obj.constant_result, attr)
5204 def compile_time_value(self, denv):
5205 attr = self.attribute
5206 if attr.startswith("__") and attr.endswith("__"):
5207 error(self.pos,
5208 "Invalid attribute name '%s' in compile-time expression" % attr)
5209 return None
5210 obj = self.obj.compile_time_value(denv)
5211 try:
5212 return getattr(obj, attr)
5213 except Exception, e:
5214 self.compile_time_value_error(e)
5216 def type_dependencies(self, env):
5217 return self.obj.type_dependencies(env)
5219 def infer_type(self, env):
5220 # FIXME: this is way too redundant with analyse_types()
5221 node = self.analyse_as_cimported_attribute_node(env, target=False)
5222 if node is not None:
5223 return node.entry.type
5224 node = self.analyse_as_unbound_cmethod_node(env)
5225 if node is not None:
5226 return node.entry.type
5227 obj_type = self.obj.infer_type(env)
5228 self.analyse_attribute(env, obj_type=obj_type)
5229 if obj_type.is_builtin_type and self.type.is_cfunction:
5230 # special case: C-API replacements for C methods of
5231 # builtin types cannot be inferred as C functions as
5232 # that would prevent their use as bound methods
5233 return py_object_type
5234 return self.type
5236 def analyse_target_declaration(self, env):
5237 pass
5239 def analyse_target_types(self, env):
5240 node = self.analyse_types(env, target = 1)
5241 if node.type.is_const:
5242 error(self.pos, "Assignment to const attribute '%s'" % self.attribute)
5243 if not node.is_lvalue():
5244 error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type)
5245 return node
5247 def analyse_types(self, env, target = 0):
5248 self.initialized_check = env.directives['initializedcheck']
5249 node = self.analyse_as_cimported_attribute_node(env, target)
5250 if node is None and not target:
5251 node = self.analyse_as_unbound_cmethod_node(env)
5252 if node is None:
5253 node = self.analyse_as_ordinary_attribute_node(env, target)
5254 assert node is not None
5255 if node.entry:
5256 node.entry.used = True
5257 if node.is_attribute:
5258 node.wrap_obj_in_nonecheck(env)
5259 return node
5261 def analyse_as_cimported_attribute_node(self, env, target):
5262 # Try to interpret this as a reference to an imported
5263 # C const, type, var or function. If successful, mutates
5264 # this node into a NameNode and returns 1, otherwise
5265 # returns 0.
5266 module_scope = self.obj.analyse_as_module(env)
5267 if module_scope:
5268 entry = module_scope.lookup_here(self.attribute)
5269 if entry and (
5270 entry.is_cglobal or entry.is_cfunction
5271 or entry.is_type or entry.is_const):
5272 return self.as_name_node(env, entry, target)
5273 return None
5275 def analyse_as_unbound_cmethod_node(self, env):
5276 # Try to interpret this as a reference to an unbound
5277 # C method of an extension type or builtin type. If successful,
5278 # creates a corresponding NameNode and returns it, otherwise
5279 # returns None.
5280 type = self.obj.analyse_as_extension_type(env)
5281 if type:
5282 entry = type.scope.lookup_here(self.attribute)
5283 if entry and entry.is_cmethod:
5284 if type.is_builtin_type:
5285 if not self.is_called:
5286 # must handle this as Python object
5287 return None
5288 ubcm_entry = entry
5289 else:
5290 # Create a temporary entry describing the C method
5291 # as an ordinary function.
5292 ubcm_entry = Symtab.Entry(entry.name,
5293 "%s->%s" % (type.vtabptr_cname, entry.cname),
5294 entry.type)
5295 ubcm_entry.is_cfunction = 1
5296 ubcm_entry.func_cname = entry.func_cname
5297 ubcm_entry.is_unbound_cmethod = 1
5298 return self.as_name_node(env, ubcm_entry, target=False)
5299 return None
5301 def analyse_as_type(self, env):
5302 module_scope = self.obj.analyse_as_module(env)
5303 if module_scope:
5304 return module_scope.lookup_type(self.attribute)
5305 if not self.obj.is_string_literal:
5306 base_type = self.obj.analyse_as_type(env)
5307 if base_type and hasattr(base_type, 'scope') and base_type.scope is not None:
5308 return base_type.scope.lookup_type(self.attribute)
5309 return None
5311 def analyse_as_extension_type(self, env):
5312 # Try to interpret this as a reference to an extension type
5313 # in a cimported module. Returns the extension type, or None.
5314 module_scope = self.obj.analyse_as_module(env)
5315 if module_scope:
5316 entry = module_scope.lookup_here(self.attribute)
5317 if entry and entry.is_type:
5318 if entry.type.is_extension_type or entry.type.is_builtin_type:
5319 return entry.type
5320 return None
5322 def analyse_as_module(self, env):
5323 # Try to interpret this as a reference to a cimported module
5324 # in another cimported module. Returns the module scope, or None.
5325 module_scope = self.obj.analyse_as_module(env)
5326 if module_scope:
5327 entry = module_scope.lookup_here(self.attribute)
5328 if entry and entry.as_module:
5329 return entry.as_module
5330 return None
5332 def as_name_node(self, env, entry, target):
5333 # Create a corresponding NameNode from this node and complete the
5334 # analyse_types phase.
5335 node = NameNode.from_node(self, name=self.attribute, entry=entry)
5336 if target:
5337 node = node.analyse_target_types(env)
5338 else:
5339 node = node.analyse_rvalue_entry(env)
5340 node.entry.used = 1
5341 return node
5343 def analyse_as_ordinary_attribute_node(self, env, target):
5344 self.obj = self.obj.analyse_types(env)
5345 self.analyse_attribute(env)
5346 if self.entry and self.entry.is_cmethod and not self.is_called:
5347 # error(self.pos, "C method can only be called")
5348 pass
5349 ## Reference to C array turns into pointer to first element.
5350 #while self.type.is_array:
5351 # self.type = self.type.element_ptr_type()
5352 if self.is_py_attr:
5353 if not target:
5354 self.is_temp = 1
5355 self.result_ctype = py_object_type
5356 elif target and self.obj.type.is_builtin_type:
5357 error(self.pos, "Assignment to an immutable object field")
5358 #elif self.type.is_memoryviewslice and not target:
5359 # self.is_temp = True
5360 return self
5362 def analyse_attribute(self, env, obj_type = None):
5363 # Look up attribute and set self.type and self.member.
5364 immutable_obj = obj_type is not None # used during type inference
5365 self.is_py_attr = 0
5366 self.member = self.attribute
5367 if obj_type is None:
5368 if self.obj.type.is_string or self.obj.type.is_pyunicode_ptr:
5369 self.obj = self.obj.coerce_to_pyobject(env)
5370 obj_type = self.obj.type
5371 else:
5372 if obj_type.is_string or obj_type.is_pyunicode_ptr:
5373 obj_type = py_object_type
5374 if obj_type.is_ptr or obj_type.is_array:
5375 obj_type = obj_type.base_type
5376 self.op = "->"
5377 elif obj_type.is_extension_type or obj_type.is_builtin_type:
5378 self.op = "->"
5379 else:
5380 self.op = "."
5381 if obj_type.has_attributes:
5382 if obj_type.attributes_known():
5383 if (obj_type.is_memoryviewslice and not
5384 obj_type.scope.lookup_here(self.attribute)):
5385 if self.attribute == 'T':
5386 self.is_memslice_transpose = True
5387 self.is_temp = True
5388 self.use_managed_ref = True
5389 self.type = self.obj.type
5390 return
5391 else:
5392 obj_type.declare_attribute(self.attribute, env, self.pos)
5393 entry = obj_type.scope.lookup_here(self.attribute)
5394 if entry and entry.is_member:
5395 entry = None
5396 else:
5397 error(self.pos,
5398 "Cannot select attribute of incomplete type '%s'"
5399 % obj_type)
5400 self.type = PyrexTypes.error_type
5401 return
5402 self.entry = entry
5403 if entry:
5404 if obj_type.is_extension_type and entry.name == "__weakref__":
5405 error(self.pos, "Illegal use of special attribute __weakref__")
5407 # def methods need the normal attribute lookup
5408 # because they do not have struct entries
5409 # fused function go through assignment synthesis
5410 # (foo = pycfunction(foo_func_obj)) and need to go through
5411 # regular Python lookup as well
5412 if (entry.is_variable and not entry.fused_cfunction) or entry.is_cmethod:
5413 self.type = entry.type
5414 self.member = entry.cname
5415 return
5416 else:
5417 # If it's not a variable or C method, it must be a Python
5418 # method of an extension type, so we treat it like a Python
5419 # attribute.
5420 pass
5421 # If we get here, the base object is not a struct/union/extension
5422 # type, or it is an extension type and the attribute is either not
5423 # declared or is declared as a Python method. Treat it as a Python
5424 # attribute reference.
5425 self.analyse_as_python_attribute(env, obj_type, immutable_obj)
5427 def analyse_as_python_attribute(self, env, obj_type=None, immutable_obj=False):
5428 if obj_type is None:
5429 obj_type = self.obj.type
5430 # mangle private '__*' Python attributes used inside of a class
5431 self.attribute = env.mangle_class_private_name(self.attribute)
5432 self.member = self.attribute
5433 self.type = py_object_type
5434 self.is_py_attr = 1
5435 if not obj_type.is_pyobject and not obj_type.is_error:
5436 if obj_type.can_coerce_to_pyobject(env):
5437 if not immutable_obj:
5438 self.obj = self.obj.coerce_to_pyobject(env)
5439 elif (obj_type.is_cfunction and (self.obj.is_name or self.obj.is_attribute)
5440 and self.obj.entry.as_variable
5441 and self.obj.entry.as_variable.type.is_pyobject):
5442 # might be an optimised builtin function => unpack it
5443 if not immutable_obj:
5444 self.obj = self.obj.coerce_to_pyobject(env)
5445 else:
5446 error(self.pos,
5447 "Object of type '%s' has no attribute '%s'" %
5448 (obj_type, self.attribute))
5450 def wrap_obj_in_nonecheck(self, env):
5451 if not env.directives['nonecheck']:
5452 return
5454 msg = None
5455 format_args = ()
5456 if (self.obj.type.is_extension_type and self.needs_none_check and not
5457 self.is_py_attr):
5458 msg = "'NoneType' object has no attribute '%s'"
5459 format_args = (self.attribute,)
5460 elif self.obj.type.is_memoryviewslice:
5461 if self.is_memslice_transpose:
5462 msg = "Cannot transpose None memoryview slice"
5463 else:
5464 entry = self.obj.type.scope.lookup_here(self.attribute)
5465 if entry:
5466 # copy/is_c_contig/shape/strides etc
5467 msg = "Cannot access '%s' attribute of None memoryview slice"
5468 format_args = (entry.name,)
5470 if msg:
5471 self.obj = self.obj.as_none_safe_node(msg, 'PyExc_AttributeError',
5472 format_args=format_args)
5475 def nogil_check(self, env):
5476 if self.is_py_attr:
5477 self.gil_error()
5478 elif self.type.is_memoryviewslice:
5479 import MemoryView
5480 MemoryView.err_if_nogil_initialized_check(self.pos, env, 'attribute')
5482 gil_message = "Accessing Python attribute"
5484 def is_simple(self):
5485 if self.obj:
5486 return self.result_in_temp() or self.obj.is_simple()
5487 else:
5488 return NameNode.is_simple(self)
5490 def is_lvalue(self):
5491 if self.obj:
5492 return not self.type.is_array
5493 else:
5494 return NameNode.is_lvalue(self)
5496 def is_ephemeral(self):
5497 if self.obj:
5498 return self.obj.is_ephemeral()
5499 else:
5500 return NameNode.is_ephemeral(self)
5502 def calculate_result_code(self):
5503 #print "AttributeNode.calculate_result_code:", self.member ###
5504 #print "...obj node =", self.obj, "code", self.obj.result() ###
5505 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
5506 obj = self.obj
5507 obj_code = obj.result_as(obj.type)
5508 #print "...obj_code =", obj_code ###
5509 if self.entry and self.entry.is_cmethod:
5510 if obj.type.is_extension_type and not self.entry.is_builtin_cmethod:
5511 if self.entry.final_func_cname:
5512 return self.entry.final_func_cname
5514 if self.type.from_fused:
5515 # If the attribute was specialized through indexing, make
5516 # sure to get the right fused name, as our entry was
5517 # replaced by our parent index node
5518 # (AnalyseExpressionsTransform)
5519 self.member = self.entry.cname
5521 return "((struct %s *)%s%s%s)->%s" % (
5522 obj.type.vtabstruct_cname, obj_code, self.op,
5523 obj.type.vtabslot_cname, self.member)
5524 elif self.result_is_used:
5525 return self.member
5526 # Generating no code at all for unused access to optimised builtin
5527 # methods fixes the problem that some optimisations only exist as
5528 # macros, i.e. there is no function pointer to them, so we would
5529 # generate invalid C code here.
5530 return
5531 elif obj.type.is_complex:
5532 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
5533 else:
5534 if obj.type.is_builtin_type and self.entry and self.entry.is_variable:
5535 # accessing a field of a builtin type, need to cast better than result_as() does
5536 obj_code = obj.type.cast_code(obj.result(), to_object_struct = True)
5537 return "%s%s%s" % (obj_code, self.op, self.member)
5539 def generate_result_code(self, code):
5540 if self.is_py_attr:
5541 if self.is_special_lookup:
5542 code.globalstate.use_utility_code(
5543 UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHandling.c"))
5544 lookup_func_name = '__Pyx_PyObject_LookupSpecial'
5545 else:
5546 code.globalstate.use_utility_code(
5547 UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
5548 lookup_func_name = '__Pyx_PyObject_GetAttrStr'
5549 code.putln(
5550 '%s = %s(%s, %s); %s' % (
5551 self.result(),
5552 lookup_func_name,
5553 self.obj.py_result(),
5554 code.intern_identifier(self.attribute),
5555 code.error_goto_if_null(self.result(), self.pos)))
5556 code.put_gotref(self.py_result())
5557 elif self.type.is_memoryviewslice:
5558 if self.is_memslice_transpose:
5559 # transpose the slice
5560 for access, packing in self.type.axes:
5561 if access == 'ptr':
5562 error(self.pos, "Transposing not supported for slices "
5563 "with indirect dimensions")
5564 return
5566 code.putln("%s = %s;" % (self.result(), self.obj.result()))
5567 if self.obj.is_name or (self.obj.is_attribute and
5568 self.obj.is_memslice_transpose):
5569 code.put_incref_memoryviewslice(self.result(), have_gil=True)
5571 T = "__pyx_memslice_transpose(&%s) == 0"
5572 code.putln(code.error_goto_if(T % self.result(), self.pos))
5573 elif self.initialized_check:
5574 code.putln(
5575 'if (unlikely(!%s.memview)) {'
5576 'PyErr_SetString(PyExc_AttributeError,'
5577 '"Memoryview is not initialized");'
5578 '%s'
5579 '}' % (self.result(), code.error_goto(self.pos)))
5580 else:
5581 # result_code contains what is needed, but we may need to insert
5582 # a check and raise an exception
5583 if self.obj.type.is_extension_type:
5584 pass
5585 elif self.entry and self.entry.is_cmethod and self.entry.utility_code:
5586 # C method implemented as function call with utility code
5587 code.globalstate.use_utility_code(self.entry.utility_code)
5589 def generate_disposal_code(self, code):
5590 if self.is_temp and self.type.is_memoryviewslice and self.is_memslice_transpose:
5591 # mirror condition for putting the memview incref here:
5592 if self.obj.is_name or (self.obj.is_attribute and
5593 self.obj.is_memslice_transpose):
5594 code.put_xdecref_memoryviewslice(
5595 self.result(), have_gil=True)
5596 else:
5597 ExprNode.generate_disposal_code(self, code)
5599 def generate_assignment_code(self, rhs, code):
5600 self.obj.generate_evaluation_code(code)
5601 if self.is_py_attr:
5602 code.globalstate.use_utility_code(
5603 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"))
5604 code.put_error_if_neg(self.pos,
5605 '__Pyx_PyObject_SetAttrStr(%s, %s, %s)' % (
5606 self.obj.py_result(),
5607 code.intern_identifier(self.attribute),
5608 rhs.py_result()))
5609 rhs.generate_disposal_code(code)
5610 rhs.free_temps(code)
5611 elif self.obj.type.is_complex:
5612 code.putln("__Pyx_SET_C%s(%s, %s);" % (
5613 self.member.upper(),
5614 self.obj.result_as(self.obj.type),
5615 rhs.result_as(self.ctype())))
5616 else:
5617 select_code = self.result()
5618 if self.type.is_pyobject and self.use_managed_ref:
5619 rhs.make_owned_reference(code)
5620 code.put_giveref(rhs.py_result())
5621 code.put_gotref(select_code)
5622 code.put_decref(select_code, self.ctype())
5623 elif self.type.is_memoryviewslice:
5624 import MemoryView
5625 MemoryView.put_assign_to_memviewslice(
5626 select_code, rhs, rhs.result(), self.type, code)
5628 if not self.type.is_memoryviewslice:
5629 code.putln(
5630 "%s = %s;" % (
5631 select_code,
5632 rhs.result_as(self.ctype())))
5633 #rhs.result()))
5634 rhs.generate_post_assignment_code(code)
5635 rhs.free_temps(code)
5636 self.obj.generate_disposal_code(code)
5637 self.obj.free_temps(code)
5639 def generate_deletion_code(self, code, ignore_nonexisting=False):
5640 self.obj.generate_evaluation_code(code)
5641 if self.is_py_attr or (self.entry.scope.is_property_scope
5642 and u'__del__' in self.entry.scope.entries):
5643 code.globalstate.use_utility_code(
5644 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"))
5645 code.put_error_if_neg(self.pos,
5646 '__Pyx_PyObject_DelAttrStr(%s, %s)' % (
5647 self.obj.py_result(),
5648 code.intern_identifier(self.attribute)))
5649 else:
5650 error(self.pos, "Cannot delete C attribute of extension type")
5651 self.obj.generate_disposal_code(code)
5652 self.obj.free_temps(code)
5654 def annotate(self, code):
5655 if self.is_py_attr:
5656 style, text = 'py_attr', 'python attribute (%s)'
5657 else:
5658 style, text = 'c_attr', 'c attribute (%s)'
5659 code.annotate(self.pos, AnnotationItem(style, text % self.type, size=len(self.attribute)))
5662 #-------------------------------------------------------------------
5664 # Constructor nodes
5666 #-------------------------------------------------------------------
5668 class StarredTargetNode(ExprNode):
5669 # A starred expression like "*a"
5671 # This is only allowed in sequence assignment targets such as
5673 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
5675 # and will be removed during type analysis (or generate an error
5676 # if it's found at unexpected places).
5678 # target ExprNode
5680 subexprs = ['target']
5681 is_starred = 1
5682 type = py_object_type
5683 is_temp = 1
5685 def __init__(self, pos, target):
5686 ExprNode.__init__(self, pos)
5687 self.target = target
5689 def analyse_declarations(self, env):
5690 error(self.pos, "can use starred expression only as assignment target")
5691 self.target.analyse_declarations(env)
5693 def analyse_types(self, env):
5694 error(self.pos, "can use starred expression only as assignment target")
5695 self.target = self.target.analyse_types(env)
5696 self.type = self.target.type
5697 return self
5699 def analyse_target_declaration(self, env):
5700 self.target.analyse_target_declaration(env)
5702 def analyse_target_types(self, env):
5703 self.target = self.target.analyse_target_types(env)
5704 self.type = self.target.type
5705 return self
5707 def calculate_result_code(self):
5708 return ""
5710 def generate_result_code(self, code):
5711 pass
5714 class SequenceNode(ExprNode):
5715 # Base class for list and tuple constructor nodes.
5716 # Contains common code for performing sequence unpacking.
5718 # args [ExprNode]
5719 # unpacked_items [ExprNode] or None
5720 # coerced_unpacked_items [ExprNode] or None
5721 # mult_factor ExprNode the integer number of content repetitions ([1,2]*3)
5723 subexprs = ['args', 'mult_factor']
5725 is_sequence_constructor = 1
5726 unpacked_items = None
5727 mult_factor = None
5728 slow = False # trade speed for code size (e.g. use PyTuple_Pack())
5730 def compile_time_value_list(self, denv):
5731 return [arg.compile_time_value(denv) for arg in self.args]
5733 def replace_starred_target_node(self):
5734 # replace a starred node in the targets by the contained expression
5735 self.starred_assignment = False
5736 args = []
5737 for arg in self.args:
5738 if arg.is_starred:
5739 if self.starred_assignment:
5740 error(arg.pos, "more than 1 starred expression in assignment")
5741 self.starred_assignment = True
5742 arg = arg.target
5743 arg.is_starred = True
5744 args.append(arg)
5745 self.args = args
5747 def analyse_target_declaration(self, env):
5748 self.replace_starred_target_node()
5749 for arg in self.args:
5750 arg.analyse_target_declaration(env)
5752 def analyse_types(self, env, skip_children=False):
5753 for i in range(len(self.args)):
5754 arg = self.args[i]
5755 if not skip_children: arg = arg.analyse_types(env)
5756 self.args[i] = arg.coerce_to_pyobject(env)
5757 if self.mult_factor:
5758 self.mult_factor = self.mult_factor.analyse_types(env)
5759 if not self.mult_factor.type.is_int:
5760 self.mult_factor = self.mult_factor.coerce_to_pyobject(env)
5761 self.is_temp = 1
5762 # not setting self.type here, subtypes do this
5763 return self
5765 def may_be_none(self):
5766 return False
5768 def analyse_target_types(self, env):
5769 if self.mult_factor:
5770 error(self.pos, "can't assign to multiplied sequence")
5771 self.unpacked_items = []
5772 self.coerced_unpacked_items = []
5773 self.any_coerced_items = False
5774 for i, arg in enumerate(self.args):
5775 arg = self.args[i] = arg.analyse_target_types(env)
5776 if arg.is_starred:
5777 if not arg.type.assignable_from(Builtin.list_type):
5778 error(arg.pos,
5779 "starred target must have Python object (list) type")
5780 if arg.type is py_object_type:
5781 arg.type = Builtin.list_type
5782 unpacked_item = PyTempNode(self.pos, env)
5783 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
5784 if unpacked_item is not coerced_unpacked_item:
5785 self.any_coerced_items = True
5786 self.unpacked_items.append(unpacked_item)
5787 self.coerced_unpacked_items.append(coerced_unpacked_item)
5788 self.type = py_object_type
5789 return self
5791 def generate_result_code(self, code):
5792 self.generate_operation_code(code)
5794 def generate_sequence_packing_code(self, code, target=None, plain=False):
5795 if target is None:
5796 target = self.result()
5797 size_factor = c_mult = ''
5798 mult_factor = None
5800 if self.mult_factor and not plain:
5801 mult_factor = self.mult_factor
5802 if mult_factor.type.is_int:
5803 c_mult = mult_factor.result()
5804 if isinstance(mult_factor.constant_result, (int,long)) \
5805 and mult_factor.constant_result > 0:
5806 size_factor = ' * %s' % mult_factor.constant_result
5807 else:
5808 size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult)
5810 if self.type is Builtin.tuple_type and (self.is_literal or self.slow) and not c_mult:
5811 # use PyTuple_Pack() to avoid generating huge amounts of one-time code
5812 code.putln('%s = PyTuple_Pack(%d, %s); %s' % (
5813 target,
5814 len(self.args),
5815 ', '.join([ arg.py_result() for arg in self.args ]),
5816 code.error_goto_if_null(target, self.pos)))
5817 code.put_gotref(target)
5818 else:
5819 # build the tuple/list step by step, potentially multiplying it as we go
5820 if self.type is Builtin.list_type:
5821 create_func, set_item_func = 'PyList_New', 'PyList_SET_ITEM'
5822 elif self.type is Builtin.tuple_type:
5823 create_func, set_item_func = 'PyTuple_New', 'PyTuple_SET_ITEM'
5824 else:
5825 raise InternalError("sequence packing for unexpected type %s" % self.type)
5826 arg_count = len(self.args)
5827 code.putln("%s = %s(%s%s); %s" % (
5828 target, create_func, arg_count, size_factor,
5829 code.error_goto_if_null(target, self.pos)))
5830 code.put_gotref(target)
5832 if c_mult:
5833 # FIXME: can't use a temp variable here as the code may
5834 # end up in the constant building function. Temps
5835 # currently don't work there.
5837 #counter = code.funcstate.allocate_temp(mult_factor.type, manage_ref=False)
5838 counter = Naming.quick_temp_cname
5839 code.putln('{ Py_ssize_t %s;' % counter)
5840 if arg_count == 1:
5841 offset = counter
5842 else:
5843 offset = '%s * %s' % (counter, arg_count)
5844 code.putln('for (%s=0; %s < %s; %s++) {' % (
5845 counter, counter, c_mult, counter
5847 else:
5848 offset = ''
5850 for i in xrange(arg_count):
5851 arg = self.args[i]
5852 if c_mult or not arg.result_in_temp():
5853 code.put_incref(arg.result(), arg.ctype())
5854 code.putln("%s(%s, %s, %s);" % (
5855 set_item_func,
5856 target,
5857 (offset and i) and ('%s + %s' % (offset, i)) or (offset or i),
5858 arg.py_result()))
5859 code.put_giveref(arg.py_result())
5861 if c_mult:
5862 code.putln('}')
5863 #code.funcstate.release_temp(counter)
5864 code.putln('}')
5866 if mult_factor is not None and mult_factor.type.is_pyobject:
5867 code.putln('{ PyObject* %s = PyNumber_InPlaceMultiply(%s, %s); %s' % (
5868 Naming.quick_temp_cname, target, mult_factor.py_result(),
5869 code.error_goto_if_null(Naming.quick_temp_cname, self.pos)
5871 code.put_gotref(Naming.quick_temp_cname)
5872 code.put_decref(target, py_object_type)
5873 code.putln('%s = %s;' % (target, Naming.quick_temp_cname))
5874 code.putln('}')
5876 def generate_subexpr_disposal_code(self, code):
5877 if self.mult_factor and self.mult_factor.type.is_int:
5878 super(SequenceNode, self).generate_subexpr_disposal_code(code)
5879 elif self.type is Builtin.tuple_type and (self.is_literal or self.slow):
5880 super(SequenceNode, self).generate_subexpr_disposal_code(code)
5881 else:
5882 # We call generate_post_assignment_code here instead
5883 # of generate_disposal_code, because values were stored
5884 # in the tuple using a reference-stealing operation.
5885 for arg in self.args:
5886 arg.generate_post_assignment_code(code)
5887 # Should NOT call free_temps -- this is invoked by the default
5888 # generate_evaluation_code which will do that.
5889 if self.mult_factor:
5890 self.mult_factor.generate_disposal_code(code)
5892 def generate_assignment_code(self, rhs, code):
5893 if self.starred_assignment:
5894 self.generate_starred_assignment_code(rhs, code)
5895 else:
5896 self.generate_parallel_assignment_code(rhs, code)
5898 for item in self.unpacked_items:
5899 item.release(code)
5900 rhs.free_temps(code)
5902 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
5903 PyrexTypes.py_object_type, [
5904 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None),
5907 def generate_parallel_assignment_code(self, rhs, code):
5908 # Need to work around the fact that generate_evaluation_code
5909 # allocates the temps in a rather hacky way -- the assignment
5910 # is evaluated twice, within each if-block.
5911 for item in self.unpacked_items:
5912 item.allocate(code)
5913 special_unpack = (rhs.type is py_object_type
5914 or rhs.type in (tuple_type, list_type)
5915 or not rhs.type.is_builtin_type)
5916 long_enough_for_a_loop = len(self.unpacked_items) > 3
5918 if special_unpack:
5919 self.generate_special_parallel_unpacking_code(
5920 code, rhs, use_loop=long_enough_for_a_loop)
5921 else:
5922 code.putln("{")
5923 self.generate_generic_parallel_unpacking_code(
5924 code, rhs, self.unpacked_items, use_loop=long_enough_for_a_loop)
5925 code.putln("}")
5927 for value_node in self.coerced_unpacked_items:
5928 value_node.generate_evaluation_code(code)
5929 for i in range(len(self.args)):
5930 self.args[i].generate_assignment_code(
5931 self.coerced_unpacked_items[i], code)
5933 def generate_special_parallel_unpacking_code(self, code, rhs, use_loop):
5934 sequence_type_test = '1'
5935 none_check = "likely(%s != Py_None)" % rhs.py_result()
5936 if rhs.type is list_type:
5937 sequence_types = ['List']
5938 if rhs.may_be_none():
5939 sequence_type_test = none_check
5940 elif rhs.type is tuple_type:
5941 sequence_types = ['Tuple']
5942 if rhs.may_be_none():
5943 sequence_type_test = none_check
5944 else:
5945 sequence_types = ['Tuple', 'List']
5946 tuple_check = 'likely(PyTuple_CheckExact(%s))' % rhs.py_result()
5947 list_check = 'PyList_CheckExact(%s)' % rhs.py_result()
5948 sequence_type_test = "(%s) || (%s)" % (tuple_check, list_check)
5950 code.putln("if (%s) {" % sequence_type_test)
5951 code.putln("PyObject* sequence = %s;" % rhs.py_result())
5953 # list/tuple => check size
5954 code.putln("#if CYTHON_COMPILING_IN_CPYTHON")
5955 code.putln("Py_ssize_t size = Py_SIZE(sequence);")
5956 code.putln("#else")
5957 code.putln("Py_ssize_t size = PySequence_Size(sequence);") # < 0 => exception
5958 code.putln("#endif")
5959 code.putln("if (unlikely(size != %d)) {" % len(self.args))
5960 code.globalstate.use_utility_code(raise_too_many_values_to_unpack)
5961 code.putln("if (size > %d) __Pyx_RaiseTooManyValuesError(%d);" % (
5962 len(self.args), len(self.args)))
5963 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
5964 code.putln("else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);")
5965 code.putln(code.error_goto(self.pos))
5966 code.putln("}")
5968 code.putln("#if CYTHON_COMPILING_IN_CPYTHON")
5969 # unpack items from list/tuple in unrolled loop (can't fail)
5970 if len(sequence_types) == 2:
5971 code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types[0])
5972 for i, item in enumerate(self.unpacked_items):
5973 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % (
5974 item.result(), sequence_types[0], i))
5975 if len(sequence_types) == 2:
5976 code.putln("} else {")
5977 for i, item in enumerate(self.unpacked_items):
5978 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % (
5979 item.result(), sequence_types[1], i))
5980 code.putln("}")
5981 for item in self.unpacked_items:
5982 code.put_incref(item.result(), item.ctype())
5984 code.putln("#else")
5985 # in non-CPython, use the PySequence protocol (which can fail)
5986 if not use_loop:
5987 for i, item in enumerate(self.unpacked_items):
5988 code.putln("%s = PySequence_ITEM(sequence, %d); %s" % (
5989 item.result(), i,
5990 code.error_goto_if_null(item.result(), self.pos)))
5991 code.put_gotref(item.result())
5992 else:
5993 code.putln("{")
5994 code.putln("Py_ssize_t i;")
5995 code.putln("PyObject** temps[%s] = {%s};" % (
5996 len(self.unpacked_items),
5997 ','.join(['&%s' % item.result() for item in self.unpacked_items])))
5998 code.putln("for (i=0; i < %s; i++) {" % len(self.unpacked_items))
5999 code.putln("PyObject* item = PySequence_ITEM(sequence, i); %s" % (
6000 code.error_goto_if_null('item', self.pos)))
6001 code.put_gotref('item')
6002 code.putln("*(temps[i]) = item;")
6003 code.putln("}")
6004 code.putln("}")
6006 code.putln("#endif")
6007 rhs.generate_disposal_code(code)
6009 if sequence_type_test == '1':
6010 code.putln("}") # all done
6011 elif sequence_type_test == none_check:
6012 # either tuple/list or None => save some code by generating the error directly
6013 code.putln("} else {")
6014 code.globalstate.use_utility_code(
6015 UtilityCode.load_cached("RaiseNoneIterError", "ObjectHandling.c"))
6016 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" % code.error_goto(self.pos))
6017 code.putln("}") # all done
6018 else:
6019 code.putln("} else {") # needs iteration fallback code
6020 self.generate_generic_parallel_unpacking_code(
6021 code, rhs, self.unpacked_items, use_loop=use_loop)
6022 code.putln("}")
6024 def generate_generic_parallel_unpacking_code(self, code, rhs, unpacked_items, use_loop, terminate=True):
6025 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
6026 code.globalstate.use_utility_code(UtilityCode.load_cached("IterFinish", "ObjectHandling.c"))
6027 code.putln("Py_ssize_t index = -1;") # must be at the start of a C block!
6029 if use_loop:
6030 code.putln("PyObject** temps[%s] = {%s};" % (
6031 len(self.unpacked_items),
6032 ','.join(['&%s' % item.result() for item in unpacked_items])))
6034 iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
6035 code.putln(
6036 "%s = PyObject_GetIter(%s); %s" % (
6037 iterator_temp,
6038 rhs.py_result(),
6039 code.error_goto_if_null(iterator_temp, self.pos)))
6040 code.put_gotref(iterator_temp)
6041 rhs.generate_disposal_code(code)
6043 iternext_func = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False)
6044 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % (
6045 iternext_func, iterator_temp))
6047 unpacking_error_label = code.new_label('unpacking_failed')
6048 unpack_code = "%s(%s)" % (iternext_func, iterator_temp)
6049 if use_loop:
6050 code.putln("for (index=0; index < %s; index++) {" % len(unpacked_items))
6051 code.put("PyObject* item = %s; if (unlikely(!item)) " % unpack_code)
6052 code.put_goto(unpacking_error_label)
6053 code.put_gotref("item")
6054 code.putln("*(temps[index]) = item;")
6055 code.putln("}")
6056 else:
6057 for i, item in enumerate(unpacked_items):
6058 code.put(
6059 "index = %d; %s = %s; if (unlikely(!%s)) " % (
6061 item.result(),
6062 unpack_code,
6063 item.result()))
6064 code.put_goto(unpacking_error_label)
6065 code.put_gotref(item.py_result())
6067 if terminate:
6068 code.globalstate.use_utility_code(
6069 UtilityCode.load_cached("UnpackItemEndCheck", "ObjectHandling.c"))
6070 code.put_error_if_neg(self.pos, "__Pyx_IternextUnpackEndCheck(%s, %d)" % (
6071 unpack_code,
6072 len(unpacked_items)))
6073 code.putln("%s = NULL;" % iternext_func)
6074 code.put_decref_clear(iterator_temp, py_object_type)
6076 unpacking_done_label = code.new_label('unpacking_done')
6077 code.put_goto(unpacking_done_label)
6079 code.put_label(unpacking_error_label)
6080 code.put_decref_clear(iterator_temp, py_object_type)
6081 code.putln("%s = NULL;" % iternext_func)
6082 code.putln("if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);")
6083 code.putln(code.error_goto(self.pos))
6084 code.put_label(unpacking_done_label)
6086 code.funcstate.release_temp(iternext_func)
6087 if terminate:
6088 code.funcstate.release_temp(iterator_temp)
6089 iterator_temp = None
6091 return iterator_temp
6093 def generate_starred_assignment_code(self, rhs, code):
6094 for i, arg in enumerate(self.args):
6095 if arg.is_starred:
6096 starred_target = self.unpacked_items[i]
6097 unpacked_fixed_items_left = self.unpacked_items[:i]
6098 unpacked_fixed_items_right = self.unpacked_items[i+1:]
6099 break
6100 else:
6101 assert False
6103 iterator_temp = None
6104 if unpacked_fixed_items_left:
6105 for item in unpacked_fixed_items_left:
6106 item.allocate(code)
6107 code.putln('{')
6108 iterator_temp = self.generate_generic_parallel_unpacking_code(
6109 code, rhs, unpacked_fixed_items_left,
6110 use_loop=True, terminate=False)
6111 for i, item in enumerate(unpacked_fixed_items_left):
6112 value_node = self.coerced_unpacked_items[i]
6113 value_node.generate_evaluation_code(code)
6114 code.putln('}')
6116 starred_target.allocate(code)
6117 target_list = starred_target.result()
6118 code.putln("%s = PySequence_List(%s); %s" % (
6119 target_list,
6120 iterator_temp or rhs.py_result(),
6121 code.error_goto_if_null(target_list, self.pos)))
6122 code.put_gotref(target_list)
6124 if iterator_temp:
6125 code.put_decref_clear(iterator_temp, py_object_type)
6126 code.funcstate.release_temp(iterator_temp)
6127 else:
6128 rhs.generate_disposal_code(code)
6130 if unpacked_fixed_items_right:
6131 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
6132 length_temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
6133 code.putln('%s = PyList_GET_SIZE(%s);' % (length_temp, target_list))
6134 code.putln("if (unlikely(%s < %d)) {" % (length_temp, len(unpacked_fixed_items_right)))
6135 code.putln("__Pyx_RaiseNeedMoreValuesError(%d+%s); %s" % (
6136 len(unpacked_fixed_items_left), length_temp,
6137 code.error_goto(self.pos)))
6138 code.putln('}')
6140 for item in unpacked_fixed_items_right[::-1]:
6141 item.allocate(code)
6142 for i, (item, coerced_arg) in enumerate(zip(unpacked_fixed_items_right[::-1],
6143 self.coerced_unpacked_items[::-1])):
6144 code.putln('#if CYTHON_COMPILING_IN_CPYTHON')
6145 code.putln("%s = PyList_GET_ITEM(%s, %s-%d); " % (
6146 item.py_result(), target_list, length_temp, i+1))
6147 # resize the list the hard way
6148 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
6149 code.putln('#else')
6150 code.putln("%s = PySequence_ITEM(%s, %s-%d); " % (
6151 item.py_result(), target_list, length_temp, i+1))
6152 code.putln('#endif')
6153 code.put_gotref(item.py_result())
6154 coerced_arg.generate_evaluation_code(code)
6156 code.putln('#if !CYTHON_COMPILING_IN_CPYTHON')
6157 sublist_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
6158 code.putln('%s = PySequence_GetSlice(%s, 0, %s-%d); %s' % (
6159 sublist_temp, target_list, length_temp, len(unpacked_fixed_items_right),
6160 code.error_goto_if_null(sublist_temp, self.pos)))
6161 code.put_gotref(sublist_temp)
6162 code.funcstate.release_temp(length_temp)
6163 code.put_decref(target_list, py_object_type)
6164 code.putln('%s = %s; %s = NULL;' % (target_list, sublist_temp, sublist_temp))
6165 code.putln('#else')
6166 code.putln('%s = %s;' % (sublist_temp, sublist_temp)) # avoid warning about unused variable
6167 code.funcstate.release_temp(sublist_temp)
6168 code.putln('#endif')
6170 for i, arg in enumerate(self.args):
6171 arg.generate_assignment_code(self.coerced_unpacked_items[i], code)
6173 def annotate(self, code):
6174 for arg in self.args:
6175 arg.annotate(code)
6176 if self.unpacked_items:
6177 for arg in self.unpacked_items:
6178 arg.annotate(code)
6179 for arg in self.coerced_unpacked_items:
6180 arg.annotate(code)
6183 class TupleNode(SequenceNode):
6184 # Tuple constructor.
6186 type = tuple_type
6187 is_partly_literal = False
6189 gil_message = "Constructing Python tuple"
6191 def analyse_types(self, env, skip_children=False):
6192 if len(self.args) == 0:
6193 node = self
6194 node.is_temp = False
6195 node.is_literal = True
6196 else:
6197 node = SequenceNode.analyse_types(self, env, skip_children)
6198 for child in node.args:
6199 if not child.is_literal:
6200 break
6201 else:
6202 if not node.mult_factor or node.mult_factor.is_literal and \
6203 isinstance(node.mult_factor.constant_result, (int, long)):
6204 node.is_temp = False
6205 node.is_literal = True
6206 else:
6207 if not node.mult_factor.type.is_pyobject:
6208 node.mult_factor = node.mult_factor.coerce_to_pyobject(env)
6209 node.is_temp = True
6210 node.is_partly_literal = True
6211 return node
6213 def is_simple(self):
6214 # either temp or constant => always simple
6215 return True
6217 def nonlocally_immutable(self):
6218 # either temp or constant => always safe
6219 return True
6221 def calculate_result_code(self):
6222 if len(self.args) > 0:
6223 return self.result_code
6224 else:
6225 return Naming.empty_tuple
6227 def calculate_constant_result(self):
6228 self.constant_result = tuple([
6229 arg.constant_result for arg in self.args])
6231 def compile_time_value(self, denv):
6232 values = self.compile_time_value_list(denv)
6233 try:
6234 return tuple(values)
6235 except Exception, e:
6236 self.compile_time_value_error(e)
6238 def generate_operation_code(self, code):
6239 if len(self.args) == 0:
6240 # result_code is Naming.empty_tuple
6241 return
6242 if self.is_partly_literal:
6243 # underlying tuple is const, but factor is not
6244 tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_level=2)
6245 const_code = code.get_cached_constants_writer()
6246 const_code.mark_pos(self.pos)
6247 self.generate_sequence_packing_code(const_code, tuple_target, plain=True)
6248 const_code.put_giveref(tuple_target)
6249 code.putln('%s = PyNumber_Multiply(%s, %s); %s' % (
6250 self.result(), tuple_target, self.mult_factor.py_result(),
6251 code.error_goto_if_null(self.result(), self.pos)
6253 code.put_gotref(self.py_result())
6254 elif self.is_literal:
6255 # non-empty cached tuple => result is global constant,
6256 # creation code goes into separate code writer
6257 self.result_code = code.get_py_const(py_object_type, 'tuple', cleanup_level=2)
6258 code = code.get_cached_constants_writer()
6259 code.mark_pos(self.pos)
6260 self.generate_sequence_packing_code(code)
6261 code.put_giveref(self.py_result())
6262 else:
6263 self.generate_sequence_packing_code(code)
6266 class ListNode(SequenceNode):
6267 # List constructor.
6269 # obj_conversion_errors [PyrexError] used internally
6270 # orignial_args [ExprNode] used internally
6272 obj_conversion_errors = []
6273 type = list_type
6274 in_module_scope = False
6276 gil_message = "Constructing Python list"
6278 def type_dependencies(self, env):
6279 return ()
6281 def infer_type(self, env):
6282 # TOOD: Infer non-object list arrays.
6283 return list_type
6285 def analyse_expressions(self, env):
6286 node = SequenceNode.analyse_expressions(self, env)
6287 return node.coerce_to_pyobject(env)
6289 def analyse_types(self, env):
6290 hold_errors()
6291 self.original_args = list(self.args)
6292 node = SequenceNode.analyse_types(self, env)
6293 node.obj_conversion_errors = held_errors()
6294 release_errors(ignore=True)
6295 if env.is_module_scope:
6296 self.in_module_scope = True
6297 return node
6299 def coerce_to(self, dst_type, env):
6300 if dst_type.is_pyobject:
6301 for err in self.obj_conversion_errors:
6302 report_error(err)
6303 self.obj_conversion_errors = []
6304 if not self.type.subtype_of(dst_type):
6305 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
6306 elif self.mult_factor:
6307 error(self.pos, "Cannot coerce multiplied list to '%s'" % dst_type)
6308 elif dst_type.is_ptr and dst_type.base_type is not PyrexTypes.c_void_type:
6309 base_type = dst_type.base_type
6310 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
6311 for i in range(len(self.original_args)):
6312 arg = self.args[i]
6313 if isinstance(arg, CoerceToPyTypeNode):
6314 arg = arg.arg
6315 self.args[i] = arg.coerce_to(base_type, env)
6316 elif dst_type.is_struct:
6317 if len(self.args) > len(dst_type.scope.var_entries):
6318 error(self.pos, "Too may members for '%s'" % dst_type)
6319 else:
6320 if len(self.args) < len(dst_type.scope.var_entries):
6321 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
6322 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
6323 if isinstance(arg, CoerceToPyTypeNode):
6324 arg = arg.arg
6325 self.args[i] = arg.coerce_to(member.type, env)
6326 self.type = dst_type
6327 else:
6328 self.type = error_type
6329 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
6330 return self
6332 def as_tuple(self):
6333 t = TupleNode(self.pos, args=self.args, mult_factor=self.mult_factor)
6334 if isinstance(self.constant_result, list):
6335 t.constant_result = tuple(self.constant_result)
6336 return t
6338 def allocate_temp_result(self, code):
6339 if self.type.is_array and self.in_module_scope:
6340 self.temp_code = code.funcstate.allocate_temp(
6341 self.type, manage_ref=False, static=True)
6342 else:
6343 SequenceNode.allocate_temp_result(self, code)
6345 def release_temp_result(self, env):
6346 if self.type.is_array:
6347 # To be valid C++, we must allocate the memory on the stack
6348 # manually and be sure not to reuse it for something else.
6349 pass
6350 else:
6351 SequenceNode.release_temp_result(self, env)
6353 def calculate_constant_result(self):
6354 if self.mult_factor:
6355 raise ValueError() # may exceed the compile time memory
6356 self.constant_result = [
6357 arg.constant_result for arg in self.args]
6359 def compile_time_value(self, denv):
6360 l = self.compile_time_value_list(denv)
6361 if self.mult_factor:
6362 l *= self.mult_factor.compile_time_value(denv)
6363 return l
6365 def generate_operation_code(self, code):
6366 if self.type.is_pyobject:
6367 for err in self.obj_conversion_errors:
6368 report_error(err)
6369 self.generate_sequence_packing_code(code)
6370 elif self.type.is_array:
6371 for i, arg in enumerate(self.args):
6372 code.putln("%s[%s] = %s;" % (
6373 self.result(),
6375 arg.result()))
6376 elif self.type.is_struct:
6377 for arg, member in zip(self.args, self.type.scope.var_entries):
6378 code.putln("%s.%s = %s;" % (
6379 self.result(),
6380 member.cname,
6381 arg.result()))
6382 else:
6383 raise InternalError("List type never specified")
6386 class ScopedExprNode(ExprNode):
6387 # Abstract base class for ExprNodes that have their own local
6388 # scope, such as generator expressions.
6390 # expr_scope Scope the inner scope of the expression
6392 subexprs = []
6393 expr_scope = None
6395 # does this node really have a local scope, e.g. does it leak loop
6396 # variables or not? non-leaking Py3 behaviour is default, except
6397 # for list comprehensions where the behaviour differs in Py2 and
6398 # Py3 (set in Parsing.py based on parser context)
6399 has_local_scope = True
6401 def init_scope(self, outer_scope, expr_scope=None):
6402 if expr_scope is not None:
6403 self.expr_scope = expr_scope
6404 elif self.has_local_scope:
6405 self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
6406 else:
6407 self.expr_scope = None
6409 def analyse_declarations(self, env):
6410 self.init_scope(env)
6412 def analyse_scoped_declarations(self, env):
6413 # this is called with the expr_scope as env
6414 pass
6416 def analyse_types(self, env):
6417 # no recursion here, the children will be analysed separately below
6418 return self
6420 def analyse_scoped_expressions(self, env):
6421 # this is called with the expr_scope as env
6422 return self
6424 def generate_evaluation_code(self, code):
6425 # set up local variables and free their references on exit
6426 generate_inner_evaluation_code = super(ScopedExprNode, self).generate_evaluation_code
6427 if not self.has_local_scope or not self.expr_scope.var_entries:
6428 # no local variables => delegate, done
6429 generate_inner_evaluation_code(code)
6430 return
6432 code.putln('{ /* enter inner scope */')
6433 py_entries = []
6434 for entry in self.expr_scope.var_entries:
6435 if not entry.in_closure:
6436 code.put_var_declaration(entry)
6437 if entry.type.is_pyobject and entry.used:
6438 py_entries.append(entry)
6439 if not py_entries:
6440 # no local Python references => no cleanup required
6441 generate_inner_evaluation_code(code)
6442 code.putln('} /* exit inner scope */')
6443 return
6445 # must free all local Python references at each exit point
6446 old_loop_labels = tuple(code.new_loop_labels())
6447 old_error_label = code.new_error_label()
6449 generate_inner_evaluation_code(code)
6451 # normal (non-error) exit
6452 for entry in py_entries:
6453 code.put_var_decref(entry)
6455 # error/loop body exit points
6456 exit_scope = code.new_label('exit_scope')
6457 code.put_goto(exit_scope)
6458 for label, old_label in ([(code.error_label, old_error_label)] +
6459 list(zip(code.get_loop_labels(), old_loop_labels))):
6460 if code.label_used(label):
6461 code.put_label(label)
6462 for entry in py_entries:
6463 code.put_var_decref(entry)
6464 code.put_goto(old_label)
6465 code.put_label(exit_scope)
6466 code.putln('} /* exit inner scope */')
6468 code.set_loop_labels(old_loop_labels)
6469 code.error_label = old_error_label
6472 class ComprehensionNode(ScopedExprNode):
6473 # A list/set/dict comprehension
6475 child_attrs = ["loop"]
6477 is_temp = True
6479 def infer_type(self, env):
6480 return self.type
6482 def analyse_declarations(self, env):
6483 self.append.target = self # this is used in the PyList_Append of the inner loop
6484 self.init_scope(env)
6486 def analyse_scoped_declarations(self, env):
6487 self.loop.analyse_declarations(env)
6489 def analyse_types(self, env):
6490 if not self.has_local_scope:
6491 self.loop = self.loop.analyse_expressions(env)
6492 return self
6494 def analyse_scoped_expressions(self, env):
6495 if self.has_local_scope:
6496 self.loop = self.loop.analyse_expressions(env)
6497 return self
6499 def may_be_none(self):
6500 return False
6502 def generate_result_code(self, code):
6503 self.generate_operation_code(code)
6505 def generate_operation_code(self, code):
6506 if self.type is Builtin.list_type:
6507 create_code = 'PyList_New(0)'
6508 elif self.type is Builtin.set_type:
6509 create_code = 'PySet_New(NULL)'
6510 elif self.type is Builtin.dict_type:
6511 create_code = 'PyDict_New()'
6512 else:
6513 raise InternalError("illegal type for comprehension: %s" % self.type)
6514 code.putln('%s = %s; %s' % (
6515 self.result(), create_code,
6516 code.error_goto_if_null(self.result(), self.pos)))
6518 code.put_gotref(self.result())
6519 self.loop.generate_execution_code(code)
6521 def annotate(self, code):
6522 self.loop.annotate(code)
6525 class ComprehensionAppendNode(Node):
6526 # Need to be careful to avoid infinite recursion:
6527 # target must not be in child_attrs/subexprs
6529 child_attrs = ['expr']
6530 target = None
6532 type = PyrexTypes.c_int_type
6534 def analyse_expressions(self, env):
6535 self.expr = self.expr.analyse_expressions(env)
6536 if not self.expr.type.is_pyobject:
6537 self.expr = self.expr.coerce_to_pyobject(env)
6538 return self
6540 def generate_execution_code(self, code):
6541 if self.target.type is list_type:
6542 code.globalstate.use_utility_code(
6543 UtilityCode.load_cached("ListCompAppend", "Optimize.c"))
6544 function = "__Pyx_ListComp_Append"
6545 elif self.target.type is set_type:
6546 function = "PySet_Add"
6547 else:
6548 raise InternalError(
6549 "Invalid type for comprehension node: %s" % self.target.type)
6551 self.expr.generate_evaluation_code(code)
6552 code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % (
6553 function,
6554 self.target.result(),
6555 self.expr.result()
6556 ), self.pos))
6557 self.expr.generate_disposal_code(code)
6558 self.expr.free_temps(code)
6560 def generate_function_definitions(self, env, code):
6561 self.expr.generate_function_definitions(env, code)
6563 def annotate(self, code):
6564 self.expr.annotate(code)
6566 class DictComprehensionAppendNode(ComprehensionAppendNode):
6567 child_attrs = ['key_expr', 'value_expr']
6569 def analyse_expressions(self, env):
6570 self.key_expr = self.key_expr.analyse_expressions(env)
6571 if not self.key_expr.type.is_pyobject:
6572 self.key_expr = self.key_expr.coerce_to_pyobject(env)
6573 self.value_expr = self.value_expr.analyse_expressions(env)
6574 if not self.value_expr.type.is_pyobject:
6575 self.value_expr = self.value_expr.coerce_to_pyobject(env)
6576 return self
6578 def generate_execution_code(self, code):
6579 self.key_expr.generate_evaluation_code(code)
6580 self.value_expr.generate_evaluation_code(code)
6581 code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % (
6582 self.target.result(),
6583 self.key_expr.result(),
6584 self.value_expr.result()
6585 ), self.pos))
6586 self.key_expr.generate_disposal_code(code)
6587 self.key_expr.free_temps(code)
6588 self.value_expr.generate_disposal_code(code)
6589 self.value_expr.free_temps(code)
6591 def generate_function_definitions(self, env, code):
6592 self.key_expr.generate_function_definitions(env, code)
6593 self.value_expr.generate_function_definitions(env, code)
6595 def annotate(self, code):
6596 self.key_expr.annotate(code)
6597 self.value_expr.annotate(code)
6600 class InlinedGeneratorExpressionNode(ScopedExprNode):
6601 # An inlined generator expression for which the result is
6602 # calculated inside of the loop. This will only be created by
6603 # transforms when replacing builtin calls on generator
6604 # expressions.
6606 # loop ForStatNode the for-loop, not containing any YieldExprNodes
6607 # result_node ResultRefNode the reference to the result value temp
6608 # orig_func String the name of the builtin function this node replaces
6610 child_attrs = ["loop"]
6611 loop_analysed = False
6612 type = py_object_type
6614 def analyse_scoped_declarations(self, env):
6615 self.loop.analyse_declarations(env)
6617 def may_be_none(self):
6618 return False
6620 def annotate(self, code):
6621 self.loop.annotate(code)
6623 def infer_type(self, env):
6624 return self.result_node.infer_type(env)
6626 def analyse_types(self, env):
6627 if not self.has_local_scope:
6628 self.loop_analysed = True
6629 self.loop = self.loop.analyse_expressions(env)
6630 self.type = self.result_node.type
6631 self.is_temp = True
6632 return self
6634 def analyse_scoped_expressions(self, env):
6635 self.loop_analysed = True
6636 if self.has_local_scope:
6637 self.loop = self.loop.analyse_expressions(env)
6638 return self
6640 def coerce_to(self, dst_type, env):
6641 if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_analysed:
6642 # We can optimise by dropping the aggregation variable and
6643 # the add operations into C. This can only be done safely
6644 # before analysing the loop body, after that, the result
6645 # reference type will have infected expressions and
6646 # assignments.
6647 self.result_node.type = self.type = dst_type
6648 return self
6649 return super(InlinedGeneratorExpressionNode, self).coerce_to(dst_type, env)
6651 def generate_result_code(self, code):
6652 self.result_node.result_code = self.result()
6653 self.loop.generate_execution_code(code)
6656 class SetNode(ExprNode):
6657 # Set constructor.
6659 type = set_type
6661 subexprs = ['args']
6663 gil_message = "Constructing Python set"
6665 def analyse_types(self, env):
6666 for i in range(len(self.args)):
6667 arg = self.args[i]
6668 arg = arg.analyse_types(env)
6669 self.args[i] = arg.coerce_to_pyobject(env)
6670 self.type = set_type
6671 self.is_temp = 1
6672 return self
6674 def may_be_none(self):
6675 return False
6677 def calculate_constant_result(self):
6678 self.constant_result = set([
6679 arg.constant_result for arg in self.args])
6681 def compile_time_value(self, denv):
6682 values = [arg.compile_time_value(denv) for arg in self.args]
6683 try:
6684 return set(values)
6685 except Exception, e:
6686 self.compile_time_value_error(e)
6688 def generate_evaluation_code(self, code):
6689 code.globalstate.use_utility_code(Builtin.py_set_utility_code)
6690 self.allocate_temp_result(code)
6691 code.putln(
6692 "%s = PySet_New(0); %s" % (
6693 self.result(),
6694 code.error_goto_if_null(self.result(), self.pos)))
6695 code.put_gotref(self.py_result())
6696 for arg in self.args:
6697 arg.generate_evaluation_code(code)
6698 code.put_error_if_neg(
6699 self.pos,
6700 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()))
6701 arg.generate_disposal_code(code)
6702 arg.free_temps(code)
6705 class DictNode(ExprNode):
6706 # Dictionary constructor.
6708 # key_value_pairs [DictItemNode]
6709 # exclude_null_values [boolean] Do not add NULL values to dict
6711 # obj_conversion_errors [PyrexError] used internally
6713 subexprs = ['key_value_pairs']
6714 is_temp = 1
6715 exclude_null_values = False
6716 type = dict_type
6718 obj_conversion_errors = []
6720 @classmethod
6721 def from_pairs(cls, pos, pairs):
6722 return cls(pos, key_value_pairs=[
6723 DictItemNode(pos, key=k, value=v) for k, v in pairs])
6725 def calculate_constant_result(self):
6726 self.constant_result = dict([
6727 item.constant_result for item in self.key_value_pairs])
6729 def compile_time_value(self, denv):
6730 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
6731 for item in self.key_value_pairs]
6732 try:
6733 return dict(pairs)
6734 except Exception, e:
6735 self.compile_time_value_error(e)
6737 def type_dependencies(self, env):
6738 return ()
6740 def infer_type(self, env):
6741 # TOOD: Infer struct constructors.
6742 return dict_type
6744 def analyse_types(self, env):
6745 hold_errors()
6746 self.key_value_pairs = [ item.analyse_types(env)
6747 for item in self.key_value_pairs ]
6748 self.obj_conversion_errors = held_errors()
6749 release_errors(ignore=True)
6750 return self
6752 def may_be_none(self):
6753 return False
6755 def coerce_to(self, dst_type, env):
6756 if dst_type.is_pyobject:
6757 self.release_errors()
6758 if not self.type.subtype_of(dst_type):
6759 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
6760 elif dst_type.is_struct_or_union:
6761 self.type = dst_type
6762 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
6763 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
6764 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
6765 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
6766 for item in self.key_value_pairs:
6767 if isinstance(item.key, CoerceToPyTypeNode):
6768 item.key = item.key.arg
6769 if not item.key.is_string_literal:
6770 error(item.key.pos, "Invalid struct field identifier")
6771 item.key = StringNode(item.key.pos, value="<error>")
6772 else:
6773 key = str(item.key.value) # converts string literals to unicode in Py3
6774 member = dst_type.scope.lookup_here(key)
6775 if not member:
6776 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
6777 else:
6778 value = item.value
6779 if isinstance(value, CoerceToPyTypeNode):
6780 value = value.arg
6781 item.value = value.coerce_to(member.type, env)
6782 else:
6783 self.type = error_type
6784 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
6785 return self
6787 def release_errors(self):
6788 for err in self.obj_conversion_errors:
6789 report_error(err)
6790 self.obj_conversion_errors = []
6792 gil_message = "Constructing Python dict"
6794 def generate_evaluation_code(self, code):
6795 # Custom method used here because key-value
6796 # pairs are evaluated and used one at a time.
6797 code.mark_pos(self.pos)
6798 self.allocate_temp_result(code)
6799 if self.type.is_pyobject:
6800 self.release_errors()
6801 code.putln(
6802 "%s = PyDict_New(); %s" % (
6803 self.result(),
6804 code.error_goto_if_null(self.result(), self.pos)))
6805 code.put_gotref(self.py_result())
6806 for item in self.key_value_pairs:
6807 item.generate_evaluation_code(code)
6808 if self.type.is_pyobject:
6809 if self.exclude_null_values:
6810 code.putln('if (%s) {' % item.value.py_result())
6811 code.put_error_if_neg(self.pos,
6812 "PyDict_SetItem(%s, %s, %s)" % (
6813 self.result(),
6814 item.key.py_result(),
6815 item.value.py_result()))
6816 if self.exclude_null_values:
6817 code.putln('}')
6818 else:
6819 code.putln("%s.%s = %s;" % (
6820 self.result(),
6821 item.key.value,
6822 item.value.result()))
6823 item.generate_disposal_code(code)
6824 item.free_temps(code)
6826 def annotate(self, code):
6827 for item in self.key_value_pairs:
6828 item.annotate(code)
6830 class DictItemNode(ExprNode):
6831 # Represents a single item in a DictNode
6833 # key ExprNode
6834 # value ExprNode
6835 subexprs = ['key', 'value']
6837 nogil_check = None # Parent DictNode takes care of it
6839 def calculate_constant_result(self):
6840 self.constant_result = (
6841 self.key.constant_result, self.value.constant_result)
6843 def analyse_types(self, env):
6844 self.key = self.key.analyse_types(env)
6845 self.value = self.value.analyse_types(env)
6846 self.key = self.key.coerce_to_pyobject(env)
6847 self.value = self.value.coerce_to_pyobject(env)
6848 return self
6850 def generate_evaluation_code(self, code):
6851 self.key.generate_evaluation_code(code)
6852 self.value.generate_evaluation_code(code)
6854 def generate_disposal_code(self, code):
6855 self.key.generate_disposal_code(code)
6856 self.value.generate_disposal_code(code)
6858 def free_temps(self, code):
6859 self.key.free_temps(code)
6860 self.value.free_temps(code)
6862 def __iter__(self):
6863 return iter([self.key, self.value])
6866 class SortedDictKeysNode(ExprNode):
6867 # build sorted list of dict keys, e.g. for dir()
6868 subexprs = ['arg']
6870 is_temp = True
6872 def __init__(self, arg):
6873 ExprNode.__init__(self, arg.pos, arg=arg)
6874 self.type = Builtin.list_type
6876 def analyse_types(self, env):
6877 arg = self.arg.analyse_types(env)
6878 if arg.type is Builtin.dict_type:
6879 arg = arg.as_none_safe_node(
6880 "'NoneType' object is not iterable")
6881 self.arg = arg
6882 return self
6884 def may_be_none(self):
6885 return False
6887 def generate_result_code(self, code):
6888 dict_result = self.arg.py_result()
6889 if self.arg.type is Builtin.dict_type:
6890 function = 'PyDict_Keys'
6891 else:
6892 function = 'PyMapping_Keys'
6893 code.putln('%s = %s(%s); %s' % (
6894 self.result(), function, dict_result,
6895 code.error_goto_if_null(self.result(), self.pos)))
6896 code.put_gotref(self.py_result())
6897 code.put_error_if_neg(
6898 self.pos, 'PyList_Sort(%s)' % self.py_result())
6901 class ModuleNameMixin(object):
6902 def get_py_mod_name(self, code):
6903 return code.get_py_string_const(
6904 self.module_name, identifier=True)
6906 def get_py_qualified_name(self, code):
6907 return code.get_py_string_const(
6908 self.qualname, identifier=True)
6911 class ClassNode(ExprNode, ModuleNameMixin):
6912 # Helper class used in the implementation of Python
6913 # class definitions. Constructs a class object given
6914 # a name, tuple of bases and class dictionary.
6916 # name EncodedString Name of the class
6917 # bases ExprNode Base class tuple
6918 # dict ExprNode Class dict (not owned by this node)
6919 # doc ExprNode or None Doc string
6920 # module_name EncodedString Name of defining module
6922 subexprs = ['bases', 'doc']
6924 def analyse_types(self, env):
6925 self.bases = self.bases.analyse_types(env)
6926 if self.doc:
6927 self.doc = self.doc.analyse_types(env)
6928 self.doc = self.doc.coerce_to_pyobject(env)
6929 self.type = py_object_type
6930 self.is_temp = 1
6931 env.use_utility_code(UtilityCode.load_cached("CreateClass", "ObjectHandling.c"))
6932 return self
6934 def may_be_none(self):
6935 return True
6937 gil_message = "Constructing Python class"
6939 def generate_result_code(self, code):
6940 cname = code.intern_identifier(self.name)
6942 if self.doc:
6943 code.put_error_if_neg(self.pos,
6944 'PyDict_SetItem(%s, %s, %s)' % (
6945 self.dict.py_result(),
6946 code.intern_identifier(
6947 StringEncoding.EncodedString("__doc__")),
6948 self.doc.py_result()))
6949 py_mod_name = self.get_py_mod_name(code)
6950 qualname = self.get_py_qualified_name(code)
6951 code.putln(
6952 '%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s' % (
6953 self.result(),
6954 self.bases.py_result(),
6955 self.dict.py_result(),
6956 cname,
6957 qualname,
6958 py_mod_name,
6959 code.error_goto_if_null(self.result(), self.pos)))
6960 code.put_gotref(self.py_result())
6963 class Py3ClassNode(ExprNode):
6964 # Helper class used in the implementation of Python3+
6965 # class definitions. Constructs a class object given
6966 # a name, tuple of bases and class dictionary.
6968 # name EncodedString Name of the class
6969 # dict ExprNode Class dict (not owned by this node)
6970 # module_name EncodedString Name of defining module
6971 # calculate_metaclass bool should call CalculateMetaclass()
6972 # allow_py2_metaclass bool should look for Py2 metaclass
6974 subexprs = []
6976 def analyse_types(self, env):
6977 self.type = py_object_type
6978 self.is_temp = 1
6979 return self
6981 def may_be_none(self):
6982 return True
6984 gil_message = "Constructing Python class"
6986 def generate_result_code(self, code):
6987 code.globalstate.use_utility_code(UtilityCode.load_cached("Py3ClassCreate", "ObjectHandling.c"))
6988 cname = code.intern_identifier(self.name)
6989 if self.mkw:
6990 mkw = self.mkw.py_result()
6991 else:
6992 mkw = 'NULL'
6993 if self.metaclass:
6994 metaclass = self.metaclass.result()
6995 else:
6996 metaclass = "((PyObject*)&__Pyx_DefaultClassType)"
6997 code.putln(
6998 '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s, %d, %d); %s' % (
6999 self.result(),
7000 metaclass,
7001 cname,
7002 self.bases.py_result(),
7003 self.dict.py_result(),
7004 mkw,
7005 self.calculate_metaclass,
7006 self.allow_py2_metaclass,
7007 code.error_goto_if_null(self.result(), self.pos)))
7008 code.put_gotref(self.py_result())
7010 class KeywordArgsNode(ExprNode):
7011 # Helper class for keyword arguments.
7013 # starstar_arg DictNode
7014 # keyword_args [DictItemNode]
7016 subexprs = ['starstar_arg', 'keyword_args']
7017 is_temp = 1
7018 type = dict_type
7020 def calculate_constant_result(self):
7021 result = dict(self.starstar_arg.constant_result)
7022 for item in self.keyword_args:
7023 key, value = item.constant_result
7024 if key in result:
7025 raise ValueError("duplicate keyword argument found: %s" % key)
7026 result[key] = value
7027 self.constant_result = result
7029 def compile_time_value(self, denv):
7030 result = self.starstar_arg.compile_time_value(denv)
7031 pairs = [ (item.key.compile_time_value(denv), item.value.compile_time_value(denv))
7032 for item in self.keyword_args ]
7033 try:
7034 result = dict(result)
7035 for key, value in pairs:
7036 if key in result:
7037 raise ValueError("duplicate keyword argument found: %s" % key)
7038 result[key] = value
7039 except Exception, e:
7040 self.compile_time_value_error(e)
7041 return result
7043 def type_dependencies(self, env):
7044 return ()
7046 def infer_type(self, env):
7047 return dict_type
7049 def analyse_types(self, env):
7050 arg = self.starstar_arg.analyse_types(env)
7051 arg = arg.coerce_to_pyobject(env)
7052 self.starstar_arg = arg.as_none_safe_node(
7053 # FIXME: CPython's error message starts with the runtime function name
7054 'argument after ** must be a mapping, not NoneType')
7055 self.keyword_args = [ item.analyse_types(env)
7056 for item in self.keyword_args ]
7057 return self
7059 def may_be_none(self):
7060 return False
7062 gil_message = "Constructing Python dict"
7064 def generate_evaluation_code(self, code):
7065 code.mark_pos(self.pos)
7066 self.allocate_temp_result(code)
7067 self.starstar_arg.generate_evaluation_code(code)
7068 if self.starstar_arg.type is not Builtin.dict_type:
7069 # CPython supports calling functions with non-dicts, so do we
7070 code.putln('if (likely(PyDict_Check(%s))) {' %
7071 self.starstar_arg.py_result())
7072 if self.keyword_args:
7073 code.putln(
7074 "%s = PyDict_Copy(%s); %s" % (
7075 self.result(),
7076 self.starstar_arg.py_result(),
7077 code.error_goto_if_null(self.result(), self.pos)))
7078 code.put_gotref(self.py_result())
7079 else:
7080 code.putln("%s = %s;" % (
7081 self.result(),
7082 self.starstar_arg.py_result()))
7083 code.put_incref(self.result(), py_object_type)
7084 if self.starstar_arg.type is not Builtin.dict_type:
7085 code.putln('} else {')
7086 code.putln(
7087 "%s = PyObject_CallFunctionObjArgs("
7088 "(PyObject*)&PyDict_Type, %s, NULL); %s" % (
7089 self.result(),
7090 self.starstar_arg.py_result(),
7091 code.error_goto_if_null(self.result(), self.pos)))
7092 code.put_gotref(self.py_result())
7093 code.putln('}')
7094 self.starstar_arg.generate_disposal_code(code)
7095 self.starstar_arg.free_temps(code)
7097 if not self.keyword_args:
7098 return
7100 code.globalstate.use_utility_code(
7101 UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c"))
7102 for item in self.keyword_args:
7103 item.generate_evaluation_code(code)
7104 code.putln("if (unlikely(PyDict_GetItem(%s, %s))) {" % (
7105 self.result(),
7106 item.key.py_result()))
7107 # FIXME: find out function name at runtime!
7108 code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % (
7109 item.key.py_result(),
7110 code.error_goto(self.pos)))
7111 code.putln("}")
7112 code.put_error_if_neg(self.pos,
7113 "PyDict_SetItem(%s, %s, %s)" % (
7114 self.result(),
7115 item.key.py_result(),
7116 item.value.py_result()))
7117 item.generate_disposal_code(code)
7118 item.free_temps(code)
7120 def annotate(self, code):
7121 self.starstar_arg.annotate(code)
7122 for item in self.keyword_args:
7123 item.annotate(code)
7125 class PyClassMetaclassNode(ExprNode):
7126 # Helper class holds Python3 metaclass object
7128 # bases ExprNode Base class tuple (not owned by this node)
7129 # mkw ExprNode Class keyword arguments (not owned by this node)
7131 subexprs = []
7133 def analyse_types(self, env):
7134 self.type = py_object_type
7135 self.is_temp = True
7136 return self
7138 def may_be_none(self):
7139 return True
7141 def generate_result_code(self, code):
7142 if self.mkw:
7143 code.globalstate.use_utility_code(
7144 UtilityCode.load_cached("Py3MetaclassGet", "ObjectHandling.c"))
7145 call = "__Pyx_Py3MetaclassGet(%s, %s)" % (
7146 self.bases.result(),
7147 self.mkw.result())
7148 else:
7149 code.globalstate.use_utility_code(
7150 UtilityCode.load_cached("CalculateMetaclass", "ObjectHandling.c"))
7151 call = "__Pyx_CalculateMetaclass(NULL, %s)" % (
7152 self.bases.result())
7153 code.putln(
7154 "%s = %s; %s" % (
7155 self.result(), call,
7156 code.error_goto_if_null(self.result(), self.pos)))
7157 code.put_gotref(self.py_result())
7159 class PyClassNamespaceNode(ExprNode, ModuleNameMixin):
7160 # Helper class holds Python3 namespace object
7162 # All this are not owned by this node
7163 # metaclass ExprNode Metaclass object
7164 # bases ExprNode Base class tuple
7165 # mkw ExprNode Class keyword arguments
7166 # doc ExprNode or None Doc string (owned)
7168 subexprs = ['doc']
7170 def analyse_types(self, env):
7171 if self.doc:
7172 self.doc = self.doc.analyse_types(env)
7173 self.doc = self.doc.coerce_to_pyobject(env)
7174 self.type = py_object_type
7175 self.is_temp = 1
7176 return self
7178 def may_be_none(self):
7179 return True
7181 def generate_result_code(self, code):
7182 cname = code.intern_identifier(self.name)
7183 py_mod_name = self.get_py_mod_name(code)
7184 qualname = self.get_py_qualified_name(code)
7185 if self.doc:
7186 doc_code = self.doc.result()
7187 else:
7188 doc_code = '(PyObject *) NULL'
7189 if self.mkw:
7190 mkw = self.mkw.py_result()
7191 else:
7192 mkw = '(PyObject *) NULL'
7193 if self.metaclass:
7194 metaclass = self.metaclass.result()
7195 else:
7196 metaclass = "(PyObject *) NULL"
7197 code.putln(
7198 "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s" % (
7199 self.result(),
7200 metaclass,
7201 self.bases.result(),
7202 cname,
7203 qualname,
7204 mkw,
7205 py_mod_name,
7206 doc_code,
7207 code.error_goto_if_null(self.result(), self.pos)))
7208 code.put_gotref(self.py_result())
7211 class ClassCellInjectorNode(ExprNode):
7212 # Initialize CyFunction.func_classobj
7213 is_temp = True
7214 type = py_object_type
7215 subexprs = []
7216 is_active = False
7218 def analyse_expressions(self, env):
7219 if self.is_active:
7220 env.use_utility_code(
7221 UtilityCode.load_cached("CyFunctionClassCell", "CythonFunction.c"))
7222 return self
7224 def generate_evaluation_code(self, code):
7225 if self.is_active:
7226 self.allocate_temp_result(code)
7227 code.putln(
7228 '%s = PyList_New(0); %s' % (
7229 self.result(),
7230 code.error_goto_if_null(self.result(), self.pos)))
7231 code.put_gotref(self.result())
7233 def generate_injection_code(self, code, classobj_cname):
7234 if self.is_active:
7235 code.putln('__Pyx_CyFunction_InitClassCell(%s, %s);' % (
7236 self.result(), classobj_cname))
7239 class ClassCellNode(ExprNode):
7240 # Class Cell for noargs super()
7241 subexprs = []
7242 is_temp = True
7243 is_generator = False
7244 type = py_object_type
7246 def analyse_types(self, env):
7247 return self
7249 def generate_result_code(self, code):
7250 if not self.is_generator:
7251 code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % (
7252 self.result(),
7253 Naming.self_cname))
7254 else:
7255 code.putln('%s = %s->classobj;' % (
7256 self.result(), Naming.generator_cname))
7257 code.putln(
7258 'if (!%s) { PyErr_SetString(PyExc_SystemError, '
7259 '"super(): empty __class__ cell"); %s }' % (
7260 self.result(),
7261 code.error_goto(self.pos)))
7262 code.put_incref(self.result(), py_object_type)
7265 class BoundMethodNode(ExprNode):
7266 # Helper class used in the implementation of Python
7267 # class definitions. Constructs an bound method
7268 # object from a class and a function.
7270 # function ExprNode Function object
7271 # self_object ExprNode self object
7273 subexprs = ['function']
7275 def analyse_types(self, env):
7276 self.function = self.function.analyse_types(env)
7277 self.type = py_object_type
7278 self.is_temp = 1
7279 return self
7281 gil_message = "Constructing a bound method"
7283 def generate_result_code(self, code):
7284 code.putln(
7285 "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % (
7286 self.result(),
7287 self.function.py_result(),
7288 self.self_object.py_result(),
7289 self.self_object.py_result(),
7290 code.error_goto_if_null(self.result(), self.pos)))
7291 code.put_gotref(self.py_result())
7293 class UnboundMethodNode(ExprNode):
7294 # Helper class used in the implementation of Python
7295 # class definitions. Constructs an unbound method
7296 # object from a class and a function.
7298 # function ExprNode Function object
7300 type = py_object_type
7301 is_temp = 1
7303 subexprs = ['function']
7305 def analyse_types(self, env):
7306 self.function = self.function.analyse_types(env)
7307 return self
7309 def may_be_none(self):
7310 return False
7312 gil_message = "Constructing an unbound method"
7314 def generate_result_code(self, code):
7315 class_cname = code.pyclass_stack[-1].classobj.result()
7316 code.putln(
7317 "%s = PyMethod_New(%s, 0, %s); %s" % (
7318 self.result(),
7319 self.function.py_result(),
7320 class_cname,
7321 code.error_goto_if_null(self.result(), self.pos)))
7322 code.put_gotref(self.py_result())
7325 class PyCFunctionNode(ExprNode, ModuleNameMixin):
7326 # Helper class used in the implementation of Python
7327 # functions. Constructs a PyCFunction object
7328 # from a PyMethodDef struct.
7330 # pymethdef_cname string PyMethodDef structure
7331 # self_object ExprNode or None
7332 # binding bool
7333 # def_node DefNode the Python function node
7334 # module_name EncodedString Name of defining module
7335 # code_object CodeObjectNode the PyCodeObject creator node
7337 subexprs = ['code_object', 'defaults_tuple', 'defaults_kwdict',
7338 'annotations_dict']
7340 self_object = None
7341 code_object = None
7342 binding = False
7343 def_node = None
7344 defaults = None
7345 defaults_struct = None
7346 defaults_pyobjects = 0
7347 defaults_tuple = None
7348 defaults_kwdict = None
7349 annotations_dict = None
7351 type = py_object_type
7352 is_temp = 1
7354 specialized_cpdefs = None
7355 is_specialization = False
7357 @classmethod
7358 def from_defnode(cls, node, binding):
7359 return cls(node.pos,
7360 def_node=node,
7361 pymethdef_cname=node.entry.pymethdef_cname,
7362 binding=binding or node.specialized_cpdefs,
7363 specialized_cpdefs=node.specialized_cpdefs,
7364 code_object=CodeObjectNode(node))
7366 def analyse_types(self, env):
7367 if self.binding:
7368 self.analyse_default_args(env)
7369 return self
7371 def analyse_default_args(self, env):
7373 Handle non-literal function's default arguments.
7375 nonliteral_objects = []
7376 nonliteral_other = []
7377 default_args = []
7378 default_kwargs = []
7379 annotations = []
7380 for arg in self.def_node.args:
7381 if arg.default:
7382 if not arg.default.is_literal:
7383 arg.is_dynamic = True
7384 if arg.type.is_pyobject:
7385 nonliteral_objects.append(arg)
7386 else:
7387 nonliteral_other.append(arg)
7388 else:
7389 arg.default = DefaultLiteralArgNode(arg.pos, arg.default)
7390 if arg.kw_only:
7391 default_kwargs.append(arg)
7392 else:
7393 default_args.append(arg)
7394 if arg.annotation:
7395 arg.annotation = arg.annotation.analyse_types(env)
7396 if not arg.annotation.type.is_pyobject:
7397 arg.annotation = arg.annotation.coerce_to_pyobject(env)
7398 annotations.append((arg.pos, arg.name, arg.annotation))
7399 if self.def_node.return_type_annotation:
7400 annotations.append((self.def_node.return_type_annotation.pos,
7401 StringEncoding.EncodedString("return"),
7402 self.def_node.return_type_annotation))
7404 if nonliteral_objects or nonliteral_other:
7405 module_scope = env.global_scope()
7406 cname = module_scope.next_id(Naming.defaults_struct_prefix)
7407 scope = Symtab.StructOrUnionScope(cname)
7408 self.defaults = []
7409 for arg in nonliteral_objects:
7410 entry = scope.declare_var(arg.name, arg.type, None,
7411 Naming.arg_prefix + arg.name,
7412 allow_pyobject=True)
7413 self.defaults.append((arg, entry))
7414 for arg in nonliteral_other:
7415 entry = scope.declare_var(arg.name, arg.type, None,
7416 Naming.arg_prefix + arg.name,
7417 allow_pyobject=False)
7418 self.defaults.append((arg, entry))
7419 entry = module_scope.declare_struct_or_union(
7420 None, 'struct', scope, 1, None, cname=cname)
7421 self.defaults_struct = scope
7422 self.defaults_pyobjects = len(nonliteral_objects)
7423 for arg, entry in self.defaults:
7424 arg.default_value = '%s->%s' % (
7425 Naming.dynamic_args_cname, entry.cname)
7426 self.def_node.defaults_struct = self.defaults_struct.name
7428 if default_args or default_kwargs:
7429 if self.defaults_struct is None:
7430 if default_args:
7431 defaults_tuple = TupleNode(self.pos, args=[
7432 arg.default for arg in default_args])
7433 self.defaults_tuple = defaults_tuple.analyse_types(env)
7434 if default_kwargs:
7435 defaults_kwdict = DictNode(self.pos, key_value_pairs=[
7436 DictItemNode(
7437 arg.pos,
7438 key=IdentifierStringNode(arg.pos, value=arg.name),
7439 value=arg.default)
7440 for arg in default_kwargs])
7441 self.defaults_kwdict = defaults_kwdict.analyse_types(env)
7442 else:
7443 if default_args:
7444 defaults_tuple = DefaultsTupleNode(
7445 self.pos, default_args, self.defaults_struct)
7446 else:
7447 defaults_tuple = NoneNode(self.pos)
7448 if default_kwargs:
7449 defaults_kwdict = DefaultsKwDictNode(
7450 self.pos, default_kwargs, self.defaults_struct)
7451 else:
7452 defaults_kwdict = NoneNode(self.pos)
7454 defaults_getter = Nodes.DefNode(
7455 self.pos, args=[], star_arg=None, starstar_arg=None,
7456 body=Nodes.ReturnStatNode(
7457 self.pos, return_type=py_object_type,
7458 value=TupleNode(
7459 self.pos, args=[defaults_tuple, defaults_kwdict])),
7460 decorators=None,
7461 name=StringEncoding.EncodedString("__defaults__"))
7462 defaults_getter.analyse_declarations(env)
7463 defaults_getter = defaults_getter.analyse_expressions(env)
7464 defaults_getter.body = defaults_getter.body.analyse_expressions(
7465 defaults_getter.local_scope)
7466 defaults_getter.py_wrapper_required = False
7467 defaults_getter.pymethdef_required = False
7468 self.def_node.defaults_getter = defaults_getter
7469 if annotations:
7470 annotations_dict = DictNode(self.pos, key_value_pairs=[
7471 DictItemNode(
7472 pos, key=IdentifierStringNode(pos, value=name),
7473 value=value)
7474 for pos, name, value in annotations])
7475 self.annotations_dict = annotations_dict.analyse_types(env)
7477 def may_be_none(self):
7478 return False
7480 gil_message = "Constructing Python function"
7482 def self_result_code(self):
7483 if self.self_object is None:
7484 self_result = "NULL"
7485 else:
7486 self_result = self.self_object.py_result()
7487 return self_result
7489 def generate_result_code(self, code):
7490 if self.binding:
7491 self.generate_cyfunction_code(code)
7492 else:
7493 self.generate_pycfunction_code(code)
7495 def generate_pycfunction_code(self, code):
7496 py_mod_name = self.get_py_mod_name(code)
7497 code.putln(
7498 '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % (
7499 self.result(),
7500 self.pymethdef_cname,
7501 self.self_result_code(),
7502 py_mod_name,
7503 code.error_goto_if_null(self.result(), self.pos)))
7505 code.put_gotref(self.py_result())
7507 def generate_cyfunction_code(self, code):
7508 if self.specialized_cpdefs:
7509 def_node = self.specialized_cpdefs[0]
7510 else:
7511 def_node = self.def_node
7513 if self.specialized_cpdefs or self.is_specialization:
7514 code.globalstate.use_utility_code(
7515 UtilityCode.load_cached("FusedFunction", "CythonFunction.c"))
7516 constructor = "__pyx_FusedFunction_NewEx"
7517 else:
7518 code.globalstate.use_utility_code(
7519 UtilityCode.load_cached("CythonFunction", "CythonFunction.c"))
7520 constructor = "__Pyx_CyFunction_NewEx"
7522 if self.code_object:
7523 code_object_result = self.code_object.py_result()
7524 else:
7525 code_object_result = 'NULL'
7527 flags = []
7528 if def_node.is_staticmethod:
7529 flags.append('__Pyx_CYFUNCTION_STATICMETHOD')
7530 elif def_node.is_classmethod:
7531 flags.append('__Pyx_CYFUNCTION_CLASSMETHOD')
7533 if def_node.local_scope.parent_scope.is_c_class_scope:
7534 flags.append('__Pyx_CYFUNCTION_CCLASS')
7536 if flags:
7537 flags = ' | '.join(flags)
7538 else:
7539 flags = '0'
7541 code.putln(
7542 '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % (
7543 self.result(),
7544 constructor,
7545 self.pymethdef_cname,
7546 flags,
7547 self.get_py_qualified_name(code),
7548 self.self_result_code(),
7549 self.get_py_mod_name(code),
7550 "PyModule_GetDict(%s)" % Naming.module_cname,
7551 code_object_result,
7552 code.error_goto_if_null(self.result(), self.pos)))
7554 code.put_gotref(self.py_result())
7556 if def_node.requires_classobj:
7557 assert code.pyclass_stack, "pyclass_stack is empty"
7558 class_node = code.pyclass_stack[-1]
7559 code.put_incref(self.py_result(), py_object_type)
7560 code.putln(
7561 'PyList_Append(%s, %s);' % (
7562 class_node.class_cell.result(),
7563 self.result()))
7564 code.put_giveref(self.py_result())
7566 if self.defaults:
7567 code.putln(
7568 'if (!__Pyx_CyFunction_InitDefaults(%s, sizeof(%s), %d)) %s' % (
7569 self.result(), self.defaults_struct.name,
7570 self.defaults_pyobjects, code.error_goto(self.pos)))
7571 defaults = '__Pyx_CyFunction_Defaults(%s, %s)' % (
7572 self.defaults_struct.name, self.result())
7573 for arg, entry in self.defaults:
7574 arg.generate_assignment_code(code, target='%s->%s' % (
7575 defaults, entry.cname))
7577 if self.defaults_tuple:
7578 code.putln('__Pyx_CyFunction_SetDefaultsTuple(%s, %s);' % (
7579 self.result(), self.defaults_tuple.py_result()))
7580 if self.defaults_kwdict:
7581 code.putln('__Pyx_CyFunction_SetDefaultsKwDict(%s, %s);' % (
7582 self.result(), self.defaults_kwdict.py_result()))
7583 if def_node.defaults_getter:
7584 code.putln('__Pyx_CyFunction_SetDefaultsGetter(%s, %s);' % (
7585 self.result(), def_node.defaults_getter.entry.pyfunc_cname))
7586 if self.annotations_dict:
7587 code.putln('__Pyx_CyFunction_SetAnnotationsDict(%s, %s);' % (
7588 self.result(), self.annotations_dict.py_result()))
7591 class InnerFunctionNode(PyCFunctionNode):
7592 # Special PyCFunctionNode that depends on a closure class
7595 binding = True
7596 needs_self_code = True
7598 def self_result_code(self):
7599 if self.needs_self_code:
7600 return "((PyObject*)%s)" % Naming.cur_scope_cname
7601 return "NULL"
7604 class CodeObjectNode(ExprNode):
7605 # Create a PyCodeObject for a CyFunction instance.
7607 # def_node DefNode the Python function node
7608 # varnames TupleNode a tuple with all local variable names
7610 subexprs = ['varnames']
7611 is_temp = False
7613 def __init__(self, def_node):
7614 ExprNode.__init__(self, def_node.pos, def_node=def_node)
7615 args = list(def_node.args)
7616 # if we have args/kwargs, then the first two in var_entries are those
7617 local_vars = [arg for arg in def_node.local_scope.var_entries if arg.name]
7618 self.varnames = TupleNode(
7619 def_node.pos,
7620 args=[IdentifierStringNode(arg.pos, value=arg.name)
7621 for arg in args + local_vars],
7622 is_temp=0,
7623 is_literal=1)
7625 def may_be_none(self):
7626 return False
7628 def calculate_result_code(self):
7629 return self.result_code
7631 def generate_result_code(self, code):
7632 self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2)
7634 code = code.get_cached_constants_writer()
7635 code.mark_pos(self.pos)
7636 func = self.def_node
7637 func_name = code.get_py_string_const(
7638 func.name, identifier=True, is_str=False, unicode_value=func.name)
7639 # FIXME: better way to get the module file path at module init time? Encoding to use?
7640 file_path = StringEncoding.BytesLiteral(func.pos[0].get_filenametable_entry().encode('utf8'))
7641 file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True)
7643 flags = []
7644 if self.def_node.star_arg:
7645 flags.append('CO_VARARGS')
7646 if self.def_node.starstar_arg:
7647 flags.append('CO_VARKEYWORDS')
7649 code.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s); %s" % (
7650 self.result_code,
7651 len(func.args) - func.num_kwonly_args, # argcount
7652 func.num_kwonly_args, # kwonlyargcount (Py3 only)
7653 len(self.varnames.args), # nlocals
7654 '|'.join(flags) or '0', # flags
7655 Naming.empty_bytes, # code
7656 Naming.empty_tuple, # consts
7657 Naming.empty_tuple, # names (FIXME)
7658 self.varnames.result(), # varnames
7659 Naming.empty_tuple, # freevars (FIXME)
7660 Naming.empty_tuple, # cellvars (FIXME)
7661 file_path_const, # filename
7662 func_name, # name
7663 self.pos[1], # firstlineno
7664 Naming.empty_bytes, # lnotab
7665 code.error_goto_if_null(self.result_code, self.pos),
7669 class DefaultLiteralArgNode(ExprNode):
7670 # CyFunction's literal argument default value
7672 # Evaluate literal only once.
7674 subexprs = []
7675 is_literal = True
7676 is_temp = False
7678 def __init__(self, pos, arg):
7679 super(DefaultLiteralArgNode, self).__init__(pos)
7680 self.arg = arg
7681 self.type = self.arg.type
7682 self.evaluated = False
7684 def analyse_types(self, env):
7685 return self
7687 def generate_result_code(self, code):
7688 pass
7690 def generate_evaluation_code(self, code):
7691 if not self.evaluated:
7692 self.arg.generate_evaluation_code(code)
7693 self.evaluated = True
7695 def result(self):
7696 return self.type.cast_code(self.arg.result())
7699 class DefaultNonLiteralArgNode(ExprNode):
7700 # CyFunction's non-literal argument default value
7702 subexprs = []
7704 def __init__(self, pos, arg, defaults_struct):
7705 super(DefaultNonLiteralArgNode, self).__init__(pos)
7706 self.arg = arg
7707 self.defaults_struct = defaults_struct
7709 def analyse_types(self, env):
7710 self.type = self.arg.type
7711 self.is_temp = False
7712 return self
7714 def generate_result_code(self, code):
7715 pass
7717 def result(self):
7718 return '__Pyx_CyFunction_Defaults(%s, %s)->%s' % (
7719 self.defaults_struct.name, Naming.self_cname,
7720 self.defaults_struct.lookup(self.arg.name).cname)
7723 class DefaultsTupleNode(TupleNode):
7724 # CyFunction's __defaults__ tuple
7726 def __init__(self, pos, defaults, defaults_struct):
7727 args = []
7728 for arg in defaults:
7729 if not arg.default.is_literal:
7730 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct)
7731 else:
7732 arg = arg.default
7733 args.append(arg)
7734 super(DefaultsTupleNode, self).__init__(pos, args=args)
7737 class DefaultsKwDictNode(DictNode):
7738 # CyFunction's __kwdefaults__ dict
7740 def __init__(self, pos, defaults, defaults_struct):
7741 items = []
7742 for arg in defaults:
7743 name = IdentifierStringNode(arg.pos, value=arg.name)
7744 if not arg.default.is_literal:
7745 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct)
7746 else:
7747 arg = arg.default
7748 items.append(DictItemNode(arg.pos, key=name, value=arg))
7749 super(DefaultsKwDictNode, self).__init__(pos, key_value_pairs=items)
7752 class LambdaNode(InnerFunctionNode):
7753 # Lambda expression node (only used as a function reference)
7755 # args [CArgDeclNode] formal arguments
7756 # star_arg PyArgDeclNode or None * argument
7757 # starstar_arg PyArgDeclNode or None ** argument
7758 # lambda_name string a module-globally unique lambda name
7759 # result_expr ExprNode
7760 # def_node DefNode the underlying function 'def' node
7762 child_attrs = ['def_node']
7764 name = StringEncoding.EncodedString('<lambda>')
7766 def analyse_declarations(self, env):
7767 self.def_node.no_assignment_synthesis = True
7768 self.def_node.pymethdef_required = True
7769 self.def_node.analyse_declarations(env)
7770 self.def_node.is_cyfunction = True
7771 self.pymethdef_cname = self.def_node.entry.pymethdef_cname
7772 env.add_lambda_def(self.def_node)
7774 def analyse_types(self, env):
7775 self.def_node = self.def_node.analyse_expressions(env)
7776 return super(LambdaNode, self).analyse_types(env)
7778 def generate_result_code(self, code):
7779 self.def_node.generate_execution_code(code)
7780 super(LambdaNode, self).generate_result_code(code)
7783 class GeneratorExpressionNode(LambdaNode):
7784 # A generator expression, e.g. (i for i in range(10))
7786 # Result is a generator.
7788 # loop ForStatNode the for-loop, containing a YieldExprNode
7789 # def_node DefNode the underlying generator 'def' node
7791 name = StringEncoding.EncodedString('genexpr')
7792 binding = False
7794 def analyse_declarations(self, env):
7795 super(GeneratorExpressionNode, self).analyse_declarations(env)
7796 # No pymethdef required
7797 self.def_node.pymethdef_required = False
7798 self.def_node.py_wrapper_required = False
7799 self.def_node.is_cyfunction = False
7800 # Force genexpr signature
7801 self.def_node.entry.signature = TypeSlots.pyfunction_noargs
7803 def generate_result_code(self, code):
7804 code.putln(
7805 '%s = %s(%s); %s' % (
7806 self.result(),
7807 self.def_node.entry.pyfunc_cname,
7808 self.self_result_code(),
7809 code.error_goto_if_null(self.result(), self.pos)))
7810 code.put_gotref(self.py_result())
7813 class YieldExprNode(ExprNode):
7814 # Yield expression node
7816 # arg ExprNode the value to return from the generator
7817 # label_num integer yield label number
7818 # is_yield_from boolean is a YieldFromExprNode to delegate to another generator
7820 subexprs = ['arg']
7821 type = py_object_type
7822 label_num = 0
7823 is_yield_from = False
7825 def analyse_types(self, env):
7826 if not self.label_num:
7827 error(self.pos, "'yield' not supported here")
7828 self.is_temp = 1
7829 if self.arg is not None:
7830 self.arg = self.arg.analyse_types(env)
7831 if not self.arg.type.is_pyobject:
7832 self.coerce_yield_argument(env)
7833 return self
7835 def coerce_yield_argument(self, env):
7836 self.arg = self.arg.coerce_to_pyobject(env)
7838 def generate_evaluation_code(self, code):
7839 if self.arg:
7840 self.arg.generate_evaluation_code(code)
7841 self.arg.make_owned_reference(code)
7842 code.putln(
7843 "%s = %s;" % (
7844 Naming.retval_cname,
7845 self.arg.result_as(py_object_type)))
7846 self.arg.generate_post_assignment_code(code)
7847 self.arg.free_temps(code)
7848 else:
7849 code.put_init_to_py_none(Naming.retval_cname, py_object_type)
7850 self.generate_yield_code(code)
7852 def generate_yield_code(self, code):
7854 Generate the code to return the argument in 'Naming.retval_cname'
7855 and to continue at the yield label.
7857 label_num, label_name = code.new_yield_label()
7858 code.use_label(label_name)
7860 saved = []
7861 code.funcstate.closure_temps.reset()
7862 for cname, type, manage_ref in code.funcstate.temps_in_use():
7863 save_cname = code.funcstate.closure_temps.allocate_temp(type)
7864 saved.append((cname, save_cname, type))
7865 if type.is_pyobject:
7866 code.put_xgiveref(cname)
7867 code.putln('%s->%s = %s;' % (Naming.cur_scope_cname, save_cname, cname))
7869 code.put_xgiveref(Naming.retval_cname)
7870 code.put_finish_refcount_context()
7871 code.putln("/* return from generator, yielding value */")
7872 code.putln("%s->resume_label = %d;" % (
7873 Naming.generator_cname, label_num))
7874 code.putln("return %s;" % Naming.retval_cname)
7876 code.put_label(label_name)
7877 for cname, save_cname, type in saved:
7878 code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname))
7879 if type.is_pyobject:
7880 code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname))
7881 code.put_xgotref(cname)
7882 code.putln(code.error_goto_if_null(Naming.sent_value_cname, self.pos))
7883 if self.result_is_used:
7884 self.allocate_temp_result(code)
7885 code.put('%s = %s; ' % (self.result(), Naming.sent_value_cname))
7886 code.put_incref(self.result(), py_object_type)
7889 class YieldFromExprNode(YieldExprNode):
7890 # "yield from GEN" expression
7891 is_yield_from = True
7893 def coerce_yield_argument(self, env):
7894 if not self.arg.type.is_string:
7895 # FIXME: support C arrays and C++ iterators?
7896 error(self.pos, "yielding from non-Python object not supported")
7897 self.arg = self.arg.coerce_to_pyobject(env)
7899 def generate_evaluation_code(self, code):
7900 code.globalstate.use_utility_code(UtilityCode.load_cached("YieldFrom", "Generator.c"))
7902 self.arg.generate_evaluation_code(code)
7903 code.putln("%s = __Pyx_Generator_Yield_From(%s, %s);" % (
7904 Naming.retval_cname,
7905 Naming.generator_cname,
7906 self.arg.result_as(py_object_type)))
7907 self.arg.generate_disposal_code(code)
7908 self.arg.free_temps(code)
7909 code.put_xgotref(Naming.retval_cname)
7911 code.putln("if (likely(%s)) {" % Naming.retval_cname)
7912 self.generate_yield_code(code)
7913 code.putln("} else {")
7914 # either error or sub-generator has normally terminated: return value => node result
7915 if self.result_is_used:
7916 # YieldExprNode has allocated the result temp for us
7917 code.putln("%s = NULL;" % self.result())
7918 code.putln("if (unlikely(__Pyx_PyGen_FetchStopIterationValue(&%s) < 0)) %s" % (
7919 self.result(),
7920 code.error_goto(self.pos)))
7921 code.put_gotref(self.result())
7922 else:
7923 code.putln("PyObject* exc_type = PyErr_Occurred();")
7924 code.putln("if (exc_type) {")
7925 code.putln("if (likely(exc_type == PyExc_StopIteration ||"
7926 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();")
7927 code.putln("else %s" % code.error_goto(self.pos))
7928 code.putln("}")
7929 code.putln("}")
7931 class GlobalsExprNode(AtomicExprNode):
7932 type = dict_type
7933 is_temp = 1
7935 def analyse_types(self, env):
7936 env.use_utility_code(Builtin.globals_utility_code)
7937 return self
7939 gil_message = "Constructing globals dict"
7941 def may_be_none(self):
7942 return False
7944 def generate_result_code(self, code):
7945 code.putln('%s = __Pyx_Globals(); %s' % (
7946 self.result(),
7947 code.error_goto_if_null(self.result(), self.pos)))
7948 code.put_gotref(self.result())
7951 class LocalsDictItemNode(DictItemNode):
7952 def analyse_types(self, env):
7953 self.key = self.key.analyse_types(env)
7954 self.value = self.value.analyse_types(env)
7955 self.key = self.key.coerce_to_pyobject(env)
7956 if self.value.type.can_coerce_to_pyobject(env):
7957 self.value = self.value.coerce_to_pyobject(env)
7958 else:
7959 self.value = None
7960 return self
7963 class FuncLocalsExprNode(DictNode):
7964 def __init__(self, pos, env):
7965 local_vars = sorted([
7966 entry.name for entry in env.entries.values() if entry.name])
7967 items = [LocalsDictItemNode(
7968 pos, key=IdentifierStringNode(pos, value=var),
7969 value=NameNode(pos, name=var, allow_null=True))
7970 for var in local_vars]
7971 DictNode.__init__(self, pos, key_value_pairs=items,
7972 exclude_null_values=True)
7974 def analyse_types(self, env):
7975 node = super(FuncLocalsExprNode, self).analyse_types(env)
7976 node.key_value_pairs = [ i for i in node.key_value_pairs
7977 if i.value is not None ]
7978 return node
7981 class PyClassLocalsExprNode(AtomicExprNode):
7982 def __init__(self, pos, pyclass_dict):
7983 AtomicExprNode.__init__(self, pos)
7984 self.pyclass_dict = pyclass_dict
7986 def analyse_types(self, env):
7987 self.type = self.pyclass_dict.type
7988 self.is_temp = False
7989 return self
7991 def may_be_none(self):
7992 return False
7994 def result(self):
7995 return self.pyclass_dict.result()
7997 def generate_result_code(self, code):
7998 pass
8001 def LocalsExprNode(pos, scope_node, env):
8002 if env.is_module_scope:
8003 return GlobalsExprNode(pos)
8004 if env.is_py_class_scope:
8005 return PyClassLocalsExprNode(pos, scope_node.dict)
8006 return FuncLocalsExprNode(pos, env)
8009 #-------------------------------------------------------------------
8011 # Unary operator nodes
8013 #-------------------------------------------------------------------
8015 compile_time_unary_operators = {
8016 'not': operator.not_,
8017 '~': operator.inv,
8018 '-': operator.neg,
8019 '+': operator.pos,
8022 class UnopNode(ExprNode):
8023 # operator string
8024 # operand ExprNode
8026 # Processing during analyse_expressions phase:
8028 # analyse_c_operation
8029 # Called when the operand is not a pyobject.
8030 # - Check operand type and coerce if needed.
8031 # - Determine result type and result code fragment.
8032 # - Allocate temporary for result if needed.
8034 subexprs = ['operand']
8035 infix = True
8037 def calculate_constant_result(self):
8038 func = compile_time_unary_operators[self.operator]
8039 self.constant_result = func(self.operand.constant_result)
8041 def compile_time_value(self, denv):
8042 func = compile_time_unary_operators.get(self.operator)
8043 if not func:
8044 error(self.pos,
8045 "Unary '%s' not supported in compile-time expression"
8046 % self.operator)
8047 operand = self.operand.compile_time_value(denv)
8048 try:
8049 return func(operand)
8050 except Exception, e:
8051 self.compile_time_value_error(e)
8053 def infer_type(self, env):
8054 operand_type = self.operand.infer_type(env)
8055 if operand_type.is_cpp_class or operand_type.is_ptr:
8056 cpp_type = operand_type.find_cpp_operation_type(self.operator)
8057 if cpp_type is not None:
8058 return cpp_type
8059 return self.infer_unop_type(env, operand_type)
8061 def infer_unop_type(self, env, operand_type):
8062 if operand_type.is_pyobject:
8063 return py_object_type
8064 else:
8065 return operand_type
8067 def may_be_none(self):
8068 if self.operand.type and self.operand.type.is_builtin_type:
8069 if self.operand.type is not type_type:
8070 return False
8071 return ExprNode.may_be_none(self)
8073 def analyse_types(self, env):
8074 self.operand = self.operand.analyse_types(env)
8075 if self.is_py_operation():
8076 self.coerce_operand_to_pyobject(env)
8077 self.type = py_object_type
8078 self.is_temp = 1
8079 elif self.is_cpp_operation():
8080 self.analyse_cpp_operation(env)
8081 else:
8082 self.analyse_c_operation(env)
8083 return self
8085 def check_const(self):
8086 return self.operand.check_const()
8088 def is_py_operation(self):
8089 return self.operand.type.is_pyobject
8091 def nogil_check(self, env):
8092 if self.is_py_operation():
8093 self.gil_error()
8095 def is_cpp_operation(self):
8096 type = self.operand.type
8097 return type.is_cpp_class
8099 def coerce_operand_to_pyobject(self, env):
8100 self.operand = self.operand.coerce_to_pyobject(env)
8102 def generate_result_code(self, code):
8103 if self.operand.type.is_pyobject:
8104 self.generate_py_operation_code(code)
8106 def generate_py_operation_code(self, code):
8107 function = self.py_operation_function()
8108 code.putln(
8109 "%s = %s(%s); %s" % (
8110 self.result(),
8111 function,
8112 self.operand.py_result(),
8113 code.error_goto_if_null(self.result(), self.pos)))
8114 code.put_gotref(self.py_result())
8116 def type_error(self):
8117 if not self.operand.type.is_error:
8118 error(self.pos, "Invalid operand type for '%s' (%s)" %
8119 (self.operator, self.operand.type))
8120 self.type = PyrexTypes.error_type
8122 def analyse_cpp_operation(self, env):
8123 cpp_type = self.operand.type.find_cpp_operation_type(self.operator)
8124 if cpp_type is None:
8125 error(self.pos, "'%s' operator not defined for %s" % (
8126 self.operator, type))
8127 self.type_error()
8128 return
8129 self.type = cpp_type
8132 class NotNode(UnopNode):
8133 # 'not' operator
8135 # operand ExprNode
8136 operator = '!'
8138 type = PyrexTypes.c_bint_type
8140 def calculate_constant_result(self):
8141 self.constant_result = not self.operand.constant_result
8143 def compile_time_value(self, denv):
8144 operand = self.operand.compile_time_value(denv)
8145 try:
8146 return not operand
8147 except Exception, e:
8148 self.compile_time_value_error(e)
8150 def infer_unop_type(self, env, operand_type):
8151 return PyrexTypes.c_bint_type
8153 def analyse_types(self, env):
8154 self.operand = self.operand.analyse_types(env)
8155 operand_type = self.operand.type
8156 if operand_type.is_cpp_class:
8157 cpp_type = operand_type.find_cpp_operation_type(self.operator)
8158 if not cpp_type:
8159 error(self.pos, "'!' operator not defined for %s" % operand_type)
8160 self.type = PyrexTypes.error_type
8161 return
8162 self.type = cpp_type
8163 else:
8164 self.operand = self.operand.coerce_to_boolean(env)
8165 return self
8167 def calculate_result_code(self):
8168 return "(!%s)" % self.operand.result()
8170 def generate_result_code(self, code):
8171 pass
8174 class UnaryPlusNode(UnopNode):
8175 # unary '+' operator
8177 operator = '+'
8179 def analyse_c_operation(self, env):
8180 self.type = PyrexTypes.widest_numeric_type(
8181 self.operand.type, PyrexTypes.c_int_type)
8183 def py_operation_function(self):
8184 return "PyNumber_Positive"
8186 def calculate_result_code(self):
8187 if self.is_cpp_operation():
8188 return "(+%s)" % self.operand.result()
8189 else:
8190 return self.operand.result()
8193 class UnaryMinusNode(UnopNode):
8194 # unary '-' operator
8196 operator = '-'
8198 def analyse_c_operation(self, env):
8199 if self.operand.type.is_numeric:
8200 self.type = PyrexTypes.widest_numeric_type(
8201 self.operand.type, PyrexTypes.c_int_type)
8202 elif self.operand.type.is_enum:
8203 self.type = PyrexTypes.c_int_type
8204 else:
8205 self.type_error()
8206 if self.type.is_complex:
8207 self.infix = False
8209 def py_operation_function(self):
8210 return "PyNumber_Negative"
8212 def calculate_result_code(self):
8213 if self.infix:
8214 return "(-%s)" % self.operand.result()
8215 else:
8216 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
8218 def get_constant_c_result_code(self):
8219 value = self.operand.get_constant_c_result_code()
8220 if value:
8221 return "(-%s)" % value
8223 class TildeNode(UnopNode):
8224 # unary '~' operator
8226 def analyse_c_operation(self, env):
8227 if self.operand.type.is_int:
8228 self.type = PyrexTypes.widest_numeric_type(
8229 self.operand.type, PyrexTypes.c_int_type)
8230 elif self.operand.type.is_enum:
8231 self.type = PyrexTypes.c_int_type
8232 else:
8233 self.type_error()
8235 def py_operation_function(self):
8236 return "PyNumber_Invert"
8238 def calculate_result_code(self):
8239 return "(~%s)" % self.operand.result()
8242 class CUnopNode(UnopNode):
8244 def is_py_operation(self):
8245 return False
8247 class DereferenceNode(CUnopNode):
8248 # unary * operator
8250 operator = '*'
8252 def infer_unop_type(self, env, operand_type):
8253 if operand_type.is_ptr:
8254 return operand_type.base_type
8255 else:
8256 return PyrexTypes.error_type
8258 def analyse_c_operation(self, env):
8259 if self.operand.type.is_ptr:
8260 self.type = self.operand.type.base_type
8261 else:
8262 self.type_error()
8264 def calculate_result_code(self):
8265 return "(*%s)" % self.operand.result()
8268 class DecrementIncrementNode(CUnopNode):
8269 # unary ++/-- operator
8271 def analyse_c_operation(self, env):
8272 if self.operand.type.is_numeric:
8273 self.type = PyrexTypes.widest_numeric_type(
8274 self.operand.type, PyrexTypes.c_int_type)
8275 elif self.operand.type.is_ptr:
8276 self.type = self.operand.type
8277 else:
8278 self.type_error()
8280 def calculate_result_code(self):
8281 if self.is_prefix:
8282 return "(%s%s)" % (self.operator, self.operand.result())
8283 else:
8284 return "(%s%s)" % (self.operand.result(), self.operator)
8286 def inc_dec_constructor(is_prefix, operator):
8287 return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds)
8290 class AmpersandNode(CUnopNode):
8291 # The C address-of operator.
8293 # operand ExprNode
8294 operator = '&'
8296 def infer_unop_type(self, env, operand_type):
8297 return PyrexTypes.c_ptr_type(operand_type)
8299 def analyse_types(self, env):
8300 self.operand = self.operand.analyse_types(env)
8301 argtype = self.operand.type
8302 if argtype.is_cpp_class:
8303 cpp_type = argtype.find_cpp_operation_type(self.operator)
8304 if cpp_type is not None:
8305 self.type = cpp_type
8306 return self
8307 if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_addressable()):
8308 if argtype.is_memoryviewslice:
8309 self.error("Cannot take address of memoryview slice")
8310 else:
8311 self.error("Taking address of non-lvalue")
8312 return self
8313 if argtype.is_pyobject:
8314 self.error("Cannot take address of Python variable")
8315 return self
8316 self.type = PyrexTypes.c_ptr_type(argtype)
8317 return self
8319 def check_const(self):
8320 return self.operand.check_const_addr()
8322 def error(self, mess):
8323 error(self.pos, mess)
8324 self.type = PyrexTypes.error_type
8325 self.result_code = "<error>"
8327 def calculate_result_code(self):
8328 return "(&%s)" % self.operand.result()
8330 def generate_result_code(self, code):
8331 pass
8334 unop_node_classes = {
8335 "+": UnaryPlusNode,
8336 "-": UnaryMinusNode,
8337 "~": TildeNode,
8340 def unop_node(pos, operator, operand):
8341 # Construct unnop node of appropriate class for
8342 # given operator.
8343 if isinstance(operand, IntNode) and operator == '-':
8344 return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)),
8345 longness=operand.longness, unsigned=operand.unsigned)
8346 elif isinstance(operand, UnopNode) and operand.operator == operator in '+-':
8347 warning(pos, "Python has no increment/decrement operator: %s%sx == %s(%sx) == x" % ((operator,)*4), 5)
8348 return unop_node_classes[operator](pos,
8349 operator = operator,
8350 operand = operand)
8353 class TypecastNode(ExprNode):
8354 # C type cast
8356 # operand ExprNode
8357 # base_type CBaseTypeNode
8358 # declarator CDeclaratorNode
8359 # typecheck boolean
8361 # If used from a transform, one can if wanted specify the attribute
8362 # "type" directly and leave base_type and declarator to None
8364 subexprs = ['operand']
8365 base_type = declarator = type = None
8367 def type_dependencies(self, env):
8368 return ()
8370 def infer_type(self, env):
8371 if self.type is None:
8372 base_type = self.base_type.analyse(env)
8373 _, self.type = self.declarator.analyse(base_type, env)
8374 return self.type
8376 def analyse_types(self, env):
8377 if self.type is None:
8378 base_type = self.base_type.analyse(env)
8379 _, self.type = self.declarator.analyse(base_type, env)
8380 if self.operand.has_constant_result():
8381 # Must be done after self.type is resolved.
8382 self.calculate_constant_result()
8383 if self.type.is_cfunction:
8384 error(self.pos,
8385 "Cannot cast to a function type")
8386 self.type = PyrexTypes.error_type
8387 self.operand = self.operand.analyse_types(env)
8388 if self.type is PyrexTypes.c_bint_type:
8389 # short circuit this to a coercion
8390 return self.operand.coerce_to_boolean(env)
8391 to_py = self.type.is_pyobject
8392 from_py = self.operand.type.is_pyobject
8393 if from_py and not to_py and self.operand.is_ephemeral():
8394 if not self.type.is_numeric and not self.type.is_cpp_class:
8395 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
8396 if to_py and not from_py:
8397 if self.type is bytes_type and self.operand.type.is_int:
8398 return CoerceIntToBytesNode(self.operand, env)
8399 elif self.operand.type.can_coerce_to_pyobject(env):
8400 self.result_ctype = py_object_type
8401 base_type = self.base_type.analyse(env)
8402 self.operand = self.operand.coerce_to(base_type, env)
8403 else:
8404 if self.operand.type.is_ptr:
8405 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
8406 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
8407 else:
8408 # Should this be an error?
8409 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
8410 self.operand = self.operand.coerce_to_simple(env)
8411 elif from_py and not to_py:
8412 if self.type.create_from_py_utility_code(env):
8413 self.operand = self.operand.coerce_to(self.type, env)
8414 elif self.type.is_ptr:
8415 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
8416 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
8417 else:
8418 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
8419 elif from_py and to_py:
8420 if self.typecheck:
8421 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
8422 elif isinstance(self.operand, SliceIndexNode):
8423 # This cast can influence the created type of string slices.
8424 self.operand = self.operand.coerce_to(self.type, env)
8425 elif self.type.is_complex and self.operand.type.is_complex:
8426 self.operand = self.operand.coerce_to_simple(env)
8427 elif self.operand.type.is_fused:
8428 self.operand = self.operand.coerce_to(self.type, env)
8429 #self.type = self.operand.type
8430 return self
8432 def is_simple(self):
8433 # either temp or a C cast => no side effects other than the operand's
8434 return self.operand.is_simple()
8436 def nonlocally_immutable(self):
8437 return self.is_temp or self.operand.nonlocally_immutable()
8439 def nogil_check(self, env):
8440 if self.type and self.type.is_pyobject and self.is_temp:
8441 self.gil_error()
8443 def check_const(self):
8444 return self.operand.check_const()
8446 def calculate_constant_result(self):
8447 self.constant_result = self.calculate_result_code(self.operand.constant_result)
8449 def calculate_result_code(self, operand_result = None):
8450 if operand_result is None:
8451 operand_result = self.operand.result()
8452 if self.type.is_complex:
8453 operand_result = self.operand.result()
8454 if self.operand.type.is_complex:
8455 real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % operand_result)
8456 imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % operand_result)
8457 else:
8458 real_part = self.type.real_type.cast_code(operand_result)
8459 imag_part = "0"
8460 return "%s(%s, %s)" % (
8461 self.type.from_parts,
8462 real_part,
8463 imag_part)
8464 else:
8465 return self.type.cast_code(operand_result)
8467 def get_constant_c_result_code(self):
8468 operand_result = self.operand.get_constant_c_result_code()
8469 if operand_result:
8470 return self.type.cast_code(operand_result)
8472 def result_as(self, type):
8473 if self.type.is_pyobject and not self.is_temp:
8474 # Optimise away some unnecessary casting
8475 return self.operand.result_as(type)
8476 else:
8477 return ExprNode.result_as(self, type)
8479 def generate_result_code(self, code):
8480 if self.is_temp:
8481 code.putln(
8482 "%s = (PyObject *)%s;" % (
8483 self.result(),
8484 self.operand.result()))
8485 code.put_incref(self.result(), self.ctype())
8488 ERR_START = "Start may not be given"
8489 ERR_NOT_STOP = "Stop must be provided to indicate shape"
8490 ERR_STEPS = ("Strides may only be given to indicate contiguity. "
8491 "Consider slicing it after conversion")
8492 ERR_NOT_POINTER = "Can only create cython.array from pointer or array"
8493 ERR_BASE_TYPE = "Pointer base type does not match cython.array base type"
8495 class CythonArrayNode(ExprNode):
8497 Used when a pointer of base_type is cast to a memoryviewslice with that
8498 base type. i.e.
8500 <int[:M:1, :N]> p
8502 creates a fortran-contiguous cython.array.
8504 We leave the type set to object so coercions to object are more efficient
8505 and less work. Acquiring a memoryviewslice from this will be just as
8506 efficient. ExprNode.coerce_to() will do the additional typecheck on
8507 self.compile_time_type
8509 This also handles <int[:, :]> my_c_array
8512 operand ExprNode the thing we're casting
8513 base_type_node MemoryViewSliceTypeNode the cast expression node
8516 subexprs = ['operand', 'shapes']
8518 shapes = None
8519 is_temp = True
8520 mode = "c"
8521 array_dtype = None
8523 shape_type = PyrexTypes.c_py_ssize_t_type
8525 def analyse_types(self, env):
8526 import MemoryView
8528 self.operand = self.operand.analyse_types(env)
8529 if self.array_dtype:
8530 array_dtype = self.array_dtype
8531 else:
8532 array_dtype = self.base_type_node.base_type_node.analyse(env)
8533 axes = self.base_type_node.axes
8535 MemoryView.validate_memslice_dtype(self.pos, array_dtype)
8537 self.type = error_type
8538 self.shapes = []
8539 ndim = len(axes)
8541 # Base type of the pointer or C array we are converting
8542 base_type = self.operand.type
8544 if not self.operand.type.is_ptr and not self.operand.type.is_array:
8545 error(self.operand.pos, ERR_NOT_POINTER)
8546 return self
8548 # Dimension sizes of C array
8549 array_dimension_sizes = []
8550 if base_type.is_array:
8551 while base_type.is_array:
8552 array_dimension_sizes.append(base_type.size)
8553 base_type = base_type.base_type
8554 elif base_type.is_ptr:
8555 base_type = base_type.base_type
8556 else:
8557 error(self.pos, "unexpected base type %s found" % base_type)
8558 return self
8560 if not (base_type.same_as(array_dtype) or base_type.is_void):
8561 error(self.operand.pos, ERR_BASE_TYPE)
8562 return self
8563 elif self.operand.type.is_array and len(array_dimension_sizes) != ndim:
8564 error(self.operand.pos,
8565 "Expected %d dimensions, array has %d dimensions" %
8566 (ndim, len(array_dimension_sizes)))
8567 return self
8569 # Verify the start, stop and step values
8570 # In case of a C array, use the size of C array in each dimension to
8571 # get an automatic cast
8572 for axis_no, axis in enumerate(axes):
8573 if not axis.start.is_none:
8574 error(axis.start.pos, ERR_START)
8575 return self
8577 if axis.stop.is_none:
8578 if array_dimension_sizes:
8579 dimsize = array_dimension_sizes[axis_no]
8580 axis.stop = IntNode(self.pos, value=str(dimsize),
8581 constant_result=dimsize,
8582 type=PyrexTypes.c_int_type)
8583 else:
8584 error(axis.pos, ERR_NOT_STOP)
8585 return self
8587 axis.stop = axis.stop.analyse_types(env)
8588 shape = axis.stop.coerce_to(self.shape_type, env)
8589 if not shape.is_literal:
8590 shape.coerce_to_temp(env)
8592 self.shapes.append(shape)
8594 first_or_last = axis_no in (0, ndim - 1)
8595 if not axis.step.is_none and first_or_last:
8596 # '1' in the first or last dimension denotes F or C contiguity
8597 axis.step = axis.step.analyse_types(env)
8598 if (not axis.step.type.is_int and axis.step.is_literal and not
8599 axis.step.type.is_error):
8600 error(axis.step.pos, "Expected an integer literal")
8601 return self
8603 if axis.step.compile_time_value(env) != 1:
8604 error(axis.step.pos, ERR_STEPS)
8605 return self
8607 if axis_no == 0:
8608 self.mode = "fortran"
8610 elif not axis.step.is_none and not first_or_last:
8611 # step provided in some other dimension
8612 error(axis.step.pos, ERR_STEPS)
8613 return self
8615 if not self.operand.is_name:
8616 self.operand = self.operand.coerce_to_temp(env)
8618 axes = [('direct', 'follow')] * len(axes)
8619 if self.mode == "fortran":
8620 axes[0] = ('direct', 'contig')
8621 else:
8622 axes[-1] = ('direct', 'contig')
8624 self.coercion_type = PyrexTypes.MemoryViewSliceType(array_dtype, axes)
8625 self.type = self.get_cython_array_type(env)
8626 MemoryView.use_cython_array_utility_code(env)
8627 env.use_utility_code(MemoryView.typeinfo_to_format_code)
8628 return self
8630 def allocate_temp_result(self, code):
8631 if self.temp_code:
8632 raise RuntimeError("temp allocated mulitple times")
8634 self.temp_code = code.funcstate.allocate_temp(self.type, True)
8636 def infer_type(self, env):
8637 return self.get_cython_array_type(env)
8639 def get_cython_array_type(self, env):
8640 return env.global_scope().context.cython_scope.viewscope.lookup("array").type
8642 def generate_result_code(self, code):
8643 import Buffer
8645 shapes = [self.shape_type.cast_code(shape.result())
8646 for shape in self.shapes]
8647 dtype = self.coercion_type.dtype
8649 shapes_temp = code.funcstate.allocate_temp(py_object_type, True)
8650 format_temp = code.funcstate.allocate_temp(py_object_type, True)
8652 itemsize = "sizeof(%s)" % dtype.declaration_code("")
8653 type_info = Buffer.get_type_information_cname(code, dtype)
8655 if self.operand.type.is_ptr:
8656 code.putln("if (!%s) {" % self.operand.result())
8657 code.putln( 'PyErr_SetString(PyExc_ValueError,'
8658 '"Cannot create cython.array from NULL pointer");')
8659 code.putln(code.error_goto(self.operand.pos))
8660 code.putln("}")
8662 code.putln("%s = __pyx_format_from_typeinfo(&%s);" %
8663 (format_temp, type_info))
8664 buildvalue_fmt = " __PYX_BUILD_PY_SSIZE_T " * len(shapes)
8665 code.putln('%s = Py_BuildValue((char*) "(" %s ")", %s);' % (
8666 shapes_temp, buildvalue_fmt, ", ".join(shapes)))
8668 err = "!%s || !%s || !PyBytes_AsString(%s)" % (format_temp,
8669 shapes_temp,
8670 format_temp)
8671 code.putln(code.error_goto_if(err, self.pos))
8672 code.put_gotref(format_temp)
8673 code.put_gotref(shapes_temp)
8675 tup = (self.result(), shapes_temp, itemsize, format_temp,
8676 self.mode, self.operand.result())
8677 code.putln('%s = __pyx_array_new('
8678 '%s, %s, PyBytes_AS_STRING(%s), '
8679 '(char *) "%s", (char *) %s);' % tup)
8680 code.putln(code.error_goto_if_null(self.result(), self.pos))
8681 code.put_gotref(self.result())
8683 def dispose(temp):
8684 code.put_decref_clear(temp, py_object_type)
8685 code.funcstate.release_temp(temp)
8687 dispose(shapes_temp)
8688 dispose(format_temp)
8690 @classmethod
8691 def from_carray(cls, src_node, env):
8693 Given a C array type, return a CythonArrayNode
8695 pos = src_node.pos
8696 base_type = src_node.type
8698 none_node = NoneNode(pos)
8699 axes = []
8701 while base_type.is_array:
8702 axes.append(SliceNode(pos, start=none_node, stop=none_node,
8703 step=none_node))
8704 base_type = base_type.base_type
8705 axes[-1].step = IntNode(pos, value="1", is_c_literal=True)
8707 memslicenode = Nodes.MemoryViewSliceTypeNode(pos, axes=axes,
8708 base_type_node=base_type)
8709 result = CythonArrayNode(pos, base_type_node=memslicenode,
8710 operand=src_node, array_dtype=base_type)
8711 result = result.analyse_types(env)
8712 return result
8714 class SizeofNode(ExprNode):
8715 # Abstract base class for sizeof(x) expression nodes.
8717 type = PyrexTypes.c_size_t_type
8719 def check_const(self):
8720 return True
8722 def generate_result_code(self, code):
8723 pass
8726 class SizeofTypeNode(SizeofNode):
8727 # C sizeof function applied to a type
8729 # base_type CBaseTypeNode
8730 # declarator CDeclaratorNode
8732 subexprs = []
8733 arg_type = None
8735 def analyse_types(self, env):
8736 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
8737 # this could be better handled by more uniformly treating types as runtime-available objects
8738 if 0 and self.base_type.module_path:
8739 path = self.base_type.module_path
8740 obj = env.lookup(path[0])
8741 if obj.as_module is None:
8742 operand = NameNode(pos=self.pos, name=path[0])
8743 for attr in path[1:]:
8744 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
8745 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
8746 self.operand = operand
8747 self.__class__ = SizeofVarNode
8748 node = self.analyse_types(env)
8749 return node
8750 if self.arg_type is None:
8751 base_type = self.base_type.analyse(env)
8752 _, arg_type = self.declarator.analyse(base_type, env)
8753 self.arg_type = arg_type
8754 self.check_type()
8755 return self
8757 def check_type(self):
8758 arg_type = self.arg_type
8759 if arg_type.is_pyobject and not arg_type.is_extension_type:
8760 error(self.pos, "Cannot take sizeof Python object")
8761 elif arg_type.is_void:
8762 error(self.pos, "Cannot take sizeof void")
8763 elif not arg_type.is_complete():
8764 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
8766 def calculate_result_code(self):
8767 if self.arg_type.is_extension_type:
8768 # the size of the pointer is boring
8769 # we want the size of the actual struct
8770 arg_code = self.arg_type.declaration_code("", deref=1)
8771 else:
8772 arg_code = self.arg_type.declaration_code("")
8773 return "(sizeof(%s))" % arg_code
8776 class SizeofVarNode(SizeofNode):
8777 # C sizeof function applied to a variable
8779 # operand ExprNode
8781 subexprs = ['operand']
8783 def analyse_types(self, env):
8784 # We may actually be looking at a type rather than a variable...
8785 # If we are, traditional analysis would fail...
8786 operand_as_type = self.operand.analyse_as_type(env)
8787 if operand_as_type:
8788 self.arg_type = operand_as_type
8789 if self.arg_type.is_fused:
8790 self.arg_type = self.arg_type.specialize(env.fused_to_specific)
8791 self.__class__ = SizeofTypeNode
8792 self.check_type()
8793 else:
8794 self.operand = self.operand.analyse_types(env)
8795 return self
8797 def calculate_result_code(self):
8798 return "(sizeof(%s))" % self.operand.result()
8800 def generate_result_code(self, code):
8801 pass
8803 class TypeofNode(ExprNode):
8804 # Compile-time type of an expression, as a string.
8806 # operand ExprNode
8807 # literal StringNode # internal
8809 literal = None
8810 type = py_object_type
8812 subexprs = ['literal'] # 'operand' will be ignored after type analysis!
8814 def analyse_types(self, env):
8815 self.operand = self.operand.analyse_types(env)
8816 value = StringEncoding.EncodedString(str(self.operand.type)) #self.operand.type.typeof_name())
8817 literal = StringNode(self.pos, value=value)
8818 literal = literal.analyse_types(env)
8819 self.literal = literal.coerce_to_pyobject(env)
8820 return self
8822 def may_be_none(self):
8823 return False
8825 def generate_evaluation_code(self, code):
8826 self.literal.generate_evaluation_code(code)
8828 def calculate_result_code(self):
8829 return self.literal.calculate_result_code()
8831 #-------------------------------------------------------------------
8833 # Binary operator nodes
8835 #-------------------------------------------------------------------
8837 compile_time_binary_operators = {
8838 '<': operator.lt,
8839 '<=': operator.le,
8840 '==': operator.eq,
8841 '!=': operator.ne,
8842 '>=': operator.ge,
8843 '>': operator.gt,
8844 'is': operator.is_,
8845 'is_not': operator.is_not,
8846 '+': operator.add,
8847 '&': operator.and_,
8848 '/': operator.truediv,
8849 '//': operator.floordiv,
8850 '<<': operator.lshift,
8851 '%': operator.mod,
8852 '*': operator.mul,
8853 '|': operator.or_,
8854 '**': operator.pow,
8855 '>>': operator.rshift,
8856 '-': operator.sub,
8857 '^': operator.xor,
8858 'in': lambda x, seq: x in seq,
8859 'not_in': lambda x, seq: x not in seq,
8862 def get_compile_time_binop(node):
8863 func = compile_time_binary_operators.get(node.operator)
8864 if not func:
8865 error(node.pos,
8866 "Binary '%s' not supported in compile-time expression"
8867 % node.operator)
8868 return func
8870 class BinopNode(ExprNode):
8871 # operator string
8872 # operand1 ExprNode
8873 # operand2 ExprNode
8875 # Processing during analyse_expressions phase:
8877 # analyse_c_operation
8878 # Called when neither operand is a pyobject.
8879 # - Check operand types and coerce if needed.
8880 # - Determine result type and result code fragment.
8881 # - Allocate temporary for result if needed.
8883 subexprs = ['operand1', 'operand2']
8884 inplace = False
8886 def calculate_constant_result(self):
8887 func = compile_time_binary_operators[self.operator]
8888 self.constant_result = func(
8889 self.operand1.constant_result,
8890 self.operand2.constant_result)
8892 def compile_time_value(self, denv):
8893 func = get_compile_time_binop(self)
8894 operand1 = self.operand1.compile_time_value(denv)
8895 operand2 = self.operand2.compile_time_value(denv)
8896 try:
8897 return func(operand1, operand2)
8898 except Exception, e:
8899 self.compile_time_value_error(e)
8901 def infer_type(self, env):
8902 return self.result_type(self.operand1.infer_type(env),
8903 self.operand2.infer_type(env))
8905 def analyse_types(self, env):
8906 self.operand1 = self.operand1.analyse_types(env)
8907 self.operand2 = self.operand2.analyse_types(env)
8908 self.analyse_operation(env)
8909 return self
8911 def analyse_operation(self, env):
8912 if self.is_py_operation():
8913 self.coerce_operands_to_pyobjects(env)
8914 self.type = self.result_type(self.operand1.type,
8915 self.operand2.type)
8916 assert self.type.is_pyobject
8917 self.is_temp = 1
8918 elif self.is_cpp_operation():
8919 self.analyse_cpp_operation(env)
8920 else:
8921 self.analyse_c_operation(env)
8923 def is_py_operation(self):
8924 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
8926 def is_py_operation_types(self, type1, type2):
8927 return type1.is_pyobject or type2.is_pyobject
8929 def is_cpp_operation(self):
8930 return (self.operand1.type.is_cpp_class
8931 or self.operand2.type.is_cpp_class)
8933 def analyse_cpp_operation(self, env):
8934 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
8935 if not entry:
8936 self.type_error()
8937 return
8938 func_type = entry.type
8939 if func_type.is_ptr:
8940 func_type = func_type.base_type
8941 if len(func_type.args) == 1:
8942 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
8943 else:
8944 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
8945 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
8946 self.type = func_type.return_type
8948 def result_type(self, type1, type2):
8949 if self.is_py_operation_types(type1, type2):
8950 if type2.is_string:
8951 type2 = Builtin.bytes_type
8952 elif type2.is_pyunicode_ptr:
8953 type2 = Builtin.unicode_type
8954 if type1.is_string:
8955 type1 = Builtin.bytes_type
8956 elif type1.is_pyunicode_ptr:
8957 type1 = Builtin.unicode_type
8958 if type1.is_builtin_type or type2.is_builtin_type:
8959 if type1 is type2 and self.operator in '**%+|&^':
8960 # FIXME: at least these operators should be safe - others?
8961 return type1
8962 result_type = self.infer_builtin_types_operation(type1, type2)
8963 if result_type is not None:
8964 return result_type
8965 return py_object_type
8966 else:
8967 return self.compute_c_result_type(type1, type2)
8969 def infer_builtin_types_operation(self, type1, type2):
8970 return None
8972 def nogil_check(self, env):
8973 if self.is_py_operation():
8974 self.gil_error()
8976 def coerce_operands_to_pyobjects(self, env):
8977 self.operand1 = self.operand1.coerce_to_pyobject(env)
8978 self.operand2 = self.operand2.coerce_to_pyobject(env)
8980 def check_const(self):
8981 return self.operand1.check_const() and self.operand2.check_const()
8983 def generate_result_code(self, code):
8984 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
8985 if self.operand1.type.is_pyobject:
8986 function = self.py_operation_function()
8987 if self.operator == '**':
8988 extra_args = ", Py_None"
8989 else:
8990 extra_args = ""
8991 code.putln(
8992 "%s = %s(%s, %s%s); %s" % (
8993 self.result(),
8994 function,
8995 self.operand1.py_result(),
8996 self.operand2.py_result(),
8997 extra_args,
8998 code.error_goto_if_null(self.result(), self.pos)))
8999 code.put_gotref(self.py_result())
9000 elif self.is_temp:
9001 code.putln("%s = %s;" % (self.result(), self.calculate_result_code()))
9003 def type_error(self):
9004 if not (self.operand1.type.is_error
9005 or self.operand2.type.is_error):
9006 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
9007 (self.operator, self.operand1.type,
9008 self.operand2.type))
9009 self.type = PyrexTypes.error_type
9012 class CBinopNode(BinopNode):
9014 def analyse_types(self, env):
9015 node = BinopNode.analyse_types(self, env)
9016 if node.is_py_operation():
9017 node.type = PyrexTypes.error_type
9018 return node
9020 def py_operation_function(self):
9021 return ""
9023 def calculate_result_code(self):
9024 return "(%s %s %s)" % (
9025 self.operand1.result(),
9026 self.operator,
9027 self.operand2.result())
9029 def compute_c_result_type(self, type1, type2):
9030 cpp_type = None
9031 if type1.is_cpp_class or type1.is_ptr:
9032 cpp_type = type1.find_cpp_operation_type(self.operator, type2)
9033 # FIXME: handle the reversed case?
9034 #if cpp_type is None and (type2.is_cpp_class or type2.is_ptr):
9035 # cpp_type = type2.find_cpp_operation_type(self.operator, type1)
9036 # FIXME: do we need to handle other cases here?
9037 return cpp_type
9040 def c_binop_constructor(operator):
9041 def make_binop_node(pos, **operands):
9042 return CBinopNode(pos, operator=operator, **operands)
9043 return make_binop_node
9045 class NumBinopNode(BinopNode):
9046 # Binary operation taking numeric arguments.
9048 infix = True
9049 overflow_check = False
9050 overflow_bit_node = None
9052 def analyse_c_operation(self, env):
9053 type1 = self.operand1.type
9054 type2 = self.operand2.type
9055 self.type = self.compute_c_result_type(type1, type2)
9056 if not self.type:
9057 self.type_error()
9058 return
9059 if self.type.is_complex:
9060 self.infix = False
9061 if (self.type.is_int
9062 and env.directives['overflowcheck']
9063 and self.operator in self.overflow_op_names):
9064 if (self.operator in ('+', '*')
9065 and self.operand1.has_constant_result()
9066 and not self.operand2.has_constant_result()):
9067 self.operand1, self.operand2 = self.operand2, self.operand1
9068 self.overflow_check = True
9069 self.overflow_fold = env.directives['overflowcheck.fold']
9070 self.func = self.type.overflow_check_binop(
9071 self.overflow_op_names[self.operator],
9072 env,
9073 const_rhs = self.operand2.has_constant_result())
9074 self.is_temp = True
9075 if not self.infix or (type1.is_numeric and type2.is_numeric):
9076 self.operand1 = self.operand1.coerce_to(self.type, env)
9077 self.operand2 = self.operand2.coerce_to(self.type, env)
9079 def compute_c_result_type(self, type1, type2):
9080 if self.c_types_okay(type1, type2):
9081 widest_type = PyrexTypes.widest_numeric_type(type1, type2)
9082 if widest_type is PyrexTypes.c_bint_type:
9083 if self.operator not in '|^&':
9084 # False + False == 0 # not False!
9085 widest_type = PyrexTypes.c_int_type
9086 else:
9087 widest_type = PyrexTypes.widest_numeric_type(
9088 widest_type, PyrexTypes.c_int_type)
9089 return widest_type
9090 else:
9091 return None
9093 def may_be_none(self):
9094 if self.type and self.type.is_builtin_type:
9095 # if we know the result type, we know the operation, so it can't be None
9096 return False
9097 type1 = self.operand1.type
9098 type2 = self.operand2.type
9099 if type1 and type1.is_builtin_type and type2 and type2.is_builtin_type:
9100 # XXX: I can't think of any case where a binary operation
9101 # on builtin types evaluates to None - add a special case
9102 # here if there is one.
9103 return False
9104 return super(NumBinopNode, self).may_be_none()
9106 def get_constant_c_result_code(self):
9107 value1 = self.operand1.get_constant_c_result_code()
9108 value2 = self.operand2.get_constant_c_result_code()
9109 if value1 and value2:
9110 return "(%s %s %s)" % (value1, self.operator, value2)
9111 else:
9112 return None
9114 def c_types_okay(self, type1, type2):
9115 #print "NumBinopNode.c_types_okay:", type1, type2 ###
9116 return (type1.is_numeric or type1.is_enum) \
9117 and (type2.is_numeric or type2.is_enum)
9119 def generate_evaluation_code(self, code):
9120 if self.overflow_check:
9121 self.overflow_bit_node = self
9122 self.overflow_bit = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
9123 code.putln("%s = 0;" % self.overflow_bit)
9124 super(NumBinopNode, self).generate_evaluation_code(code)
9125 if self.overflow_check:
9126 code.putln("if (unlikely(%s)) {" % self.overflow_bit)
9127 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large");')
9128 code.putln(code.error_goto(self.pos))
9129 code.putln("}")
9130 code.funcstate.release_temp(self.overflow_bit)
9132 def calculate_result_code(self):
9133 if self.overflow_bit_node is not None:
9134 return "%s(%s, %s, &%s)" % (
9135 self.func,
9136 self.operand1.result(),
9137 self.operand2.result(),
9138 self.overflow_bit_node.overflow_bit)
9139 elif self.infix:
9140 return "(%s %s %s)" % (
9141 self.operand1.result(),
9142 self.operator,
9143 self.operand2.result())
9144 else:
9145 func = self.type.binary_op(self.operator)
9146 if func is None:
9147 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
9148 return "%s(%s, %s)" % (
9149 func,
9150 self.operand1.result(),
9151 self.operand2.result())
9153 def is_py_operation_types(self, type1, type2):
9154 return (type1.is_unicode_char or
9155 type2.is_unicode_char or
9156 BinopNode.is_py_operation_types(self, type1, type2))
9158 def py_operation_function(self):
9159 function_name = self.py_functions[self.operator]
9160 if self.inplace:
9161 function_name = function_name.replace('PyNumber_', 'PyNumber_InPlace')
9162 return function_name
9164 py_functions = {
9165 "|": "PyNumber_Or",
9166 "^": "PyNumber_Xor",
9167 "&": "PyNumber_And",
9168 "<<": "PyNumber_Lshift",
9169 ">>": "PyNumber_Rshift",
9170 "+": "PyNumber_Add",
9171 "-": "PyNumber_Subtract",
9172 "*": "PyNumber_Multiply",
9173 "/": "__Pyx_PyNumber_Divide",
9174 "//": "PyNumber_FloorDivide",
9175 "%": "PyNumber_Remainder",
9176 "**": "PyNumber_Power"
9179 overflow_op_names = {
9180 "+": "add",
9181 "-": "sub",
9182 "*": "mul",
9183 "<<": "lshift",
9187 class IntBinopNode(NumBinopNode):
9188 # Binary operation taking integer arguments.
9190 def c_types_okay(self, type1, type2):
9191 #print "IntBinopNode.c_types_okay:", type1, type2 ###
9192 return (type1.is_int or type1.is_enum) \
9193 and (type2.is_int or type2.is_enum)
9196 class AddNode(NumBinopNode):
9197 # '+' operator.
9199 def is_py_operation_types(self, type1, type2):
9200 if type1.is_string and type2.is_string or type1.is_pyunicode_ptr and type2.is_pyunicode_ptr:
9201 return 1
9202 else:
9203 return NumBinopNode.is_py_operation_types(self, type1, type2)
9205 def infer_builtin_types_operation(self, type1, type2):
9206 # b'abc' + 'abc' raises an exception in Py3,
9207 # so we can safely infer the Py2 type for bytes here
9208 string_types = [bytes_type, str_type, basestring_type, unicode_type] # Py2.4 lacks tuple.index()
9209 if type1 in string_types and type2 in string_types:
9210 return string_types[max(string_types.index(type1),
9211 string_types.index(type2))]
9212 return None
9214 def compute_c_result_type(self, type1, type2):
9215 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
9216 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
9217 return type1
9218 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
9219 return type2
9220 else:
9221 return NumBinopNode.compute_c_result_type(
9222 self, type1, type2)
9224 def py_operation_function(self):
9225 type1, type2 = self.operand1.type, self.operand2.type
9226 if type1 is unicode_type or type2 is unicode_type:
9227 if type1.is_builtin_type and type2.is_builtin_type:
9228 if self.operand1.may_be_none() or self.operand2.may_be_none():
9229 return '__Pyx_PyUnicode_ConcatSafe'
9230 else:
9231 return '__Pyx_PyUnicode_Concat'
9232 return super(AddNode, self).py_operation_function()
9235 class SubNode(NumBinopNode):
9236 # '-' operator.
9238 def compute_c_result_type(self, type1, type2):
9239 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
9240 return type1
9241 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
9242 return PyrexTypes.c_ptrdiff_t_type
9243 else:
9244 return NumBinopNode.compute_c_result_type(
9245 self, type1, type2)
9248 class MulNode(NumBinopNode):
9249 # '*' operator.
9251 def is_py_operation_types(self, type1, type2):
9252 if ((type1.is_string and type2.is_int) or
9253 (type2.is_string and type1.is_int)):
9254 return 1
9255 else:
9256 return NumBinopNode.is_py_operation_types(self, type1, type2)
9258 def infer_builtin_types_operation(self, type1, type2):
9259 # let's assume that whatever builtin type you multiply a string with
9260 # will either return a string of the same type or fail with an exception
9261 string_types = (bytes_type, str_type, basestring_type, unicode_type)
9262 if type1 in string_types and type2.is_builtin_type:
9263 return type1
9264 if type2 in string_types and type1.is_builtin_type:
9265 return type2
9266 # multiplication of containers/numbers with an integer value
9267 # always (?) returns the same type
9268 if type1.is_int:
9269 return type2
9270 if type2.is_int:
9271 return type1
9272 return None
9275 class DivNode(NumBinopNode):
9276 # '/' or '//' operator.
9278 cdivision = None
9279 truedivision = None # == "unknown" if operator == '/'
9280 ctruedivision = False
9281 cdivision_warnings = False
9282 zerodivision_check = None
9284 def find_compile_time_binary_operator(self, op1, op2):
9285 func = compile_time_binary_operators[self.operator]
9286 if self.operator == '/' and self.truedivision is None:
9287 # => true div for floats, floor div for integers
9288 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
9289 func = compile_time_binary_operators['//']
9290 return func
9292 def calculate_constant_result(self):
9293 op1 = self.operand1.constant_result
9294 op2 = self.operand2.constant_result
9295 func = self.find_compile_time_binary_operator(op1, op2)
9296 self.constant_result = func(
9297 self.operand1.constant_result,
9298 self.operand2.constant_result)
9300 def compile_time_value(self, denv):
9301 operand1 = self.operand1.compile_time_value(denv)
9302 operand2 = self.operand2.compile_time_value(denv)
9303 try:
9304 func = self.find_compile_time_binary_operator(
9305 operand1, operand2)
9306 return func(operand1, operand2)
9307 except Exception, e:
9308 self.compile_time_value_error(e)
9310 def analyse_operation(self, env):
9311 if self.cdivision or env.directives['cdivision']:
9312 self.ctruedivision = False
9313 else:
9314 self.ctruedivision = self.truedivision
9315 NumBinopNode.analyse_operation(self, env)
9316 if self.is_cpp_operation():
9317 self.cdivision = True
9318 if not self.type.is_pyobject:
9319 self.zerodivision_check = (
9320 self.cdivision is None and not env.directives['cdivision']
9321 and (not self.operand2.has_constant_result() or
9322 self.operand2.constant_result == 0))
9323 if self.zerodivision_check or env.directives['cdivision_warnings']:
9324 # Need to check ahead of time to warn or raise zero division error
9325 self.operand1 = self.operand1.coerce_to_simple(env)
9326 self.operand2 = self.operand2.coerce_to_simple(env)
9328 def compute_c_result_type(self, type1, type2):
9329 if self.operator == '/' and self.ctruedivision:
9330 if not type1.is_float and not type2.is_float:
9331 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
9332 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
9333 return widest_type
9334 return NumBinopNode.compute_c_result_type(self, type1, type2)
9336 def zero_division_message(self):
9337 if self.type.is_int:
9338 return "integer division or modulo by zero"
9339 else:
9340 return "float division"
9342 def generate_evaluation_code(self, code):
9343 if not self.type.is_pyobject and not self.type.is_complex:
9344 if self.cdivision is None:
9345 self.cdivision = (code.globalstate.directives['cdivision']
9346 or not self.type.signed
9347 or self.type.is_float)
9348 if not self.cdivision:
9349 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
9350 NumBinopNode.generate_evaluation_code(self, code)
9351 self.generate_div_warning_code(code)
9353 def generate_div_warning_code(self, code):
9354 if not self.type.is_pyobject:
9355 if self.zerodivision_check:
9356 if not self.infix:
9357 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
9358 else:
9359 zero_test = "%s == 0" % self.operand2.result()
9360 code.putln("if (unlikely(%s)) {" % zero_test)
9361 code.put_ensure_gil()
9362 code.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
9363 code.put_release_ensured_gil()
9364 code.putln(code.error_goto(self.pos))
9365 code.putln("}")
9366 if self.type.is_int and self.type.signed and self.operator != '%':
9367 code.globalstate.use_utility_code(division_overflow_test_code)
9368 if self.operand2.type.signed == 2:
9369 # explicitly signed, no runtime check needed
9370 minus1_check = 'unlikely(%s == -1)' % self.operand2.result()
9371 else:
9372 type_of_op2 = self.operand2.type.declaration_code('')
9373 minus1_check = '(!(((%s)-1) > 0)) && unlikely(%s == (%s)-1)' % (
9374 type_of_op2, self.operand2.result(), type_of_op2)
9375 code.putln("else if (sizeof(%s) == sizeof(long) && %s "
9376 " && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
9377 self.type.declaration_code(''),
9378 minus1_check,
9379 self.operand1.result()))
9380 code.put_ensure_gil()
9381 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large to perform division");')
9382 code.put_release_ensured_gil()
9383 code.putln(code.error_goto(self.pos))
9384 code.putln("}")
9385 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
9386 code.globalstate.use_utility_code(cdivision_warning_utility_code)
9387 code.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % (
9388 self.operand1.result(),
9389 self.operand2.result()))
9390 code.put_ensure_gil()
9391 code.putln(code.set_error_info(self.pos, used=True))
9392 code.putln("if (__Pyx_cdivision_warning(%(FILENAME)s, "
9393 "%(LINENO)s)) {" % {
9394 'FILENAME': Naming.filename_cname,
9395 'LINENO': Naming.lineno_cname,
9397 code.put_release_ensured_gil()
9398 code.put_goto(code.error_label)
9399 code.putln("}")
9400 code.put_release_ensured_gil()
9401 code.putln("}")
9403 def calculate_result_code(self):
9404 if self.type.is_complex:
9405 return NumBinopNode.calculate_result_code(self)
9406 elif self.type.is_float and self.operator == '//':
9407 return "floor(%s / %s)" % (
9408 self.operand1.result(),
9409 self.operand2.result())
9410 elif self.truedivision or self.cdivision:
9411 op1 = self.operand1.result()
9412 op2 = self.operand2.result()
9413 if self.truedivision:
9414 if self.type != self.operand1.type:
9415 op1 = self.type.cast_code(op1)
9416 if self.type != self.operand2.type:
9417 op2 = self.type.cast_code(op2)
9418 return "(%s / %s)" % (op1, op2)
9419 else:
9420 return "__Pyx_div_%s(%s, %s)" % (
9421 self.type.specialization_name(),
9422 self.operand1.result(),
9423 self.operand2.result())
9426 class ModNode(DivNode):
9427 # '%' operator.
9429 def is_py_operation_types(self, type1, type2):
9430 return (type1.is_string
9431 or type2.is_string
9432 or NumBinopNode.is_py_operation_types(self, type1, type2))
9434 def infer_builtin_types_operation(self, type1, type2):
9435 # b'%s' % xyz raises an exception in Py3, so it's safe to infer the type for Py2
9436 if type1 is unicode_type:
9437 # None + xyz may be implemented by RHS
9438 if type2.is_builtin_type or not self.operand1.may_be_none():
9439 return type1
9440 elif type1 in (bytes_type, str_type, basestring_type):
9441 if type2 is unicode_type:
9442 return type2
9443 elif type2.is_numeric:
9444 return type1
9445 elif type1 is bytes_type and not type2.is_builtin_type:
9446 return None # RHS might implement '% operator differently in Py3
9447 else:
9448 return basestring_type # either str or unicode, can't tell
9449 return None
9451 def zero_division_message(self):
9452 if self.type.is_int:
9453 return "integer division or modulo by zero"
9454 else:
9455 return "float divmod()"
9457 def analyse_operation(self, env):
9458 DivNode.analyse_operation(self, env)
9459 if not self.type.is_pyobject:
9460 if self.cdivision is None:
9461 self.cdivision = env.directives['cdivision'] or not self.type.signed
9462 if not self.cdivision and not self.type.is_int and not self.type.is_float:
9463 error(self.pos, "mod operator not supported for type '%s'" % self.type)
9465 def generate_evaluation_code(self, code):
9466 if not self.type.is_pyobject and not self.cdivision:
9467 if self.type.is_int:
9468 code.globalstate.use_utility_code(
9469 mod_int_utility_code.specialize(self.type))
9470 else: # float
9471 code.globalstate.use_utility_code(
9472 mod_float_utility_code.specialize(
9473 self.type, math_h_modifier=self.type.math_h_modifier))
9474 # note: skipping over DivNode here
9475 NumBinopNode.generate_evaluation_code(self, code)
9476 self.generate_div_warning_code(code)
9478 def calculate_result_code(self):
9479 if self.cdivision:
9480 if self.type.is_float:
9481 return "fmod%s(%s, %s)" % (
9482 self.type.math_h_modifier,
9483 self.operand1.result(),
9484 self.operand2.result())
9485 else:
9486 return "(%s %% %s)" % (
9487 self.operand1.result(),
9488 self.operand2.result())
9489 else:
9490 return "__Pyx_mod_%s(%s, %s)" % (
9491 self.type.specialization_name(),
9492 self.operand1.result(),
9493 self.operand2.result())
9495 def py_operation_function(self):
9496 if self.operand1.type is unicode_type:
9497 if self.operand1.may_be_none():
9498 return '__Pyx_PyUnicode_FormatSafe'
9499 else:
9500 return 'PyUnicode_Format'
9501 elif self.operand1.type is str_type:
9502 if self.operand1.may_be_none():
9503 return '__Pyx_PyString_FormatSafe'
9504 else:
9505 return '__Pyx_PyString_Format'
9506 return super(ModNode, self).py_operation_function()
9509 class PowNode(NumBinopNode):
9510 # '**' operator.
9512 def analyse_c_operation(self, env):
9513 NumBinopNode.analyse_c_operation(self, env)
9514 if self.type.is_complex:
9515 if self.type.real_type.is_float:
9516 self.operand1 = self.operand1.coerce_to(self.type, env)
9517 self.operand2 = self.operand2.coerce_to(self.type, env)
9518 self.pow_func = "__Pyx_c_pow" + self.type.real_type.math_h_modifier
9519 else:
9520 error(self.pos, "complex int powers not supported")
9521 self.pow_func = "<error>"
9522 elif self.type.is_float:
9523 self.pow_func = "pow" + self.type.math_h_modifier
9524 elif self.type.is_int:
9525 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
9526 env.use_utility_code(
9527 int_pow_utility_code.specialize(
9528 func_name=self.pow_func,
9529 type=self.type.declaration_code(''),
9530 signed=self.type.signed and 1 or 0))
9531 elif not self.type.is_error:
9532 error(self.pos, "got unexpected types for C power operator: %s, %s" %
9533 (self.operand1.type, self.operand2.type))
9535 def calculate_result_code(self):
9536 # Work around MSVC overloading ambiguity.
9537 def typecast(operand):
9538 if self.type == operand.type:
9539 return operand.result()
9540 else:
9541 return self.type.cast_code(operand.result())
9542 return "%s(%s, %s)" % (
9543 self.pow_func,
9544 typecast(self.operand1),
9545 typecast(self.operand2))
9548 # Note: This class is temporarily "shut down" into an ineffective temp
9549 # allocation mode.
9551 # More sophisticated temp reuse was going on before, one could have a
9552 # look at adding this again after /all/ classes are converted to the
9553 # new temp scheme. (The temp juggling cannot work otherwise).
9554 class BoolBinopNode(ExprNode):
9555 # Short-circuiting boolean operation.
9557 # operator string
9558 # operand1 ExprNode
9559 # operand2 ExprNode
9561 subexprs = ['operand1', 'operand2']
9563 def infer_type(self, env):
9564 type1 = self.operand1.infer_type(env)
9565 type2 = self.operand2.infer_type(env)
9566 return PyrexTypes.independent_spanning_type(type1, type2)
9568 def may_be_none(self):
9569 if self.operator == 'or':
9570 return self.operand2.may_be_none()
9571 else:
9572 return self.operand1.may_be_none() or self.operand2.may_be_none()
9574 def calculate_constant_result(self):
9575 if self.operator == 'and':
9576 self.constant_result = \
9577 self.operand1.constant_result and \
9578 self.operand2.constant_result
9579 else:
9580 self.constant_result = \
9581 self.operand1.constant_result or \
9582 self.operand2.constant_result
9584 def compile_time_value(self, denv):
9585 if self.operator == 'and':
9586 return self.operand1.compile_time_value(denv) \
9587 and self.operand2.compile_time_value(denv)
9588 else:
9589 return self.operand1.compile_time_value(denv) \
9590 or self.operand2.compile_time_value(denv)
9592 def coerce_to_boolean(self, env):
9593 return BoolBinopNode(
9594 self.pos,
9595 operator = self.operator,
9596 operand1 = self.operand1.coerce_to_boolean(env),
9597 operand2 = self.operand2.coerce_to_boolean(env),
9598 type = PyrexTypes.c_bint_type,
9599 is_temp = self.is_temp)
9601 def analyse_types(self, env):
9602 self.operand1 = self.operand1.analyse_types(env)
9603 self.operand2 = self.operand2.analyse_types(env)
9604 self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
9605 self.operand1 = self.operand1.coerce_to(self.type, env)
9606 self.operand2 = self.operand2.coerce_to(self.type, env)
9608 # For what we're about to do, it's vital that
9609 # both operands be temp nodes.
9610 self.operand1 = self.operand1.coerce_to_simple(env)
9611 self.operand2 = self.operand2.coerce_to_simple(env)
9612 self.is_temp = 1
9613 return self
9615 gil_message = "Truth-testing Python object"
9617 def check_const(self):
9618 return self.operand1.check_const() and self.operand2.check_const()
9620 def generate_evaluation_code(self, code):
9621 code.mark_pos(self.pos)
9622 self.operand1.generate_evaluation_code(code)
9623 test_result, uses_temp = self.generate_operand1_test(code)
9624 if self.operator == 'and':
9625 sense = ""
9626 else:
9627 sense = "!"
9628 code.putln(
9629 "if (%s%s) {" % (
9630 sense,
9631 test_result))
9632 if uses_temp:
9633 code.funcstate.release_temp(test_result)
9634 self.operand1.generate_disposal_code(code)
9635 self.operand2.generate_evaluation_code(code)
9636 self.allocate_temp_result(code)
9637 self.operand2.make_owned_reference(code)
9638 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
9639 self.operand2.generate_post_assignment_code(code)
9640 self.operand2.free_temps(code)
9641 code.putln("} else {")
9642 self.operand1.make_owned_reference(code)
9643 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
9644 self.operand1.generate_post_assignment_code(code)
9645 self.operand1.free_temps(code)
9646 code.putln("}")
9648 def generate_operand1_test(self, code):
9649 # Generate code to test the truth of the first operand.
9650 if self.type.is_pyobject:
9651 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
9652 manage_ref=False)
9653 code.putln(
9654 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
9655 test_result,
9656 self.operand1.py_result(),
9657 code.error_goto_if_neg(test_result, self.pos)))
9658 else:
9659 test_result = self.operand1.result()
9660 return (test_result, self.type.is_pyobject)
9663 class CondExprNode(ExprNode):
9664 # Short-circuiting conditional expression.
9666 # test ExprNode
9667 # true_val ExprNode
9668 # false_val ExprNode
9670 true_val = None
9671 false_val = None
9673 subexprs = ['test', 'true_val', 'false_val']
9675 def type_dependencies(self, env):
9676 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
9678 def infer_type(self, env):
9679 return PyrexTypes.independent_spanning_type(
9680 self.true_val.infer_type(env),
9681 self.false_val.infer_type(env))
9683 def calculate_constant_result(self):
9684 if self.test.constant_result:
9685 self.constant_result = self.true_val.constant_result
9686 else:
9687 self.constant_result = self.false_val.constant_result
9689 def analyse_types(self, env):
9690 self.test = self.test.analyse_types(env).coerce_to_boolean(env)
9691 self.true_val = self.true_val.analyse_types(env)
9692 self.false_val = self.false_val.analyse_types(env)
9693 self.is_temp = 1
9694 return self.analyse_result_type(env)
9696 def analyse_result_type(self, env):
9697 self.type = PyrexTypes.independent_spanning_type(
9698 self.true_val.type, self.false_val.type)
9699 if self.type.is_pyobject:
9700 self.result_ctype = py_object_type
9701 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
9702 self.true_val = self.true_val.coerce_to(self.type, env)
9703 self.false_val = self.false_val.coerce_to(self.type, env)
9704 if self.type == PyrexTypes.error_type:
9705 self.type_error()
9706 return self
9708 def coerce_to(self, dst_type, env):
9709 self.true_val = self.true_val.coerce_to(dst_type, env)
9710 self.false_val = self.false_val.coerce_to(dst_type, env)
9711 self.result_ctype = None
9712 return self.analyse_result_type(env)
9714 def type_error(self):
9715 if not (self.true_val.type.is_error or self.false_val.type.is_error):
9716 error(self.pos, "Incompatible types in conditional expression (%s; %s)" %
9717 (self.true_val.type, self.false_val.type))
9718 self.type = PyrexTypes.error_type
9720 def check_const(self):
9721 return (self.test.check_const()
9722 and self.true_val.check_const()
9723 and self.false_val.check_const())
9725 def generate_evaluation_code(self, code):
9726 # Because subexprs may not be evaluated we can use a more optimal
9727 # subexpr allocation strategy than the default, so override evaluation_code.
9729 code.mark_pos(self.pos)
9730 self.allocate_temp_result(code)
9731 self.test.generate_evaluation_code(code)
9732 code.putln("if (%s) {" % self.test.result() )
9733 self.eval_and_get(code, self.true_val)
9734 code.putln("} else {")
9735 self.eval_and_get(code, self.false_val)
9736 code.putln("}")
9737 self.test.generate_disposal_code(code)
9738 self.test.free_temps(code)
9740 def eval_and_get(self, code, expr):
9741 expr.generate_evaluation_code(code)
9742 expr.make_owned_reference(code)
9743 code.putln('%s = %s;' % (self.result(), expr.result_as(self.ctype())))
9744 expr.generate_post_assignment_code(code)
9745 expr.free_temps(code)
9747 richcmp_constants = {
9748 "<" : "Py_LT",
9749 "<=": "Py_LE",
9750 "==": "Py_EQ",
9751 "!=": "Py_NE",
9752 "<>": "Py_NE",
9753 ">" : "Py_GT",
9754 ">=": "Py_GE",
9755 # the following are faked by special compare functions
9756 "in" : "Py_EQ",
9757 "not_in": "Py_NE",
9760 class CmpNode(object):
9761 # Mixin class containing code common to PrimaryCmpNodes
9762 # and CascadedCmpNodes.
9764 special_bool_cmp_function = None
9765 special_bool_cmp_utility_code = None
9767 def infer_type(self, env):
9768 # TODO: Actually implement this (after merging with -unstable).
9769 return py_object_type
9771 def calculate_cascaded_constant_result(self, operand1_result):
9772 func = compile_time_binary_operators[self.operator]
9773 operand2_result = self.operand2.constant_result
9774 if (isinstance(operand1_result, (bytes, unicode)) and
9775 isinstance(operand2_result, (bytes, unicode)) and
9776 type(operand1_result) != type(operand2_result)):
9777 # string comparison of different types isn't portable
9778 return
9780 if self.operator in ('in', 'not_in'):
9781 if isinstance(self.operand2, (ListNode, TupleNode, SetNode)):
9782 if not self.operand2.args:
9783 self.constant_result = self.operator == 'not_in'
9784 return
9785 elif isinstance(self.operand2, ListNode) and not self.cascade:
9786 # tuples are more efficient to store than lists
9787 self.operand2 = self.operand2.as_tuple()
9788 elif isinstance(self.operand2, DictNode):
9789 if not self.operand2.key_value_pairs:
9790 self.constant_result = self.operator == 'not_in'
9791 return
9793 self.constant_result = func(operand1_result, operand2_result)
9795 def cascaded_compile_time_value(self, operand1, denv):
9796 func = get_compile_time_binop(self)
9797 operand2 = self.operand2.compile_time_value(denv)
9798 try:
9799 result = func(operand1, operand2)
9800 except Exception, e:
9801 self.compile_time_value_error(e)
9802 result = None
9803 if result:
9804 cascade = self.cascade
9805 if cascade:
9806 result = result and cascade.cascaded_compile_time_value(operand2, denv)
9807 return result
9809 def is_cpp_comparison(self):
9810 return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class
9812 def find_common_int_type(self, env, op, operand1, operand2):
9813 # type1 != type2 and at least one of the types is not a C int
9814 type1 = operand1.type
9815 type2 = operand2.type
9816 type1_can_be_int = False
9817 type2_can_be_int = False
9819 if operand1.is_string_literal and operand1.can_coerce_to_char_literal():
9820 type1_can_be_int = True
9821 if operand2.is_string_literal and operand2.can_coerce_to_char_literal():
9822 type2_can_be_int = True
9824 if type1.is_int:
9825 if type2_can_be_int:
9826 return type1
9827 elif type2.is_int:
9828 if type1_can_be_int:
9829 return type2
9830 elif type1_can_be_int:
9831 if type2_can_be_int:
9832 if Builtin.unicode_type in (type1, type2):
9833 return PyrexTypes.c_py_ucs4_type
9834 else:
9835 return PyrexTypes.c_uchar_type
9837 return None
9839 def find_common_type(self, env, op, operand1, common_type=None):
9840 operand2 = self.operand2
9841 type1 = operand1.type
9842 type2 = operand2.type
9844 new_common_type = None
9846 # catch general errors
9847 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
9848 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
9849 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
9850 new_common_type = error_type
9852 # try to use numeric comparisons where possible
9853 elif type1.is_complex or type2.is_complex:
9854 if op not in ('==', '!=') \
9855 and (type1.is_complex or type1.is_numeric) \
9856 and (type2.is_complex or type2.is_numeric):
9857 error(self.pos, "complex types are unordered")
9858 new_common_type = error_type
9859 elif type1.is_pyobject:
9860 new_common_type = type1
9861 elif type2.is_pyobject:
9862 new_common_type = type2
9863 else:
9864 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
9865 elif type1.is_numeric and type2.is_numeric:
9866 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
9867 elif common_type is None or not common_type.is_pyobject:
9868 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
9870 if new_common_type is None:
9871 # fall back to generic type compatibility tests
9872 if type1 == type2:
9873 new_common_type = type1
9874 elif type1.is_pyobject or type2.is_pyobject:
9875 if type2.is_numeric or type2.is_string:
9876 if operand2.check_for_coercion_error(type1, env):
9877 new_common_type = error_type
9878 else:
9879 new_common_type = py_object_type
9880 elif type1.is_numeric or type1.is_string:
9881 if operand1.check_for_coercion_error(type2, env):
9882 new_common_type = error_type
9883 else:
9884 new_common_type = py_object_type
9885 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
9886 new_common_type = py_object_type
9887 else:
9888 # one Python type and one non-Python type, not assignable
9889 self.invalid_types_error(operand1, op, operand2)
9890 new_common_type = error_type
9891 elif type1.assignable_from(type2):
9892 new_common_type = type1
9893 elif type2.assignable_from(type1):
9894 new_common_type = type2
9895 else:
9896 # C types that we couldn't handle up to here are an error
9897 self.invalid_types_error(operand1, op, operand2)
9898 new_common_type = error_type
9900 if new_common_type.is_string and (isinstance(operand1, BytesNode) or
9901 isinstance(operand2, BytesNode)):
9902 # special case when comparing char* to bytes literal: must
9903 # compare string values!
9904 new_common_type = bytes_type
9906 # recursively merge types
9907 if common_type is None or new_common_type.is_error:
9908 common_type = new_common_type
9909 else:
9910 # we could do a lot better by splitting the comparison
9911 # into a non-Python part and a Python part, but this is
9912 # safer for now
9913 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
9915 if self.cascade:
9916 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
9918 return common_type
9920 def invalid_types_error(self, operand1, op, operand2):
9921 error(self.pos, "Invalid types for '%s' (%s, %s)" %
9922 (op, operand1.type, operand2.type))
9924 def is_python_comparison(self):
9925 return (not self.is_ptr_contains()
9926 and not self.is_c_string_contains()
9927 and (self.has_python_operands()
9928 or (self.cascade and self.cascade.is_python_comparison())
9929 or self.operator in ('in', 'not_in')))
9931 def coerce_operands_to(self, dst_type, env):
9932 operand2 = self.operand2
9933 if operand2.type != dst_type:
9934 self.operand2 = operand2.coerce_to(dst_type, env)
9935 if self.cascade:
9936 self.cascade.coerce_operands_to(dst_type, env)
9938 def is_python_result(self):
9939 return ((self.has_python_operands() and
9940 self.special_bool_cmp_function is None and
9941 self.operator not in ('is', 'is_not', 'in', 'not_in') and
9942 not self.is_c_string_contains() and
9943 not self.is_ptr_contains())
9944 or (self.cascade and self.cascade.is_python_result()))
9946 def is_c_string_contains(self):
9947 return self.operator in ('in', 'not_in') and \
9948 ((self.operand1.type.is_int
9949 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
9950 (self.operand1.type.is_unicode_char
9951 and self.operand2.type is unicode_type))
9953 def is_ptr_contains(self):
9954 if self.operator in ('in', 'not_in'):
9955 container_type = self.operand2.type
9956 return (container_type.is_ptr or container_type.is_array) \
9957 and not container_type.is_string
9959 def find_special_bool_compare_function(self, env, operand1, result_is_bool=False):
9960 # note: currently operand1 must get coerced to a Python object if we succeed here!
9961 if self.operator in ('==', '!='):
9962 type1, type2 = operand1.type, self.operand2.type
9963 if result_is_bool or (type1.is_builtin_type and type2.is_builtin_type):
9964 if type1 is Builtin.unicode_type or type2 is Builtin.unicode_type:
9965 self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c")
9966 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals"
9967 return True
9968 elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type:
9969 self.special_bool_cmp_utility_code = UtilityCode.load_cached("BytesEquals", "StringTools.c")
9970 self.special_bool_cmp_function = "__Pyx_PyBytes_Equals"
9971 return True
9972 elif type1 is Builtin.basestring_type or type2 is Builtin.basestring_type:
9973 self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c")
9974 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals"
9975 return True
9976 elif type1 is Builtin.str_type or type2 is Builtin.str_type:
9977 self.special_bool_cmp_utility_code = UtilityCode.load_cached("StrEquals", "StringTools.c")
9978 self.special_bool_cmp_function = "__Pyx_PyString_Equals"
9979 return True
9980 elif self.operator in ('in', 'not_in'):
9981 if self.operand2.type is Builtin.dict_type:
9982 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
9983 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyDictContains", "ObjectHandling.c")
9984 self.special_bool_cmp_function = "__Pyx_PyDict_Contains"
9985 return True
9986 elif self.operand2.type is Builtin.unicode_type:
9987 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
9988 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyUnicodeContains", "StringTools.c")
9989 self.special_bool_cmp_function = "__Pyx_PyUnicode_Contains"
9990 return True
9991 else:
9992 if not self.operand2.type.is_pyobject:
9993 self.operand2 = self.operand2.coerce_to_pyobject(env)
9994 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySequenceContains", "ObjectHandling.c")
9995 self.special_bool_cmp_function = "__Pyx_PySequence_Contains"
9996 return True
9997 return False
9999 def generate_operation_code(self, code, result_code,
10000 operand1, op , operand2):
10001 if self.type.is_pyobject:
10002 error_clause = code.error_goto_if_null
10003 got_ref = "__Pyx_XGOTREF(%s); " % result_code
10004 if self.special_bool_cmp_function:
10005 code.globalstate.use_utility_code(
10006 UtilityCode.load_cached("PyBoolOrNullFromLong", "ObjectHandling.c"))
10007 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
10008 else:
10009 coerce_result = "__Pyx_PyBool_FromLong"
10010 else:
10011 error_clause = code.error_goto_if_neg
10012 got_ref = ""
10013 coerce_result = ""
10015 if self.special_bool_cmp_function:
10016 if operand1.type.is_pyobject:
10017 result1 = operand1.py_result()
10018 else:
10019 result1 = operand1.result()
10020 if operand2.type.is_pyobject:
10021 result2 = operand2.py_result()
10022 else:
10023 result2 = operand2.result()
10024 if self.special_bool_cmp_utility_code:
10025 code.globalstate.use_utility_code(self.special_bool_cmp_utility_code)
10026 code.putln(
10027 "%s = %s(%s(%s, %s, %s)); %s%s" % (
10028 result_code,
10029 coerce_result,
10030 self.special_bool_cmp_function,
10031 result1, result2, richcmp_constants[op],
10032 got_ref,
10033 error_clause(result_code, self.pos)))
10035 elif operand1.type.is_pyobject and op not in ('is', 'is_not'):
10036 assert op not in ('in', 'not_in'), op
10037 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s%s" % (
10038 result_code,
10039 operand1.py_result(),
10040 operand2.py_result(),
10041 richcmp_constants[op],
10042 got_ref,
10043 error_clause(result_code, self.pos)))
10045 elif operand1.type.is_complex:
10046 code.putln("%s = %s(%s%s(%s, %s));" % (
10047 result_code,
10048 coerce_result,
10049 op == "!=" and "!" or "",
10050 operand1.type.unary_op('eq'),
10051 operand1.result(),
10052 operand2.result()))
10054 else:
10055 type1 = operand1.type
10056 type2 = operand2.type
10057 if (type1.is_extension_type or type2.is_extension_type) \
10058 and not type1.same_as(type2):
10059 common_type = py_object_type
10060 elif type1.is_numeric:
10061 common_type = PyrexTypes.widest_numeric_type(type1, type2)
10062 else:
10063 common_type = type1
10064 code1 = operand1.result_as(common_type)
10065 code2 = operand2.result_as(common_type)
10066 code.putln("%s = %s(%s %s %s);" % (
10067 result_code,
10068 coerce_result,
10069 code1,
10070 self.c_operator(op),
10071 code2))
10073 def c_operator(self, op):
10074 if op == 'is':
10075 return "=="
10076 elif op == 'is_not':
10077 return "!="
10078 else:
10079 return op
10081 class PrimaryCmpNode(ExprNode, CmpNode):
10082 # Non-cascaded comparison or first comparison of
10083 # a cascaded sequence.
10085 # operator string
10086 # operand1 ExprNode
10087 # operand2 ExprNode
10088 # cascade CascadedCmpNode
10090 # We don't use the subexprs mechanism, because
10091 # things here are too complicated for it to handle.
10092 # Instead, we override all the framework methods
10093 # which use it.
10095 child_attrs = ['operand1', 'operand2', 'coerced_operand2', 'cascade']
10097 cascade = None
10098 coerced_operand2 = None
10099 is_memslice_nonecheck = False
10101 def infer_type(self, env):
10102 # TODO: Actually implement this (after merging with -unstable).
10103 return py_object_type
10105 def type_dependencies(self, env):
10106 return ()
10108 def calculate_constant_result(self):
10109 assert not self.cascade
10110 self.calculate_cascaded_constant_result(self.operand1.constant_result)
10112 def compile_time_value(self, denv):
10113 operand1 = self.operand1.compile_time_value(denv)
10114 return self.cascaded_compile_time_value(operand1, denv)
10116 def analyse_types(self, env):
10117 self.operand1 = self.operand1.analyse_types(env)
10118 self.operand2 = self.operand2.analyse_types(env)
10119 if self.is_cpp_comparison():
10120 self.analyse_cpp_comparison(env)
10121 if self.cascade:
10122 error(self.pos, "Cascading comparison not yet supported for cpp types.")
10123 return self
10125 if self.analyse_memoryviewslice_comparison(env):
10126 return self
10128 if self.cascade:
10129 self.cascade = self.cascade.analyse_types(env)
10131 if self.operator in ('in', 'not_in'):
10132 if self.is_c_string_contains():
10133 self.is_pycmp = False
10134 common_type = None
10135 if self.cascade:
10136 error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
10137 return self
10138 if self.operand2.type is unicode_type:
10139 env.use_utility_code(UtilityCode.load_cached("PyUCS4InUnicode", "StringTools.c"))
10140 else:
10141 if self.operand1.type is PyrexTypes.c_uchar_type:
10142 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env)
10143 if self.operand2.type is not bytes_type:
10144 self.operand2 = self.operand2.coerce_to(bytes_type, env)
10145 env.use_utility_code(UtilityCode.load_cached("BytesContains", "StringTools.c"))
10146 self.operand2 = self.operand2.as_none_safe_node(
10147 "argument of type 'NoneType' is not iterable")
10148 elif self.is_ptr_contains():
10149 if self.cascade:
10150 error(self.pos, "Cascading comparison not supported for 'val in sliced pointer'.")
10151 self.type = PyrexTypes.c_bint_type
10152 # Will be transformed by IterationTransform
10153 return self
10154 elif self.find_special_bool_compare_function(env, self.operand1):
10155 if not self.operand1.type.is_pyobject:
10156 self.operand1 = self.operand1.coerce_to_pyobject(env)
10157 common_type = None # if coercion needed, the method call above has already done it
10158 self.is_pycmp = False # result is bint
10159 else:
10160 common_type = py_object_type
10161 self.is_pycmp = True
10162 elif self.find_special_bool_compare_function(env, self.operand1):
10163 if not self.operand1.type.is_pyobject:
10164 self.operand1 = self.operand1.coerce_to_pyobject(env)
10165 common_type = None # if coercion needed, the method call above has already done it
10166 self.is_pycmp = False # result is bint
10167 else:
10168 common_type = self.find_common_type(env, self.operator, self.operand1)
10169 self.is_pycmp = common_type.is_pyobject
10171 if common_type is not None and not common_type.is_error:
10172 if self.operand1.type != common_type:
10173 self.operand1 = self.operand1.coerce_to(common_type, env)
10174 self.coerce_operands_to(common_type, env)
10176 if self.cascade:
10177 self.operand2 = self.operand2.coerce_to_simple(env)
10178 self.cascade.coerce_cascaded_operands_to_temp(env)
10179 operand2 = self.cascade.optimise_comparison(self.operand2, env)
10180 if operand2 is not self.operand2:
10181 self.coerced_operand2 = operand2
10182 if self.is_python_result():
10183 self.type = PyrexTypes.py_object_type
10184 else:
10185 self.type = PyrexTypes.c_bint_type
10186 cdr = self.cascade
10187 while cdr:
10188 cdr.type = self.type
10189 cdr = cdr.cascade
10190 if self.is_pycmp or self.cascade or self.special_bool_cmp_function:
10191 # 1) owned reference, 2) reused value, 3) potential function error return value
10192 self.is_temp = 1
10193 return self
10195 def analyse_cpp_comparison(self, env):
10196 type1 = self.operand1.type
10197 type2 = self.operand2.type
10198 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
10199 if entry is None:
10200 error(self.pos, "Invalid types for '%s' (%s, %s)" %
10201 (self.operator, type1, type2))
10202 self.type = PyrexTypes.error_type
10203 self.result_code = "<error>"
10204 return
10205 func_type = entry.type
10206 if func_type.is_ptr:
10207 func_type = func_type.base_type
10208 if len(func_type.args) == 1:
10209 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
10210 else:
10211 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
10212 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
10213 self.is_pycmp = False
10214 self.type = func_type.return_type
10216 def analyse_memoryviewslice_comparison(self, env):
10217 have_none = self.operand1.is_none or self.operand2.is_none
10218 have_slice = (self.operand1.type.is_memoryviewslice or
10219 self.operand2.type.is_memoryviewslice)
10220 ops = ('==', '!=', 'is', 'is_not')
10221 if have_slice and have_none and self.operator in ops:
10222 self.is_pycmp = False
10223 self.type = PyrexTypes.c_bint_type
10224 self.is_memslice_nonecheck = True
10225 return True
10227 return False
10229 def coerce_to_boolean(self, env):
10230 if self.is_pycmp:
10231 # coercing to bool => may allow for more efficient comparison code
10232 if self.find_special_bool_compare_function(
10233 env, self.operand1, result_is_bool=True):
10234 self.is_pycmp = False
10235 self.type = PyrexTypes.c_bint_type
10236 self.is_temp = 1
10237 if self.cascade:
10238 operand2 = self.cascade.optimise_comparison(
10239 self.operand2, env, result_is_bool=True)
10240 if operand2 is not self.operand2:
10241 self.coerced_operand2 = operand2
10242 return self
10243 # TODO: check if we can optimise parts of the cascade here
10244 return ExprNode.coerce_to_boolean(self, env)
10246 def has_python_operands(self):
10247 return (self.operand1.type.is_pyobject
10248 or self.operand2.type.is_pyobject)
10250 def check_const(self):
10251 if self.cascade:
10252 self.not_const()
10253 return False
10254 else:
10255 return self.operand1.check_const() and self.operand2.check_const()
10257 def calculate_result_code(self):
10258 if self.operand1.type.is_complex:
10259 if self.operator == "!=":
10260 negation = "!"
10261 else:
10262 negation = ""
10263 return "(%s%s(%s, %s))" % (
10264 negation,
10265 self.operand1.type.binary_op('=='),
10266 self.operand1.result(),
10267 self.operand2.result())
10268 elif self.is_c_string_contains():
10269 if self.operand2.type is unicode_type:
10270 method = "__Pyx_UnicodeContainsUCS4"
10271 else:
10272 method = "__Pyx_BytesContains"
10273 if self.operator == "not_in":
10274 negation = "!"
10275 else:
10276 negation = ""
10277 return "(%s%s(%s, %s))" % (
10278 negation,
10279 method,
10280 self.operand2.result(),
10281 self.operand1.result())
10282 else:
10283 result1 = self.operand1.result()
10284 result2 = self.operand2.result()
10285 if self.is_memslice_nonecheck:
10286 if self.operand1.type.is_memoryviewslice:
10287 result1 = "((PyObject *) %s.memview)" % result1
10288 else:
10289 result2 = "((PyObject *) %s.memview)" % result2
10291 return "(%s %s %s)" % (
10292 result1,
10293 self.c_operator(self.operator),
10294 result2)
10296 def generate_evaluation_code(self, code):
10297 self.operand1.generate_evaluation_code(code)
10298 self.operand2.generate_evaluation_code(code)
10299 if self.is_temp:
10300 self.allocate_temp_result(code)
10301 self.generate_operation_code(code, self.result(),
10302 self.operand1, self.operator, self.operand2)
10303 if self.cascade:
10304 self.cascade.generate_evaluation_code(
10305 code, self.result(), self.coerced_operand2 or self.operand2,
10306 needs_evaluation=self.coerced_operand2 is not None)
10307 self.operand1.generate_disposal_code(code)
10308 self.operand1.free_temps(code)
10309 self.operand2.generate_disposal_code(code)
10310 self.operand2.free_temps(code)
10312 def generate_subexpr_disposal_code(self, code):
10313 # If this is called, it is a non-cascaded cmp,
10314 # so only need to dispose of the two main operands.
10315 self.operand1.generate_disposal_code(code)
10316 self.operand2.generate_disposal_code(code)
10318 def free_subexpr_temps(self, code):
10319 # If this is called, it is a non-cascaded cmp,
10320 # so only need to dispose of the two main operands.
10321 self.operand1.free_temps(code)
10322 self.operand2.free_temps(code)
10324 def annotate(self, code):
10325 self.operand1.annotate(code)
10326 self.operand2.annotate(code)
10327 if self.cascade:
10328 self.cascade.annotate(code)
10331 class CascadedCmpNode(Node, CmpNode):
10332 # A CascadedCmpNode is not a complete expression node. It
10333 # hangs off the side of another comparison node, shares
10334 # its left operand with that node, and shares its result
10335 # with the PrimaryCmpNode at the head of the chain.
10337 # operator string
10338 # operand2 ExprNode
10339 # cascade CascadedCmpNode
10341 child_attrs = ['operand2', 'coerced_operand2', 'cascade']
10343 cascade = None
10344 coerced_operand2 = None
10345 constant_result = constant_value_not_set # FIXME: where to calculate this?
10347 def infer_type(self, env):
10348 # TODO: Actually implement this (after merging with -unstable).
10349 return py_object_type
10351 def type_dependencies(self, env):
10352 return ()
10354 def has_constant_result(self):
10355 return self.constant_result is not constant_value_not_set and \
10356 self.constant_result is not not_a_constant
10358 def analyse_types(self, env):
10359 self.operand2 = self.operand2.analyse_types(env)
10360 if self.cascade:
10361 self.cascade = self.cascade.analyse_types(env)
10362 return self
10364 def has_python_operands(self):
10365 return self.operand2.type.is_pyobject
10367 def optimise_comparison(self, operand1, env, result_is_bool=False):
10368 if self.find_special_bool_compare_function(env, operand1, result_is_bool):
10369 self.is_pycmp = False
10370 self.type = PyrexTypes.c_bint_type
10371 if not operand1.type.is_pyobject:
10372 operand1 = operand1.coerce_to_pyobject(env)
10373 if self.cascade:
10374 operand2 = self.cascade.optimise_comparison(self.operand2, env, result_is_bool)
10375 if operand2 is not self.operand2:
10376 self.coerced_operand2 = operand2
10377 return operand1
10379 def coerce_operands_to_pyobjects(self, env):
10380 self.operand2 = self.operand2.coerce_to_pyobject(env)
10381 if self.operand2.type is dict_type and self.operator in ('in', 'not_in'):
10382 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
10383 if self.cascade:
10384 self.cascade.coerce_operands_to_pyobjects(env)
10386 def coerce_cascaded_operands_to_temp(self, env):
10387 if self.cascade:
10388 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
10389 self.operand2 = self.operand2.coerce_to_simple(env)
10390 self.cascade.coerce_cascaded_operands_to_temp(env)
10392 def generate_evaluation_code(self, code, result, operand1, needs_evaluation=False):
10393 if self.type.is_pyobject:
10394 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
10395 code.put_decref(result, self.type)
10396 else:
10397 code.putln("if (%s) {" % result)
10398 if needs_evaluation:
10399 operand1.generate_evaluation_code(code)
10400 self.operand2.generate_evaluation_code(code)
10401 self.generate_operation_code(code, result,
10402 operand1, self.operator, self.operand2)
10403 if self.cascade:
10404 self.cascade.generate_evaluation_code(
10405 code, result, self.coerced_operand2 or self.operand2,
10406 needs_evaluation=self.coerced_operand2 is not None)
10407 if needs_evaluation:
10408 operand1.generate_disposal_code(code)
10409 operand1.free_temps(code)
10410 # Cascaded cmp result is always temp
10411 self.operand2.generate_disposal_code(code)
10412 self.operand2.free_temps(code)
10413 code.putln("}")
10415 def annotate(self, code):
10416 self.operand2.annotate(code)
10417 if self.cascade:
10418 self.cascade.annotate(code)
10421 binop_node_classes = {
10422 "or": BoolBinopNode,
10423 "and": BoolBinopNode,
10424 "|": IntBinopNode,
10425 "^": IntBinopNode,
10426 "&": IntBinopNode,
10427 "<<": IntBinopNode,
10428 ">>": IntBinopNode,
10429 "+": AddNode,
10430 "-": SubNode,
10431 "*": MulNode,
10432 "/": DivNode,
10433 "//": DivNode,
10434 "%": ModNode,
10435 "**": PowNode
10438 def binop_node(pos, operator, operand1, operand2, inplace=False):
10439 # Construct binop node of appropriate class for
10440 # given operator.
10441 return binop_node_classes[operator](pos,
10442 operator = operator,
10443 operand1 = operand1,
10444 operand2 = operand2,
10445 inplace = inplace)
10447 #-------------------------------------------------------------------
10449 # Coercion nodes
10451 # Coercion nodes are special in that they are created during
10452 # the analyse_types phase of parse tree processing.
10453 # Their __init__ methods consequently incorporate some aspects
10454 # of that phase.
10456 #-------------------------------------------------------------------
10458 class CoercionNode(ExprNode):
10459 # Abstract base class for coercion nodes.
10461 # arg ExprNode node being coerced
10463 subexprs = ['arg']
10464 constant_result = not_a_constant
10466 def __init__(self, arg):
10467 super(CoercionNode, self).__init__(arg.pos)
10468 self.arg = arg
10469 if debug_coercion:
10470 print("%s Coercing %s" % (self, self.arg))
10472 def calculate_constant_result(self):
10473 # constant folding can break type coercion, so this is disabled
10474 pass
10476 def annotate(self, code):
10477 self.arg.annotate(code)
10478 if self.arg.type != self.type:
10479 file, line, col = self.pos
10480 code.annotate((file, line, col-1), AnnotationItem(
10481 style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
10483 class CoerceToMemViewSliceNode(CoercionNode):
10485 Coerce an object to a memoryview slice. This holds a new reference in
10486 a managed temp.
10489 def __init__(self, arg, dst_type, env):
10490 assert dst_type.is_memoryviewslice
10491 assert not arg.type.is_memoryviewslice
10492 CoercionNode.__init__(self, arg)
10493 self.type = dst_type
10494 self.is_temp = 1
10495 self.env = env
10496 self.use_managed_ref = True
10497 self.arg = arg
10499 def generate_result_code(self, code):
10500 self.type.create_from_py_utility_code(self.env)
10501 code.putln("%s = %s(%s);" % (self.result(),
10502 self.type.from_py_function,
10503 self.arg.py_result()))
10505 error_cond = self.type.error_condition(self.result())
10506 code.putln(code.error_goto_if(error_cond, self.pos))
10509 class CastNode(CoercionNode):
10510 # Wrap a node in a C type cast.
10512 def __init__(self, arg, new_type):
10513 CoercionNode.__init__(self, arg)
10514 self.type = new_type
10516 def may_be_none(self):
10517 return self.arg.may_be_none()
10519 def calculate_result_code(self):
10520 return self.arg.result_as(self.type)
10522 def generate_result_code(self, code):
10523 self.arg.generate_result_code(code)
10526 class PyTypeTestNode(CoercionNode):
10527 # This node is used to check that a generic Python
10528 # object is an instance of a particular extension type.
10529 # This node borrows the result of its argument node.
10531 exact_builtin_type = True
10533 def __init__(self, arg, dst_type, env, notnone=False):
10534 # The arg is know to be a Python object, and
10535 # the dst_type is known to be an extension type.
10536 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
10537 CoercionNode.__init__(self, arg)
10538 self.type = dst_type
10539 self.result_ctype = arg.ctype()
10540 self.notnone = notnone
10542 nogil_check = Node.gil_error
10543 gil_message = "Python type test"
10545 def analyse_types(self, env):
10546 return self
10548 def may_be_none(self):
10549 if self.notnone:
10550 return False
10551 return self.arg.may_be_none()
10553 def is_simple(self):
10554 return self.arg.is_simple()
10556 def result_in_temp(self):
10557 return self.arg.result_in_temp()
10559 def is_ephemeral(self):
10560 return self.arg.is_ephemeral()
10562 def nonlocally_immutable(self):
10563 return self.arg.nonlocally_immutable()
10565 def calculate_constant_result(self):
10566 # FIXME
10567 pass
10569 def calculate_result_code(self):
10570 return self.arg.result()
10572 def generate_result_code(self, code):
10573 if self.type.typeobj_is_available():
10574 if self.type.is_builtin_type:
10575 type_test = self.type.type_test_code(
10576 self.arg.py_result(),
10577 self.notnone, exact=self.exact_builtin_type)
10578 else:
10579 type_test = self.type.type_test_code(
10580 self.arg.py_result(), self.notnone)
10581 code.globalstate.use_utility_code(
10582 UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
10583 code.putln("if (!(%s)) %s" % (
10584 type_test, code.error_goto(self.pos)))
10585 else:
10586 error(self.pos, "Cannot test type of extern C class "
10587 "without type object name specification")
10589 def generate_post_assignment_code(self, code):
10590 self.arg.generate_post_assignment_code(code)
10592 def free_temps(self, code):
10593 self.arg.free_temps(code)
10596 class NoneCheckNode(CoercionNode):
10597 # This node is used to check that a Python object is not None and
10598 # raises an appropriate exception (as specified by the creating
10599 # transform).
10601 is_nonecheck = True
10603 def __init__(self, arg, exception_type_cname, exception_message,
10604 exception_format_args):
10605 CoercionNode.__init__(self, arg)
10606 self.type = arg.type
10607 self.result_ctype = arg.ctype()
10608 self.exception_type_cname = exception_type_cname
10609 self.exception_message = exception_message
10610 self.exception_format_args = tuple(exception_format_args or ())
10612 nogil_check = None # this node only guards an operation that would fail already
10614 def analyse_types(self, env):
10615 return self
10617 def may_be_none(self):
10618 return False
10620 def is_simple(self):
10621 return self.arg.is_simple()
10623 def result_in_temp(self):
10624 return self.arg.result_in_temp()
10626 def nonlocally_immutable(self):
10627 return self.arg.nonlocally_immutable()
10629 def calculate_result_code(self):
10630 return self.arg.result()
10632 def condition(self):
10633 if self.type.is_pyobject:
10634 return self.arg.py_result()
10635 elif self.type.is_memoryviewslice:
10636 return "((PyObject *) %s.memview)" % self.arg.result()
10637 else:
10638 raise Exception("unsupported type")
10640 def put_nonecheck(self, code):
10641 code.putln(
10642 "if (unlikely(%s == Py_None)) {" % self.condition())
10644 if self.in_nogil_context:
10645 code.put_ensure_gil()
10647 escape = StringEncoding.escape_byte_string
10648 if self.exception_format_args:
10649 code.putln('PyErr_Format(%s, "%s", %s);' % (
10650 self.exception_type_cname,
10651 StringEncoding.escape_byte_string(
10652 self.exception_message.encode('UTF-8')),
10653 ', '.join([ '"%s"' % escape(str(arg).encode('UTF-8'))
10654 for arg in self.exception_format_args ])))
10655 else:
10656 code.putln('PyErr_SetString(%s, "%s");' % (
10657 self.exception_type_cname,
10658 escape(self.exception_message.encode('UTF-8'))))
10660 if self.in_nogil_context:
10661 code.put_release_ensured_gil()
10663 code.putln(code.error_goto(self.pos))
10664 code.putln("}")
10666 def generate_result_code(self, code):
10667 self.put_nonecheck(code)
10669 def generate_post_assignment_code(self, code):
10670 self.arg.generate_post_assignment_code(code)
10672 def free_temps(self, code):
10673 self.arg.free_temps(code)
10676 class CoerceToPyTypeNode(CoercionNode):
10677 # This node is used to convert a C data type
10678 # to a Python object.
10680 type = py_object_type
10681 is_temp = 1
10683 def __init__(self, arg, env, type=py_object_type):
10684 if not arg.type.create_to_py_utility_code(env):
10685 error(arg.pos, "Cannot convert '%s' to Python object" % arg.type)
10686 elif arg.type.is_complex:
10687 # special case: complex coercion is so complex that it
10688 # uses a macro ("__pyx_PyComplex_FromComplex()"), for
10689 # which the argument must be simple
10690 arg = arg.coerce_to_simple(env)
10691 CoercionNode.__init__(self, arg)
10692 if type is py_object_type:
10693 # be specific about some known types
10694 if arg.type.is_string or arg.type.is_cpp_string:
10695 self.type = default_str_type(env)
10696 elif arg.type.is_pyunicode_ptr or arg.type.is_unicode_char:
10697 self.type = unicode_type
10698 elif arg.type.is_complex:
10699 self.type = Builtin.complex_type
10700 elif arg.type.is_string or arg.type.is_cpp_string:
10701 if (type not in (bytes_type, bytearray_type)
10702 and not env.directives['c_string_encoding']):
10703 error(arg.pos,
10704 "default encoding required for conversion from '%s' to '%s'" %
10705 (arg.type, type))
10706 self.type = type
10707 else:
10708 # FIXME: check that the target type and the resulting type are compatible
10709 pass
10711 if arg.type.is_memoryviewslice:
10712 # Register utility codes at this point
10713 arg.type.get_to_py_function(env, arg)
10715 self.env = env
10717 gil_message = "Converting to Python object"
10719 def may_be_none(self):
10720 # FIXME: is this always safe?
10721 return False
10723 def coerce_to_boolean(self, env):
10724 arg_type = self.arg.type
10725 if (arg_type == PyrexTypes.c_bint_type or
10726 (arg_type.is_pyobject and arg_type.name == 'bool')):
10727 return self.arg.coerce_to_temp(env)
10728 else:
10729 return CoerceToBooleanNode(self, env)
10731 def coerce_to_integer(self, env):
10732 # If not already some C integer type, coerce to longint.
10733 if self.arg.type.is_int:
10734 return self.arg
10735 else:
10736 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
10738 def analyse_types(self, env):
10739 # The arg is always already analysed
10740 return self
10742 def generate_result_code(self, code):
10743 arg_type = self.arg.type
10744 if arg_type.is_memoryviewslice:
10745 funccall = arg_type.get_to_py_function(self.env, self.arg)
10746 else:
10747 func = arg_type.to_py_function
10748 if arg_type.is_string or arg_type.is_cpp_string:
10749 if self.type in (bytes_type, str_type, unicode_type):
10750 func = func.replace("Object", self.type.name.title())
10751 elif self.type is bytearray_type:
10752 func = func.replace("Object", "ByteArray")
10753 funccall = "%s(%s)" % (func, self.arg.result())
10755 code.putln('%s = %s; %s' % (
10756 self.result(),
10757 funccall,
10758 code.error_goto_if_null(self.result(), self.pos)))
10760 code.put_gotref(self.py_result())
10763 class CoerceIntToBytesNode(CoerceToPyTypeNode):
10764 # This node is used to convert a C int type to a Python bytes
10765 # object.
10767 is_temp = 1
10769 def __init__(self, arg, env):
10770 arg = arg.coerce_to_simple(env)
10771 CoercionNode.__init__(self, arg)
10772 self.type = Builtin.bytes_type
10774 def generate_result_code(self, code):
10775 arg = self.arg
10776 arg_result = arg.result()
10777 if arg.type not in (PyrexTypes.c_char_type,
10778 PyrexTypes.c_uchar_type,
10779 PyrexTypes.c_schar_type):
10780 if arg.type.signed:
10781 code.putln("if ((%s < 0) || (%s > 255)) {" % (
10782 arg_result, arg_result))
10783 else:
10784 code.putln("if (%s > 255) {" % arg_result)
10785 code.putln('PyErr_SetString(PyExc_OverflowError, '
10786 '"value too large to pack into a byte"); %s' % (
10787 code.error_goto(self.pos)))
10788 code.putln('}')
10789 temp = None
10790 if arg.type is not PyrexTypes.c_char_type:
10791 temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False)
10792 code.putln("%s = (char)%s;" % (temp, arg_result))
10793 arg_result = temp
10794 code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % (
10795 self.result(),
10796 arg_result,
10797 code.error_goto_if_null(self.result(), self.pos)))
10798 if temp is not None:
10799 code.funcstate.release_temp(temp)
10800 code.put_gotref(self.py_result())
10803 class CoerceFromPyTypeNode(CoercionNode):
10804 # This node is used to convert a Python object
10805 # to a C data type.
10807 def __init__(self, result_type, arg, env):
10808 CoercionNode.__init__(self, arg)
10809 self.type = result_type
10810 self.is_temp = 1
10811 if not result_type.create_from_py_utility_code(env):
10812 error(arg.pos,
10813 "Cannot convert Python object to '%s'" % result_type)
10814 if self.type.is_string or self.type.is_pyunicode_ptr:
10815 if self.arg.is_ephemeral():
10816 error(arg.pos,
10817 "Obtaining '%s' from temporary Python value" % result_type)
10818 elif self.arg.is_name and self.arg.entry and self.arg.entry.is_pyglobal:
10819 warning(arg.pos,
10820 "Obtaining '%s' from externally modifiable global Python value" % result_type,
10821 level=1)
10823 def analyse_types(self, env):
10824 # The arg is always already analysed
10825 return self
10827 def generate_result_code(self, code):
10828 function = self.type.from_py_function
10829 operand = self.arg.py_result()
10830 rhs = "%s(%s)" % (function, operand)
10831 if self.type.is_enum:
10832 rhs = typecast(self.type, c_long_type, rhs)
10833 code.putln('%s = %s; %s' % (
10834 self.result(),
10835 rhs,
10836 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
10837 if self.type.is_pyobject:
10838 code.put_gotref(self.py_result())
10840 def nogil_check(self, env):
10841 error(self.pos, "Coercion from Python not allowed without the GIL")
10844 class CoerceToBooleanNode(CoercionNode):
10845 # This node is used when a result needs to be used
10846 # in a boolean context.
10848 type = PyrexTypes.c_bint_type
10850 _special_builtins = {
10851 Builtin.list_type : 'PyList_GET_SIZE',
10852 Builtin.tuple_type : 'PyTuple_GET_SIZE',
10853 Builtin.bytes_type : 'PyBytes_GET_SIZE',
10854 Builtin.unicode_type : 'PyUnicode_GET_SIZE',
10857 def __init__(self, arg, env):
10858 CoercionNode.__init__(self, arg)
10859 if arg.type.is_pyobject:
10860 self.is_temp = 1
10862 def nogil_check(self, env):
10863 if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None:
10864 self.gil_error()
10866 gil_message = "Truth-testing Python object"
10868 def check_const(self):
10869 if self.is_temp:
10870 self.not_const()
10871 return False
10872 return self.arg.check_const()
10874 def calculate_result_code(self):
10875 return "(%s != 0)" % self.arg.result()
10877 def generate_result_code(self, code):
10878 if not self.is_temp:
10879 return
10880 test_func = self._special_builtins.get(self.arg.type)
10881 if test_func is not None:
10882 code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % (
10883 self.result(),
10884 self.arg.py_result(),
10885 test_func,
10886 self.arg.py_result()))
10887 else:
10888 code.putln(
10889 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
10890 self.result(),
10891 self.arg.py_result(),
10892 code.error_goto_if_neg(self.result(), self.pos)))
10894 class CoerceToComplexNode(CoercionNode):
10896 def __init__(self, arg, dst_type, env):
10897 if arg.type.is_complex:
10898 arg = arg.coerce_to_simple(env)
10899 self.type = dst_type
10900 CoercionNode.__init__(self, arg)
10901 dst_type.create_declaration_utility_code(env)
10903 def calculate_result_code(self):
10904 if self.arg.type.is_complex:
10905 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
10906 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
10907 else:
10908 real_part = self.arg.result()
10909 imag_part = "0"
10910 return "%s(%s, %s)" % (
10911 self.type.from_parts,
10912 real_part,
10913 imag_part)
10915 def generate_result_code(self, code):
10916 pass
10918 class CoerceToTempNode(CoercionNode):
10919 # This node is used to force the result of another node
10920 # to be stored in a temporary. It is only used if the
10921 # argument node's result is not already in a temporary.
10923 def __init__(self, arg, env):
10924 CoercionNode.__init__(self, arg)
10925 self.type = self.arg.type.as_argument_type()
10926 self.constant_result = self.arg.constant_result
10927 self.is_temp = 1
10928 if self.type.is_pyobject:
10929 self.result_ctype = py_object_type
10931 gil_message = "Creating temporary Python reference"
10933 def analyse_types(self, env):
10934 # The arg is always already analysed
10935 return self
10937 def coerce_to_boolean(self, env):
10938 self.arg = self.arg.coerce_to_boolean(env)
10939 if self.arg.is_simple():
10940 return self.arg
10941 self.type = self.arg.type
10942 self.result_ctype = self.type
10943 return self
10945 def generate_result_code(self, code):
10946 #self.arg.generate_evaluation_code(code) # Already done
10947 # by generic generate_subexpr_evaluation_code!
10948 code.putln("%s = %s;" % (
10949 self.result(), self.arg.result_as(self.ctype())))
10950 if self.use_managed_ref:
10951 if self.type.is_pyobject:
10952 code.put_incref(self.result(), self.ctype())
10953 elif self.type.is_memoryviewslice:
10954 code.put_incref_memoryviewslice(self.result(),
10955 not self.in_nogil_context)
10957 class ProxyNode(CoercionNode):
10959 A node that should not be replaced by transforms or other means,
10960 and hence can be useful to wrap the argument to a clone node
10962 MyNode -> ProxyNode -> ArgNode
10963 CloneNode -^
10966 nogil_check = None
10968 def __init__(self, arg):
10969 super(ProxyNode, self).__init__(arg)
10970 self.constant_result = arg.constant_result
10971 self._proxy_type()
10973 def analyse_expressions(self, env):
10974 self.arg = self.arg.analyse_expressions(env)
10975 self._proxy_type()
10976 return self
10978 def _proxy_type(self):
10979 if hasattr(self.arg, 'type'):
10980 self.type = self.arg.type
10981 self.result_ctype = self.arg.result_ctype
10982 if hasattr(self.arg, 'entry'):
10983 self.entry = self.arg.entry
10985 def generate_result_code(self, code):
10986 self.arg.generate_result_code(code)
10988 def result(self):
10989 return self.arg.result()
10991 def is_simple(self):
10992 return self.arg.is_simple()
10994 def may_be_none(self):
10995 return self.arg.may_be_none()
10997 def generate_evaluation_code(self, code):
10998 self.arg.generate_evaluation_code(code)
11000 def generate_result_code(self, code):
11001 self.arg.generate_result_code(code)
11003 def generate_disposal_code(self, code):
11004 self.arg.generate_disposal_code(code)
11006 def free_temps(self, code):
11007 self.arg.free_temps(code)
11009 class CloneNode(CoercionNode):
11010 # This node is employed when the result of another node needs
11011 # to be used multiple times. The argument node's result must
11012 # be in a temporary. This node "borrows" the result from the
11013 # argument node, and does not generate any evaluation or
11014 # disposal code for it. The original owner of the argument
11015 # node is responsible for doing those things.
11017 subexprs = [] # Arg is not considered a subexpr
11018 nogil_check = None
11020 def __init__(self, arg):
11021 CoercionNode.__init__(self, arg)
11022 self.constant_result = arg.constant_result
11023 if hasattr(arg, 'type'):
11024 self.type = arg.type
11025 self.result_ctype = arg.result_ctype
11026 if hasattr(arg, 'entry'):
11027 self.entry = arg.entry
11029 def result(self):
11030 return self.arg.result()
11032 def may_be_none(self):
11033 return self.arg.may_be_none()
11035 def type_dependencies(self, env):
11036 return self.arg.type_dependencies(env)
11038 def infer_type(self, env):
11039 return self.arg.infer_type(env)
11041 def analyse_types(self, env):
11042 self.type = self.arg.type
11043 self.result_ctype = self.arg.result_ctype
11044 self.is_temp = 1
11045 if hasattr(self.arg, 'entry'):
11046 self.entry = self.arg.entry
11047 return self
11049 def is_simple(self):
11050 return True # result is always in a temp (or a name)
11052 def generate_evaluation_code(self, code):
11053 pass
11055 def generate_result_code(self, code):
11056 pass
11058 def generate_disposal_code(self, code):
11059 pass
11061 def free_temps(self, code):
11062 pass
11065 class CMethodSelfCloneNode(CloneNode):
11066 # Special CloneNode for the self argument of builtin C methods
11067 # that accepts subtypes of the builtin type. This is safe only
11068 # for 'final' subtypes, as subtypes of the declared type may
11069 # override the C method.
11071 def coerce_to(self, dst_type, env):
11072 if dst_type.is_builtin_type and self.type.subtype_of(dst_type):
11073 return self
11074 return CloneNode.coerce_to(self, dst_type, env)
11077 class ModuleRefNode(ExprNode):
11078 # Simple returns the module object
11080 type = py_object_type
11081 is_temp = False
11082 subexprs = []
11084 def analyse_types(self, env):
11085 return self
11087 def may_be_none(self):
11088 return False
11090 def calculate_result_code(self):
11091 return Naming.module_cname
11093 def generate_result_code(self, code):
11094 pass
11096 class DocstringRefNode(ExprNode):
11097 # Extracts the docstring of the body element
11099 subexprs = ['body']
11100 type = py_object_type
11101 is_temp = True
11103 def __init__(self, pos, body):
11104 ExprNode.__init__(self, pos)
11105 assert body.type.is_pyobject
11106 self.body = body
11108 def analyse_types(self, env):
11109 return self
11111 def generate_result_code(self, code):
11112 code.putln('%s = __Pyx_GetAttr(%s, %s); %s' % (
11113 self.result(), self.body.result(),
11114 code.intern_identifier(StringEncoding.EncodedString("__doc__")),
11115 code.error_goto_if_null(self.result(), self.pos)))
11116 code.put_gotref(self.result())
11120 #------------------------------------------------------------------------------------
11122 # Runtime support code
11124 #------------------------------------------------------------------------------------
11126 pyerr_occurred_withgil_utility_code= UtilityCode(
11127 proto = """
11128 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */
11129 """,
11130 impl = """
11131 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) {
11132 int err;
11133 #ifdef WITH_THREAD
11134 PyGILState_STATE _save = PyGILState_Ensure();
11135 #endif
11136 err = !!PyErr_Occurred();
11137 #ifdef WITH_THREAD
11138 PyGILState_Release(_save);
11139 #endif
11140 return err;
11145 #------------------------------------------------------------------------------------
11147 raise_unbound_local_error_utility_code = UtilityCode(
11148 proto = """
11149 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);
11150 """,
11151 impl = """
11152 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) {
11153 PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname);
11155 """)
11157 raise_closure_name_error_utility_code = UtilityCode(
11158 proto = """
11159 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname);
11160 """,
11161 impl = """
11162 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) {
11163 PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname);
11165 """)
11167 # Don't inline the function, it should really never be called in production
11168 raise_unbound_memoryview_utility_code_nogil = UtilityCode(
11169 proto = """
11170 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname);
11171 """,
11172 impl = """
11173 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) {
11174 #ifdef WITH_THREAD
11175 PyGILState_STATE gilstate = PyGILState_Ensure();
11176 #endif
11177 __Pyx_RaiseUnboundLocalError(varname);
11178 #ifdef WITH_THREAD
11179 PyGILState_Release(gilstate);
11180 #endif
11182 """,
11183 requires = [raise_unbound_local_error_utility_code])
11185 #------------------------------------------------------------------------------------
11187 raise_too_many_values_to_unpack = UtilityCode.load_cached("RaiseTooManyValuesToUnpack", "ObjectHandling.c")
11188 raise_need_more_values_to_unpack = UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c")
11189 tuple_unpacking_error_code = UtilityCode.load_cached("UnpackTupleError", "ObjectHandling.c")
11191 #------------------------------------------------------------------------------------
11193 int_pow_utility_code = UtilityCode(
11194 proto="""
11195 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
11196 """,
11197 impl="""
11198 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
11199 %(type)s t = b;
11200 switch (e) {
11201 case 3:
11202 t *= b;
11203 case 2:
11204 t *= b;
11205 case 1:
11206 return t;
11207 case 0:
11208 return 1;
11210 #if %(signed)s
11211 if (unlikely(e<0)) return 0;
11212 #endif
11213 t = 1;
11214 while (likely(e)) {
11215 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
11216 b *= b;
11217 e >>= 1;
11219 return t;
11221 """)
11223 # ------------------------------ Division ------------------------------------
11225 div_int_utility_code = UtilityCode(
11226 proto="""
11227 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
11228 """,
11229 impl="""
11230 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
11231 %(type)s q = a / b;
11232 %(type)s r = a - q*b;
11233 q -= ((r != 0) & ((r ^ b) < 0));
11234 return q;
11236 """)
11238 mod_int_utility_code = UtilityCode(
11239 proto="""
11240 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
11241 """,
11242 impl="""
11243 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
11244 %(type)s r = a %% b;
11245 r += ((r != 0) & ((r ^ b) < 0)) * b;
11246 return r;
11248 """)
11250 mod_float_utility_code = UtilityCode(
11251 proto="""
11252 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
11253 """,
11254 impl="""
11255 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
11256 %(type)s r = fmod%(math_h_modifier)s(a, b);
11257 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
11258 return r;
11260 """)
11262 cdivision_warning_utility_code = UtilityCode(
11263 proto="""
11264 static int __Pyx_cdivision_warning(const char *, int); /* proto */
11265 """,
11266 impl="""
11267 static int __Pyx_cdivision_warning(const char *filename, int lineno) {
11268 #if CYTHON_COMPILING_IN_PYPY
11269 filename++; // avoid compiler warnings
11270 lineno++;
11271 return PyErr_Warn(PyExc_RuntimeWarning,
11272 "division with oppositely signed operands, C and Python semantics differ");
11273 #else
11274 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
11275 "division with oppositely signed operands, C and Python semantics differ",
11276 filename,
11277 lineno,
11278 __Pyx_MODULE_NAME,
11279 NULL);
11280 #endif
11282 """)
11284 # from intobject.c
11285 division_overflow_test_code = UtilityCode(
11286 proto="""
11287 #define UNARY_NEG_WOULD_OVERFLOW(x) \
11288 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
11289 """)