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