Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 2953:4b2e6c18fe38
enable for-in iteration also for C arrays of known size
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Thu Feb 11 20:42:35 2010 +0100 (2 years ago) |
| parents | b6f2a92470ab |
| children | 3eaf609fe667 |
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())
1044 class NewExprNode(AtomicExprNode):
1046 # C++ new statement
1047 #
1048 # cppclass string c++ class to create
1049 # template_parameters None or [ExprNode] temlate parameters, if any
1051 def infer_type(self, env):
1052 entry = env.lookup(self.cppclass)
1053 if entry is None or not entry.is_cpp_class:
1054 error(self.pos, "new operator can only be applied to a C++ class")
1055 return
1056 self.cpp_check(env)
1057 if self.template_parameters is not None:
1058 template_types = [v.analyse_as_type(env) for v in self.template_parameters]
1059 type = entry.type.specialize_here(self.pos, template_types)
1060 else:
1061 type = entry.type
1062 constructor = type.scope.lookup(u'<init>')
1063 if constructor is None:
1064 return_type = PyrexTypes.CFuncType(type, [])
1065 return_type = PyrexTypes.CPtrType(return_type)
1066 type.scope.declare_cfunction(u'<init>', return_type, self.pos)
1067 constructor = type.scope.lookup(u'<init>')
1068 self.class_type = type
1069 self.entry = constructor
1070 self.type = constructor.type
1071 return self.type
1073 def analyse_types(self, env):
1074 self.infer_type(env)
1076 def generate_result_code(self, code):
1077 pass
1079 def calculate_result_code(self):
1080 return "new " + self.class_type.declaration_code("")
1083 class NameNode(AtomicExprNode):
1084 # Reference to a local or global variable name.
1085 #
1086 # name string Python name of the variable
1087 # entry Entry Symbol table entry
1088 # type_entry Entry For extension type names, the original type entry
1090 is_name = True
1091 is_cython_module = False
1092 cython_attribute = None
1093 lhs_of_first_assignment = False
1094 is_used_as_rvalue = 0
1095 entry = None
1096 type_entry = None
1098 def create_analysed_rvalue(pos, env, entry):
1099 node = NameNode(pos)
1100 node.analyse_types(env, entry=entry)
1101 return node
1103 def as_cython_attribute(self):
1104 return self.cython_attribute
1106 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1108 def type_dependencies(self, env):
1109 if self.entry is None:
1110 self.entry = env.lookup(self.name)
1111 if self.entry is not None and self.entry.type.is_unspecified:
1112 return (self.entry,)
1113 else:
1114 return ()
1116 def infer_type(self, env):
1117 if self.entry is None:
1118 self.entry = env.lookup(self.name)
1119 if self.entry is None:
1120 return py_object_type
1121 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1122 self.name == self.entry.type.name:
1123 # Unfortunately the type attribute of type objects
1124 # is used for the pointer to the type they represent.
1125 return type_type
1126 else:
1127 return self.entry.type
1129 def compile_time_value(self, denv):
1130 try:
1131 return denv.lookup(self.name)
1132 except KeyError:
1133 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1135 def get_constant_c_result_code(self):
1136 if not self.entry or self.entry.type.is_pyobject:
1137 return None
1138 return self.entry.cname
1140 def coerce_to(self, dst_type, env):
1141 # If coercing to a generic pyobject and this is a builtin
1142 # C function with a Python equivalent, manufacture a NameNode
1143 # referring to the Python builtin.
1144 #print "NameNode.coerce_to:", self.name, dst_type ###
1145 if dst_type is py_object_type:
1146 entry = self.entry
1147 if entry and entry.is_cfunction:
1148 var_entry = entry.as_variable
1149 if var_entry:
1150 if var_entry.is_builtin and Options.cache_builtins:
1151 var_entry = env.declare_builtin(var_entry.name, self.pos)
1152 node = NameNode(self.pos, name = self.name)
1153 node.entry = var_entry
1154 node.analyse_rvalue_entry(env)
1155 return node
1156 return super(NameNode, self).coerce_to(dst_type, env)
1158 def analyse_as_module(self, env):
1159 # Try to interpret this as a reference to a cimported module.
1160 # Returns the module scope, or None.
1161 entry = self.entry
1162 if not entry:
1163 entry = env.lookup(self.name)
1164 if entry and entry.as_module:
1165 return entry.as_module
1166 return None
1168 def analyse_as_type(self, env):
1169 if self.cython_attribute:
1170 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1171 else:
1172 type = PyrexTypes.parse_basic_type(self.name)
1173 if type:
1174 return type
1175 entry = self.entry
1176 if not entry:
1177 entry = env.lookup(self.name)
1178 if entry and entry.is_type:
1179 return entry.type
1180 else:
1181 return None
1183 def analyse_as_extension_type(self, env):
1184 # Try to interpret this as a reference to an extension type.
1185 # Returns the extension type, or None.
1186 entry = self.entry
1187 if not entry:
1188 entry = env.lookup(self.name)
1189 if entry and entry.is_type and entry.type.is_extension_type:
1190 return entry.type
1191 else:
1192 return None
1194 def analyse_target_declaration(self, env):
1195 if not self.entry:
1196 self.entry = env.lookup_here(self.name)
1197 if not self.entry:
1198 if env.directives['warn.undeclared']:
1199 warning(self.pos, "implicit declaration of '%s'" % self.name, 1)
1200 if env.directives['infer_types'] != False:
1201 type = unspecified_type
1202 else:
1203 type = py_object_type
1204 self.entry = env.declare_var(self.name, type, self.pos)
1205 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1206 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1207 if self.entry.is_declared_generic:
1208 self.result_ctype = py_object_type
1210 def analyse_types(self, env):
1211 if self.entry is None:
1212 self.entry = env.lookup(self.name)
1213 if not self.entry:
1214 self.entry = env.declare_builtin(self.name, self.pos)
1215 if not self.entry:
1216 self.type = PyrexTypes.error_type
1217 return
1218 entry = self.entry
1219 if entry:
1220 entry.used = 1
1221 if entry.type.is_buffer:
1222 import Buffer
1223 Buffer.used_buffer_aux_vars(entry)
1224 if entry.utility_code:
1225 env.use_utility_code(entry.utility_code)
1226 self.analyse_rvalue_entry(env)
1228 def analyse_target_types(self, env):
1229 self.analyse_entry(env)
1230 if not self.is_lvalue():
1231 error(self.pos, "Assignment to non-lvalue '%s'"
1232 % self.name)
1233 self.type = PyrexTypes.error_type
1234 self.entry.used = 1
1235 if self.entry.type.is_buffer:
1236 import Buffer
1237 Buffer.used_buffer_aux_vars(self.entry)
1239 def analyse_rvalue_entry(self, env):
1240 #print "NameNode.analyse_rvalue_entry:", self.name ###
1241 #print "Entry:", self.entry.__dict__ ###
1242 self.analyse_entry(env)
1243 entry = self.entry
1244 if entry.is_declared_generic:
1245 self.result_ctype = py_object_type
1246 if entry.is_pyglobal or entry.is_builtin:
1247 if Options.cache_builtins and entry.is_builtin:
1248 self.is_temp = 0
1249 else:
1250 self.is_temp = 1
1251 env.use_utility_code(get_name_interned_utility_code)
1252 self.is_used_as_rvalue = 1
1254 def nogil_check(self, env):
1255 if self.is_used_as_rvalue:
1256 entry = self.entry
1257 if entry.is_builtin:
1258 # if not Options.cache_builtins: # cached builtins are ok
1259 self.gil_error()
1260 elif entry.is_pyglobal:
1261 self.gil_error()
1263 gil_message = "Accessing Python global or builtin"
1265 def analyse_entry(self, env):
1266 #print "NameNode.analyse_entry:", self.name ###
1267 self.check_identifier_kind()
1268 entry = self.entry
1269 type = entry.type
1270 self.type = type
1272 def check_identifier_kind(self):
1273 # Check that this is an appropriate kind of name for use in an
1274 # expression. Also finds the variable entry associated with
1275 # an extension type.
1276 entry = self.entry
1277 if entry.is_type and entry.type.is_extension_type:
1278 self.type_entry = entry
1279 if not (entry.is_const or entry.is_variable
1280 or entry.is_builtin or entry.is_cfunction
1281 or entry.is_cpp_class):
1282 if self.entry.as_variable:
1283 self.entry = self.entry.as_variable
1284 else:
1285 error(self.pos,
1286 "'%s' is not a constant, variable or function identifier" % self.name)
1288 def is_simple(self):
1289 # If it's not a C variable, it'll be in a temp.
1290 return 1
1292 def calculate_target_results(self, env):
1293 pass
1295 def check_const(self):
1296 entry = self.entry
1297 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1298 self.not_const()
1299 return False
1300 return True
1302 def check_const_addr(self):
1303 entry = self.entry
1304 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1305 self.addr_not_const()
1306 return False
1307 return True
1309 def is_lvalue(self):
1310 return self.entry.is_variable and \
1311 not self.entry.type.is_array and \
1312 not self.entry.is_readonly
1314 def is_ephemeral(self):
1315 # Name nodes are never ephemeral, even if the
1316 # result is in a temporary.
1317 return 0
1319 def calculate_result_code(self):
1320 entry = self.entry
1321 if not entry:
1322 return "<error>" # There was an error earlier
1323 return entry.cname
1325 def generate_result_code(self, code):
1326 assert hasattr(self, 'entry')
1327 entry = self.entry
1328 if entry is None:
1329 return # There was an error earlier
1330 if entry.is_builtin and Options.cache_builtins:
1331 return # Lookup already cached
1332 elif entry.is_pyglobal or entry.is_builtin:
1333 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1334 interned_cname = code.intern_identifier(self.entry.name)
1335 if entry.is_builtin:
1336 namespace = Naming.builtins_cname
1337 else: # entry.is_pyglobal
1338 namespace = entry.scope.namespace_cname
1339 code.globalstate.use_utility_code(get_name_interned_utility_code)
1340 code.putln(
1341 '%s = __Pyx_GetName(%s, %s); %s' % (
1342 self.result(),
1343 namespace,
1344 interned_cname,
1345 code.error_goto_if_null(self.result(), self.pos)))
1346 code.put_gotref(self.py_result())
1348 elif entry.is_local and False:
1349 # control flow not good enough yet
1350 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1351 if assigned is False:
1352 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1353 elif not Options.init_local_none and assigned is None:
1354 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1355 (entry.cname, entry.name, code.error_goto(self.pos)))
1356 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1358 def generate_assignment_code(self, rhs, code):
1359 #print "NameNode.generate_assignment_code:", self.name ###
1360 entry = self.entry
1361 if entry is None:
1362 return # There was an error earlier
1364 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1365 and not self.lhs_of_first_assignment):
1366 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1368 # is_pyglobal seems to be True for module level-globals only.
1369 # We use this to access class->tp_dict if necessary.
1370 if entry.is_pyglobal:
1371 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1372 interned_cname = code.intern_identifier(self.entry.name)
1373 namespace = self.entry.scope.namespace_cname
1374 if entry.is_member:
1375 # if the entry is a member we have to cheat: SetAttr does not work
1376 # on types, so we create a descriptor which is then added to tp_dict
1377 code.put_error_if_neg(self.pos,
1378 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1379 namespace,
1380 interned_cname,
1381 rhs.py_result()))
1382 rhs.generate_disposal_code(code)
1383 rhs.free_temps(code)
1384 # in Py2.6+, we need to invalidate the method cache
1385 code.putln("PyType_Modified(%s);" %
1386 entry.scope.parent_type.typeptr_cname)
1387 else:
1388 code.put_error_if_neg(self.pos,
1389 'PyObject_SetAttr(%s, %s, %s)' % (
1390 namespace,
1391 interned_cname,
1392 rhs.py_result()))
1393 if debug_disposal_code:
1394 print("NameNode.generate_assignment_code:")
1395 print("...generating disposal code for %s" % rhs)
1396 rhs.generate_disposal_code(code)
1397 rhs.free_temps(code)
1398 else:
1399 if self.type.is_buffer:
1400 # Generate code for doing the buffer release/acquisition.
1401 # This might raise an exception in which case the assignment (done
1402 # below) will not happen.
1403 #
1404 # The reason this is not in a typetest-like node is because the
1405 # variables that the acquired buffer info is stored to is allocated
1406 # per entry and coupled with it.
1407 self.generate_acquire_buffer(rhs, code)
1409 if self.type.is_pyobject:
1410 #print "NameNode.generate_assignment_code: to", self.name ###
1411 #print "...from", rhs ###
1412 #print "...LHS type", self.type, "ctype", self.ctype() ###
1413 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1414 if self.use_managed_ref:
1415 rhs.make_owned_reference(code)
1416 if entry.is_cglobal:
1417 code.put_gotref(self.py_result())
1418 if self.use_managed_ref and not self.lhs_of_first_assignment:
1419 if entry.is_local and not Options.init_local_none:
1420 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1421 if initalized is True:
1422 code.put_decref(self.result(), self.ctype())
1423 elif initalized is None:
1424 code.put_xdecref(self.result(), self.ctype())
1425 else:
1426 code.put_decref(self.result(), self.ctype())
1427 if self.use_managed_ref:
1428 if entry.is_cglobal:
1429 code.put_giveref(rhs.py_result())
1430 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1431 if debug_disposal_code:
1432 print("NameNode.generate_assignment_code:")
1433 print("...generating post-assignment code for %s" % rhs)
1434 rhs.generate_post_assignment_code(code)
1435 rhs.free_temps(code)
1437 def generate_acquire_buffer(self, rhs, code):
1438 # rhstmp is only used in case the rhs is a complicated expression leading to
1439 # the object, to avoid repeating the same C expression for every reference
1440 # to the rhs. It does NOT hold a reference.
1441 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1442 if pretty_rhs:
1443 rhstmp = rhs.result_as(self.ctype())
1444 else:
1445 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1446 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1448 buffer_aux = self.entry.buffer_aux
1449 bufstruct = buffer_aux.buffer_info_var.cname
1450 import Buffer
1451 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1452 is_initialized=not self.lhs_of_first_assignment,
1453 pos=self.pos, code=code)
1455 if not pretty_rhs:
1456 code.putln("%s = 0;" % rhstmp)
1457 code.funcstate.release_temp(rhstmp)
1459 def generate_deletion_code(self, code):
1460 if self.entry is None:
1461 return # There was an error earlier
1462 if not self.entry.is_pyglobal:
1463 error(self.pos, "Deletion of local or C global name not supported")
1464 return
1465 code.put_error_if_neg(self.pos,
1466 '__Pyx_DelAttrString(%s, "%s")' % (
1467 Naming.module_cname,
1468 self.entry.name))
1470 def annotate(self, code):
1471 if hasattr(self, 'is_called') and self.is_called:
1472 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1473 if self.type.is_pyobject:
1474 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1475 else:
1476 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1478 class BackquoteNode(ExprNode):
1479 # `expr`
1480 #
1481 # arg ExprNode
1483 type = py_object_type
1485 subexprs = ['arg']
1487 def analyse_types(self, env):
1488 self.arg.analyse_types(env)
1489 self.arg = self.arg.coerce_to_pyobject(env)
1490 self.is_temp = 1
1492 gil_message = "Backquote expression"
1494 def calculate_constant_result(self):
1495 self.constant_result = repr(self.arg.constant_result)
1497 def generate_result_code(self, code):
1498 code.putln(
1499 "%s = PyObject_Repr(%s); %s" % (
1500 self.result(),
1501 self.arg.py_result(),
1502 code.error_goto_if_null(self.result(), self.pos)))
1503 code.put_gotref(self.py_result())
1507 class ImportNode(ExprNode):
1508 # Used as part of import statement implementation.
1509 # Implements result =
1510 # __import__(module_name, globals(), None, name_list)
1511 #
1512 # module_name StringNode dotted name of module
1513 # name_list ListNode or None list of names to be imported
1515 type = py_object_type
1517 subexprs = ['module_name', 'name_list']
1519 def analyse_types(self, env):
1520 self.module_name.analyse_types(env)
1521 self.module_name = self.module_name.coerce_to_pyobject(env)
1522 if self.name_list:
1523 self.name_list.analyse_types(env)
1524 self.name_list.coerce_to_pyobject(env)
1525 self.is_temp = 1
1526 env.use_utility_code(import_utility_code)
1528 gil_message = "Python import"
1530 def generate_result_code(self, code):
1531 if self.name_list:
1532 name_list_code = self.name_list.py_result()
1533 else:
1534 name_list_code = "0"
1535 code.putln(
1536 "%s = __Pyx_Import(%s, %s); %s" % (
1537 self.result(),
1538 self.module_name.py_result(),
1539 name_list_code,
1540 code.error_goto_if_null(self.result(), self.pos)))
1541 code.put_gotref(self.py_result())
1544 class IteratorNode(ExprNode):
1545 # Used as part of for statement implementation.
1546 #
1547 # allocate_counter_temp/release_counter_temp needs to be called
1548 # by parent (ForInStatNode)
1549 #
1550 # Implements result = iter(sequence)
1551 #
1552 # sequence ExprNode
1554 type = py_object_type
1556 subexprs = ['sequence']
1558 def analyse_types(self, env):
1559 self.sequence.analyse_types(env)
1560 if isinstance(self.sequence, SliceIndexNode) and \
1561 (self.sequence.base.type.is_array or self.sequence.base.type.is_ptr) \
1562 or self.sequence.type.is_array and self.sequence.type.size is not None:
1563 # C array iteration will be transformed later on
1564 pass
1565 else:
1566 self.sequence = self.sequence.coerce_to_pyobject(env)
1567 self.is_temp = 1
1569 gil_message = "Iterating over Python object"
1571 def allocate_counter_temp(self, code):
1572 self.counter_cname = code.funcstate.allocate_temp(
1573 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1575 def release_counter_temp(self, code):
1576 code.funcstate.release_temp(self.counter_cname)
1578 def generate_result_code(self, code):
1579 is_builtin_sequence = self.sequence.type is list_type or \
1580 self.sequence.type is tuple_type
1581 may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
1582 if is_builtin_sequence:
1583 code.putln(
1584 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1585 elif may_be_a_sequence:
1586 code.putln(
1587 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1588 self.sequence.py_result(),
1589 self.sequence.py_result()))
1590 if may_be_a_sequence:
1591 code.putln(
1592 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1593 self.counter_cname,
1594 self.result(),
1595 self.sequence.py_result(),
1596 self.result()))
1597 code.putln("} else {")
1598 if is_builtin_sequence:
1599 code.putln(
1600 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1601 code.error_goto(self.pos))
1602 else:
1603 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1604 self.counter_cname,
1605 self.result(),
1606 self.sequence.py_result(),
1607 code.error_goto_if_null(self.result(), self.pos)))
1608 code.put_gotref(self.py_result())
1609 if may_be_a_sequence:
1610 code.putln("}")
1613 class NextNode(AtomicExprNode):
1614 # Used as part of for statement implementation.
1615 # Implements result = iterator.next()
1616 # Created during analyse_types phase.
1617 # The iterator is not owned by this node.
1618 #
1619 # iterator ExprNode
1621 type = py_object_type
1623 def __init__(self, iterator, env):
1624 self.pos = iterator.pos
1625 self.iterator = iterator
1626 self.is_temp = 1
1628 def generate_result_code(self, code):
1629 sequence_type = self.iterator.sequence.type
1630 if sequence_type is list_type:
1631 type_checks = [(list_type, "List")]
1632 elif sequence_type is tuple_type:
1633 type_checks = [(tuple_type, "Tuple")]
1634 elif not sequence_type.is_builtin_type:
1635 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1636 else:
1637 type_checks = []
1639 for py_type, prefix in type_checks:
1640 if len(type_checks) > 1:
1641 code.putln(
1642 "if (likely(Py%s_CheckExact(%s))) {" % (
1643 prefix, self.iterator.py_result()))
1644 code.putln(
1645 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1646 self.iterator.counter_cname,
1647 prefix,
1648 self.iterator.py_result()))
1649 code.putln(
1650 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1651 self.result(),
1652 prefix,
1653 self.iterator.py_result(),
1654 self.iterator.counter_cname,
1655 self.result(),
1656 self.iterator.counter_cname))
1657 if len(type_checks) > 1:
1658 code.put("} else ")
1659 if len(type_checks) == 1:
1660 return
1661 code.putln("{")
1662 code.putln(
1663 "%s = PyIter_Next(%s);" % (
1664 self.result(),
1665 self.iterator.py_result()))
1666 code.putln(
1667 "if (!%s) {" %
1668 self.result())
1669 code.putln(code.error_goto_if_PyErr(self.pos))
1670 code.putln("break;")
1671 code.putln("}")
1672 code.put_gotref(self.py_result())
1673 code.putln("}")
1676 class ExcValueNode(AtomicExprNode):
1677 # Node created during analyse_types phase
1678 # of an ExceptClauseNode to fetch the current
1679 # exception value.
1681 type = py_object_type
1683 def __init__(self, pos, env):
1684 ExprNode.__init__(self, pos)
1686 def set_var(self, var):
1687 self.var = var
1689 def calculate_result_code(self):
1690 return self.var
1692 def generate_result_code(self, code):
1693 pass
1695 def analyse_types(self, env):
1696 pass
1699 class TempNode(ExprNode):
1700 # Node created during analyse_types phase
1701 # of some nodes to hold a temporary value.
1702 #
1703 # Note: One must call "allocate" and "release" on
1704 # the node during code generation to get/release the temp.
1705 # This is because the temp result is often used outside of
1706 # the regular cycle.
1708 subexprs = []
1710 def __init__(self, pos, type, env):
1711 ExprNode.__init__(self, pos)
1712 self.type = type
1713 if type.is_pyobject:
1714 self.result_ctype = py_object_type
1715 self.is_temp = 1
1717 def analyse_types(self, env):
1718 return self.type
1720 def generate_result_code(self, code):
1721 pass
1723 def allocate(self, code):
1724 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1726 def release(self, code):
1727 code.funcstate.release_temp(self.temp_cname)
1728 self.temp_cname = None
1730 def result(self):
1731 try:
1732 return self.temp_cname
1733 except:
1734 assert False, "Remember to call allocate/release on TempNode"
1735 raise
1737 # Do not participate in normal temp alloc/dealloc:
1738 def allocate_temp_result(self, code):
1739 pass
1741 def release_temp_result(self, code):
1742 pass
1744 class PyTempNode(TempNode):
1745 # TempNode holding a Python value.
1747 def __init__(self, pos, env):
1748 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1750 class RawCNameExprNode(ExprNode):
1751 subexprs = []
1753 def __init__(self, pos, type=None):
1754 self.pos = pos
1755 self.type = type
1757 def analyse_types(self, env):
1758 return self.type
1760 def set_cname(self, cname):
1761 self.cname = cname
1763 def result(self):
1764 return self.cname
1766 def generate_result_code(self, code):
1767 pass
1770 #-------------------------------------------------------------------
1771 #
1772 # Trailer nodes
1773 #
1774 #-------------------------------------------------------------------
1776 class IndexNode(ExprNode):
1777 # Sequence indexing.
1778 #
1779 # base ExprNode
1780 # index ExprNode
1781 # indices [ExprNode]
1782 # is_buffer_access boolean Whether this is a buffer access.
1783 #
1784 # indices is used on buffer access, index on non-buffer access.
1785 # The former contains a clean list of index parameters, the
1786 # latter whatever Python object is needed for index access.
1788 subexprs = ['base', 'index', 'indices']
1789 indices = None
1791 def __init__(self, pos, index, *args, **kw):
1792 ExprNode.__init__(self, pos, index=index, *args, **kw)
1793 self._index = index
1795 def calculate_constant_result(self):
1796 self.constant_result = \
1797 self.base.constant_result[self.index.constant_result]
1799 def compile_time_value(self, denv):
1800 base = self.base.compile_time_value(denv)
1801 index = self.index.compile_time_value(denv)
1802 try:
1803 return base[index]
1804 except Exception, e:
1805 self.compile_time_value_error(e)
1807 def is_ephemeral(self):
1808 return self.base.is_ephemeral()
1810 def analyse_target_declaration(self, env):
1811 pass
1813 def analyse_as_type(self, env):
1814 base_type = self.base.analyse_as_type(env)
1815 if base_type and not base_type.is_pyobject:
1816 if base_type.is_cpp_class:
1817 if isinstance(self.index, TupleNode):
1818 template_values = self.index.args
1819 else:
1820 template_values = [self.index]
1821 import Nodes
1822 type_node = Nodes.TemplatedTypeNode(
1823 pos = self.pos,
1824 positional_args = template_values,
1825 keyword_args = None)
1826 return type_node.analyse(env, base_type = base_type)
1827 else:
1828 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1829 return None
1831 def type_dependencies(self, env):
1832 return self.base.type_dependencies(env)
1834 def infer_type(self, env):
1835 if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1836 return py_object_type
1837 base_type = self.base.infer_type(env)
1838 if base_type.is_ptr or base_type.is_array:
1839 return base_type.base_type
1840 else:
1841 # TODO: Handle buffers (hopefully without too much redundancy).
1842 return py_object_type
1844 def analyse_types(self, env):
1845 self.analyse_base_and_index_types(env, getting = 1)
1847 def analyse_target_types(self, env):
1848 self.analyse_base_and_index_types(env, setting = 1)
1850 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1851 # Note: This might be cleaned up by having IndexNode
1852 # parsed in a saner way and only construct the tuple if
1853 # needed.
1855 # Note that this function must leave IndexNode in a cloneable state.
1856 # For buffers, self.index is packed out on the initial analysis, and
1857 # when cloning self.indices is copied.
1858 self.is_buffer_access = False
1860 self.base.analyse_types(env)
1861 if self.base.type.is_error:
1862 # Do not visit child tree if base is undeclared to avoid confusing
1863 # error messages
1864 self.type = PyrexTypes.error_type
1865 return
1867 # Handle the case where base is a literal char* (and we expect a string, not an int)
1868 if isinstance(self.base, BytesNode):
1869 self.base = self.base.coerce_to_pyobject(env)
1871 skip_child_analysis = False
1872 buffer_access = False
1873 if self.base.type.is_buffer:
1874 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1875 if self.indices:
1876 indices = self.indices
1877 else:
1878 if isinstance(self.index, TupleNode):
1879 indices = self.index.args
1880 else:
1881 indices = [self.index]
1882 if len(indices) == self.base.type.ndim:
1883 buffer_access = True
1884 skip_child_analysis = True
1885 for x in indices:
1886 x.analyse_types(env)
1887 if not x.type.is_int:
1888 buffer_access = False
1890 # On cloning, indices is cloned. Otherwise, unpack index into indices
1891 assert not (buffer_access and isinstance(self.index, CloneNode))
1893 if buffer_access:
1894 self.indices = indices
1895 self.index = None
1896 self.type = self.base.type.dtype
1897 self.is_buffer_access = True
1898 self.buffer_type = self.base.entry.type
1900 if getting and self.type.is_pyobject:
1901 self.is_temp = True
1902 if setting:
1903 if not self.base.entry.type.writable:
1904 error(self.pos, "Writing to readonly buffer")
1905 else:
1906 self.base.entry.buffer_aux.writable_needed = True
1907 else:
1908 if isinstance(self.index, TupleNode):
1909 self.index.analyse_types(env, skip_children=skip_child_analysis)
1910 elif not skip_child_analysis:
1911 self.index.analyse_types(env)
1912 self.original_index_type = self.index.type
1913 if self.base.type.is_pyobject:
1914 if self.index.type.is_int:
1915 if (not setting
1916 and (self.base.type is list_type or self.base.type is tuple_type)
1917 and (not self.index.type.signed or isinstance(self.index, IntNode) and int(self.index.value) >= 0)
1918 and not env.directives['boundscheck']):
1919 self.is_temp = 0
1920 else:
1921 self.is_temp = 1
1922 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1923 else:
1924 self.index = self.index.coerce_to_pyobject(env)
1925 self.is_temp = 1
1926 self.type = py_object_type
1927 else:
1928 if self.base.type.is_ptr or self.base.type.is_array:
1929 self.type = self.base.type.base_type
1930 if self.index.type.is_pyobject:
1931 self.index = self.index.coerce_to(
1932 PyrexTypes.c_py_ssize_t_type, env)
1933 if not self.index.type.is_int:
1934 error(self.pos,
1935 "Invalid index type '%s'" %
1936 self.index.type)
1937 elif self.base.type.is_cpp_class:
1938 function = env.lookup_operator("[]", [self.base, self.index])
1939 function = self.base.type.scope.lookup("operator[]")
1940 if function is None:
1941 error(self.pos, "Indexing '%s' not supported for index type '%s'" % (self.base.type, self.index.type))
1942 self.type = PyrexTypes.error_type
1943 self.result_code = "<error>"
1944 return
1945 func_type = function.type
1946 if func_type.is_ptr:
1947 func_type = func_type.base_type
1948 self.index = self.index.coerce_to(func_type.args[0].type, env)
1949 self.type = func_type.return_type
1950 if setting and not func_type.return_type.is_reference:
1951 error(self.pos, "Can't set non-reference '%s'" % self.type)
1952 else:
1953 error(self.pos,
1954 "Attempting to index non-array type '%s'" %
1955 self.base.type)
1956 self.type = PyrexTypes.error_type
1957 gil_message = "Indexing Python object"
1959 def nogil_check(self, env):
1960 if self.is_buffer_access:
1961 if env.directives['boundscheck']:
1962 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1963 return
1964 elif self.type.is_pyobject:
1965 error(self.pos, "Cannot access buffer with object dtype without gil")
1966 return
1967 super(IndexNode, self).nogil_check(env)
1970 def check_const_addr(self):
1971 return self.base.check_const_addr() and self.index.check_const()
1973 def is_lvalue(self):
1974 return 1
1976 def calculate_result_code(self):
1977 if self.is_buffer_access:
1978 return "(*%s)" % self.buffer_ptr_code
1979 elif self.base.type is list_type:
1980 return "PyList_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
1981 elif self.base.type is tuple_type:
1982 return "PyTuple_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
1983 else:
1984 return "(%s[%s])" % (
1985 self.base.result(), self.index.result())
1987 def extra_index_params(self):
1988 if self.index.type.is_int:
1989 if self.original_index_type.signed:
1990 size_adjustment = ""
1991 else:
1992 size_adjustment = "+1"
1993 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1994 else:
1995 return ""
1997 def generate_subexpr_evaluation_code(self, code):
1998 self.base.generate_evaluation_code(code)
1999 if not self.indices:
2000 self.index.generate_evaluation_code(code)
2001 else:
2002 for i in self.indices:
2003 i.generate_evaluation_code(code)
2005 def generate_subexpr_disposal_code(self, code):
2006 self.base.generate_disposal_code(code)
2007 if not self.indices:
2008 self.index.generate_disposal_code(code)
2009 else:
2010 for i in self.indices:
2011 i.generate_disposal_code(code)
2013 def free_subexpr_temps(self, code):
2014 self.base.free_temps(code)
2015 if not self.indices:
2016 self.index.free_temps(code)
2017 else:
2018 for i in self.indices:
2019 i.free_temps(code)
2021 def generate_result_code(self, code):
2022 if self.is_buffer_access:
2023 if code.globalstate.directives['nonecheck']:
2024 self.put_nonecheck(code)
2025 self.buffer_ptr_code = self.buffer_lookup_code(code)
2026 if self.type.is_pyobject:
2027 # is_temp is True, so must pull out value and incref it.
2028 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
2029 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
2030 elif self.type.is_pyobject and self.is_temp:
2031 if self.index.type.is_int:
2032 index_code = self.index.result()
2033 if self.base.type is list_type:
2034 function = "__Pyx_GetItemInt_List"
2035 elif self.base.type is tuple_type:
2036 function = "__Pyx_GetItemInt_Tuple"
2037 else:
2038 function = "__Pyx_GetItemInt"
2039 code.globalstate.use_utility_code(getitem_int_utility_code)
2040 else:
2041 function = "PyObject_GetItem"
2042 index_code = self.index.py_result()
2043 sign_code = ""
2044 code.putln(
2045 "%s = %s(%s, %s%s); if (!%s) %s" % (
2046 self.result(),
2047 function,
2048 self.base.py_result(),
2049 index_code,
2050 self.extra_index_params(),
2051 self.result(),
2052 code.error_goto(self.pos)))
2053 code.put_gotref(self.py_result())
2055 def generate_setitem_code(self, value_code, code):
2056 if self.index.type.is_int:
2057 function = "__Pyx_SetItemInt"
2058 index_code = self.index.result()
2059 code.globalstate.use_utility_code(setitem_int_utility_code)
2060 else:
2061 index_code = self.index.py_result()
2062 if self.base.type is dict_type:
2063 function = "PyDict_SetItem"
2064 # It would seem that we could specalized lists/tuples, but that
2065 # shouldn't happen here.
2066 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
2067 # not a PyObject*, and bad conversion here would give the wrong
2068 # exception. Also, tuples are supposed to be immutable, and raise
2069 # TypeErrors when trying to set their entries (PyTuple_SetItem
2070 # is for creating new tuples from).
2071 else:
2072 function = "PyObject_SetItem"
2073 code.putln(
2074 "if (%s(%s, %s, %s%s) < 0) %s" % (
2075 function,
2076 self.base.py_result(),
2077 index_code,
2078 value_code,
2079 self.extra_index_params(),
2080 code.error_goto(self.pos)))
2082 def generate_buffer_setitem_code(self, rhs, code, op=""):
2083 # Used from generate_assignment_code and InPlaceAssignmentNode
2084 if code.globalstate.directives['nonecheck']:
2085 self.put_nonecheck(code)
2086 ptrexpr = self.buffer_lookup_code(code)
2087 if self.buffer_type.dtype.is_pyobject:
2088 # Must manage refcounts. Decref what is already there
2089 # and incref what we put in.
2090 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2091 rhs_code = rhs.result()
2092 code.putln("%s = %s;" % (ptr, ptrexpr))
2093 code.put_gotref("*%s" % ptr)
2094 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2095 ptr, rhs_code
2096 ))
2097 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2098 code.put_giveref("*%s" % ptr)
2099 code.funcstate.release_temp(ptr)
2100 else:
2101 # Simple case
2102 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2104 def generate_assignment_code(self, rhs, code):
2105 self.generate_subexpr_evaluation_code(code)
2106 if self.is_buffer_access:
2107 self.generate_buffer_setitem_code(rhs, code)
2108 elif self.type.is_pyobject:
2109 self.generate_setitem_code(rhs.py_result(), code)
2110 else:
2111 code.putln(
2112 "%s = %s;" % (
2113 self.result(), rhs.result()))
2114 self.generate_subexpr_disposal_code(code)
2115 self.free_subexpr_temps(code)
2116 rhs.generate_disposal_code(code)
2117 rhs.free_temps(code)
2119 def generate_deletion_code(self, code):
2120 self.generate_subexpr_evaluation_code(code)
2121 #if self.type.is_pyobject:
2122 if self.index.type.is_int:
2123 function = "__Pyx_DelItemInt"
2124 index_code = self.index.result()
2125 code.globalstate.use_utility_code(delitem_int_utility_code)
2126 else:
2127 index_code = self.index.py_result()
2128 if self.base.type is dict_type:
2129 function = "PyDict_DelItem"
2130 else:
2131 function = "PyObject_DelItem"
2132 code.putln(
2133 "if (%s(%s, %s%s) < 0) %s" % (
2134 function,
2135 self.base.py_result(),
2136 index_code,
2137 self.extra_index_params(),
2138 code.error_goto(self.pos)))
2139 self.generate_subexpr_disposal_code(code)
2140 self.free_subexpr_temps(code)
2142 def buffer_lookup_code(self, code):
2143 # Assign indices to temps
2144 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2145 for temp, index in zip(index_temps, self.indices):
2146 code.putln("%s = %s;" % (temp, index.result()))
2147 # Generate buffer access code using these temps
2148 import Buffer
2149 # The above could happen because child_attrs is wrong somewhere so that
2150 # options are not propagated.
2151 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2152 index_signeds=[i.type.signed for i in self.indices],
2153 index_cnames=index_temps,
2154 directives=code.globalstate.directives,
2155 pos=self.pos, code=code)
2157 def put_nonecheck(self, code):
2158 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2159 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2160 code.putln("__Pyx_RaiseNoneIndexingError();")
2161 code.putln(code.error_goto(self.pos))
2162 code.putln("}")
2164 class SliceIndexNode(ExprNode):
2165 # 2-element slice indexing
2166 #
2167 # base ExprNode
2168 # start ExprNode or None
2169 # stop ExprNode or None
2171 subexprs = ['base', 'start', 'stop']
2173 def infer_type(self, env):
2174 base_type = self.base.infer_type(env)
2175 if base_type.is_string:
2176 return bytes_type
2177 elif base_type in (bytes_type, str_type, unicode_type,
2178 list_type, tuple_type):
2179 return base_type
2180 return py_object_type
2182 def calculate_constant_result(self):
2183 self.constant_result = self.base.constant_result[
2184 self.start.constant_result : self.stop.constant_result]
2186 def compile_time_value(self, denv):
2187 base = self.base.compile_time_value(denv)
2188 if self.start is None:
2189 start = 0
2190 else:
2191 start = self.start.compile_time_value(denv)
2192 if self.stop is None:
2193 stop = None
2194 else:
2195 stop = self.stop.compile_time_value(denv)
2196 try:
2197 return base[start:stop]
2198 except Exception, e:
2199 self.compile_time_value_error(e)
2201 def analyse_target_declaration(self, env):
2202 pass
2204 def analyse_target_types(self, env):
2205 self.analyse_types(env)
2206 # when assigning, we must accept any Python type
2207 if self.type.is_pyobject:
2208 self.type = py_object_type
2210 def analyse_types(self, env):
2211 self.base.analyse_types(env)
2212 if self.start:
2213 self.start.analyse_types(env)
2214 if self.stop:
2215 self.stop.analyse_types(env)
2216 base_type = self.base.type
2217 if base_type.is_string:
2218 self.type = bytes_type
2219 elif base_type.is_array or base_type.is_ptr:
2220 # we need a ptr type here instead of an array type, as
2221 # array types can result in invalid type casts in the C
2222 # code
2223 self.type = PyrexTypes.CPtrType(base_type.base_type)
2224 else:
2225 self.base = self.base.coerce_to_pyobject(env)
2226 self.type = py_object_type
2227 if base_type.is_builtin_type:
2228 # slicing builtin types returns something of the same type
2229 self.type = base_type
2230 c_int = PyrexTypes.c_py_ssize_t_type
2231 if self.start:
2232 self.start = self.start.coerce_to(c_int, env)
2233 if self.stop:
2234 self.stop = self.stop.coerce_to(c_int, env)
2235 self.is_temp = 1
2237 nogil_check = Node.gil_error
2238 gil_message = "Slicing Python object"
2240 def generate_result_code(self, code):
2241 if not self.type.is_pyobject:
2242 error(self.pos,
2243 "Slicing is not currently supported for '%s'." % self.type)
2244 return
2245 if self.base.type.is_string:
2246 if self.stop is None:
2247 code.putln(
2248 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2249 self.result(),
2250 self.base.result(),
2251 self.start_code(),
2252 code.error_goto_if_null(self.result(), self.pos)))
2253 else:
2254 code.putln(
2255 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2256 self.result(),
2257 self.base.result(),
2258 self.start_code(),
2259 self.stop_code(),
2260 self.start_code(),
2261 code.error_goto_if_null(self.result(), self.pos)))
2262 else:
2263 code.putln(
2264 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2265 self.result(),
2266 self.base.py_result(),
2267 self.start_code(),
2268 self.stop_code(),
2269 code.error_goto_if_null(self.result(), self.pos)))
2270 code.put_gotref(self.py_result())
2272 def generate_assignment_code(self, rhs, code):
2273 self.generate_subexpr_evaluation_code(code)
2274 if self.type.is_pyobject:
2275 code.put_error_if_neg(self.pos,
2276 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2277 self.base.py_result(),
2278 self.start_code(),
2279 self.stop_code(),
2280 rhs.result()))
2281 else:
2282 start_offset = ''
2283 if self.start:
2284 start_offset = self.start_code()
2285 if start_offset == '0':
2286 start_offset = ''
2287 else:
2288 start_offset += '+'
2289 if rhs.type.is_array:
2290 array_length = rhs.type.size
2291 self.generate_slice_guard_code(code, array_length)
2292 else:
2293 error(self.pos,
2294 "Slice assignments from pointers are not yet supported.")
2295 # FIXME: fix the array size according to start/stop
2296 array_length = self.base.type.size
2297 for i in range(array_length):
2298 code.putln("%s[%s%s] = %s[%d];" % (
2299 self.base.result(), start_offset, i,
2300 rhs.result(), i))
2301 self.generate_subexpr_disposal_code(code)
2302 self.free_subexpr_temps(code)
2303 rhs.generate_disposal_code(code)
2304 rhs.free_temps(code)
2306 def generate_deletion_code(self, code):
2307 if not self.base.type.is_pyobject:
2308 error(self.pos,
2309 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2310 return
2311 self.generate_subexpr_evaluation_code(code)
2312 code.put_error_if_neg(self.pos,
2313 "PySequence_DelSlice(%s, %s, %s)" % (
2314 self.base.py_result(),
2315 self.start_code(),
2316 self.stop_code()))
2317 self.generate_subexpr_disposal_code(code)
2319 def generate_slice_guard_code(self, code, target_size):
2320 if not self.base.type.is_array:
2321 return
2322 slice_size = self.base.type.size
2323 start = stop = None
2324 if self.stop:
2325 stop = self.stop.result()
2326 try:
2327 stop = int(stop)
2328 if stop < 0:
2329 slice_size = self.base.type.size + stop
2330 else:
2331 slice_size = stop
2332 stop = None
2333 except ValueError:
2334 pass
2335 if self.start:
2336 start = self.start.result()
2337 try:
2338 start = int(start)
2339 if start < 0:
2340 start = self.base.type.size + start
2341 slice_size -= start
2342 start = None
2343 except ValueError:
2344 pass
2345 check = None
2346 if slice_size < 0:
2347 if target_size > 0:
2348 error(self.pos, "Assignment to empty slice.")
2349 elif start is None and stop is None:
2350 # we know the exact slice length
2351 if target_size != slice_size:
2352 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2353 slice_size, target_size))
2354 elif start is not None:
2355 if stop is None:
2356 stop = slice_size
2357 check = "(%s)-(%s)" % (stop, start)
2358 else: # stop is not None:
2359 check = stop
2360 if check:
2361 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2362 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));' % (
2363 target_size, check))
2364 code.putln(code.error_goto(self.pos))
2365 code.putln("}")
2367 def start_code(self):
2368 if self.start:
2369 return self.start.result()
2370 else:
2371 return "0"
2373 def stop_code(self):
2374 if self.stop:
2375 return self.stop.result()
2376 elif self.base.type.is_array:
2377 return self.base.type.size
2378 else:
2379 return "PY_SSIZE_T_MAX"
2381 def calculate_result_code(self):
2382 # self.result() is not used, but this method must exist
2383 return "<unused>"
2386 class SliceNode(ExprNode):
2387 # start:stop:step in subscript list
2388 #
2389 # start ExprNode
2390 # stop ExprNode
2391 # step ExprNode
2393 type = py_object_type
2394 is_temp = 1
2396 def calculate_constant_result(self):
2397 self.constant_result = self.base.constant_result[
2398 self.start.constant_result : \
2399 self.stop.constant_result : \
2400 self.step.constant_result]
2402 def compile_time_value(self, denv):
2403 start = self.start.compile_time_value(denv)
2404 if self.stop is None:
2405 stop = None
2406 else:
2407 stop = self.stop.compile_time_value(denv)
2408 if self.step is None:
2409 step = None
2410 else:
2411 step = self.step.compile_time_value(denv)
2412 try:
2413 return slice(start, stop, step)
2414 except Exception, e:
2415 self.compile_time_value_error(e)
2417 subexprs = ['start', 'stop', 'step']
2419 def analyse_types(self, env):
2420 self.start.analyse_types(env)
2421 self.stop.analyse_types(env)
2422 self.step.analyse_types(env)
2423 self.start = self.start.coerce_to_pyobject(env)
2424 self.stop = self.stop.coerce_to_pyobject(env)
2425 self.step = self.step.coerce_to_pyobject(env)
2427 gil_message = "Constructing Python slice object"
2429 def generate_result_code(self, code):
2430 code.putln(
2431 "%s = PySlice_New(%s, %s, %s); %s" % (
2432 self.result(),
2433 self.start.py_result(),
2434 self.stop.py_result(),
2435 self.step.py_result(),
2436 code.error_goto_if_null(self.result(), self.pos)))
2437 code.put_gotref(self.py_result())
2440 class CallNode(ExprNode):
2442 def analyse_as_type_constructor(self, env):
2443 type = self.function.analyse_as_type(env)
2444 if type and type.is_struct_or_union:
2445 args, kwds = self.explicit_args_kwds()
2446 items = []
2447 for arg, member in zip(args, type.scope.var_entries):
2448 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2449 if kwds:
2450 items += kwds.key_value_pairs
2451 self.key_value_pairs = items
2452 self.__class__ = DictNode
2453 self.analyse_types(env)
2454 self.coerce_to(type, env)
2455 return True
2457 def nogil_check(self, env):
2458 func_type = self.function_type()
2459 if func_type.is_pyobject:
2460 self.gil_error()
2461 elif not getattr(func_type, 'nogil', False):
2462 self.gil_error()
2464 gil_message = "Calling gil-requiring function"
2467 class SimpleCallNode(CallNode):
2468 # Function call without keyword, * or ** args.
2469 #
2470 # function ExprNode
2471 # args [ExprNode]
2472 # arg_tuple ExprNode or None used internally
2473 # self ExprNode or None used internally
2474 # coerced_self ExprNode or None used internally
2475 # wrapper_call bool used internally
2476 # has_optional_args bool used internally
2478 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2480 self = None
2481 coerced_self = None
2482 arg_tuple = None
2483 wrapper_call = False
2484 has_optional_args = False
2486 def compile_time_value(self, denv):
2487 function = self.function.compile_time_value(denv)
2488 args = [arg.compile_time_value(denv) for arg in self.args]
2489 try:
2490 return function(*args)
2491 except Exception, e:
2492 self.compile_time_value_error(e)
2494 def type_dependencies(self, env):
2495 # TODO: Update when Danilo's C++ code merged in to handle the
2496 # the case of function overloading.
2497 return self.function.type_dependencies(env)
2499 def infer_type(self, env):
2500 function = self.function
2501 func_type = function.infer_type(env)
2502 if isinstance(self.function, NewExprNode):
2503 return PyrexTypes.CPtrType(self.function.class_type)
2504 if func_type.is_ptr:
2505 func_type = func_type.base_type
2506 if func_type.is_cfunction:
2507 return func_type.return_type
2508 elif func_type is type_type:
2509 if function.is_name and function.entry and function.entry.type:
2510 result_type = function.entry.type
2511 if result_type.is_extension_type:
2512 return result_type
2513 elif result_type.is_builtin_type:
2514 if function.entry.name == 'float':
2515 return PyrexTypes.c_double_type
2516 elif function.entry.name in Builtin.types_that_construct_their_instance:
2517 return result_type
2518 return py_object_type
2520 def analyse_as_type(self, env):
2521 attr = self.function.as_cython_attribute()
2522 if attr == 'pointer':
2523 if len(self.args) != 1:
2524 error(self.args.pos, "only one type allowed.")
2525 else:
2526 type = self.args[0].analyse_as_type(env)
2527 if not type:
2528 error(self.args[0].pos, "Unknown type")
2529 else:
2530 return PyrexTypes.CPtrType(type)
2532 def explicit_args_kwds(self):
2533 return self.args, None
2535 def analyse_types(self, env):
2536 if self.analyse_as_type_constructor(env):
2537 return
2538 function = self.function
2539 function.is_called = 1
2540 self.function.analyse_types(env)
2541 if function.is_attribute and function.entry and function.entry.is_cmethod:
2542 # Take ownership of the object from which the attribute
2543 # was obtained, because we need to pass it as 'self'.
2544 self.self = function.obj
2545 function.obj = CloneNode(self.self)
2546 func_type = self.function_type()
2547 if func_type.is_pyobject:
2548 self.arg_tuple = TupleNode(self.pos, args = self.args)
2549 self.arg_tuple.analyse_types(env)
2550 self.args = None
2551 if func_type is Builtin.type_type and function.is_name and \
2552 function.entry and \
2553 function.entry.is_builtin and \
2554 function.entry.name in Builtin.types_that_construct_their_instance:
2555 # calling a builtin type that returns a specific object type
2556 if function.entry.name == 'float':
2557 # the following will come true later on in a transform
2558 self.type = PyrexTypes.c_double_type
2559 self.result_ctype = PyrexTypes.c_double_type
2560 else:
2561 self.type = Builtin.builtin_types[function.entry.name]
2562 self.result_ctype = py_object_type
2563 elif function.is_name and function.type_entry:
2564 # We are calling an extension type constructor. As
2565 # long as we do not support __new__(), the result type
2566 # is clear
2567 self.type = function.type_entry.type
2568 self.result_ctype = py_object_type
2569 else:
2570 self.type = py_object_type
2571 self.is_temp = 1
2572 else:
2573 for arg in self.args:
2574 arg.analyse_types(env)
2575 if self.self and func_type.args:
2576 # Coerce 'self' to the type expected by the method.
2577 expected_type = func_type.args[0].type
2578 self.coerced_self = CloneNode(self.self).coerce_to(
2579 expected_type, env)
2580 # Insert coerced 'self' argument into argument list.
2581 self.args.insert(0, self.coerced_self)
2582 self.analyse_c_function_call(env)
2584 def function_type(self):
2585 # Return the type of the function being called, coercing a function
2586 # pointer to a function if necessary.
2587 func_type = self.function.type
2588 if func_type.is_ptr:
2589 func_type = func_type.base_type
2590 return func_type
2592 def analyse_c_function_call(self, env):
2593 if self.function.type.is_cpp_class:
2594 function = self.function.type.scope.lookup("operator()")
2595 if function is None:
2596 self.type = PyrexTypes.error_type
2597 self.result_code = "<error>"
2598 return
2599 else:
2600 function = self.function.entry
2601 entry = PyrexTypes.best_match(self.args, function.all_alternatives(), self.pos)
2602 if not entry:
2603 self.type = PyrexTypes.error_type
2604 self.result_code = "<error>"
2605 return
2606 self.function.entry = entry
2607 self.function.type = entry.type
2608 func_type = self.function_type()
2609 # Check no. of args
2610 max_nargs = len(func_type.args)
2611 expected_nargs = max_nargs - func_type.optional_arg_count
2612 actual_nargs = len(self.args)
2613 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2614 self.has_optional_args = 1
2615 self.is_temp = 1
2616 # Coerce arguments
2617 for i in range(min(max_nargs, actual_nargs)):
2618 formal_type = func_type.args[i].type
2619 self.args[i] = self.args[i].coerce_to(formal_type, env)
2620 for i in range(max_nargs, actual_nargs):
2621 if self.args[i].type.is_pyobject:
2622 error(self.args[i].pos,
2623 "Python object cannot be passed as a varargs parameter")
2624 # Calc result type and code fragment
2625 if isinstance(self.function, NewExprNode):
2626 self.type = PyrexTypes.CPtrType(self.function.class_type)
2627 else:
2628 self.type = func_type.return_type
2629 if self.type.is_pyobject:
2630 self.result_ctype = py_object_type
2631 self.is_temp = 1
2632 elif func_type.exception_value is not None \
2633 or func_type.exception_check:
2634 self.is_temp = 1
2635 # C++ exception handler
2636 if func_type.exception_check == '+':
2637 if func_type.exception_value is None:
2638 env.use_utility_code(cpp_exception_utility_code)
2640 def calculate_result_code(self):
2641 return self.c_call_code()
2643 def c_call_code(self):
2644 func_type = self.function_type()
2645 if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
2646 return "<error>"
2647 formal_args = func_type.args
2648 arg_list_code = []
2649 args = zip(formal_args, self.args)
2650 max_nargs = len(func_type.args)
2651 expected_nargs = max_nargs - func_type.optional_arg_count
2652 actual_nargs = len(self.args)
2653 for formal_arg, actual_arg in args[:expected_nargs]:
2654 arg_code = actual_arg.result_as(formal_arg.type)
2655 arg_list_code.append(arg_code)
2657 if func_type.is_overridable:
2658 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2660 if func_type.optional_arg_count:
2661 if expected_nargs == actual_nargs:
2662 optional_args = 'NULL'
2663 else:
2664 optional_args = "&%s" % self.opt_arg_struct
2665 arg_list_code.append(optional_args)
2667 for actual_arg in self.args[len(formal_args):]:
2668 arg_list_code.append(actual_arg.result())
2669 result = "%s(%s)" % (self.function.result(),
2670 ', '.join(arg_list_code))
2671 return result
2673 def generate_result_code(self, code):
2674 func_type = self.function_type()
2675 if func_type.is_pyobject:
2676 arg_code = self.arg_tuple.py_result()
2677 code.putln(
2678 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2679 self.result(),
2680 self.function.py_result(),
2681 arg_code,
2682 code.error_goto_if_null(self.result(), self.pos)))
2683 code.put_gotref(self.py_result())
2684 elif func_type.is_cfunction:
2685 if self.has_optional_args:
2686 actual_nargs = len(self.args)
2687 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2688 self.opt_arg_struct = code.funcstate.allocate_temp(
2689 func_type.op_arg_struct.base_type, manage_ref=True)
2690 code.putln("%s.%s = %s;" % (
2691 self.opt_arg_struct,
2692 Naming.pyrex_prefix + "n",
2693 len(self.args) - expected_nargs))
2694 args = zip(func_type.args, self.args)
2695 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2696 code.putln("%s.%s = %s;" % (
2697 self.opt_arg_struct,
2698 func_type.opt_arg_cname(formal_arg.name),
2699 actual_arg.result_as(formal_arg.type)))
2700 exc_checks = []
2701 if self.type.is_pyobject and self.is_temp:
2702 exc_checks.append("!%s" % self.result())
2703 else:
2704 exc_val = func_type.exception_value
2705 exc_check = func_type.exception_check
2706 if exc_val is not None:
2707 exc_checks.append("%s == %s" % (self.result(), exc_val))
2708 if exc_check:
2709 exc_checks.append("PyErr_Occurred()")
2710 if self.is_temp or exc_checks:
2711 rhs = self.c_call_code()
2712 if self.result():
2713 lhs = "%s = " % self.result()
2714 if self.is_temp and self.type.is_pyobject:
2715 #return_type = self.type # func_type.return_type
2716 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2717 # "from", return_type, "to pyobject" ###
2718 rhs = typecast(py_object_type, self.type, rhs)
2719 else:
2720 lhs = ""
2721 if func_type.exception_check == '+':
2722 if func_type.exception_value is None:
2723 raise_py_exception = "__Pyx_CppExn2PyErr()"
2724 elif func_type.exception_value.type.is_pyobject:
2725 raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
2726 func_type.exception_value.entry.cname,
2727 func_type.exception_value.entry.cname)
2728 else:
2729 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2730 code.putln(
2731 "try {%s%s;} catch(...) {%s; %s}" % (
2732 lhs,
2733 rhs,
2734 raise_py_exception,
2735 code.error_goto(self.pos)))
2736 else:
2737 if exc_checks:
2738 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2739 else:
2740 goto_error = ""
2741 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2742 if self.type.is_pyobject and self.result():
2743 code.put_gotref(self.py_result())
2744 if self.has_optional_args:
2745 code.funcstate.release_temp(self.opt_arg_struct)
2748 class PythonCapiFunctionNode(ExprNode):
2749 subexprs = []
2750 def __init__(self, pos, py_name, cname, func_type, utility_code = None):
2751 self.pos = pos
2752 self.name = py_name
2753 self.cname = cname
2754 self.type = func_type
2755 self.utility_code = utility_code
2757 def analyse_types(self, env):
2758 pass
2760 def generate_result_code(self, code):
2761 if self.utility_code:
2762 code.globalstate.use_utility_code(self.utility_code)
2764 def calculate_result_code(self):
2765 return self.cname
2767 class PythonCapiCallNode(SimpleCallNode):
2768 # Python C-API Function call (only created in transforms)
2770 def __init__(self, pos, function_name, func_type,
2771 utility_code = None, py_name=None, **kwargs):
2772 self.type = func_type.return_type
2773 self.result_ctype = self.type
2774 self.function = PythonCapiFunctionNode(
2775 pos, py_name, function_name, func_type,
2776 utility_code = utility_code)
2777 # call this last so that we can override the constructed
2778 # attributes above with explicit keyword arguments if required
2779 SimpleCallNode.__init__(self, pos, **kwargs)
2782 class GeneralCallNode(CallNode):
2783 # General Python function call, including keyword,
2784 # * and ** arguments.
2785 #
2786 # function ExprNode
2787 # positional_args ExprNode Tuple of positional arguments
2788 # keyword_args ExprNode or None Dict of keyword arguments
2789 # starstar_arg ExprNode or None Dict of extra keyword args
2791 type = py_object_type
2793 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2795 nogil_check = Node.gil_error
2797 def compile_time_value(self, denv):
2798 function = self.function.compile_time_value(denv)
2799 positional_args = self.positional_args.compile_time_value(denv)
2800 keyword_args = self.keyword_args.compile_time_value(denv)
2801 starstar_arg = self.starstar_arg.compile_time_value(denv)
2802 try:
2803 keyword_args.update(starstar_arg)
2804 return function(*positional_args, **keyword_args)
2805 except Exception, e:
2806 self.compile_time_value_error(e)
2808 def explicit_args_kwds(self):
2809 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2810 raise PostParseError(self.pos,
2811 'Compile-time keyword arguments must be explicit.')
2812 return self.positional_args.args, self.keyword_args
2814 def analyse_types(self, env):
2815 if self.analyse_as_type_constructor(env):
2816 return
2817 self.function.analyse_types(env)
2818 self.positional_args.analyse_types(env)
2819 if self.keyword_args:
2820 self.keyword_args.analyse_types(env)
2821 if self.starstar_arg:
2822 self.starstar_arg.analyse_types(env)
2823 if not self.function.type.is_pyobject:
2824 if self.function.type.is_error:
2825 self.type = error_type
2826 return
2827 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2828 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2829 else:
2830 self.function = self.function.coerce_to_pyobject(env)
2831 self.positional_args = \
2832 self.positional_args.coerce_to_pyobject(env)
2833 if self.starstar_arg:
2834 self.starstar_arg = \
2835 self.starstar_arg.coerce_to_pyobject(env)
2836 function = self.function
2837 if function.is_name and function.type_entry:
2838 # We are calling an extension type constructor. As long
2839 # as we do not support __new__(), the result type is clear
2840 self.type = function.type_entry.type
2841 self.result_ctype = py_object_type
2842 else:
2843 self.type = py_object_type
2844 self.is_temp = 1
2846 def generate_result_code(self, code):
2847 if self.type.is_error: return
2848 kwargs_call_function = "PyEval_CallObjectWithKeywords"
2849 if self.keyword_args and self.starstar_arg:
2850 code.put_error_if_neg(self.pos,
2851 "PyDict_Update(%s, %s)" % (
2852 self.keyword_args.py_result(),
2853 self.starstar_arg.py_result()))
2854 keyword_code = self.keyword_args.py_result()
2855 elif self.keyword_args:
2856 keyword_code = self.keyword_args.py_result()
2857 elif self.starstar_arg:
2858 keyword_code = self.starstar_arg.py_result()
2859 if self.starstar_arg.type is not Builtin.dict_type:
2860 # CPython supports calling functions with non-dicts, so do we
2861 code.globalstate.use_utility_code(kwargs_call_utility_code)
2862 kwargs_call_function = "__Pyx_PyEval_CallObjectWithKeywords"
2863 else:
2864 keyword_code = None
2865 if not keyword_code:
2866 call_code = "PyObject_Call(%s, %s, NULL)" % (
2867 self.function.py_result(),
2868 self.positional_args.py_result())
2869 else:
2870 call_code = "%s(%s, %s, %s)" % (
2871 kwargs_call_function,
2872 self.function.py_result(),
2873 self.positional_args.py_result(),
2874 keyword_code)
2875 code.putln(
2876 "%s = %s; %s" % (
2877 self.result(),
2878 call_code,
2879 code.error_goto_if_null(self.result(), self.pos)))
2880 code.put_gotref(self.py_result())
2883 class AsTupleNode(ExprNode):
2884 # Convert argument to tuple. Used for normalising
2885 # the * argument of a function call.
2886 #
2887 # arg ExprNode
2889 subexprs = ['arg']
2891 def calculate_constant_result(self):
2892 self.constant_result = tuple(self.base.constant_result)
2894 def compile_time_value(self, denv):
2895 arg = self.arg.compile_time_value(denv)
2896 try:
2897 return tuple(arg)
2898 except Exception, e:
2899 self.compile_time_value_error(e)
2901 def analyse_types(self, env):
2902 self.arg.analyse_types(env)
2903 self.arg = self.arg.coerce_to_pyobject(env)
2904 self.type = tuple_type
2905 self.is_temp = 1
2907 nogil_check = Node.gil_error
2908 gil_message = "Constructing Python tuple"
2910 def generate_result_code(self, code):
2911 code.putln(
2912 "%s = PySequence_Tuple(%s); %s" % (
2913 self.result(),
2914 self.arg.py_result(),
2915 code.error_goto_if_null(self.result(), self.pos)))
2916 code.put_gotref(self.py_result())
2919 class AttributeNode(ExprNode):
2920 # obj.attribute
2921 #
2922 # obj ExprNode
2923 # attribute string
2924 # needs_none_check boolean Used if obj is an extension type.
2925 # If set to True, it is known that the type is not None.
2926 #
2927 # Used internally:
2928 #
2929 # is_py_attr boolean Is a Python getattr operation
2930 # member string C name of struct member
2931 # is_called boolean Function call is being done on result
2932 # entry Entry Symbol table entry of attribute
2934 is_attribute = 1
2935 subexprs = ['obj']
2937 type = PyrexTypes.error_type
2938 entry = None
2939 is_called = 0
2940 needs_none_check = True
2942 def as_cython_attribute(self):
2943 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2944 return self.attribute
2945 cy = self.obj.as_cython_attribute()
2946 if cy:
2947 return "%s.%s" % (cy, self.attribute)
2949 def coerce_to(self, dst_type, env):
2950 # If coercing to a generic pyobject and this is a cpdef function
2951 # we can create the corresponding attribute
2952 if dst_type is py_object_type:
2953 entry = self.entry
2954 if entry and entry.is_cfunction and entry.as_variable:
2955 # must be a cpdef function
2956 self.is_temp = 1
2957 self.entry = entry.as_variable
2958 self.analyse_as_python_attribute(env)
2959 return self
2960 return ExprNode.coerce_to(self, dst_type, env)
2962 def calculate_constant_result(self):
2963 attr = self.attribute
2964 if attr.startswith("__") and attr.endswith("__"):
2965 return
2966 self.constant_result = getattr(self.obj.constant_result, attr)
2968 def compile_time_value(self, denv):
2969 attr = self.attribute
2970 if attr.startswith("__") and attr.endswith("__"):
2971 error(self.pos,
2972 "Invalid attribute name '%s' in compile-time expression" % attr)
2973 return None
2974 obj = self.obj.compile_time_value(denv)
2975 try:
2976 return getattr(obj, attr)
2977 except Exception, e:
2978 self.compile_time_value_error(e)
2980 def type_dependencies(self, env):
2981 return self.obj.type_dependencies(env)
2983 def infer_type(self, env):
2984 if self.analyse_as_cimported_attribute(env, 0):
2985 return self.entry.type
2986 elif self.analyse_as_unbound_cmethod(env):
2987 return self.entry.type
2988 else:
2989 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2990 return self.type
2992 def analyse_target_declaration(self, env):
2993 pass
2995 def analyse_target_types(self, env):
2996 self.analyse_types(env, target = 1)
2998 def analyse_types(self, env, target = 0):
2999 if self.analyse_as_cimported_attribute(env, target):
3000 return
3001 if not target and self.analyse_as_unbound_cmethod(env):
3002 return
3003 self.analyse_as_ordinary_attribute(env, target)
3005 def analyse_as_cimported_attribute(self, env, target):
3006 # Try to interpret this as a reference to an imported
3007 # C const, type, var or function. If successful, mutates
3008 # this node into a NameNode and returns 1, otherwise
3009 # returns 0.
3010 module_scope = self.obj.analyse_as_module(env)
3011 if module_scope:
3012 entry = module_scope.lookup_here(self.attribute)
3013 if entry and (
3014 entry.is_cglobal or entry.is_cfunction
3015 or entry.is_type or entry.is_const):
3016 self.mutate_into_name_node(env, entry, target)
3017 return 1
3018 return 0
3020 def analyse_as_unbound_cmethod(self, env):
3021 # Try to interpret this as a reference to an unbound
3022 # C method of an extension type. If successful, mutates
3023 # this node into a NameNode and returns 1, otherwise
3024 # returns 0.
3025 type = self.obj.analyse_as_extension_type(env)
3026 if type:
3027 entry = type.scope.lookup_here(self.attribute)
3028 if entry and entry.is_cmethod:
3029 # Create a temporary entry describing the C method
3030 # as an ordinary function.
3031 ubcm_entry = Symtab.Entry(entry.name,
3032 "%s->%s" % (type.vtabptr_cname, entry.cname),
3033 entry.type)
3034 ubcm_entry.is_cfunction = 1
3035 ubcm_entry.func_cname = entry.func_cname
3036 ubcm_entry.is_unbound_cmethod = 1
3037 self.mutate_into_name_node(env, ubcm_entry, None)
3038 return 1
3039 return 0
3041 def analyse_as_type(self, env):
3042 module_scope = self.obj.analyse_as_module(env)
3043 if module_scope:
3044 return module_scope.lookup_type(self.attribute)
3045 return None
3047 def analyse_as_extension_type(self, env):
3048 # Try to interpret this as a reference to an extension type
3049 # in a cimported module. Returns the extension type, or None.
3050 module_scope = self.obj.analyse_as_module(env)
3051 if module_scope:
3052 entry = module_scope.lookup_here(self.attribute)
3053 if entry and entry.is_type and entry.type.is_extension_type:
3054 return entry.type
3055 return None
3057 def analyse_as_module(self, env):
3058 # Try to interpret this as a reference to a cimported module
3059 # in another cimported module. Returns the module scope, or None.
3060 module_scope = self.obj.analyse_as_module(env)
3061 if module_scope:
3062 entry = module_scope.lookup_here(self.attribute)
3063 if entry and entry.as_module:
3064 return entry.as_module
3065 return None
3067 def mutate_into_name_node(self, env, entry, target):
3068 # Mutate this node into a NameNode and complete the
3069 # analyse_types phase.
3070 self.__class__ = NameNode
3071 self.name = self.attribute
3072 self.entry = entry
3073 del self.obj
3074 del self.attribute
3075 if target:
3076 NameNode.analyse_target_types(self, env)
3077 else:
3078 NameNode.analyse_rvalue_entry(self, env)
3080 def analyse_as_ordinary_attribute(self, env, target):
3081 self.obj.analyse_types(env)
3082 self.analyse_attribute(env)
3083 if self.entry and self.entry.is_cmethod and not self.is_called:
3084 # error(self.pos, "C method can only be called")
3085 pass
3086 ## Reference to C array turns into pointer to first element.
3087 #while self.type.is_array:
3088 # self.type = self.type.element_ptr_type()
3089 if self.is_py_attr:
3090 if not target:
3091 self.is_temp = 1
3092 self.result_ctype = py_object_type
3094 def analyse_attribute(self, env, obj_type = None):
3095 # Look up attribute and set self.type and self.member.
3096 self.is_py_attr = 0
3097 self.member = self.attribute
3098 if obj_type is None:
3099 if self.obj.type.is_string:
3100 self.obj = self.obj.coerce_to_pyobject(env)
3101 obj_type = self.obj.type
3102 else:
3103 if obj_type.is_string:
3104 obj_type = py_object_type
3105 if obj_type.is_ptr or obj_type.is_array:
3106 obj_type = obj_type.base_type
3107 self.op = "->"
3108 elif obj_type.is_extension_type:
3109 self.op = "->"
3110 else:
3111 self.op = "."
3112 if obj_type.has_attributes:
3113 entry = None
3114 if obj_type.attributes_known():
3115 entry = obj_type.scope.lookup_here(self.attribute)
3116 if entry and entry.is_member:
3117 entry = None
3118 else:
3119 error(self.pos,
3120 "Cannot select attribute of incomplete type '%s'"
3121 % obj_type)
3122 self.type = PyrexTypes.error_type
3123 return
3124 self.entry = entry
3125 if entry:
3126 if obj_type.is_extension_type and entry.name == "__weakref__":
3127 error(self.pos, "Illegal use of special attribute __weakref__")
3128 # methods need the normal attribute lookup
3129 # because they do not have struct entries
3130 if entry.is_variable or entry.is_cmethod:
3131 self.type = entry.type
3132 self.member = entry.cname
3133 return
3134 else:
3135 # If it's not a variable or C method, it must be a Python
3136 # method of an extension type, so we treat it like a Python
3137 # attribute.
3138 pass
3139 # If we get here, the base object is not a struct/union/extension
3140 # type, or it is an extension type and the attribute is either not
3141 # declared or is declared as a Python method. Treat it as a Python
3142 # attribute reference.
3143 self.analyse_as_python_attribute(env, obj_type)
3145 def analyse_as_python_attribute(self, env, obj_type = None):
3146 if obj_type is None:
3147 obj_type = self.obj.type
3148 self.member = self.attribute
3149 self.type = py_object_type
3150 self.is_py_attr = 1
3151 if not obj_type.is_pyobject and not obj_type.is_error:
3152 if obj_type.can_coerce_to_pyobject(env):
3153 self.obj = self.obj.coerce_to_pyobject(env)
3154 else:
3155 error(self.pos,
3156 "Object of type '%s' has no attribute '%s'" %
3157 (obj_type, self.attribute))
3159 def nogil_check(self, env):
3160 if self.is_py_attr:
3161 self.gil_error()
3163 gil_message = "Accessing Python attribute"
3165 def is_simple(self):
3166 if self.obj:
3167 return self.result_in_temp() or self.obj.is_simple()
3168 else:
3169 return NameNode.is_simple(self)
3171 def is_lvalue(self):
3172 if self.obj:
3173 return 1
3174 else:
3175 return NameNode.is_lvalue(self)
3177 def is_ephemeral(self):
3178 if self.obj:
3179 return self.obj.is_ephemeral()
3180 else:
3181 return NameNode.is_ephemeral(self)
3183 def calculate_result_code(self):
3184 #print "AttributeNode.calculate_result_code:", self.member ###
3185 #print "...obj node =", self.obj, "code", self.obj.result() ###
3186 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3187 obj = self.obj
3188 obj_code = obj.result_as(obj.type)
3189 #print "...obj_code =", obj_code ###
3190 if self.entry and self.entry.is_cmethod:
3191 if obj.type.is_extension_type:
3192 return "((struct %s *)%s%s%s)->%s" % (
3193 obj.type.vtabstruct_cname, obj_code, self.op,
3194 obj.type.vtabslot_cname, self.member)
3195 else:
3196 return self.member
3197 elif obj.type.is_complex:
3198 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3199 else:
3200 return "%s%s%s" % (obj_code, self.op, self.member)
3202 def generate_result_code(self, code):
3203 interned_attr_cname = code.intern_identifier(self.attribute)
3204 if self.is_py_attr:
3205 code.putln(
3206 '%s = PyObject_GetAttr(%s, %s); %s' % (
3207 self.result(),
3208 self.obj.py_result(),
3209 interned_attr_cname,
3210 code.error_goto_if_null(self.result(), self.pos)))
3211 code.put_gotref(self.py_result())
3212 else:
3213 # result_code contains what is needed, but we may need to insert
3214 # a check and raise an exception
3215 if (self.obj.type.is_extension_type
3216 and self.needs_none_check
3217 and code.globalstate.directives['nonecheck']):
3218 self.put_nonecheck(code)
3220 def generate_assignment_code(self, rhs, code):
3221 interned_attr_cname = code.intern_identifier(self.attribute)
3222 self.obj.generate_evaluation_code(code)
3223 if self.is_py_attr:
3224 code.put_error_if_neg(self.pos,
3225 'PyObject_SetAttr(%s, %s, %s)' % (
3226 self.obj.py_result(),
3227 interned_attr_cname,
3228 rhs.py_result()))
3229 rhs.generate_disposal_code(code)
3230 rhs.free_temps(code)
3231 elif self.obj.type.is_complex:
3232 code.putln("__Pyx_SET_C%s(%s, %s);" % (
3233 self.member.upper(),
3234 self.obj.result_as(self.obj.type),
3235 rhs.result_as(self.ctype())))
3236 else:
3237 if (self.obj.type.is_extension_type
3238 and self.needs_none_check
3239 and code.globalstate.directives['nonecheck']):
3240 self.put_nonecheck(code)
3242 select_code = self.result()
3243 if self.type.is_pyobject and self.use_managed_ref:
3244 rhs.make_owned_reference(code)
3245 code.put_giveref(rhs.py_result())
3246 code.put_gotref(select_code)
3247 code.put_decref(select_code, self.ctype())
3248 code.putln(
3249 "%s = %s;" % (
3250 select_code,
3251 rhs.result_as(self.ctype())))
3252 #rhs.result()))
3253 rhs.generate_post_assignment_code(code)
3254 rhs.free_temps(code)
3255 self.obj.generate_disposal_code(code)
3256 self.obj.free_temps(code)
3258 def generate_deletion_code(self, code):
3259 interned_attr_cname = code.intern_identifier(self.attribute)
3260 self.obj.generate_evaluation_code(code)
3261 if self.is_py_attr:
3262 code.put_error_if_neg(self.pos,
3263 'PyObject_DelAttr(%s, %s)' % (
3264 self.obj.py_result(),
3265 interned_attr_cname))
3266 else:
3267 error(self.pos, "Cannot delete C attribute of extension type")
3268 self.obj.generate_disposal_code(code)
3269 self.obj.free_temps(code)
3271 def annotate(self, code):
3272 if self.is_py_attr:
3273 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3274 else:
3275 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3277 def put_nonecheck(self, code):
3278 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3279 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3280 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3281 code.putln(code.error_goto(self.pos))
3282 code.putln("}")
3285 #-------------------------------------------------------------------
3286 #
3287 # Constructor nodes
3288 #
3289 #-------------------------------------------------------------------
3291 class StarredTargetNode(ExprNode):
3292 # A starred expression like "*a"
3293 #
3294 # This is only allowed in sequence assignment targets such as
3295 #
3296 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3297 #
3298 # and will be removed during type analysis (or generate an error
3299 # if it's found at unexpected places).
3300 #
3301 # target ExprNode
3303 subexprs = ['target']
3304 is_starred = 1
3305 type = py_object_type
3306 is_temp = 1
3308 def __init__(self, pos, target):
3309 self.pos = pos
3310 self.target = target
3312 def analyse_declarations(self, env):
3313 error(self.pos, "can use starred expression only as assignment target")
3314 self.target.analyse_declarations(env)
3316 def analyse_types(self, env):
3317 error(self.pos, "can use starred expression only as assignment target")
3318 self.target.analyse_types(env)
3319 self.type = self.target.type
3321 def analyse_target_declaration(self, env):
3322 self.target.analyse_target_declaration(env)
3324 def analyse_target_types(self, env):
3325 self.target.analyse_target_types(env)
3326 self.type = self.target.type
3328 def calculate_result_code(self):
3329 return ""
3331 def generate_result_code(self, code):
3332 pass
3335 class SequenceNode(ExprNode):
3336 # Base class for list and tuple constructor nodes.
3337 # Contains common code for performing sequence unpacking.
3338 #
3339 # args [ExprNode]
3340 # iterator ExprNode
3341 # unpacked_items [ExprNode] or None
3342 # coerced_unpacked_items [ExprNode] or None
3344 subexprs = ['args']
3346 is_sequence_constructor = 1
3347 unpacked_items = None
3349 def compile_time_value_list(self, denv):
3350 return [arg.compile_time_value(denv) for arg in self.args]
3352 def replace_starred_target_node(self):
3353 # replace a starred node in the targets by the contained expression
3354 self.starred_assignment = False
3355 args = []
3356 for arg in self.args:
3357 if arg.is_starred:
3358 if self.starred_assignment:
3359 error(arg.pos, "more than 1 starred expression in assignment")
3360 self.starred_assignment = True
3361 arg = arg.target
3362 arg.is_starred = True
3363 args.append(arg)
3364 self.args = args
3366 def analyse_target_declaration(self, env):
3367 self.replace_starred_target_node()
3368 for arg in self.args:
3369 arg.analyse_target_declaration(env)
3371 def analyse_types(self, env, skip_children=False):
3372 for i in range(len(self.args)):
3373 arg = self.args[i]
3374 if not skip_children: arg.analyse_types(env)
3375 self.args[i] = arg.coerce_to_pyobject(env)
3376 self.type = py_object_type
3377 self.is_temp = 1
3379 def analyse_target_types(self, env):
3380 self.iterator = PyTempNode(self.pos, env)
3381 self.unpacked_items = []
3382 self.coerced_unpacked_items = []
3383 for arg in self.args:
3384 arg.analyse_target_types(env)
3385 if arg.is_starred:
3386 if not arg.type.assignable_from(Builtin.list_type):
3387 error(arg.pos,
3388 "starred target must have Python object (list) type")
3389 if arg.type is py_object_type:
3390 arg.type = Builtin.list_type
3391 unpacked_item = PyTempNode(self.pos, env)
3392 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3393 self.unpacked_items.append(unpacked_item)
3394 self.coerced_unpacked_items.append(coerced_unpacked_item)
3395 self.type = py_object_type
3397 def generate_result_code(self, code):
3398 self.generate_operation_code(code)
3400 def generate_assignment_code(self, rhs, code):
3401 if self.starred_assignment:
3402 self.generate_starred_assignment_code(rhs, code)
3403 else:
3404 self.generate_parallel_assignment_code(rhs, code)
3406 for item in self.unpacked_items:
3407 item.release(code)
3408 rhs.free_temps(code)
3410 def generate_parallel_assignment_code(self, rhs, code):
3411 # Need to work around the fact that generate_evaluation_code
3412 # allocates the temps in a rather hacky way -- the assignment
3413 # is evaluated twice, within each if-block.
3415 code.globalstate.use_utility_code(unpacking_utility_code)
3417 if rhs.type is tuple_type:
3418 tuple_check = "likely(%s != Py_None)"
3419 else:
3420 tuple_check = "PyTuple_CheckExact(%s)"
3421 code.putln(
3422 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3423 tuple_check % rhs.py_result(),
3424 rhs.py_result(),
3425 len(self.args)))
3426 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3427 for item in self.unpacked_items:
3428 item.allocate(code)
3429 for i in range(len(self.args)):
3430 item = self.unpacked_items[i]
3431 code.put(
3432 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3433 item.result(),
3434 i))
3435 code.put_incref(item.result(), item.ctype())
3436 value_node = self.coerced_unpacked_items[i]
3437 value_node.generate_evaluation_code(code)
3438 rhs.generate_disposal_code(code)
3440 for i in range(len(self.args)):
3441 self.args[i].generate_assignment_code(
3442 self.coerced_unpacked_items[i], code)
3444 code.putln("} else {")
3446 if rhs.type is tuple_type:
3447 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3448 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3449 rhs.py_result(), len(self.args)))
3450 code.putln(code.error_goto(self.pos))
3451 else:
3452 self.iterator.allocate(code)
3453 code.putln(
3454 "%s = PyObject_GetIter(%s); %s" % (
3455 self.iterator.result(),
3456 rhs.py_result(),
3457 code.error_goto_if_null(self.iterator.result(), self.pos)))
3458 code.put_gotref(self.iterator.py_result())
3459 rhs.generate_disposal_code(code)
3460 for i in range(len(self.args)):
3461 item = self.unpacked_items[i]
3462 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3463 self.iterator.py_result(), i)
3464 code.putln(
3465 "%s = %s; %s" % (
3466 item.result(),
3467 typecast(item.ctype(), py_object_type, unpack_code),
3468 code.error_goto_if_null(item.result(), self.pos)))
3469 code.put_gotref(item.py_result())
3470 value_node = self.coerced_unpacked_items[i]
3471 value_node.generate_evaluation_code(code)
3472 code.put_error_if_neg(self.pos,
3473 "__Pyx_EndUnpack(%s)" % (
3474 self.iterator.py_result()))
3475 if debug_disposal_code:
3476 print("UnpackNode.generate_assignment_code:")
3477 print("...generating disposal code for %s" % self.iterator)
3478 self.iterator.generate_disposal_code(code)
3479 self.iterator.free_temps(code)
3480 self.iterator.release(code)
3482 for i in range(len(self.args)):
3483 self.args[i].generate_assignment_code(
3484 self.coerced_unpacked_items[i], code)
3486 code.putln("}")
3488 def generate_starred_assignment_code(self, rhs, code):
3489 code.globalstate.use_utility_code(unpacking_utility_code)
3491 for i, arg in enumerate(self.args):
3492 if arg.is_starred:
3493 starred_target = self.unpacked_items[i]
3494 fixed_args_left = self.args[:i]
3495 fixed_args_right = self.args[i+1:]
3496 break
3498 self.iterator.allocate(code)
3499 code.putln(
3500 "%s = PyObject_GetIter(%s); %s" % (
3501 self.iterator.result(),
3502 rhs.py_result(),
3503 code.error_goto_if_null(self.iterator.result(), self.pos)))
3504 code.put_gotref(self.iterator.py_result())
3505 rhs.generate_disposal_code(code)
3507 for item in self.unpacked_items:
3508 item.allocate(code)
3509 for i in range(len(fixed_args_left)):
3510 item = self.unpacked_items[i]
3511 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3512 self.iterator.py_result(), i)
3513 code.putln(
3514 "%s = %s; %s" % (
3515 item.result(),
3516 typecast(item.ctype(), py_object_type, unpack_code),
3517 code.error_goto_if_null(item.result(), self.pos)))
3518 code.put_gotref(item.py_result())
3519 value_node = self.coerced_unpacked_items[i]
3520 value_node.generate_evaluation_code(code)
3522 target_list = starred_target.result()
3523 code.putln("%s = PySequence_List(%s); %s" % (
3524 target_list, self.iterator.py_result(),
3525 code.error_goto_if_null(target_list, self.pos)))
3526 code.put_gotref(target_list)
3527 if fixed_args_right:
3528 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3529 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3530 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3531 (target_list, len(unpacked_right_args))))
3532 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3533 len(fixed_args_left), target_list,
3534 code.error_goto(self.pos)))
3535 code.putln('}')
3536 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3537 self.coerced_unpacked_items[::-1])):
3538 code.putln(
3539 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3540 arg.py_result(),
3541 target_list, target_list))
3542 # resize the list the hard way
3543 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3544 code.put_gotref(arg.py_result())
3545 coerced_arg.generate_evaluation_code(code)
3547 self.iterator.generate_disposal_code(code)
3548 self.iterator.free_temps(code)
3549 self.iterator.release(code)
3551 for i in range(len(self.args)):
3552 self.args[i].generate_assignment_code(
3553 self.coerced_unpacked_items[i], code)
3555 def annotate(self, code):
3556 for arg in self.args:
3557 arg.annotate(code)
3558 if self.unpacked_items:
3559 for arg in self.unpacked_items:
3560 arg.annotate(code)
3561 for arg in self.coerced_unpacked_items:
3562 arg.annotate(code)
3565 class TupleNode(SequenceNode):
3566 # Tuple constructor.
3568 type = tuple_type
3570 gil_message = "Constructing Python tuple"
3572 def analyse_types(self, env, skip_children=False):
3573 if len(self.args) == 0:
3574 self.is_temp = 0
3575 self.is_literal = 1
3576 else:
3577 SequenceNode.analyse_types(self, env, skip_children)
3579 def calculate_result_code(self):
3580 if len(self.args) > 0:
3581 error(self.pos, "Positive length tuples must be constructed.")
3582 else:
3583 return Naming.empty_tuple
3585 def calculate_constant_result(self):
3586 self.constant_result = tuple([
3587 arg.constant_result for arg in self.args])
3589 def compile_time_value(self, denv):
3590 values = self.compile_time_value_list(denv)
3591 try:
3592 return tuple(values)
3593 except Exception, e:
3594 self.compile_time_value_error(e)
3596 def generate_operation_code(self, code):
3597 if len(self.args) == 0:
3598 # result_code is Naming.empty_tuple
3599 return
3600 code.putln(
3601 "%s = PyTuple_New(%s); %s" % (
3602 self.result(),
3603 len(self.args),
3604 code.error_goto_if_null(self.result(), self.pos)))
3605 code.put_gotref(self.py_result())
3606 for i in range(len(self.args)):
3607 arg = self.args[i]
3608 if not arg.result_in_temp():
3609 code.put_incref(arg.result(), arg.ctype())
3610 code.putln(
3611 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3612 self.result(),
3613 i,
3614 arg.py_result()))
3615 code.put_giveref(arg.py_result())
3617 def generate_subexpr_disposal_code(self, code):
3618 # We call generate_post_assignment_code here instead
3619 # of generate_disposal_code, because values were stored
3620 # in the tuple using a reference-stealing operation.
3621 for arg in self.args:
3622 arg.generate_post_assignment_code(code)
3623 # Should NOT call free_temps -- this is invoked by the default
3624 # generate_evaluation_code which will do that.
3627 class ListNode(SequenceNode):
3628 # List constructor.
3630 # obj_conversion_errors [PyrexError] used internally
3631 # orignial_args [ExprNode] used internally
3633 obj_conversion_errors = []
3635 gil_message = "Constructing Python list"
3637 def type_dependencies(self, env):
3638 return ()
3640 def infer_type(self, env):
3641 # TOOD: Infer non-object list arrays.
3642 return list_type
3644 def analyse_expressions(self, env):
3645 SequenceNode.analyse_expressions(self, env)
3646 self.coerce_to_pyobject(env)
3648 def analyse_types(self, env):
3649 hold_errors()
3650 self.original_args = list(self.args)
3651 SequenceNode.analyse_types(self, env)
3652 self.type = list_type
3653 self.obj_conversion_errors = held_errors()
3654 release_errors(ignore=True)
3656 def coerce_to(self, dst_type, env):
3657 if dst_type.is_pyobject:
3658 for err in self.obj_conversion_errors:
3659 report_error(err)
3660 self.obj_conversion_errors = []
3661 if not self.type.subtype_of(dst_type):
3662 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3663 elif dst_type.is_ptr:
3664 base_type = dst_type.base_type
3665 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3666 for i in range(len(self.original_args)):
3667 arg = self.args[i]
3668 if isinstance(arg, CoerceToPyTypeNode):
3669 arg = arg.arg
3670 self.args[i] = arg.coerce_to(base_type, env)
3671 elif dst_type.is_struct:
3672 if len(self.args) > len(dst_type.scope.var_entries):
3673 error(self.pos, "Too may members for '%s'" % dst_type)
3674 else:
3675 if len(self.args) < len(dst_type.scope.var_entries):
3676 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3677 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3678 if isinstance(arg, CoerceToPyTypeNode):
3679 arg = arg.arg
3680 self.args[i] = arg.coerce_to(member.type, env)
3681 self.type = dst_type
3682 else:
3683 self.type = error_type
3684 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3685 return self
3687 def release_temp(self, env):
3688 if self.type.is_array:
3689 # To be valid C++, we must allocate the memory on the stack
3690 # manually and be sure not to reuse it for something else.
3691 pass
3692 else:
3693 SequenceNode.release_temp(self, env)
3695 def calculate_constant_result(self):
3696 self.constant_result = [
3697 arg.constant_result for arg in self.args]
3699 def compile_time_value(self, denv):
3700 return self.compile_time_value_list(denv)
3702 def generate_operation_code(self, code):
3703 if self.type.is_pyobject:
3704 for err in self.obj_conversion_errors:
3705 report_error(err)
3706 code.putln("%s = PyList_New(%s); %s" %
3707 (self.result(),
3708 len(self.args),
3709 code.error_goto_if_null(self.result(), self.pos)))
3710 code.put_gotref(self.py_result())
3711 for i in range(len(self.args)):
3712 arg = self.args[i]
3713 #if not arg.is_temp:
3714 if not arg.result_in_temp():
3715 code.put_incref(arg.result(), arg.ctype())
3716 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3717 (self.result(),
3718 i,
3719 arg.py_result()))
3720 code.put_giveref(arg.py_result())
3721 elif self.type.is_array:
3722 for i, arg in enumerate(self.args):
3723 code.putln("%s[%s] = %s;" % (
3724 self.result(),
3725 i,
3726 arg.result()))
3727 elif self.type.is_struct:
3728 for arg, member in zip(self.args, self.type.scope.var_entries):
3729 code.putln("%s.%s = %s;" % (
3730 self.result(),
3731 member.cname,
3732 arg.result()))
3733 else:
3734 raise InternalError("List type never specified")
3736 def generate_subexpr_disposal_code(self, code):
3737 # We call generate_post_assignment_code here instead
3738 # of generate_disposal_code, because values were stored
3739 # in the list using a reference-stealing operation.
3740 for arg in self.args:
3741 arg.generate_post_assignment_code(code)
3742 # Should NOT call free_temps -- this is invoked by the default
3743 # generate_evaluation_code which will do that.
3746 class ComprehensionNode(ExprNode):
3747 subexprs = ["target"]
3748 child_attrs = ["loop", "append"]
3750 def infer_type(self, env):
3751 return self.target.infer_type(env)
3753 def analyse_declarations(self, env):
3754 self.append.target = self # this is used in the PyList_Append of the inner loop
3755 self.loop.analyse_declarations(env)
3757 def analyse_types(self, env):
3758 self.target.analyse_expressions(env)
3759 self.type = self.target.type
3760 self.loop.analyse_expressions(env)
3762 def calculate_result_code(self):
3763 return self.target.result()
3765 def generate_result_code(self, code):
3766 self.generate_operation_code(code)
3768 def generate_operation_code(self, code):
3769 self.loop.generate_execution_code(code)
3771 def annotate(self, code):
3772 self.loop.annotate(code)
3775 class ComprehensionAppendNode(ExprNode):
3776 # Need to be careful to avoid infinite recursion:
3777 # target must not be in child_attrs/subexprs
3778 subexprs = ['expr']
3780 type = PyrexTypes.c_int_type
3782 def analyse_types(self, env):
3783 self.expr.analyse_types(env)
3784 if not self.expr.type.is_pyobject:
3785 self.expr = self.expr.coerce_to_pyobject(env)
3786 self.is_temp = 1
3788 def generate_result_code(self, code):
3789 if self.target.type is list_type:
3790 function = "PyList_Append"
3791 elif self.target.type is set_type:
3792 function = "PySet_Add"
3793 else:
3794 raise InternalError(
3795 "Invalid type for comprehension node: %s" % self.target.type)
3797 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3798 (self.result(),
3799 function,
3800 self.target.result(),
3801 self.expr.result(),
3802 code.error_goto_if(self.result(), self.pos)))
3804 class DictComprehensionAppendNode(ComprehensionAppendNode):
3805 subexprs = ['key_expr', 'value_expr']
3807 def analyse_types(self, env):
3808 self.key_expr.analyse_types(env)
3809 if not self.key_expr.type.is_pyobject:
3810 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3811 self.value_expr.analyse_types(env)
3812 if not self.value_expr.type.is_pyobject:
3813 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3814 self.is_temp = 1
3816 def generate_result_code(self, code):
3817 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3818 (self.result(),
3819 self.target.result(),
3820 self.key_expr.result(),
3821 self.value_expr.result(),
3822 code.error_goto_if(self.result(), self.pos)))
3825 class SetNode(ExprNode):
3826 # Set constructor.
3828 type = set_type
3830 subexprs = ['args']
3832 gil_message = "Constructing Python set"
3834 def analyse_types(self, env):
3835 for i in range(len(self.args)):
3836 arg = self.args[i]
3837 arg.analyse_types(env)
3838 self.args[i] = arg.coerce_to_pyobject(env)
3839 self.type = set_type
3840 self.is_temp = 1
3842 def calculate_constant_result(self):
3843 self.constant_result = set([
3844 arg.constant_result for arg in self.args])
3846 def compile_time_value(self, denv):
3847 values = [arg.compile_time_value(denv) for arg in self.args]
3848 try:
3849 return set(values)
3850 except Exception, e:
3851 self.compile_time_value_error(e)
3853 def generate_evaluation_code(self, code):
3854 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3855 self.allocate_temp_result(code)
3856 code.putln(
3857 "%s = PySet_New(0); %s" % (
3858 self.result(),
3859 code.error_goto_if_null(self.result(), self.pos)))
3860 code.put_gotref(self.py_result())
3861 for arg in self.args:
3862 arg.generate_evaluation_code(code)
3863 code.putln(
3864 code.error_goto_if_neg(
3865 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3866 self.pos))
3867 arg.generate_disposal_code(code)
3868 arg.free_temps(code)
3871 class DictNode(ExprNode):
3872 # Dictionary constructor.
3873 #
3874 # key_value_pairs [DictItemNode]
3875 #
3876 # obj_conversion_errors [PyrexError] used internally
3878 subexprs = ['key_value_pairs']
3879 is_temp = 1
3880 type = dict_type
3882 obj_conversion_errors = []
3884 def calculate_constant_result(self):
3885 self.constant_result = dict([
3886 item.constant_result for item in self.key_value_pairs])
3888 def compile_time_value(self, denv):
3889 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3890 for item in self.key_value_pairs]
3891 try:
3892 return dict(pairs)
3893 except Exception, e:
3894 self.compile_time_value_error(e)
3896 def type_dependencies(self, env):
3897 return ()
3899 def infer_type(self, env):
3900 # TOOD: Infer struct constructors.
3901 return dict_type
3903 def analyse_types(self, env):
3904 hold_errors()
3905 for item in self.key_value_pairs:
3906 item.analyse_types(env)
3907 self.obj_conversion_errors = held_errors()
3908 release_errors(ignore=True)
3910 def coerce_to(self, dst_type, env):
3911 if dst_type.is_pyobject:
3912 self.release_errors()
3913 if not self.type.subtype_of(dst_type):
3914 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3915 elif dst_type.is_struct_or_union:
3916 self.type = dst_type
3917 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3918 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3919 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3920 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3921 for item in self.key_value_pairs:
3922 if isinstance(item.key, CoerceToPyTypeNode):
3923 item.key = item.key.arg
3924 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3925 error(item.key.pos, "Invalid struct field identifier")
3926 item.key = StringNode(item.key.pos, value="<error>")
3927 else:
3928 key = str(item.key.value) # converts string literals to unicode in Py3
3929 member = dst_type.scope.lookup_here(key)
3930 if not member:
3931 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3932 else:
3933 value = item.value
3934 if isinstance(value, CoerceToPyTypeNode):
3935 value = value.arg
3936 item.value = value.coerce_to(member.type, env)
3937 else:
3938 self.type = error_type
3939 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3940 return self
3942 def release_errors(self):
3943 for err in self.obj_conversion_errors:
3944 report_error(err)
3945 self.obj_conversion_errors = []
3947 gil_message = "Constructing Python dict"
3949 def generate_evaluation_code(self, code):
3950 # Custom method used here because key-value
3951 # pairs are evaluated and used one at a time.
3952 code.mark_pos(self.pos)
3953 self.allocate_temp_result(code)
3954 if self.type.is_pyobject:
3955 self.release_errors()
3956 code.putln(
3957 "%s = PyDict_New(); %s" % (
3958 self.result(),
3959 code.error_goto_if_null(self.result(), self.pos)))
3960 code.put_gotref(self.py_result())
3961 for item in self.key_value_pairs:
3962 item.generate_evaluation_code(code)
3963 if self.type.is_pyobject:
3964 code.put_error_if_neg(self.pos,
3965 "PyDict_SetItem(%s, %s, %s)" % (
3966 self.result(),
3967 item.key.py_result(),
3968 item.value.py_result()))
3969 else:
3970 code.putln("%s.%s = %s;" % (
3971 self.result(),
3972 item.key.value,
3973 item.value.result()))
3974 item.generate_disposal_code(code)
3975 item.free_temps(code)
3977 def annotate(self, code):
3978 for item in self.key_value_pairs:
3979 item.annotate(code)
3981 class DictItemNode(ExprNode):
3982 # Represents a single item in a DictNode
3983 #
3984 # key ExprNode
3985 # value ExprNode
3986 subexprs = ['key', 'value']
3988 nogil_check = None # Parent DictNode takes care of it
3990 def calculate_constant_result(self):
3991 self.constant_result = (
3992 self.key.constant_result, self.value.constant_result)
3994 def analyse_types(self, env):
3995 self.key.analyse_types(env)
3996 self.value.analyse_types(env)
3997 self.key = self.key.coerce_to_pyobject(env)
3998 self.value = self.value.coerce_to_pyobject(env)
4000 def generate_evaluation_code(self, code):
4001 self.key.generate_evaluation_code(code)
4002 self.value.generate_evaluation_code(code)
4004 def generate_disposal_code(self, code):
4005 self.key.generate_disposal_code(code)
4006 self.value.generate_disposal_code(code)
4008 def free_temps(self, code):
4009 self.key.free_temps(code)
4010 self.value.free_temps(code)
4012 def __iter__(self):
4013 return iter([self.key, self.value])
4016 class ClassNode(ExprNode):
4017 # Helper class used in the implementation of Python
4018 # class definitions. Constructs a class object given
4019 # a name, tuple of bases and class dictionary.
4020 #
4021 # name EncodedString Name of the class
4022 # bases ExprNode Base class tuple
4023 # dict ExprNode Class dict (not owned by this node)
4024 # doc ExprNode or None Doc string
4025 # module_name string Name of defining module
4027 subexprs = ['bases', 'doc']
4029 def analyse_types(self, env):
4030 self.bases.analyse_types(env)
4031 if self.doc:
4032 self.doc.analyse_types(env)
4033 self.doc = self.doc.coerce_to_pyobject(env)
4034 self.module_name = env.global_scope().qualified_name
4035 self.type = py_object_type
4036 self.is_temp = 1
4037 env.use_utility_code(create_class_utility_code);
4039 gil_message = "Constructing Python class"
4041 def generate_result_code(self, code):
4042 cname = code.intern_identifier(self.name)
4043 if self.doc:
4044 code.put_error_if_neg(self.pos,
4045 'PyDict_SetItemString(%s, "__doc__", %s)' % (
4046 self.dict.py_result(),
4047 self.doc.py_result()))
4048 code.putln(
4049 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
4050 self.result(),
4051 self.bases.py_result(),
4052 self.dict.py_result(),
4053 cname,
4054 self.module_name,
4055 code.error_goto_if_null(self.result(), self.pos)))
4056 code.put_gotref(self.py_result())
4059 class UnboundMethodNode(ExprNode):
4060 # Helper class used in the implementation of Python
4061 # class definitions. Constructs an unbound method
4062 # object from a class and a function.
4063 #
4064 # function ExprNode Function object
4066 type = py_object_type
4067 is_temp = 1
4069 subexprs = ['function']
4071 def analyse_types(self, env):
4072 self.function.analyse_types(env)
4074 gil_message = "Constructing an unbound method"
4076 def generate_result_code(self, code):
4077 class_cname = code.pyclass_stack[-1].classobj.result()
4078 code.putln(
4079 "%s = PyMethod_New(%s, 0, %s); %s" % (
4080 self.result(),
4081 self.function.py_result(),
4082 class_cname,
4083 code.error_goto_if_null(self.result(), self.pos)))
4084 code.put_gotref(self.py_result())
4087 class PyCFunctionNode(AtomicExprNode):
4088 # Helper class used in the implementation of Python
4089 # class definitions. Constructs a PyCFunction object
4090 # from a PyMethodDef struct.
4091 #
4092 # pymethdef_cname string PyMethodDef structure
4094 type = py_object_type
4095 is_temp = 1
4097 def analyse_types(self, env):
4098 pass
4100 gil_message = "Constructing Python function"
4102 def generate_result_code(self, code):
4103 code.putln(
4104 "%s = PyCFunction_New(&%s, 0); %s" % (
4105 self.result(),
4106 self.pymethdef_cname,
4107 code.error_goto_if_null(self.result(), self.pos)))
4108 code.put_gotref(self.py_result())
4110 #-------------------------------------------------------------------
4111 #
4112 # Unary operator nodes
4113 #
4114 #-------------------------------------------------------------------
4116 compile_time_unary_operators = {
4117 'not': operator.not_,
4118 '~': operator.inv,
4119 '-': operator.neg,
4120 '+': operator.pos,
4121 }
4123 class UnopNode(ExprNode):
4124 # operator string
4125 # operand ExprNode
4126 #
4127 # Processing during analyse_expressions phase:
4128 #
4129 # analyse_c_operation
4130 # Called when the operand is not a pyobject.
4131 # - Check operand type and coerce if needed.
4132 # - Determine result type and result code fragment.
4133 # - Allocate temporary for result if needed.
4135 subexprs = ['operand']
4136 infix = True
4138 def calculate_constant_result(self):
4139 func = compile_time_unary_operators[self.operator]
4140 self.constant_result = func(self.operand.constant_result)
4142 def compile_time_value(self, denv):
4143 func = compile_time_unary_operators.get(self.operator)
4144 if not func:
4145 error(self.pos,
4146 "Unary '%s' not supported in compile-time expression"
4147 % self.operator)
4148 operand = self.operand.compile_time_value(denv)
4149 try:
4150 return func(operand)
4151 except Exception, e:
4152 self.compile_time_value_error(e)
4154 def infer_type(self, env):
4155 return self.operand.infer_type(env)
4157 def analyse_types(self, env):
4158 self.operand.analyse_types(env)
4159 if self.is_py_operation():
4160 self.coerce_operand_to_pyobject(env)
4161 self.type = py_object_type
4162 self.is_temp = 1
4163 elif self.is_cpp_operation():
4164 self.analyse_cpp_operation(env)
4165 else:
4166 self.analyse_c_operation(env)
4168 def check_const(self):
4169 return self.operand.check_const()
4171 def is_py_operation(self):
4172 return self.operand.type.is_pyobject
4174 def nogil_check(self, env):
4175 if self.is_py_operation():
4176 self.gil_error()
4178 def is_cpp_operation(self):
4179 type = self.operand.type
4180 return type.is_cpp_class or type.is_reference and type.base_type.is_cpp_class
4182 def coerce_operand_to_pyobject(self, env):
4183 self.operand = self.operand.coerce_to_pyobject(env)
4185 def generate_result_code(self, code):
4186 if self.operand.type.is_pyobject:
4187 self.generate_py_operation_code(code)
4189 def generate_py_operation_code(self, code):
4190 function = self.py_operation_function()
4191 code.putln(
4192 "%s = %s(%s); %s" % (
4193 self.result(),
4194 function,
4195 self.operand.py_result(),
4196 code.error_goto_if_null(self.result(), self.pos)))
4197 code.put_gotref(self.py_result())
4199 def type_error(self):
4200 if not self.operand.type.is_error:
4201 error(self.pos, "Invalid operand type for '%s' (%s)" %
4202 (self.operator, self.operand.type))
4203 self.type = PyrexTypes.error_type
4205 def analyse_cpp_operation(self, env):
4206 type = self.operand.type
4207 if type.is_ptr or type.is_reference:
4208 type = type.base_type
4209 entry = env.lookup(type.name)
4210 function = entry.type.scope.lookup("operator%s" % self.operator)
4211 if not function:
4212 error(self.pos, "'%s' operator not defined for %s"
4213 % (self.operator, type))
4214 self.type_error()
4215 return
4216 func_type = function.type
4217 if func_type.is_ptr:
4218 func_type = func_type.base_type
4219 self.type = func_type.return_type
4222 class NotNode(ExprNode):
4223 # 'not' operator
4224 #
4225 # operand ExprNode
4227 type = PyrexTypes.c_bint_type
4229 subexprs = ['operand']
4231 def calculate_constant_result(self):
4232 self.constant_result = not self.operand.constant_result
4234 def compile_time_value(self, denv):
4235 operand = self.operand.compile_time_value(denv)
4236 try:
4237 return not operand
4238 except Exception, e:
4239 self.compile_time_value_error(e)
4241 def infer_type(self, env):
4242 return PyrexTypes.c_bint_type
4244 def analyse_types(self, env):
4245 self.operand.analyse_types(env)
4246 self.operand = self.operand.coerce_to_boolean(env)
4248 def calculate_result_code(self):
4249 return "(!%s)" % self.operand.result()
4251 def generate_result_code(self, code):
4252 pass
4255 class UnaryPlusNode(UnopNode):
4256 # unary '+' operator
4258 operator = '+'
4260 def analyse_c_operation(self, env):
4261 self.type = self.operand.type
4263 def py_operation_function(self):
4264 return "PyNumber_Positive"
4266 def calculate_result_code(self):
4267 if self.is_cpp_operation():
4268 return "(+%s)" % self.operand.result()
4269 else:
4270 return self.operand.result()
4273 class UnaryMinusNode(UnopNode):
4274 # unary '-' operator
4276 operator = '-'
4278 def analyse_c_operation(self, env):
4279 if self.operand.type.is_numeric:
4280 self.type = self.operand.type
4281 else:
4282 self.type_error()
4283 if self.type.is_complex:
4284 self.infix = False
4286 def py_operation_function(self):
4287 return "PyNumber_Negative"
4289 def calculate_result_code(self):
4290 if self.infix:
4291 return "(-%s)" % self.operand.result()
4292 else:
4293 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4295 def get_constant_c_result_code(self):
4296 value = self.operand.get_constant_c_result_code()
4297 if value:
4298 return "(-%s)" % (value)
4300 class TildeNode(UnopNode):
4301 # unary '~' operator
4303 def analyse_c_operation(self, env):
4304 if self.operand.type.is_int:
4305 self.type = self.operand.type
4306 else:
4307 self.type_error()
4309 def py_operation_function(self):
4310 return "PyNumber_Invert"
4312 def calculate_result_code(self):
4313 return "(~%s)" % self.operand.result()
4316 class CUnopNode(UnopNode):
4318 def is_py_operation(self):
4319 return False
4321 class DereferenceNode(CUnopNode):
4322 # unary * operator
4324 operator = '*'
4326 def analyse_c_operation(self, env):
4327 if self.operand.type.is_ptr:
4328 self.type = self.operand.type.base_type
4329 else:
4330 self.type_error()
4332 def calculate_result_code(self):
4333 return "(*%s)" % self.operand.result()
4336 class DecrementIncrementNode(CUnopNode):
4337 # unary ++/-- operator
4339 def analyse_c_operation(self, env):
4340 if self.operand.type.is_ptr or self.operand.type.is_numeric:
4341 self.type = self.operand.type
4342 else:
4343 self.type_error()
4345 def calculate_result_code(self):
4346 if self.is_prefix:
4347 return "(%s%s)" % (self.operator, self.operand.result())
4348 else:
4349 return "(%s%s)" % (self.operand.result(), self.operator)
4351 def inc_dec_constructor(is_prefix, operator):
4352 return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds)
4355 class AmpersandNode(ExprNode):
4356 # The C address-of operator.
4357 #
4358 # operand ExprNode
4360 subexprs = ['operand']
4362 def infer_type(self, env):
4363 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4365 def analyse_types(self, env):
4366 self.operand.analyse_types(env)
4367 argtype = self.operand.type
4368 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4369 self.error("Taking address of non-lvalue")
4370 return
4371 if argtype.is_pyobject:
4372 self.error("Cannot take address of Python variable")
4373 return
4374 self.type = PyrexTypes.c_ptr_type(argtype)
4376 def check_const(self):
4377 return self.operand.check_const_addr()
4379 def error(self, mess):
4380 error(self.pos, mess)
4381 self.type = PyrexTypes.error_type
4382 self.result_code = "<error>"
4384 def calculate_result_code(self):
4385 return "(&%s)" % self.operand.result()
4387 def generate_result_code(self, code):
4388 pass
4391 unop_node_classes = {
4392 "+": UnaryPlusNode,
4393 "-": UnaryMinusNode,
4394 "~": TildeNode,
4395 }
4397 def unop_node(pos, operator, operand):
4398 # Construct unnop node of appropriate class for
4399 # given operator.
4400 if isinstance(operand, IntNode) and operator == '-':
4401 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4402 elif isinstance(operand, UnopNode) and operand.operator == operator:
4403 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4404 return unop_node_classes[operator](pos,
4405 operator = operator,
4406 operand = operand)
4409 class TypecastNode(ExprNode):
4410 # C type cast
4411 #
4412 # operand ExprNode
4413 # base_type CBaseTypeNode
4414 # declarator CDeclaratorNode
4415 #
4416 # If used from a transform, one can if wanted specify the attribute
4417 # "type" directly and leave base_type and declarator to None
4419 subexprs = ['operand']
4420 base_type = declarator = type = None
4422 def type_dependencies(self, env):
4423 return ()
4425 def infer_type(self, env):
4426 if self.type is None:
4427 base_type = self.base_type.analyse(env)
4428 _, self.type = self.declarator.analyse(base_type, env)
4429 return self.type
4431 def analyse_types(self, env):
4432 if self.type is None:
4433 base_type = self.base_type.analyse(env)
4434 _, self.type = self.declarator.analyse(base_type, env)
4435 if self.type.is_cfunction:
4436 error(self.pos,
4437 "Cannot cast to a function type")
4438 self.type = PyrexTypes.error_type
4439 self.operand.analyse_types(env)
4440 to_py = self.type.is_pyobject
4441 from_py = self.operand.type.is_pyobject
4442 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4443 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4444 if to_py and not from_py:
4445 if self.operand.type.can_coerce_to_pyobject(env):
4446 self.result_ctype = py_object_type
4447 self.operand = self.operand.coerce_to_pyobject(env)
4448 else:
4449 if self.operand.type.is_ptr:
4450 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4451 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4452 else:
4453 # Should this be an error?
4454 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4455 self.operand = self.operand.coerce_to_simple(env)
4456 elif from_py and not to_py:
4457 if self.type.create_from_py_utility_code(env):
4458 self.operand = self.operand.coerce_to(self.type, env)
4459 elif self.type.is_ptr:
4460 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4461 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4462 else:
4463 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4464 elif from_py and to_py:
4465 if self.typecheck and self.type.is_extension_type:
4466 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4467 elif self.type.is_complex and self.operand.type.is_complex:
4468 self.operand = self.operand.coerce_to_simple(env)
4470 def nogil_check(self, env):
4471 if self.type and self.type.is_pyobject and self.is_temp:
4472 self.gil_error()
4474 def check_const(self):
4475 return self.operand.check_const()
4477 def calculate_constant_result(self):
4478 # we usually do not know the result of a type cast at code
4479 # generation time
4480 pass
4482 def calculate_result_code(self):
4483 if self.type.is_complex:
4484 operand_result = self.operand.result()
4485 if self.operand.type.is_complex:
4486 real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % operand_result)
4487 imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % operand_result)
4488 else:
4489 real_part = self.type.real_type.cast_code(operand_result)
4490 imag_part = "0"
4491 return "%s(%s, %s)" % (
4492 self.type.from_parts,
4493 real_part,
4494 imag_part)
4495 else:
4496 return self.type.cast_code(self.operand.result())
4498 def get_constant_c_result_code(self):
4499 operand_result = self.operand.get_constant_c_result_code()
4500 if operand_result:
4501 return self.type.cast_code(operand_result)
4503 def result_as(self, type):
4504 if self.type.is_pyobject and not self.is_temp:
4505 # Optimise away some unnecessary casting
4506 return self.operand.result_as(type)
4507 else:
4508 return ExprNode.result_as(self, type)
4510 def generate_result_code(self, code):
4511 if self.is_temp:
4512 code.putln(
4513 "%s = (PyObject *)%s;" % (
4514 self.result(),
4515 self.operand.result()))
4516 code.put_incref(self.result(), self.ctype())
4519 class SizeofNode(ExprNode):
4520 # Abstract base class for sizeof(x) expression nodes.
4522 type = PyrexTypes.c_size_t_type
4524 def check_const(self):
4525 return True
4527 def generate_result_code(self, code):
4528 pass
4531 class SizeofTypeNode(SizeofNode):
4532 # C sizeof function applied to a type
4533 #
4534 # base_type CBaseTypeNode
4535 # declarator CDeclaratorNode
4537 subexprs = []
4538 arg_type = None
4540 def analyse_types(self, env):
4541 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4542 # this could be better handled by more uniformly treating types as runtime-available objects
4543 if 0 and self.base_type.module_path:
4544 path = self.base_type.module_path
4545 obj = env.lookup(path[0])
4546 if obj.as_module is None:
4547 operand = NameNode(pos=self.pos, name=path[0])
4548 for attr in path[1:]:
4549 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4550 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4551 self.operand = operand
4552 self.__class__ = SizeofVarNode
4553 self.analyse_types(env)
4554 return
4555 if self.arg_type is None:
4556 base_type = self.base_type.analyse(env)
4557 _, arg_type = self.declarator.analyse(base_type, env)
4558 self.arg_type = arg_type
4559 self.check_type()
4561 def check_type(self):
4562 arg_type = self.arg_type
4563 if arg_type.is_pyobject and not arg_type.is_extension_type:
4564 error(self.pos, "Cannot take sizeof Python object")
4565 elif arg_type.is_void:
4566 error(self.pos, "Cannot take sizeof void")
4567 elif not arg_type.is_complete():
4568 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4570 def calculate_result_code(self):
4571 if self.arg_type.is_extension_type:
4572 # the size of the pointer is boring
4573 # we want the size of the actual struct
4574 arg_code = self.arg_type.declaration_code("", deref=1)
4575 else:
4576 arg_code = self.arg_type.declaration_code("")
4577 return "(sizeof(%s))" % arg_code
4580 class SizeofVarNode(SizeofNode):
4581 # C sizeof function applied to a variable
4582 #
4583 # operand ExprNode
4585 subexprs = ['operand']
4587 def analyse_types(self, env):
4588 # We may actually be looking at a type rather than a variable...
4589 # If we are, traditional analysis would fail...
4590 operand_as_type = self.operand.analyse_as_type(env)
4591 if operand_as_type:
4592 self.arg_type = operand_as_type
4593 self.__class__ = SizeofTypeNode
4594 self.check_type()
4595 else:
4596 self.operand.analyse_types(env)
4598 def calculate_result_code(self):
4599 return "(sizeof(%s))" % self.operand.result()
4601 def generate_result_code(self, code):
4602 pass
4604 class TypeofNode(ExprNode):
4605 # Compile-time type of an expression, as a string.
4606 #
4607 # operand ExprNode
4608 # literal StringNode # internal
4610 literal = None
4611 type = py_object_type
4613 subexprs = ['literal'] # 'operand' will be ignored after type analysis!
4615 def analyse_types(self, env):
4616 self.operand.analyse_types(env)
4617 self.literal = StringNode(
4618 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4619 self.literal.analyse_types(env)
4620 self.literal = self.literal.coerce_to_pyobject(env)
4622 def generate_evaluation_code(self, code):
4623 self.literal.generate_evaluation_code(code)
4625 def calculate_result_code(self):
4626 return self.literal.calculate_result_code()
4628 #-------------------------------------------------------------------
4629 #
4630 # Binary operator nodes
4631 #
4632 #-------------------------------------------------------------------
4634 def _not_in(x, seq):
4635 return x not in seq
4637 compile_time_binary_operators = {
4638 '<': operator.lt,
4639 '<=': operator.le,
4640 '==': operator.eq,
4641 '!=': operator.ne,
4642 '>=': operator.ge,
4643 '>': operator.gt,
4644 'is': operator.is_,
4645 'is_not': operator.is_not,
4646 '+': operator.add,
4647 '&': operator.and_,
4648 '/': operator.truediv,
4649 '//': operator.floordiv,
4650 '<<': operator.lshift,
4651 '%': operator.mod,
4652 '*': operator.mul,
4653 '|': operator.or_,
4654 '**': operator.pow,
4655 '>>': operator.rshift,
4656 '-': operator.sub,
4657 '^': operator.xor,
4658 'in': operator.contains,
4659 'not_in': _not_in,
4660 }
4662 def get_compile_time_binop(node):
4663 func = compile_time_binary_operators.get(node.operator)
4664 if not func:
4665 error(node.pos,
4666 "Binary '%s' not supported in compile-time expression"
4667 % node.operator)
4668 return func
4670 class BinopNode(ExprNode):
4671 # operator string
4672 # operand1 ExprNode
4673 # operand2 ExprNode
4674 #
4675 # Processing during analyse_expressions phase:
4676 #
4677 # analyse_c_operation
4678 # Called when neither operand is a pyobject.
4679 # - Check operand types and coerce if needed.
4680 # - Determine result type and result code fragment.
4681 # - Allocate temporary for result if needed.
4683 subexprs = ['operand1', 'operand2']
4685 def calculate_constant_result(self):
4686 func = compile_time_binary_operators[self.operator]
4687 self.constant_result = func(
4688 self.operand1.constant_result,
4689 self.operand2.constant_result)
4691 def compile_time_value(self, denv):
4692 func = get_compile_time_binop(self)
4693 operand1 = self.operand1.compile_time_value(denv)
4694 operand2 = self.operand2.compile_time_value(denv)
4695 try:
4696 return func(operand1, operand2)
4697 except Exception, e:
4698 self.compile_time_value_error(e)
4700 def infer_type(self, env):
4701 return self.result_type(self.operand1.infer_type(env),
4702 self.operand2.infer_type(env))
4704 def analyse_types(self, env):
4705 self.operand1.analyse_types(env)
4706 self.operand2.analyse_types(env)
4707 if self.is_py_operation():
4708 self.coerce_operands_to_pyobjects(env)
4709 self.type = py_object_type
4710 self.is_temp = 1
4711 elif self.is_cpp_operation():
4712 self.analyse_cpp_operation(env)
4713 else:
4714 self.analyse_c_operation(env)
4716 def is_py_operation(self):
4717 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4719 def is_py_operation_types(self, type1, type2):
4720 return type1.is_pyobject or type2.is_pyobject
4722 def is_cpp_operation(self):
4723 type1 = self.operand1.type
4724 type2 = self.operand2.type
4725 if type1.is_reference:
4726 type1 = type1.base_type
4727 if type2.is_reference:
4728 type2 = type2.base_type
4729 return (type1.is_cpp_class
4730 or type2.is_cpp_class)
4732 def analyse_cpp_operation(self, env):
4733 type1 = self.operand1.type
4734 type2 = self.operand2.type
4735 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
4736 if not entry:
4737 self.type_error()
4738 return
4739 func_type = entry.type
4740 if func_type.is_ptr:
4741 func_type = func_type.base_type
4742 if len(func_type.args) == 1:
4743 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
4744 else:
4745 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
4746 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
4747 self.type = func_type.return_type
4749 def result_type(self, type1, type2):
4750 if self.is_py_operation_types(type1, type2):
4751 return py_object_type
4752 else:
4753 return self.compute_c_result_type(type1, type2)
4755 def nogil_check(self, env):
4756 if self.is_py_operation():
4757 self.gil_error()
4759 def coerce_operands_to_pyobjects(self, env):
4760 self.operand1 = self.operand1.coerce_to_pyobject(env)
4761 self.operand2 = self.operand2.coerce_to_pyobject(env)
4763 def check_const(self):
4764 return self.operand1.check_const() and self.operand2.check_const()
4766 def generate_result_code(self, code):
4767 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4768 if self.operand1.type.is_pyobject:
4769 function = self.py_operation_function()
4770 if function == "PyNumber_Power":
4771 extra_args = ", Py_None"
4772 else:
4773 extra_args = ""
4774 code.putln(
4775 "%s = %s(%s, %s%s); %s" % (
4776 self.result(),
4777 function,
4778 self.operand1.py_result(),
4779 self.operand2.py_result(),
4780 extra_args,
4781 code.error_goto_if_null(self.result(), self.pos)))
4782 code.put_gotref(self.py_result())
4784 def type_error(self):
4785 if not (self.operand1.type.is_error
4786 or self.operand2.type.is_error):
4787 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4788 (self.operator, self.operand1.type,
4789 self.operand2.type))
4790 self.type = PyrexTypes.error_type
4793 class NumBinopNode(BinopNode):
4794 # Binary operation taking numeric arguments.
4796 infix = True
4798 def analyse_c_operation(self, env):
4799 type1 = self.operand1.type
4800 type2 = self.operand2.type
4801 self.type = self.compute_c_result_type(type1, type2)
4802 if not self.type:
4803 self.type_error()
4804 return
4805 if self.type.is_complex:
4806 self.infix = False
4807 if not self.infix:
4808 self.operand1 = self.operand1.coerce_to(self.type, env)
4809 self.operand2 = self.operand2.coerce_to(self.type, env)
4811 def compute_c_result_type(self, type1, type2):
4812 if self.c_types_okay(type1, type2):
4813 return PyrexTypes.widest_numeric_type(type1, type2)
4814 else:
4815 return None
4817 def get_constant_c_result_code(self):
4818 value1 = self.operand1.get_constant_c_result_code()
4819 value2 = self.operand2.get_constant_c_result_code()
4820 if value1 and value2:
4821 return "(%s %s %s)" % (value1, self.operator, value2)
4822 else:
4823 return None
4825 def c_types_okay(self, type1, type2):
4826 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4827 return (type1.is_numeric or type1.is_enum) \
4828 and (type2.is_numeric or type2.is_enum)
4830 def calculate_result_code(self):
4831 if self.infix:
4832 return "(%s %s %s)" % (
4833 self.operand1.result(),
4834 self.operator,
4835 self.operand2.result())
4836 else:
4837 func = self.type.binary_op(self.operator)
4838 if func is None:
4839 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4840 return "%s(%s, %s)" % (
4841 func,
4842 self.operand1.result(),
4843 self.operand2.result())
4845 def py_operation_function(self):
4846 return self.py_functions[self.operator]
4848 py_functions = {
4849 "|": "PyNumber_Or",
4850 "^": "PyNumber_Xor",
4851 "&": "PyNumber_And",
4852 "<<": "PyNumber_Lshift",
4853 ">>": "PyNumber_Rshift",
4854 "+": "PyNumber_Add",
4855 "-": "PyNumber_Subtract",
4856 "*": "PyNumber_Multiply",
4857 "/": "__Pyx_PyNumber_Divide",
4858 "//": "PyNumber_FloorDivide",
4859 "%": "PyNumber_Remainder",
4860 "**": "PyNumber_Power"
4861 }
4864 class IntBinopNode(NumBinopNode):
4865 # Binary operation taking integer arguments.
4867 def c_types_okay(self, type1, type2):
4868 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4869 return (type1.is_int or type1.is_enum) \
4870 and (type2.is_int or type2.is_enum)
4873 class AddNode(NumBinopNode):
4874 # '+' operator.
4876 def is_py_operation_types(self, type1, type2):
4877 if type1.is_string and type2.is_string:
4878 return 1
4879 else:
4880 return NumBinopNode.is_py_operation_types(self, type1, type2)
4882 def compute_c_result_type(self, type1, type2):
4883 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4884 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4885 return type1
4886 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4887 return type2
4888 else:
4889 return NumBinopNode.compute_c_result_type(
4890 self, type1, type2)
4893 class SubNode(NumBinopNode):
4894 # '-' operator.
4896 def compute_c_result_type(self, type1, type2):
4897 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4898 return type1
4899 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4900 return PyrexTypes.c_int_type
4901 else:
4902 return NumBinopNode.compute_c_result_type(
4903 self, type1, type2)
4906 class MulNode(NumBinopNode):
4907 # '*' operator.
4909 def is_py_operation_types(self, type1, type2):
4910 if (type1.is_string and type2.is_int) \
4911 or (type2.is_string and type1.is_int):
4912 return 1
4913 else:
4914 return NumBinopNode.is_py_operation_types(self, type1, type2)
4917 class DivNode(NumBinopNode):
4918 # '/' or '//' operator.
4920 cdivision = None
4921 truedivision = None # == "unknown" if operator == '/'
4922 ctruedivision = False
4923 cdivision_warnings = False
4924 zerodivision_check = None
4926 def find_compile_time_binary_operator(self, op1, op2):
4927 func = compile_time_binary_operators[self.operator]
4928 if self.operator == '/' and self.truedivision is None:
4929 # => true div for floats, floor div for integers
4930 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4931 func = compile_time_binary_operators['//']
4932 return func
4934 def calculate_constant_result(self):
4935 op1 = self.operand1.constant_result
4936 op2 = self.operand2.constant_result
4937 func = self.find_compile_time_binary_operator(op1, op2)
4938 self.constant_result = func(
4939 self.operand1.constant_result,
4940 self.operand2.constant_result)
4942 def compile_time_value(self, denv):
4943 operand1 = self.operand1.compile_time_value(denv)
4944 operand2 = self.operand2.compile_time_value(denv)
4945 try:
4946 func = self.find_compile_time_binary_operator(
4947 self, operand1, operand2)
4948 return func(operand1, operand2)
4949 except Exception, e:
4950 self.compile_time_value_error(e)
4952 def analyse_types(self, env):
4953 if self.cdivision or env.directives['cdivision']:
4954 self.ctruedivision = False
4955 else:
4956 self.ctruedivision = self.truedivision
4957 NumBinopNode.analyse_types(self, env)
4958 if self.is_cpp_operation():
4959 self.cdivision = True
4960 if not self.type.is_pyobject:
4961 self.zerodivision_check = (
4962 self.cdivision is None and not env.directives['cdivision']
4963 and (self.operand2.constant_result is not_a_constant or
4964 self.operand2.constant_result == 0))
4965 if self.zerodivision_check or env.directives['cdivision_warnings']:
4966 # Need to check ahead of time to warn or raise zero division error
4967 self.operand1 = self.operand1.coerce_to_simple(env)
4968 self.operand2 = self.operand2.coerce_to_simple(env)
4969 if env.nogil:
4970 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4972 def compute_c_result_type(self, type1, type2):
4973 if self.operator == '/' and self.ctruedivision:
4974 if not type1.is_float and not type2.is_float:
4975 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4976 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4977 return widest_type
4978 return NumBinopNode.compute_c_result_type(self, type1, type2)
4980 def zero_division_message(self):
4981 if self.type.is_int:
4982 return "integer division or modulo by zero"
4983 else:
4984 return "float division"
4986 def generate_evaluation_code(self, code):
4987 if not self.type.is_pyobject and not self.type.is_complex:
4988 if self.cdivision is None:
4989 self.cdivision = (code.globalstate.directives['cdivision']
4990 or not self.type.signed
4991 or self.type.is_float)
4992 if not self.cdivision:
4993 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4994 NumBinopNode.generate_evaluation_code(self, code)
4995 self.generate_div_warning_code(code)
4997 def generate_div_warning_code(self, code):
4998 if not self.type.is_pyobject:
4999 if self.zerodivision_check:
5000 if not self.infix:
5001 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
5002 else:
5003 zero_test = "%s == 0" % self.operand2.result()
5004 code.putln("if (unlikely(%s)) {" % zero_test)
5005 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
5006 code.putln(code.error_goto(self.pos))
5007 code.putln("}")
5008 if self.type.is_int and self.type.signed and self.operator != '%':
5009 code.globalstate.use_utility_code(division_overflow_test_code)
5010 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
5011 self.type.declaration_code(''),
5012 self.operand2.result(),
5013 self.operand1.result()))
5014 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
5015 code.putln(code.error_goto(self.pos))
5016 code.putln("}")
5017 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
5018 code.globalstate.use_utility_code(cdivision_warning_utility_code)
5019 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
5020 self.operand1.result(),
5021 self.operand2.result()))
5022 code.putln(code.set_error_info(self.pos));
5023 code.put("if (__Pyx_cdivision_warning()) ")
5024 code.put_goto(code.error_label)
5025 code.putln("}")
5027 def calculate_result_code(self):
5028 if self.type.is_complex:
5029 return NumBinopNode.calculate_result_code(self)
5030 elif self.type.is_float and self.operator == '//':
5031 return "floor(%s / %s)" % (
5032 self.operand1.result(),
5033 self.operand2.result())
5034 elif self.truedivision or self.cdivision:
5035 op1 = self.operand1.result()
5036 op2 = self.operand2.result()
5037 if self.truedivision:
5038 if self.type != self.operand1.type:
5039 op1 = self.type.cast_code(op1)
5040 if self.type != self.operand2.type:
5041 op2 = self.type.cast_code(op2)
5042 return "(%s / %s)" % (op1, op2)
5043 else:
5044 return "__Pyx_div_%s(%s, %s)" % (
5045 self.type.specalization_name(),
5046 self.operand1.result(),
5047 self.operand2.result())
5050 class ModNode(DivNode):
5051 # '%' operator.
5053 def is_py_operation_types(self, type1, type2):
5054 return (type1.is_string
5055 or type2.is_string
5056 or NumBinopNode.is_py_operation_types(self, type1, type2))
5058 def zero_division_message(self):
5059 if self.type.is_int:
5060 return "integer division or modulo by zero"
5061 else:
5062 return "float divmod()"
5064 def generate_evaluation_code(self, code):
5065 if not self.type.is_pyobject:
5066 if self.cdivision is None:
5067 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
5068 if not self.cdivision:
5069 if self.type.is_int:
5070 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
5071 else:
5072 code.globalstate.use_utility_code(
5073 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
5074 NumBinopNode.generate_evaluation_code(self, code)
5075 self.generate_div_warning_code(code)
5077 def calculate_result_code(self):
5078 if self.cdivision:
5079 if self.type.is_float:
5080 return "fmod%s(%s, %s)" % (
5081 self.type.math_h_modifier,
5082 self.operand1.result(),
5083 self.operand2.result())
5084 else:
5085 return "(%s %% %s)" % (
5086 self.operand1.result(),
5087 self.operand2.result())
5088 else:
5089 return "__Pyx_mod_%s(%s, %s)" % (
5090 self.type.specalization_name(),
5091 self.operand1.result(),
5092 self.operand2.result())
5094 class PowNode(NumBinopNode):
5095 # '**' operator.
5097 def analyse_c_operation(self, env):
5098 NumBinopNode.analyse_c_operation(self, env)
5099 if self.type.is_complex:
5100 error(self.pos, "complex powers not yet supported")
5101 self.pow_func = "<error>"
5102 elif self.type.is_float:
5103 self.pow_func = "pow"
5104 else:
5105 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
5106 env.use_utility_code(
5107 int_pow_utility_code.specialize(func_name=self.pow_func,
5108 type=self.type.declaration_code('')))
5110 def calculate_result_code(self):
5111 return "%s(%s, %s)" % (
5112 self.pow_func,
5113 self.operand1.result(),
5114 self.operand2.result())
5117 # Note: This class is temporary "shut down" into an ineffective mode temp
5118 # allocation mode.
5119 #
5120 # More sophisticated temp reuse was going on before,
5121 # one could have a look at adding this again after /all/ classes
5122 # are converted to the new temp scheme. (The temp juggling cannot work
5123 # otherwise).
5124 class BoolBinopNode(ExprNode):
5125 # Short-circuiting boolean operation.
5126 #
5127 # operator string
5128 # operand1 ExprNode
5129 # operand2 ExprNode
5131 subexprs = ['operand1', 'operand2']
5133 def infer_type(self, env):
5134 type1 = self.operand1.infer_type(env)
5135 type2 = self.operand2.infer_type(env)
5136 return PyrexTypes.spanning_type(type1, type2)
5138 def calculate_constant_result(self):
5139 if self.operator == 'and':
5140 self.constant_result = \
5141 self.operand1.constant_result and \
5142 self.operand2.constant_result
5143 else:
5144 self.constant_result = \
5145 self.operand1.constant_result or \
5146 self.operand2.constant_result
5148 def compile_time_value(self, denv):
5149 if self.operator == 'and':
5150 return self.operand1.compile_time_value(denv) \
5151 and self.operand2.compile_time_value(denv)
5152 else:
5153 return self.operand1.compile_time_value(denv) \
5154 or self.operand2.compile_time_value(denv)
5156 def coerce_to_boolean(self, env):
5157 self.operand1 = self.operand1.coerce_to_boolean(env)
5158 self.operand2 = self.operand2.coerce_to_boolean(env)
5159 self.type = PyrexTypes.c_bint_type
5160 return self
5162 def analyse_types(self, env):
5163 self.operand1.analyse_types(env)
5164 self.operand2.analyse_types(env)
5165 self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
5166 self.operand1 = self.operand1.coerce_to(self.type, env)
5167 self.operand2 = self.operand2.coerce_to(self.type, env)
5169 # For what we're about to do, it's vital that
5170 # both operands be temp nodes.
5171 self.operand1 = self.operand1.coerce_to_simple(env)
5172 self.operand2 = self.operand2.coerce_to_simple(env)
5173 self.is_temp = 1
5175 gil_message = "Truth-testing Python object"
5177 def check_const(self):
5178 return self.operand1.check_const() and self.operand2.check_const()
5180 def generate_evaluation_code(self, code):
5181 code.mark_pos(self.pos)
5182 self.operand1.generate_evaluation_code(code)
5183 test_result, uses_temp = self.generate_operand1_test(code)
5184 if self.operator == 'and':
5185 sense = ""
5186 else:
5187 sense = "!"
5188 code.putln(
5189 "if (%s%s) {" % (
5190 sense,
5191 test_result))
5192 if uses_temp:
5193 code.funcstate.release_temp(test_result)
5194 self.operand1.generate_disposal_code(code)
5195 self.operand2.generate_evaluation_code(code)
5196 self.allocate_temp_result(code)
5197 self.operand2.make_owned_reference(code)
5198 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
5199 self.operand2.generate_post_assignment_code(code)
5200 self.operand2.free_temps(code)
5201 code.putln("} else {")
5202 self.operand1.make_owned_reference(code)
5203 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
5204 self.operand1.generate_post_assignment_code(code)
5205 self.operand1.free_temps(code)
5206 code.putln("}")
5208 def generate_operand1_test(self, code):
5209 # Generate code to test the truth of the first operand.
5210 if self.type.is_pyobject:
5211 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
5212 manage_ref=False)
5213 code.putln(
5214 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5215 test_result,
5216 self.operand1.py_result(),
5217 code.error_goto_if_neg(test_result, self.pos)))
5218 else:
5219 test_result = self.operand1.result()
5220 return (test_result, self.type.is_pyobject)
5223 class CondExprNode(ExprNode):
5224 # Short-circuiting conditional expression.
5225 #
5226 # test ExprNode
5227 # true_val ExprNode
5228 # false_val ExprNode
5230 true_val = None
5231 false_val = None
5233 subexprs = ['test', 'true_val', 'false_val']
5235 def type_dependencies(self, env):
5236 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5238 def infer_type(self, env):
5239 return self.compute_result_type(self.true_val.infer_type(env),
5240 self.false_val.infer_type(env))
5242 def calculate_constant_result(self):
5243 if self.test.constant_result:
5244 self.constant_result = self.true_val.constant_result
5245 else:
5246 self.constant_result = self.false_val.constant_result
5248 def analyse_types(self, env):
5249 self.test.analyse_types(env)
5250 self.test = self.test.coerce_to_boolean(env)
5251 self.true_val.analyse_types(env)
5252 self.false_val.analyse_types(env)
5253 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
5254 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
5255 self.true_val = self.true_val.coerce_to(self.type, env)
5256 self.false_val = self.false_val.coerce_to(self.type, env)
5257 self.is_temp = 1
5258 if self.type == PyrexTypes.error_type:
5259 self.type_error()
5261 def compute_result_type(self, type1, type2):
5262 if type1 == type2:
5263 return type1
5264 elif type1.is_numeric and type2.is_numeric:
5265 return PyrexTypes.widest_numeric_type(type1, type2)
5266 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
5267 return type2
5268 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
5269 return type1
5270 elif type1.is_pyobject or type2.is_pyobject:
5271 return py_object_type
5272 elif type1.assignable_from(type2):
5273 return type1
5274 elif type2.assignable_from(type1):
5275 return type2
5276 else:
5277 return PyrexTypes.error_type
5279 def type_error(self):
5280 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5281 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5282 (self.true_val.type, self.false_val.type))
5283 self.type = PyrexTypes.error_type
5285 def check_const(self):
5286 return (self.test.check_const()
5287 and self.true_val.check_const()
5288 and self.false_val.check_const())
5290 def generate_evaluation_code(self, code):
5291 # Because subexprs may not be evaluated we can use a more optimal
5292 # subexpr allocation strategy than the default, so override evaluation_code.
5294 code.mark_pos(self.pos)
5295 self.allocate_temp_result(code)
5296 self.test.generate_evaluation_code(code)
5297 code.putln("if (%s) {" % self.test.result() )
5298 self.eval_and_get(code, self.true_val)
5299 code.putln("} else {")
5300 self.eval_and_get(code, self.false_val)
5301 code.putln("}")
5302 self.test.generate_disposal_code(code)
5303 self.test.free_temps(code)
5305 def eval_and_get(self, code, expr):
5306 expr.generate_evaluation_code(code)
5307 expr.make_owned_reference(code)
5308 code.putln("%s = %s;" % (self.result(), expr.result()))
5309 expr.generate_post_assignment_code(code)
5310 expr.free_temps(code)
5312 richcmp_constants = {
5313 "<" : "Py_LT",
5314 "<=": "Py_LE",
5315 "==": "Py_EQ",
5316 "!=": "Py_NE",
5317 "<>": "Py_NE",
5318 ">" : "Py_GT",
5319 ">=": "Py_GE",
5320 }
5322 class CmpNode(object):
5323 # Mixin class containing code common to PrimaryCmpNodes
5324 # and CascadedCmpNodes.
5326 def infer_types(self, env):
5327 # TODO: Actually implement this (after merging with -unstable).
5328 return py_object_type
5330 def calculate_cascaded_constant_result(self, operand1_result):
5331 func = compile_time_binary_operators[self.operator]
5332 operand2_result = self.operand2.constant_result
5333 result = func(operand1_result, operand2_result)
5334 if result and self.cascade:
5335 result = result and \
5336 self.cascade.cascaded_compile_time_value(operand2_result)
5337 self.constant_result = result
5339 def cascaded_compile_time_value(self, operand1, denv):
5340 func = get_compile_time_binop(self)
5341 operand2 = self.operand2.compile_time_value(denv)
5342 try:
5343 result = func(operand1, operand2)
5344 except Exception, e:
5345 self.compile_time_value_error(e)
5346 result = None
5347 if result:
5348 cascade = self.cascade
5349 if cascade:
5350 # FIXME: I bet this must call cascaded_compile_time_value()
5351 result = result and cascade.compile_time_value(operand2, denv)
5352 return result
5354 def is_cpp_comparison(self):
5355 type1 = self.operand1.type
5356 type2 = self.operand2.type
5357 if type1.is_reference:
5358 type1 = type1.base_type
5359 if type2.is_reference:
5360 type2 = type2.base_type
5361 return type1.is_cpp_class or type2.is_cpp_class
5363 def find_common_int_type(self, env, op, operand1, operand2):
5364 # type1 != type2 and at least one of the types is not a C int
5365 type1 = operand1.type
5366 type2 = operand2.type
5367 type1_can_be_int = False
5368 type2_can_be_int = False
5370 if isinstance(operand1, (StringNode, BytesNode)) \
5371 and operand1.can_coerce_to_char_literal():
5372 type1_can_be_int = True
5373 if isinstance(operand2, (StringNode, BytesNode)) \
5374 and operand2.can_coerce_to_char_literal():
5375 type2_can_be_int = True
5377 if type1.is_int:
5378 if type2_can_be_int:
5379 return type1
5380 elif type2.is_int:
5381 if type1_can_be_int:
5382 return type2
5383 elif type1_can_be_int:
5384 if type2_can_be_int:
5385 return PyrexTypes.c_uchar_type
5387 return None
5389 def find_common_type(self, env, op, operand1, common_type=None):
5390 operand2 = self.operand2
5391 type1 = operand1.type
5392 type2 = operand2.type
5394 new_common_type = None
5396 # catch general errors
5397 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5398 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5399 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5400 new_common_type = error_type
5402 # try to use numeric comparisons where possible
5403 elif type1.is_complex or type2.is_complex:
5404 if op not in ('==', '!='):
5405 error(self.pos, "complex types are unordered")
5406 new_common_type = error_type
5407 if type1.is_pyobject:
5408 new_common_type = type1
5409 elif type2.is_pyobject:
5410 new_common_type = type2
5411 else:
5412 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5413 elif type1.is_numeric and type2.is_numeric:
5414 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5415 elif common_type is None or not common_type.is_pyobject:
5416 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5418 if new_common_type is None:
5419 # fall back to generic type compatibility tests
5420 if type1 == type2:
5421 new_common_type = type1
5422 elif type1.is_pyobject or type2.is_pyobject:
5423 if type2.is_numeric or type2.is_string:
5424 if operand2.check_for_coercion_error(type1):
5425 new_common_type = error_type
5426 else:
5427 new_common_type = py_object_type
5428 elif type1.is_numeric or type1.is_string:
5429 if operand1.check_for_coercion_error(type2):
5430 new_common_type = error_type
5431 else:
5432 new_common_type = py_object_type
5433 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
5434 new_common_type = py_object_type
5435 else:
5436 # one Python type and one non-Python type, not assignable
5437 self.invalid_types_error(operand1, op, operand2)
5438 new_common_type = error_type
5439 elif type1.assignable_from(type2):
5440 new_common_type = type1
5441 elif type2.assignable_from(type1):
5442 new_common_type = type2
5443 else:
5444 # C types that we couldn't handle up to here are an error
5445 self.invalid_types_error(operand1, op, operand2)
5446 new_common_type = error_type
5448 # recursively merge types
5449 if common_type is None or new_common_type.is_error:
5450 common_type = new_common_type
5451 else:
5452 # we could do a lot better by splitting the comparison
5453 # into a non-Python part and a Python part, but this is
5454 # safer for now
5455 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5457 if self.cascade:
5458 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5460 return common_type
5462 def invalid_types_error(self, operand1, op, operand2):
5463 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5464 (op, operand1.type, operand2.type))
5466 def is_python_comparison(self):
5467 return (self.has_python_operands()
5468 or (self.cascade and self.cascade.is_python_comparison())
5469 or self.operator in ('in', 'not_in'))
5471 def coerce_operands_to(self, dst_type, env):
5472 operand2 = self.operand2
5473 if operand2.type != dst_type:
5474 self.operand2 = operand2.coerce_to(dst_type, env)
5475 if self.cascade:
5476 self.cascade.coerce_operands_to(dst_type, env)
5478 def is_python_result(self):
5479 return ((self.has_python_operands() and
5480 self.operator not in ('is', 'is_not', 'in', 'not_in'))
5481 or (self.cascade and self.cascade.is_python_result()))
5483 def generate_operation_code(self, code, result_code,
5484 operand1, op , operand2):
5485 if self.type is PyrexTypes.py_object_type:
5486 coerce_result = "__Pyx_PyBool_FromLong"
5487 else:
5488 coerce_result = ""
5489 if 'not' in op:
5490 negation = "!"
5491 else:
5492 negation = ""
5493 if op == 'in' or op == 'not_in':
5494 code.globalstate.use_utility_code(contians_utility_code)
5495 if self.type is PyrexTypes.py_object_type:
5496 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5497 if op == 'not_in':
5498 negation = "__Pyx_NegateNonNeg"
5499 if operand2.type is dict_type:
5500 code.globalstate.use_utility_code(
5501 raise_none_iter_error_utility_code)
5502 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5503 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5504 code.error_goto(self.pos))
5505 code.putln("} else {")
5506 method = "PyDict_Contains"
5507 else:
5508 method = "PySequence_Contains"
5509 if self.type is PyrexTypes.py_object_type:
5510 error_clause = code.error_goto_if_null
5511 got_ref = "__Pyx_XGOTREF(%s); " % result_code
5512 else:
5513 error_clause = code.error_goto_if_neg
5514 got_ref = ""
5515 code.putln(
5516 "%s = %s(%s(%s(%s, %s))); %s%s" % (
5517 result_code,
5518 coerce_result,
5519 negation,
5520 method,
5521 operand2.py_result(),
5522 operand1.py_result(),
5523 got_ref,
5524 error_clause(result_code, self.pos)))
5525 if operand2.type is dict_type:
5526 code.putln("}")
5528 elif (operand1.type.is_pyobject
5529 and op not in ('is', 'is_not')):
5530 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5531 result_code,
5532 operand1.py_result(),
5533 operand2.py_result(),
5534 richcmp_constants[op],
5535 code.error_goto_if_null(result_code, self.pos)))
5536 code.put_gotref(result_code)
5537 elif operand1.type.is_complex:
5538 if op == "!=":
5539 negation = "!"
5540 else:
5541 negation = ""
5542 code.putln("%s = %s(%s%s(%s, %s));" % (
5543 result_code,
5544 coerce_result,
5545 negation,
5546 operand1.type.unary_op('eq'),
5547 operand1.result(),
5548 operand2.result()))
5549 else:
5550 type1 = operand1.type
5551 type2 = operand2.type
5552 if (type1.is_extension_type or type2.is_extension_type) \
5553 and not type1.same_as(type2):
5554 common_type = py_object_type
5555 elif type1.is_numeric:
5556 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5557 else:
5558 common_type = type1
5559 code1 = operand1.result_as(common_type)
5560 code2 = operand2.result_as(common_type)
5561 code.putln("%s = %s(%s %s %s);" % (
5562 result_code,
5563 coerce_result,
5564 code1,
5565 self.c_operator(op),
5566 code2))
5568 def c_operator(self, op):
5569 if op == 'is':
5570 return "=="
5571 elif op == 'is_not':
5572 return "!="
5573 else:
5574 return op
5576 contians_utility_code = UtilityCode(
5577 proto="""
5578 static CYTHON_INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
5579 static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5580 return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
5581 }
5582 """)
5585 class PrimaryCmpNode(ExprNode, CmpNode):
5586 # Non-cascaded comparison or first comparison of
5587 # a cascaded sequence.
5588 #
5589 # operator string
5590 # operand1 ExprNode
5591 # operand2 ExprNode
5592 # cascade CascadedCmpNode
5594 # We don't use the subexprs mechanism, because
5595 # things here are too complicated for it to handle.
5596 # Instead, we override all the framework methods
5597 # which use it.
5599 child_attrs = ['operand1', 'operand2', 'cascade']
5601 cascade = None
5603 def infer_type(self, env):
5604 # TODO: Actually implement this (after merging with -unstable).
5605 return py_object_type
5607 def type_dependencies(self, env):
5608 return ()
5610 def calculate_constant_result(self):
5611 self.constant_result = self.calculate_cascaded_constant_result(
5612 self.operand1.constant_result)
5614 def compile_time_value(self, denv):
5615 operand1 = self.operand1.compile_time_value(denv)
5616 return self.cascaded_compile_time_value(operand1, denv)
5618 def analyse_types(self, env):
5619 self.operand1.analyse_types(env)
5620 self.operand2.analyse_types(env)
5621 if self.is_cpp_comparison():
5622 self.analyse_cpp_comparison(env)
5623 if self.cascade:
5624 error(self.pos, "Cascading comparison not yet supported for cpp types.")
5625 return
5626 if self.cascade:
5627 self.cascade.analyse_types(env)
5629 if self.operator in ('in', 'not_in'):
5630 common_type = py_object_type
5631 self.is_pycmp = True
5632 else:
5633 common_type = self.find_common_type(env, self.operator, self.operand1)
5634 self.is_pycmp = common_type.is_pyobject
5636 if not common_type.is_error:
5637 if self.operand1.type != common_type:
5638 self.operand1 = self.operand1.coerce_to(common_type, env)
5639 self.coerce_operands_to(common_type, env)
5641 if self.cascade:
5642 self.operand2 = self.operand2.coerce_to_simple(env)
5643 self.cascade.coerce_cascaded_operands_to_temp(env)
5644 if self.is_python_result():
5645 self.type = PyrexTypes.py_object_type
5646 else:
5647 self.type = PyrexTypes.c_bint_type
5648 cdr = self.cascade
5649 while cdr:
5650 cdr.type = self.type
5651 cdr = cdr.cascade
5652 if self.is_pycmp or self.cascade:
5653 self.is_temp = 1
5655 def analyse_cpp_comparison(self, env):
5656 type1 = self.operand1.type
5657 type2 = self.operand2.type
5658 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2])
5659 if entry is None:
5660 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5661 (self.operator, type1, type2))
5662 self.type = PyrexTypes.error_type
5663 self.result_code = "<error>"
5664 return
5665 func_type = entry.type
5666 if func_type.is_ptr:
5667 func_type = func_type.base_type
5668 if len(func_type.args) == 1:
5669 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env)
5670 else:
5671 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
5672 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
5673 self.type = func_type.return_type
5675 def has_python_operands(self):
5676 return (self.operand1.type.is_pyobject
5677 or self.operand2.type.is_pyobject)
5679 def check_const(self):
5680 if self.cascade:
5681 self.not_const()
5682 return False
5683 else:
5684 return self.operand1.check_const() and self.operand2.check_const()
5686 def calculate_result_code(self):
5687 if self.operand1.type.is_complex:
5688 if self.operator == "!=":
5689 negation = "!"
5690 else:
5691 negation = ""
5692 return "(%s%s(%s, %s))" % (
5693 negation,
5694 self.operand1.type.binary_op('=='),
5695 self.operand1.result(),
5696 self.operand2.result())
5697 else:
5698 return "(%s %s %s)" % (
5699 self.operand1.result(),
5700 self.c_operator(self.operator),
5701 self.operand2.result())
5703 def generate_evaluation_code(self, code):
5704 self.operand1.generate_evaluation_code(code)
5705 self.operand2.generate_evaluation_code(code)
5706 if self.is_temp:
5707 self.allocate_temp_result(code)
5708 self.generate_operation_code(code, self.result(),
5709 self.operand1, self.operator, self.operand2)
5710 if self.cascade:
5711 self.cascade.generate_evaluation_code(code,
5712 self.result(), self.operand2)
5713 self.operand1.generate_disposal_code(code)
5714 self.operand1.free_temps(code)
5715 self.operand2.generate_disposal_code(code)
5716 self.operand2.free_temps(code)
5718 def generate_subexpr_disposal_code(self, code):
5719 # If this is called, it is a non-cascaded cmp,
5720 # so only need to dispose of the two main operands.
5721 self.operand1.generate_disposal_code(code)
5722 self.operand2.generate_disposal_code(code)
5724 def free_subexpr_temps(self, code):
5725 # If this is called, it is a non-cascaded cmp,
5726 # so only need to dispose of the two main operands.
5727 self.operand1.free_temps(code)
5728 self.operand2.free_temps(code)
5730 def annotate(self, code):
5731 self.operand1.annotate(code)
5732 self.operand2.annotate(code)
5733 if self.cascade:
5734 self.cascade.annotate(code)
5737 class CascadedCmpNode(Node, CmpNode):
5738 # A CascadedCmpNode is not a complete expression node. It
5739 # hangs off the side of another comparison node, shares
5740 # its left operand with that node, and shares its result
5741 # with the PrimaryCmpNode at the head of the chain.
5742 #
5743 # operator string
5744 # operand2 ExprNode
5745 # cascade CascadedCmpNode
5747 child_attrs = ['operand2', 'cascade']
5749 cascade = None
5750 constant_result = constant_value_not_set # FIXME: where to calculate this?
5752 def infer_type(self, env):
5753 # TODO: Actually implement this (after merging with -unstable).
5754 return py_object_type
5756 def type_dependencies(self, env):
5757 return ()
5759 def analyse_types(self, env):
5760 self.operand2.analyse_types(env)
5761 if self.cascade:
5762 self.cascade.analyse_types(env)
5764 def has_python_operands(self):
5765 return self.operand2.type.is_pyobject
5767 def coerce_operands_to_pyobjects(self, env):
5768 self.operand2 = self.operand2.coerce_to_pyobject(env)
5769 if self.cascade:
5770 self.cascade.coerce_operands_to_pyobjects(env)
5772 def coerce_cascaded_operands_to_temp(self, env):
5773 if self.cascade:
5774 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5775 self.operand2 = self.operand2.coerce_to_simple(env)
5776 self.cascade.coerce_cascaded_operands_to_temp(env)
5778 def generate_evaluation_code(self, code, result, operand1):
5779 if self.type.is_pyobject:
5780 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5781 code.put_decref(result, self.type)
5782 else:
5783 code.putln("if (%s) {" % result)
5784 self.operand2.generate_evaluation_code(code)
5785 self.generate_operation_code(code, result,
5786 operand1, self.operator, self.operand2)
5787 if self.cascade:
5788 self.cascade.generate_evaluation_code(
5789 code, result, self.operand2)
5790 # Cascaded cmp result is always temp
5791 self.operand2.generate_disposal_code(code)
5792 self.operand2.free_temps(code)
5793 code.putln("}")
5795 def annotate(self, code):
5796 self.operand2.annotate(code)
5797 if self.cascade:
5798 self.cascade.annotate(code)
5801 binop_node_classes = {
5802 "or": BoolBinopNode,
5803 "and": BoolBinopNode,
5804 "|": IntBinopNode,
5805 "^": IntBinopNode,
5806 "&": IntBinopNode,
5807 "<<": IntBinopNode,
5808 ">>": IntBinopNode,
5809 "+": AddNode,
5810 "-": SubNode,
5811 "*": MulNode,
5812 "/": DivNode,
5813 "//": DivNode,
5814 "%": ModNode,
5815 "**": PowNode
5816 }
5818 def binop_node(pos, operator, operand1, operand2):
5819 # Construct binop node of appropriate class for
5820 # given operator.
5821 return binop_node_classes[operator](pos,
5822 operator = operator,
5823 operand1 = operand1,
5824 operand2 = operand2)
5826 #-------------------------------------------------------------------
5827 #
5828 # Coercion nodes
5829 #
5830 # Coercion nodes are special in that they are created during
5831 # the analyse_types phase of parse tree processing.
5832 # Their __init__ methods consequently incorporate some aspects
5833 # of that phase.
5834 #
5835 #-------------------------------------------------------------------
5837 class CoercionNode(ExprNode):
5838 # Abstract base class for coercion nodes.
5839 #
5840 # arg ExprNode node being coerced
5842 subexprs = ['arg']
5843 constant_result = not_a_constant
5845 def __init__(self, arg):
5846 self.pos = arg.pos
5847 self.arg = arg
5848 if debug_coercion:
5849 print("%s Coercing %s" % (self, self.arg))
5851 def calculate_constant_result(self):
5852 # constant folding can break type coercion, so this is disabled
5853 pass
5855 def annotate(self, code):
5856 self.arg.annotate(code)
5857 if self.arg.type != self.type:
5858 file, line, col = self.pos
5859 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5862 class CastNode(CoercionNode):
5863 # Wrap a node in a C type cast.
5865 def __init__(self, arg, new_type):
5866 CoercionNode.__init__(self, arg)
5867 self.type = new_type
5869 def calculate_result_code(self):
5870 return self.arg.result_as(self.type)
5872 def generate_result_code(self, code):
5873 self.arg.generate_result_code(code)
5876 class PyTypeTestNode(CoercionNode):
5877 # This node is used to check that a generic Python
5878 # object is an instance of a particular extension type.
5879 # This node borrows the result of its argument node.
5881 def __init__(self, arg, dst_type, env, notnone=False):
5882 # The arg is know to be a Python object, and
5883 # the dst_type is known to be an extension type.
5884 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5885 CoercionNode.__init__(self, arg)
5886 self.type = dst_type
5887 self.result_ctype = arg.ctype()
5888 self.notnone = notnone
5890 nogil_check = Node.gil_error
5891 gil_message = "Python type test"
5893 def analyse_types(self, env):
5894 pass
5896 def result_in_temp(self):
5897 return self.arg.result_in_temp()
5899 def is_ephemeral(self):
5900 return self.arg.is_ephemeral()
5902 def calculate_constant_result(self):
5903 # FIXME
5904 pass
5906 def calculate_result_code(self):
5907 return self.arg.result()
5909 def generate_result_code(self, code):
5910 if self.type.typeobj_is_available():
5911 if not self.type.is_builtin_type:
5912 code.globalstate.use_utility_code(type_test_utility_code)
5913 code.putln(
5914 "if (!(%s)) %s" % (
5915 self.type.type_test_code(self.arg.py_result(), self.notnone),
5916 code.error_goto(self.pos)))
5917 else:
5918 error(self.pos, "Cannot test type of extern C class "
5919 "without type object name specification")
5921 def generate_post_assignment_code(self, code):
5922 self.arg.generate_post_assignment_code(code)
5924 def free_temps(self, code):
5925 self.arg.free_temps(code)
5928 class NoneCheckNode(CoercionNode):
5929 # This node is used to check that a Python object is not None and
5930 # raises an appropriate exception (as specified by the creating
5931 # transform).
5933 def __init__(self, arg, exception_type_cname, exception_message):
5934 CoercionNode.__init__(self, arg)
5935 self.type = arg.type
5936 self.result_ctype = arg.ctype()
5937 self.exception_type_cname = exception_type_cname
5938 self.exception_message = exception_message
5940 def analyse_types(self, env):
5941 pass
5943 def result_in_temp(self):
5944 return self.arg.result_in_temp()
5946 def calculate_result_code(self):
5947 return self.arg.result()
5949 def generate_result_code(self, code):
5950 code.putln(
5951 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5952 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5953 self.exception_type_cname,
5954 StringEncoding.escape_byte_string(
5955 self.exception_message.encode('UTF-8')),
5956 code.error_goto(self.pos)))
5957 code.putln("}")
5959 def generate_post_assignment_code(self, code):
5960 self.arg.generate_post_assignment_code(code)
5962 def free_temps(self, code):
5963 self.arg.free_temps(code)
5966 class CoerceToPyTypeNode(CoercionNode):
5967 # This node is used to convert a C data type
5968 # to a Python object.
5970 type = py_object_type
5971 is_temp = 1
5973 def __init__(self, arg, env, type=py_object_type):
5974 CoercionNode.__init__(self, arg)
5975 if not arg.type.create_to_py_utility_code(env):
5976 error(arg.pos,
5977 "Cannot convert '%s' to Python object" % arg.type)
5978 if type is not py_object_type:
5979 self.type = py_object_type
5980 elif arg.type.is_string:
5981 self.type = Builtin.bytes_type
5983 gil_message = "Converting to Python object"
5985 def coerce_to_boolean(self, env):
5986 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5988 def coerce_to_integer(self, env):
5989 # If not already some C integer type, coerce to longint.
5990 if self.arg.type.is_int:
5991 return self.arg
5992 else:
5993 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5995 def analyse_types(self, env):
5996 # The arg is always already analysed
5997 pass
5999 def generate_result_code(self, code):
6000 function = self.arg.type.to_py_function
6001 code.putln('%s = %s(%s); %s' % (
6002 self.result(),
6003 function,
6004 self.arg.result(),
6005 code.error_goto_if_null(self.result(), self.pos)))
6006 code.put_gotref(self.py_result())
6009 class CoerceFromPyTypeNode(CoercionNode):
6010 # This node is used to convert a Python object
6011 # to a C data type.
6013 def __init__(self, result_type, arg, env):
6014 CoercionNode.__init__(self, arg)
6015 self.type = result_type
6016 self.is_temp = 1
6017 if not result_type.create_from_py_utility_code(env):
6018 error(arg.pos,
6019 "Cannot convert Python object to '%s'" % result_type)
6020 if self.type.is_string and self.arg.is_ephemeral():
6021 error(arg.pos,
6022 "Obtaining char * from temporary Python value")
6024 def analyse_types(self, env):
6025 # The arg is always already analysed
6026 pass
6028 def generate_result_code(self, code):
6029 function = self.type.from_py_function
6030 operand = self.arg.py_result()
6031 rhs = "%s(%s)" % (function, operand)
6032 if self.type.is_enum:
6033 rhs = typecast(self.type, c_long_type, rhs)
6034 code.putln('%s = %s; %s' % (
6035 self.result(),
6036 rhs,
6037 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
6038 if self.type.is_pyobject:
6039 code.put_gotref(self.py_result())
6042 class CoerceToBooleanNode(CoercionNode):
6043 # This node is used when a result needs to be used
6044 # in a boolean context.
6046 type = PyrexTypes.c_bint_type
6048 def __init__(self, arg, env):
6049 CoercionNode.__init__(self, arg)
6050 if arg.type.is_pyobject:
6051 self.is_temp = 1
6053 def nogil_check(self, env):
6054 if self.arg.type.is_pyobject:
6055 self.gil_error()
6057 gil_message = "Truth-testing Python object"
6059 def check_const(self):
6060 if self.is_temp:
6061 self.not_const()
6062 return False
6063 return self.arg.check_const()
6065 def calculate_result_code(self):
6066 return "(%s != 0)" % self.arg.result()
6068 def generate_result_code(self, code):
6069 if self.arg.type.is_pyobject:
6070 code.putln(
6071 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
6072 self.result(),
6073 self.arg.py_result(),
6074 code.error_goto_if_neg(self.result(), self.pos)))
6076 class CoerceToComplexNode(CoercionNode):
6078 def __init__(self, arg, dst_type, env):
6079 if arg.type.is_complex:
6080 arg = arg.coerce_to_simple(env)
6081 self.type = dst_type
6082 CoercionNode.__init__(self, arg)
6083 dst_type.create_declaration_utility_code(env)
6085 def calculate_result_code(self):
6086 if self.arg.type.is_complex:
6087 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
6088 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
6089 else:
6090 real_part = self.arg.result()
6091 imag_part = "0"
6092 return "%s(%s, %s)" % (
6093 self.type.from_parts,
6094 real_part,
6095 imag_part)
6097 def generate_result_code(self, code):
6098 pass
6100 class CoerceToTempNode(CoercionNode):
6101 # This node is used to force the result of another node
6102 # to be stored in a temporary. It is only used if the
6103 # argument node's result is not already in a temporary.
6105 def __init__(self, arg, env):
6106 CoercionNode.__init__(self, arg)
6107 self.type = self.arg.type
6108 self.is_temp = 1
6109 if self.type.is_pyobject:
6110 self.result_ctype = py_object_type
6112 gil_message = "Creating temporary Python reference"
6114 def analyse_types(self, env):
6115 # The arg is always already analysed
6116 pass
6118 def coerce_to_boolean(self, env):
6119 self.arg = self.arg.coerce_to_boolean(env)
6120 self.type = self.arg.type
6121 self.result_ctype = self.type
6122 return self
6124 def generate_result_code(self, code):
6125 #self.arg.generate_evaluation_code(code) # Already done
6126 # by generic generate_subexpr_evaluation_code!
6127 code.putln("%s = %s;" % (
6128 self.result(), self.arg.result_as(self.ctype())))
6129 if self.type.is_pyobject and self.use_managed_ref:
6130 code.put_incref(self.result(), self.ctype())
6133 class CloneNode(CoercionNode):
6134 # This node is employed when the result of another node needs
6135 # to be used multiple times. The argument node's result must
6136 # be in a temporary. This node "borrows" the result from the
6137 # argument node, and does not generate any evaluation or
6138 # disposal code for it. The original owner of the argument
6139 # node is responsible for doing those things.
6141 subexprs = [] # Arg is not considered a subexpr
6142 nogil_check = None
6144 def __init__(self, arg):
6145 CoercionNode.__init__(self, arg)
6146 if hasattr(arg, 'type'):
6147 self.type = arg.type
6148 self.result_ctype = arg.result_ctype
6149 if hasattr(arg, 'entry'):
6150 self.entry = arg.entry
6152 def result(self):
6153 return self.arg.result()
6155 def type_dependencies(self, env):
6156 return self.arg.type_dependencies(env)
6158 def infer_type(self, env):
6159 return self.arg.infer_type(env)
6161 def analyse_types(self, env):
6162 self.type = self.arg.type
6163 self.result_ctype = self.arg.result_ctype
6164 self.is_temp = 1
6165 if hasattr(self.arg, 'entry'):
6166 self.entry = self.arg.entry
6168 def generate_evaluation_code(self, code):
6169 pass
6171 def generate_result_code(self, code):
6172 pass
6174 def generate_disposal_code(self, code):
6175 pass
6177 def free_temps(self, code):
6178 pass
6181 class ModuleRefNode(ExprNode):
6182 # Simple returns the module object
6184 type = py_object_type
6185 is_temp = False
6186 subexprs = []
6188 def analyse_types(self, env):
6189 pass
6191 def calculate_result_code(self):
6192 return Naming.module_cname
6194 def generate_result_code(self, code):
6195 pass
6197 class DocstringRefNode(ExprNode):
6198 # Extracts the docstring of the body element
6200 subexprs = ['body']
6201 type = py_object_type
6202 is_temp = True
6204 def __init__(self, pos, body):
6205 ExprNode.__init__(self, pos)
6206 assert body.type.is_pyobject
6207 self.body = body
6209 def analyse_types(self, env):
6210 pass
6212 def generate_result_code(self, code):
6213 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
6214 (self.result(), self.body.result()))
6215 code.put_gotref(self.result())
6219 #------------------------------------------------------------------------------------
6220 #
6221 # Runtime support code
6222 #
6223 #------------------------------------------------------------------------------------
6225 get_name_interned_utility_code = UtilityCode(
6226 proto = """
6227 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
6228 """,
6229 impl = """
6230 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
6231 PyObject *result;
6232 result = PyObject_GetAttr(dict, name);
6233 if (!result)
6234 PyErr_SetObject(PyExc_NameError, name);
6235 return result;
6236 }
6237 """)
6239 #------------------------------------------------------------------------------------
6241 import_utility_code = UtilityCode(
6242 proto = """
6243 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
6244 """,
6245 impl = """
6246 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
6247 PyObject *__import__ = 0;
6248 PyObject *empty_list = 0;
6249 PyObject *module = 0;
6250 PyObject *global_dict = 0;
6251 PyObject *empty_dict = 0;
6252 PyObject *list;
6253 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
6254 if (!__import__)
6255 goto bad;
6256 if (from_list)
6257 list = from_list;
6258 else {
6259 empty_list = PyList_New(0);
6260 if (!empty_list)
6261 goto bad;
6262 list = empty_list;
6263 }
6264 global_dict = PyModule_GetDict(%(GLOBALS)s);
6265 if (!global_dict)
6266 goto bad;
6267 empty_dict = PyDict_New();
6268 if (!empty_dict)
6269 goto bad;
6270 module = PyObject_CallFunctionObjArgs(__import__,
6271 name, global_dict, empty_dict, list, NULL);
6272 bad:
6273 Py_XDECREF(empty_list);
6274 Py_XDECREF(__import__);
6275 Py_XDECREF(empty_dict);
6276 return module;
6277 }
6278 """ % {
6279 "BUILTINS": Naming.builtins_cname,
6280 "GLOBALS": Naming.module_cname,
6281 })
6283 #------------------------------------------------------------------------------------
6285 get_exception_utility_code = UtilityCode(
6286 proto = """
6287 static PyObject *__Pyx_GetExcValue(void); /*proto*/
6288 """,
6289 impl = """
6290 static PyObject *__Pyx_GetExcValue(void) {
6291 PyObject *type = 0, *value = 0, *tb = 0;
6292 PyObject *tmp_type, *tmp_value, *tmp_tb;
6293 PyObject *result = 0;
6294 PyThreadState *tstate = PyThreadState_Get();
6295 PyErr_Fetch(&type, &value, &tb);
6296 PyErr_NormalizeException(&type, &value, &tb);
6297 if (PyErr_Occurred())
6298 goto bad;
6299 if (!value) {
6300 value = Py_None;
6301 Py_INCREF(value);
6302 }
6303 tmp_type = tstate->exc_type;
6304 tmp_value = tstate->exc_value;
6305 tmp_tb = tstate->exc_traceback;
6306 tstate->exc_type = type;
6307 tstate->exc_value = value;
6308 tstate->exc_traceback = tb;
6309 /* Make sure tstate is in a consistent state when we XDECREF
6310 these objects (XDECREF may run arbitrary code). */
6311 Py_XDECREF(tmp_type);
6312 Py_XDECREF(tmp_value);
6313 Py_XDECREF(tmp_tb);
6314 result = value;
6315 Py_XINCREF(result);
6316 type = 0;
6317 value = 0;
6318 tb = 0;
6319 bad:
6320 Py_XDECREF(type);
6321 Py_XDECREF(value);
6322 Py_XDECREF(tb);
6323 return result;
6324 }
6325 """)
6327 #------------------------------------------------------------------------------------
6329 type_test_utility_code = UtilityCode(
6330 proto = """
6331 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6332 """,
6333 impl = """
6334 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6335 if (unlikely(!type)) {
6336 PyErr_Format(PyExc_SystemError, "Missing type object");
6337 return 0;
6338 }
6339 if (likely(PyObject_TypeCheck(obj, type)))
6340 return 1;
6341 PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
6342 Py_TYPE(obj)->tp_name, type->tp_name);
6343 return 0;
6344 }
6345 """)
6347 #------------------------------------------------------------------------------------
6349 create_class_utility_code = UtilityCode(
6350 proto = """
6351 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6352 """,
6353 impl = """
6354 static PyObject *__Pyx_CreateClass(
6355 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6356 {
6357 PyObject *py_modname;
6358 PyObject *result = 0;
6360 #if PY_MAJOR_VERSION < 3
6361 py_modname = PyString_FromString(modname);
6362 #else
6363 py_modname = PyUnicode_FromString(modname);
6364 #endif
6365 if (!py_modname)
6366 goto bad;
6367 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6368 goto bad;
6369 #if PY_MAJOR_VERSION < 3
6370 result = PyClass_New(bases, dict, name);
6371 #else
6372 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6373 #endif
6374 bad:
6375 Py_XDECREF(py_modname);
6376 return result;
6377 }
6378 """)
6380 #------------------------------------------------------------------------------------
6382 cpp_exception_utility_code = UtilityCode(
6383 proto = """
6384 #ifndef __Pyx_CppExn2PyErr
6385 static void __Pyx_CppExn2PyErr() {
6386 try {
6387 if (PyErr_Occurred())
6388 ; // let the latest Python exn pass through and ignore the current one
6389 else
6390 throw;
6391 } catch (const std::out_of_range& exn) {
6392 // catch out_of_range explicitly so the proper Python exn may be raised
6393 PyErr_SetString(PyExc_IndexError, exn.what());
6394 } catch (const std::exception& exn) {
6395 PyErr_SetString(PyExc_RuntimeError, exn.what());
6396 }
6397 catch (...)
6398 {
6399 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6400 }
6401 }
6402 #endif
6403 """,
6404 impl = ""
6405 )
6407 #------------------------------------------------------------------------------------
6409 # If the is_unsigned flag is set, we need to do some extra work to make
6410 # sure the index doesn't become negative.
6412 getitem_int_utility_code = UtilityCode(
6413 proto = """
6415 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6416 PyObject *r;
6417 if (!j) return NULL;
6418 r = PyObject_GetItem(o, j);
6419 Py_DECREF(j);
6420 return r;
6421 }
6423 """ + ''.join([
6424 """
6425 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6426 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6427 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6429 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6430 if (likely(o != Py_None)) {
6431 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6432 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6433 Py_INCREF(r);
6434 return r;
6435 }
6436 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6437 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6438 Py_INCREF(r);
6439 return r;
6440 }
6441 }
6442 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6443 }
6444 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6445 ]) + """
6447 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6448 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6449 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6451 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6452 PyObject *r;
6453 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6454 r = PyList_GET_ITEM(o, i);
6455 Py_INCREF(r);
6456 }
6457 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6458 r = PyTuple_GET_ITEM(o, i);
6459 Py_INCREF(r);
6460 }
6461 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6462 r = PySequence_GetItem(o, i);
6463 }
6464 else {
6465 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6466 }
6467 return r;
6468 }
6469 """,
6470 impl = """
6471 """)
6475 #------------------------------------------------------------------------------------
6477 setitem_int_utility_code = UtilityCode(
6478 proto = """
6479 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6480 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6481 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6483 static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6484 int r;
6485 if (!j) return -1;
6486 r = PyObject_SetItem(o, j, v);
6487 Py_DECREF(j);
6488 return r;
6489 }
6491 static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6492 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6493 Py_INCREF(v);
6494 Py_DECREF(PyList_GET_ITEM(o, i));
6495 PyList_SET_ITEM(o, i, v);
6496 return 1;
6497 }
6498 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6499 return PySequence_SetItem(o, i, v);
6500 else {
6501 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6502 return __Pyx_SetItemInt_Generic(o, j, v);
6503 }
6504 }
6505 """,
6506 impl = """
6507 """)
6509 #------------------------------------------------------------------------------------
6511 delitem_int_utility_code = UtilityCode(
6512 proto = """
6513 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6514 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6515 __Pyx_DelItem_Generic(o, to_py_func(i)))
6517 static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6518 int r;
6519 if (!j) return -1;
6520 r = PyObject_DelItem(o, j);
6521 Py_DECREF(j);
6522 return r;
6523 }
6525 static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6526 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6527 return PySequence_DelItem(o, i);
6528 else {
6529 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6530 return __Pyx_DelItem_Generic(o, j);
6531 }
6532 }
6533 """,
6534 impl = """
6535 """)
6537 #------------------------------------------------------------------------------------
6539 raise_noneattr_error_utility_code = UtilityCode(
6540 proto = """
6541 static CYTHON_INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6542 """,
6543 impl = '''
6544 static CYTHON_INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6545 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6546 }
6547 ''')
6549 raise_noneindex_error_utility_code = UtilityCode(
6550 proto = """
6551 static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void);
6552 """,
6553 impl = '''
6554 static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void) {
6555 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6556 }
6557 ''')
6559 raise_none_iter_error_utility_code = UtilityCode(
6560 proto = """
6561 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
6562 """,
6563 impl = '''
6564 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6565 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6566 }
6567 ''')
6569 raise_too_many_values_to_unpack = UtilityCode(
6570 proto = """
6571 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void);
6572 """,
6573 impl = '''
6574 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(void) {
6575 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6576 }
6577 ''')
6579 raise_need_more_values_to_unpack = UtilityCode(
6580 proto = """
6581 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6582 """,
6583 impl = '''
6584 static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6585 PyErr_Format(PyExc_ValueError,
6586 #if PY_VERSION_HEX < 0x02050000
6587 "need more than %d value%s to unpack", (int)index,
6588 #else
6589 "need more than %zd value%s to unpack", index,
6590 #endif
6591 (index == 1) ? "" : "s");
6592 }
6593 ''')
6595 #------------------------------------------------------------------------------------
6597 tuple_unpacking_error_code = UtilityCode(
6598 proto = """
6599 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6600 """,
6601 impl = """
6602 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6603 if (t == Py_None) {
6604 __Pyx_RaiseNoneNotIterableError();
6605 } else if (PyTuple_GET_SIZE(t) < index) {
6606 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6607 } else {
6608 __Pyx_RaiseTooManyValuesError();
6609 }
6610 }
6611 """,
6612 requires = [raise_none_iter_error_utility_code,
6613 raise_need_more_values_to_unpack,
6614 raise_too_many_values_to_unpack]
6615 )
6617 unpacking_utility_code = UtilityCode(
6618 proto = """
6619 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6620 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6621 """,
6622 impl = """
6623 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6624 PyObject *item;
6625 if (!(item = PyIter_Next(iter))) {
6626 if (!PyErr_Occurred()) {
6627 __Pyx_RaiseNeedMoreValuesError(index);
6628 }
6629 }
6630 return item;
6631 }
6633 static int __Pyx_EndUnpack(PyObject *iter) {
6634 PyObject *item;
6635 if ((item = PyIter_Next(iter))) {
6636 Py_DECREF(item);
6637 __Pyx_RaiseTooManyValuesError();
6638 return -1;
6639 }
6640 else if (!PyErr_Occurred())
6641 return 0;
6642 else
6643 return -1;
6644 }
6645 """,
6646 requires = [raise_need_more_values_to_unpack,
6647 raise_too_many_values_to_unpack]
6648 )
6650 #------------------------------------------------------------------------------------
6652 # CPython supports calling functions with non-dict kwargs by
6653 # converting them to a dict first
6655 kwargs_call_utility_code = UtilityCode(
6656 proto = """
6657 static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject*, PyObject*, PyObject*); /*proto*/
6658 """,
6659 impl = """
6660 static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject *callable, PyObject *args, PyObject *kwargs) {
6661 PyObject* result;
6662 if (likely(PyDict_Check(kwargs))) {
6663 return PyEval_CallObjectWithKeywords(callable, args, kwargs);
6664 } else {
6665 PyObject* real_dict;
6666 real_dict = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, kwargs, NULL);
6667 if (unlikely(!real_dict))
6668 return NULL;
6669 result = PyEval_CallObjectWithKeywords(callable, args, real_dict);
6670 Py_DECREF(real_dict);
6671 return result; /* may be NULL */
6672 }
6673 }
6674 """,
6675 )
6678 #------------------------------------------------------------------------------------
6680 int_pow_utility_code = UtilityCode(
6681 proto="""
6682 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6683 """,
6684 impl="""
6685 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6686 %(type)s t = b;
6687 switch (e) {
6688 case 3:
6689 t *= b;
6690 case 2:
6691 t *= b;
6692 case 1:
6693 return t;
6694 case 0:
6695 return 1;
6696 }
6697 if (unlikely(e<0)) return 0;
6698 t = 1;
6699 while (likely(e)) {
6700 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6701 b *= b;
6702 e >>= 1;
6703 }
6704 return t;
6705 }
6706 """)
6708 # ------------------------------ Division ------------------------------------
6710 div_int_utility_code = UtilityCode(
6711 proto="""
6712 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6713 """,
6714 impl="""
6715 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6716 %(type)s q = a / b;
6717 %(type)s r = a - q*b;
6718 q -= ((r != 0) & ((r ^ b) < 0));
6719 return q;
6720 }
6721 """)
6723 mod_int_utility_code = UtilityCode(
6724 proto="""
6725 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6726 """,
6727 impl="""
6728 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6729 %(type)s r = a %% b;
6730 r += ((r != 0) & ((r ^ b) < 0)) * b;
6731 return r;
6732 }
6733 """)
6735 mod_float_utility_code = UtilityCode(
6736 proto="""
6737 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6738 """,
6739 impl="""
6740 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6741 %(type)s r = fmod%(math_h_modifier)s(a, b);
6742 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6743 return r;
6744 }
6745 """)
6747 cdivision_warning_utility_code = UtilityCode(
6748 proto="""
6749 static int __Pyx_cdivision_warning(void); /* proto */
6750 """,
6751 impl="""
6752 static int __Pyx_cdivision_warning(void) {
6753 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6754 "division with oppositely signed operands, C and Python semantics differ",
6755 %(FILENAME)s,
6756 %(LINENO)s,
6757 __Pyx_MODULE_NAME,
6758 NULL);
6759 }
6760 """ % {
6761 'FILENAME': Naming.filename_cname,
6762 'LINENO': Naming.lineno_cname,
6763 })
6765 # from intobject.c
6766 division_overflow_test_code = UtilityCode(
6767 proto="""
6768 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6769 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6770 """)
