Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 2802:df9b7285ec6a
implement #470: non-dicts as **kwargs
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Thu Jan 14 08:36:13 2010 +0100 (2 years ago) |
| parents | 0c48cba30316 |
| children | 5d1ea5364347 |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
7 from Errors import error, warning, warn_once, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Code import UtilityCode
10 import StringEncoding
11 import Naming
12 import Nodes
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, \
17 unicode_type, str_type, bytes_type, type_type
18 import Builtin
19 import Symtab
20 import Options
21 from Annotate import AnnotationItem
23 from Cython.Debugging import print_call_chain
24 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
25 debug_coercion
27 try:
28 set
29 except NameError:
30 from sets import Set as set
32 class NotConstant(object): pass # just for the name
33 not_a_constant = NotConstant()
34 constant_value_not_set = object()
36 # error messages when coercing from key[0] to key[1]
37 find_coercion_error = {
38 # string related errors
39 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
40 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
41 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects do not support coercion to C types.",
42 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
43 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
44 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
45 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
46 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
47 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
48 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
49 }.get
52 class ExprNode(Node):
53 # subexprs [string] Class var holding names of subexpr node attrs
54 # type PyrexType Type of the result
55 # result_code string Code fragment
56 # result_ctype string C type of result_code if different from type
57 # is_temp boolean Result is in a temporary variable
58 # is_sequence_constructor
59 # boolean Is a list or tuple constructor expression
60 # is_starred boolean Is a starred expression (e.g. '*a')
61 # saved_subexpr_nodes
62 # [ExprNode or [ExprNode or None] or None]
63 # Cached result of subexpr_nodes()
64 # use_managed_ref boolean use ref-counted temps/assignments/etc.
66 result_ctype = None
67 type = None
68 temp_code = None
69 old_temp = None # error checker for multiple frees etc.
70 use_managed_ref = True # can be set by optimisation transforms
72 # The Analyse Expressions phase for expressions is split
73 # into two sub-phases:
74 #
75 # Analyse Types
76 # Determines the result type of the expression based
77 # on the types of its sub-expressions, and inserts
78 # coercion nodes into the expression tree where needed.
79 # Marks nodes which will need to have temporary variables
80 # allocated.
81 #
82 # Allocate Temps
83 # Allocates temporary variables where needed, and fills
84 # in the result_code field of each node.
85 #
86 # ExprNode provides some convenience routines which
87 # perform both of the above phases. These should only
88 # be called from statement nodes, and only when no
89 # coercion nodes need to be added around the expression
90 # being analysed. In that case, the above two phases
91 # should be invoked separately.
92 #
93 # Framework code in ExprNode provides much of the common
94 # processing for the various phases. It makes use of the
95 # 'subexprs' class attribute of ExprNodes, which should
96 # contain a list of the names of attributes which can
97 # hold sub-nodes or sequences of sub-nodes.
98 #
99 # The framework makes use of a number of abstract methods.
100 # Their responsibilities are as follows.
101 #
102 # Declaration Analysis phase
103 #
104 # analyse_target_declaration
105 # Called during the Analyse Declarations phase to analyse
106 # the LHS of an assignment or argument of a del statement.
107 # Nodes which cannot be the LHS of an assignment need not
108 # implement it.
109 #
110 # Expression Analysis phase
111 #
112 # analyse_types
113 # - Call analyse_types on all sub-expressions.
114 # - Check operand types, and wrap coercion nodes around
115 # sub-expressions where needed.
116 # - Set the type of this node.
117 # - If a temporary variable will be required for the
118 # result, set the is_temp flag of this node.
119 #
120 # analyse_target_types
121 # Called during the Analyse Types phase to analyse
122 # the LHS of an assignment or argument of a del
123 # statement. Similar responsibilities to analyse_types.
124 #
125 # target_code
126 # Called by the default implementation of allocate_target_temps.
127 # Should return a C lvalue for assigning to the node. The default
128 # implementation calls calculate_result_code.
129 #
130 # check_const
131 # - Check that this node and its subnodes form a
132 # legal constant expression. If so, do nothing,
133 # otherwise call not_const.
134 #
135 # The default implementation of check_const
136 # assumes that the expression is not constant.
137 #
138 # check_const_addr
139 # - Same as check_const, except check that the
140 # expression is a C lvalue whose address is
141 # constant. Otherwise, call addr_not_const.
142 #
143 # The default implementation of calc_const_addr
144 # assumes that the expression is not a constant
145 # lvalue.
146 #
147 # Code Generation phase
148 #
149 # generate_evaluation_code
150 # - Call generate_evaluation_code for sub-expressions.
151 # - Perform the functions of generate_result_code
152 # (see below).
153 # - If result is temporary, call generate_disposal_code
154 # on all sub-expressions.
155 #
156 # A default implementation of generate_evaluation_code
157 # is provided which uses the following abstract methods:
158 #
159 # generate_result_code
160 # - Generate any C statements necessary to calculate
161 # the result of this node from the results of its
162 # sub-expressions.
163 #
164 # calculate_result_code
165 # - Should return a C code fragment evaluating to the
166 # result. This is only called when the result is not
167 # a temporary.
168 #
169 # generate_assignment_code
170 # Called on the LHS of an assignment.
171 # - Call generate_evaluation_code for sub-expressions.
172 # - Generate code to perform the assignment.
173 # - If the assignment absorbed a reference, call
174 # generate_post_assignment_code on the RHS,
175 # otherwise call generate_disposal_code on it.
176 #
177 # generate_deletion_code
178 # Called on an argument of a del statement.
179 # - Call generate_evaluation_code for sub-expressions.
180 # - Generate code to perform the deletion.
181 # - Call generate_disposal_code on all sub-expressions.
182 #
183 #
185 is_sequence_constructor = 0
186 is_attribute = 0
188 saved_subexpr_nodes = None
189 is_temp = 0
190 is_target = 0
191 is_starred = 0
193 constant_result = constant_value_not_set
195 try:
196 _get_child_attrs = operator.attrgetter('subexprs')
197 except AttributeError:
198 # Python 2.3
199 def _get_child_attrs(self):
200 return self.subexprs
201 child_attrs = property(fget=_get_child_attrs)
203 def not_implemented(self, method_name):
204 print_call_chain(method_name, "not implemented") ###
205 raise InternalError(
206 "%s.%s not implemented" %
207 (self.__class__.__name__, method_name))
209 def is_lvalue(self):
210 return 0
212 def is_ephemeral(self):
213 # An ephemeral node is one whose result is in
214 # a Python temporary and we suspect there are no
215 # other references to it. Certain operations are
216 # disallowed on such values, since they are
217 # likely to result in a dangling pointer.
218 return self.type.is_pyobject and self.is_temp
220 def subexpr_nodes(self):
221 # Extract a list of subexpression nodes based
222 # on the contents of the subexprs class attribute.
223 nodes = []
224 for name in self.subexprs:
225 item = getattr(self, name)
226 if item is not None:
227 if type(item) is list:
228 nodes.extend(item)
229 else:
230 nodes.append(item)
231 return nodes
233 def result(self):
234 if self.is_temp:
235 return self.temp_code
236 else:
237 return self.calculate_result_code()
239 def result_as(self, type = None):
240 # Return the result code cast to the specified C type.
241 return typecast(type, self.ctype(), self.result())
243 def py_result(self):
244 # Return the result code cast to PyObject *.
245 return self.result_as(py_object_type)
247 def ctype(self):
248 # Return the native C type of the result (i.e. the
249 # C type of the result_code expression).
250 return self.result_ctype or self.type
252 def get_constant_c_result_code(self):
253 # Return the constant value of this node as a result code
254 # string, or None if the node is not constant. This method
255 # can be called when the constant result code is required
256 # before the code generation phase.
257 #
258 # The return value is a string that can represent a simple C
259 # value, a constant C name or a constant C expression. If the
260 # node type depends on Python code, this must return None.
261 return None
263 def calculate_constant_result(self):
264 # Calculate the constant compile time result value of this
265 # expression and store it in ``self.constant_result``. Does
266 # nothing by default, thus leaving ``self.constant_result``
267 # unknown. If valid, the result can be an arbitrary Python
268 # value.
269 #
270 # This must only be called when it is assured that all
271 # sub-expressions have a valid constant_result value. The
272 # ConstantFolding transform will do this.
273 pass
275 def compile_time_value(self, denv):
276 # Return value of compile-time expression, or report error.
277 error(self.pos, "Invalid compile-time expression")
279 def compile_time_value_error(self, e):
280 error(self.pos, "Error in compile-time expression: %s: %s" % (
281 e.__class__.__name__, e))
283 # ------------- Declaration Analysis ----------------
285 def analyse_target_declaration(self, env):
286 error(self.pos, "Cannot assign to or delete this")
288 # ------------- Expression Analysis ----------------
290 def analyse_const_expression(self, env):
291 # Called during the analyse_declarations phase of a
292 # constant expression. Analyses the expression's type,
293 # checks whether it is a legal const expression,
294 # and determines its value.
295 self.analyse_types(env)
296 return self.check_const()
298 def analyse_expressions(self, env):
299 # Convenience routine performing both the Type
300 # Analysis and Temp Allocation phases for a whole
301 # expression.
302 self.analyse_types(env)
304 def analyse_target_expression(self, env, rhs):
305 # Convenience routine performing both the Type
306 # Analysis and Temp Allocation phases for the LHS of
307 # an assignment.
308 self.analyse_target_types(env)
310 def analyse_boolean_expression(self, env):
311 # Analyse expression and coerce to a boolean.
312 self.analyse_types(env)
313 bool = self.coerce_to_boolean(env)
314 return bool
316 def analyse_temp_boolean_expression(self, env):
317 # Analyse boolean expression and coerce result into
318 # a temporary. This is used when a branch is to be
319 # performed on the result and we won't have an
320 # opportunity to ensure disposal code is executed
321 # afterwards. By forcing the result into a temporary,
322 # we ensure that all disposal has been done by the
323 # time we get the result.
324 self.analyse_types(env)
325 bool = self.coerce_to_boolean(env)
326 temp_bool = bool.coerce_to_temp(env)
327 return temp_bool
329 # --------------- Type Inference -----------------
331 def type_dependencies(self, env):
332 # Returns the list of entries whose types must be determined
333 # before the type of self can be infered.
334 if hasattr(self, 'type') and self.type is not None:
335 return ()
336 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
338 def infer_type(self, env):
339 # Attempt to deduce the type of self.
340 # Differs from analyse_types as it avoids unnecessary
341 # analysis of subexpressions, but can assume everything
342 # in self.type_dependencies() has been resolved.
343 if hasattr(self, 'type') and self.type is not None:
344 return self.type
345 elif hasattr(self, 'entry') and self.entry is not None:
346 return self.entry.type
347 else:
348 self.not_implemented("infer_type")
350 # --------------- Type Analysis ------------------
352 def analyse_as_module(self, env):
353 # If this node can be interpreted as a reference to a
354 # cimported module, return its scope, else None.
355 return None
357 def analyse_as_type(self, env):
358 # If this node can be interpreted as a reference to a
359 # type, return that type, else None.
360 return None
362 def analyse_as_extension_type(self, env):
363 # If this node can be interpreted as a reference to an
364 # extension type, return its type, else None.
365 return None
367 def analyse_types(self, env):
368 self.not_implemented("analyse_types")
370 def analyse_target_types(self, env):
371 self.analyse_types(env)
373 def nogil_check(self, env):
374 # By default, any expression based on Python objects is
375 # prevented in nogil environments. Subtypes must override
376 # this if they can work without the GIL.
377 if self.type.is_pyobject:
378 self.gil_error()
380 def gil_assignment_check(self, env):
381 if env.nogil and self.type.is_pyobject:
382 error(self.pos, "Assignment of Python object not allowed without gil")
384 def check_const(self):
385 self.not_const()
386 return False
388 def not_const(self):
389 error(self.pos, "Not allowed in a constant expression")
391 def check_const_addr(self):
392 self.addr_not_const()
393 return False
395 def addr_not_const(self):
396 error(self.pos, "Address is not constant")
398 # ----------------- Result Allocation -----------------
400 def result_in_temp(self):
401 # Return true if result is in a temporary owned by
402 # this node or one of its subexpressions. Overridden
403 # by certain nodes which can share the result of
404 # a subnode.
405 return self.is_temp
407 def target_code(self):
408 # Return code fragment for use as LHS of a C assignment.
409 return self.calculate_result_code()
411 def calculate_result_code(self):
412 self.not_implemented("calculate_result_code")
414 # def release_target_temp(self, env):
415 # # Release temporaries used by LHS of an assignment.
416 # self.release_subexpr_temps(env)
418 def allocate_temp_result(self, code):
419 if self.temp_code:
420 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
421 type = self.type
422 if not type.is_void:
423 if type.is_pyobject:
424 type = PyrexTypes.py_object_type
425 self.temp_code = code.funcstate.allocate_temp(
426 type, manage_ref=self.use_managed_ref)
427 else:
428 self.temp_code = None
430 def release_temp_result(self, code):
431 if not self.temp_code:
432 if self.old_temp:
433 raise RuntimeError("temp %s released multiple times in %s" % (
434 self.old_temp, self.__class__.__name__))
435 else:
436 raise RuntimeError("no temp, but release requested in %s" % (
437 self.__class__.__name__))
438 code.funcstate.release_temp(self.temp_code)
439 self.old_temp = self.temp_code
440 self.temp_code = None
442 # ---------------- Code Generation -----------------
444 def make_owned_reference(self, code):
445 # If result is a pyobject, make sure we own
446 # a reference to it.
447 if self.type.is_pyobject and not self.result_in_temp():
448 code.put_incref(self.result(), self.ctype())
450 def generate_evaluation_code(self, code):
451 code.mark_pos(self.pos)
453 # Generate code to evaluate this node and
454 # its sub-expressions, and dispose of any
455 # temporary results of its sub-expressions.
456 self.generate_subexpr_evaluation_code(code)
458 if self.is_temp:
459 self.allocate_temp_result(code)
461 self.generate_result_code(code)
462 if self.is_temp:
463 # If we are temp we do not need to wait until this node is disposed
464 # before disposing children.
465 self.generate_subexpr_disposal_code(code)
466 self.free_subexpr_temps(code)
468 def generate_subexpr_evaluation_code(self, code):
469 for node in self.subexpr_nodes():
470 node.generate_evaluation_code(code)
472 def generate_result_code(self, code):
473 self.not_implemented("generate_result_code")
475 def generate_disposal_code(self, code):
476 if self.is_temp:
477 if self.type.is_pyobject:
478 code.put_decref_clear(self.result(), self.ctype())
479 else:
480 # Already done if self.is_temp
481 self.generate_subexpr_disposal_code(code)
483 def generate_subexpr_disposal_code(self, code):
484 # Generate code to dispose of temporary results
485 # of all sub-expressions.
486 for node in self.subexpr_nodes():
487 node.generate_disposal_code(code)
489 def generate_post_assignment_code(self, code):
490 if self.is_temp:
491 if self.type.is_pyobject:
492 code.putln("%s = 0;" % self.result())
493 else:
494 self.generate_subexpr_disposal_code(code)
496 def generate_assignment_code(self, rhs, code):
497 # Stub method for nodes which are not legal as
498 # the LHS of an assignment. An error will have
499 # been reported earlier.
500 pass
502 def generate_deletion_code(self, code):
503 # Stub method for nodes that are not legal as
504 # the argument of a del statement. An error
505 # will have been reported earlier.
506 pass
508 def free_temps(self, code):
509 if self.is_temp:
510 if not self.type.is_void:
511 self.release_temp_result(code)
512 else:
513 self.free_subexpr_temps(code)
515 def free_subexpr_temps(self, code):
516 for sub in self.subexpr_nodes():
517 sub.free_temps(code)
519 # ---------------- Annotation ---------------------
521 def annotate(self, code):
522 for node in self.subexpr_nodes():
523 node.annotate(code)
525 # ----------------- Coercion ----------------------
527 def coerce_to(self, dst_type, env):
528 # Coerce the result so that it can be assigned to
529 # something of type dst_type. If processing is necessary,
530 # wraps this node in a coercion node and returns that.
531 # Otherwise, returns this node unchanged.
532 #
533 # This method is called during the analyse_expressions
534 # phase of the src_node's processing.
535 #
536 # Note that subclasses that override this (especially
537 # ConstNodes) must not (re-)set their own .type attribute
538 # here. Since expression nodes may turn up in different
539 # places in the tree (e.g. inside of CloneNodes in cascaded
540 # assignments), this method must return a new node instance
541 # if it changes the type.
542 #
543 src = self
544 src_type = self.type
545 src_is_py_type = src_type.is_pyobject
546 dst_is_py_type = dst_type.is_pyobject
548 if self.check_for_coercion_error(dst_type):
549 return self
551 if dst_type.is_pyobject:
552 if not src.type.is_pyobject:
553 src = CoerceToPyTypeNode(src, env)
554 if not src.type.subtype_of(dst_type):
555 if not isinstance(src, NoneNode):
556 src = PyTypeTestNode(src, dst_type, env)
557 elif src.type.is_pyobject:
558 src = CoerceFromPyTypeNode(dst_type, src, env)
559 elif (dst_type.is_complex
560 and src_type != dst_type
561 and dst_type.assignable_from(src_type)):
562 src = CoerceToComplexNode(src, dst_type, env)
563 else: # neither src nor dst are py types
564 # Added the string comparison, since for c types that
565 # is enough, but Cython gets confused when the types are
566 # in different pxi files.
567 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
568 self.fail_assignment(dst_type)
569 return src
571 def fail_assignment(self, dst_type):
572 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
574 def check_for_coercion_error(self, dst_type, fail=False, default=None):
575 if fail and not default:
576 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
577 message = find_coercion_error((self.type, dst_type), default)
578 if message is not None:
579 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
580 return True
581 if fail:
582 self.fail_assignment(dst_type)
583 return True
584 return False
586 def coerce_to_pyobject(self, env):
587 return self.coerce_to(PyrexTypes.py_object_type, env)
589 def coerce_to_boolean(self, env):
590 # Coerce result to something acceptable as
591 # a boolean value.
592 type = self.type
593 if type.is_pyobject or type.is_ptr or type.is_float:
594 return CoerceToBooleanNode(self, env)
595 else:
596 if not type.is_int and not type.is_error:
597 error(self.pos,
598 "Type '%s' not acceptable as a boolean" % type)
599 return self
601 def coerce_to_integer(self, env):
602 # If not already some C integer type, coerce to longint.
603 if self.type.is_int:
604 return self
605 else:
606 return self.coerce_to(PyrexTypes.c_long_type, env)
608 def coerce_to_temp(self, env):
609 # Ensure that the result is in a temporary.
610 if self.result_in_temp():
611 return self
612 else:
613 return CoerceToTempNode(self, env)
615 def coerce_to_simple(self, env):
616 # Ensure that the result is simple (see is_simple).
617 if self.is_simple():
618 return self
619 else:
620 return self.coerce_to_temp(env)
622 def is_simple(self):
623 # A node is simple if its result is something that can
624 # be referred to without performing any operations, e.g.
625 # a constant, local var, C global var, struct member
626 # reference, or temporary.
627 return self.result_in_temp()
629 def as_cython_attribute(self):
630 return None
632 class AtomicExprNode(ExprNode):
633 # Abstract base class for expression nodes which have
634 # no sub-expressions.
636 subexprs = []
638 # Override to optimize -- we know we have no children
639 def generate_subexpr_evaluation_code(self, code):
640 pass
641 def generate_subexpr_disposal_code(self, code):
642 pass
644 class PyConstNode(AtomicExprNode):
645 # Abstract base class for constant Python values.
647 is_literal = 1
648 type = py_object_type
650 def is_simple(self):
651 return 1
653 def analyse_types(self, env):
654 pass
656 def calculate_result_code(self):
657 return self.value
659 def generate_result_code(self, code):
660 pass
663 class NoneNode(PyConstNode):
664 # The constant value None
666 value = "Py_None"
668 constant_result = None
670 nogil_check = None
672 def compile_time_value(self, denv):
673 return None
675 class EllipsisNode(PyConstNode):
676 # '...' in a subscript list.
678 value = "Py_Ellipsis"
680 constant_result = Ellipsis
682 def compile_time_value(self, denv):
683 return Ellipsis
686 class ConstNode(AtomicExprNode):
687 # Abstract base type for literal constant nodes.
688 #
689 # value string C code fragment
691 is_literal = 1
692 nogil_check = None
694 def is_simple(self):
695 return 1
697 def analyse_types(self, env):
698 pass # Types are held in class variables
700 def check_const(self):
701 return True
703 def get_constant_c_result_code(self):
704 return self.calculate_result_code()
706 def calculate_result_code(self):
707 return str(self.value)
709 def generate_result_code(self, code):
710 pass
713 class BoolNode(ConstNode):
714 type = PyrexTypes.c_bint_type
715 # The constant value True or False
717 def calculate_constant_result(self):
718 self.constant_result = self.value
720 def compile_time_value(self, denv):
721 return self.value
723 def calculate_result_code(self):
724 return str(int(self.value))
727 class NullNode(ConstNode):
728 type = PyrexTypes.c_null_ptr_type
729 value = "NULL"
730 constant_result = 0
732 def get_constant_c_result_code(self):
733 return self.value
736 class CharNode(ConstNode):
737 type = PyrexTypes.c_char_type
739 def calculate_constant_result(self):
740 self.constant_result = ord(self.value)
742 def compile_time_value(self, denv):
743 return ord(self.value)
745 def calculate_result_code(self):
746 return "'%s'" % StringEncoding.escape_char(self.value)
749 class IntNode(ConstNode):
751 # unsigned "" or "U"
752 # longness "" or "L" or "LL"
754 unsigned = ""
755 longness = ""
756 type = PyrexTypes.c_long_type
758 def coerce_to(self, dst_type, env):
759 if self.type is dst_type:
760 return self
761 node = IntNode(self.pos, value=self.value,
762 unsigned=self.unsigned, longness=self.longness)
763 if dst_type.is_numeric and not dst_type.is_complex:
764 return node
765 if dst_type.is_pyobject:
766 node.type = PyrexTypes.py_object_type
767 # We still need to perform normal coerce_to processing on the
768 # result, because we might be coercing to an extension type,
769 # in which case a type test node will be needed.
770 return ConstNode.coerce_to(node, dst_type, env)
772 def coerce_to_boolean(self, env):
773 return IntNode(
774 self.pos, value=self.value,
775 type = PyrexTypes.c_bint_type,
776 unsigned=self.unsigned, longness=self.longness)
778 def generate_evaluation_code(self, code):
779 if self.type.is_pyobject:
780 # pre-allocate a Python version of the number
781 self.result_code = code.get_py_num(self.value, self.longness)
782 else:
783 self.result_code = self.get_constant_c_result_code()
785 def get_constant_c_result_code(self):
786 return str(self.value) + self.unsigned + self.longness
788 def calculate_result_code(self):
789 return self.result_code
791 def calculate_constant_result(self):
792 self.constant_result = int(self.value, 0)
794 def compile_time_value(self, denv):
795 return int(self.value, 0)
798 class FloatNode(ConstNode):
799 type = PyrexTypes.c_double_type
801 def calculate_constant_result(self):
802 self.constant_result = float(self.value)
804 def compile_time_value(self, denv):
805 return float(self.value)
807 def calculate_result_code(self):
808 strval = repr(float(self.value))
809 if strval == 'nan':
810 return "(Py_HUGE_VAL * 0)"
811 elif strval == 'inf':
812 return "Py_HUGE_VAL"
813 elif strval == '-inf':
814 return "(-Py_HUGE_VAL)"
815 else:
816 return strval
819 class BytesNode(ConstNode):
820 # A char* or bytes literal
821 #
822 # value BytesLiteral
824 type = PyrexTypes.c_char_ptr_type
826 def compile_time_value(self, denv):
827 return self.value
829 def analyse_as_type(self, env):
830 type = PyrexTypes.parse_basic_type(self.value)
831 if type is not None:
832 return type
833 from TreeFragment import TreeFragment
834 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
835 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
836 sizeof_node = declaration.root.stats[0].expr
837 sizeof_node.analyse_types(env)
838 if isinstance(sizeof_node, SizeofTypeNode):
839 return sizeof_node.arg_type
841 def can_coerce_to_char_literal(self):
842 return len(self.value) == 1
844 def coerce_to(self, dst_type, env):
845 if dst_type.is_int:
846 if not self.can_coerce_to_char_literal():
847 error(self.pos, "Only single-character strings can be coerced into ints.")
848 return self
849 return CharNode(self.pos, value=self.value)
851 node = BytesNode(self.pos, value=self.value)
852 if dst_type == PyrexTypes.c_char_ptr_type:
853 node.type = PyrexTypes.c_char_ptr_type
854 return node
855 elif dst_type == PyrexTypes.c_uchar_ptr_type:
856 node.type = PyrexTypes.c_char_ptr_type
857 return CastNode(node, PyrexTypes.c_uchar_ptr_type)
859 if not self.type.is_pyobject:
860 if dst_type in (py_object_type, Builtin.bytes_type):
861 node.type = Builtin.bytes_type
862 elif dst_type.is_pyobject:
863 self.fail_assignment(dst_type)
864 return self
865 elif dst_type.is_pyobject and dst_type is not py_object_type:
866 self.check_for_coercion_error(dst_type, fail=True)
867 return node
869 # We still need to perform normal coerce_to processing on the
870 # result, because we might be coercing to an extension type,
871 # in which case a type test node will be needed.
872 return ConstNode.coerce_to(node, dst_type, env)
874 def as_py_string_node(self, env):
875 # Return a new BytesNode with the same value as this node
876 # but whose type is a Python type instead of a C type.
877 return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
879 def generate_evaluation_code(self, code):
880 if self.type.is_pyobject:
881 self.result_code = code.get_py_string_const(self.value)
882 else:
883 self.result_code = code.get_string_const(self.value)
885 def get_constant_c_result_code(self):
886 return None # FIXME
888 def calculate_result_code(self):
889 return self.result_code
892 class UnicodeNode(PyConstNode):
893 # A Python unicode object
894 #
895 # value EncodedString
897 type = unicode_type
899 def coerce_to(self, dst_type, env):
900 if dst_type is self.type:
901 pass
902 elif not dst_type.is_pyobject:
903 error(self.pos, "Unicode objects do not support coercion to C types.")
904 elif dst_type is not py_object_type:
905 if not self.check_for_coercion_error(dst_type):
906 self.fail_assignment(dst_type)
907 return self
909 def generate_evaluation_code(self, code):
910 self.result_code = code.get_py_string_const(self.value)
912 def calculate_result_code(self):
913 return self.result_code
915 def compile_time_value(self, env):
916 return self.value
919 class StringNode(PyConstNode):
920 # A Python str object, i.e. a byte string in Python 2.x and a
921 # unicode string in Python 3.x
922 #
923 # value BytesLiteral or EncodedString
924 # is_identifier boolean
926 type = str_type
927 is_identifier = None
929 def coerce_to(self, dst_type, env):
930 if dst_type is not py_object_type and not str_type.subtype_of(dst_type):
931 # if dst_type is Builtin.bytes_type:
932 # # special case: bytes = 'str literal'
933 # return BytesNode(self.pos, value=self.value)
934 if not dst_type.is_pyobject:
935 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
936 self.check_for_coercion_error(dst_type, fail=True)
938 # this will be a unicode string in Py3, so make sure we can decode it
939 if self.value.encoding:
940 encoding = self.value.encoding
941 try:
942 self.value.decode(encoding)
943 except UnicodeDecodeError:
944 error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
946 return self
948 def can_coerce_to_char_literal(self):
949 return not self.is_identifier and len(self.value) == 1
951 def generate_evaluation_code(self, code):
952 self.result_code = code.get_py_string_const(
953 self.value, identifier=self.is_identifier, is_str=True)
955 def get_constant_c_result_code(self):
956 return None
958 def calculate_result_code(self):
959 return self.result_code
961 def compile_time_value(self, env):
962 return self.value
965 class IdentifierStringNode(StringNode):
966 # A special str value that represents an identifier (bytes in Py2,
967 # unicode in Py3).
968 is_identifier = True
971 class LongNode(AtomicExprNode):
972 # Python long integer literal
973 #
974 # value string
976 type = py_object_type
978 def calculate_constant_result(self):
979 self.constant_result = long(self.value)
981 def compile_time_value(self, denv):
982 return long(self.value)
984 def analyse_types(self, env):
985 self.is_temp = 1
987 gil_message = "Constructing Python long int"
989 def generate_result_code(self, code):
990 code.putln(
991 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
992 self.result(),
993 self.value,
994 code.error_goto_if_null(self.result(), self.pos)))
995 code.put_gotref(self.py_result())
998 class ImagNode(AtomicExprNode):
999 # Imaginary number literal
1000 #
1001 # value float imaginary part
1003 type = PyrexTypes.c_double_complex_type
1005 def calculate_constant_result(self):
1006 self.constant_result = complex(0.0, self.value)
1008 def compile_time_value(self, denv):
1009 return complex(0.0, self.value)
1011 def analyse_types(self, env):
1012 self.type.create_declaration_utility_code(env)
1014 def coerce_to(self, dst_type, env):
1015 if self.type is dst_type:
1016 return self
1017 node = ImagNode(self.pos, value=self.value)
1018 if dst_type.is_pyobject:
1019 node.is_temp = 1
1020 node.type = PyrexTypes.py_object_type
1021 # We still need to perform normal coerce_to processing on the
1022 # result, because we might be coercing to an extension type,
1023 # in which case a type test node will be needed.
1024 return AtomicExprNode.coerce_to(node, dst_type, env)
1026 gil_message = "Constructing complex number"
1028 def calculate_result_code(self):
1029 if self.type.is_pyobject:
1030 return self.result()
1031 else:
1032 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1034 def generate_result_code(self, code):
1035 if self.type.is_pyobject:
1036 code.putln(
1037 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1038 self.result(),
1039 float(self.value),
1040 code.error_goto_if_null(self.result(), self.pos)))
1041 code.put_gotref(self.py_result())
1045 class NameNode(AtomicExprNode):
1046 # Reference to a local or global variable name.
1047 #
1048 # name string Python name of the variable
1049 # entry Entry Symbol table entry
1050 # type_entry Entry For extension type names, the original type entry
1052 is_name = True
1053 is_cython_module = False
1054 cython_attribute = None
1055 lhs_of_first_assignment = False
1056 is_used_as_rvalue = 0
1057 entry = None
1058 type_entry = None
1060 def create_analysed_rvalue(pos, env, entry):
1061 node = NameNode(pos)
1062 node.analyse_types(env, entry=entry)
1063 return node
1065 def as_cython_attribute(self):
1066 return self.cython_attribute
1068 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1070 def type_dependencies(self, env):
1071 if self.entry is None:
1072 self.entry = env.lookup(self.name)
1073 if self.entry is not None and self.entry.type.is_unspecified:
1074 return (self.entry,)
1075 else:
1076 return ()
1078 def infer_type(self, env):
1079 if self.entry is None:
1080 self.entry = env.lookup(self.name)
1081 if self.entry is None:
1082 return py_object_type
1083 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1084 self.name == self.entry.type.name:
1085 # Unfortunately the type attribute of type objects
1086 # is used for the pointer to the type they represent.
1087 return type_type
1088 else:
1089 return self.entry.type
1091 def compile_time_value(self, denv):
1092 try:
1093 return denv.lookup(self.name)
1094 except KeyError:
1095 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1097 def get_constant_c_result_code(self):
1098 if not self.entry or self.entry.type.is_pyobject:
1099 return None
1100 return self.entry.cname
1102 def coerce_to(self, dst_type, env):
1103 # If coercing to a generic pyobject and this is a builtin
1104 # C function with a Python equivalent, manufacture a NameNode
1105 # referring to the Python builtin.
1106 #print "NameNode.coerce_to:", self.name, dst_type ###
1107 if dst_type is py_object_type:
1108 entry = self.entry
1109 if entry and entry.is_cfunction:
1110 var_entry = entry.as_variable
1111 if var_entry:
1112 if var_entry.is_builtin and Options.cache_builtins:
1113 var_entry = env.declare_builtin(var_entry.name, self.pos)
1114 node = NameNode(self.pos, name = self.name)
1115 node.entry = var_entry
1116 node.analyse_rvalue_entry(env)
1117 return node
1118 return super(NameNode, self).coerce_to(dst_type, env)
1120 def analyse_as_module(self, env):
1121 # Try to interpret this as a reference to a cimported module.
1122 # Returns the module scope, or None.
1123 entry = self.entry
1124 if not entry:
1125 entry = env.lookup(self.name)
1126 if entry and entry.as_module:
1127 return entry.as_module
1128 return None
1130 def analyse_as_type(self, env):
1131 if self.cython_attribute:
1132 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1133 else:
1134 type = PyrexTypes.parse_basic_type(self.name)
1135 if type:
1136 return type
1137 entry = self.entry
1138 if not entry:
1139 entry = env.lookup(self.name)
1140 if entry and entry.is_type:
1141 return entry.type
1142 else:
1143 return None
1145 def analyse_as_extension_type(self, env):
1146 # Try to interpret this as a reference to an extension type.
1147 # Returns the extension type, or None.
1148 entry = self.entry
1149 if not entry:
1150 entry = env.lookup(self.name)
1151 if entry and entry.is_type and entry.type.is_extension_type:
1152 return entry.type
1153 else:
1154 return None
1156 def analyse_target_declaration(self, env):
1157 if not self.entry:
1158 self.entry = env.lookup_here(self.name)
1159 if not self.entry:
1160 if env.directives['infer_types'] != False:
1161 type = unspecified_type
1162 else:
1163 type = py_object_type
1164 self.entry = env.declare_var(self.name, type, self.pos)
1165 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1166 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1167 if self.entry.is_declared_generic:
1168 self.result_ctype = py_object_type
1170 def analyse_types(self, env):
1171 if self.entry is None:
1172 self.entry = env.lookup(self.name)
1173 if not self.entry:
1174 self.entry = env.declare_builtin(self.name, self.pos)
1175 if not self.entry:
1176 self.type = PyrexTypes.error_type
1177 return
1178 entry = self.entry
1179 if entry:
1180 entry.used = 1
1181 if entry.type.is_buffer:
1182 import Buffer
1183 Buffer.used_buffer_aux_vars(entry)
1184 if entry.utility_code:
1185 env.use_utility_code(entry.utility_code)
1186 self.analyse_rvalue_entry(env)
1188 def analyse_target_types(self, env):
1189 self.analyse_entry(env)
1190 if not self.is_lvalue():
1191 error(self.pos, "Assignment to non-lvalue '%s'"
1192 % self.name)
1193 self.type = PyrexTypes.error_type
1194 self.entry.used = 1
1195 if self.entry.type.is_buffer:
1196 import Buffer
1197 Buffer.used_buffer_aux_vars(self.entry)
1199 def analyse_rvalue_entry(self, env):
1200 #print "NameNode.analyse_rvalue_entry:", self.name ###
1201 #print "Entry:", self.entry.__dict__ ###
1202 self.analyse_entry(env)
1203 entry = self.entry
1204 if entry.is_declared_generic:
1205 self.result_ctype = py_object_type
1206 if entry.is_pyglobal or entry.is_builtin:
1207 if Options.cache_builtins and entry.is_builtin:
1208 self.is_temp = 0
1209 else:
1210 self.is_temp = 1
1211 self.is_used_as_rvalue = 1
1212 env.use_utility_code(get_name_interned_utility_code)
1214 def nogil_check(self, env):
1215 if self.is_used_as_rvalue:
1216 entry = self.entry
1217 if entry.is_builtin:
1218 # if not Options.cache_builtins: # cached builtins are ok
1219 self.gil_error()
1220 elif entry.is_pyglobal:
1221 self.gil_error()
1223 gil_message = "Accessing Python global or builtin"
1225 def analyse_entry(self, env):
1226 #print "NameNode.analyse_entry:", self.name ###
1227 self.check_identifier_kind()
1228 entry = self.entry
1229 type = entry.type
1230 self.type = type
1232 def check_identifier_kind(self):
1233 # Check that this is an appropriate kind of name for use in an
1234 # expression. Also finds the variable entry associated with
1235 # an extension type.
1236 entry = self.entry
1237 if entry.is_type and entry.type.is_extension_type:
1238 self.type_entry = entry
1239 if not (entry.is_const or entry.is_variable
1240 or entry.is_builtin or entry.is_cfunction):
1241 if self.entry.as_variable:
1242 self.entry = self.entry.as_variable
1243 else:
1244 error(self.pos,
1245 "'%s' is not a constant, variable or function identifier" % self.name)
1247 def is_simple(self):
1248 # If it's not a C variable, it'll be in a temp.
1249 return 1
1251 def calculate_target_results(self, env):
1252 pass
1254 def check_const(self):
1255 entry = self.entry
1256 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1257 self.not_const()
1258 return False
1259 return True
1261 def check_const_addr(self):
1262 entry = self.entry
1263 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1264 self.addr_not_const()
1265 return False
1266 return True
1268 def is_lvalue(self):
1269 return self.entry.is_variable and \
1270 not self.entry.type.is_array and \
1271 not self.entry.is_readonly
1273 def is_ephemeral(self):
1274 # Name nodes are never ephemeral, even if the
1275 # result is in a temporary.
1276 return 0
1278 def calculate_result_code(self):
1279 entry = self.entry
1280 if not entry:
1281 return "<error>" # There was an error earlier
1282 return entry.cname
1284 def generate_result_code(self, code):
1285 assert hasattr(self, 'entry')
1286 entry = self.entry
1287 if entry is None:
1288 return # There was an error earlier
1289 if entry.is_builtin and Options.cache_builtins:
1290 return # Lookup already cached
1291 elif entry.is_pyglobal or entry.is_builtin:
1292 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1293 interned_cname = code.intern_identifier(self.entry.name)
1294 if entry.is_builtin:
1295 namespace = Naming.builtins_cname
1296 else: # entry.is_pyglobal
1297 namespace = entry.scope.namespace_cname
1298 code.putln(
1299 '%s = __Pyx_GetName(%s, %s); %s' % (
1300 self.result(),
1301 namespace,
1302 interned_cname,
1303 code.error_goto_if_null(self.result(), self.pos)))
1304 code.put_gotref(self.py_result())
1306 elif entry.is_local and False:
1307 # control flow not good enough yet
1308 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1309 if assigned is False:
1310 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1311 elif not Options.init_local_none and assigned is None:
1312 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1313 (entry.cname, entry.name, code.error_goto(self.pos)))
1314 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1316 def generate_assignment_code(self, rhs, code):
1317 #print "NameNode.generate_assignment_code:", self.name ###
1318 entry = self.entry
1319 if entry is None:
1320 return # There was an error earlier
1322 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1323 and not self.lhs_of_first_assignment):
1324 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1326 # is_pyglobal seems to be True for module level-globals only.
1327 # We use this to access class->tp_dict if necessary.
1328 if entry.is_pyglobal:
1329 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1330 interned_cname = code.intern_identifier(self.entry.name)
1331 namespace = self.entry.scope.namespace_cname
1332 if entry.is_member:
1333 # if the entry is a member we have to cheat: SetAttr does not work
1334 # on types, so we create a descriptor which is then added to tp_dict
1335 code.put_error_if_neg(self.pos,
1336 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1337 namespace,
1338 interned_cname,
1339 rhs.py_result()))
1340 rhs.generate_disposal_code(code)
1341 rhs.free_temps(code)
1342 # in Py2.6+, we need to invalidate the method cache
1343 code.putln("PyType_Modified(%s);" %
1344 entry.scope.parent_type.typeptr_cname)
1345 else:
1346 code.put_error_if_neg(self.pos,
1347 'PyObject_SetAttr(%s, %s, %s)' % (
1348 namespace,
1349 interned_cname,
1350 rhs.py_result()))
1351 if debug_disposal_code:
1352 print("NameNode.generate_assignment_code:")
1353 print("...generating disposal code for %s" % rhs)
1354 rhs.generate_disposal_code(code)
1355 rhs.free_temps(code)
1356 else:
1357 if self.type.is_buffer:
1358 # Generate code for doing the buffer release/acquisition.
1359 # This might raise an exception in which case the assignment (done
1360 # below) will not happen.
1361 #
1362 # The reason this is not in a typetest-like node is because the
1363 # variables that the acquired buffer info is stored to is allocated
1364 # per entry and coupled with it.
1365 self.generate_acquire_buffer(rhs, code)
1367 if self.type.is_pyobject:
1368 #print "NameNode.generate_assignment_code: to", self.name ###
1369 #print "...from", rhs ###
1370 #print "...LHS type", self.type, "ctype", self.ctype() ###
1371 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1372 if self.use_managed_ref:
1373 rhs.make_owned_reference(code)
1374 if entry.is_cglobal:
1375 code.put_gotref(self.py_result())
1376 if self.use_managed_ref and not self.lhs_of_first_assignment:
1377 if entry.is_local and not Options.init_local_none:
1378 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1379 if initalized is True:
1380 code.put_decref(self.result(), self.ctype())
1381 elif initalized is None:
1382 code.put_xdecref(self.result(), self.ctype())
1383 else:
1384 code.put_decref(self.result(), self.ctype())
1385 if self.use_managed_ref:
1386 if entry.is_cglobal:
1387 code.put_giveref(rhs.py_result())
1388 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1389 if debug_disposal_code:
1390 print("NameNode.generate_assignment_code:")
1391 print("...generating post-assignment code for %s" % rhs)
1392 rhs.generate_post_assignment_code(code)
1393 rhs.free_temps(code)
1395 def generate_acquire_buffer(self, rhs, code):
1396 # rhstmp is only used in case the rhs is a complicated expression leading to
1397 # the object, to avoid repeating the same C expression for every reference
1398 # to the rhs. It does NOT hold a reference.
1399 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1400 if pretty_rhs:
1401 rhstmp = rhs.result_as(self.ctype())
1402 else:
1403 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1404 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1406 buffer_aux = self.entry.buffer_aux
1407 bufstruct = buffer_aux.buffer_info_var.cname
1408 import Buffer
1409 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1410 is_initialized=not self.lhs_of_first_assignment,
1411 pos=self.pos, code=code)
1413 if not pretty_rhs:
1414 code.putln("%s = 0;" % rhstmp)
1415 code.funcstate.release_temp(rhstmp)
1417 def generate_deletion_code(self, code):
1418 if self.entry is None:
1419 return # There was an error earlier
1420 if not self.entry.is_pyglobal:
1421 error(self.pos, "Deletion of local or C global name not supported")
1422 return
1423 code.put_error_if_neg(self.pos,
1424 '__Pyx_DelAttrString(%s, "%s")' % (
1425 Naming.module_cname,
1426 self.entry.name))
1428 def annotate(self, code):
1429 if hasattr(self, 'is_called') and self.is_called:
1430 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1431 if self.type.is_pyobject:
1432 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1433 else:
1434 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1436 class BackquoteNode(ExprNode):
1437 # `expr`
1438 #
1439 # arg ExprNode
1441 type = py_object_type
1443 subexprs = ['arg']
1445 def analyse_types(self, env):
1446 self.arg.analyse_types(env)
1447 self.arg = self.arg.coerce_to_pyobject(env)
1448 self.is_temp = 1
1450 gil_message = "Backquote expression"
1452 def calculate_constant_result(self):
1453 self.constant_result = repr(self.arg.constant_result)
1455 def generate_result_code(self, code):
1456 code.putln(
1457 "%s = PyObject_Repr(%s); %s" % (
1458 self.result(),
1459 self.arg.py_result(),
1460 code.error_goto_if_null(self.result(), self.pos)))
1461 code.put_gotref(self.py_result())
1465 class ImportNode(ExprNode):
1466 # Used as part of import statement implementation.
1467 # Implements result =
1468 # __import__(module_name, globals(), None, name_list)
1469 #
1470 # module_name StringNode dotted name of module
1471 # name_list ListNode or None list of names to be imported
1473 type = py_object_type
1475 subexprs = ['module_name', 'name_list']
1477 def analyse_types(self, env):
1478 self.module_name.analyse_types(env)
1479 self.module_name = self.module_name.coerce_to_pyobject(env)
1480 if self.name_list:
1481 self.name_list.analyse_types(env)
1482 self.name_list.coerce_to_pyobject(env)
1483 self.is_temp = 1
1484 env.use_utility_code(import_utility_code)
1486 gil_message = "Python import"
1488 def generate_result_code(self, code):
1489 if self.name_list:
1490 name_list_code = self.name_list.py_result()
1491 else:
1492 name_list_code = "0"
1493 code.putln(
1494 "%s = __Pyx_Import(%s, %s); %s" % (
1495 self.result(),
1496 self.module_name.py_result(),
1497 name_list_code,
1498 code.error_goto_if_null(self.result(), self.pos)))
1499 code.put_gotref(self.py_result())
1502 class IteratorNode(ExprNode):
1503 # Used as part of for statement implementation.
1504 #
1505 # allocate_counter_temp/release_counter_temp needs to be called
1506 # by parent (ForInStatNode)
1507 #
1508 # Implements result = iter(sequence)
1509 #
1510 # sequence ExprNode
1512 type = py_object_type
1514 subexprs = ['sequence']
1516 def analyse_types(self, env):
1517 self.sequence.analyse_types(env)
1518 self.sequence = self.sequence.coerce_to_pyobject(env)
1519 self.is_temp = 1
1521 gil_message = "Iterating over Python object"
1523 def allocate_counter_temp(self, code):
1524 self.counter_cname = code.funcstate.allocate_temp(
1525 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1527 def release_counter_temp(self, code):
1528 code.funcstate.release_temp(self.counter_cname)
1530 def generate_result_code(self, code):
1531 is_builtin_sequence = self.sequence.type is list_type or \
1532 self.sequence.type is tuple_type
1533 may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
1534 if is_builtin_sequence:
1535 code.putln(
1536 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1537 elif may_be_a_sequence:
1538 code.putln(
1539 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1540 self.sequence.py_result(),
1541 self.sequence.py_result()))
1542 if may_be_a_sequence:
1543 code.putln(
1544 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1545 self.counter_cname,
1546 self.result(),
1547 self.sequence.py_result(),
1548 self.result()))
1549 code.putln("} else {")
1550 if is_builtin_sequence:
1551 code.putln(
1552 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1553 code.error_goto(self.pos))
1554 else:
1555 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1556 self.counter_cname,
1557 self.result(),
1558 self.sequence.py_result(),
1559 code.error_goto_if_null(self.result(), self.pos)))
1560 code.put_gotref(self.py_result())
1561 if may_be_a_sequence:
1562 code.putln("}")
1565 class NextNode(AtomicExprNode):
1566 # Used as part of for statement implementation.
1567 # Implements result = iterator.next()
1568 # Created during analyse_types phase.
1569 # The iterator is not owned by this node.
1570 #
1571 # iterator ExprNode
1573 type = py_object_type
1575 def __init__(self, iterator, env):
1576 self.pos = iterator.pos
1577 self.iterator = iterator
1578 self.is_temp = 1
1580 def generate_result_code(self, code):
1581 sequence_type = self.iterator.sequence.type
1582 if sequence_type is list_type:
1583 type_checks = [(list_type, "List")]
1584 elif sequence_type is tuple_type:
1585 type_checks = [(tuple_type, "Tuple")]
1586 elif not sequence_type.is_builtin_type:
1587 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1588 else:
1589 type_checks = []
1591 for py_type, prefix in type_checks:
1592 if len(type_checks) > 1:
1593 code.putln(
1594 "if (likely(Py%s_CheckExact(%s))) {" % (
1595 prefix, self.iterator.py_result()))
1596 code.putln(
1597 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1598 self.iterator.counter_cname,
1599 prefix,
1600 self.iterator.py_result()))
1601 code.putln(
1602 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1603 self.result(),
1604 prefix,
1605 self.iterator.py_result(),
1606 self.iterator.counter_cname,
1607 self.result(),
1608 self.iterator.counter_cname))
1609 if len(type_checks) > 1:
1610 code.put("} else ")
1611 if len(type_checks) == 1:
1612 return
1613 code.putln("{")
1614 code.putln(
1615 "%s = PyIter_Next(%s);" % (
1616 self.result(),
1617 self.iterator.py_result()))
1618 code.putln(
1619 "if (!%s) {" %
1620 self.result())
1621 code.putln(code.error_goto_if_PyErr(self.pos))
1622 code.putln("break;")
1623 code.putln("}")
1624 code.put_gotref(self.py_result())
1625 code.putln("}")
1628 class ExcValueNode(AtomicExprNode):
1629 # Node created during analyse_types phase
1630 # of an ExceptClauseNode to fetch the current
1631 # exception value.
1633 type = py_object_type
1635 def __init__(self, pos, env):
1636 ExprNode.__init__(self, pos)
1638 def set_var(self, var):
1639 self.var = var
1641 def calculate_result_code(self):
1642 return self.var
1644 def generate_result_code(self, code):
1645 pass
1647 def analyse_types(self, env):
1648 pass
1651 class TempNode(ExprNode):
1652 # Node created during analyse_types phase
1653 # of some nodes to hold a temporary value.
1654 #
1655 # Note: One must call "allocate" and "release" on
1656 # the node during code generation to get/release the temp.
1657 # This is because the temp result is often used outside of
1658 # the regular cycle.
1660 subexprs = []
1662 def __init__(self, pos, type, env):
1663 ExprNode.__init__(self, pos)
1664 self.type = type
1665 if type.is_pyobject:
1666 self.result_ctype = py_object_type
1667 self.is_temp = 1
1669 def analyse_types(self, env):
1670 return self.type
1672 def generate_result_code(self, code):
1673 pass
1675 def allocate(self, code):
1676 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1678 def release(self, code):
1679 code.funcstate.release_temp(self.temp_cname)
1680 self.temp_cname = None
1682 def result(self):
1683 try:
1684 return self.temp_cname
1685 except:
1686 assert False, "Remember to call allocate/release on TempNode"
1687 raise
1689 # Do not participate in normal temp alloc/dealloc:
1690 def allocate_temp_result(self, code):
1691 pass
1693 def release_temp_result(self, code):
1694 pass
1696 class PyTempNode(TempNode):
1697 # TempNode holding a Python value.
1699 def __init__(self, pos, env):
1700 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1702 class RawCNameExprNode(ExprNode):
1703 subexprs = []
1705 def __init__(self, pos, type=None):
1706 self.pos = pos
1707 self.type = type
1709 def analyse_types(self, env):
1710 return self.type
1712 def set_cname(self, cname):
1713 self.cname = cname
1715 def result(self):
1716 return self.cname
1718 def generate_result_code(self, code):
1719 pass
1722 #-------------------------------------------------------------------
1723 #
1724 # Trailer nodes
1725 #
1726 #-------------------------------------------------------------------
1728 class IndexNode(ExprNode):
1729 # Sequence indexing.
1730 #
1731 # base ExprNode
1732 # index ExprNode
1733 # indices [ExprNode]
1734 # is_buffer_access boolean Whether this is a buffer access.
1735 #
1736 # indices is used on buffer access, index on non-buffer access.
1737 # The former contains a clean list of index parameters, the
1738 # latter whatever Python object is needed for index access.
1740 subexprs = ['base', 'index', 'indices']
1741 indices = None
1743 def __init__(self, pos, index, *args, **kw):
1744 ExprNode.__init__(self, pos, index=index, *args, **kw)
1745 self._index = index
1747 def calculate_constant_result(self):
1748 self.constant_result = \
1749 self.base.constant_result[self.index.constant_result]
1751 def compile_time_value(self, denv):
1752 base = self.base.compile_time_value(denv)
1753 index = self.index.compile_time_value(denv)
1754 try:
1755 return base[index]
1756 except Exception, e:
1757 self.compile_time_value_error(e)
1759 def is_ephemeral(self):
1760 return self.base.is_ephemeral()
1762 def analyse_target_declaration(self, env):
1763 pass
1765 def analyse_as_type(self, env):
1766 base_type = self.base.analyse_as_type(env)
1767 if base_type and not base_type.is_pyobject:
1768 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1769 return None
1771 def type_dependencies(self, env):
1772 return self.base.type_dependencies(env)
1774 def infer_type(self, env):
1775 if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1776 return py_object_type
1777 base_type = self.base.infer_type(env)
1778 if base_type.is_ptr or base_type.is_array:
1779 return base_type.base_type
1780 else:
1781 # TODO: Handle buffers (hopefully without too much redundancy).
1782 return py_object_type
1784 def analyse_types(self, env):
1785 self.analyse_base_and_index_types(env, getting = 1)
1787 def analyse_target_types(self, env):
1788 self.analyse_base_and_index_types(env, setting = 1)
1790 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1791 # Note: This might be cleaned up by having IndexNode
1792 # parsed in a saner way and only construct the tuple if
1793 # needed.
1795 # Note that this function must leave IndexNode in a cloneable state.
1796 # For buffers, self.index is packed out on the initial analysis, and
1797 # when cloning self.indices is copied.
1798 self.is_buffer_access = False
1800 self.base.analyse_types(env)
1801 if self.base.type.is_error:
1802 # Do not visit child tree if base is undeclared to avoid confusing
1803 # error messages
1804 self.type = PyrexTypes.error_type
1805 return
1807 # Handle the case where base is a literal char* (and we expect a string, not an int)
1808 if isinstance(self.base, BytesNode):
1809 self.base = self.base.coerce_to_pyobject(env)
1811 skip_child_analysis = False
1812 buffer_access = False
1813 if self.base.type.is_buffer:
1814 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1815 if self.indices:
1816 indices = self.indices
1817 else:
1818 if isinstance(self.index, TupleNode):
1819 indices = self.index.args
1820 else:
1821 indices = [self.index]
1822 if len(indices) == self.base.type.ndim:
1823 buffer_access = True
1824 skip_child_analysis = True
1825 for x in indices:
1826 x.analyse_types(env)
1827 if not x.type.is_int:
1828 buffer_access = False
1830 # On cloning, indices is cloned. Otherwise, unpack index into indices
1831 assert not (buffer_access and isinstance(self.index, CloneNode))
1833 if buffer_access:
1834 self.indices = indices
1835 self.index = None
1836 self.type = self.base.type.dtype
1837 self.is_buffer_access = True
1838 self.buffer_type = self.base.entry.type
1840 if getting and self.type.is_pyobject:
1841 self.is_temp = True
1842 if setting:
1843 if not self.base.entry.type.writable:
1844 error(self.pos, "Writing to readonly buffer")
1845 else:
1846 self.base.entry.buffer_aux.writable_needed = True
1847 else:
1848 if isinstance(self.index, TupleNode):
1849 self.index.analyse_types(env, skip_children=skip_child_analysis)
1850 elif not skip_child_analysis:
1851 self.index.analyse_types(env)
1852 self.original_index_type = self.index.type
1853 if self.base.type.is_pyobject:
1854 if self.index.type.is_int:
1855 if (not setting
1856 and (self.base.type is list_type or self.base.type is tuple_type)
1857 and (not self.index.type.signed or isinstance(self.index, IntNode) and int(self.index.value) >= 0)
1858 and not env.directives['boundscheck']):
1859 self.is_temp = 0
1860 else:
1861 self.is_temp = 1
1862 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1863 else:
1864 self.index = self.index.coerce_to_pyobject(env)
1865 self.is_temp = 1
1866 self.type = py_object_type
1867 else:
1868 if self.base.type.is_ptr or self.base.type.is_array:
1869 self.type = self.base.type.base_type
1870 else:
1871 error(self.pos,
1872 "Attempting to index non-array type '%s'" %
1873 self.base.type)
1874 self.type = PyrexTypes.error_type
1875 if self.index.type.is_pyobject:
1876 self.index = self.index.coerce_to(
1877 PyrexTypes.c_py_ssize_t_type, env)
1878 if not self.index.type.is_int:
1879 error(self.pos,
1880 "Invalid index type '%s'" %
1881 self.index.type)
1882 gil_message = "Indexing Python object"
1884 def nogil_check(self, env):
1885 if self.is_buffer_access:
1886 if env.directives['boundscheck']:
1887 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1888 return
1889 elif self.type.is_pyobject:
1890 error(self.pos, "Cannot access buffer with object dtype without gil")
1891 return
1892 super(IndexNode, self).nogil_check(env)
1895 def check_const_addr(self):
1896 return self.base.check_const_addr() and self.index.check_const()
1898 def is_lvalue(self):
1899 return 1
1901 def calculate_result_code(self):
1902 if self.is_buffer_access:
1903 return "(*%s)" % self.buffer_ptr_code
1904 elif self.base.type is list_type:
1905 return "PyList_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
1906 elif self.base.type is tuple_type:
1907 return "PyTuple_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
1908 else:
1909 return "(%s[%s])" % (
1910 self.base.result(), self.index.result())
1912 def extra_index_params(self):
1913 if self.index.type.is_int:
1914 if self.original_index_type.signed:
1915 size_adjustment = ""
1916 else:
1917 size_adjustment = "+1"
1918 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1919 else:
1920 return ""
1922 def generate_subexpr_evaluation_code(self, code):
1923 self.base.generate_evaluation_code(code)
1924 if not self.indices:
1925 self.index.generate_evaluation_code(code)
1926 else:
1927 for i in self.indices:
1928 i.generate_evaluation_code(code)
1930 def generate_subexpr_disposal_code(self, code):
1931 self.base.generate_disposal_code(code)
1932 if not self.indices:
1933 self.index.generate_disposal_code(code)
1934 else:
1935 for i in self.indices:
1936 i.generate_disposal_code(code)
1938 def free_subexpr_temps(self, code):
1939 self.base.free_temps(code)
1940 if not self.indices:
1941 self.index.free_temps(code)
1942 else:
1943 for i in self.indices:
1944 i.free_temps(code)
1946 def generate_result_code(self, code):
1947 if self.is_buffer_access:
1948 if code.globalstate.directives['nonecheck']:
1949 self.put_nonecheck(code)
1950 self.buffer_ptr_code = self.buffer_lookup_code(code)
1951 if self.type.is_pyobject:
1952 # is_temp is True, so must pull out value and incref it.
1953 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1954 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1955 elif self.type.is_pyobject and self.is_temp:
1956 if self.index.type.is_int:
1957 index_code = self.index.result()
1958 if self.base.type is list_type:
1959 function = "__Pyx_GetItemInt_List"
1960 elif self.base.type is tuple_type:
1961 function = "__Pyx_GetItemInt_Tuple"
1962 else:
1963 function = "__Pyx_GetItemInt"
1964 code.globalstate.use_utility_code(getitem_int_utility_code)
1965 else:
1966 function = "PyObject_GetItem"
1967 index_code = self.index.py_result()
1968 sign_code = ""
1969 code.putln(
1970 "%s = %s(%s, %s%s); if (!%s) %s" % (
1971 self.result(),
1972 function,
1973 self.base.py_result(),
1974 index_code,
1975 self.extra_index_params(),
1976 self.result(),
1977 code.error_goto(self.pos)))
1978 code.put_gotref(self.py_result())
1980 def generate_setitem_code(self, value_code, code):
1981 if self.index.type.is_int:
1982 function = "__Pyx_SetItemInt"
1983 index_code = self.index.result()
1984 code.globalstate.use_utility_code(setitem_int_utility_code)
1985 else:
1986 index_code = self.index.py_result()
1987 if self.base.type is dict_type:
1988 function = "PyDict_SetItem"
1989 # It would seem that we could specalized lists/tuples, but that
1990 # shouldn't happen here.
1991 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1992 # not a PyObject*, and bad conversion here would give the wrong
1993 # exception. Also, tuples are supposed to be immutable, and raise
1994 # TypeErrors when trying to set their entries (PyTuple_SetItem
1995 # is for creating new tuples from).
1996 else:
1997 function = "PyObject_SetItem"
1998 code.putln(
1999 "if (%s(%s, %s, %s%s) < 0) %s" % (
2000 function,
2001 self.base.py_result(),
2002 index_code,
2003 value_code,
2004 self.extra_index_params(),
2005 code.error_goto(self.pos)))
2007 def generate_buffer_setitem_code(self, rhs, code, op=""):
2008 # Used from generate_assignment_code and InPlaceAssignmentNode
2009 if code.globalstate.directives['nonecheck']:
2010 self.put_nonecheck(code)
2011 ptrexpr = self.buffer_lookup_code(code)
2012 if self.buffer_type.dtype.is_pyobject:
2013 # Must manage refcounts. Decref what is already there
2014 # and incref what we put in.
2015 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2016 rhs_code = rhs.result()
2017 code.putln("%s = %s;" % (ptr, ptrexpr))
2018 code.put_gotref("*%s" % ptr)
2019 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2020 ptr, rhs_code
2021 ))
2022 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2023 code.put_giveref("*%s" % ptr)
2024 code.funcstate.release_temp(ptr)
2025 else:
2026 # Simple case
2027 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2029 def generate_assignment_code(self, rhs, code):
2030 self.generate_subexpr_evaluation_code(code)
2031 if self.is_buffer_access:
2032 self.generate_buffer_setitem_code(rhs, code)
2033 elif self.type.is_pyobject:
2034 self.generate_setitem_code(rhs.py_result(), code)
2035 else:
2036 code.putln(
2037 "%s = %s;" % (
2038 self.result(), rhs.result()))
2039 self.generate_subexpr_disposal_code(code)
2040 self.free_subexpr_temps(code)
2041 rhs.generate_disposal_code(code)
2042 rhs.free_temps(code)
2044 def generate_deletion_code(self, code):
2045 self.generate_subexpr_evaluation_code(code)
2046 #if self.type.is_pyobject:
2047 if self.index.type.is_int:
2048 function = "__Pyx_DelItemInt"
2049 index_code = self.index.result()
2050 code.globalstate.use_utility_code(delitem_int_utility_code)
2051 else:
2052 index_code = self.index.py_result()
2053 if self.base.type is dict_type:
2054 function = "PyDict_DelItem"
2055 else:
2056 function = "PyObject_DelItem"
2057 code.putln(
2058 "if (%s(%s, %s%s) < 0) %s" % (
2059 function,
2060 self.base.py_result(),
2061 index_code,
2062 self.extra_index_params(),
2063 code.error_goto(self.pos)))
2064 self.generate_subexpr_disposal_code(code)
2065 self.free_subexpr_temps(code)
2067 def buffer_lookup_code(self, code):
2068 # Assign indices to temps
2069 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2070 for temp, index in zip(index_temps, self.indices):
2071 code.putln("%s = %s;" % (temp, index.result()))
2072 # Generate buffer access code using these temps
2073 import Buffer
2074 # The above could happen because child_attrs is wrong somewhere so that
2075 # options are not propagated.
2076 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2077 index_signeds=[i.type.signed for i in self.indices],
2078 index_cnames=index_temps,
2079 directives=code.globalstate.directives,
2080 pos=self.pos, code=code)
2082 def put_nonecheck(self, code):
2083 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2084 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2085 code.putln("__Pyx_RaiseNoneIndexingError();")
2086 code.putln(code.error_goto(self.pos))
2087 code.putln("}")
2089 class SliceIndexNode(ExprNode):
2090 # 2-element slice indexing
2091 #
2092 # base ExprNode
2093 # start ExprNode or None
2094 # stop ExprNode or None
2096 subexprs = ['base', 'start', 'stop']
2098 def infer_type(self, env):
2099 base_type = self.base.infer_type(env)
2100 if base_type.is_string:
2101 return bytes_type
2102 elif base_type in (bytes_type, str_type, unicode_type,
2103 list_type, tuple_type):
2104 return base_type
2105 return py_object_type
2107 def calculate_constant_result(self):
2108 self.constant_result = self.base.constant_result[
2109 self.start.constant_result : self.stop.constant_result]
2111 def compile_time_value(self, denv):
2112 base = self.base.compile_time_value(denv)
2113 if self.start is None:
2114 start = 0
2115 else:
2116 start = self.start.compile_time_value(denv)
2117 if self.stop is None:
2118 stop = None
2119 else:
2120 stop = self.stop.compile_time_value(denv)
2121 try:
2122 return base[start:stop]
2123 except Exception, e:
2124 self.compile_time_value_error(e)
2126 def analyse_target_declaration(self, env):
2127 pass
2129 def analyse_target_types(self, env):
2130 self.analyse_types(env)
2131 # when assigning, we must accept any Python type
2132 if self.type.is_pyobject:
2133 self.type = py_object_type
2135 def analyse_types(self, env):
2136 self.base.analyse_types(env)
2137 if self.start:
2138 self.start.analyse_types(env)
2139 if self.stop:
2140 self.stop.analyse_types(env)
2141 base_type = self.base.type
2142 if base_type.is_string:
2143 self.type = bytes_type
2144 elif base_type.is_array or base_type.is_ptr:
2145 # we need a ptr type here instead of an array type, as
2146 # array types can result in invalid type casts in the C
2147 # code
2148 self.type = PyrexTypes.CPtrType(base_type.base_type)
2149 else:
2150 self.base = self.base.coerce_to_pyobject(env)
2151 self.type = py_object_type
2152 if base_type.is_builtin_type:
2153 # slicing builtin types returns something of the same type
2154 self.type = base_type
2155 c_int = PyrexTypes.c_py_ssize_t_type
2156 if self.start:
2157 self.start = self.start.coerce_to(c_int, env)
2158 if self.stop:
2159 self.stop = self.stop.coerce_to(c_int, env)
2160 self.is_temp = 1
2162 nogil_check = Node.gil_error
2163 gil_message = "Slicing Python object"
2165 def generate_result_code(self, code):
2166 if not self.type.is_pyobject:
2167 error(self.pos,
2168 "Slicing is not currently supported for '%s'." % self.type)
2169 return
2170 if self.base.type.is_string:
2171 if self.stop is None:
2172 code.putln(
2173 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2174 self.result(),
2175 self.base.result(),
2176 self.start_code(),
2177 code.error_goto_if_null(self.result(), self.pos)))
2178 else:
2179 code.putln(
2180 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2181 self.result(),
2182 self.base.result(),
2183 self.start_code(),
2184 self.stop_code(),
2185 self.start_code(),
2186 code.error_goto_if_null(self.result(), self.pos)))
2187 else:
2188 code.putln(
2189 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2190 self.result(),
2191 self.base.py_result(),
2192 self.start_code(),
2193 self.stop_code(),
2194 code.error_goto_if_null(self.result(), self.pos)))
2195 code.put_gotref(self.py_result())
2197 def generate_assignment_code(self, rhs, code):
2198 self.generate_subexpr_evaluation_code(code)
2199 if self.type.is_pyobject:
2200 code.put_error_if_neg(self.pos,
2201 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2202 self.base.py_result(),
2203 self.start_code(),
2204 self.stop_code(),
2205 rhs.result()))
2206 else:
2207 start_offset = ''
2208 if self.start:
2209 start_offset = self.start_code()
2210 if start_offset == '0':
2211 start_offset = ''
2212 else:
2213 start_offset += '+'
2214 if rhs.type.is_array:
2215 array_length = rhs.type.size
2216 self.generate_slice_guard_code(code, array_length)
2217 else:
2218 error(self.pos,
2219 "Slice assignments from pointers are not yet supported.")
2220 # FIXME: fix the array size according to start/stop
2221 array_length = self.base.type.size
2222 for i in range(array_length):
2223 code.putln("%s[%s%s] = %s[%d];" % (
2224 self.base.result(), start_offset, i,
2225 rhs.result(), i))
2226 self.generate_subexpr_disposal_code(code)
2227 self.free_subexpr_temps(code)
2228 rhs.generate_disposal_code(code)
2229 rhs.free_temps(code)
2231 def generate_deletion_code(self, code):
2232 if not self.base.type.is_pyobject:
2233 error(self.pos,
2234 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2235 return
2236 self.generate_subexpr_evaluation_code(code)
2237 code.put_error_if_neg(self.pos,
2238 "PySequence_DelSlice(%s, %s, %s)" % (
2239 self.base.py_result(),
2240 self.start_code(),
2241 self.stop_code()))
2242 self.generate_subexpr_disposal_code(code)
2244 def generate_slice_guard_code(self, code, target_size):
2245 if not self.base.type.is_array:
2246 return
2247 slice_size = self.base.type.size
2248 start = stop = None
2249 if self.stop:
2250 stop = self.stop.result()
2251 try:
2252 stop = int(stop)
2253 if stop < 0:
2254 slice_size = self.base.type.size + stop
2255 else:
2256 slice_size = stop
2257 stop = None
2258 except ValueError:
2259 pass
2260 if self.start:
2261 start = self.start.result()
2262 try:
2263 start = int(start)
2264 if start < 0:
2265 start = self.base.type.size + start
2266 slice_size -= start
2267 start = None
2268 except ValueError:
2269 pass
2270 check = None
2271 if slice_size < 0:
2272 if target_size > 0:
2273 error(self.pos, "Assignment to empty slice.")
2274 elif start is None and stop is None:
2275 # we know the exact slice length
2276 if target_size != slice_size:
2277 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2278 slice_size, target_size))
2279 elif start is not None:
2280 if stop is None:
2281 stop = slice_size
2282 check = "(%s)-(%s)" % (stop, start)
2283 else: # stop is not None:
2284 check = stop
2285 if check:
2286 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2287 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%"PY_FORMAT_SIZE_T"d, got %%"PY_FORMAT_SIZE_T"d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
2288 target_size, check))
2289 code.putln(code.error_goto(self.pos))
2290 code.putln("}")
2292 def start_code(self):
2293 if self.start:
2294 return self.start.result()
2295 else:
2296 return "0"
2298 def stop_code(self):
2299 if self.stop:
2300 return self.stop.result()
2301 elif self.base.type.is_array:
2302 return self.base.type.size
2303 else:
2304 return "PY_SSIZE_T_MAX"
2306 def calculate_result_code(self):
2307 # self.result() is not used, but this method must exist
2308 return "<unused>"
2311 class SliceNode(ExprNode):
2312 # start:stop:step in subscript list
2313 #
2314 # start ExprNode
2315 # stop ExprNode
2316 # step ExprNode
2318 type = py_object_type
2319 is_temp = 1
2321 def calculate_constant_result(self):
2322 self.constant_result = self.base.constant_result[
2323 self.start.constant_result : \
2324 self.stop.constant_result : \
2325 self.step.constant_result]
2327 def compile_time_value(self, denv):
2328 start = self.start.compile_time_value(denv)
2329 if self.stop is None:
2330 stop = None
2331 else:
2332 stop = self.stop.compile_time_value(denv)
2333 if self.step is None:
2334 step = None
2335 else:
2336 step = self.step.compile_time_value(denv)
2337 try:
2338 return slice(start, stop, step)
2339 except Exception, e:
2340 self.compile_time_value_error(e)
2342 subexprs = ['start', 'stop', 'step']
2344 def analyse_types(self, env):
2345 self.start.analyse_types(env)
2346 self.stop.analyse_types(env)
2347 self.step.analyse_types(env)
2348 self.start = self.start.coerce_to_pyobject(env)
2349 self.stop = self.stop.coerce_to_pyobject(env)
2350 self.step = self.step.coerce_to_pyobject(env)
2352 gil_message = "Constructing Python slice object"
2354 def generate_result_code(self, code):
2355 code.putln(
2356 "%s = PySlice_New(%s, %s, %s); %s" % (
2357 self.result(),
2358 self.start.py_result(),
2359 self.stop.py_result(),
2360 self.step.py_result(),
2361 code.error_goto_if_null(self.result(), self.pos)))
2362 code.put_gotref(self.py_result())
2365 class CallNode(ExprNode):
2367 def analyse_as_type_constructor(self, env):
2368 type = self.function.analyse_as_type(env)
2369 if type and type.is_struct_or_union:
2370 args, kwds = self.explicit_args_kwds()
2371 items = []
2372 for arg, member in zip(args, type.scope.var_entries):
2373 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2374 if kwds:
2375 items += kwds.key_value_pairs
2376 self.key_value_pairs = items
2377 self.__class__ = DictNode
2378 self.analyse_types(env)
2379 self.coerce_to(type, env)
2380 return True
2382 def nogil_check(self, env):
2383 func_type = self.function_type()
2384 if func_type.is_pyobject:
2385 self.gil_error()
2386 elif not getattr(func_type, 'nogil', False):
2387 self.gil_error()
2389 gil_message = "Calling gil-requiring function"
2392 class SimpleCallNode(CallNode):
2393 # Function call without keyword, * or ** args.
2394 #
2395 # function ExprNode
2396 # args [ExprNode]
2397 # arg_tuple ExprNode or None used internally
2398 # self ExprNode or None used internally
2399 # coerced_self ExprNode or None used internally
2400 # wrapper_call bool used internally
2401 # has_optional_args bool used internally
2403 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2405 self = None
2406 coerced_self = None
2407 arg_tuple = None
2408 wrapper_call = False
2409 has_optional_args = False
2411 def compile_time_value(self, denv):
2412 function = self.function.compile_time_value(denv)
2413 args = [arg.compile_time_value(denv) for arg in self.args]
2414 try:
2415 return function(*args)
2416 except Exception, e:
2417 self.compile_time_value_error(e)
2419 def type_dependencies(self, env):
2420 # TODO: Update when Danilo's C++ code merged in to handle the
2421 # the case of function overloading.
2422 return self.function.type_dependencies(env)
2424 def infer_type(self, env):
2425 function = self.function
2426 func_type = function.infer_type(env)
2427 if func_type.is_ptr:
2428 func_type = func_type.base_type
2429 if func_type.is_cfunction:
2430 return func_type.return_type
2431 elif func_type is type_type:
2432 if function.is_name and function.entry and function.entry.type:
2433 result_type = function.entry.type
2434 if result_type.is_extension_type:
2435 return result_type
2436 elif result_type.is_builtin_type:
2437 if function.entry.name == 'float':
2438 return PyrexTypes.c_double_type
2439 elif function.entry.name in Builtin.types_that_construct_their_instance:
2440 return result_type
2441 return py_object_type
2443 def analyse_as_type(self, env):
2444 attr = self.function.as_cython_attribute()
2445 if attr == 'pointer':
2446 if len(self.args) != 1:
2447 error(self.args.pos, "only one type allowed.")
2448 else:
2449 type = self.args[0].analyse_as_type(env)
2450 if not type:
2451 error(self.args[0].pos, "Unknown type")
2452 else:
2453 return PyrexTypes.CPtrType(type)
2455 def explicit_args_kwds(self):
2456 return self.args, None
2458 def analyse_types(self, env):
2459 if self.analyse_as_type_constructor(env):
2460 return
2461 function = self.function
2462 function.is_called = 1
2463 self.function.analyse_types(env)
2464 if function.is_attribute and function.entry and function.entry.is_cmethod:
2465 # Take ownership of the object from which the attribute
2466 # was obtained, because we need to pass it as 'self'.
2467 self.self = function.obj
2468 function.obj = CloneNode(self.self)
2469 func_type = self.function_type()
2470 if func_type.is_pyobject:
2471 self.arg_tuple = TupleNode(self.pos, args = self.args)
2472 self.arg_tuple.analyse_types(env)
2473 self.args = None
2474 if func_type is Builtin.type_type and function.is_name and \
2475 function.entry and \
2476 function.entry.is_builtin and \
2477 function.entry.name in Builtin.types_that_construct_their_instance:
2478 # calling a builtin type that returns a specific object type
2479 if function.entry.name == 'float':
2480 # the following will come true later on in a transform
2481 self.type = PyrexTypes.c_double_type
2482 self.result_ctype = PyrexTypes.c_double_type
2483 else:
2484 self.type = Builtin.builtin_types[function.entry.name]
2485 self.result_ctype = py_object_type
2486 elif function.is_name and function.type_entry:
2487 # We are calling an extension type constructor. As
2488 # long as we do not support __new__(), the result type
2489 # is clear
2490 self.type = function.type_entry.type
2491 self.result_ctype = py_object_type
2492 else:
2493 self.type = py_object_type
2494 self.is_temp = 1
2495 else:
2496 for arg in self.args:
2497 arg.analyse_types(env)
2498 if self.self and func_type.args:
2499 # Coerce 'self' to the type expected by the method.
2500 expected_type = func_type.args[0].type
2501 self.coerced_self = CloneNode(self.self).coerce_to(
2502 expected_type, env)
2503 # Insert coerced 'self' argument into argument list.
2504 self.args.insert(0, self.coerced_self)
2505 self.analyse_c_function_call(env)
2507 def function_type(self):
2508 # Return the type of the function being called, coercing a function
2509 # pointer to a function if necessary.
2510 func_type = self.function.type
2511 if func_type.is_ptr:
2512 func_type = func_type.base_type
2513 return func_type
2515 def analyse_c_function_call(self, env):
2516 func_type = self.function_type()
2517 # Check function type
2518 if not func_type.is_cfunction:
2519 if not func_type.is_error:
2520 error(self.pos, "Calling non-function type '%s'" %
2521 func_type)
2522 self.type = PyrexTypes.error_type
2523 self.result_code = "<error>"
2524 return
2525 # Check no. of args
2526 max_nargs = len(func_type.args)
2527 expected_nargs = max_nargs - func_type.optional_arg_count
2528 actual_nargs = len(self.args)
2529 if actual_nargs < expected_nargs \
2530 or (not func_type.has_varargs and actual_nargs > max_nargs):
2531 expected_str = str(expected_nargs)
2532 if func_type.has_varargs:
2533 expected_str = "at least " + expected_str
2534 elif func_type.optional_arg_count:
2535 if actual_nargs < max_nargs:
2536 expected_str = "at least " + expected_str
2537 else:
2538 expected_str = "at most " + str(max_nargs)
2539 error(self.pos,
2540 "Call with wrong number of arguments (expected %s, got %s)"
2541 % (expected_str, actual_nargs))
2542 self.args = None
2543 self.type = PyrexTypes.error_type
2544 self.result_code = "<error>"
2545 return
2546 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2547 self.has_optional_args = 1
2548 self.is_temp = 1
2549 # Coerce arguments
2550 for i in range(min(max_nargs, actual_nargs)):
2551 formal_type = func_type.args[i].type
2552 self.args[i] = self.args[i].coerce_to(formal_type, env)
2553 for i in range(max_nargs, actual_nargs):
2554 if self.args[i].type.is_pyobject:
2555 error(self.args[i].pos,
2556 "Python object cannot be passed as a varargs parameter")
2557 # Calc result type and code fragment
2558 self.type = func_type.return_type
2559 if self.type.is_pyobject:
2560 self.result_ctype = py_object_type
2561 self.is_temp = 1
2562 elif func_type.exception_value is not None \
2563 or func_type.exception_check:
2564 self.is_temp = 1
2565 # C++ exception handler
2566 if func_type.exception_check == '+':
2567 if func_type.exception_value is None:
2568 env.use_utility_code(cpp_exception_utility_code)
2570 def calculate_result_code(self):
2571 return self.c_call_code()
2573 def c_call_code(self):
2574 func_type = self.function_type()
2575 if self.args is None or not func_type.is_cfunction:
2576 return "<error>"
2577 formal_args = func_type.args
2578 arg_list_code = []
2579 args = zip(formal_args, self.args)
2580 max_nargs = len(func_type.args)
2581 expected_nargs = max_nargs - func_type.optional_arg_count
2582 actual_nargs = len(self.args)
2583 for formal_arg, actual_arg in args[:expected_nargs]:
2584 arg_code = actual_arg.result_as(formal_arg.type)
2585 arg_list_code.append(arg_code)
2587 if func_type.is_overridable:
2588 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2590 if func_type.optional_arg_count:
2591 if expected_nargs == actual_nargs:
2592 optional_args = 'NULL'
2593 else:
2594 optional_args = "&%s" % self.opt_arg_struct
2595 arg_list_code.append(optional_args)
2597 for actual_arg in self.args[len(formal_args):]:
2598 arg_list_code.append(actual_arg.result())
2599 result = "%s(%s)" % (self.function.result(),
2600 ', '.join(arg_list_code))
2601 return result
2603 def generate_result_code(self, code):
2604 func_type = self.function_type()
2605 if func_type.is_pyobject:
2606 arg_code = self.arg_tuple.py_result()
2607 code.putln(
2608 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2609 self.result(),
2610 self.function.py_result(),
2611 arg_code,
2612 code.error_goto_if_null(self.result(), self.pos)))
2613 code.put_gotref(self.py_result())
2614 elif func_type.is_cfunction:
2615 if self.has_optional_args:
2616 actual_nargs = len(self.args)
2617 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2618 self.opt_arg_struct = code.funcstate.allocate_temp(
2619 func_type.op_arg_struct.base_type, manage_ref=True)
2620 code.putln("%s.%s = %s;" % (
2621 self.opt_arg_struct,
2622 Naming.pyrex_prefix + "n",
2623 len(self.args) - expected_nargs))
2624 args = zip(func_type.args, self.args)
2625 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2626 code.putln("%s.%s = %s;" % (
2627 self.opt_arg_struct,
2628 func_type.opt_arg_cname(formal_arg.name),
2629 actual_arg.result_as(formal_arg.type)))
2630 exc_checks = []
2631 if self.type.is_pyobject and self.is_temp:
2632 exc_checks.append("!%s" % self.result())
2633 else:
2634 exc_val = func_type.exception_value
2635 exc_check = func_type.exception_check
2636 if exc_val is not None:
2637 exc_checks.append("%s == %s" % (self.result(), exc_val))
2638 if exc_check:
2639 exc_checks.append("PyErr_Occurred()")
2640 if self.is_temp or exc_checks:
2641 rhs = self.c_call_code()
2642 if self.result():
2643 lhs = "%s = " % self.result()
2644 if self.is_temp and self.type.is_pyobject:
2645 #return_type = self.type # func_type.return_type
2646 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2647 # "from", return_type, "to pyobject" ###
2648 rhs = typecast(py_object_type, self.type, rhs)
2649 else:
2650 lhs = ""
2651 if func_type.exception_check == '+':
2652 if func_type.exception_value is None:
2653 raise_py_exception = "__Pyx_CppExn2PyErr()"
2654 elif func_type.exception_value.type.is_pyobject:
2655 raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
2656 func_type.exception_value.entry.cname,
2657 func_type.exception_value.entry.cname)
2658 else:
2659 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2660 code.putln(
2661 "try {%s%s;} catch(...) {%s; %s}" % (
2662 lhs,
2663 rhs,
2664 raise_py_exception,
2665 code.error_goto(self.pos)))
2666 else:
2667 if exc_checks:
2668 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2669 else:
2670 goto_error = ""
2671 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2672 if self.type.is_pyobject and self.result():
2673 code.put_gotref(self.py_result())
2674 if self.has_optional_args:
2675 code.funcstate.release_temp(self.opt_arg_struct)
2678 class PythonCapiFunctionNode(ExprNode):
2679 subexprs = []
2680 def __init__(self, pos, py_name, cname, func_type, utility_code = None):
2681 self.pos = pos
2682 self.name = py_name
2683 self.cname = cname
2684 self.type = func_type
2685 self.utility_code = utility_code
2687 def analyse_types(self, env):
2688 pass
2690 def generate_result_code(self, code):
2691 if self.utility_code:
2692 code.globalstate.use_utility_code(self.utility_code)
2694 def calculate_result_code(self):
2695 return self.cname
2697 class PythonCapiCallNode(SimpleCallNode):
2698 # Python C-API Function call (only created in transforms)
2700 def __init__(self, pos, function_name, func_type,
2701 utility_code = None, py_name=None, **kwargs):
2702 self.type = func_type.return_type
2703 self.result_ctype = self.type
2704 self.function = PythonCapiFunctionNode(
2705 pos, py_name, function_name, func_type,
2706 utility_code = utility_code)
2707 # call this last so that we can override the constructed
2708 # attributes above with explicit keyword arguments if required
2709 SimpleCallNode.__init__(self, pos, **kwargs)
2712 class GeneralCallNode(CallNode):
2713 # General Python function call, including keyword,
2714 # * and ** arguments.
2715 #
2716 # function ExprNode
2717 # positional_args ExprNode Tuple of positional arguments
2718 # keyword_args ExprNode or None Dict of keyword arguments
2719 # starstar_arg ExprNode or None Dict of extra keyword args
2721 type = py_object_type
2723 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2725 nogil_check = Node.gil_error
2727 def compile_time_value(self, denv):
2728 function = self.function.compile_time_value(denv)
2729 positional_args = self.positional_args.compile_time_value(denv)
2730 keyword_args = self.keyword_args.compile_time_value(denv)
2731 starstar_arg = self.starstar_arg.compile_time_value(denv)
2732 try:
2733 keyword_args.update(starstar_arg)
2734 return function(*positional_args, **keyword_args)
2735 except Exception, e:
2736 self.compile_time_value_error(e)
2738 def explicit_args_kwds(self):
2739 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2740 raise PostParseError(self.pos,
2741 'Compile-time keyword arguments must be explicit.')
2742 return self.positional_args.args, self.keyword_args
2744 def analyse_types(self, env):
2745 if self.analyse_as_type_constructor(env):
2746 return
2747 self.function.analyse_types(env)
2748 self.positional_args.analyse_types(env)
2749 if self.keyword_args:
2750 self.keyword_args.analyse_types(env)
2751 if self.starstar_arg:
2752 self.starstar_arg.analyse_types(env)
2753 if not self.function.type.is_pyobject:
2754 if self.function.type.is_error:
2755 self.type = error_type
2756 return
2757 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2758 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2759 else:
2760 self.function = self.function.coerce_to_pyobject(env)
2761 self.positional_args = \
2762 self.positional_args.coerce_to_pyobject(env)
2763 if self.starstar_arg:
2764 self.starstar_arg = \
2765 self.starstar_arg.coerce_to_pyobject(env)
2766 function = self.function
2767 if function.is_name and function.type_entry:
2768 # We are calling an extension type constructor. As long
2769 # as we do not support __new__(), the result type is clear
2770 self.type = function.type_entry.type
2771 self.result_ctype = py_object_type
2772 else:
2773 self.type = py_object_type
2774 self.is_temp = 1
2776 def generate_result_code(self, code):
2777 if self.type.is_error: return
2778 dict_temp = dict_ref = None
2779 if self.keyword_args and self.starstar_arg:
2780 code.put_error_if_neg(self.pos,
2781 "PyDict_Update(%s, %s)" % (
2782 self.keyword_args.py_result(),
2783 self.starstar_arg.py_result()))
2784 keyword_code = self.keyword_args.py_result()
2785 elif self.keyword_args:
2786 keyword_code = self.keyword_args.py_result()
2787 elif self.starstar_arg:
2788 keyword_code = self.starstar_arg.py_result()
2789 if self.starstar_arg.type is not Builtin.dict_type:
2790 # CPython supports calling functions with non-dicts, so do we
2791 dict_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
2792 dict_ref = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2793 code.putln("if (unlikely(!PyDict_Check(%s))) {" % keyword_code)
2794 code.putln(
2795 "%s = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, %s, NULL); %s" % (
2796 dict_ref,
2797 keyword_code,
2798 code.error_goto_if_null(dict_ref, self.pos)))
2799 code.put_gotref(dict_ref)
2800 code.putln("%s = %s;" % (dict_temp, dict_ref))
2801 code.putln("} else {")
2802 code.putln("%s = 0;" % dict_ref)
2803 code.putln("%s = %s;" % (dict_temp, keyword_code))
2804 code.putln("}")
2805 keyword_code = dict_temp
2806 else:
2807 keyword_code = None
2808 if not keyword_code:
2809 call_code = "PyObject_Call(%s, %s, NULL)" % (
2810 self.function.py_result(),
2811 self.positional_args.py_result())
2812 else:
2813 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2814 self.function.py_result(),
2815 self.positional_args.py_result(),
2816 keyword_code)
2817 code.putln(
2818 "%s = %s; %s" % (
2819 self.result(),
2820 call_code,
2821 code.error_goto_if_null(self.result(), self.pos)))
2822 code.put_gotref(self.py_result())
2823 if dict_ref is not None:
2824 code.funcstate.release_temp(dict_temp)
2825 code.put_xdecref_clear(dict_ref, py_object_type)
2826 code.funcstate.release_temp(dict_ref)
2829 class AsTupleNode(ExprNode):
2830 # Convert argument to tuple. Used for normalising
2831 # the * argument of a function call.
2832 #
2833 # arg ExprNode
2835 subexprs = ['arg']
2837 def calculate_constant_result(self):
2838 self.constant_result = tuple(self.base.constant_result)
2840 def compile_time_value(self, denv):
2841 arg = self.arg.compile_time_value(denv)
2842 try:
2843 return tuple(arg)
2844 except Exception, e:
2845 self.compile_time_value_error(e)
2847 def analyse_types(self, env):
2848 self.arg.analyse_types(env)
2849 self.arg = self.arg.coerce_to_pyobject(env)
2850 self.type = tuple_type
2851 self.is_temp = 1
2853 nogil_check = Node.gil_error
2854 gil_message = "Constructing Python tuple"
2856 def generate_result_code(self, code):
2857 code.putln(
2858 "%s = PySequence_Tuple(%s); %s" % (
2859 self.result(),
2860 self.arg.py_result(),
2861 code.error_goto_if_null(self.result(), self.pos)))
2862 code.put_gotref(self.py_result())
2865 class AttributeNode(ExprNode):
2866 # obj.attribute
2867 #
2868 # obj ExprNode
2869 # attribute string
2870 # needs_none_check boolean Used if obj is an extension type.
2871 # If set to True, it is known that the type is not None.
2872 #
2873 # Used internally:
2874 #
2875 # is_py_attr boolean Is a Python getattr operation
2876 # member string C name of struct member
2877 # is_called boolean Function call is being done on result
2878 # entry Entry Symbol table entry of attribute
2880 is_attribute = 1
2881 subexprs = ['obj']
2883 type = PyrexTypes.error_type
2884 entry = None
2885 is_called = 0
2886 needs_none_check = True
2888 def as_cython_attribute(self):
2889 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2890 return self.attribute
2892 def coerce_to(self, dst_type, env):
2893 # If coercing to a generic pyobject and this is a cpdef function
2894 # we can create the corresponding attribute
2895 if dst_type is py_object_type:
2896 entry = self.entry
2897 if entry and entry.is_cfunction and entry.as_variable:
2898 # must be a cpdef function
2899 self.is_temp = 1
2900 self.entry = entry.as_variable
2901 self.analyse_as_python_attribute(env)
2902 return self
2903 return ExprNode.coerce_to(self, dst_type, env)
2905 def calculate_constant_result(self):
2906 attr = self.attribute
2907 if attr.startswith("__") and attr.endswith("__"):
2908 return
2909 self.constant_result = getattr(self.obj.constant_result, attr)
2911 def compile_time_value(self, denv):
2912 attr = self.attribute
2913 if attr.startswith("__") and attr.endswith("__"):
2914 error(self.pos,
2915 "Invalid attribute name '%s' in compile-time expression" % attr)
2916 return None
2917 obj = self.obj.compile_time_value(denv)
2918 try:
2919 return getattr(obj, attr)
2920 except Exception, e:
2921 self.compile_time_value_error(e)
2923 def type_dependencies(self, env):
2924 return self.obj.type_dependencies(env)
2926 def infer_type(self, env):
2927 if self.analyse_as_cimported_attribute(env, 0):
2928 return self.entry.type
2929 elif self.analyse_as_unbound_cmethod(env):
2930 return self.entry.type
2931 else:
2932 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2933 return self.type
2935 def analyse_target_declaration(self, env):
2936 pass
2938 def analyse_target_types(self, env):
2939 self.analyse_types(env, target = 1)
2941 def analyse_types(self, env, target = 0):
2942 if self.analyse_as_cimported_attribute(env, target):
2943 return
2944 if not target and self.analyse_as_unbound_cmethod(env):
2945 return
2946 self.analyse_as_ordinary_attribute(env, target)
2948 def analyse_as_cimported_attribute(self, env, target):
2949 # Try to interpret this as a reference to an imported
2950 # C const, type, var or function. If successful, mutates
2951 # this node into a NameNode and returns 1, otherwise
2952 # returns 0.
2953 module_scope = self.obj.analyse_as_module(env)
2954 if module_scope:
2955 entry = module_scope.lookup_here(self.attribute)
2956 if entry and (
2957 entry.is_cglobal or entry.is_cfunction
2958 or entry.is_type or entry.is_const):
2959 self.mutate_into_name_node(env, entry, target)
2960 return 1
2961 return 0
2963 def analyse_as_unbound_cmethod(self, env):
2964 # Try to interpret this as a reference to an unbound
2965 # C method of an extension type. If successful, mutates
2966 # this node into a NameNode and returns 1, otherwise
2967 # returns 0.
2968 type = self.obj.analyse_as_extension_type(env)
2969 if type:
2970 entry = type.scope.lookup_here(self.attribute)
2971 if entry and entry.is_cmethod:
2972 # Create a temporary entry describing the C method
2973 # as an ordinary function.
2974 ubcm_entry = Symtab.Entry(entry.name,
2975 "%s->%s" % (type.vtabptr_cname, entry.cname),
2976 entry.type)
2977 ubcm_entry.is_cfunction = 1
2978 ubcm_entry.func_cname = entry.func_cname
2979 ubcm_entry.is_unbound_cmethod = 1
2980 self.mutate_into_name_node(env, ubcm_entry, None)
2981 return 1
2982 return 0
2984 def analyse_as_type(self, env):
2985 module_scope = self.obj.analyse_as_module(env)
2986 if module_scope:
2987 return module_scope.lookup_type(self.attribute)
2988 return None
2990 def analyse_as_extension_type(self, env):
2991 # Try to interpret this as a reference to an extension type
2992 # in a cimported module. Returns the extension type, or None.
2993 module_scope = self.obj.analyse_as_module(env)
2994 if module_scope:
2995 entry = module_scope.lookup_here(self.attribute)
2996 if entry and entry.is_type and entry.type.is_extension_type:
2997 return entry.type
2998 return None
3000 def analyse_as_module(self, env):
3001 # Try to interpret this as a reference to a cimported module
3002 # in another cimported module. Returns the module scope, or None.
3003 module_scope = self.obj.analyse_as_module(env)
3004 if module_scope:
3005 entry = module_scope.lookup_here(self.attribute)
3006 if entry and entry.as_module:
3007 return entry.as_module
3008 return None
3010 def mutate_into_name_node(self, env, entry, target):
3011 # Mutate this node into a NameNode and complete the
3012 # analyse_types phase.
3013 self.__class__ = NameNode
3014 self.name = self.attribute
3015 self.entry = entry
3016 del self.obj
3017 del self.attribute
3018 if target:
3019 NameNode.analyse_target_types(self, env)
3020 else:
3021 NameNode.analyse_rvalue_entry(self, env)
3023 def analyse_as_ordinary_attribute(self, env, target):
3024 self.obj.analyse_types(env)
3025 self.analyse_attribute(env)
3026 if self.entry and self.entry.is_cmethod and not self.is_called:
3027 # error(self.pos, "C method can only be called")
3028 pass
3029 ## Reference to C array turns into pointer to first element.
3030 #while self.type.is_array:
3031 # self.type = self.type.element_ptr_type()
3032 if self.is_py_attr:
3033 if not target:
3034 self.is_temp = 1
3035 self.result_ctype = py_object_type
3037 def analyse_attribute(self, env, obj_type = None):
3038 # Look up attribute and set self.type and self.member.
3039 self.is_py_attr = 0
3040 self.member = self.attribute
3041 if obj_type is None:
3042 if self.obj.type.is_string:
3043 self.obj = self.obj.coerce_to_pyobject(env)
3044 obj_type = self.obj.type
3045 else:
3046 if obj_type.is_string:
3047 obj_type = py_object_type
3048 if obj_type.is_ptr or obj_type.is_array:
3049 obj_type = obj_type.base_type
3050 self.op = "->"
3051 elif obj_type.is_extension_type:
3052 self.op = "->"
3053 else:
3054 self.op = "."
3055 if obj_type.has_attributes:
3056 entry = None
3057 if obj_type.attributes_known():
3058 entry = obj_type.scope.lookup_here(self.attribute)
3059 if entry and entry.is_member:
3060 entry = None
3061 else:
3062 error(self.pos,
3063 "Cannot select attribute of incomplete type '%s'"
3064 % obj_type)
3065 self.type = PyrexTypes.error_type
3066 return
3067 self.entry = entry
3068 if entry:
3069 if obj_type.is_extension_type and entry.name == "__weakref__":
3070 error(self.pos, "Illegal use of special attribute __weakref__")
3071 # methods need the normal attribute lookup
3072 # because they do not have struct entries
3073 if entry.is_variable or entry.is_cmethod:
3074 self.type = entry.type
3075 self.member = entry.cname
3076 return
3077 else:
3078 # If it's not a variable or C method, it must be a Python
3079 # method of an extension type, so we treat it like a Python
3080 # attribute.
3081 pass
3082 # If we get here, the base object is not a struct/union/extension
3083 # type, or it is an extension type and the attribute is either not
3084 # declared or is declared as a Python method. Treat it as a Python
3085 # attribute reference.
3086 self.analyse_as_python_attribute(env, obj_type)
3088 def analyse_as_python_attribute(self, env, obj_type = None):
3089 if obj_type is None:
3090 obj_type = self.obj.type
3091 self.member = self.attribute
3092 self.type = py_object_type
3093 self.is_py_attr = 1
3094 if not obj_type.is_pyobject and not obj_type.is_error:
3095 if obj_type.can_coerce_to_pyobject(env):
3096 self.obj = self.obj.coerce_to_pyobject(env)
3097 else:
3098 error(self.pos,
3099 "Object of type '%s' has no attribute '%s'" %
3100 (obj_type, self.attribute))
3102 def nogil_check(self, env):
3103 if self.is_py_attr:
3104 self.gil_error()
3106 gil_message = "Accessing Python attribute"
3108 def is_simple(self):
3109 if self.obj:
3110 return self.result_in_temp() or self.obj.is_simple()
3111 else:
3112 return NameNode.is_simple(self)
3114 def is_lvalue(self):
3115 if self.obj:
3116 return 1
3117 else:
3118 return NameNode.is_lvalue(self)
3120 def is_ephemeral(self):
3121 if self.obj:
3122 return self.obj.is_ephemeral()
3123 else:
3124 return NameNode.is_ephemeral(self)
3126 def calculate_result_code(self):
3127 #print "AttributeNode.calculate_result_code:", self.member ###
3128 #print "...obj node =", self.obj, "code", self.obj.result() ###
3129 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3130 obj = self.obj
3131 obj_code = obj.result_as(obj.type)
3132 #print "...obj_code =", obj_code ###
3133 if self.entry and self.entry.is_cmethod:
3134 if obj.type.is_extension_type:
3135 return "((struct %s *)%s%s%s)->%s" % (
3136 obj.type.vtabstruct_cname, obj_code, self.op,
3137 obj.type.vtabslot_cname, self.member)
3138 else:
3139 return self.member
3140 elif obj.type.is_complex:
3141 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3142 else:
3143 return "%s%s%s" % (obj_code, self.op, self.member)
3145 def generate_result_code(self, code):
3146 interned_attr_cname = code.intern_identifier(self.attribute)
3147 if self.is_py_attr:
3148 code.putln(
3149 '%s = PyObject_GetAttr(%s, %s); %s' % (
3150 self.result(),
3151 self.obj.py_result(),
3152 interned_attr_cname,
3153 code.error_goto_if_null(self.result(), self.pos)))
3154 code.put_gotref(self.py_result())
3155 else:
3156 # result_code contains what is needed, but we may need to insert
3157 # a check and raise an exception
3158 if (self.obj.type.is_extension_type
3159 and self.needs_none_check
3160 and code.globalstate.directives['nonecheck']):
3161 self.put_nonecheck(code)
3163 def generate_assignment_code(self, rhs, code):
3164 interned_attr_cname = code.intern_identifier(self.attribute)
3165 self.obj.generate_evaluation_code(code)
3166 if self.is_py_attr:
3167 code.put_error_if_neg(self.pos,
3168 'PyObject_SetAttr(%s, %s, %s)' % (
3169 self.obj.py_result(),
3170 interned_attr_cname,
3171 rhs.py_result()))
3172 rhs.generate_disposal_code(code)
3173 rhs.free_temps(code)
3174 elif self.obj.type.is_complex:
3175 code.putln("__Pyx_SET_C%s(%s, %s);" % (
3176 self.member.upper(),
3177 self.obj.result_as(self.obj.type),
3178 rhs.result_as(self.ctype())))
3179 else:
3180 if (self.obj.type.is_extension_type
3181 and self.needs_none_check
3182 and code.globalstate.directives['nonecheck']):
3183 self.put_nonecheck(code)
3185 select_code = self.result()
3186 if self.type.is_pyobject and self.use_managed_ref:
3187 rhs.make_owned_reference(code)
3188 code.put_giveref(rhs.py_result())
3189 code.put_gotref(select_code)
3190 code.put_decref(select_code, self.ctype())
3191 code.putln(
3192 "%s = %s;" % (
3193 select_code,
3194 rhs.result_as(self.ctype())))
3195 #rhs.result()))
3196 rhs.generate_post_assignment_code(code)
3197 rhs.free_temps(code)
3198 self.obj.generate_disposal_code(code)
3199 self.obj.free_temps(code)
3201 def generate_deletion_code(self, code):
3202 interned_attr_cname = code.intern_identifier(self.attribute)
3203 self.obj.generate_evaluation_code(code)
3204 if self.is_py_attr:
3205 code.put_error_if_neg(self.pos,
3206 'PyObject_DelAttr(%s, %s)' % (
3207 self.obj.py_result(),
3208 interned_attr_cname))
3209 else:
3210 error(self.pos, "Cannot delete C attribute of extension type")
3211 self.obj.generate_disposal_code(code)
3212 self.obj.free_temps(code)
3214 def annotate(self, code):
3215 if self.is_py_attr:
3216 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3217 else:
3218 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3220 def put_nonecheck(self, code):
3221 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3222 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3223 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3224 code.putln(code.error_goto(self.pos))
3225 code.putln("}")
3228 #-------------------------------------------------------------------
3229 #
3230 # Constructor nodes
3231 #
3232 #-------------------------------------------------------------------
3234 class StarredTargetNode(ExprNode):
3235 # A starred expression like "*a"
3236 #
3237 # This is only allowed in sequence assignment targets such as
3238 #
3239 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3240 #
3241 # and will be removed during type analysis (or generate an error
3242 # if it's found at unexpected places).
3243 #
3244 # target ExprNode
3246 subexprs = ['target']
3247 is_starred = 1
3248 type = py_object_type
3249 is_temp = 1
3251 def __init__(self, pos, target):
3252 self.pos = pos
3253 self.target = target
3255 def analyse_declarations(self, env):
3256 error(self.pos, "can use starred expression only as assignment target")
3257 self.target.analyse_declarations(env)
3259 def analyse_types(self, env):
3260 error(self.pos, "can use starred expression only as assignment target")
3261 self.target.analyse_types(env)
3262 self.type = self.target.type
3264 def analyse_target_declaration(self, env):
3265 self.target.analyse_target_declaration(env)
3267 def analyse_target_types(self, env):
3268 self.target.analyse_target_types(env)
3269 self.type = self.target.type
3271 def calculate_result_code(self):
3272 return ""
3274 def generate_result_code(self, code):
3275 pass
3278 class SequenceNode(ExprNode):
3279 # Base class for list and tuple constructor nodes.
3280 # Contains common code for performing sequence unpacking.
3281 #
3282 # args [ExprNode]
3283 # iterator ExprNode
3284 # unpacked_items [ExprNode] or None
3285 # coerced_unpacked_items [ExprNode] or None
3287 subexprs = ['args']
3289 is_sequence_constructor = 1
3290 unpacked_items = None
3292 def compile_time_value_list(self, denv):
3293 return [arg.compile_time_value(denv) for arg in self.args]
3295 def replace_starred_target_node(self):
3296 # replace a starred node in the targets by the contained expression
3297 self.starred_assignment = False
3298 args = []
3299 for arg in self.args:
3300 if arg.is_starred:
3301 if self.starred_assignment:
3302 error(arg.pos, "more than 1 starred expression in assignment")
3303 self.starred_assignment = True
3304 arg = arg.target
3305 arg.is_starred = True
3306 args.append(arg)
3307 self.args = args
3309 def analyse_target_declaration(self, env):
3310 self.replace_starred_target_node()
3311 for arg in self.args:
3312 arg.analyse_target_declaration(env)
3314 def analyse_types(self, env, skip_children=False):
3315 for i in range(len(self.args)):
3316 arg = self.args[i]
3317 if not skip_children: arg.analyse_types(env)
3318 self.args[i] = arg.coerce_to_pyobject(env)
3319 self.type = py_object_type
3320 self.is_temp = 1
3322 def analyse_target_types(self, env):
3323 self.iterator = PyTempNode(self.pos, env)
3324 self.unpacked_items = []
3325 self.coerced_unpacked_items = []
3326 for arg in self.args:
3327 arg.analyse_target_types(env)
3328 if arg.is_starred:
3329 if not arg.type.assignable_from(Builtin.list_type):
3330 error(arg.pos,
3331 "starred target must have Python object (list) type")
3332 if arg.type is py_object_type:
3333 arg.type = Builtin.list_type
3334 unpacked_item = PyTempNode(self.pos, env)
3335 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3336 self.unpacked_items.append(unpacked_item)
3337 self.coerced_unpacked_items.append(coerced_unpacked_item)
3338 self.type = py_object_type
3340 def generate_result_code(self, code):
3341 self.generate_operation_code(code)
3343 def generate_assignment_code(self, rhs, code):
3344 if self.starred_assignment:
3345 self.generate_starred_assignment_code(rhs, code)
3346 else:
3347 self.generate_parallel_assignment_code(rhs, code)
3349 for item in self.unpacked_items:
3350 item.release(code)
3351 rhs.free_temps(code)
3353 def generate_parallel_assignment_code(self, rhs, code):
3354 # Need to work around the fact that generate_evaluation_code
3355 # allocates the temps in a rather hacky way -- the assignment
3356 # is evaluated twice, within each if-block.
3358 code.globalstate.use_utility_code(unpacking_utility_code)
3360 if rhs.type is tuple_type:
3361 tuple_check = "likely(%s != Py_None)"
3362 else:
3363 tuple_check = "PyTuple_CheckExact(%s)"
3364 code.putln(
3365 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3366 tuple_check % rhs.py_result(),
3367 rhs.py_result(),
3368 len(self.args)))
3369 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3370 for item in self.unpacked_items:
3371 item.allocate(code)
3372 for i in range(len(self.args)):
3373 item = self.unpacked_items[i]
3374 code.put(
3375 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3376 item.result(),
3377 i))
3378 code.put_incref(item.result(), item.ctype())
3379 value_node = self.coerced_unpacked_items[i]
3380 value_node.generate_evaluation_code(code)
3381 rhs.generate_disposal_code(code)
3383 for i in range(len(self.args)):
3384 self.args[i].generate_assignment_code(
3385 self.coerced_unpacked_items[i], code)
3387 code.putln("} else {")
3389 if rhs.type is tuple_type:
3390 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3391 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3392 rhs.py_result(), len(self.args)))
3393 code.putln(code.error_goto(self.pos))
3394 else:
3395 self.iterator.allocate(code)
3396 code.putln(
3397 "%s = PyObject_GetIter(%s); %s" % (
3398 self.iterator.result(),
3399 rhs.py_result(),
3400 code.error_goto_if_null(self.iterator.result(), self.pos)))
3401 code.put_gotref(self.iterator.py_result())
3402 rhs.generate_disposal_code(code)
3403 for i in range(len(self.args)):
3404 item = self.unpacked_items[i]
3405 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3406 self.iterator.py_result(), i)
3407 code.putln(
3408 "%s = %s; %s" % (
3409 item.result(),
3410 typecast(item.ctype(), py_object_type, unpack_code),
3411 code.error_goto_if_null(item.result(), self.pos)))
3412 code.put_gotref(item.py_result())
3413 value_node = self.coerced_unpacked_items[i]
3414 value_node.generate_evaluation_code(code)
3415 code.put_error_if_neg(self.pos,
3416 "__Pyx_EndUnpack(%s)" % (
3417 self.iterator.py_result()))
3418 if debug_disposal_code:
3419 print("UnpackNode.generate_assignment_code:")
3420 print("...generating disposal code for %s" % self.iterator)
3421 self.iterator.generate_disposal_code(code)
3422 self.iterator.free_temps(code)
3423 self.iterator.release(code)
3425 for i in range(len(self.args)):
3426 self.args[i].generate_assignment_code(
3427 self.coerced_unpacked_items[i], code)
3429 code.putln("}")
3431 def generate_starred_assignment_code(self, rhs, code):
3432 code.globalstate.use_utility_code(unpacking_utility_code)
3434 for i, arg in enumerate(self.args):
3435 if arg.is_starred:
3436 starred_target = self.unpacked_items[i]
3437 fixed_args_left = self.args[:i]
3438 fixed_args_right = self.args[i+1:]
3439 break
3441 self.iterator.allocate(code)
3442 code.putln(
3443 "%s = PyObject_GetIter(%s); %s" % (
3444 self.iterator.result(),
3445 rhs.py_result(),
3446 code.error_goto_if_null(self.iterator.result(), self.pos)))
3447 code.put_gotref(self.iterator.py_result())
3448 rhs.generate_disposal_code(code)
3450 for item in self.unpacked_items:
3451 item.allocate(code)
3452 for i in range(len(fixed_args_left)):
3453 item = self.unpacked_items[i]
3454 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3455 self.iterator.py_result(), i)
3456 code.putln(
3457 "%s = %s; %s" % (
3458 item.result(),
3459 typecast(item.ctype(), py_object_type, unpack_code),
3460 code.error_goto_if_null(item.result(), self.pos)))
3461 code.put_gotref(item.py_result())
3462 value_node = self.coerced_unpacked_items[i]
3463 value_node.generate_evaluation_code(code)
3465 target_list = starred_target.result()
3466 code.putln("%s = PySequence_List(%s); %s" % (
3467 target_list, self.iterator.py_result(),
3468 code.error_goto_if_null(target_list, self.pos)))
3469 code.put_gotref(target_list)
3470 if fixed_args_right:
3471 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3472 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3473 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3474 (target_list, len(unpacked_right_args))))
3475 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3476 len(fixed_args_left), target_list,
3477 code.error_goto(self.pos)))
3478 code.putln('}')
3479 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3480 self.coerced_unpacked_items[::-1])):
3481 code.putln(
3482 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3483 arg.py_result(),
3484 target_list, target_list))
3485 # resize the list the hard way
3486 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3487 code.put_gotref(arg.py_result())
3488 coerced_arg.generate_evaluation_code(code)
3490 self.iterator.generate_disposal_code(code)
3491 self.iterator.free_temps(code)
3492 self.iterator.release(code)
3494 for i in range(len(self.args)):
3495 self.args[i].generate_assignment_code(
3496 self.coerced_unpacked_items[i], code)
3498 def annotate(self, code):
3499 for arg in self.args:
3500 arg.annotate(code)
3501 if self.unpacked_items:
3502 for arg in self.unpacked_items:
3503 arg.annotate(code)
3504 for arg in self.coerced_unpacked_items:
3505 arg.annotate(code)
3508 class TupleNode(SequenceNode):
3509 # Tuple constructor.
3511 type = tuple_type
3513 gil_message = "Constructing Python tuple"
3515 def analyse_types(self, env, skip_children=False):
3516 if len(self.args) == 0:
3517 self.is_temp = 0
3518 self.is_literal = 1
3519 else:
3520 SequenceNode.analyse_types(self, env, skip_children)
3522 def calculate_result_code(self):
3523 if len(self.args) > 0:
3524 error(self.pos, "Positive length tuples must be constructed.")
3525 else:
3526 return Naming.empty_tuple
3528 def calculate_constant_result(self):
3529 self.constant_result = tuple([
3530 arg.constant_result for arg in self.args])
3532 def compile_time_value(self, denv):
3533 values = self.compile_time_value_list(denv)
3534 try:
3535 return tuple(values)
3536 except Exception, e:
3537 self.compile_time_value_error(e)
3539 def generate_operation_code(self, code):
3540 if len(self.args) == 0:
3541 # result_code is Naming.empty_tuple
3542 return
3543 code.putln(
3544 "%s = PyTuple_New(%s); %s" % (
3545 self.result(),
3546 len(self.args),
3547 code.error_goto_if_null(self.result(), self.pos)))
3548 code.put_gotref(self.py_result())
3549 for i in range(len(self.args)):
3550 arg = self.args[i]
3551 if not arg.result_in_temp():
3552 code.put_incref(arg.result(), arg.ctype())
3553 code.putln(
3554 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3555 self.result(),
3556 i,
3557 arg.py_result()))
3558 code.put_giveref(arg.py_result())
3560 def generate_subexpr_disposal_code(self, code):
3561 # We call generate_post_assignment_code here instead
3562 # of generate_disposal_code, because values were stored
3563 # in the tuple using a reference-stealing operation.
3564 for arg in self.args:
3565 arg.generate_post_assignment_code(code)
3566 # Should NOT call free_temps -- this is invoked by the default
3567 # generate_evaluation_code which will do that.
3570 class ListNode(SequenceNode):
3571 # List constructor.
3573 # obj_conversion_errors [PyrexError] used internally
3574 # orignial_args [ExprNode] used internally
3576 obj_conversion_errors = []
3578 gil_message = "Constructing Python list"
3580 def type_dependencies(self, env):
3581 return ()
3583 def infer_type(self, env):
3584 # TOOD: Infer non-object list arrays.
3585 return list_type
3587 def analyse_expressions(self, env):
3588 SequenceNode.analyse_expressions(self, env)
3589 self.coerce_to_pyobject(env)
3591 def analyse_types(self, env):
3592 hold_errors()
3593 self.original_args = list(self.args)
3594 SequenceNode.analyse_types(self, env)
3595 self.type = list_type
3596 self.obj_conversion_errors = held_errors()
3597 release_errors(ignore=True)
3599 def coerce_to(self, dst_type, env):
3600 if dst_type.is_pyobject:
3601 for err in self.obj_conversion_errors:
3602 report_error(err)
3603 self.obj_conversion_errors = []
3604 if not self.type.subtype_of(dst_type):
3605 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3606 elif dst_type.is_ptr:
3607 base_type = dst_type.base_type
3608 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3609 for i in range(len(self.original_args)):
3610 arg = self.args[i]
3611 if isinstance(arg, CoerceToPyTypeNode):
3612 arg = arg.arg
3613 self.args[i] = arg.coerce_to(base_type, env)
3614 elif dst_type.is_struct:
3615 if len(self.args) > len(dst_type.scope.var_entries):
3616 error(self.pos, "Too may members for '%s'" % dst_type)
3617 else:
3618 if len(self.args) < len(dst_type.scope.var_entries):
3619 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3620 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3621 if isinstance(arg, CoerceToPyTypeNode):
3622 arg = arg.arg
3623 self.args[i] = arg.coerce_to(member.type, env)
3624 self.type = dst_type
3625 else:
3626 self.type = error_type
3627 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3628 return self
3630 def release_temp(self, env):
3631 if self.type.is_array:
3632 # To be valid C++, we must allocate the memory on the stack
3633 # manually and be sure not to reuse it for something else.
3634 pass
3635 else:
3636 SequenceNode.release_temp(self, env)
3638 def calculate_constant_result(self):
3639 self.constant_result = [
3640 arg.constant_result for arg in self.args]
3642 def compile_time_value(self, denv):
3643 return self.compile_time_value_list(denv)
3645 def generate_operation_code(self, code):
3646 if self.type.is_pyobject:
3647 for err in self.obj_conversion_errors:
3648 report_error(err)
3649 code.putln("%s = PyList_New(%s); %s" %
3650 (self.result(),
3651 len(self.args),
3652 code.error_goto_if_null(self.result(), self.pos)))
3653 code.put_gotref(self.py_result())
3654 for i in range(len(self.args)):
3655 arg = self.args[i]
3656 #if not arg.is_temp:
3657 if not arg.result_in_temp():
3658 code.put_incref(arg.result(), arg.ctype())
3659 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3660 (self.result(),
3661 i,
3662 arg.py_result()))
3663 code.put_giveref(arg.py_result())
3664 elif self.type.is_array:
3665 for i, arg in enumerate(self.args):
3666 code.putln("%s[%s] = %s;" % (
3667 self.result(),
3668 i,
3669 arg.result()))
3670 elif self.type.is_struct:
3671 for arg, member in zip(self.args, self.type.scope.var_entries):
3672 code.putln("%s.%s = %s;" % (
3673 self.result(),
3674 member.cname,
3675 arg.result()))
3676 else:
3677 raise InternalError("List type never specified")
3679 def generate_subexpr_disposal_code(self, code):
3680 # We call generate_post_assignment_code here instead
3681 # of generate_disposal_code, because values were stored
3682 # in the list using a reference-stealing operation.
3683 for arg in self.args:
3684 arg.generate_post_assignment_code(code)
3685 # Should NOT call free_temps -- this is invoked by the default
3686 # generate_evaluation_code which will do that.
3689 class ComprehensionNode(ExprNode):
3690 subexprs = ["target"]
3691 child_attrs = ["loop", "append"]
3693 def infer_type(self, env):
3694 return self.target.infer_type(env)
3696 def analyse_declarations(self, env):
3697 self.append.target = self # this is used in the PyList_Append of the inner loop
3698 self.loop.analyse_declarations(env)
3700 def analyse_types(self, env):
3701 self.target.analyse_expressions(env)
3702 self.type = self.target.type
3703 self.loop.analyse_expressions(env)
3705 def calculate_result_code(self):
3706 return self.target.result()
3708 def generate_result_code(self, code):
3709 self.generate_operation_code(code)
3711 def generate_operation_code(self, code):
3712 self.loop.generate_execution_code(code)
3714 def annotate(self, code):
3715 self.loop.annotate(code)
3718 class ComprehensionAppendNode(ExprNode):
3719 # Need to be careful to avoid infinite recursion:
3720 # target must not be in child_attrs/subexprs
3721 subexprs = ['expr']
3723 type = PyrexTypes.c_int_type
3725 def analyse_types(self, env):
3726 self.expr.analyse_types(env)
3727 if not self.expr.type.is_pyobject:
3728 self.expr = self.expr.coerce_to_pyobject(env)
3729 self.is_temp = 1
3731 def generate_result_code(self, code):
3732 if self.target.type is list_type:
3733 function = "PyList_Append"
3734 elif self.target.type is set_type:
3735 function = "PySet_Add"
3736 else:
3737 raise InternalError(
3738 "Invalid type for comprehension node: %s" % self.target.type)
3740 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3741 (self.result(),
3742 function,
3743 self.target.result(),
3744 self.expr.result(),
3745 code.error_goto_if(self.result(), self.pos)))
3747 class DictComprehensionAppendNode(ComprehensionAppendNode):
3748 subexprs = ['key_expr', 'value_expr']
3750 def analyse_types(self, env):
3751 self.key_expr.analyse_types(env)
3752 if not self.key_expr.type.is_pyobject:
3753 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3754 self.value_expr.analyse_types(env)
3755 if not self.value_expr.type.is_pyobject:
3756 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3757 self.is_temp = 1
3759 def generate_result_code(self, code):
3760 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3761 (self.result(),
3762 self.target.result(),
3763 self.key_expr.result(),
3764 self.value_expr.result(),
3765 code.error_goto_if(self.result(), self.pos)))
3768 class SetNode(ExprNode):
3769 # Set constructor.
3771 type = set_type
3773 subexprs = ['args']
3775 gil_message = "Constructing Python set"
3777 def analyse_types(self, env):
3778 for i in range(len(self.args)):
3779 arg = self.args[i]
3780 arg.analyse_types(env)
3781 self.args[i] = arg.coerce_to_pyobject(env)
3782 self.type = set_type
3783 self.is_temp = 1
3785 def calculate_constant_result(self):
3786 self.constant_result = set([
3787 arg.constant_result for arg in self.args])
3789 def compile_time_value(self, denv):
3790 values = [arg.compile_time_value(denv) for arg in self.args]
3791 try:
3792 return set(values)
3793 except Exception, e:
3794 self.compile_time_value_error(e)
3796 def generate_evaluation_code(self, code):
3797 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3798 self.allocate_temp_result(code)
3799 code.putln(
3800 "%s = PySet_New(0); %s" % (
3801 self.result(),
3802 code.error_goto_if_null(self.result(), self.pos)))
3803 code.put_gotref(self.py_result())
3804 for arg in self.args:
3805 arg.generate_evaluation_code(code)
3806 code.putln(
3807 code.error_goto_if_neg(
3808 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3809 self.pos))
3810 arg.generate_disposal_code(code)
3811 arg.free_temps(code)
3814 class DictNode(ExprNode):
3815 # Dictionary constructor.
3816 #
3817 # key_value_pairs [DictItemNode]
3818 #
3819 # obj_conversion_errors [PyrexError] used internally
3821 subexprs = ['key_value_pairs']
3822 is_temp = 1
3823 type = dict_type
3825 obj_conversion_errors = []
3827 def calculate_constant_result(self):
3828 self.constant_result = dict([
3829 item.constant_result for item in self.key_value_pairs])
3831 def compile_time_value(self, denv):
3832 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3833 for item in self.key_value_pairs]
3834 try:
3835 return dict(pairs)
3836 except Exception, e:
3837 self.compile_time_value_error(e)
3839 def type_dependencies(self, env):
3840 return ()
3842 def infer_type(self, env):
3843 # TOOD: Infer struct constructors.
3844 return dict_type
3846 def analyse_types(self, env):
3847 hold_errors()
3848 for item in self.key_value_pairs:
3849 item.analyse_types(env)
3850 self.obj_conversion_errors = held_errors()
3851 release_errors(ignore=True)
3853 def coerce_to(self, dst_type, env):
3854 if dst_type.is_pyobject:
3855 self.release_errors()
3856 if not self.type.subtype_of(dst_type):
3857 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3858 elif dst_type.is_struct_or_union:
3859 self.type = dst_type
3860 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3861 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3862 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3863 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3864 for item in self.key_value_pairs:
3865 if isinstance(item.key, CoerceToPyTypeNode):
3866 item.key = item.key.arg
3867 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3868 error(item.key.pos, "Invalid struct field identifier")
3869 item.key = StringNode(item.key.pos, value="<error>")
3870 else:
3871 key = str(item.key.value) # converts string literals to unicode in Py3
3872 member = dst_type.scope.lookup_here(key)
3873 if not member:
3874 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3875 else:
3876 value = item.value
3877 if isinstance(value, CoerceToPyTypeNode):
3878 value = value.arg
3879 item.value = value.coerce_to(member.type, env)
3880 else:
3881 self.type = error_type
3882 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3883 return self
3885 def release_errors(self):
3886 for err in self.obj_conversion_errors:
3887 report_error(err)
3888 self.obj_conversion_errors = []
3890 gil_message = "Constructing Python dict"
3892 def generate_evaluation_code(self, code):
3893 # Custom method used here because key-value
3894 # pairs are evaluated and used one at a time.
3895 code.mark_pos(self.pos)
3896 self.allocate_temp_result(code)
3897 if self.type.is_pyobject:
3898 self.release_errors()
3899 code.putln(
3900 "%s = PyDict_New(); %s" % (
3901 self.result(),
3902 code.error_goto_if_null(self.result(), self.pos)))
3903 code.put_gotref(self.py_result())
3904 for item in self.key_value_pairs:
3905 item.generate_evaluation_code(code)
3906 if self.type.is_pyobject:
3907 code.put_error_if_neg(self.pos,
3908 "PyDict_SetItem(%s, %s, %s)" % (
3909 self.result(),
3910 item.key.py_result(),
3911 item.value.py_result()))
3912 else:
3913 code.putln("%s.%s = %s;" % (
3914 self.result(),
3915 item.key.value,
3916 item.value.result()))
3917 item.generate_disposal_code(code)
3918 item.free_temps(code)
3920 def annotate(self, code):
3921 for item in self.key_value_pairs:
3922 item.annotate(code)
3924 class DictItemNode(ExprNode):
3925 # Represents a single item in a DictNode
3926 #
3927 # key ExprNode
3928 # value ExprNode
3929 subexprs = ['key', 'value']
3931 nogil_check = None # Parent DictNode takes care of it
3933 def calculate_constant_result(self):
3934 self.constant_result = (
3935 self.key.constant_result, self.value.constant_result)
3937 def analyse_types(self, env):
3938 self.key.analyse_types(env)
3939 self.value.analyse_types(env)
3940 self.key = self.key.coerce_to_pyobject(env)
3941 self.value = self.value.coerce_to_pyobject(env)
3943 def generate_evaluation_code(self, code):
3944 self.key.generate_evaluation_code(code)
3945 self.value.generate_evaluation_code(code)
3947 def generate_disposal_code(self, code):
3948 self.key.generate_disposal_code(code)
3949 self.value.generate_disposal_code(code)
3951 def free_temps(self, code):
3952 self.key.free_temps(code)
3953 self.value.free_temps(code)
3955 def __iter__(self):
3956 return iter([self.key, self.value])
3959 class ClassNode(ExprNode):
3960 # Helper class used in the implementation of Python
3961 # class definitions. Constructs a class object given
3962 # a name, tuple of bases and class dictionary.
3963 #
3964 # name EncodedString Name of the class
3965 # bases ExprNode Base class tuple
3966 # dict ExprNode Class dict (not owned by this node)
3967 # doc ExprNode or None Doc string
3968 # module_name string Name of defining module
3970 subexprs = ['bases', 'doc']
3972 def analyse_types(self, env):
3973 self.bases.analyse_types(env)
3974 if self.doc:
3975 self.doc.analyse_types(env)
3976 self.doc = self.doc.coerce_to_pyobject(env)
3977 self.module_name = env.global_scope().qualified_name
3978 self.type = py_object_type
3979 self.is_temp = 1
3980 env.use_utility_code(create_class_utility_code);
3982 gil_message = "Constructing Python class"
3984 def generate_result_code(self, code):
3985 cname = code.intern_identifier(self.name)
3986 if self.doc:
3987 code.put_error_if_neg(self.pos,
3988 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3989 self.dict.py_result(),
3990 self.doc.py_result()))
3991 code.putln(
3992 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3993 self.result(),
3994 self.bases.py_result(),
3995 self.dict.py_result(),
3996 cname,
3997 self.module_name,
3998 code.error_goto_if_null(self.result(), self.pos)))
3999 code.put_gotref(self.py_result())
4002 class UnboundMethodNode(ExprNode):
4003 # Helper class used in the implementation of Python
4004 # class definitions. Constructs an unbound method
4005 # object from a class and a function.
4006 #
4007 # function ExprNode Function object
4009 type = py_object_type
4010 is_temp = 1
4012 subexprs = ['function']
4014 def analyse_types(self, env):
4015 self.function.analyse_types(env)
4017 gil_message = "Constructing an unbound method"
4019 def generate_result_code(self, code):
4020 class_cname = code.pyclass_stack[-1].classobj.result()
4021 code.putln(
4022 "%s = PyMethod_New(%s, 0, %s); %s" % (
4023 self.result(),
4024 self.function.py_result(),
4025 class_cname,
4026 code.error_goto_if_null(self.result(), self.pos)))
4027 code.put_gotref(self.py_result())
4029 class PyCFunctionNode(AtomicExprNode):
4030 # Helper class used in the implementation of Python
4031 # class definitions. Constructs a PyCFunction object
4032 # from a PyMethodDef struct.
4033 #
4034 # pymethdef_cname string PyMethodDef structure
4036 type = py_object_type
4037 is_temp = 1
4039 def analyse_types(self, env):
4040 pass
4042 gil_message = "Constructing Python function"
4044 def generate_result_code(self, code):
4045 code.putln(
4046 "%s = PyCFunction_New(&%s, 0); %s" % (
4047 self.result(),
4048 self.pymethdef_cname,
4049 code.error_goto_if_null(self.result(), self.pos)))
4050 code.put_gotref(self.py_result())
4052 #-------------------------------------------------------------------
4053 #
4054 # Unary operator nodes
4055 #
4056 #-------------------------------------------------------------------
4058 compile_time_unary_operators = {
4059 'not': operator.not_,
4060 '~': operator.inv,
4061 '-': operator.neg,
4062 '+': operator.pos,
4063 }
4065 class UnopNode(ExprNode):
4066 # operator string
4067 # operand ExprNode
4068 #
4069 # Processing during analyse_expressions phase:
4070 #
4071 # analyse_c_operation
4072 # Called when the operand is not a pyobject.
4073 # - Check operand type and coerce if needed.
4074 # - Determine result type and result code fragment.
4075 # - Allocate temporary for result if needed.
4077 subexprs = ['operand']
4078 infix = True
4080 def calculate_constant_result(self):
4081 func = compile_time_unary_operators[self.operator]
4082 self.constant_result = func(self.operand.constant_result)
4084 def compile_time_value(self, denv):
4085 func = compile_time_unary_operators.get(self.operator)
4086 if not func:
4087 error(self.pos,
4088 "Unary '%s' not supported in compile-time expression"
4089 % self.operator)
4090 operand = self.operand.compile_time_value(denv)
4091 try:
4092 return func(operand)
4093 except Exception, e:
4094 self.compile_time_value_error(e)
4096 def infer_type(self, env):
4097 return self.operand.infer_type(env)
4099 def analyse_types(self, env):
4100 self.operand.analyse_types(env)
4101 if self.is_py_operation():
4102 self.coerce_operand_to_pyobject(env)
4103 self.type = py_object_type
4104 self.is_temp = 1
4105 else:
4106 self.analyse_c_operation(env)
4108 def check_const(self):
4109 return self.operand.check_const()
4111 def is_py_operation(self):
4112 return self.operand.type.is_pyobject
4114 def nogil_check(self, env):
4115 if self.is_py_operation():
4116 self.gil_error()
4118 def coerce_operand_to_pyobject(self, env):
4119 self.operand = self.operand.coerce_to_pyobject(env)
4121 def generate_result_code(self, code):
4122 if self.operand.type.is_pyobject:
4123 self.generate_py_operation_code(code)
4125 def generate_py_operation_code(self, code):
4126 function = self.py_operation_function()
4127 code.putln(
4128 "%s = %s(%s); %s" % (
4129 self.result(),
4130 function,
4131 self.operand.py_result(),
4132 code.error_goto_if_null(self.result(), self.pos)))
4133 code.put_gotref(self.py_result())
4135 def type_error(self):
4136 if not self.operand.type.is_error:
4137 error(self.pos, "Invalid operand type for '%s' (%s)" %
4138 (self.operator, self.operand.type))
4139 self.type = PyrexTypes.error_type
4142 class NotNode(ExprNode):
4143 # 'not' operator
4144 #
4145 # operand ExprNode
4147 type = PyrexTypes.c_bint_type
4149 subexprs = ['operand']
4151 def calculate_constant_result(self):
4152 self.constant_result = not self.operand.constant_result
4154 def compile_time_value(self, denv):
4155 operand = self.operand.compile_time_value(denv)
4156 try:
4157 return not operand
4158 except Exception, e:
4159 self.compile_time_value_error(e)
4161 def infer_type(self, env):
4162 return PyrexTypes.c_bint_type
4164 def analyse_types(self, env):
4165 self.operand.analyse_types(env)
4166 self.operand = self.operand.coerce_to_boolean(env)
4168 def calculate_result_code(self):
4169 return "(!%s)" % self.operand.result()
4171 def generate_result_code(self, code):
4172 pass
4175 class UnaryPlusNode(UnopNode):
4176 # unary '+' operator
4178 operator = '+'
4180 def analyse_c_operation(self, env):
4181 self.type = self.operand.type
4183 def py_operation_function(self):
4184 return "PyNumber_Positive"
4186 def calculate_result_code(self):
4187 return self.operand.result()
4190 class UnaryMinusNode(UnopNode):
4191 # unary '-' operator
4193 operator = '-'
4195 def analyse_c_operation(self, env):
4196 if self.operand.type.is_numeric:
4197 self.type = self.operand.type
4198 else:
4199 self.type_error()
4200 if self.type.is_complex:
4201 self.infix = False
4203 def py_operation_function(self):
4204 return "PyNumber_Negative"
4206 def calculate_result_code(self):
4207 if self.infix:
4208 return "(-%s)" % self.operand.result()
4209 else:
4210 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4212 def get_constant_c_result_code(self):
4213 value = self.operand.get_constant_c_result_code()
4214 if value:
4215 return "(-%s)" % (value)
4217 class TildeNode(UnopNode):
4218 # unary '~' operator
4220 def analyse_c_operation(self, env):
4221 if self.operand.type.is_int:
4222 self.type = self.operand.type
4223 else:
4224 self.type_error()
4226 def py_operation_function(self):
4227 return "PyNumber_Invert"
4229 def calculate_result_code(self):
4230 return "(~%s)" % self.operand.result()
4233 class AmpersandNode(ExprNode):
4234 # The C address-of operator.
4235 #
4236 # operand ExprNode
4238 subexprs = ['operand']
4240 def infer_type(self, env):
4241 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4243 def analyse_types(self, env):
4244 self.operand.analyse_types(env)
4245 argtype = self.operand.type
4246 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4247 self.error("Taking address of non-lvalue")
4248 return
4249 if argtype.is_pyobject:
4250 self.error("Cannot take address of Python variable")
4251 return
4252 self.type = PyrexTypes.c_ptr_type(argtype)
4254 def check_const(self):
4255 return self.operand.check_const_addr()
4257 def error(self, mess):
4258 error(self.pos, mess)
4259 self.type = PyrexTypes.error_type
4260 self.result_code = "<error>"
4262 def calculate_result_code(self):
4263 return "(&%s)" % self.operand.result()
4265 def generate_result_code(self, code):
4266 pass
4269 unop_node_classes = {
4270 "+": UnaryPlusNode,
4271 "-": UnaryMinusNode,
4272 "~": TildeNode,
4273 }
4275 def unop_node(pos, operator, operand):
4276 # Construct unnop node of appropriate class for
4277 # given operator.
4278 if isinstance(operand, IntNode) and operator == '-':
4279 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4280 elif isinstance(operand, UnopNode) and operand.operator == operator:
4281 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4282 return unop_node_classes[operator](pos,
4283 operator = operator,
4284 operand = operand)
4287 class TypecastNode(ExprNode):
4288 # C type cast
4289 #
4290 # operand ExprNode
4291 # base_type CBaseTypeNode
4292 # declarator CDeclaratorNode
4293 #
4294 # If used from a transform, one can if wanted specify the attribute
4295 # "type" directly and leave base_type and declarator to None
4297 subexprs = ['operand']
4298 base_type = declarator = type = None
4300 def type_dependencies(self, env):
4301 return ()
4303 def infer_type(self, env):
4304 if self.type is None:
4305 base_type = self.base_type.analyse(env)
4306 _, self.type = self.declarator.analyse(base_type, env)
4307 return self.type
4309 def analyse_types(self, env):
4310 if self.type is None:
4311 base_type = self.base_type.analyse(env)
4312 _, self.type = self.declarator.analyse(base_type, env)
4313 if self.type.is_cfunction:
4314 error(self.pos,
4315 "Cannot cast to a function type")
4316 self.type = PyrexTypes.error_type
4317 self.operand.analyse_types(env)
4318 to_py = self.type.is_pyobject
4319 from_py = self.operand.type.is_pyobject
4320 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4321 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4322 if to_py and not from_py:
4323 if self.operand.type.can_coerce_to_pyobject(env):
4324 self.result_ctype = py_object_type
4325 self.operand = self.operand.coerce_to_pyobject(env)
4326 else:
4327 if self.operand.type.is_ptr:
4328 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4329 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4330 else:
4331 # Should this be an error?
4332 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4333 self.operand = self.operand.coerce_to_simple(env)
4334 elif from_py and not to_py:
4335 if self.type.create_from_py_utility_code(env):
4336 self.operand = self.operand.coerce_to(self.type, env)
4337 elif self.type.is_ptr:
4338 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4339 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4340 else:
4341 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4342 elif from_py and to_py:
4343 if self.typecheck and self.type.is_extension_type:
4344 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4346 def nogil_check(self, env):
4347 if self.type and self.type.is_pyobject and self.is_temp:
4348 self.gil_error()
4350 def check_const(self):
4351 return self.operand.check_const()
4353 def calculate_constant_result(self):
4354 # we usually do not know the result of a type cast at code
4355 # generation time
4356 pass
4358 def calculate_result_code(self):
4359 opnd = self.operand
4360 return self.type.cast_code(opnd.result())
4362 def get_constant_c_result_code(self):
4363 operand_result = self.operand.get_constant_c_result_code()
4364 if operand_result:
4365 return self.type.cast_code(operand_result)
4367 def result_as(self, type):
4368 if self.type.is_pyobject and not self.is_temp:
4369 # Optimise away some unnecessary casting
4370 return self.operand.result_as(type)
4371 else:
4372 return ExprNode.result_as(self, type)
4374 def generate_result_code(self, code):
4375 if self.is_temp:
4376 code.putln(
4377 "%s = (PyObject *)%s;" % (
4378 self.result(),
4379 self.operand.result()))
4380 code.put_incref(self.result(), self.ctype())
4383 class SizeofNode(ExprNode):
4384 # Abstract base class for sizeof(x) expression nodes.
4386 type = PyrexTypes.c_size_t_type
4388 def check_const(self):
4389 return True
4391 def generate_result_code(self, code):
4392 pass
4395 class SizeofTypeNode(SizeofNode):
4396 # C sizeof function applied to a type
4397 #
4398 # base_type CBaseTypeNode
4399 # declarator CDeclaratorNode
4401 subexprs = []
4402 arg_type = None
4404 def analyse_types(self, env):
4405 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4406 # this could be better handled by more uniformly treating types as runtime-available objects
4407 if 0 and self.base_type.module_path:
4408 path = self.base_type.module_path
4409 obj = env.lookup(path[0])
4410 if obj.as_module is None:
4411 operand = NameNode(pos=self.pos, name=path[0])
4412 for attr in path[1:]:
4413 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4414 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4415 self.operand = operand
4416 self.__class__ = SizeofVarNode
4417 self.analyse_types(env)
4418 return
4419 if self.arg_type is None:
4420 base_type = self.base_type.analyse(env)
4421 _, arg_type = self.declarator.analyse(base_type, env)
4422 self.arg_type = arg_type
4423 self.check_type()
4425 def check_type(self):
4426 arg_type = self.arg_type
4427 if arg_type.is_pyobject and not arg_type.is_extension_type:
4428 error(self.pos, "Cannot take sizeof Python object")
4429 elif arg_type.is_void:
4430 error(self.pos, "Cannot take sizeof void")
4431 elif not arg_type.is_complete():
4432 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4434 def calculate_result_code(self):
4435 if self.arg_type.is_extension_type:
4436 # the size of the pointer is boring
4437 # we want the size of the actual struct
4438 arg_code = self.arg_type.declaration_code("", deref=1)
4439 else:
4440 arg_code = self.arg_type.declaration_code("")
4441 return "(sizeof(%s))" % arg_code
4444 class SizeofVarNode(SizeofNode):
4445 # C sizeof function applied to a variable
4446 #
4447 # operand ExprNode
4449 subexprs = ['operand']
4451 def analyse_types(self, env):
4452 # We may actually be looking at a type rather than a variable...
4453 # If we are, traditional analysis would fail...
4454 operand_as_type = self.operand.analyse_as_type(env)
4455 if operand_as_type:
4456 self.arg_type = operand_as_type
4457 self.__class__ = SizeofTypeNode
4458 self.check_type()
4459 else:
4460 self.operand.analyse_types(env)
4462 def calculate_result_code(self):
4463 return "(sizeof(%s))" % self.operand.result()
4465 def generate_result_code(self, code):
4466 pass
4468 class TypeofNode(ExprNode):
4469 # Compile-time type of an expression, as a string.
4470 #
4471 # operand ExprNode
4472 # literal StringNode # internal
4474 literal = None
4475 type = py_object_type
4477 subexprs = ['literal'] # 'operand' will be ignored after type analysis!
4479 def analyse_types(self, env):
4480 self.operand.analyse_types(env)
4481 self.literal = StringNode(
4482 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4483 self.literal.analyse_types(env)
4484 self.literal = self.literal.coerce_to_pyobject(env)
4486 def generate_evaluation_code(self, code):
4487 self.literal.generate_evaluation_code(code)
4489 def calculate_result_code(self):
4490 return self.literal.calculate_result_code()
4492 #-------------------------------------------------------------------
4493 #
4494 # Binary operator nodes
4495 #
4496 #-------------------------------------------------------------------
4498 def _not_in(x, seq):
4499 return x not in seq
4501 compile_time_binary_operators = {
4502 '<': operator.lt,
4503 '<=': operator.le,
4504 '==': operator.eq,
4505 '!=': operator.ne,
4506 '>=': operator.ge,
4507 '>': operator.gt,
4508 'is': operator.is_,
4509 'is_not': operator.is_not,
4510 '+': operator.add,
4511 '&': operator.and_,
4512 '/': operator.truediv,
4513 '//': operator.floordiv,
4514 '<<': operator.lshift,
4515 '%': operator.mod,
4516 '*': operator.mul,
4517 '|': operator.or_,
4518 '**': operator.pow,
4519 '>>': operator.rshift,
4520 '-': operator.sub,
4521 '^': operator.xor,
4522 'in': operator.contains,
4523 'not_in': _not_in,
4524 }
4526 def get_compile_time_binop(node):
4527 func = compile_time_binary_operators.get(node.operator)
4528 if not func:
4529 error(node.pos,
4530 "Binary '%s' not supported in compile-time expression"
4531 % node.operator)
4532 return func
4534 class BinopNode(ExprNode):
4535 # operator string
4536 # operand1 ExprNode
4537 # operand2 ExprNode
4538 #
4539 # Processing during analyse_expressions phase:
4540 #
4541 # analyse_c_operation
4542 # Called when neither operand is a pyobject.
4543 # - Check operand types and coerce if needed.
4544 # - Determine result type and result code fragment.
4545 # - Allocate temporary for result if needed.
4547 subexprs = ['operand1', 'operand2']
4549 def calculate_constant_result(self):
4550 func = compile_time_binary_operators[self.operator]
4551 self.constant_result = func(
4552 self.operand1.constant_result,
4553 self.operand2.constant_result)
4555 def compile_time_value(self, denv):
4556 func = get_compile_time_binop(self)
4557 operand1 = self.operand1.compile_time_value(denv)
4558 operand2 = self.operand2.compile_time_value(denv)
4559 try:
4560 return func(operand1, operand2)
4561 except Exception, e:
4562 self.compile_time_value_error(e)
4564 def infer_type(self, env):
4565 return self.result_type(self.operand1.infer_type(env),
4566 self.operand2.infer_type(env))
4568 def analyse_types(self, env):
4569 self.operand1.analyse_types(env)
4570 self.operand2.analyse_types(env)
4571 if self.is_py_operation():
4572 self.coerce_operands_to_pyobjects(env)
4573 self.type = py_object_type
4574 self.is_temp = 1
4575 else:
4576 self.analyse_c_operation(env)
4578 def is_py_operation(self):
4579 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4581 def is_py_operation_types(self, type1, type2):
4582 return type1.is_pyobject or type2.is_pyobject
4584 def result_type(self, type1, type2):
4585 if self.is_py_operation_types(type1, type2):
4586 return py_object_type
4587 else:
4588 return self.compute_c_result_type(type1, type2)
4590 def nogil_check(self, env):
4591 if self.is_py_operation():
4592 self.gil_error()
4594 def coerce_operands_to_pyobjects(self, env):
4595 self.operand1 = self.operand1.coerce_to_pyobject(env)
4596 self.operand2 = self.operand2.coerce_to_pyobject(env)
4598 def check_const(self):
4599 return self.operand1.check_const() and self.operand2.check_const()
4601 def generate_result_code(self, code):
4602 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4603 if self.operand1.type.is_pyobject:
4604 function = self.py_operation_function()
4605 if function == "PyNumber_Power":
4606 extra_args = ", Py_None"
4607 else:
4608 extra_args = ""
4609 code.putln(
4610 "%s = %s(%s, %s%s); %s" % (
4611 self.result(),
4612 function,
4613 self.operand1.py_result(),
4614 self.operand2.py_result(),
4615 extra_args,
4616 code.error_goto_if_null(self.result(), self.pos)))
4617 code.put_gotref(self.py_result())
4619 def type_error(self):
4620 if not (self.operand1.type.is_error
4621 or self.operand2.type.is_error):
4622 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4623 (self.operator, self.operand1.type,
4624 self.operand2.type))
4625 self.type = PyrexTypes.error_type
4628 class NumBinopNode(BinopNode):
4629 # Binary operation taking numeric arguments.
4631 infix = True
4633 def analyse_c_operation(self, env):
4634 type1 = self.operand1.type
4635 type2 = self.operand2.type
4636 self.type = self.compute_c_result_type(type1, type2)
4637 if not self.type:
4638 self.type_error()
4639 return
4640 if self.type.is_complex:
4641 self.infix = False
4642 if not self.infix:
4643 self.operand1 = self.operand1.coerce_to(self.type, env)
4644 self.operand2 = self.operand2.coerce_to(self.type, env)
4646 def compute_c_result_type(self, type1, type2):
4647 if self.c_types_okay(type1, type2):
4648 return PyrexTypes.widest_numeric_type(type1, type2)
4649 else:
4650 return None
4652 def get_constant_c_result_code(self):
4653 value1 = self.operand1.get_constant_c_result_code()
4654 value2 = self.operand2.get_constant_c_result_code()
4655 if value1 and value2:
4656 return "(%s %s %s)" % (value1, self.operator, value2)
4657 else:
4658 return None
4660 def c_types_okay(self, type1, type2):
4661 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4662 return (type1.is_numeric or type1.is_enum) \
4663 and (type2.is_numeric or type2.is_enum)
4665 def calculate_result_code(self):
4666 if self.infix:
4667 return "(%s %s %s)" % (
4668 self.operand1.result(),
4669 self.operator,
4670 self.operand2.result())
4671 else:
4672 func = self.type.binary_op(self.operator)
4673 if func is None:
4674 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4675 return "%s(%s, %s)" % (
4676 func,
4677 self.operand1.result(),
4678 self.operand2.result())
4680 def py_operation_function(self):
4681 return self.py_functions[self.operator]
4683 py_functions = {
4684 "|": "PyNumber_Or",
4685 "^": "PyNumber_Xor",
4686 "&": "PyNumber_And",
4687 "<<": "PyNumber_Lshift",
4688 ">>": "PyNumber_Rshift",
4689 "+": "PyNumber_Add",
4690 "-": "PyNumber_Subtract",
4691 "*": "PyNumber_Multiply",
4692 "/": "__Pyx_PyNumber_Divide",
4693 "//": "PyNumber_FloorDivide",
4694 "%": "PyNumber_Remainder",
4695 "**": "PyNumber_Power"
4696 }
4699 class IntBinopNode(NumBinopNode):
4700 # Binary operation taking integer arguments.
4702 def c_types_okay(self, type1, type2):
4703 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4704 return (type1.is_int or type1.is_enum) \
4705 and (type2.is_int or type2.is_enum)
4708 class AddNode(NumBinopNode):
4709 # '+' operator.
4711 def is_py_operation_types(self, type1, type2):
4712 if type1.is_string and type2.is_string:
4713 return 1
4714 else:
4715 return NumBinopNode.is_py_operation_types(self, type1, type2)
4717 def compute_c_result_type(self, type1, type2):
4718 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4719 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4720 return type1
4721 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4722 return type2
4723 else:
4724 return NumBinopNode.compute_c_result_type(
4725 self, type1, type2)
4728 class SubNode(NumBinopNode):
4729 # '-' operator.
4731 def compute_c_result_type(self, type1, type2):
4732 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4733 return type1
4734 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4735 return PyrexTypes.c_int_type
4736 else:
4737 return NumBinopNode.compute_c_result_type(
4738 self, type1, type2)
4741 class MulNode(NumBinopNode):
4742 # '*' operator.
4744 def is_py_operation_types(self, type1, type2):
4745 if (type1.is_string and type2.is_int) \
4746 or (type2.is_string and type1.is_int):
4747 return 1
4748 else:
4749 return NumBinopNode.is_py_operation_types(self, type1, type2)
4752 class DivNode(NumBinopNode):
4753 # '/' or '//' operator.
4755 cdivision = None
4756 truedivision = None # == "unknown" if operator == '/'
4757 ctruedivision = False
4758 cdivision_warnings = False
4759 zerodivision_check = None
4761 def find_compile_time_binary_operator(self, op1, op2):
4762 func = compile_time_binary_operators[self.operator]
4763 if self.operator == '/' and self.truedivision is None:
4764 # => true div for floats, floor div for integers
4765 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4766 func = compile_time_binary_operators['//']
4767 return func
4769 def calculate_constant_result(self):
4770 op1 = self.operand1.constant_result
4771 op2 = self.operand2.constant_result
4772 func = self.find_compile_time_binary_operator(op1, op2)
4773 self.constant_result = func(
4774 self.operand1.constant_result,
4775 self.operand2.constant_result)
4777 def compile_time_value(self, denv):
4778 operand1 = self.operand1.compile_time_value(denv)
4779 operand2 = self.operand2.compile_time_value(denv)
4780 try:
4781 func = self.find_compile_time_binary_operator(
4782 self, operand1, operand2)
4783 return func(operand1, operand2)
4784 except Exception, e:
4785 self.compile_time_value_error(e)
4787 def analyse_types(self, env):
4788 if self.cdivision or env.directives['cdivision']:
4789 self.ctruedivision = False
4790 else:
4791 self.ctruedivision = self.truedivision
4792 NumBinopNode.analyse_types(self, env)
4793 if not self.type.is_pyobject:
4794 self.zerodivision_check = (
4795 self.cdivision is None and not env.directives['cdivision']
4796 and (self.operand2.constant_result is not_a_constant or
4797 self.operand2.constant_result == 0))
4798 if self.zerodivision_check or env.directives['cdivision_warnings']:
4799 # Need to check ahead of time to warn or raise zero division error
4800 self.operand1 = self.operand1.coerce_to_simple(env)
4801 self.operand2 = self.operand2.coerce_to_simple(env)
4802 if env.nogil:
4803 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4805 def compute_c_result_type(self, type1, type2):
4806 if self.operator == '/' and self.ctruedivision:
4807 if not type1.is_float and not type2.is_float:
4808 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4809 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4810 return widest_type
4811 return NumBinopNode.compute_c_result_type(self, type1, type2)
4813 def zero_division_message(self):
4814 if self.type.is_int:
4815 return "integer division or modulo by zero"
4816 else:
4817 return "float division"
4819 def generate_evaluation_code(self, code):
4820 if not self.type.is_pyobject and not self.type.is_complex:
4821 if self.cdivision is None:
4822 self.cdivision = (code.globalstate.directives['cdivision']
4823 or not self.type.signed
4824 or self.type.is_float)
4825 if not self.cdivision:
4826 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4827 NumBinopNode.generate_evaluation_code(self, code)
4828 self.generate_div_warning_code(code)
4830 def generate_div_warning_code(self, code):
4831 if not self.type.is_pyobject:
4832 if self.zerodivision_check:
4833 if not self.infix:
4834 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4835 else:
4836 zero_test = "%s == 0" % self.operand2.result()
4837 code.putln("if (unlikely(%s)) {" % zero_test)
4838 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4839 code.putln(code.error_goto(self.pos))
4840 code.putln("}")
4841 if self.type.is_int and self.type.signed and self.operator != '%':
4842 code.globalstate.use_utility_code(division_overflow_test_code)
4843 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4844 self.type.declaration_code(''),
4845 self.operand2.result(),
4846 self.operand1.result()))
4847 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4848 code.putln(code.error_goto(self.pos))
4849 code.putln("}")
4850 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4851 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4852 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4853 self.operand1.result(),
4854 self.operand2.result()))
4855 code.putln(code.set_error_info(self.pos));
4856 code.put("if (__Pyx_cdivision_warning()) ")
4857 code.put_goto(code.error_label)
4858 code.putln("}")
4860 def calculate_result_code(self):
4861 if self.type.is_complex:
4862 return NumBinopNode.calculate_result_code(self)
4863 elif self.type.is_float and self.operator == '//':
4864 return "floor(%s / %s)" % (
4865 self.operand1.result(),
4866 self.operand2.result())
4867 elif self.truedivision or self.cdivision:
4868 op1 = self.operand1.result()
4869 op2 = self.operand2.result()
4870 if self.truedivision:
4871 if self.type != self.operand1.type:
4872 op1 = self.type.cast_code(op1)
4873 if self.type != self.operand2.type:
4874 op2 = self.type.cast_code(op2)
4875 return "(%s / %s)" % (op1, op2)
4876 else:
4877 return "__Pyx_div_%s(%s, %s)" % (
4878 self.type.specalization_name(),
4879 self.operand1.result(),
4880 self.operand2.result())
4883 class ModNode(DivNode):
4884 # '%' operator.
4886 def is_py_operation_types(self, type1, type2):
4887 return (type1.is_string
4888 or type2.is_string
4889 or NumBinopNode.is_py_operation_types(self, type1, type2))
4891 def zero_division_message(self):
4892 if self.type.is_int:
4893 return "integer division or modulo by zero"
4894 else:
4895 return "float divmod()"
4897 def generate_evaluation_code(self, code):
4898 if not self.type.is_pyobject:
4899 if self.cdivision is None:
4900 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4901 if not self.cdivision:
4902 if self.type.is_int:
4903 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4904 else:
4905 code.globalstate.use_utility_code(
4906 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4907 NumBinopNode.generate_evaluation_code(self, code)
4908 self.generate_div_warning_code(code)
4910 def calculate_result_code(self):
4911 if self.cdivision:
4912 if self.type.is_float:
4913 return "fmod%s(%s, %s)" % (
4914 self.type.math_h_modifier,
4915 self.operand1.result(),
4916 self.operand2.result())
4917 else:
4918 return "(%s %% %s)" % (
4919 self.operand1.result(),
4920 self.operand2.result())
4921 else:
4922 return "__Pyx_mod_%s(%s, %s)" % (
4923 self.type.specalization_name(),
4924 self.operand1.result(),
4925 self.operand2.result())
4927 class PowNode(NumBinopNode):
4928 # '**' operator.
4930 def analyse_c_operation(self, env):
4931 NumBinopNode.analyse_c_operation(self, env)
4932 if self.type.is_complex:
4933 error(self.pos, "complex powers not yet supported")
4934 self.pow_func = "<error>"
4935 elif self.type.is_float:
4936 self.pow_func = "pow"
4937 else:
4938 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4939 env.use_utility_code(
4940 int_pow_utility_code.specialize(func_name=self.pow_func,
4941 type=self.type.declaration_code('')))
4943 def calculate_result_code(self):
4944 return "%s(%s, %s)" % (
4945 self.pow_func,
4946 self.operand1.result(),
4947 self.operand2.result())
4950 # Note: This class is temporary "shut down" into an ineffective mode temp
4951 # allocation mode.
4952 #
4953 # More sophisticated temp reuse was going on before,
4954 # one could have a look at adding this again after /all/ classes
4955 # are converted to the new temp scheme. (The temp juggling cannot work
4956 # otherwise).
4957 class BoolBinopNode(ExprNode):
4958 # Short-circuiting boolean operation.
4959 #
4960 # operator string
4961 # operand1 ExprNode
4962 # operand2 ExprNode
4964 subexprs = ['operand1', 'operand2']
4966 def infer_type(self, env):
4967 type1 = self.operand1.infer_type(env)
4968 type2 = self.operand2.infer_type(env)
4969 return PyrexTypes.spanning_type(type1, type2)
4971 def calculate_constant_result(self):
4972 if self.operator == 'and':
4973 self.constant_result = \
4974 self.operand1.constant_result and \
4975 self.operand2.constant_result
4976 else:
4977 self.constant_result = \
4978 self.operand1.constant_result or \
4979 self.operand2.constant_result
4981 def compile_time_value(self, denv):
4982 if self.operator == 'and':
4983 return self.operand1.compile_time_value(denv) \
4984 and self.operand2.compile_time_value(denv)
4985 else:
4986 return self.operand1.compile_time_value(denv) \
4987 or self.operand2.compile_time_value(denv)
4989 def coerce_to_boolean(self, env):
4990 self.operand1 = self.operand1.coerce_to_boolean(env)
4991 self.operand2 = self.operand2.coerce_to_boolean(env)
4992 self.type = PyrexTypes.c_bint_type
4993 return self
4995 def analyse_types(self, env):
4996 self.operand1.analyse_types(env)
4997 self.operand2.analyse_types(env)
4998 self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
4999 self.operand1 = self.operand1.coerce_to(self.type, env)
5000 self.operand2 = self.operand2.coerce_to(self.type, env)
5002 # For what we're about to do, it's vital that
5003 # both operands be temp nodes.
5004 self.operand1 = self.operand1.coerce_to_simple(env)
5005 self.operand2 = self.operand2.coerce_to_simple(env)
5006 self.is_temp = 1
5008 gil_message = "Truth-testing Python object"
5010 def check_const(self):
5011 return self.operand1.check_const() and self.operand2.check_const()
5013 def generate_evaluation_code(self, code):
5014 code.mark_pos(self.pos)
5015 self.operand1.generate_evaluation_code(code)
5016 test_result, uses_temp = self.generate_operand1_test(code)
5017 if self.operator == 'and':
5018 sense = ""
5019 else:
5020 sense = "!"
5021 code.putln(
5022 "if (%s%s) {" % (
5023 sense,
5024 test_result))
5025 if uses_temp:
5026 code.funcstate.release_temp(test_result)
5027 self.operand1.generate_disposal_code(code)
5028 self.operand2.generate_evaluation_code(code)
5029 self.allocate_temp_result(code)
5030 self.operand2.make_owned_reference(code)
5031 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
5032 self.operand2.generate_post_assignment_code(code)
5033 self.operand2.free_temps(code)
5034 code.putln("} else {")
5035 self.operand1.make_owned_reference(code)
5036 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
5037 self.operand1.generate_post_assignment_code(code)
5038 self.operand1.free_temps(code)
5039 code.putln("}")
5041 def generate_operand1_test(self, code):
5042 # Generate code to test the truth of the first operand.
5043 if self.type.is_pyobject:
5044 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
5045 manage_ref=False)
5046 code.putln(
5047 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5048 test_result,
5049 self.operand1.py_result(),
5050 code.error_goto_if_neg(test_result, self.pos)))
5051 else:
5052 test_result = self.operand1.result()
5053 return (test_result, self.type.is_pyobject)
5056 class CondExprNode(ExprNode):
5057 # Short-circuiting conditional expression.
5058 #
5059 # test ExprNode
5060 # true_val ExprNode
5061 # false_val ExprNode
5063 true_val = None
5064 false_val = None
5066 subexprs = ['test', 'true_val', 'false_val']
5068 def type_dependencies(self, env):
5069 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5071 def infer_type(self, env):
5072 return self.compute_result_type(self.true_val.infer_type(env),
5073 self.false_val.infer_type(env))
5075 def calculate_constant_result(self):
5076 if self.test.constant_result:
5077 self.constant_result = self.true_val.constant_result
5078 else:
5079 self.constant_result = self.false_val.constant_result
5081 def analyse_types(self, env):
5082 self.test.analyse_types(env)
5083 self.test = self.test.coerce_to_boolean(env)
5084 self.true_val.analyse_types(env)
5085 self.false_val.analyse_types(env)
5086 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
5087 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
5088 self.true_val = self.true_val.coerce_to(self.type, env)
5089 self.false_val = self.false_val.coerce_to(self.type, env)
5090 self.is_temp = 1
5091 if self.type == PyrexTypes.error_type:
5092 self.type_error()
5094 def compute_result_type(self, type1, type2):
5095 if type1 == type2:
5096 return type1
5097 elif type1.is_numeric and type2.is_numeric:
5098 return PyrexTypes.widest_numeric_type(type1, type2)
5099 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
5100 return type2
5101 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
5102 return type1
5103 elif type1.is_pyobject or type2.is_pyobject:
5104 return py_object_type
5105 elif type1.assignable_from(type2):
5106 return type1
5107 elif type2.assignable_from(type1):
5108 return type2
5109 else:
5110 return PyrexTypes.error_type
5112 def type_error(self):
5113 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5114 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5115 (self.true_val.type, self.false_val.type))
5116 self.type = PyrexTypes.error_type
5118 def check_const(self):
5119 return (self.test.check_const()
5120 and self.true_val.check_const()
5121 and self.false_val.check_const())
5123 def generate_evaluation_code(self, code):
5124 # Because subexprs may not be evaluated we can use a more optimal
5125 # subexpr allocation strategy than the default, so override evaluation_code.
5127 code.mark_pos(self.pos)
5128 self.allocate_temp_result(code)
5129 self.test.generate_evaluation_code(code)
5130 code.putln("if (%s) {" % self.test.result() )
5131 self.eval_and_get(code, self.true_val)
5132 code.putln("} else {")
5133 self.eval_and_get(code, self.false_val)
5134 code.putln("}")
5135 self.test.generate_disposal_code(code)
5136 self.test.free_temps(code)
5138 def eval_and_get(self, code, expr):
5139 expr.generate_evaluation_code(code)
5140 expr.make_owned_reference(code)
5141 code.putln("%s = %s;" % (self.result(), expr.result()))
5142 expr.generate_post_assignment_code(code)
5143 expr.free_temps(code)
5145 richcmp_constants = {
5146 "<" : "Py_LT",
5147 "<=": "Py_LE",
5148 "==": "Py_EQ",
5149 "!=": "Py_NE",
5150 "<>": "Py_NE",
5151 ">" : "Py_GT",
5152 ">=": "Py_GE",
5153 }
5155 class CmpNode(object):
5156 # Mixin class containing code common to PrimaryCmpNodes
5157 # and CascadedCmpNodes.
5159 def infer_types(self, env):
5160 # TODO: Actually implement this (after merging with -unstable).
5161 return py_object_type
5163 def calculate_cascaded_constant_result(self, operand1_result):
5164 func = compile_time_binary_operators[self.operator]
5165 operand2_result = self.operand2.constant_result
5166 result = func(operand1_result, operand2_result)
5167 if result and self.cascade:
5168 result = result and \
5169 self.cascade.cascaded_compile_time_value(operand2_result)
5170 self.constant_result = result
5172 def cascaded_compile_time_value(self, operand1, denv):
5173 func = get_compile_time_binop(self)
5174 operand2 = self.operand2.compile_time_value(denv)
5175 try:
5176 result = func(operand1, operand2)
5177 except Exception, e:
5178 self.compile_time_value_error(e)
5179 result = None
5180 if result:
5181 cascade = self.cascade
5182 if cascade:
5183 # FIXME: I bet this must call cascaded_compile_time_value()
5184 result = result and cascade.compile_time_value(operand2, denv)
5185 return result
5187 def find_common_int_type(self, env, op, operand1, operand2):
5188 # type1 != type2 and at least one of the types is not a C int
5189 type1 = operand1.type
5190 type2 = operand2.type
5191 type1_can_be_int = False
5192 type2_can_be_int = False
5194 if isinstance(operand1, (StringNode, BytesNode)) \
5195 and operand1.can_coerce_to_char_literal():
5196 type1_can_be_int = True
5197 if isinstance(operand2, (StringNode, BytesNode)) \
5198 and operand2.can_coerce_to_char_literal():
5199 type2_can_be_int = True
5201 if type1.is_int:
5202 if type2_can_be_int:
5203 return type1
5204 elif type2.is_int:
5205 if type1_can_be_int:
5206 return type2
5207 elif type1_can_be_int:
5208 if type2_can_be_int:
5209 return PyrexTypes.c_uchar_type
5211 return None
5213 def find_common_type(self, env, op, operand1, common_type=None):
5214 operand2 = self.operand2
5215 type1 = operand1.type
5216 type2 = operand2.type
5218 new_common_type = None
5220 # catch general errors
5221 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5222 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5223 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5224 new_common_type = error_type
5226 # try to use numeric comparisons where possible
5227 elif type1.is_complex or type2.is_complex:
5228 if op not in ('==', '!='):
5229 error(self.pos, "complex types are unordered")
5230 new_common_type = error_type
5231 if type1.is_pyobject:
5232 new_common_type = type1
5233 elif type2.is_pyobject:
5234 new_common_type = type2
5235 else:
5236 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5237 elif type1.is_numeric and type2.is_numeric:
5238 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5239 elif common_type is None or not common_type.is_pyobject:
5240 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5242 if new_common_type is None:
5243 # fall back to generic type compatibility tests
5244 if type1 == type2:
5245 new_common_type = type1
5246 elif type1.is_pyobject or type2.is_pyobject:
5247 if type2.is_numeric or type2.is_string:
5248 if operand2.check_for_coercion_error(type1):
5249 new_common_type = error_type
5250 else:
5251 new_common_type = py_object_type
5252 elif type1.is_numeric or type1.is_string:
5253 if operand1.check_for_coercion_error(type2):
5254 new_common_type = error_type
5255 else:
5256 new_common_type = py_object_type
5257 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
5258 new_common_type = py_object_type
5259 else:
5260 # one Python type and one non-Python type, not assignable
5261 self.invalid_types_error(operand1, op, operand2)
5262 new_common_type = error_type
5263 elif type1.assignable_from(type2):
5264 new_common_type = type1
5265 elif type2.assignable_from(type1):
5266 new_common_type = type2
5267 else:
5268 # C types that we couldn't handle up to here are an error
5269 self.invalid_types_error(operand1, op, operand2)
5270 new_common_type = error_type
5272 # recursively merge types
5273 if common_type is None or new_common_type.is_error:
5274 common_type = new_common_type
5275 else:
5276 # we could do a lot better by splitting the comparison
5277 # into a non-Python part and a Python part, but this is
5278 # safer for now
5279 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5281 if self.cascade:
5282 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5284 return common_type
5286 def invalid_types_error(self, operand1, op, operand2):
5287 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5288 (op, operand1.type, operand2.type))
5290 def is_python_comparison(self):
5291 return (self.has_python_operands()
5292 or (self.cascade and self.cascade.is_python_comparison())
5293 or self.operator in ('in', 'not_in'))
5295 def coerce_operands_to(self, dst_type, env):
5296 operand2 = self.operand2
5297 if operand2.type != dst_type:
5298 self.operand2 = operand2.coerce_to(dst_type, env)
5299 if self.cascade:
5300 self.cascade.coerce_operands_to(dst_type, env)
5302 def is_python_result(self):
5303 return ((self.has_python_operands() and
5304 self.operator not in ('is', 'is_not', 'in', 'not_in'))
5305 or (self.cascade and self.cascade.is_python_result()))
5307 def generate_operation_code(self, code, result_code,
5308 operand1, op , operand2):
5309 if self.type is PyrexTypes.py_object_type:
5310 coerce_result = "__Pyx_PyBool_FromLong"
5311 else:
5312 coerce_result = ""
5313 if 'not' in op:
5314 negation = "!"
5315 else:
5316 negation = ""
5317 if op == 'in' or op == 'not_in':
5318 code.globalstate.use_utility_code(contians_utility_code)
5319 if self.type is PyrexTypes.py_object_type:
5320 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5321 if op == 'not_in':
5322 negation = "__Pyx_NegateNonNeg"
5323 if operand2.type is dict_type:
5324 code.globalstate.use_utility_code(
5325 raise_none_iter_error_utility_code)
5326 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5327 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5328 code.error_goto(self.pos))
5329 code.putln("} else {")
5330 method = "PyDict_Contains"
5331 else:
5332 method = "PySequence_Contains"
5333 if self.type is PyrexTypes.py_object_type:
5334 error_clause = code.error_goto_if_null
5335 got_ref = "__Pyx_XGOTREF(%s); " % result_code
5336 else:
5337 error_clause = code.error_goto_if_neg
5338 got_ref = ""
5339 code.putln(
5340 "%s = %s(%s(%s(%s, %s))); %s%s" % (
5341 result_code,
5342 coerce_result,
5343 negation,
5344 method,
5345 operand2.py_result(),
5346 operand1.py_result(),
5347 got_ref,
5348 error_clause(result_code, self.pos)))
5349 if operand2.type is dict_type:
5350 code.putln("}")
5352 elif (operand1.type.is_pyobject
5353 and op not in ('is', 'is_not')):
5354 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5355 result_code,
5356 operand1.py_result(),
5357 operand2.py_result(),
5358 richcmp_constants[op],
5359 code.error_goto_if_null(result_code, self.pos)))
5360 code.put_gotref(result_code)
5361 elif operand1.type.is_complex:
5362 if op == "!=":
5363 negation = "!"
5364 else:
5365 negation = ""
5366 code.putln("%s = %s(%s%s(%s, %s));" % (
5367 result_code,
5368 coerce_result,
5369 negation,
5370 operand1.type.unary_op('eq'),
5371 operand1.result(),
5372 operand2.result()))
5373 else:
5374 type1 = operand1.type
5375 type2 = operand2.type
5376 if (type1.is_extension_type or type2.is_extension_type) \
5377 and not type1.same_as(type2):
5378 common_type = py_object_type
5379 elif type1.is_numeric:
5380 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5381 else:
5382 common_type = type1
5383 code1 = operand1.result_as(common_type)
5384 code2 = operand2.result_as(common_type)
5385 code.putln("%s = %s(%s %s %s);" % (
5386 result_code,
5387 coerce_result,
5388 code1,
5389 self.c_operator(op),
5390 code2))
5392 def c_operator(self, op):
5393 if op == 'is':
5394 return "=="
5395 elif op == 'is_not':
5396 return "!="
5397 else:
5398 return op
5400 contians_utility_code = UtilityCode(
5401 proto="""
5402 static INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
5403 static INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5404 return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
5405 }
5406 """)
5409 class PrimaryCmpNode(ExprNode, CmpNode):
5410 # Non-cascaded comparison or first comparison of
5411 # a cascaded sequence.
5412 #
5413 # operator string
5414 # operand1 ExprNode
5415 # operand2 ExprNode
5416 # cascade CascadedCmpNode
5418 # We don't use the subexprs mechanism, because
5419 # things here are too complicated for it to handle.
5420 # Instead, we override all the framework methods
5421 # which use it.
5423 child_attrs = ['operand1', 'operand2', 'cascade']
5425 cascade = None
5427 def infer_type(self, env):
5428 # TODO: Actually implement this (after merging with -unstable).
5429 return py_object_type
5431 def type_dependencies(self, env):
5432 return ()
5434 def calculate_constant_result(self):
5435 self.constant_result = self.calculate_cascaded_constant_result(
5436 self.operand1.constant_result)
5438 def compile_time_value(self, denv):
5439 operand1 = self.operand1.compile_time_value(denv)
5440 return self.cascaded_compile_time_value(operand1, denv)
5442 def analyse_types(self, env):
5443 self.operand1.analyse_types(env)
5444 self.operand2.analyse_types(env)
5445 if self.cascade:
5446 self.cascade.analyse_types(env)
5448 if self.operator in ('in', 'not_in'):
5449 common_type = py_object_type
5450 self.is_pycmp = True
5451 else:
5452 common_type = self.find_common_type(env, self.operator, self.operand1)
5453 self.is_pycmp = common_type.is_pyobject
5455 if not common_type.is_error:
5456 if self.operand1.type != common_type:
5457 self.operand1 = self.operand1.coerce_to(common_type, env)
5458 self.coerce_operands_to(common_type, env)
5460 if self.cascade:
5461 self.operand2 = self.operand2.coerce_to_simple(env)
5462 self.cascade.coerce_cascaded_operands_to_temp(env)
5463 if self.is_python_result():
5464 self.type = PyrexTypes.py_object_type
5465 else:
5466 self.type = PyrexTypes.c_bint_type
5467 cdr = self.cascade
5468 while cdr:
5469 cdr.type = self.type
5470 cdr = cdr.cascade
5471 if self.is_pycmp or self.cascade:
5472 self.is_temp = 1
5474 def has_python_operands(self):
5475 return (self.operand1.type.is_pyobject
5476 or self.operand2.type.is_pyobject)
5478 def check_const(self):
5479 if self.cascade:
5480 self.not_const()
5481 return False
5482 else:
5483 return self.operand1.check_const() and self.operand2.check_const()
5485 def calculate_result_code(self):
5486 if self.operand1.type.is_complex:
5487 if self.operator == "!=":
5488 negation = "!"
5489 else:
5490 negation = ""
5491 return "(%s%s(%s, %s))" % (
5492 negation,
5493 self.operand1.type.binary_op('=='),
5494 self.operand1.result(),
5495 self.operand2.result())
5496 else:
5497 return "(%s %s %s)" % (
5498 self.operand1.result(),
5499 self.c_operator(self.operator),
5500 self.operand2.result())
5502 def generate_evaluation_code(self, code):
5503 self.operand1.generate_evaluation_code(code)
5504 self.operand2.generate_evaluation_code(code)
5505 if self.is_temp:
5506 self.allocate_temp_result(code)
5507 self.generate_operation_code(code, self.result(),
5508 self.operand1, self.operator, self.operand2)
5509 if self.cascade:
5510 self.cascade.generate_evaluation_code(code,
5511 self.result(), self.operand2)
5512 self.operand1.generate_disposal_code(code)
5513 self.operand1.free_temps(code)
5514 self.operand2.generate_disposal_code(code)
5515 self.operand2.free_temps(code)
5517 def generate_subexpr_disposal_code(self, code):
5518 # If this is called, it is a non-cascaded cmp,
5519 # so only need to dispose of the two main operands.
5520 self.operand1.generate_disposal_code(code)
5521 self.operand2.generate_disposal_code(code)
5523 def free_subexpr_temps(self, code):
5524 # If this is called, it is a non-cascaded cmp,
5525 # so only need to dispose of the two main operands.
5526 self.operand1.free_temps(code)
5527 self.operand2.free_temps(code)
5529 def annotate(self, code):
5530 self.operand1.annotate(code)
5531 self.operand2.annotate(code)
5532 if self.cascade:
5533 self.cascade.annotate(code)
5536 class CascadedCmpNode(Node, CmpNode):
5537 # A CascadedCmpNode is not a complete expression node. It
5538 # hangs off the side of another comparison node, shares
5539 # its left operand with that node, and shares its result
5540 # with the PrimaryCmpNode at the head of the chain.
5541 #
5542 # operator string
5543 # operand2 ExprNode
5544 # cascade CascadedCmpNode
5546 child_attrs = ['operand2', 'cascade']
5548 cascade = None
5549 constant_result = constant_value_not_set # FIXME: where to calculate this?
5551 def infer_type(self, env):
5552 # TODO: Actually implement this (after merging with -unstable).
5553 return py_object_type
5555 def type_dependencies(self, env):
5556 return ()
5558 def analyse_types(self, env):
5559 self.operand2.analyse_types(env)
5560 if self.cascade:
5561 self.cascade.analyse_types(env)
5563 def has_python_operands(self):
5564 return self.operand2.type.is_pyobject
5566 def coerce_operands_to_pyobjects(self, env):
5567 self.operand2 = self.operand2.coerce_to_pyobject(env)
5568 if self.cascade:
5569 self.cascade.coerce_operands_to_pyobjects(env)
5571 def coerce_cascaded_operands_to_temp(self, env):
5572 if self.cascade:
5573 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5574 self.operand2 = self.operand2.coerce_to_simple(env)
5575 self.cascade.coerce_cascaded_operands_to_temp(env)
5577 def generate_evaluation_code(self, code, result, operand1):
5578 if self.type.is_pyobject:
5579 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5580 code.put_decref(result, self.type)
5581 else:
5582 code.putln("if (%s) {" % result)
5583 self.operand2.generate_evaluation_code(code)
5584 self.generate_operation_code(code, result,
5585 operand1, self.operator, self.operand2)
5586 if self.cascade:
5587 self.cascade.generate_evaluation_code(
5588 code, result, self.operand2)
5589 # Cascaded cmp result is always temp
5590 self.operand2.generate_disposal_code(code)
5591 self.operand2.free_temps(code)
5592 code.putln("}")
5594 def annotate(self, code):
5595 self.operand2.annotate(code)
5596 if self.cascade:
5597 self.cascade.annotate(code)
5600 binop_node_classes = {
5601 "or": BoolBinopNode,
5602 "and": BoolBinopNode,
5603 "|": IntBinopNode,
5604 "^": IntBinopNode,
5605 "&": IntBinopNode,
5606 "<<": IntBinopNode,
5607 ">>": IntBinopNode,
5608 "+": AddNode,
5609 "-": SubNode,
5610 "*": MulNode,
5611 "/": DivNode,
5612 "//": DivNode,
5613 "%": ModNode,
5614 "**": PowNode
5615 }
5617 def binop_node(pos, operator, operand1, operand2):
5618 # Construct binop node of appropriate class for
5619 # given operator.
5620 return binop_node_classes[operator](pos,
5621 operator = operator,
5622 operand1 = operand1,
5623 operand2 = operand2)
5625 #-------------------------------------------------------------------
5626 #
5627 # Coercion nodes
5628 #
5629 # Coercion nodes are special in that they are created during
5630 # the analyse_types phase of parse tree processing.
5631 # Their __init__ methods consequently incorporate some aspects
5632 # of that phase.
5633 #
5634 #-------------------------------------------------------------------
5636 class CoercionNode(ExprNode):
5637 # Abstract base class for coercion nodes.
5638 #
5639 # arg ExprNode node being coerced
5641 subexprs = ['arg']
5642 constant_result = not_a_constant
5644 def __init__(self, arg):
5645 self.pos = arg.pos
5646 self.arg = arg
5647 if debug_coercion:
5648 print("%s Coercing %s" % (self, self.arg))
5650 def calculate_constant_result(self):
5651 # constant folding can break type coercion, so this is disabled
5652 pass
5654 def annotate(self, code):
5655 self.arg.annotate(code)
5656 if self.arg.type != self.type:
5657 file, line, col = self.pos
5658 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5661 class CastNode(CoercionNode):
5662 # Wrap a node in a C type cast.
5664 def __init__(self, arg, new_type):
5665 CoercionNode.__init__(self, arg)
5666 self.type = new_type
5668 def calculate_result_code(self):
5669 return self.arg.result_as(self.type)
5671 def generate_result_code(self, code):
5672 self.arg.generate_result_code(code)
5675 class PyTypeTestNode(CoercionNode):
5676 # This node is used to check that a generic Python
5677 # object is an instance of a particular extension type.
5678 # This node borrows the result of its argument node.
5680 def __init__(self, arg, dst_type, env, notnone=False):
5681 # The arg is know to be a Python object, and
5682 # the dst_type is known to be an extension type.
5683 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5684 CoercionNode.__init__(self, arg)
5685 self.type = dst_type
5686 self.result_ctype = arg.ctype()
5687 self.notnone = notnone
5689 nogil_check = Node.gil_error
5690 gil_message = "Python type test"
5692 def analyse_types(self, env):
5693 pass
5695 def result_in_temp(self):
5696 return self.arg.result_in_temp()
5698 def is_ephemeral(self):
5699 return self.arg.is_ephemeral()
5701 def calculate_constant_result(self):
5702 # FIXME
5703 pass
5705 def calculate_result_code(self):
5706 return self.arg.result()
5708 def generate_result_code(self, code):
5709 if self.type.typeobj_is_available():
5710 if not self.type.is_builtin_type:
5711 code.globalstate.use_utility_code(type_test_utility_code)
5712 code.putln(
5713 "if (!(%s)) %s" % (
5714 self.type.type_test_code(self.arg.py_result(), self.notnone),
5715 code.error_goto(self.pos)))
5716 else:
5717 error(self.pos, "Cannot test type of extern C class "
5718 "without type object name specification")
5720 def generate_post_assignment_code(self, code):
5721 self.arg.generate_post_assignment_code(code)
5723 def free_temps(self, code):
5724 self.arg.free_temps(code)
5727 class NoneCheckNode(CoercionNode):
5728 # This node is used to check that a Python object is not None and
5729 # raises an appropriate exception (as specified by the creating
5730 # transform).
5732 def __init__(self, arg, exception_type_cname, exception_message):
5733 CoercionNode.__init__(self, arg)
5734 self.type = arg.type
5735 self.result_ctype = arg.ctype()
5736 self.exception_type_cname = exception_type_cname
5737 self.exception_message = exception_message
5739 def analyse_types(self, env):
5740 pass
5742 def result_in_temp(self):
5743 return self.arg.result_in_temp()
5745 def calculate_result_code(self):
5746 return self.arg.result()
5748 def generate_result_code(self, code):
5749 code.putln(
5750 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5751 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5752 self.exception_type_cname,
5753 StringEncoding.escape_byte_string(
5754 self.exception_message.encode('UTF-8')),
5755 code.error_goto(self.pos)))
5756 code.putln("}")
5758 def generate_post_assignment_code(self, code):
5759 self.arg.generate_post_assignment_code(code)
5761 def free_temps(self, code):
5762 self.arg.free_temps(code)
5765 class CoerceToPyTypeNode(CoercionNode):
5766 # This node is used to convert a C data type
5767 # to a Python object.
5769 type = py_object_type
5770 is_temp = 1
5772 def __init__(self, arg, env, type=py_object_type):
5773 CoercionNode.__init__(self, arg)
5774 if not arg.type.create_to_py_utility_code(env):
5775 error(arg.pos,
5776 "Cannot convert '%s' to Python object" % arg.type)
5777 if type is not py_object_type:
5778 self.type = py_object_type
5779 elif arg.type.is_string:
5780 self.type = Builtin.bytes_type
5782 gil_message = "Converting to Python object"
5784 def coerce_to_boolean(self, env):
5785 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5787 def coerce_to_integer(self, env):
5788 # If not already some C integer type, coerce to longint.
5789 if self.arg.type.is_int:
5790 return self.arg
5791 else:
5792 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5794 def analyse_types(self, env):
5795 # The arg is always already analysed
5796 pass
5798 def generate_result_code(self, code):
5799 function = self.arg.type.to_py_function
5800 code.putln('%s = %s(%s); %s' % (
5801 self.result(),
5802 function,
5803 self.arg.result(),
5804 code.error_goto_if_null(self.result(), self.pos)))
5805 code.put_gotref(self.py_result())
5808 class CoerceFromPyTypeNode(CoercionNode):
5809 # This node is used to convert a Python object
5810 # to a C data type.
5812 def __init__(self, result_type, arg, env):
5813 CoercionNode.__init__(self, arg)
5814 self.type = result_type
5815 self.is_temp = 1
5816 if not result_type.create_from_py_utility_code(env):
5817 error(arg.pos,
5818 "Cannot convert Python object to '%s'" % result_type)
5819 if self.type.is_string and self.arg.is_ephemeral():
5820 error(arg.pos,
5821 "Obtaining char * from temporary Python value")
5823 def analyse_types(self, env):
5824 # The arg is always already analysed
5825 pass
5827 def generate_result_code(self, code):
5828 function = self.type.from_py_function
5829 operand = self.arg.py_result()
5830 rhs = "%s(%s)" % (function, operand)
5831 if self.type.is_enum:
5832 rhs = typecast(self.type, c_long_type, rhs)
5833 code.putln('%s = %s; %s' % (
5834 self.result(),
5835 rhs,
5836 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5837 if self.type.is_pyobject:
5838 code.put_gotref(self.py_result())
5841 class CoerceToBooleanNode(CoercionNode):
5842 # This node is used when a result needs to be used
5843 # in a boolean context.
5845 type = PyrexTypes.c_bint_type
5847 def __init__(self, arg, env):
5848 CoercionNode.__init__(self, arg)
5849 if arg.type.is_pyobject:
5850 self.is_temp = 1
5852 def nogil_check(self, env):
5853 if self.arg.type.is_pyobject:
5854 self.gil_error()
5856 gil_message = "Truth-testing Python object"
5858 def check_const(self):
5859 if self.is_temp:
5860 self.not_const()
5861 return False
5862 return self.arg.check_const()
5864 def calculate_result_code(self):
5865 return "(%s != 0)" % self.arg.result()
5867 def generate_result_code(self, code):
5868 if self.arg.type.is_pyobject:
5869 code.putln(
5870 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5871 self.result(),
5872 self.arg.py_result(),
5873 code.error_goto_if_neg(self.result(), self.pos)))
5875 class CoerceToComplexNode(CoercionNode):
5877 def __init__(self, arg, dst_type, env):
5878 if arg.type.is_complex:
5879 arg = arg.coerce_to_simple(env)
5880 self.type = dst_type
5881 CoercionNode.__init__(self, arg)
5882 dst_type.create_declaration_utility_code(env)
5884 def calculate_result_code(self):
5885 if self.arg.type.is_complex:
5886 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
5887 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
5888 else:
5889 real_part = self.arg.result()
5890 imag_part = "0"
5891 return "%s(%s, %s)" % (
5892 self.type.from_parts,
5893 real_part,
5894 imag_part)
5896 def generate_result_code(self, code):
5897 pass
5899 class CoerceToTempNode(CoercionNode):
5900 # This node is used to force the result of another node
5901 # to be stored in a temporary. It is only used if the
5902 # argument node's result is not already in a temporary.
5904 def __init__(self, arg, env):
5905 CoercionNode.__init__(self, arg)
5906 self.type = self.arg.type
5907 self.is_temp = 1
5908 if self.type.is_pyobject:
5909 self.result_ctype = py_object_type
5911 gil_message = "Creating temporary Python reference"
5913 def analyse_types(self, env):
5914 # The arg is always already analysed
5915 pass
5917 def coerce_to_boolean(self, env):
5918 self.arg = self.arg.coerce_to_boolean(env)
5919 self.type = self.arg.type
5920 self.result_ctype = self.type
5921 return self
5923 def generate_result_code(self, code):
5924 #self.arg.generate_evaluation_code(code) # Already done
5925 # by generic generate_subexpr_evaluation_code!
5926 code.putln("%s = %s;" % (
5927 self.result(), self.arg.result_as(self.ctype())))
5928 if self.type.is_pyobject and self.use_managed_ref:
5929 code.put_incref(self.result(), self.ctype())
5932 class CloneNode(CoercionNode):
5933 # This node is employed when the result of another node needs
5934 # to be used multiple times. The argument node's result must
5935 # be in a temporary. This node "borrows" the result from the
5936 # argument node, and does not generate any evaluation or
5937 # disposal code for it. The original owner of the argument
5938 # node is responsible for doing those things.
5940 subexprs = [] # Arg is not considered a subexpr
5941 nogil_check = None
5943 def __init__(self, arg):
5944 CoercionNode.__init__(self, arg)
5945 if hasattr(arg, 'type'):
5946 self.type = arg.type
5947 self.result_ctype = arg.result_ctype
5948 if hasattr(arg, 'entry'):
5949 self.entry = arg.entry
5951 def result(self):
5952 return self.arg.result()
5954 def type_dependencies(self, env):
5955 return self.arg.type_dependencies(env)
5957 def infer_type(self, env):
5958 return self.arg.infer_type(env)
5960 def analyse_types(self, env):
5961 self.type = self.arg.type
5962 self.result_ctype = self.arg.result_ctype
5963 self.is_temp = 1
5964 if hasattr(self.arg, 'entry'):
5965 self.entry = self.arg.entry
5967 def generate_evaluation_code(self, code):
5968 pass
5970 def generate_result_code(self, code):
5971 pass
5973 def generate_disposal_code(self, code):
5974 pass
5976 def free_temps(self, code):
5977 pass
5980 class ModuleRefNode(ExprNode):
5981 # Simple returns the module object
5983 type = py_object_type
5984 is_temp = False
5985 subexprs = []
5987 def analyse_types(self, env):
5988 pass
5990 def calculate_result_code(self):
5991 return Naming.module_cname
5993 def generate_result_code(self, code):
5994 pass
5996 class DocstringRefNode(ExprNode):
5997 # Extracts the docstring of the body element
5999 subexprs = ['body']
6000 type = py_object_type
6001 is_temp = True
6003 def __init__(self, pos, body):
6004 ExprNode.__init__(self, pos)
6005 assert body.type.is_pyobject
6006 self.body = body
6008 def analyse_types(self, env):
6009 pass
6011 def generate_result_code(self, code):
6012 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
6013 (self.result(), self.body.result()))
6014 code.put_gotref(self.result())
6018 #------------------------------------------------------------------------------------
6019 #
6020 # Runtime support code
6021 #
6022 #------------------------------------------------------------------------------------
6024 get_name_interned_utility_code = UtilityCode(
6025 proto = """
6026 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
6027 """,
6028 impl = """
6029 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
6030 PyObject *result;
6031 result = PyObject_GetAttr(dict, name);
6032 if (!result)
6033 PyErr_SetObject(PyExc_NameError, name);
6034 return result;
6035 }
6036 """)
6038 #------------------------------------------------------------------------------------
6040 import_utility_code = UtilityCode(
6041 proto = """
6042 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
6043 """,
6044 impl = """
6045 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
6046 PyObject *__import__ = 0;
6047 PyObject *empty_list = 0;
6048 PyObject *module = 0;
6049 PyObject *global_dict = 0;
6050 PyObject *empty_dict = 0;
6051 PyObject *list;
6052 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
6053 if (!__import__)
6054 goto bad;
6055 if (from_list)
6056 list = from_list;
6057 else {
6058 empty_list = PyList_New(0);
6059 if (!empty_list)
6060 goto bad;
6061 list = empty_list;
6062 }
6063 global_dict = PyModule_GetDict(%(GLOBALS)s);
6064 if (!global_dict)
6065 goto bad;
6066 empty_dict = PyDict_New();
6067 if (!empty_dict)
6068 goto bad;
6069 module = PyObject_CallFunctionObjArgs(__import__,
6070 name, global_dict, empty_dict, list, NULL);
6071 bad:
6072 Py_XDECREF(empty_list);
6073 Py_XDECREF(__import__);
6074 Py_XDECREF(empty_dict);
6075 return module;
6076 }
6077 """ % {
6078 "BUILTINS": Naming.builtins_cname,
6079 "GLOBALS": Naming.module_cname,
6080 })
6082 #------------------------------------------------------------------------------------
6084 get_exception_utility_code = UtilityCode(
6085 proto = """
6086 static PyObject *__Pyx_GetExcValue(void); /*proto*/
6087 """,
6088 impl = """
6089 static PyObject *__Pyx_GetExcValue(void) {
6090 PyObject *type = 0, *value = 0, *tb = 0;
6091 PyObject *tmp_type, *tmp_value, *tmp_tb;
6092 PyObject *result = 0;
6093 PyThreadState *tstate = PyThreadState_Get();
6094 PyErr_Fetch(&type, &value, &tb);
6095 PyErr_NormalizeException(&type, &value, &tb);
6096 if (PyErr_Occurred())
6097 goto bad;
6098 if (!value) {
6099 value = Py_None;
6100 Py_INCREF(value);
6101 }
6102 tmp_type = tstate->exc_type;
6103 tmp_value = tstate->exc_value;
6104 tmp_tb = tstate->exc_traceback;
6105 tstate->exc_type = type;
6106 tstate->exc_value = value;
6107 tstate->exc_traceback = tb;
6108 /* Make sure tstate is in a consistent state when we XDECREF
6109 these objects (XDECREF may run arbitrary code). */
6110 Py_XDECREF(tmp_type);
6111 Py_XDECREF(tmp_value);
6112 Py_XDECREF(tmp_tb);
6113 result = value;
6114 Py_XINCREF(result);
6115 type = 0;
6116 value = 0;
6117 tb = 0;
6118 bad:
6119 Py_XDECREF(type);
6120 Py_XDECREF(value);
6121 Py_XDECREF(tb);
6122 return result;
6123 }
6124 """)
6126 #------------------------------------------------------------------------------------
6128 type_test_utility_code = UtilityCode(
6129 proto = """
6130 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6131 """,
6132 impl = """
6133 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6134 if (unlikely(!type)) {
6135 PyErr_Format(PyExc_SystemError, "Missing type object");
6136 return 0;
6137 }
6138 if (likely(PyObject_TypeCheck(obj, type)))
6139 return 1;
6140 PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
6141 Py_TYPE(obj)->tp_name, type->tp_name);
6142 return 0;
6143 }
6144 """)
6146 #------------------------------------------------------------------------------------
6148 create_class_utility_code = UtilityCode(
6149 proto = """
6150 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6151 """,
6152 impl = """
6153 static PyObject *__Pyx_CreateClass(
6154 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6155 {
6156 PyObject *py_modname;
6157 PyObject *result = 0;
6159 #if PY_MAJOR_VERSION < 3
6160 py_modname = PyString_FromString(modname);
6161 #else
6162 py_modname = PyUnicode_FromString(modname);
6163 #endif
6164 if (!py_modname)
6165 goto bad;
6166 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6167 goto bad;
6168 #if PY_MAJOR_VERSION < 3
6169 result = PyClass_New(bases, dict, name);
6170 #else
6171 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6172 #endif
6173 bad:
6174 Py_XDECREF(py_modname);
6175 return result;
6176 }
6177 """)
6179 #------------------------------------------------------------------------------------
6181 cpp_exception_utility_code = UtilityCode(
6182 proto = """
6183 #ifndef __Pyx_CppExn2PyErr
6184 static void __Pyx_CppExn2PyErr() {
6185 try {
6186 if (PyErr_Occurred())
6187 ; // let the latest Python exn pass through and ignore the current one
6188 else
6189 throw;
6190 } catch (const std::out_of_range& exn) {
6191 // catch out_of_range explicitly so the proper Python exn may be raised
6192 PyErr_SetString(PyExc_IndexError, exn.what());
6193 } catch (const std::exception& exn) {
6194 PyErr_SetString(PyExc_RuntimeError, exn.what());
6195 }
6196 catch (...)
6197 {
6198 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6199 }
6200 }
6201 #endif
6202 """,
6203 impl = ""
6204 )
6206 #------------------------------------------------------------------------------------
6208 # If the is_unsigned flag is set, we need to do some extra work to make
6209 # sure the index doesn't become negative.
6211 getitem_int_utility_code = UtilityCode(
6212 proto = """
6214 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6215 PyObject *r;
6216 if (!j) return NULL;
6217 r = PyObject_GetItem(o, j);
6218 Py_DECREF(j);
6219 return r;
6220 }
6222 """ + ''.join([
6223 """
6224 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6225 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6226 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6228 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6229 if (likely(o != Py_None)) {
6230 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6231 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6232 Py_INCREF(r);
6233 return r;
6234 }
6235 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6236 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6237 Py_INCREF(r);
6238 return r;
6239 }
6240 }
6241 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6242 }
6243 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6244 ]) + """
6246 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6247 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6248 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6250 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6251 PyObject *r;
6252 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6253 r = PyList_GET_ITEM(o, i);
6254 Py_INCREF(r);
6255 }
6256 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6257 r = PyTuple_GET_ITEM(o, i);
6258 Py_INCREF(r);
6259 }
6260 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6261 r = PySequence_GetItem(o, i);
6262 }
6263 else {
6264 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6265 }
6266 return r;
6267 }
6268 """,
6269 impl = """
6270 """)
6274 #------------------------------------------------------------------------------------
6276 setitem_int_utility_code = UtilityCode(
6277 proto = """
6278 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6279 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6280 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6282 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6283 int r;
6284 if (!j) return -1;
6285 r = PyObject_SetItem(o, j, v);
6286 Py_DECREF(j);
6287 return r;
6288 }
6290 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6291 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6292 Py_INCREF(v);
6293 Py_DECREF(PyList_GET_ITEM(o, i));
6294 PyList_SET_ITEM(o, i, v);
6295 return 1;
6296 }
6297 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6298 return PySequence_SetItem(o, i, v);
6299 else {
6300 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6301 return __Pyx_SetItemInt_Generic(o, j, v);
6302 }
6303 }
6304 """,
6305 impl = """
6306 """)
6308 #------------------------------------------------------------------------------------
6310 delitem_int_utility_code = UtilityCode(
6311 proto = """
6312 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6313 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6314 __Pyx_DelItem_Generic(o, to_py_func(i)))
6316 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6317 int r;
6318 if (!j) return -1;
6319 r = PyObject_DelItem(o, j);
6320 Py_DECREF(j);
6321 return r;
6322 }
6324 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6325 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6326 return PySequence_DelItem(o, i);
6327 else {
6328 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6329 return __Pyx_DelItem_Generic(o, j);
6330 }
6331 }
6332 """,
6333 impl = """
6334 """)
6336 #------------------------------------------------------------------------------------
6338 raise_noneattr_error_utility_code = UtilityCode(
6339 proto = """
6340 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6341 """,
6342 impl = '''
6343 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6344 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6345 }
6346 ''')
6348 raise_noneindex_error_utility_code = UtilityCode(
6349 proto = """
6350 static INLINE void __Pyx_RaiseNoneIndexingError(void);
6351 """,
6352 impl = '''
6353 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
6354 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6355 }
6356 ''')
6358 raise_none_iter_error_utility_code = UtilityCode(
6359 proto = """
6360 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
6361 """,
6362 impl = '''
6363 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6364 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6365 }
6366 ''')
6368 raise_too_many_values_to_unpack = UtilityCode(
6369 proto = """
6370 static INLINE void __Pyx_RaiseTooManyValuesError(void);
6371 """,
6372 impl = '''
6373 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
6374 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6375 }
6376 ''')
6378 raise_need_more_values_to_unpack = UtilityCode(
6379 proto = """
6380 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6381 """,
6382 impl = '''
6383 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6384 PyErr_Format(PyExc_ValueError,
6385 #if PY_VERSION_HEX < 0x02050000
6386 "need more than %d value%s to unpack", (int)index,
6387 #else
6388 "need more than %zd value%s to unpack", index,
6389 #endif
6390 (index == 1) ? "" : "s");
6391 }
6392 ''')
6394 #------------------------------------------------------------------------------------
6396 tuple_unpacking_error_code = UtilityCode(
6397 proto = """
6398 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6399 """,
6400 impl = """
6401 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6402 if (t == Py_None) {
6403 __Pyx_RaiseNoneNotIterableError();
6404 } else if (PyTuple_GET_SIZE(t) < index) {
6405 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6406 } else {
6407 __Pyx_RaiseTooManyValuesError();
6408 }
6409 }
6410 """,
6411 requires = [raise_none_iter_error_utility_code,
6412 raise_need_more_values_to_unpack,
6413 raise_too_many_values_to_unpack]
6414 )
6416 unpacking_utility_code = UtilityCode(
6417 proto = """
6418 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6419 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6420 """,
6421 impl = """
6422 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6423 PyObject *item;
6424 if (!(item = PyIter_Next(iter))) {
6425 if (!PyErr_Occurred()) {
6426 __Pyx_RaiseNeedMoreValuesError(index);
6427 }
6428 }
6429 return item;
6430 }
6432 static int __Pyx_EndUnpack(PyObject *iter) {
6433 PyObject *item;
6434 if ((item = PyIter_Next(iter))) {
6435 Py_DECREF(item);
6436 __Pyx_RaiseTooManyValuesError();
6437 return -1;
6438 }
6439 else if (!PyErr_Occurred())
6440 return 0;
6441 else
6442 return -1;
6443 }
6444 """,
6445 requires = [raise_need_more_values_to_unpack,
6446 raise_too_many_values_to_unpack]
6447 )
6450 #------------------------------------------------------------------------------------
6452 int_pow_utility_code = UtilityCode(
6453 proto="""
6454 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6455 """,
6456 impl="""
6457 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6458 %(type)s t = b;
6459 switch (e) {
6460 case 3:
6461 t *= b;
6462 case 2:
6463 t *= b;
6464 case 1:
6465 return t;
6466 case 0:
6467 return 1;
6468 }
6469 if (unlikely(e<0)) return 0;
6470 t = 1;
6471 while (likely(e)) {
6472 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6473 b *= b;
6474 e >>= 1;
6475 }
6476 return t;
6477 }
6478 """)
6480 # ------------------------------ Division ------------------------------------
6482 div_int_utility_code = UtilityCode(
6483 proto="""
6484 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6485 """,
6486 impl="""
6487 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6488 %(type)s q = a / b;
6489 %(type)s r = a - q*b;
6490 q -= ((r != 0) & ((r ^ b) < 0));
6491 return q;
6492 }
6493 """)
6495 mod_int_utility_code = UtilityCode(
6496 proto="""
6497 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6498 """,
6499 impl="""
6500 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6501 %(type)s r = a %% b;
6502 r += ((r != 0) & ((r ^ b) < 0)) * b;
6503 return r;
6504 }
6505 """)
6507 mod_float_utility_code = UtilityCode(
6508 proto="""
6509 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6510 """,
6511 impl="""
6512 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6513 %(type)s r = fmod%(math_h_modifier)s(a, b);
6514 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6515 return r;
6516 }
6517 """)
6519 cdivision_warning_utility_code = UtilityCode(
6520 proto="""
6521 static int __Pyx_cdivision_warning(void); /* proto */
6522 """,
6523 impl="""
6524 static int __Pyx_cdivision_warning(void) {
6525 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6526 "division with oppositely signed operands, C and Python semantics differ",
6527 %(FILENAME)s,
6528 %(LINENO)s,
6529 __Pyx_MODULE_NAME,
6530 NULL);
6531 }
6532 """ % {
6533 'FILENAME': Naming.filename_cname,
6534 'LINENO': Naming.lineno_cname,
6535 })
6537 # from intobject.c
6538 division_overflow_test_code = UtilityCode(
6539 proto="""
6540 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6541 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6542 """)
