Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 2507:8d8cc4c9b91b

fix bug 412: str char comparison, refactoring to move comparison coercions closer in the code
author Stefan Behnel <scoder@users.berlios.de>
date Sat Oct 17 22:34:28 2009 +0200 (2 years ago)
parents 961ad8050e5f
children b0bb4d405755
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()
65 result_ctype = None
66 type = None
67 temp_code = None
68 old_temp = None # error checker for multiple frees etc.
70 # The Analyse Expressions phase for expressions is split
71 # into two sub-phases:
72 #
73 # Analyse Types
74 # Determines the result type of the expression based
75 # on the types of its sub-expressions, and inserts
76 # coercion nodes into the expression tree where needed.
77 # Marks nodes which will need to have temporary variables
78 # allocated.
79 #
80 # Allocate Temps
81 # Allocates temporary variables where needed, and fills
82 # in the result_code field of each node.
83 #
84 # ExprNode provides some convenience routines which
85 # perform both of the above phases. These should only
86 # be called from statement nodes, and only when no
87 # coercion nodes need to be added around the expression
88 # being analysed. In that case, the above two phases
89 # should be invoked separately.
90 #
91 # Framework code in ExprNode provides much of the common
92 # processing for the various phases. It makes use of the
93 # 'subexprs' class attribute of ExprNodes, which should
94 # contain a list of the names of attributes which can
95 # hold sub-nodes or sequences of sub-nodes.
96 #
97 # The framework makes use of a number of abstract methods.
98 # Their responsibilities are as follows.
99 #
100 # Declaration Analysis phase
101 #
102 # analyse_target_declaration
103 # Called during the Analyse Declarations phase to analyse
104 # the LHS of an assignment or argument of a del statement.
105 # Nodes which cannot be the LHS of an assignment need not
106 # implement it.
107 #
108 # Expression Analysis phase
109 #
110 # analyse_types
111 # - Call analyse_types on all sub-expressions.
112 # - Check operand types, and wrap coercion nodes around
113 # sub-expressions where needed.
114 # - Set the type of this node.
115 # - If a temporary variable will be required for the
116 # result, set the is_temp flag of this node.
117 #
118 # analyse_target_types
119 # Called during the Analyse Types phase to analyse
120 # the LHS of an assignment or argument of a del
121 # statement. Similar responsibilities to analyse_types.
122 #
123 # target_code
124 # Called by the default implementation of allocate_target_temps.
125 # Should return a C lvalue for assigning to the node. The default
126 # implementation calls calculate_result_code.
127 #
128 # check_const
129 # - Check that this node and its subnodes form a
130 # legal constant expression. If so, do nothing,
131 # otherwise call not_const.
132 #
133 # The default implementation of check_const
134 # assumes that the expression is not constant.
135 #
136 # check_const_addr
137 # - Same as check_const, except check that the
138 # expression is a C lvalue whose address is
139 # constant. Otherwise, call addr_not_const.
140 #
141 # The default implementation of calc_const_addr
142 # assumes that the expression is not a constant
143 # lvalue.
144 #
145 # Code Generation phase
146 #
147 # generate_evaluation_code
148 # - Call generate_evaluation_code for sub-expressions.
149 # - Perform the functions of generate_result_code
150 # (see below).
151 # - If result is temporary, call generate_disposal_code
152 # on all sub-expressions.
153 #
154 # A default implementation of generate_evaluation_code
155 # is provided which uses the following abstract methods:
156 #
157 # generate_result_code
158 # - Generate any C statements necessary to calculate
159 # the result of this node from the results of its
160 # sub-expressions.
161 #
162 # calculate_result_code
163 # - Should return a C code fragment evaluating to the
164 # result. This is only called when the result is not
165 # a temporary.
166 #
167 # generate_assignment_code
168 # Called on the LHS of an assignment.
169 # - Call generate_evaluation_code for sub-expressions.
170 # - Generate code to perform the assignment.
171 # - If the assignment absorbed a reference, call
172 # generate_post_assignment_code on the RHS,
173 # otherwise call generate_disposal_code on it.
174 #
175 # generate_deletion_code
176 # Called on an argument of a del statement.
177 # - Call generate_evaluation_code for sub-expressions.
178 # - Generate code to perform the deletion.
179 # - Call generate_disposal_code on all sub-expressions.
180 #
181 #
183 is_sequence_constructor = 0
184 is_attribute = 0
186 saved_subexpr_nodes = None
187 is_temp = 0
188 is_target = 0
189 is_starred = 0
191 constant_result = constant_value_not_set
193 try:
194 _get_child_attrs = operator.attrgetter('subexprs')
195 except AttributeError:
196 # Python 2.3
197 def _get_child_attrs(self):
198 return self.subexprs
199 child_attrs = property(fget=_get_child_attrs)
201 def not_implemented(self, method_name):
202 print_call_chain(method_name, "not implemented") ###
203 raise InternalError(
204 "%s.%s not implemented" %
205 (self.__class__.__name__, method_name))
207 def is_lvalue(self):
208 return 0
210 def is_ephemeral(self):
211 # An ephemeral node is one whose result is in
212 # a Python temporary and we suspect there are no
213 # other references to it. Certain operations are
214 # disallowed on such values, since they are
215 # likely to result in a dangling pointer.
216 return self.type.is_pyobject and self.is_temp
218 def subexpr_nodes(self):
219 # Extract a list of subexpression nodes based
220 # on the contents of the subexprs class attribute.
221 nodes = []
222 for name in self.subexprs:
223 item = getattr(self, name)
224 if item is not None:
225 if type(item) is list:
226 nodes.extend(item)
227 else:
228 nodes.append(item)
229 return nodes
231 def result(self):
232 if self.is_temp:
233 return self.temp_code
234 else:
235 return self.calculate_result_code()
237 def result_as(self, type = None):
238 # Return the result code cast to the specified C type.
239 return typecast(type, self.ctype(), self.result())
241 def py_result(self):
242 # Return the result code cast to PyObject *.
243 return self.result_as(py_object_type)
245 def ctype(self):
246 # Return the native C type of the result (i.e. the
247 # C type of the result_code expression).
248 return self.result_ctype or self.type
250 def get_constant_c_result_code(self):
251 # Return the constant value of this node as a result code
252 # string, or None if the node is not constant. This method
253 # can be called when the constant result code is required
254 # before the code generation phase.
255 #
256 # The return value is a string that can represent a simple C
257 # value, a constant C name or a constant C expression. If the
258 # node type depends on Python code, this must return None.
259 return None
261 def calculate_constant_result(self):
262 # Calculate the constant compile time result value of this
263 # expression and store it in ``self.constant_result``. Does
264 # nothing by default, thus leaving ``self.constant_result``
265 # unknown. If valid, the result can be an arbitrary Python
266 # value.
267 #
268 # This must only be called when it is assured that all
269 # sub-expressions have a valid constant_result value. The
270 # ConstantFolding transform will do this.
271 pass
273 def compile_time_value(self, denv):
274 # Return value of compile-time expression, or report error.
275 error(self.pos, "Invalid compile-time expression")
277 def compile_time_value_error(self, e):
278 error(self.pos, "Error in compile-time expression: %s: %s" % (
279 e.__class__.__name__, e))
281 # ------------- Declaration Analysis ----------------
283 def analyse_target_declaration(self, env):
284 error(self.pos, "Cannot assign to or delete this")
286 # ------------- Expression Analysis ----------------
288 def analyse_const_expression(self, env):
289 # Called during the analyse_declarations phase of a
290 # constant expression. Analyses the expression's type,
291 # checks whether it is a legal const expression,
292 # and determines its value.
293 self.analyse_types(env)
294 self.check_const()
296 def analyse_expressions(self, env):
297 # Convenience routine performing both the Type
298 # Analysis and Temp Allocation phases for a whole
299 # expression.
300 self.analyse_types(env)
302 def analyse_target_expression(self, env, rhs):
303 # Convenience routine performing both the Type
304 # Analysis and Temp Allocation phases for the LHS of
305 # an assignment.
306 self.analyse_target_types(env)
308 def analyse_boolean_expression(self, env):
309 # Analyse expression and coerce to a boolean.
310 self.analyse_types(env)
311 bool = self.coerce_to_boolean(env)
312 return bool
314 def analyse_temp_boolean_expression(self, env):
315 # Analyse boolean expression and coerce result into
316 # a temporary. This is used when a branch is to be
317 # performed on the result and we won't have an
318 # opportunity to ensure disposal code is executed
319 # afterwards. By forcing the result into a temporary,
320 # we ensure that all disposal has been done by the
321 # time we get the result.
322 self.analyse_types(env)
323 bool = self.coerce_to_boolean(env)
324 temp_bool = bool.coerce_to_temp(env)
325 return temp_bool
327 # --------------- Type Inference -----------------
329 def type_dependencies(self, env):
330 # Returns the list of entries whose types must be determined
331 # before the type of self can be infered.
332 if hasattr(self, 'type') and self.type is not None:
333 return ()
334 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
336 def infer_type(self, env):
337 # Attempt to deduce the type of self.
338 # Differs from analyse_types as it avoids unnecessary
339 # analysis of subexpressions, but can assume everything
340 # in self.type_dependencies() has been resolved.
341 if hasattr(self, 'type') and self.type is not None:
342 return self.type
343 elif hasattr(self, 'entry') and self.entry is not None:
344 return self.entry.type
345 else:
346 self.not_implemented("infer_type")
348 # --------------- Type Analysis ------------------
350 def analyse_as_module(self, env):
351 # If this node can be interpreted as a reference to a
352 # cimported module, return its scope, else None.
353 return None
355 def analyse_as_type(self, env):
356 # If this node can be interpreted as a reference to a
357 # type, return that type, else None.
358 return None
360 def analyse_as_extension_type(self, env):
361 # If this node can be interpreted as a reference to an
362 # extension type, return its type, else None.
363 return None
365 def analyse_types(self, env):
366 self.not_implemented("analyse_types")
368 def analyse_target_types(self, env):
369 self.analyse_types(env)
371 def nogil_check(self, env):
372 # By default, any expression based on Python objects is
373 # prevented in nogil environments. Subtypes must override
374 # this if they can work without the GIL.
375 if self.type.is_pyobject:
376 self.gil_error()
378 def gil_assignment_check(self, env):
379 if env.nogil and self.type.is_pyobject:
380 error(self.pos, "Assignment of Python object not allowed without gil")
382 def check_const(self):
383 self.not_const()
385 def not_const(self):
386 error(self.pos, "Not allowed in a constant expression")
388 def check_const_addr(self):
389 self.addr_not_const()
391 def addr_not_const(self):
392 error(self.pos, "Address is not constant")
394 # ----------------- Result Allocation -----------------
396 def result_in_temp(self):
397 # Return true if result is in a temporary owned by
398 # this node or one of its subexpressions. Overridden
399 # by certain nodes which can share the result of
400 # a subnode.
401 return self.is_temp
403 def target_code(self):
404 # Return code fragment for use as LHS of a C assignment.
405 return self.calculate_result_code()
407 def calculate_result_code(self):
408 self.not_implemented("calculate_result_code")
410 # def release_target_temp(self, env):
411 # # Release temporaries used by LHS of an assignment.
412 # self.release_subexpr_temps(env)
414 def allocate_temp_result(self, code):
415 if self.temp_code:
416 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
417 type = self.type
418 if not type.is_void:
419 if type.is_pyobject:
420 type = PyrexTypes.py_object_type
421 self.temp_code = code.funcstate.allocate_temp(
422 type, manage_ref=True)
423 else:
424 self.temp_code = None
426 def release_temp_result(self, code):
427 if not self.temp_code:
428 if self.old_temp:
429 raise RuntimeError("temp %s released multiple times in %s" % (
430 self.old_temp, self.__class__.__name__))
431 else:
432 raise RuntimeError("no temp, but release requested in %s" % (
433 self.__class__.__name__))
434 code.funcstate.release_temp(self.temp_code)
435 self.old_temp = self.temp_code
436 self.temp_code = None
438 # ---------------- Code Generation -----------------
440 def make_owned_reference(self, code):
441 # If result is a pyobject, make sure we own
442 # a reference to it.
443 if self.type.is_pyobject and not self.result_in_temp():
444 code.put_incref(self.result(), self.ctype())
446 def generate_evaluation_code(self, code):
447 code.mark_pos(self.pos)
449 # Generate code to evaluate this node and
450 # its sub-expressions, and dispose of any
451 # temporary results of its sub-expressions.
452 self.generate_subexpr_evaluation_code(code)
454 if self.is_temp:
455 self.allocate_temp_result(code)
457 self.generate_result_code(code)
458 if self.is_temp:
459 # If we are temp we do not need to wait until this node is disposed
460 # before disposing children.
461 self.generate_subexpr_disposal_code(code)
462 self.free_subexpr_temps(code)
464 def generate_subexpr_evaluation_code(self, code):
465 for node in self.subexpr_nodes():
466 node.generate_evaluation_code(code)
468 def generate_result_code(self, code):
469 self.not_implemented("generate_result_code")
471 def generate_disposal_code(self, code):
472 if self.is_temp:
473 if self.type.is_pyobject:
474 code.put_decref_clear(self.result(), self.ctype())
475 else:
476 # Already done if self.is_temp
477 self.generate_subexpr_disposal_code(code)
479 def generate_subexpr_disposal_code(self, code):
480 # Generate code to dispose of temporary results
481 # of all sub-expressions.
482 for node in self.subexpr_nodes():
483 node.generate_disposal_code(code)
485 def generate_post_assignment_code(self, code):
486 if self.is_temp:
487 if self.type.is_pyobject:
488 code.putln("%s = 0;" % self.result())
489 else:
490 self.generate_subexpr_disposal_code(code)
492 def generate_assignment_code(self, rhs, code):
493 # Stub method for nodes which are not legal as
494 # the LHS of an assignment. An error will have
495 # been reported earlier.
496 pass
498 def generate_deletion_code(self, code):
499 # Stub method for nodes that are not legal as
500 # the argument of a del statement. An error
501 # will have been reported earlier.
502 pass
504 def free_temps(self, code):
505 if self.is_temp:
506 if not self.type.is_void:
507 self.release_temp_result(code)
508 else:
509 self.free_subexpr_temps(code)
511 def free_subexpr_temps(self, code):
512 for sub in self.subexpr_nodes():
513 sub.free_temps(code)
515 # ---------------- Annotation ---------------------
517 def annotate(self, code):
518 for node in self.subexpr_nodes():
519 node.annotate(code)
521 # ----------------- Coercion ----------------------
523 def coerce_to(self, dst_type, env):
524 # Coerce the result so that it can be assigned to
525 # something of type dst_type. If processing is necessary,
526 # wraps this node in a coercion node and returns that.
527 # Otherwise, returns this node unchanged.
528 #
529 # This method is called during the analyse_expressions
530 # phase of the src_node's processing.
531 src = self
532 src_type = self.type
533 src_is_py_type = src_type.is_pyobject
534 dst_is_py_type = dst_type.is_pyobject
536 if self.check_for_coercion_error(dst_type):
537 return self
539 if dst_type.is_pyobject:
540 if not src.type.is_pyobject:
541 src = CoerceToPyTypeNode(src, env)
542 if not src.type.subtype_of(dst_type):
543 if not isinstance(src, NoneNode):
544 src = PyTypeTestNode(src, dst_type, env)
545 elif src.type.is_pyobject:
546 src = CoerceFromPyTypeNode(dst_type, src, env)
547 elif (dst_type.is_complex
548 and src_type != dst_type
549 and dst_type.assignable_from(src_type)):
550 src = CoerceToComplexNode(src, dst_type, env)
551 else: # neither src nor dst are py types
552 # Added the string comparison, since for c types that
553 # is enough, but Cython gets confused when the types are
554 # in different pxi files.
555 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
556 self.fail_assignment(dst_type)
557 return src
559 def fail_assignment(self, dst_type):
560 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
562 def check_for_coercion_error(self, dst_type, fail=False, default=None):
563 if fail and not default:
564 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
565 message = find_coercion_error((self.type, dst_type), default)
566 if message is not None:
567 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
568 return True
569 if fail:
570 self.fail_assignment(dst_type)
571 return True
572 return False
574 def coerce_to_pyobject(self, env):
575 return self.coerce_to(PyrexTypes.py_object_type, env)
577 def coerce_to_boolean(self, env):
578 # Coerce result to something acceptable as
579 # a boolean value.
580 type = self.type
581 if type.is_pyobject or type.is_ptr or type.is_float:
582 return CoerceToBooleanNode(self, env)
583 else:
584 if not type.is_int and not type.is_error:
585 error(self.pos,
586 "Type '%s' not acceptable as a boolean" % type)
587 return self
589 def coerce_to_integer(self, env):
590 # If not already some C integer type, coerce to longint.
591 if self.type.is_int:
592 return self
593 else:
594 return self.coerce_to(PyrexTypes.c_long_type, env)
596 def coerce_to_temp(self, env):
597 # Ensure that the result is in a temporary.
598 if self.result_in_temp():
599 return self
600 else:
601 return CoerceToTempNode(self, env)
603 def coerce_to_simple(self, env):
604 # Ensure that the result is simple (see is_simple).
605 if self.is_simple():
606 return self
607 else:
608 return self.coerce_to_temp(env)
610 def is_simple(self):
611 # A node is simple if its result is something that can
612 # be referred to without performing any operations, e.g.
613 # a constant, local var, C global var, struct member
614 # reference, or temporary.
615 return self.result_in_temp()
617 def as_cython_attribute(self):
618 return None
620 class AtomicExprNode(ExprNode):
621 # Abstract base class for expression nodes which have
622 # no sub-expressions.
624 subexprs = []
626 # Override to optimize -- we know we have no children
627 def generate_subexpr_evaluation_code(self, code):
628 pass
629 def generate_subexpr_disposal_code(self, code):
630 pass
632 class PyConstNode(AtomicExprNode):
633 # Abstract base class for constant Python values.
635 is_literal = 1
636 type = py_object_type
638 def is_simple(self):
639 return 1
641 def analyse_types(self, env):
642 pass
644 def calculate_result_code(self):
645 return self.value
647 def generate_result_code(self, code):
648 pass
651 class NoneNode(PyConstNode):
652 # The constant value None
654 value = "Py_None"
656 constant_result = None
658 nogil_check = None
660 def compile_time_value(self, denv):
661 return None
663 class EllipsisNode(PyConstNode):
664 # '...' in a subscript list.
666 value = "Py_Ellipsis"
668 constant_result = Ellipsis
670 def compile_time_value(self, denv):
671 return Ellipsis
674 class ConstNode(AtomicExprNode):
675 # Abstract base type for literal constant nodes.
676 #
677 # value string C code fragment
679 is_literal = 1
680 nogil_check = None
682 def is_simple(self):
683 return 1
685 def analyse_types(self, env):
686 pass # Types are held in class variables
688 def check_const(self):
689 pass
691 def get_constant_c_result_code(self):
692 return self.calculate_result_code()
694 def calculate_result_code(self):
695 return str(self.value)
697 def generate_result_code(self, code):
698 pass
701 class BoolNode(ConstNode):
702 type = PyrexTypes.c_bint_type
703 # The constant value True or False
705 def calculate_constant_result(self):
706 self.constant_result = self.value
708 def compile_time_value(self, denv):
709 return self.value
711 def calculate_result_code(self):
712 return str(int(self.value))
715 class NullNode(ConstNode):
716 type = PyrexTypes.c_null_ptr_type
717 value = "NULL"
718 constant_result = 0
720 def get_constant_c_result_code(self):
721 return self.value
724 class CharNode(ConstNode):
725 type = PyrexTypes.c_char_type
727 def calculate_constant_result(self):
728 self.constant_result = ord(self.value)
730 def compile_time_value(self, denv):
731 return ord(self.value)
733 def calculate_result_code(self):
734 return "'%s'" % StringEncoding.escape_char(self.value)
737 class IntNode(ConstNode):
739 # unsigned "" or "U"
740 # longness "" or "L" or "LL"
742 unsigned = ""
743 longness = ""
744 type = PyrexTypes.c_long_type
746 def coerce_to(self, dst_type, env):
747 if dst_type.is_numeric and not dst_type.is_complex:
748 self.type = PyrexTypes.c_long_type
749 return self
750 # Arrange for a Python version of the number to be pre-allocated
751 # when coercing to a Python type.
752 if dst_type.is_pyobject:
753 self.type = PyrexTypes.py_object_type
754 # We still need to perform normal coerce_to processing on the
755 # result, because we might be coercing to an extension type,
756 # in which case a type test node will be needed.
757 return ConstNode.coerce_to(self, dst_type, env)
759 def coerce_to_boolean(self, env):
760 self.type = PyrexTypes.c_bint_type
761 return self
763 def generate_evaluation_code(self, code):
764 if self.type.is_pyobject:
765 self.result_code = code.get_py_num(self.value, self.longness)
766 else:
767 self.result_code = self.get_constant_c_result_code()
769 def get_constant_c_result_code(self):
770 return str(self.value) + self.unsigned + self.longness
772 def calculate_result_code(self):
773 return self.result_code
775 def calculate_constant_result(self):
776 self.constant_result = int(self.value, 0)
778 def compile_time_value(self, denv):
779 return int(self.value, 0)
782 class FloatNode(ConstNode):
783 type = PyrexTypes.c_double_type
785 def calculate_constant_result(self):
786 self.constant_result = float(self.value)
788 def compile_time_value(self, denv):
789 return float(self.value)
791 def calculate_result_code(self):
792 strval = repr(float(self.value))
793 if strval == 'nan':
794 return "(Py_HUGE_VAL * 0)"
795 elif strval == 'inf':
796 return "Py_HUGE_VAL"
797 elif strval == '-inf':
798 return "(-Py_HUGE_VAL)"
799 else:
800 return strval
803 class BytesNode(ConstNode):
804 # A char* or bytes literal
805 #
806 # value BytesLiteral
808 type = PyrexTypes.c_char_ptr_type
810 def compile_time_value(self, denv):
811 return self.value
813 def analyse_as_type(self, env):
814 type = PyrexTypes.parse_basic_type(self.value)
815 if type is not None:
816 return type
817 from TreeFragment import TreeFragment
818 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
819 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
820 sizeof_node = declaration.root.stats[0].expr
821 sizeof_node.analyse_types(env)
822 if isinstance(sizeof_node, SizeofTypeNode):
823 return sizeof_node.arg_type
825 def can_coerce_to_char_literal(self):
826 return len(self.value) == 1
828 def coerce_to(self, dst_type, env):
829 if dst_type == PyrexTypes.c_char_ptr_type:
830 self.type = PyrexTypes.c_char_ptr_type
831 return self
832 elif dst_type == PyrexTypes.c_uchar_ptr_type:
833 self.type = PyrexTypes.c_char_ptr_type
834 return CastNode(self, PyrexTypes.c_uchar_ptr_type)
836 if dst_type.is_int:
837 if not self.can_coerce_to_char_literal():
838 error(self.pos, "Only single-character strings can be coerced into ints.")
839 return self
840 return CharNode(self.pos, value=self.value)
842 node = self
843 if not self.type.is_pyobject:
844 if dst_type in (py_object_type, Builtin.bytes_type):
845 node = self.as_py_string_node(env)
846 elif dst_type.is_pyobject:
847 self.fail_assignment(dst_type)
848 return self
849 else:
850 node = self
851 elif dst_type.is_pyobject and dst_type is not py_object_type:
852 self.check_for_coercion_error(dst_type, fail=True)
853 return self
855 # We still need to perform normal coerce_to processing on the
856 # result, because we might be coercing to an extension type,
857 # in which case a type test node will be needed.
858 return ConstNode.coerce_to(node, dst_type, env)
860 def as_py_string_node(self, env):
861 # Return a new BytesNode with the same value as this node
862 # but whose type is a Python type instead of a C type.
863 return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
865 def generate_evaluation_code(self, code):
866 if self.type.is_pyobject:
867 self.result_code = code.get_py_string_const(self.value)
868 else:
869 self.result_code = code.get_string_const(self.value)
871 def get_constant_c_result_code(self):
872 return None # FIXME
874 def calculate_result_code(self):
875 return self.result_code
878 class UnicodeNode(PyConstNode):
879 # A Python unicode object
880 #
881 # value EncodedString
883 type = unicode_type
885 def coerce_to(self, dst_type, env):
886 if dst_type is self.type:
887 pass
888 elif not dst_type.is_pyobject:
889 error(self.pos, "Unicode objects do not support coercion to C types.")
890 elif dst_type is not py_object_type:
891 if not self.check_for_coercion_error(dst_type):
892 self.fail_assignment(dst_type)
893 return self
895 def generate_evaluation_code(self, code):
896 self.result_code = code.get_py_string_const(self.value)
898 def calculate_result_code(self):
899 return self.result_code
901 def compile_time_value(self, env):
902 return self.value
905 class StringNode(PyConstNode):
906 # A Python str object, i.e. a byte string in Python 2.x and a
907 # unicode string in Python 3.x
908 #
909 # value BytesLiteral or EncodedString
910 # is_identifier boolean
912 type = str_type
913 is_identifier = False
915 def coerce_to(self, dst_type, env):
916 if dst_type is not py_object_type and dst_type is not str_type:
917 # if dst_type is Builtin.bytes_type:
918 # # special case: bytes = 'str literal'
919 # return BytesNode(self.pos, value=self.value)
920 if not dst_type.is_pyobject:
921 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
922 self.check_for_coercion_error(dst_type, fail=True)
924 # this will be a unicode string in Py3, so make sure we can decode it
925 if not self.is_identifier:
926 encoding = self.value.encoding or 'UTF-8'
927 try:
928 self.value.decode(encoding)
929 except UnicodeDecodeError:
930 error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
932 return self
934 def can_coerce_to_char_literal(self):
935 return not self.is_identifier and len(self.value) == 1
937 def generate_evaluation_code(self, code):
938 self.result_code = code.get_py_string_const(
939 self.value, identifier=self.is_identifier, is_str=True)
941 def get_constant_c_result_code(self):
942 return None
944 def calculate_result_code(self):
945 return self.result_code
947 def compile_time_value(self, env):
948 return self.value
951 class IdentifierStringNode(StringNode):
952 # A special str value that represents an identifier (bytes in Py2,
953 # unicode in Py3).
954 is_identifier = True
957 class LongNode(AtomicExprNode):
958 # Python long integer literal
959 #
960 # value string
962 type = py_object_type
964 def calculate_constant_result(self):
965 self.constant_result = long(self.value)
967 def compile_time_value(self, denv):
968 return long(self.value)
970 def analyse_types(self, env):
971 self.is_temp = 1
973 gil_message = "Constructing Python long int"
975 def generate_result_code(self, code):
976 code.putln(
977 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
978 self.result(),
979 self.value,
980 code.error_goto_if_null(self.result(), self.pos)))
981 code.put_gotref(self.py_result())
984 class ImagNode(AtomicExprNode):
985 # Imaginary number literal
986 #
987 # value float imaginary part
989 type = PyrexTypes.c_double_complex_type
991 def calculate_constant_result(self):
992 self.constant_result = complex(0.0, self.value)
994 def compile_time_value(self, denv):
995 return complex(0.0, self.value)
997 def analyse_types(self, env):
998 self.type.create_declaration_utility_code(env)
1000 def coerce_to(self, dst_type, env):
1001 # Arrange for a Python version of the number to be pre-allocated
1002 # when coercing to a Python type.
1003 if dst_type.is_pyobject:
1004 self.is_temp = 1
1005 self.type = PyrexTypes.py_object_type
1006 # We still need to perform normal coerce_to processing on the
1007 # result, because we might be coercing to an extension type,
1008 # in which case a type test node will be needed.
1009 return AtomicExprNode.coerce_to(self, dst_type, env)
1011 gil_message = "Constructing complex number"
1013 def calculate_result_code(self):
1014 if self.type.is_pyobject:
1015 return self.result()
1016 else:
1017 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1019 def generate_result_code(self, code):
1020 if self.type.is_pyobject:
1021 code.putln(
1022 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1023 self.result(),
1024 float(self.value),
1025 code.error_goto_if_null(self.result(), self.pos)))
1026 code.put_gotref(self.py_result())
1030 class NameNode(AtomicExprNode):
1031 # Reference to a local or global variable name.
1033 # name string Python name of the variable
1034 # entry Entry Symbol table entry
1035 # type_entry Entry For extension type names, the original type entry
1037 is_name = True
1038 is_cython_module = False
1039 cython_attribute = None
1040 lhs_of_first_assignment = False
1041 is_used_as_rvalue = 0
1042 entry = None
1043 type_entry = None
1045 def create_analysed_rvalue(pos, env, entry):
1046 node = NameNode(pos)
1047 node.analyse_types(env, entry=entry)
1048 return node
1050 def as_cython_attribute(self):
1051 return self.cython_attribute
1053 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1055 def type_dependencies(self, env):
1056 if self.entry is None:
1057 self.entry = env.lookup(self.name)
1058 if self.entry is not None and self.entry.type.is_unspecified:
1059 return (self.entry,)
1060 else:
1061 return ()
1063 def infer_type(self, env):
1064 if self.entry is None:
1065 self.entry = env.lookup(self.name)
1066 if self.entry is None:
1067 return py_object_type
1068 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1069 self.name == self.entry.type.name:
1070 # Unfortunately the type attribute of type objects
1071 # is used for the pointer to the type the represent.
1072 return type_type
1073 else:
1074 return self.entry.type
1076 def compile_time_value(self, denv):
1077 try:
1078 return denv.lookup(self.name)
1079 except KeyError:
1080 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1082 def get_constant_c_result_code(self):
1083 if not self.entry or self.entry.type.is_pyobject:
1084 return None
1085 return self.entry.cname
1087 def coerce_to(self, dst_type, env):
1088 # If coercing to a generic pyobject and this is a builtin
1089 # C function with a Python equivalent, manufacture a NameNode
1090 # referring to the Python builtin.
1091 #print "NameNode.coerce_to:", self.name, dst_type ###
1092 if dst_type is py_object_type:
1093 entry = self.entry
1094 if entry and entry.is_cfunction:
1095 var_entry = entry.as_variable
1096 if var_entry:
1097 if var_entry.is_builtin and Options.cache_builtins:
1098 var_entry = env.declare_builtin(var_entry.name, self.pos)
1099 node = NameNode(self.pos, name = self.name)
1100 node.entry = var_entry
1101 node.analyse_rvalue_entry(env)
1102 return node
1103 return super(NameNode, self).coerce_to(dst_type, env)
1105 def analyse_as_module(self, env):
1106 # Try to interpret this as a reference to a cimported module.
1107 # Returns the module scope, or None.
1108 entry = self.entry
1109 if not entry:
1110 entry = env.lookup(self.name)
1111 if entry and entry.as_module:
1112 return entry.as_module
1113 return None
1115 def analyse_as_type(self, env):
1116 if self.cython_attribute:
1117 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1118 else:
1119 type = PyrexTypes.parse_basic_type(self.name)
1120 if type:
1121 return type
1122 entry = self.entry
1123 if not entry:
1124 entry = env.lookup(self.name)
1125 if entry and entry.is_type:
1126 return entry.type
1127 else:
1128 return None
1130 def analyse_as_extension_type(self, env):
1131 # Try to interpret this as a reference to an extension type.
1132 # Returns the extension type, or None.
1133 entry = self.entry
1134 if not entry:
1135 entry = env.lookup(self.name)
1136 if entry and entry.is_type and entry.type.is_extension_type:
1137 return entry.type
1138 else:
1139 return None
1141 def analyse_target_declaration(self, env):
1142 if not self.entry:
1143 self.entry = env.lookup_here(self.name)
1144 if not self.entry:
1145 if env.directives['infer_types']:
1146 type = unspecified_type
1147 else:
1148 type = py_object_type
1149 self.entry = env.declare_var(self.name, type, self.pos)
1150 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1151 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1152 if self.entry.is_declared_generic:
1153 self.result_ctype = py_object_type
1155 def analyse_types(self, env):
1156 if self.entry is None:
1157 self.entry = env.lookup(self.name)
1158 if not self.entry:
1159 self.entry = env.declare_builtin(self.name, self.pos)
1160 if not self.entry:
1161 self.type = PyrexTypes.error_type
1162 return
1163 entry = self.entry
1164 if entry:
1165 entry.used = 1
1166 if entry.type.is_buffer:
1167 import Buffer
1168 Buffer.used_buffer_aux_vars(entry)
1169 if entry.utility_code:
1170 env.use_utility_code(entry.utility_code)
1171 self.analyse_rvalue_entry(env)
1173 def analyse_target_types(self, env):
1174 self.analyse_entry(env)
1175 if not self.is_lvalue():
1176 error(self.pos, "Assignment to non-lvalue '%s'"
1177 % self.name)
1178 self.type = PyrexTypes.error_type
1179 self.entry.used = 1
1180 if self.entry.type.is_buffer:
1181 import Buffer
1182 Buffer.used_buffer_aux_vars(self.entry)
1184 def analyse_rvalue_entry(self, env):
1185 #print "NameNode.analyse_rvalue_entry:", self.name ###
1186 #print "Entry:", self.entry.__dict__ ###
1187 self.analyse_entry(env)
1188 entry = self.entry
1189 if entry.is_declared_generic:
1190 self.result_ctype = py_object_type
1191 if entry.is_pyglobal or entry.is_builtin:
1192 if Options.cache_builtins and entry.is_builtin:
1193 self.is_temp = 0
1194 else:
1195 self.is_temp = 1
1196 self.is_used_as_rvalue = 1
1197 env.use_utility_code(get_name_interned_utility_code)
1199 def nogil_check(self, env):
1200 if self.is_used_as_rvalue:
1201 entry = self.entry
1202 if entry.is_builtin:
1203 # if not Options.cache_builtins: # cached builtins are ok
1204 self.gil_error()
1205 elif entry.is_pyglobal:
1206 self.gil_error()
1208 gil_message = "Accessing Python global or builtin"
1210 def analyse_entry(self, env):
1211 #print "NameNode.analyse_entry:", self.name ###
1212 self.check_identifier_kind()
1213 entry = self.entry
1214 type = entry.type
1215 self.type = type
1217 def check_identifier_kind(self):
1218 # Check that this is an appropriate kind of name for use in an
1219 # expression. Also finds the variable entry associated with
1220 # an extension type.
1221 entry = self.entry
1222 if entry.is_type and entry.type.is_extension_type:
1223 self.type_entry = entry
1224 if not (entry.is_const or entry.is_variable
1225 or entry.is_builtin or entry.is_cfunction):
1226 if self.entry.as_variable:
1227 self.entry = self.entry.as_variable
1228 else:
1229 error(self.pos,
1230 "'%s' is not a constant, variable or function identifier" % self.name)
1232 def is_simple(self):
1233 # If it's not a C variable, it'll be in a temp.
1234 return 1
1236 def calculate_target_results(self, env):
1237 pass
1239 def check_const(self):
1240 entry = self.entry
1241 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1242 self.not_const()
1244 def check_const_addr(self):
1245 entry = self.entry
1246 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1247 self.addr_not_const()
1249 def is_lvalue(self):
1250 return self.entry.is_variable and \
1251 not self.entry.type.is_array and \
1252 not self.entry.is_readonly
1254 def is_ephemeral(self):
1255 # Name nodes are never ephemeral, even if the
1256 # result is in a temporary.
1257 return 0
1259 def calculate_result_code(self):
1260 entry = self.entry
1261 if not entry:
1262 return "<error>" # There was an error earlier
1263 return entry.cname
1265 def generate_result_code(self, code):
1266 assert hasattr(self, 'entry')
1267 entry = self.entry
1268 if entry is None:
1269 return # There was an error earlier
1270 if entry.is_builtin and Options.cache_builtins:
1271 return # Lookup already cached
1272 elif entry.is_pyglobal or entry.is_builtin:
1273 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1274 interned_cname = code.intern_identifier(self.entry.name)
1275 if entry.is_builtin:
1276 namespace = Naming.builtins_cname
1277 else: # entry.is_pyglobal
1278 namespace = entry.scope.namespace_cname
1279 code.putln(
1280 '%s = __Pyx_GetName(%s, %s); %s' % (
1281 self.result(),
1282 namespace,
1283 interned_cname,
1284 code.error_goto_if_null(self.result(), self.pos)))
1285 code.put_gotref(self.py_result())
1287 elif entry.is_local and False:
1288 # control flow not good enough yet
1289 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1290 if assigned is False:
1291 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1292 elif not Options.init_local_none and assigned is None:
1293 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1294 (entry.cname, entry.name, code.error_goto(self.pos)))
1295 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1297 def generate_assignment_code(self, rhs, code):
1298 #print "NameNode.generate_assignment_code:", self.name ###
1299 entry = self.entry
1300 if entry is None:
1301 return # There was an error earlier
1303 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1304 and not self.lhs_of_first_assignment):
1305 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1307 # is_pyglobal seems to be True for module level-globals only.
1308 # We use this to access class->tp_dict if necessary.
1309 if entry.is_pyglobal:
1310 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1311 interned_cname = code.intern_identifier(self.entry.name)
1312 namespace = self.entry.scope.namespace_cname
1313 if entry.is_member:
1314 # if the entry is a member we have to cheat: SetAttr does not work
1315 # on types, so we create a descriptor which is then added to tp_dict
1316 code.put_error_if_neg(self.pos,
1317 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1318 namespace,
1319 interned_cname,
1320 rhs.py_result()))
1321 rhs.generate_disposal_code(code)
1322 rhs.free_temps(code)
1323 # in Py2.6+, we need to invalidate the method cache
1324 code.putln("PyType_Modified(%s);" %
1325 entry.scope.parent_type.typeptr_cname)
1326 else:
1327 code.put_error_if_neg(self.pos,
1328 'PyObject_SetAttr(%s, %s, %s)' % (
1329 namespace,
1330 interned_cname,
1331 rhs.py_result()))
1332 if debug_disposal_code:
1333 print("NameNode.generate_assignment_code:")
1334 print("...generating disposal code for %s" % rhs)
1335 rhs.generate_disposal_code(code)
1336 rhs.free_temps(code)
1337 else:
1338 if self.type.is_buffer:
1339 # Generate code for doing the buffer release/acquisition.
1340 # This might raise an exception in which case the assignment (done
1341 # below) will not happen.
1343 # The reason this is not in a typetest-like node is because the
1344 # variables that the acquired buffer info is stored to is allocated
1345 # per entry and coupled with it.
1346 self.generate_acquire_buffer(rhs, code)
1348 if self.type.is_pyobject:
1349 rhs.make_owned_reference(code)
1350 #print "NameNode.generate_assignment_code: to", self.name ###
1351 #print "...from", rhs ###
1352 #print "...LHS type", self.type, "ctype", self.ctype() ###
1353 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1354 if entry.is_cglobal:
1355 code.put_gotref(self.py_result())
1356 if not self.lhs_of_first_assignment:
1357 if entry.is_local and not Options.init_local_none:
1358 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1359 if initalized is True:
1360 code.put_decref(self.result(), self.ctype())
1361 elif initalized is None:
1362 code.put_xdecref(self.result(), self.ctype())
1363 else:
1364 code.put_decref(self.result(), self.ctype())
1365 if entry.is_cglobal:
1366 code.put_giveref(rhs.py_result())
1367 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1368 if debug_disposal_code:
1369 print("NameNode.generate_assignment_code:")
1370 print("...generating post-assignment code for %s" % rhs)
1371 rhs.generate_post_assignment_code(code)
1372 rhs.free_temps(code)
1374 def generate_acquire_buffer(self, rhs, code):
1375 # rhstmp is only used in case the rhs is a complicated expression leading to
1376 # the object, to avoid repeating the same C expression for every reference
1377 # to the rhs. It does NOT hold a reference.
1378 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1379 if pretty_rhs:
1380 rhstmp = rhs.result_as(self.ctype())
1381 else:
1382 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1383 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1385 buffer_aux = self.entry.buffer_aux
1386 bufstruct = buffer_aux.buffer_info_var.cname
1387 import Buffer
1388 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1389 is_initialized=not self.lhs_of_first_assignment,
1390 pos=self.pos, code=code)
1392 if not pretty_rhs:
1393 code.putln("%s = 0;" % rhstmp)
1394 code.funcstate.release_temp(rhstmp)
1396 def generate_deletion_code(self, code):
1397 if self.entry is None:
1398 return # There was an error earlier
1399 if not self.entry.is_pyglobal:
1400 error(self.pos, "Deletion of local or C global name not supported")
1401 return
1402 code.put_error_if_neg(self.pos,
1403 '__Pyx_DelAttrString(%s, "%s")' % (
1404 Naming.module_cname,
1405 self.entry.name))
1407 def annotate(self, code):
1408 if hasattr(self, 'is_called') and self.is_called:
1409 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1410 if self.type.is_pyobject:
1411 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1412 else:
1413 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1415 class BackquoteNode(ExprNode):
1416 # `expr`
1418 # arg ExprNode
1420 type = py_object_type
1422 subexprs = ['arg']
1424 def analyse_types(self, env):
1425 self.arg.analyse_types(env)
1426 self.arg = self.arg.coerce_to_pyobject(env)
1427 self.is_temp = 1
1429 gil_message = "Backquote expression"
1431 def calculate_constant_result(self):
1432 self.constant_result = repr(self.arg.constant_result)
1434 def generate_result_code(self, code):
1435 code.putln(
1436 "%s = PyObject_Repr(%s); %s" % (
1437 self.result(),
1438 self.arg.py_result(),
1439 code.error_goto_if_null(self.result(), self.pos)))
1440 code.put_gotref(self.py_result())
1444 class ImportNode(ExprNode):
1445 # Used as part of import statement implementation.
1446 # Implements result =
1447 # __import__(module_name, globals(), None, name_list)
1449 # module_name StringNode dotted name of module
1450 # name_list ListNode or None list of names to be imported
1452 type = py_object_type
1454 subexprs = ['module_name', 'name_list']
1456 def analyse_types(self, env):
1457 self.module_name.analyse_types(env)
1458 self.module_name = self.module_name.coerce_to_pyobject(env)
1459 if self.name_list:
1460 self.name_list.analyse_types(env)
1461 self.name_list.coerce_to_pyobject(env)
1462 self.is_temp = 1
1463 env.use_utility_code(import_utility_code)
1465 gil_message = "Python import"
1467 def generate_result_code(self, code):
1468 if self.name_list:
1469 name_list_code = self.name_list.py_result()
1470 else:
1471 name_list_code = "0"
1472 code.putln(
1473 "%s = __Pyx_Import(%s, %s); %s" % (
1474 self.result(),
1475 self.module_name.py_result(),
1476 name_list_code,
1477 code.error_goto_if_null(self.result(), self.pos)))
1478 code.put_gotref(self.py_result())
1481 class IteratorNode(ExprNode):
1482 # Used as part of for statement implementation.
1484 # allocate_counter_temp/release_counter_temp needs to be called
1485 # by parent (ForInStatNode)
1487 # Implements result = iter(sequence)
1489 # sequence ExprNode
1491 type = py_object_type
1493 subexprs = ['sequence']
1495 def analyse_types(self, env):
1496 self.sequence.analyse_types(env)
1497 self.sequence = self.sequence.coerce_to_pyobject(env)
1498 self.is_temp = 1
1500 gil_message = "Iterating over Python object"
1502 def allocate_counter_temp(self, code):
1503 self.counter_cname = code.funcstate.allocate_temp(
1504 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1506 def release_counter_temp(self, code):
1507 code.funcstate.release_temp(self.counter_cname)
1509 def generate_result_code(self, code):
1510 is_builtin_sequence = self.sequence.type is list_type or \
1511 self.sequence.type is tuple_type
1512 if is_builtin_sequence:
1513 code.putln(
1514 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1515 else:
1516 code.putln(
1517 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1518 self.sequence.py_result(),
1519 self.sequence.py_result()))
1520 code.putln(
1521 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1522 self.counter_cname,
1523 self.result(),
1524 self.sequence.py_result(),
1525 self.result()))
1526 code.putln("} else {")
1527 if is_builtin_sequence:
1528 code.putln(
1529 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1530 code.error_goto(self.pos))
1531 else:
1532 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1533 self.counter_cname,
1534 self.result(),
1535 self.sequence.py_result(),
1536 code.error_goto_if_null(self.result(), self.pos)))
1537 code.put_gotref(self.py_result())
1538 code.putln("}")
1541 class NextNode(AtomicExprNode):
1542 # Used as part of for statement implementation.
1543 # Implements result = iterator.next()
1544 # Created during analyse_types phase.
1545 # The iterator is not owned by this node.
1547 # iterator ExprNode
1549 type = py_object_type
1551 def __init__(self, iterator, env):
1552 self.pos = iterator.pos
1553 self.iterator = iterator
1554 self.is_temp = 1
1556 def generate_result_code(self, code):
1557 if self.iterator.sequence.type is list_type:
1558 type_checks = [(list_type, "List")]
1559 elif self.iterator.sequence.type is tuple_type:
1560 type_checks = [(tuple_type, "Tuple")]
1561 else:
1562 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1564 for py_type, prefix in type_checks:
1565 if len(type_checks) > 1:
1566 code.putln(
1567 "if (likely(Py%s_CheckExact(%s))) {" % (
1568 prefix, self.iterator.py_result()))
1569 code.putln(
1570 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1571 self.iterator.counter_cname,
1572 prefix,
1573 self.iterator.py_result()))
1574 code.putln(
1575 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1576 self.result(),
1577 prefix,
1578 self.iterator.py_result(),
1579 self.iterator.counter_cname,
1580 self.result(),
1581 self.iterator.counter_cname))
1582 if len(type_checks) > 1:
1583 code.put("} else ")
1584 if len(type_checks) == 1:
1585 return
1586 code.putln("{")
1587 code.putln(
1588 "%s = PyIter_Next(%s);" % (
1589 self.result(),
1590 self.iterator.py_result()))
1591 code.putln(
1592 "if (!%s) {" %
1593 self.result())
1594 code.putln(code.error_goto_if_PyErr(self.pos))
1595 code.putln("break;")
1596 code.putln("}")
1597 code.put_gotref(self.py_result())
1598 code.putln("}")
1601 class ExcValueNode(AtomicExprNode):
1602 # Node created during analyse_types phase
1603 # of an ExceptClauseNode to fetch the current
1604 # exception value.
1606 type = py_object_type
1608 def __init__(self, pos, env):
1609 ExprNode.__init__(self, pos)
1611 def set_var(self, var):
1612 self.var = var
1614 def calculate_result_code(self):
1615 return self.var
1617 def generate_result_code(self, code):
1618 pass
1620 def analyse_types(self, env):
1621 pass
1624 class TempNode(ExprNode):
1625 # Node created during analyse_types phase
1626 # of some nodes to hold a temporary value.
1628 # Note: One must call "allocate" and "release" on
1629 # the node during code generation to get/release the temp.
1630 # This is because the temp result is often used outside of
1631 # the regular cycle.
1633 subexprs = []
1635 def __init__(self, pos, type, env):
1636 ExprNode.__init__(self, pos)
1637 self.type = type
1638 if type.is_pyobject:
1639 self.result_ctype = py_object_type
1640 self.is_temp = 1
1642 def analyse_types(self, env):
1643 return self.type
1645 def generate_result_code(self, code):
1646 pass
1648 def allocate(self, code):
1649 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1651 def release(self, code):
1652 code.funcstate.release_temp(self.temp_cname)
1653 self.temp_cname = None
1655 def result(self):
1656 try:
1657 return self.temp_cname
1658 except:
1659 assert False, "Remember to call allocate/release on TempNode"
1660 raise
1662 # Do not participate in normal temp alloc/dealloc:
1663 def allocate_temp_result(self, code):
1664 pass
1666 def release_temp_result(self, code):
1667 pass
1669 class PyTempNode(TempNode):
1670 # TempNode holding a Python value.
1672 def __init__(self, pos, env):
1673 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1675 class RawCNameExprNode(ExprNode):
1676 subexprs = []
1678 def __init__(self, pos, type=None):
1679 self.pos = pos
1680 self.type = type
1682 def analyse_types(self, env):
1683 return self.type
1685 def set_cname(self, cname):
1686 self.cname = cname
1688 def result(self):
1689 return self.cname
1691 def generate_result_code(self, code):
1692 pass
1695 #-------------------------------------------------------------------
1697 # Trailer nodes
1699 #-------------------------------------------------------------------
1701 class IndexNode(ExprNode):
1702 # Sequence indexing.
1704 # base ExprNode
1705 # index ExprNode
1706 # indices [ExprNode]
1707 # is_buffer_access boolean Whether this is a buffer access.
1709 # indices is used on buffer access, index on non-buffer access.
1710 # The former contains a clean list of index parameters, the
1711 # latter whatever Python object is needed for index access.
1713 subexprs = ['base', 'index', 'indices']
1714 indices = None
1716 def __init__(self, pos, index, *args, **kw):
1717 ExprNode.__init__(self, pos, index=index, *args, **kw)
1718 self._index = index
1720 def calculate_constant_result(self):
1721 self.constant_result = \
1722 self.base.constant_result[self.index.constant_result]
1724 def compile_time_value(self, denv):
1725 base = self.base.compile_time_value(denv)
1726 index = self.index.compile_time_value(denv)
1727 try:
1728 return base[index]
1729 except Exception, e:
1730 self.compile_time_value_error(e)
1732 def is_ephemeral(self):
1733 return self.base.is_ephemeral()
1735 def analyse_target_declaration(self, env):
1736 pass
1738 def analyse_as_type(self, env):
1739 base_type = self.base.analyse_as_type(env)
1740 if base_type and not base_type.is_pyobject:
1741 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1742 return None
1744 def type_dependencies(self, env):
1745 return self.base.type_dependencies(env)
1747 def infer_type(self, env):
1748 if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1749 return py_object_type
1750 base_type = self.base.infer_type(env)
1751 if base_type.is_ptr or base_type.is_array:
1752 return base_type.base_type
1753 else:
1754 # TODO: Handle buffers (hopefully without too much redundancy).
1755 return py_object_type
1757 def analyse_types(self, env):
1758 self.analyse_base_and_index_types(env, getting = 1)
1760 def analyse_target_types(self, env):
1761 self.analyse_base_and_index_types(env, setting = 1)
1763 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1764 # Note: This might be cleaned up by having IndexNode
1765 # parsed in a saner way and only construct the tuple if
1766 # needed.
1768 # Note that this function must leave IndexNode in a cloneable state.
1769 # For buffers, self.index is packed out on the initial analysis, and
1770 # when cloning self.indices is copied.
1771 self.is_buffer_access = False
1773 self.base.analyse_types(env)
1774 # Handle the case where base is a literal char* (and we expect a string, not an int)
1775 if isinstance(self.base, BytesNode):
1776 self.base = self.base.coerce_to_pyobject(env)
1778 skip_child_analysis = False
1779 buffer_access = False
1780 if self.base.type.is_buffer:
1781 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1782 if self.indices:
1783 indices = self.indices
1784 else:
1785 if isinstance(self.index, TupleNode):
1786 indices = self.index.args
1787 else:
1788 indices = [self.index]
1789 if len(indices) == self.base.type.ndim:
1790 buffer_access = True
1791 skip_child_analysis = True
1792 for x in indices:
1793 x.analyse_types(env)
1794 if not x.type.is_int:
1795 buffer_access = False
1797 # On cloning, indices is cloned. Otherwise, unpack index into indices
1798 assert not (buffer_access and isinstance(self.index, CloneNode))
1800 if buffer_access:
1801 self.indices = indices
1802 self.index = None
1803 self.type = self.base.type.dtype
1804 self.is_buffer_access = True
1805 self.buffer_type = self.base.entry.type
1807 if getting and self.type.is_pyobject:
1808 self.is_temp = True
1809 if setting:
1810 if not self.base.entry.type.writable:
1811 error(self.pos, "Writing to readonly buffer")
1812 else:
1813 self.base.entry.buffer_aux.writable_needed = True
1814 else:
1815 if isinstance(self.index, TupleNode):
1816 self.index.analyse_types(env, skip_children=skip_child_analysis)
1817 elif not skip_child_analysis:
1818 self.index.analyse_types(env)
1819 self.original_index_type = self.index.type
1820 if self.base.type.is_pyobject:
1821 if self.index.type.is_int:
1822 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1823 else:
1824 self.index = self.index.coerce_to_pyobject(env)
1825 self.type = py_object_type
1826 self.is_temp = 1
1827 else:
1828 if self.base.type.is_ptr or self.base.type.is_array:
1829 self.type = self.base.type.base_type
1830 else:
1831 error(self.pos,
1832 "Attempting to index non-array type '%s'" %
1833 self.base.type)
1834 self.type = PyrexTypes.error_type
1835 if self.index.type.is_pyobject:
1836 self.index = self.index.coerce_to(
1837 PyrexTypes.c_py_ssize_t_type, env)
1838 if not self.index.type.is_int:
1839 error(self.pos,
1840 "Invalid index type '%s'" %
1841 self.index.type)
1842 gil_message = "Indexing Python object"
1844 def nogil_check(self, env):
1845 if self.is_buffer_access:
1846 if env.directives['boundscheck']:
1847 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1848 return
1849 elif self.type.is_pyobject:
1850 error(self.pos, "Cannot access buffer with object dtype without gil")
1851 return
1852 super(IndexNode, self).nogil_check(env)
1855 def check_const_addr(self):
1856 self.base.check_const_addr()
1857 self.index.check_const()
1859 def is_lvalue(self):
1860 return 1
1862 def calculate_result_code(self):
1863 if self.is_buffer_access:
1864 return "(*%s)" % self.buffer_ptr_code
1865 else:
1866 return "(%s[%s])" % (
1867 self.base.result(), self.index.result())
1869 def extra_index_params(self):
1870 if self.index.type.is_int:
1871 if self.original_index_type.signed:
1872 size_adjustment = ""
1873 else:
1874 size_adjustment = "+1"
1875 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1876 else:
1877 return ""
1879 def generate_subexpr_evaluation_code(self, code):
1880 self.base.generate_evaluation_code(code)
1881 if not self.indices:
1882 self.index.generate_evaluation_code(code)
1883 else:
1884 for i in self.indices:
1885 i.generate_evaluation_code(code)
1887 def generate_subexpr_disposal_code(self, code):
1888 self.base.generate_disposal_code(code)
1889 if not self.indices:
1890 self.index.generate_disposal_code(code)
1891 else:
1892 for i in self.indices:
1893 i.generate_disposal_code(code)
1895 def free_subexpr_temps(self, code):
1896 self.base.free_temps(code)
1897 if not self.indices:
1898 self.index.free_temps(code)
1899 else:
1900 for i in self.indices:
1901 i.free_temps(code)
1903 def generate_result_code(self, code):
1904 if self.is_buffer_access:
1905 if code.globalstate.directives['nonecheck']:
1906 self.put_nonecheck(code)
1907 self.buffer_ptr_code = self.buffer_lookup_code(code)
1908 if self.type.is_pyobject:
1909 # is_temp is True, so must pull out value and incref it.
1910 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1911 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1912 elif self.type.is_pyobject:
1913 if self.index.type.is_int:
1914 index_code = self.index.result()
1915 if self.base.type is list_type:
1916 function = "__Pyx_GetItemInt_List"
1917 elif self.base.type is tuple_type:
1918 function = "__Pyx_GetItemInt_Tuple"
1919 else:
1920 function = "__Pyx_GetItemInt"
1921 code.globalstate.use_utility_code(getitem_int_utility_code)
1922 else:
1923 function = "PyObject_GetItem"
1924 index_code = self.index.py_result()
1925 sign_code = ""
1926 code.putln(
1927 "%s = %s(%s, %s%s); if (!%s) %s" % (
1928 self.result(),
1929 function,
1930 self.base.py_result(),
1931 index_code,
1932 self.extra_index_params(),
1933 self.result(),
1934 code.error_goto(self.pos)))
1935 code.put_gotref(self.py_result())
1937 def generate_setitem_code(self, value_code, code):
1938 if self.index.type.is_int:
1939 function = "__Pyx_SetItemInt"
1940 index_code = self.index.result()
1941 code.globalstate.use_utility_code(setitem_int_utility_code)
1942 else:
1943 index_code = self.index.py_result()
1944 if self.base.type is dict_type:
1945 function = "PyDict_SetItem"
1946 # It would seem that we could specalized lists/tuples, but that
1947 # shouldn't happen here.
1948 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1949 # not a PyObject*, and bad conversion here would give the wrong
1950 # exception. Also, tuples are supposed to be immutable, and raise
1951 # TypeErrors when trying to set their entries (PyTuple_SetItem
1952 # is for creating new tuples from).
1953 else:
1954 function = "PyObject_SetItem"
1955 code.putln(
1956 "if (%s(%s, %s, %s%s) < 0) %s" % (
1957 function,
1958 self.base.py_result(),
1959 index_code,
1960 value_code,
1961 self.extra_index_params(),
1962 code.error_goto(self.pos)))
1964 def generate_buffer_setitem_code(self, rhs, code, op=""):
1965 # Used from generate_assignment_code and InPlaceAssignmentNode
1966 if code.globalstate.directives['nonecheck']:
1967 self.put_nonecheck(code)
1968 ptrexpr = self.buffer_lookup_code(code)
1969 if self.buffer_type.dtype.is_pyobject:
1970 # Must manage refcounts. Decref what is already there
1971 # and incref what we put in.
1972 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1973 rhs_code = rhs.result()
1974 code.putln("%s = %s;" % (ptr, ptrexpr))
1975 code.put_gotref("*%s" % ptr)
1976 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1977 ptr, rhs_code
1978 ))
1979 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1980 code.put_giveref("*%s" % ptr)
1981 code.funcstate.release_temp(ptr)
1982 else:
1983 # Simple case
1984 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1986 def generate_assignment_code(self, rhs, code):
1987 self.generate_subexpr_evaluation_code(code)
1988 if self.is_buffer_access:
1989 self.generate_buffer_setitem_code(rhs, code)
1990 elif self.type.is_pyobject:
1991 self.generate_setitem_code(rhs.py_result(), code)
1992 else:
1993 code.putln(
1994 "%s = %s;" % (
1995 self.result(), rhs.result()))
1996 self.generate_subexpr_disposal_code(code)
1997 self.free_subexpr_temps(code)
1998 rhs.generate_disposal_code(code)
1999 rhs.free_temps(code)
2001 def generate_deletion_code(self, code):
2002 self.generate_subexpr_evaluation_code(code)
2003 #if self.type.is_pyobject:
2004 if self.index.type.is_int:
2005 function = "__Pyx_DelItemInt"
2006 index_code = self.index.result()
2007 code.globalstate.use_utility_code(delitem_int_utility_code)
2008 else:
2009 index_code = self.index.py_result()
2010 if self.base.type is dict_type:
2011 function = "PyDict_DelItem"
2012 else:
2013 function = "PyObject_DelItem"
2014 code.putln(
2015 "if (%s(%s, %s%s) < 0) %s" % (
2016 function,
2017 self.base.py_result(),
2018 index_code,
2019 self.extra_index_params(),
2020 code.error_goto(self.pos)))
2021 self.generate_subexpr_disposal_code(code)
2022 self.free_subexpr_temps(code)
2024 def buffer_lookup_code(self, code):
2025 # Assign indices to temps
2026 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2027 for temp, index in zip(index_temps, self.indices):
2028 code.putln("%s = %s;" % (temp, index.result()))
2029 # Generate buffer access code using these temps
2030 import Buffer
2031 # The above could happen because child_attrs is wrong somewhere so that
2032 # options are not propagated.
2033 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2034 index_signeds=[i.type.signed for i in self.indices],
2035 index_cnames=index_temps,
2036 directives=code.globalstate.directives,
2037 pos=self.pos, code=code)
2039 def put_nonecheck(self, code):
2040 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2041 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2042 code.putln("__Pyx_RaiseNoneIndexingError();")
2043 code.putln(code.error_goto(self.pos))
2044 code.putln("}")
2046 class SliceIndexNode(ExprNode):
2047 # 2-element slice indexing
2049 # base ExprNode
2050 # start ExprNode or None
2051 # stop ExprNode or None
2053 subexprs = ['base', 'start', 'stop']
2055 def calculate_constant_result(self):
2056 self.constant_result = self.base.constant_result[
2057 self.start.constant_result : self.stop.constant_result]
2059 def compile_time_value(self, denv):
2060 base = self.base.compile_time_value(denv)
2061 if self.start is None:
2062 start = 0
2063 else:
2064 start = self.start.compile_time_value(denv)
2065 if self.stop is None:
2066 stop = None
2067 else:
2068 stop = self.stop.compile_time_value(denv)
2069 try:
2070 return base[start:stop]
2071 except Exception, e:
2072 self.compile_time_value_error(e)
2074 def analyse_target_declaration(self, env):
2075 pass
2077 def analyse_target_types(self, env):
2078 self.analyse_types(env)
2079 # when assigning, we must accept any Python type
2080 if self.type.is_pyobject:
2081 self.type = py_object_type
2083 def analyse_types(self, env):
2084 self.base.analyse_types(env)
2085 if self.start:
2086 self.start.analyse_types(env)
2087 if self.stop:
2088 self.stop.analyse_types(env)
2089 base_type = self.base.type
2090 if base_type.is_string:
2091 self.type = bytes_type
2092 elif base_type.is_array or base_type.is_ptr:
2093 # we need a ptr type here instead of an array type, as
2094 # array types can result in invalid type casts in the C
2095 # code
2096 self.type = PyrexTypes.CPtrType(base_type.base_type)
2097 else:
2098 self.base = self.base.coerce_to_pyobject(env)
2099 self.type = py_object_type
2100 if base_type.is_builtin_type:
2101 # slicing builtin types returns something of the same type
2102 self.type = base_type
2103 c_int = PyrexTypes.c_py_ssize_t_type
2104 if self.start:
2105 self.start = self.start.coerce_to(c_int, env)
2106 if self.stop:
2107 self.stop = self.stop.coerce_to(c_int, env)
2108 self.is_temp = 1
2110 nogil_check = Node.gil_error
2111 gil_message = "Slicing Python object"
2113 def generate_result_code(self, code):
2114 if not self.type.is_pyobject:
2115 error(self.pos,
2116 "Slicing is not currently supported for '%s'." % self.type)
2117 return
2118 if self.base.type.is_string:
2119 if self.stop is None:
2120 code.putln(
2121 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2122 self.result(),
2123 self.base.result(),
2124 self.start_code(),
2125 code.error_goto_if_null(self.result(), self.pos)))
2126 else:
2127 code.putln(
2128 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2129 self.result(),
2130 self.base.result(),
2131 self.start_code(),
2132 self.stop_code(),
2133 self.start_code(),
2134 code.error_goto_if_null(self.result(), self.pos)))
2135 else:
2136 code.putln(
2137 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2138 self.result(),
2139 self.base.py_result(),
2140 self.start_code(),
2141 self.stop_code(),
2142 code.error_goto_if_null(self.result(), self.pos)))
2143 code.put_gotref(self.py_result())
2145 def generate_assignment_code(self, rhs, code):
2146 self.generate_subexpr_evaluation_code(code)
2147 if self.type.is_pyobject:
2148 code.put_error_if_neg(self.pos,
2149 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2150 self.base.py_result(),
2151 self.start_code(),
2152 self.stop_code(),
2153 rhs.result()))
2154 else:
2155 start_offset = ''
2156 if self.start:
2157 start_offset = self.start_code()
2158 if start_offset == '0':
2159 start_offset = ''
2160 else:
2161 start_offset += '+'
2162 if rhs.type.is_array:
2163 array_length = rhs.type.size
2164 self.generate_slice_guard_code(code, array_length)
2165 else:
2166 error(self.pos,
2167 "Slice assignments from pointers are not yet supported.")
2168 # FIXME: fix the array size according to start/stop
2169 array_length = self.base.type.size
2170 for i in range(array_length):
2171 code.putln("%s[%s%s] = %s[%d];" % (
2172 self.base.result(), start_offset, i,
2173 rhs.result(), i))
2174 self.generate_subexpr_disposal_code(code)
2175 self.free_subexpr_temps(code)
2176 rhs.generate_disposal_code(code)
2177 rhs.free_temps(code)
2179 def generate_deletion_code(self, code):
2180 if not self.base.type.is_pyobject:
2181 error(self.pos,
2182 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2183 return
2184 self.generate_subexpr_evaluation_code(code)
2185 code.put_error_if_neg(self.pos,
2186 "PySequence_DelSlice(%s, %s, %s)" % (
2187 self.base.py_result(),
2188 self.start_code(),
2189 self.stop_code()))
2190 self.generate_subexpr_disposal_code(code)
2192 def generate_slice_guard_code(self, code, target_size):
2193 if not self.base.type.is_array:
2194 return
2195 slice_size = self.base.type.size
2196 start = stop = None
2197 if self.stop:
2198 stop = self.stop.result()
2199 try:
2200 stop = int(stop)
2201 if stop < 0:
2202 slice_size = self.base.type.size + stop
2203 else:
2204 slice_size = stop
2205 stop = None
2206 except ValueError:
2207 pass
2208 if self.start:
2209 start = self.start.result()
2210 try:
2211 start = int(start)
2212 if start < 0:
2213 start = self.base.type.size + start
2214 slice_size -= start
2215 start = None
2216 except ValueError:
2217 pass
2218 check = None
2219 if slice_size < 0:
2220 if target_size > 0:
2221 error(self.pos, "Assignment to empty slice.")
2222 elif start is None and stop is None:
2223 # we know the exact slice length
2224 if target_size != slice_size:
2225 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2226 slice_size, target_size))
2227 elif start is not None:
2228 if stop is None:
2229 stop = slice_size
2230 check = "(%s)-(%s)" % (stop, start)
2231 else: # stop is not None:
2232 check = stop
2233 if check:
2234 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2235 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));' % (
2236 target_size, check))
2237 code.putln(code.error_goto(self.pos))
2238 code.putln("}")
2240 def start_code(self):
2241 if self.start:
2242 return self.start.result()
2243 else:
2244 return "0"
2246 def stop_code(self):
2247 if self.stop:
2248 return self.stop.result()
2249 elif self.base.type.is_array:
2250 return self.base.type.size
2251 else:
2252 return "PY_SSIZE_T_MAX"
2254 def calculate_result_code(self):
2255 # self.result() is not used, but this method must exist
2256 return "<unused>"
2259 class SliceNode(ExprNode):
2260 # start:stop:step in subscript list
2262 # start ExprNode
2263 # stop ExprNode
2264 # step ExprNode
2266 type = py_object_type
2267 is_temp = 1
2269 def calculate_constant_result(self):
2270 self.constant_result = self.base.constant_result[
2271 self.start.constant_result : \
2272 self.stop.constant_result : \
2273 self.step.constant_result]
2275 def compile_time_value(self, denv):
2276 start = self.start.compile_time_value(denv)
2277 if self.stop is None:
2278 stop = None
2279 else:
2280 stop = self.stop.compile_time_value(denv)
2281 if self.step is None:
2282 step = None
2283 else:
2284 step = self.step.compile_time_value(denv)
2285 try:
2286 return slice(start, stop, step)
2287 except Exception, e:
2288 self.compile_time_value_error(e)
2290 subexprs = ['start', 'stop', 'step']
2292 def analyse_types(self, env):
2293 self.start.analyse_types(env)
2294 self.stop.analyse_types(env)
2295 self.step.analyse_types(env)
2296 self.start = self.start.coerce_to_pyobject(env)
2297 self.stop = self.stop.coerce_to_pyobject(env)
2298 self.step = self.step.coerce_to_pyobject(env)
2300 gil_message = "Constructing Python slice object"
2302 def generate_result_code(self, code):
2303 code.putln(
2304 "%s = PySlice_New(%s, %s, %s); %s" % (
2305 self.result(),
2306 self.start.py_result(),
2307 self.stop.py_result(),
2308 self.step.py_result(),
2309 code.error_goto_if_null(self.result(), self.pos)))
2310 code.put_gotref(self.py_result())
2313 class CallNode(ExprNode):
2315 def analyse_as_type_constructor(self, env):
2316 type = self.function.analyse_as_type(env)
2317 if type and type.is_struct_or_union:
2318 args, kwds = self.explicit_args_kwds()
2319 items = []
2320 for arg, member in zip(args, type.scope.var_entries):
2321 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2322 if kwds:
2323 items += kwds.key_value_pairs
2324 self.key_value_pairs = items
2325 self.__class__ = DictNode
2326 self.analyse_types(env)
2327 self.coerce_to(type, env)
2328 return True
2330 def nogil_check(self, env):
2331 func_type = self.function_type()
2332 if func_type.is_pyobject:
2333 self.gil_error()
2334 elif not getattr(func_type, 'nogil', False):
2335 self.gil_error()
2337 gil_message = "Calling gil-requiring function"
2340 class SimpleCallNode(CallNode):
2341 # Function call without keyword, * or ** args.
2343 # function ExprNode
2344 # args [ExprNode]
2345 # arg_tuple ExprNode or None used internally
2346 # self ExprNode or None used internally
2347 # coerced_self ExprNode or None used internally
2348 # wrapper_call bool used internally
2349 # has_optional_args bool used internally
2351 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2353 self = None
2354 coerced_self = None
2355 arg_tuple = None
2356 wrapper_call = False
2357 has_optional_args = False
2359 def compile_time_value(self, denv):
2360 function = self.function.compile_time_value(denv)
2361 args = [arg.compile_time_value(denv) for arg in self.args]
2362 try:
2363 return function(*args)
2364 except Exception, e:
2365 self.compile_time_value_error(e)
2367 def type_dependencies(self, env):
2368 # TODO: Update when Danilo's C++ code merged in to handle the
2369 # the case of function overloading.
2370 return self.function.type_dependencies(env)
2372 def infer_type(self, env):
2373 func_type = self.function.infer_type(env)
2374 if func_type.is_ptr:
2375 func_type = func_type.base_type
2376 if func_type.is_cfunction:
2377 return func_type.return_type
2378 else:
2379 return py_object_type
2381 def analyse_as_type(self, env):
2382 attr = self.function.as_cython_attribute()
2383 if attr == 'pointer':
2384 if len(self.args) != 1:
2385 error(self.args.pos, "only one type allowed.")
2386 else:
2387 type = self.args[0].analyse_as_type(env)
2388 if not type:
2389 error(self.args[0].pos, "Unknown type")
2390 else:
2391 return PyrexTypes.CPtrType(type)
2393 def explicit_args_kwds(self):
2394 return self.args, None
2396 def analyse_types(self, env):
2397 if self.analyse_as_type_constructor(env):
2398 return
2399 function = self.function
2400 function.is_called = 1
2401 self.function.analyse_types(env)
2402 if function.is_attribute and function.entry and function.entry.is_cmethod:
2403 # Take ownership of the object from which the attribute
2404 # was obtained, because we need to pass it as 'self'.
2405 self.self = function.obj
2406 function.obj = CloneNode(self.self)
2407 func_type = self.function_type()
2408 if func_type.is_pyobject:
2409 self.arg_tuple = TupleNode(self.pos, args = self.args)
2410 self.arg_tuple.analyse_types(env)
2411 self.args = None
2412 if function.is_name and function.type_entry:
2413 # We are calling an extension type constructor. As
2414 # long as we do not support __new__(), the result type
2415 # is clear
2416 self.type = function.type_entry.type
2417 self.result_ctype = py_object_type
2418 else:
2419 self.type = py_object_type
2420 self.is_temp = 1
2421 else:
2422 for arg in self.args:
2423 arg.analyse_types(env)
2424 if self.self and func_type.args:
2425 # Coerce 'self' to the type expected by the method.
2426 expected_type = func_type.args[0].type
2427 self.coerced_self = CloneNode(self.self).coerce_to(
2428 expected_type, env)
2429 # Insert coerced 'self' argument into argument list.
2430 self.args.insert(0, self.coerced_self)
2431 self.analyse_c_function_call(env)
2433 def function_type(self):
2434 # Return the type of the function being called, coercing a function
2435 # pointer to a function if necessary.
2436 func_type = self.function.type
2437 if func_type.is_ptr:
2438 func_type = func_type.base_type
2439 return func_type
2441 def analyse_c_function_call(self, env):
2442 func_type = self.function_type()
2443 # Check function type
2444 if not func_type.is_cfunction:
2445 if not func_type.is_error:
2446 error(self.pos, "Calling non-function type '%s'" %
2447 func_type)
2448 self.type = PyrexTypes.error_type
2449 self.result_code = "<error>"
2450 return
2451 # Check no. of args
2452 max_nargs = len(func_type.args)
2453 expected_nargs = max_nargs - func_type.optional_arg_count
2454 actual_nargs = len(self.args)
2455 if actual_nargs < expected_nargs \
2456 or (not func_type.has_varargs and actual_nargs > max_nargs):
2457 expected_str = str(expected_nargs)
2458 if func_type.has_varargs:
2459 expected_str = "at least " + expected_str
2460 elif func_type.optional_arg_count:
2461 if actual_nargs < max_nargs:
2462 expected_str = "at least " + expected_str
2463 else:
2464 expected_str = "at most " + str(max_nargs)
2465 error(self.pos,
2466 "Call with wrong number of arguments (expected %s, got %s)"
2467 % (expected_str, actual_nargs))
2468 self.args = None
2469 self.type = PyrexTypes.error_type
2470 self.result_code = "<error>"
2471 return
2472 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2473 self.has_optional_args = 1
2474 self.is_temp = 1
2475 # Coerce arguments
2476 for i in range(min(max_nargs, actual_nargs)):
2477 formal_type = func_type.args[i].type
2478 self.args[i] = self.args[i].coerce_to(formal_type, env)
2479 for i in range(max_nargs, actual_nargs):
2480 if self.args[i].type.is_pyobject:
2481 error(self.args[i].pos,
2482 "Python object cannot be passed as a varargs parameter")
2483 # Calc result type and code fragment
2484 self.type = func_type.return_type
2485 if self.type.is_pyobject:
2486 self.result_ctype = py_object_type
2487 self.is_temp = 1
2488 elif func_type.exception_value is not None \
2489 or func_type.exception_check:
2490 self.is_temp = 1
2491 # C++ exception handler
2492 if func_type.exception_check == '+':
2493 if func_type.exception_value is None:
2494 env.use_utility_code(cpp_exception_utility_code)
2496 def calculate_result_code(self):
2497 return self.c_call_code()
2499 def c_call_code(self):
2500 func_type = self.function_type()
2501 if self.args is None or not func_type.is_cfunction:
2502 return "<error>"
2503 formal_args = func_type.args
2504 arg_list_code = []
2505 args = zip(formal_args, self.args)
2506 max_nargs = len(func_type.args)
2507 expected_nargs = max_nargs - func_type.optional_arg_count
2508 actual_nargs = len(self.args)
2509 for formal_arg, actual_arg in args[:expected_nargs]:
2510 arg_code = actual_arg.result_as(formal_arg.type)
2511 arg_list_code.append(arg_code)
2513 if func_type.is_overridable:
2514 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2516 if func_type.optional_arg_count:
2517 if expected_nargs == actual_nargs:
2518 optional_args = 'NULL'
2519 else:
2520 optional_args = "&%s" % self.opt_arg_struct
2521 arg_list_code.append(optional_args)
2523 for actual_arg in self.args[len(formal_args):]:
2524 arg_list_code.append(actual_arg.result())
2525 result = "%s(%s)" % (self.function.result(),
2526 ', '.join(arg_list_code))
2527 return result
2529 def generate_result_code(self, code):
2530 func_type = self.function_type()
2531 if func_type.is_pyobject:
2532 arg_code = self.arg_tuple.py_result()
2533 code.putln(
2534 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2535 self.result(),
2536 self.function.py_result(),
2537 arg_code,
2538 code.error_goto_if_null(self.result(), self.pos)))
2539 code.put_gotref(self.py_result())
2540 elif func_type.is_cfunction:
2541 if self.has_optional_args:
2542 actual_nargs = len(self.args)
2543 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2544 self.opt_arg_struct = code.funcstate.allocate_temp(
2545 func_type.op_arg_struct.base_type, manage_ref=True)
2546 code.putln("%s.%s = %s;" % (
2547 self.opt_arg_struct,
2548 Naming.pyrex_prefix + "n",
2549 len(self.args) - expected_nargs))
2550 args = zip(func_type.args, self.args)
2551 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2552 code.putln("%s.%s = %s;" % (
2553 self.opt_arg_struct,
2554 formal_arg.name,
2555 actual_arg.result_as(formal_arg.type)))
2556 exc_checks = []
2557 if self.type.is_pyobject:
2558 exc_checks.append("!%s" % self.result())
2559 else:
2560 exc_val = func_type.exception_value
2561 exc_check = func_type.exception_check
2562 if exc_val is not None:
2563 exc_checks.append("%s == %s" % (self.result(), exc_val))
2564 if exc_check:
2565 exc_checks.append("PyErr_Occurred()")
2566 if self.is_temp or exc_checks:
2567 rhs = self.c_call_code()
2568 if self.result():
2569 lhs = "%s = " % self.result()
2570 if self.is_temp and self.type.is_pyobject:
2571 #return_type = self.type # func_type.return_type
2572 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2573 # "from", return_type, "to pyobject" ###
2574 rhs = typecast(py_object_type, self.type, rhs)
2575 else:
2576 lhs = ""
2577 if func_type.exception_check == '+':
2578 if func_type.exception_value is None:
2579 raise_py_exception = "__Pyx_CppExn2PyErr()"
2580 elif func_type.exception_value.type.is_pyobject:
2581 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2582 else:
2583 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2584 code.putln(
2585 "try {%s%s;} catch(...) {%s; %s}" % (
2586 lhs,
2587 rhs,
2588 raise_py_exception,
2589 code.error_goto(self.pos)))
2590 else:
2591 if exc_checks:
2592 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2593 else:
2594 goto_error = ""
2595 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2596 if self.type.is_pyobject and self.result():
2597 code.put_gotref(self.py_result())
2598 if self.has_optional_args:
2599 code.funcstate.release_temp(self.opt_arg_struct)
2602 class PythonCapiFunctionNode(ExprNode):
2603 subexprs = []
2604 def __init__(self, pos, name, func_type, utility_code = None):
2605 self.pos = pos
2606 self.name = name
2607 self.type = func_type
2608 self.utility_code = utility_code
2610 def generate_result_code(self, code):
2611 if self.utility_code:
2612 code.globalstate.use_utility_code(self.utility_code)
2614 def calculate_result_code(self):
2615 return self.name
2617 class PythonCapiCallNode(SimpleCallNode):
2618 # Python C-API Function call (only created in transforms)
2620 def __init__(self, pos, function_name, func_type,
2621 utility_code = None, **kwargs):
2622 self.type = func_type.return_type
2623 self.result_ctype = self.type
2624 self.function = PythonCapiFunctionNode(
2625 pos, function_name, func_type,
2626 utility_code = utility_code)
2627 # call this last so that we can override the constructed
2628 # attributes above with explicit keyword arguments if required
2629 SimpleCallNode.__init__(self, pos, **kwargs)
2632 class GeneralCallNode(CallNode):
2633 # General Python function call, including keyword,
2634 # * and ** arguments.
2636 # function ExprNode
2637 # positional_args ExprNode Tuple of positional arguments
2638 # keyword_args ExprNode or None Dict of keyword arguments
2639 # starstar_arg ExprNode or None Dict of extra keyword args
2641 type = py_object_type
2643 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2645 nogil_check = Node.gil_error
2647 def compile_time_value(self, denv):
2648 function = self.function.compile_time_value(denv)
2649 positional_args = self.positional_args.compile_time_value(denv)
2650 keyword_args = self.keyword_args.compile_time_value(denv)
2651 starstar_arg = self.starstar_arg.compile_time_value(denv)
2652 try:
2653 keyword_args.update(starstar_arg)
2654 return function(*positional_args, **keyword_args)
2655 except Exception, e:
2656 self.compile_time_value_error(e)
2658 def explicit_args_kwds(self):
2659 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2660 raise PostParseError(self.pos,
2661 'Compile-time keyword arguments must be explicit.')
2662 return self.positional_args.args, self.keyword_args
2664 def analyse_types(self, env):
2665 if self.analyse_as_type_constructor(env):
2666 return
2667 self.function.analyse_types(env)
2668 self.positional_args.analyse_types(env)
2669 if self.keyword_args:
2670 self.keyword_args.analyse_types(env)
2671 if self.starstar_arg:
2672 self.starstar_arg.analyse_types(env)
2673 if not self.function.type.is_pyobject:
2674 if self.function.type.is_error:
2675 self.type = error_type
2676 return error_type
2677 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2678 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2679 else:
2680 self.function = self.function.coerce_to_pyobject(env)
2681 self.positional_args = \
2682 self.positional_args.coerce_to_pyobject(env)
2683 if self.starstar_arg:
2684 self.starstar_arg = \
2685 self.starstar_arg.coerce_to_pyobject(env)
2686 function = self.function
2687 if function.is_name and function.type_entry:
2688 # We are calling an extension type constructor. As long
2689 # as we do not support __new__(), the result type is clear
2690 self.type = function.type_entry.type
2691 self.result_ctype = py_object_type
2692 else:
2693 self.type = py_object_type
2694 self.is_temp = 1
2696 def generate_result_code(self, code):
2697 if self.type.is_error: return
2698 if self.keyword_args and self.starstar_arg:
2699 code.put_error_if_neg(self.pos,
2700 "PyDict_Update(%s, %s)" % (
2701 self.keyword_args.py_result(),
2702 self.starstar_arg.py_result()))
2703 keyword_code = self.keyword_args.py_result()
2704 elif self.keyword_args:
2705 keyword_code = self.keyword_args.py_result()
2706 elif self.starstar_arg:
2707 keyword_code = self.starstar_arg.py_result()
2708 else:
2709 keyword_code = None
2710 if not keyword_code:
2711 call_code = "PyObject_Call(%s, %s, NULL)" % (
2712 self.function.py_result(),
2713 self.positional_args.py_result())
2714 else:
2715 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2716 self.function.py_result(),
2717 self.positional_args.py_result(),
2718 keyword_code)
2719 code.putln(
2720 "%s = %s; %s" % (
2721 self.result(),
2722 call_code,
2723 code.error_goto_if_null(self.result(), self.pos)))
2724 code.put_gotref(self.py_result())
2727 class AsTupleNode(ExprNode):
2728 # Convert argument to tuple. Used for normalising
2729 # the * argument of a function call.
2731 # arg ExprNode
2733 subexprs = ['arg']
2735 def calculate_constant_result(self):
2736 self.constant_result = tuple(self.base.constant_result)
2738 def compile_time_value(self, denv):
2739 arg = self.arg.compile_time_value(denv)
2740 try:
2741 return tuple(arg)
2742 except Exception, e:
2743 self.compile_time_value_error(e)
2745 def analyse_types(self, env):
2746 self.arg.analyse_types(env)
2747 self.arg = self.arg.coerce_to_pyobject(env)
2748 self.type = tuple_type
2749 self.is_temp = 1
2751 nogil_check = Node.gil_error
2752 gil_message = "Constructing Python tuple"
2754 def generate_result_code(self, code):
2755 code.putln(
2756 "%s = PySequence_Tuple(%s); %s" % (
2757 self.result(),
2758 self.arg.py_result(),
2759 code.error_goto_if_null(self.result(), self.pos)))
2760 code.put_gotref(self.py_result())
2763 class AttributeNode(ExprNode):
2764 # obj.attribute
2766 # obj ExprNode
2767 # attribute string
2768 # needs_none_check boolean Used if obj is an extension type.
2769 # If set to True, it is known that the type is not None.
2771 # Used internally:
2773 # is_py_attr boolean Is a Python getattr operation
2774 # member string C name of struct member
2775 # is_called boolean Function call is being done on result
2776 # entry Entry Symbol table entry of attribute
2778 is_attribute = 1
2779 subexprs = ['obj']
2781 type = PyrexTypes.error_type
2782 entry = None
2783 is_called = 0
2784 needs_none_check = True
2786 def as_cython_attribute(self):
2787 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2788 return self.attribute
2790 def coerce_to(self, dst_type, env):
2791 # If coercing to a generic pyobject and this is a cpdef function
2792 # we can create the corresponding attribute
2793 if dst_type is py_object_type:
2794 entry = self.entry
2795 if entry and entry.is_cfunction and entry.as_variable:
2796 # must be a cpdef function
2797 self.is_temp = 1
2798 self.entry = entry.as_variable
2799 self.analyse_as_python_attribute(env)
2800 return self
2801 return ExprNode.coerce_to(self, dst_type, env)
2803 def calculate_constant_result(self):
2804 attr = self.attribute
2805 if attr.startswith("__") and attr.endswith("__"):
2806 return
2807 self.constant_result = getattr(self.obj.constant_result, attr)
2809 def compile_time_value(self, denv):
2810 attr = self.attribute
2811 if attr.startswith("__") and attr.endswith("__"):
2812 error(self.pos,
2813 "Invalid attribute name '%s' in compile-time expression" % attr)
2814 return None
2815 obj = self.obj.compile_time_value(denv)
2816 try:
2817 return getattr(obj, attr)
2818 except Exception, e:
2819 self.compile_time_value_error(e)
2821 def type_dependencies(self, env):
2822 return self.obj.type_dependencies(env)
2824 def infer_type(self, env):
2825 if self.analyse_as_cimported_attribute(env, 0):
2826 return self.entry.type
2827 elif self.analyse_as_unbound_cmethod(env):
2828 return self.entry.type
2829 else:
2830 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2831 return self.type
2833 def analyse_target_declaration(self, env):
2834 pass
2836 def analyse_target_types(self, env):
2837 self.analyse_types(env, target = 1)
2839 def analyse_types(self, env, target = 0):
2840 if self.analyse_as_cimported_attribute(env, target):
2841 return
2842 if not target and self.analyse_as_unbound_cmethod(env):
2843 return
2844 self.analyse_as_ordinary_attribute(env, target)
2846 def analyse_as_cimported_attribute(self, env, target):
2847 # Try to interpret this as a reference to an imported
2848 # C const, type, var or function. If successful, mutates
2849 # this node into a NameNode and returns 1, otherwise
2850 # returns 0.
2851 module_scope = self.obj.analyse_as_module(env)
2852 if module_scope:
2853 entry = module_scope.lookup_here(self.attribute)
2854 if entry and (
2855 entry.is_cglobal or entry.is_cfunction
2856 or entry.is_type or entry.is_const):
2857 self.mutate_into_name_node(env, entry, target)
2858 return 1
2859 return 0
2861 def analyse_as_unbound_cmethod(self, env):
2862 # Try to interpret this as a reference to an unbound
2863 # C method of an extension type. If successful, mutates
2864 # this node into a NameNode and returns 1, otherwise
2865 # returns 0.
2866 type = self.obj.analyse_as_extension_type(env)
2867 if type:
2868 entry = type.scope.lookup_here(self.attribute)
2869 if entry and entry.is_cmethod:
2870 # Create a temporary entry describing the C method
2871 # as an ordinary function.
2872 ubcm_entry = Symtab.Entry(entry.name,
2873 "%s->%s" % (type.vtabptr_cname, entry.cname),
2874 entry.type)
2875 ubcm_entry.is_cfunction = 1
2876 ubcm_entry.func_cname = entry.func_cname
2877 ubcm_entry.is_unbound_cmethod = 1
2878 self.mutate_into_name_node(env, ubcm_entry, None)
2879 return 1
2880 return 0
2882 def analyse_as_type(self, env):
2883 module_scope = self.obj.analyse_as_module(env)
2884 if module_scope:
2885 return module_scope.lookup_type(self.attribute)
2886 return None
2888 def analyse_as_extension_type(self, env):
2889 # Try to interpret this as a reference to an extension type
2890 # in a cimported module. Returns the extension type, or None.
2891 module_scope = self.obj.analyse_as_module(env)
2892 if module_scope:
2893 entry = module_scope.lookup_here(self.attribute)
2894 if entry and entry.is_type and entry.type.is_extension_type:
2895 return entry.type
2896 return None
2898 def analyse_as_module(self, env):
2899 # Try to interpret this as a reference to a cimported module
2900 # in another cimported module. Returns the module scope, or None.
2901 module_scope = self.obj.analyse_as_module(env)
2902 if module_scope:
2903 entry = module_scope.lookup_here(self.attribute)
2904 if entry and entry.as_module:
2905 return entry.as_module
2906 return None
2908 def mutate_into_name_node(self, env, entry, target):
2909 # Mutate this node into a NameNode and complete the
2910 # analyse_types phase.
2911 self.__class__ = NameNode
2912 self.name = self.attribute
2913 self.entry = entry
2914 del self.obj
2915 del self.attribute
2916 if target:
2917 NameNode.analyse_target_types(self, env)
2918 else:
2919 NameNode.analyse_rvalue_entry(self, env)
2921 def analyse_as_ordinary_attribute(self, env, target):
2922 self.obj.analyse_types(env)
2923 self.analyse_attribute(env)
2924 if self.entry and self.entry.is_cmethod and not self.is_called:
2925 # error(self.pos, "C method can only be called")
2926 pass
2927 ## Reference to C array turns into pointer to first element.
2928 #while self.type.is_array:
2929 # self.type = self.type.element_ptr_type()
2930 if self.is_py_attr:
2931 if not target:
2932 self.is_temp = 1
2933 self.result_ctype = py_object_type
2935 def analyse_attribute(self, env, obj_type = None):
2936 # Look up attribute and set self.type and self.member.
2937 self.is_py_attr = 0
2938 self.member = self.attribute
2939 if obj_type is None:
2940 if self.obj.type.is_string:
2941 self.obj = self.obj.coerce_to_pyobject(env)
2942 obj_type = self.obj.type
2943 else:
2944 if obj_type.is_string:
2945 obj_type = py_object_type
2946 if obj_type.is_ptr or obj_type.is_array:
2947 obj_type = obj_type.base_type
2948 self.op = "->"
2949 elif obj_type.is_extension_type:
2950 self.op = "->"
2951 else:
2952 self.op = "."
2953 if obj_type.has_attributes:
2954 entry = None
2955 if obj_type.attributes_known():
2956 entry = obj_type.scope.lookup_here(self.attribute)
2957 if entry and entry.is_member:
2958 entry = None
2959 else:
2960 error(self.pos,
2961 "Cannot select attribute of incomplete type '%s'"
2962 % obj_type)
2963 self.type = PyrexTypes.error_type
2964 return
2965 self.entry = entry
2966 if entry:
2967 if obj_type.is_extension_type and entry.name == "__weakref__":
2968 error(self.pos, "Illegal use of special attribute __weakref__")
2969 # methods need the normal attribute lookup
2970 # because they do not have struct entries
2971 if entry.is_variable or entry.is_cmethod:
2972 self.type = entry.type
2973 self.member = entry.cname
2974 return
2975 else:
2976 # If it's not a variable or C method, it must be a Python
2977 # method of an extension type, so we treat it like a Python
2978 # attribute.
2979 pass
2980 # If we get here, the base object is not a struct/union/extension
2981 # type, or it is an extension type and the attribute is either not
2982 # declared or is declared as a Python method. Treat it as a Python
2983 # attribute reference.
2984 self.analyse_as_python_attribute(env, obj_type)
2986 def analyse_as_python_attribute(self, env, obj_type = None):
2987 if obj_type is None:
2988 obj_type = self.obj.type
2989 self.member = self.attribute
2990 if obj_type.is_pyobject:
2991 self.type = py_object_type
2992 self.is_py_attr = 1
2993 else:
2994 if not obj_type.is_error:
2995 error(self.pos,
2996 "Object of type '%s' has no attribute '%s'" %
2997 (obj_type, self.attribute))
2999 def nogil_check(self, env):
3000 if self.is_py_attr:
3001 self.gil_error()
3003 gil_message = "Accessing Python attribute"
3005 def is_simple(self):
3006 if self.obj:
3007 return self.result_in_temp() or self.obj.is_simple()
3008 else:
3009 return NameNode.is_simple(self)
3011 def is_lvalue(self):
3012 if self.obj:
3013 return 1
3014 else:
3015 return NameNode.is_lvalue(self)
3017 def is_ephemeral(self):
3018 if self.obj:
3019 return self.obj.is_ephemeral()
3020 else:
3021 return NameNode.is_ephemeral(self)
3023 def calculate_result_code(self):
3024 #print "AttributeNode.calculate_result_code:", self.member ###
3025 #print "...obj node =", self.obj, "code", self.obj.result() ###
3026 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3027 obj = self.obj
3028 obj_code = obj.result_as(obj.type)
3029 #print "...obj_code =", obj_code ###
3030 if self.entry and self.entry.is_cmethod:
3031 if obj.type.is_extension_type:
3032 return "((struct %s *)%s%s%s)->%s" % (
3033 obj.type.vtabstruct_cname, obj_code, self.op,
3034 obj.type.vtabslot_cname, self.member)
3035 else:
3036 return self.member
3037 elif obj.type.is_complex:
3038 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3039 else:
3040 return "%s%s%s" % (obj_code, self.op, self.member)
3042 def generate_result_code(self, code):
3043 interned_attr_cname = code.intern_identifier(self.attribute)
3044 if self.is_py_attr:
3045 code.putln(
3046 '%s = PyObject_GetAttr(%s, %s); %s' % (
3047 self.result(),
3048 self.obj.py_result(),
3049 interned_attr_cname,
3050 code.error_goto_if_null(self.result(), self.pos)))
3051 code.put_gotref(self.py_result())
3052 else:
3053 # result_code contains what is needed, but we may need to insert
3054 # a check and raise an exception
3055 if (self.obj.type.is_extension_type
3056 and self.needs_none_check
3057 and code.globalstate.directives['nonecheck']):
3058 self.put_nonecheck(code)
3060 def generate_assignment_code(self, rhs, code):
3061 interned_attr_cname = code.intern_identifier(self.attribute)
3062 self.obj.generate_evaluation_code(code)
3063 if self.is_py_attr:
3064 code.put_error_if_neg(self.pos,
3065 'PyObject_SetAttr(%s, %s, %s)' % (
3066 self.obj.py_result(),
3067 interned_attr_cname,
3068 rhs.py_result()))
3069 rhs.generate_disposal_code(code)
3070 rhs.free_temps(code)
3071 else:
3072 if (self.obj.type.is_extension_type
3073 and self.needs_none_check
3074 and code.globalstate.directives['nonecheck']):
3075 self.put_nonecheck(code)
3077 select_code = self.result()
3078 if self.type.is_pyobject:
3079 rhs.make_owned_reference(code)
3080 code.put_giveref(rhs.py_result())
3081 code.put_gotref(select_code)
3082 code.put_decref(select_code, self.ctype())
3083 code.putln(
3084 "%s = %s;" % (
3085 select_code,
3086 rhs.result_as(self.ctype())))
3087 #rhs.result()))
3088 rhs.generate_post_assignment_code(code)
3089 rhs.free_temps(code)
3090 self.obj.generate_disposal_code(code)
3091 self.obj.free_temps(code)
3093 def generate_deletion_code(self, code):
3094 interned_attr_cname = code.intern_identifier(self.attribute)
3095 self.obj.generate_evaluation_code(code)
3096 if self.is_py_attr:
3097 code.put_error_if_neg(self.pos,
3098 'PyObject_DelAttr(%s, %s)' % (
3099 self.obj.py_result(),
3100 interned_attr_cname))
3101 else:
3102 error(self.pos, "Cannot delete C attribute of extension type")
3103 self.obj.generate_disposal_code(code)
3104 self.obj.free_temps(code)
3106 def annotate(self, code):
3107 if self.is_py_attr:
3108 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3109 else:
3110 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3112 def put_nonecheck(self, code):
3113 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3114 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3115 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3116 code.putln(code.error_goto(self.pos))
3117 code.putln("}")
3120 #-------------------------------------------------------------------
3122 # Constructor nodes
3124 #-------------------------------------------------------------------
3126 class StarredTargetNode(ExprNode):
3127 # A starred expression like "*a"
3129 # This is only allowed in sequence assignment targets such as
3131 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3133 # and will be removed during type analysis (or generate an error
3134 # if it's found at unexpected places).
3136 # target ExprNode
3138 subexprs = ['target']
3139 is_starred = 1
3140 type = py_object_type
3141 is_temp = 1
3143 def __init__(self, pos, target):
3144 self.pos = pos
3145 self.target = target
3147 def analyse_declarations(self, env):
3148 error(self.pos, "can use starred expression only as assignment target")
3149 self.target.analyse_declarations(env)
3151 def analyse_types(self, env):
3152 error(self.pos, "can use starred expression only as assignment target")
3153 self.target.analyse_types(env)
3154 self.type = self.target.type
3156 def analyse_target_declaration(self, env):
3157 self.target.analyse_target_declaration(env)
3159 def analyse_target_types(self, env):
3160 self.target.analyse_target_types(env)
3161 self.type = self.target.type
3163 def calculate_result_code(self):
3164 return ""
3166 def generate_result_code(self, code):
3167 pass
3170 class SequenceNode(ExprNode):
3171 # Base class for list and tuple constructor nodes.
3172 # Contains common code for performing sequence unpacking.
3174 # args [ExprNode]
3175 # iterator ExprNode
3176 # unpacked_items [ExprNode] or None
3177 # coerced_unpacked_items [ExprNode] or None
3179 subexprs = ['args']
3181 is_sequence_constructor = 1
3182 unpacked_items = None
3184 def compile_time_value_list(self, denv):
3185 return [arg.compile_time_value(denv) for arg in self.args]
3187 def replace_starred_target_node(self):
3188 # replace a starred node in the targets by the contained expression
3189 self.starred_assignment = False
3190 args = []
3191 for arg in self.args:
3192 if arg.is_starred:
3193 if self.starred_assignment:
3194 error(arg.pos, "more than 1 starred expression in assignment")
3195 self.starred_assignment = True
3196 arg = arg.target
3197 arg.is_starred = True
3198 args.append(arg)
3199 self.args = args
3201 def analyse_target_declaration(self, env):
3202 self.replace_starred_target_node()
3203 for arg in self.args:
3204 arg.analyse_target_declaration(env)
3206 def analyse_types(self, env, skip_children=False):
3207 for i in range(len(self.args)):
3208 arg = self.args[i]
3209 if not skip_children: arg.analyse_types(env)
3210 self.args[i] = arg.coerce_to_pyobject(env)
3211 self.type = py_object_type
3212 self.is_temp = 1
3214 def analyse_target_types(self, env):
3215 self.iterator = PyTempNode(self.pos, env)
3216 self.unpacked_items = []
3217 self.coerced_unpacked_items = []
3218 for arg in self.args:
3219 arg.analyse_target_types(env)
3220 if arg.is_starred:
3221 if not arg.type.assignable_from(Builtin.list_type):
3222 error(arg.pos,
3223 "starred target must have Python object (list) type")
3224 if arg.type is py_object_type:
3225 arg.type = Builtin.list_type
3226 unpacked_item = PyTempNode(self.pos, env)
3227 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3228 self.unpacked_items.append(unpacked_item)
3229 self.coerced_unpacked_items.append(coerced_unpacked_item)
3230 self.type = py_object_type
3232 def generate_result_code(self, code):
3233 self.generate_operation_code(code)
3235 def generate_assignment_code(self, rhs, code):
3236 if self.starred_assignment:
3237 self.generate_starred_assignment_code(rhs, code)
3238 else:
3239 self.generate_parallel_assignment_code(rhs, code)
3241 for item in self.unpacked_items:
3242 item.release(code)
3243 rhs.free_temps(code)
3245 def generate_parallel_assignment_code(self, rhs, code):
3246 # Need to work around the fact that generate_evaluation_code
3247 # allocates the temps in a rather hacky way -- the assignment
3248 # is evaluated twice, within each if-block.
3250 code.globalstate.use_utility_code(unpacking_utility_code)
3252 if rhs.type is tuple_type:
3253 tuple_check = "likely(%s != Py_None)"
3254 else:
3255 tuple_check = "PyTuple_CheckExact(%s)"
3256 code.putln(
3257 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3258 tuple_check % rhs.py_result(),
3259 rhs.py_result(),
3260 len(self.args)))
3261 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3262 for item in self.unpacked_items:
3263 item.allocate(code)
3264 for i in range(len(self.args)):
3265 item = self.unpacked_items[i]
3266 code.put(
3267 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3268 item.result(),
3269 i))
3270 code.put_incref(item.result(), item.ctype())
3271 value_node = self.coerced_unpacked_items[i]
3272 value_node.generate_evaluation_code(code)
3273 rhs.generate_disposal_code(code)
3275 for i in range(len(self.args)):
3276 self.args[i].generate_assignment_code(
3277 self.coerced_unpacked_items[i], code)
3279 code.putln("} else {")
3281 if rhs.type is tuple_type:
3282 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3283 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3284 rhs.py_result(), len(self.args)))
3285 code.putln(code.error_goto(self.pos))
3286 else:
3287 self.iterator.allocate(code)
3288 code.putln(
3289 "%s = PyObject_GetIter(%s); %s" % (
3290 self.iterator.result(),
3291 rhs.py_result(),
3292 code.error_goto_if_null(self.iterator.result(), self.pos)))
3293 code.put_gotref(self.iterator.py_result())
3294 rhs.generate_disposal_code(code)
3295 for i in range(len(self.args)):
3296 item = self.unpacked_items[i]
3297 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3298 self.iterator.py_result(), i)
3299 code.putln(
3300 "%s = %s; %s" % (
3301 item.result(),
3302 typecast(item.ctype(), py_object_type, unpack_code),
3303 code.error_goto_if_null(item.result(), self.pos)))
3304 code.put_gotref(item.py_result())
3305 value_node = self.coerced_unpacked_items[i]
3306 value_node.generate_evaluation_code(code)
3307 code.put_error_if_neg(self.pos,
3308 "__Pyx_EndUnpack(%s)" % (
3309 self.iterator.py_result()))
3310 if debug_disposal_code:
3311 print("UnpackNode.generate_assignment_code:")
3312 print("...generating disposal code for %s" % self.iterator)
3313 self.iterator.generate_disposal_code(code)
3314 self.iterator.free_temps(code)
3315 self.iterator.release(code)
3317 for i in range(len(self.args)):
3318 self.args[i].generate_assignment_code(
3319 self.coerced_unpacked_items[i], code)
3321 code.putln("}")
3323 def generate_starred_assignment_code(self, rhs, code):
3324 code.globalstate.use_utility_code(unpacking_utility_code)
3326 for i, arg in enumerate(self.args):
3327 if arg.is_starred:
3328 starred_target = self.unpacked_items[i]
3329 fixed_args_left = self.args[:i]
3330 fixed_args_right = self.args[i+1:]
3331 break
3333 self.iterator.allocate(code)
3334 code.putln(
3335 "%s = PyObject_GetIter(%s); %s" % (
3336 self.iterator.result(),
3337 rhs.py_result(),
3338 code.error_goto_if_null(self.iterator.result(), self.pos)))
3339 code.put_gotref(self.iterator.py_result())
3340 rhs.generate_disposal_code(code)
3342 for item in self.unpacked_items:
3343 item.allocate(code)
3344 for i in range(len(fixed_args_left)):
3345 item = self.unpacked_items[i]
3346 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3347 self.iterator.py_result(), i)
3348 code.putln(
3349 "%s = %s; %s" % (
3350 item.result(),
3351 typecast(item.ctype(), py_object_type, unpack_code),
3352 code.error_goto_if_null(item.result(), self.pos)))
3353 code.put_gotref(item.py_result())
3354 value_node = self.coerced_unpacked_items[i]
3355 value_node.generate_evaluation_code(code)
3357 target_list = starred_target.result()
3358 code.putln("%s = PySequence_List(%s); %s" % (
3359 target_list, self.iterator.py_result(),
3360 code.error_goto_if_null(target_list, self.pos)))
3361 code.put_gotref(target_list)
3362 if fixed_args_right:
3363 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3364 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3365 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3366 (target_list, len(unpacked_right_args))))
3367 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3368 len(fixed_args_left), target_list,
3369 code.error_goto(self.pos)))
3370 code.putln('}')
3371 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3372 self.coerced_unpacked_items[::-1])):
3373 code.putln(
3374 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3375 arg.py_result(),
3376 target_list, target_list))
3377 # resize the list the hard way
3378 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3379 code.put_gotref(arg.py_result())
3380 coerced_arg.generate_evaluation_code(code)
3382 self.iterator.generate_disposal_code(code)
3383 self.iterator.free_temps(code)
3384 self.iterator.release(code)
3386 for i in range(len(self.args)):
3387 self.args[i].generate_assignment_code(
3388 self.coerced_unpacked_items[i], code)
3390 def annotate(self, code):
3391 for arg in self.args:
3392 arg.annotate(code)
3393 if self.unpacked_items:
3394 for arg in self.unpacked_items:
3395 arg.annotate(code)
3396 for arg in self.coerced_unpacked_items:
3397 arg.annotate(code)
3400 class TupleNode(SequenceNode):
3401 # Tuple constructor.
3403 type = tuple_type
3405 gil_message = "Constructing Python tuple"
3407 def analyse_types(self, env, skip_children=False):
3408 if len(self.args) == 0:
3409 self.is_temp = 0
3410 self.is_literal = 1
3411 else:
3412 SequenceNode.analyse_types(self, env, skip_children)
3414 def calculate_result_code(self):
3415 if len(self.args) > 0:
3416 error(self.pos, "Positive length tuples must be constructed.")
3417 else:
3418 return Naming.empty_tuple
3420 def calculate_constant_result(self):
3421 self.constant_result = tuple([
3422 arg.constant_result for arg in self.args])
3424 def compile_time_value(self, denv):
3425 values = self.compile_time_value_list(denv)
3426 try:
3427 return tuple(values)
3428 except Exception, e:
3429 self.compile_time_value_error(e)
3431 def generate_operation_code(self, code):
3432 if len(self.args) == 0:
3433 # result_code is Naming.empty_tuple
3434 return
3435 code.putln(
3436 "%s = PyTuple_New(%s); %s" % (
3437 self.result(),
3438 len(self.args),
3439 code.error_goto_if_null(self.result(), self.pos)))
3440 code.put_gotref(self.py_result())
3441 for i in range(len(self.args)):
3442 arg = self.args[i]
3443 if not arg.result_in_temp():
3444 code.put_incref(arg.result(), arg.ctype())
3445 code.putln(
3446 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3447 self.result(),
3448 i,
3449 arg.py_result()))
3450 code.put_giveref(arg.py_result())
3452 def generate_subexpr_disposal_code(self, code):
3453 # We call generate_post_assignment_code here instead
3454 # of generate_disposal_code, because values were stored
3455 # in the tuple using a reference-stealing operation.
3456 for arg in self.args:
3457 arg.generate_post_assignment_code(code)
3458 # Should NOT call free_temps -- this is invoked by the default
3459 # generate_evaluation_code which will do that.
3462 class ListNode(SequenceNode):
3463 # List constructor.
3465 # obj_conversion_errors [PyrexError] used internally
3466 # orignial_args [ExprNode] used internally
3468 obj_conversion_errors = []
3470 gil_message = "Constructing Python list"
3472 def type_dependencies(self, env):
3473 return ()
3475 def infer_type(self, env):
3476 # TOOD: Infer non-object list arrays.
3477 return list_type
3479 def analyse_expressions(self, env):
3480 SequenceNode.analyse_expressions(self, env)
3481 self.coerce_to_pyobject(env)
3483 def analyse_types(self, env):
3484 hold_errors()
3485 self.original_args = list(self.args)
3486 SequenceNode.analyse_types(self, env)
3487 self.type = list_type
3488 self.obj_conversion_errors = held_errors()
3489 release_errors(ignore=True)
3491 def coerce_to(self, dst_type, env):
3492 if dst_type.is_pyobject:
3493 for err in self.obj_conversion_errors:
3494 report_error(err)
3495 self.obj_conversion_errors = []
3496 if not self.type.subtype_of(dst_type):
3497 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3498 elif dst_type.is_ptr:
3499 base_type = dst_type.base_type
3500 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3501 for i in range(len(self.original_args)):
3502 arg = self.args[i]
3503 if isinstance(arg, CoerceToPyTypeNode):
3504 arg = arg.arg
3505 self.args[i] = arg.coerce_to(base_type, env)
3506 elif dst_type.is_struct:
3507 if len(self.args) > len(dst_type.scope.var_entries):
3508 error(self.pos, "Too may members for '%s'" % dst_type)
3509 else:
3510 if len(self.args) < len(dst_type.scope.var_entries):
3511 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3512 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3513 if isinstance(arg, CoerceToPyTypeNode):
3514 arg = arg.arg
3515 self.args[i] = arg.coerce_to(member.type, env)
3516 self.type = dst_type
3517 else:
3518 self.type = error_type
3519 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3520 return self
3522 def release_temp(self, env):
3523 if self.type.is_array:
3524 # To be valid C++, we must allocate the memory on the stack
3525 # manually and be sure not to reuse it for something else.
3526 pass
3527 else:
3528 SequenceNode.release_temp(self, env)
3530 def calculate_constant_result(self):
3531 self.constant_result = [
3532 arg.constant_result for arg in self.args]
3534 def compile_time_value(self, denv):
3535 return self.compile_time_value_list(denv)
3537 def generate_operation_code(self, code):
3538 if self.type.is_pyobject:
3539 for err in self.obj_conversion_errors:
3540 report_error(err)
3541 code.putln("%s = PyList_New(%s); %s" %
3542 (self.result(),
3543 len(self.args),
3544 code.error_goto_if_null(self.result(), self.pos)))
3545 code.put_gotref(self.py_result())
3546 for i in range(len(self.args)):
3547 arg = self.args[i]
3548 #if not arg.is_temp:
3549 if not arg.result_in_temp():
3550 code.put_incref(arg.result(), arg.ctype())
3551 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3552 (self.result(),
3553 i,
3554 arg.py_result()))
3555 code.put_giveref(arg.py_result())
3556 elif self.type.is_array:
3557 for i, arg in enumerate(self.args):
3558 code.putln("%s[%s] = %s;" % (
3559 self.result(),
3560 i,
3561 arg.result()))
3562 elif self.type.is_struct:
3563 for arg, member in zip(self.args, self.type.scope.var_entries):
3564 code.putln("%s.%s = %s;" % (
3565 self.result(),
3566 member.cname,
3567 arg.result()))
3568 else:
3569 raise InternalError("List type never specified")
3571 def generate_subexpr_disposal_code(self, code):
3572 # We call generate_post_assignment_code here instead
3573 # of generate_disposal_code, because values were stored
3574 # in the list using a reference-stealing operation.
3575 for arg in self.args:
3576 arg.generate_post_assignment_code(code)
3577 # Should NOT call free_temps -- this is invoked by the default
3578 # generate_evaluation_code which will do that.
3581 class ComprehensionNode(ExprNode):
3582 subexprs = ["target"]
3583 child_attrs = ["loop", "append"]
3585 def infer_type(self, env):
3586 return self.target.infer_type(env)
3588 def analyse_types(self, env):
3589 self.target.analyse_expressions(env)
3590 self.type = self.target.type
3591 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3592 # We are analysing declarations to late.
3593 self.loop.target.analyse_target_declaration(env)
3594 env.infer_types()
3595 self.loop.analyse_declarations(env)
3596 self.loop.analyse_expressions(env)
3598 def calculate_result_code(self):
3599 return self.target.result()
3601 def generate_result_code(self, code):
3602 self.generate_operation_code(code)
3604 def generate_operation_code(self, code):
3605 self.loop.generate_execution_code(code)
3607 def annotate(self, code):
3608 self.loop.annotate(code)
3611 class ComprehensionAppendNode(ExprNode):
3612 # Need to be careful to avoid infinite recursion:
3613 # target must not be in child_attrs/subexprs
3614 subexprs = ['expr']
3616 type = PyrexTypes.c_int_type
3618 def analyse_types(self, env):
3619 self.expr.analyse_types(env)
3620 if not self.expr.type.is_pyobject:
3621 self.expr = self.expr.coerce_to_pyobject(env)
3622 self.is_temp = 1
3624 def generate_result_code(self, code):
3625 if self.target.type is list_type:
3626 function = "PyList_Append"
3627 elif self.target.type is set_type:
3628 function = "PySet_Add"
3629 else:
3630 raise InternalError(
3631 "Invalid type for comprehension node: %s" % self.target.type)
3633 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3634 (self.result(),
3635 function,
3636 self.target.result(),
3637 self.expr.result(),
3638 code.error_goto_if(self.result(), self.pos)))
3640 class DictComprehensionAppendNode(ComprehensionAppendNode):
3641 subexprs = ['key_expr', 'value_expr']
3643 def analyse_types(self, env):
3644 self.key_expr.analyse_types(env)
3645 if not self.key_expr.type.is_pyobject:
3646 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3647 self.value_expr.analyse_types(env)
3648 if not self.value_expr.type.is_pyobject:
3649 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3650 self.is_temp = 1
3652 def generate_result_code(self, code):
3653 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3654 (self.result(),
3655 self.target.result(),
3656 self.key_expr.result(),
3657 self.value_expr.result(),
3658 code.error_goto_if(self.result(), self.pos)))
3661 class SetNode(ExprNode):
3662 # Set constructor.
3664 type = set_type
3666 subexprs = ['args']
3668 gil_message = "Constructing Python set"
3670 def analyse_types(self, env):
3671 for i in range(len(self.args)):
3672 arg = self.args[i]
3673 arg.analyse_types(env)
3674 self.args[i] = arg.coerce_to_pyobject(env)
3675 self.type = set_type
3676 self.is_temp = 1
3678 def calculate_constant_result(self):
3679 self.constant_result = set([
3680 arg.constant_result for arg in self.args])
3682 def compile_time_value(self, denv):
3683 values = [arg.compile_time_value(denv) for arg in self.args]
3684 try:
3685 return set(values)
3686 except Exception, e:
3687 self.compile_time_value_error(e)
3689 def generate_evaluation_code(self, code):
3690 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3691 self.allocate_temp_result(code)
3692 code.putln(
3693 "%s = PySet_New(0); %s" % (
3694 self.result(),
3695 code.error_goto_if_null(self.result(), self.pos)))
3696 code.put_gotref(self.py_result())
3697 for arg in self.args:
3698 arg.generate_evaluation_code(code)
3699 code.putln(
3700 code.error_goto_if_neg(
3701 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3702 self.pos))
3703 arg.generate_disposal_code(code)
3704 arg.free_temps(code)
3707 class DictNode(ExprNode):
3708 # Dictionary constructor.
3710 # key_value_pairs [DictItemNode]
3712 # obj_conversion_errors [PyrexError] used internally
3714 subexprs = ['key_value_pairs']
3715 is_temp = 1
3716 type = dict_type
3718 type = dict_type
3719 obj_conversion_errors = []
3721 def calculate_constant_result(self):
3722 self.constant_result = dict([
3723 item.constant_result for item in self.key_value_pairs])
3725 def compile_time_value(self, denv):
3726 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3727 for item in self.key_value_pairs]
3728 try:
3729 return dict(pairs)
3730 except Exception, e:
3731 self.compile_time_value_error(e)
3733 def type_dependencies(self, env):
3734 return ()
3736 def infer_type(self, env):
3737 # TOOD: Infer struct constructors.
3738 return dict_type
3740 def analyse_types(self, env):
3741 hold_errors()
3742 for item in self.key_value_pairs:
3743 item.analyse_types(env)
3744 self.obj_conversion_errors = held_errors()
3745 release_errors(ignore=True)
3747 def coerce_to(self, dst_type, env):
3748 if dst_type.is_pyobject:
3749 self.release_errors()
3750 if not self.type.subtype_of(dst_type):
3751 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3752 elif dst_type.is_struct_or_union:
3753 self.type = dst_type
3754 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3755 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3756 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3757 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3758 for item in self.key_value_pairs:
3759 if isinstance(item.key, CoerceToPyTypeNode):
3760 item.key = item.key.arg
3761 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3762 error(item.key.pos, "Invalid struct field identifier")
3763 item.key = StringNode(item.key.pos, value="<error>")
3764 else:
3765 key = str(item.key.value) # converts string literals to unicode in Py3
3766 member = dst_type.scope.lookup_here(key)
3767 if not member:
3768 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3769 else:
3770 value = item.value
3771 if isinstance(value, CoerceToPyTypeNode):
3772 value = value.arg
3773 item.value = value.coerce_to(member.type, env)
3774 else:
3775 self.type = error_type
3776 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3777 return self
3779 def release_errors(self):
3780 for err in self.obj_conversion_errors:
3781 report_error(err)
3782 self.obj_conversion_errors = []
3784 gil_message = "Constructing Python dict"
3786 def generate_evaluation_code(self, code):
3787 # Custom method used here because key-value
3788 # pairs are evaluated and used one at a time.
3789 code.mark_pos(self.pos)
3790 self.allocate_temp_result(code)
3791 if self.type.is_pyobject:
3792 self.release_errors()
3793 code.putln(
3794 "%s = PyDict_New(); %s" % (
3795 self.result(),
3796 code.error_goto_if_null(self.result(), self.pos)))
3797 code.put_gotref(self.py_result())
3798 for item in self.key_value_pairs:
3799 item.generate_evaluation_code(code)
3800 if self.type.is_pyobject:
3801 code.put_error_if_neg(self.pos,
3802 "PyDict_SetItem(%s, %s, %s)" % (
3803 self.result(),
3804 item.key.py_result(),
3805 item.value.py_result()))
3806 else:
3807 code.putln("%s.%s = %s;" % (
3808 self.result(),
3809 item.key.value,
3810 item.value.result()))
3811 item.generate_disposal_code(code)
3812 item.free_temps(code)
3814 def annotate(self, code):
3815 for item in self.key_value_pairs:
3816 item.annotate(code)
3818 class DictItemNode(ExprNode):
3819 # Represents a single item in a DictNode
3821 # key ExprNode
3822 # value ExprNode
3823 subexprs = ['key', 'value']
3825 nogil_check = None # Parent DictNode takes care of it
3827 def calculate_constant_result(self):
3828 self.constant_result = (
3829 self.key.constant_result, self.value.constant_result)
3831 def analyse_types(self, env):
3832 self.key.analyse_types(env)
3833 self.value.analyse_types(env)
3834 self.key = self.key.coerce_to_pyobject(env)
3835 self.value = self.value.coerce_to_pyobject(env)
3837 def generate_evaluation_code(self, code):
3838 self.key.generate_evaluation_code(code)
3839 self.value.generate_evaluation_code(code)
3841 def generate_disposal_code(self, code):
3842 self.key.generate_disposal_code(code)
3843 self.value.generate_disposal_code(code)
3845 def free_temps(self, code):
3846 self.key.free_temps(code)
3847 self.value.free_temps(code)
3849 def __iter__(self):
3850 return iter([self.key, self.value])
3853 class ClassNode(ExprNode):
3854 # Helper class used in the implementation of Python
3855 # class definitions. Constructs a class object given
3856 # a name, tuple of bases and class dictionary.
3858 # name EncodedString Name of the class
3859 # bases ExprNode Base class tuple
3860 # dict ExprNode Class dict (not owned by this node)
3861 # doc ExprNode or None Doc string
3862 # module_name string Name of defining module
3864 subexprs = ['bases', 'doc']
3866 def analyse_types(self, env):
3867 self.bases.analyse_types(env)
3868 if self.doc:
3869 self.doc.analyse_types(env)
3870 self.doc = self.doc.coerce_to_pyobject(env)
3871 self.module_name = env.global_scope().qualified_name
3872 self.type = py_object_type
3873 self.is_temp = 1
3874 env.use_utility_code(create_class_utility_code);
3876 gil_message = "Constructing Python class"
3878 def generate_result_code(self, code):
3879 cname = code.intern_identifier(self.name)
3880 if self.doc:
3881 code.put_error_if_neg(self.pos,
3882 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3883 self.dict.py_result(),
3884 self.doc.py_result()))
3885 code.putln(
3886 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3887 self.result(),
3888 self.bases.py_result(),
3889 self.dict.py_result(),
3890 cname,
3891 self.module_name,
3892 code.error_goto_if_null(self.result(), self.pos)))
3893 code.put_gotref(self.py_result())
3896 class UnboundMethodNode(ExprNode):
3897 # Helper class used in the implementation of Python
3898 # class definitions. Constructs an unbound method
3899 # object from a class and a function.
3901 # function ExprNode Function object
3903 type = py_object_type
3904 is_temp = 1
3906 subexprs = ['function']
3908 def analyse_types(self, env):
3909 self.function.analyse_types(env)
3911 gil_message = "Constructing an unbound method"
3913 def generate_result_code(self, code):
3914 class_cname = code.pyclass_stack[-1].classobj.result()
3915 code.putln(
3916 "%s = PyMethod_New(%s, 0, %s); %s" % (
3917 self.result(),
3918 self.function.py_result(),
3919 class_cname,
3920 code.error_goto_if_null(self.result(), self.pos)))
3921 code.put_gotref(self.py_result())
3923 class PyCFunctionNode(AtomicExprNode):
3924 # Helper class used in the implementation of Python
3925 # class definitions. Constructs a PyCFunction object
3926 # from a PyMethodDef struct.
3928 # pymethdef_cname string PyMethodDef structure
3930 type = py_object_type
3931 is_temp = 1
3933 def analyse_types(self, env):
3934 pass
3936 gil_message = "Constructing Python function"
3938 def generate_result_code(self, code):
3939 code.putln(
3940 "%s = PyCFunction_New(&%s, 0); %s" % (
3941 self.result(),
3942 self.pymethdef_cname,
3943 code.error_goto_if_null(self.result(), self.pos)))
3944 code.put_gotref(self.py_result())
3946 #-------------------------------------------------------------------
3948 # Unary operator nodes
3950 #-------------------------------------------------------------------
3952 compile_time_unary_operators = {
3953 'not': operator.not_,
3954 '~': operator.inv,
3955 '-': operator.neg,
3956 '+': operator.pos,
3959 class UnopNode(ExprNode):
3960 # operator string
3961 # operand ExprNode
3963 # Processing during analyse_expressions phase:
3965 # analyse_c_operation
3966 # Called when the operand is not a pyobject.
3967 # - Check operand type and coerce if needed.
3968 # - Determine result type and result code fragment.
3969 # - Allocate temporary for result if needed.
3971 subexprs = ['operand']
3972 infix = True
3974 def calculate_constant_result(self):
3975 func = compile_time_unary_operators[self.operator]
3976 self.constant_result = func(self.operand.constant_result)
3978 def compile_time_value(self, denv):
3979 func = compile_time_unary_operators.get(self.operator)
3980 if not func:
3981 error(self.pos,
3982 "Unary '%s' not supported in compile-time expression"
3983 % self.operator)
3984 operand = self.operand.compile_time_value(denv)
3985 try:
3986 return func(operand)
3987 except Exception, e:
3988 self.compile_time_value_error(e)
3990 def infer_type(self, env):
3991 return self.operand.infer_type(env)
3993 def analyse_types(self, env):
3994 self.operand.analyse_types(env)
3995 if self.is_py_operation():
3996 self.coerce_operand_to_pyobject(env)
3997 self.type = py_object_type
3998 self.is_temp = 1
3999 else:
4000 self.analyse_c_operation(env)
4002 def check_const(self):
4003 self.operand.check_const()
4005 def is_py_operation(self):
4006 return self.operand.type.is_pyobject
4008 def nogil_check(self, env):
4009 if self.is_py_operation():
4010 self.gil_error()
4012 def coerce_operand_to_pyobject(self, env):
4013 self.operand = self.operand.coerce_to_pyobject(env)
4015 def generate_result_code(self, code):
4016 if self.operand.type.is_pyobject:
4017 self.generate_py_operation_code(code)
4019 def generate_py_operation_code(self, code):
4020 function = self.py_operation_function()
4021 code.putln(
4022 "%s = %s(%s); %s" % (
4023 self.result(),
4024 function,
4025 self.operand.py_result(),
4026 code.error_goto_if_null(self.result(), self.pos)))
4027 code.put_gotref(self.py_result())
4029 def type_error(self):
4030 if not self.operand.type.is_error:
4031 error(self.pos, "Invalid operand type for '%s' (%s)" %
4032 (self.operator, self.operand.type))
4033 self.type = PyrexTypes.error_type
4036 class NotNode(ExprNode):
4037 # 'not' operator
4039 # operand ExprNode
4041 type = PyrexTypes.c_bint_type
4043 subexprs = ['operand']
4045 def calculate_constant_result(self):
4046 self.constant_result = not self.operand.constant_result
4048 def compile_time_value(self, denv):
4049 operand = self.operand.compile_time_value(denv)
4050 try:
4051 return not operand
4052 except Exception, e:
4053 self.compile_time_value_error(e)
4055 def infer_type(self, env):
4056 return PyrexTypes.c_bint_type
4058 def analyse_types(self, env):
4059 self.operand.analyse_types(env)
4060 self.operand = self.operand.coerce_to_boolean(env)
4062 def calculate_result_code(self):
4063 return "(!%s)" % self.operand.result()
4065 def generate_result_code(self, code):
4066 pass
4069 class UnaryPlusNode(UnopNode):
4070 # unary '+' operator
4072 operator = '+'
4074 def analyse_c_operation(self, env):
4075 self.type = self.operand.type
4077 def py_operation_function(self):
4078 return "PyNumber_Positive"
4080 def calculate_result_code(self):
4081 return self.operand.result()
4084 class UnaryMinusNode(UnopNode):
4085 # unary '-' operator
4087 operator = '-'
4089 def analyse_c_operation(self, env):
4090 if self.operand.type.is_numeric:
4091 self.type = self.operand.type
4092 else:
4093 self.type_error()
4094 if self.type.is_complex:
4095 self.infix = False
4097 def py_operation_function(self):
4098 return "PyNumber_Negative"
4100 def calculate_result_code(self):
4101 if self.infix:
4102 return "(-%s)" % self.operand.result()
4103 else:
4104 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4106 class TildeNode(UnopNode):
4107 # unary '~' operator
4109 def analyse_c_operation(self, env):
4110 if self.operand.type.is_int:
4111 self.type = self.operand.type
4112 else:
4113 self.type_error()
4115 def py_operation_function(self):
4116 return "PyNumber_Invert"
4118 def calculate_result_code(self):
4119 return "(~%s)" % self.operand.result()
4122 class AmpersandNode(ExprNode):
4123 # The C address-of operator.
4125 # operand ExprNode
4127 subexprs = ['operand']
4129 def infer_type(self, env):
4130 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4132 def analyse_types(self, env):
4133 self.operand.analyse_types(env)
4134 argtype = self.operand.type
4135 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4136 self.error("Taking address of non-lvalue")
4137 return
4138 if argtype.is_pyobject:
4139 self.error("Cannot take address of Python variable")
4140 return
4141 self.type = PyrexTypes.c_ptr_type(argtype)
4143 def check_const(self):
4144 self.operand.check_const_addr()
4146 def error(self, mess):
4147 error(self.pos, mess)
4148 self.type = PyrexTypes.error_type
4149 self.result_code = "<error>"
4151 def calculate_result_code(self):
4152 return "(&%s)" % self.operand.result()
4154 def generate_result_code(self, code):
4155 pass
4158 unop_node_classes = {
4159 "+": UnaryPlusNode,
4160 "-": UnaryMinusNode,
4161 "~": TildeNode,
4164 def unop_node(pos, operator, operand):
4165 # Construct unnop node of appropriate class for
4166 # given operator.
4167 if isinstance(operand, IntNode) and operator == '-':
4168 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4169 elif isinstance(operand, UnopNode) and operand.operator == operator:
4170 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4171 return unop_node_classes[operator](pos,
4172 operator = operator,
4173 operand = operand)
4176 class TypecastNode(ExprNode):
4177 # C type cast
4179 # operand ExprNode
4180 # base_type CBaseTypeNode
4181 # declarator CDeclaratorNode
4183 # If used from a transform, one can if wanted specify the attribute
4184 # "type" directly and leave base_type and declarator to None
4186 subexprs = ['operand']
4187 base_type = declarator = type = None
4189 def type_dependencies(self, env):
4190 return ()
4192 def infer_type(self, env):
4193 if self.type is None:
4194 base_type = self.base_type.analyse(env)
4195 _, self.type = self.declarator.analyse(base_type, env)
4196 return self.type
4198 def analyse_types(self, env):
4199 if self.type is None:
4200 base_type = self.base_type.analyse(env)
4201 _, self.type = self.declarator.analyse(base_type, env)
4202 if self.type.is_cfunction:
4203 error(self.pos,
4204 "Cannot cast to a function type")
4205 self.type = PyrexTypes.error_type
4206 self.operand.analyse_types(env)
4207 to_py = self.type.is_pyobject
4208 from_py = self.operand.type.is_pyobject
4209 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4210 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4211 if to_py and not from_py:
4212 if self.operand.type.create_to_py_utility_code(env):
4213 self.result_ctype = py_object_type
4214 self.operand = self.operand.coerce_to_pyobject(env)
4215 else:
4216 if self.operand.type.is_ptr:
4217 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4218 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4219 else:
4220 # Should this be an error?
4221 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4222 self.operand = self.operand.coerce_to_simple(env)
4223 elif from_py and not to_py:
4224 if self.type.create_from_py_utility_code(env):
4225 self.operand = self.operand.coerce_to(self.type, env)
4226 elif self.type.is_ptr:
4227 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4228 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4229 else:
4230 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4231 elif from_py and to_py:
4232 if self.typecheck and self.type.is_extension_type:
4233 self.operand = PyTypeTestNode(self.operand, self.type, env)
4235 def nogil_check(self, env):
4236 if self.type and self.type.is_pyobject and self.is_temp:
4237 self.gil_error()
4239 def check_const(self):
4240 self.operand.check_const()
4242 def calculate_constant_result(self):
4243 # we usually do not know the result of a type cast at code
4244 # generation time
4245 pass
4247 def calculate_result_code(self):
4248 opnd = self.operand
4249 return self.type.cast_code(opnd.result())
4251 def result_as(self, type):
4252 if self.type.is_pyobject and not self.is_temp:
4253 # Optimise away some unnecessary casting
4254 return self.operand.result_as(type)
4255 else:
4256 return ExprNode.result_as(self, type)
4258 def generate_result_code(self, code):
4259 if self.is_temp:
4260 code.putln(
4261 "%s = (PyObject *)%s;" % (
4262 self.result(),
4263 self.operand.result()))
4264 code.put_incref(self.result(), self.ctype())
4267 class SizeofNode(ExprNode):
4268 # Abstract base class for sizeof(x) expression nodes.
4270 type = PyrexTypes.c_size_t_type
4272 def check_const(self):
4273 pass
4275 def generate_result_code(self, code):
4276 pass
4279 class SizeofTypeNode(SizeofNode):
4280 # C sizeof function applied to a type
4282 # base_type CBaseTypeNode
4283 # declarator CDeclaratorNode
4285 subexprs = []
4286 arg_type = None
4288 def analyse_types(self, env):
4289 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4290 # this could be better handled by more uniformly treating types as runtime-available objects
4291 if 0 and self.base_type.module_path:
4292 path = self.base_type.module_path
4293 obj = env.lookup(path[0])
4294 if obj.as_module is None:
4295 operand = NameNode(pos=self.pos, name=path[0])
4296 for attr in path[1:]:
4297 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4298 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4299 self.operand = operand
4300 self.__class__ = SizeofVarNode
4301 self.analyse_types(env)
4302 return
4303 if self.arg_type is None:
4304 base_type = self.base_type.analyse(env)
4305 _, arg_type = self.declarator.analyse(base_type, env)
4306 self.arg_type = arg_type
4307 self.check_type()
4309 def check_type(self):
4310 arg_type = self.arg_type
4311 if arg_type.is_pyobject and not arg_type.is_extension_type:
4312 error(self.pos, "Cannot take sizeof Python object")
4313 elif arg_type.is_void:
4314 error(self.pos, "Cannot take sizeof void")
4315 elif not arg_type.is_complete():
4316 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4318 def calculate_result_code(self):
4319 if self.arg_type.is_extension_type:
4320 # the size of the pointer is boring
4321 # we want the size of the actual struct
4322 arg_code = self.arg_type.declaration_code("", deref=1)
4323 else:
4324 arg_code = self.arg_type.declaration_code("")
4325 return "(sizeof(%s))" % arg_code
4328 class SizeofVarNode(SizeofNode):
4329 # C sizeof function applied to a variable
4331 # operand ExprNode
4333 subexprs = ['operand']
4335 def analyse_types(self, env):
4336 # We may actually be looking at a type rather than a variable...
4337 # If we are, traditional analysis would fail...
4338 operand_as_type = self.operand.analyse_as_type(env)
4339 if operand_as_type:
4340 self.arg_type = operand_as_type
4341 self.__class__ = SizeofTypeNode
4342 self.check_type()
4343 else:
4344 self.operand.analyse_types(env)
4346 def calculate_result_code(self):
4347 return "(sizeof(%s))" % self.operand.result()
4349 def generate_result_code(self, code):
4350 pass
4352 class TypeofNode(ExprNode):
4353 # Compile-time type of an expression, as a string.
4355 # operand ExprNode
4356 # literal StringNode # internal
4358 literal = None
4359 type = py_object_type
4361 subexprs = ['operand', 'literal']
4363 def analyse_types(self, env):
4364 self.operand.analyse_types(env)
4365 self.literal = StringNode(
4366 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4367 self.literal.analyse_types(env)
4368 self.literal = self.literal.coerce_to_pyobject(env)
4370 def generate_evaluation_code(self, code):
4371 self.literal.generate_evaluation_code(code)
4373 def calculate_result_code(self):
4374 return self.literal.calculate_result_code()
4376 #-------------------------------------------------------------------
4378 # Binary operator nodes
4380 #-------------------------------------------------------------------
4382 def _not_in(x, seq):
4383 return x not in seq
4385 compile_time_binary_operators = {
4386 '<': operator.lt,
4387 '<=': operator.le,
4388 '==': operator.eq,
4389 '!=': operator.ne,
4390 '>=': operator.ge,
4391 '>': operator.gt,
4392 'is': operator.is_,
4393 'is_not': operator.is_not,
4394 '+': operator.add,
4395 '&': operator.and_,
4396 '/': operator.truediv,
4397 '//': operator.floordiv,
4398 '<<': operator.lshift,
4399 '%': operator.mod,
4400 '*': operator.mul,
4401 '|': operator.or_,
4402 '**': operator.pow,
4403 '>>': operator.rshift,
4404 '-': operator.sub,
4405 '^': operator.xor,
4406 'in': operator.contains,
4407 'not_in': _not_in,
4410 def get_compile_time_binop(node):
4411 func = compile_time_binary_operators.get(node.operator)
4412 if not func:
4413 error(node.pos,
4414 "Binary '%s' not supported in compile-time expression"
4415 % node.operator)
4416 return func
4418 class BinopNode(ExprNode):
4419 # operator string
4420 # operand1 ExprNode
4421 # operand2 ExprNode
4423 # Processing during analyse_expressions phase:
4425 # analyse_c_operation
4426 # Called when neither operand is a pyobject.
4427 # - Check operand types and coerce if needed.
4428 # - Determine result type and result code fragment.
4429 # - Allocate temporary for result if needed.
4431 subexprs = ['operand1', 'operand2']
4433 def calculate_constant_result(self):
4434 func = compile_time_binary_operators[self.operator]
4435 self.constant_result = func(
4436 self.operand1.constant_result,
4437 self.operand2.constant_result)
4439 def compile_time_value(self, denv):
4440 func = get_compile_time_binop(self)
4441 operand1 = self.operand1.compile_time_value(denv)
4442 operand2 = self.operand2.compile_time_value(denv)
4443 try:
4444 return func(operand1, operand2)
4445 except Exception, e:
4446 self.compile_time_value_error(e)
4448 def infer_type(self, env):
4449 return self.result_type(self.operand1.infer_type(env),
4450 self.operand2.infer_type(env))
4452 def analyse_types(self, env):
4453 self.operand1.analyse_types(env)
4454 self.operand2.analyse_types(env)
4455 if self.is_py_operation():
4456 self.coerce_operands_to_pyobjects(env)
4457 self.type = py_object_type
4458 self.is_temp = 1
4459 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4460 self.operand1 = self.operand1.coerce_to_temp(env)
4461 else:
4462 self.analyse_c_operation(env)
4464 def is_py_operation(self):
4465 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4467 def is_py_operation_types(self, type1, type2):
4468 return type1.is_pyobject or type2.is_pyobject
4470 def result_type(self, type1, type2):
4471 if self.is_py_operation_types(type1, type2):
4472 return py_object_type
4473 else:
4474 return self.compute_c_result_type(type1, type2)
4476 def nogil_check(self, env):
4477 if self.is_py_operation():
4478 self.gil_error()
4480 def coerce_operands_to_pyobjects(self, env):
4481 self.operand1 = self.operand1.coerce_to_pyobject(env)
4482 self.operand2 = self.operand2.coerce_to_pyobject(env)
4484 def check_const(self):
4485 self.operand1.check_const()
4486 self.operand2.check_const()
4488 def generate_result_code(self, code):
4489 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4490 if self.operand1.type.is_pyobject:
4491 function = self.py_operation_function()
4492 if function == "PyNumber_Power":
4493 extra_args = ", Py_None"
4494 else:
4495 extra_args = ""
4496 code.putln(
4497 "%s = %s(%s, %s%s); %s" % (
4498 self.result(),
4499 function,
4500 self.operand1.py_result(),
4501 self.operand2.py_result(),
4502 extra_args,
4503 code.error_goto_if_null(self.result(), self.pos)))
4504 code.put_gotref(self.py_result())
4506 def type_error(self):
4507 if not (self.operand1.type.is_error
4508 or self.operand2.type.is_error):
4509 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4510 (self.operator, self.operand1.type,
4511 self.operand2.type))
4512 self.type = PyrexTypes.error_type
4515 class NumBinopNode(BinopNode):
4516 # Binary operation taking numeric arguments.
4518 infix = True
4520 def analyse_c_operation(self, env):
4521 type1 = self.operand1.type
4522 type2 = self.operand2.type
4523 self.type = self.compute_c_result_type(type1, type2)
4524 if not self.type:
4525 self.type_error()
4526 return
4527 if self.type.is_complex:
4528 self.infix = False
4529 if not self.infix:
4530 self.operand1 = self.operand1.coerce_to(self.type, env)
4531 self.operand2 = self.operand2.coerce_to(self.type, env)
4533 def compute_c_result_type(self, type1, type2):
4534 if self.c_types_okay(type1, type2):
4535 return PyrexTypes.widest_numeric_type(type1, type2)
4536 else:
4537 return None
4539 def get_constant_c_result_code(self):
4540 value1 = self.operand1.get_constant_c_result_code()
4541 value2 = self.operand2.get_constant_c_result_code()
4542 if value1 and value2:
4543 return "(%s %s %s)" % (value1, self.operator, value2)
4544 else:
4545 return None
4547 def c_types_okay(self, type1, type2):
4548 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4549 return (type1.is_numeric or type1.is_enum) \
4550 and (type2.is_numeric or type2.is_enum)
4552 def calculate_result_code(self):
4553 if self.infix:
4554 return "(%s %s %s)" % (
4555 self.operand1.result(),
4556 self.operator,
4557 self.operand2.result())
4558 else:
4559 func = self.type.binary_op(self.operator)
4560 if func is None:
4561 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4562 return "%s(%s, %s)" % (
4563 func,
4564 self.operand1.result(),
4565 self.operand2.result())
4567 def py_operation_function(self):
4568 return self.py_functions[self.operator]
4570 py_functions = {
4571 "|": "PyNumber_Or",
4572 "^": "PyNumber_Xor",
4573 "&": "PyNumber_And",
4574 "<<": "PyNumber_Lshift",
4575 ">>": "PyNumber_Rshift",
4576 "+": "PyNumber_Add",
4577 "-": "PyNumber_Subtract",
4578 "*": "PyNumber_Multiply",
4579 "/": "__Pyx_PyNumber_Divide",
4580 "//": "PyNumber_FloorDivide",
4581 "%": "PyNumber_Remainder",
4582 "**": "PyNumber_Power"
4586 class IntBinopNode(NumBinopNode):
4587 # Binary operation taking integer arguments.
4589 def c_types_okay(self, type1, type2):
4590 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4591 return (type1.is_int or type1.is_enum) \
4592 and (type2.is_int or type2.is_enum)
4595 class AddNode(NumBinopNode):
4596 # '+' operator.
4598 def is_py_operation_types(self, type1, type2):
4599 if type1.is_string and type2.is_string:
4600 return 1
4601 else:
4602 return NumBinopNode.is_py_operation_types(self, type1, type2)
4604 def compute_c_result_type(self, type1, type2):
4605 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4606 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4607 return type1
4608 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4609 return type2
4610 else:
4611 return NumBinopNode.compute_c_result_type(
4612 self, type1, type2)
4615 class SubNode(NumBinopNode):
4616 # '-' operator.
4618 def compute_c_result_type(self, type1, type2):
4619 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4620 return type1
4621 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4622 return PyrexTypes.c_int_type
4623 else:
4624 return NumBinopNode.compute_c_result_type(
4625 self, type1, type2)
4628 class MulNode(NumBinopNode):
4629 # '*' operator.
4631 def is_py_operation_types(self, type1, type2):
4632 if (type1.is_string and type2.is_int) \
4633 or (type2.is_string and type1.is_int):
4634 return 1
4635 else:
4636 return NumBinopNode.is_py_operation_types(self, type1, type2)
4639 class DivNode(NumBinopNode):
4640 # '/' or '//' operator.
4642 cdivision = None
4643 truedivision = None # == "unknown" if operator == '/'
4644 ctruedivision = False
4645 cdivision_warnings = False
4646 zerodivision_check = None
4648 def find_compile_time_binary_operator(self, op1, op2):
4649 func = compile_time_binary_operators[self.operator]
4650 if self.operator == '/' and self.truedivision is None:
4651 # => true div for floats, floor div for integers
4652 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4653 func = compile_time_binary_operators['//']
4654 return func
4656 def calculate_constant_result(self):
4657 op1 = self.operand1.constant_result
4658 op2 = self.operand2.constant_result
4659 func = self.find_compile_time_binary_operator(op1, op2)
4660 self.constant_result = func(
4661 self.operand1.constant_result,
4662 self.operand2.constant_result)
4664 def compile_time_value(self, denv):
4665 operand1 = self.operand1.compile_time_value(denv)
4666 operand2 = self.operand2.compile_time_value(denv)
4667 try:
4668 func = self.find_compile_time_binary_operator(
4669 self, operand1, operand2)
4670 return func(operand1, operand2)
4671 except Exception, e:
4672 self.compile_time_value_error(e)
4674 def analyse_types(self, env):
4675 if self.cdivision or env.directives['cdivision']:
4676 self.ctruedivision = False
4677 else:
4678 self.ctruedivision = self.truedivision
4679 NumBinopNode.analyse_types(self, env)
4680 if not self.type.is_pyobject:
4681 self.zerodivision_check = (
4682 self.cdivision is None and not env.directives['cdivision']
4683 and (self.operand2.constant_result is not_a_constant or
4684 self.operand2.constant_result == 0))
4685 if self.zerodivision_check or env.directives['cdivision_warnings']:
4686 # Need to check ahead of time to warn or raise zero division error
4687 self.operand1 = self.operand1.coerce_to_simple(env)
4688 self.operand2 = self.operand2.coerce_to_simple(env)
4689 if env.nogil:
4690 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4692 def compute_c_result_type(self, type1, type2):
4693 if self.operator == '/' and self.ctruedivision:
4694 if not type1.is_float and not type2.is_float:
4695 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4696 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4697 return widest_type
4698 return NumBinopNode.compute_c_result_type(self, type1, type2)
4700 def zero_division_message(self):
4701 if self.type.is_int:
4702 return "integer division or modulo by zero"
4703 else:
4704 return "float division"
4706 def generate_evaluation_code(self, code):
4707 if not self.type.is_pyobject and not self.type.is_complex:
4708 if self.cdivision is None:
4709 self.cdivision = (code.globalstate.directives['cdivision']
4710 or not self.type.signed
4711 or self.type.is_float)
4712 if not self.cdivision:
4713 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4714 NumBinopNode.generate_evaluation_code(self, code)
4715 self.generate_div_warning_code(code)
4717 def generate_div_warning_code(self, code):
4718 if not self.type.is_pyobject:
4719 if self.zerodivision_check:
4720 if not self.infix:
4721 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4722 else:
4723 zero_test = "%s == 0" % self.operand2.result()
4724 code.putln("if (unlikely(%s)) {" % zero_test)
4725 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4726 code.putln(code.error_goto(self.pos))
4727 code.putln("}")
4728 if self.type.is_int and self.type.signed and self.operator != '%':
4729 code.globalstate.use_utility_code(division_overflow_test_code)
4730 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4731 self.type.declaration_code(''),
4732 self.operand2.result(),
4733 self.operand1.result()))
4734 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4735 code.putln(code.error_goto(self.pos))
4736 code.putln("}")
4737 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4738 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4739 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4740 self.operand1.result(),
4741 self.operand2.result()))
4742 code.putln(code.set_error_info(self.pos));
4743 code.put("if (__Pyx_cdivision_warning()) ")
4744 code.put_goto(code.error_label)
4745 code.putln("}")
4747 def calculate_result_code(self):
4748 if self.type.is_complex:
4749 return NumBinopNode.calculate_result_code(self)
4750 elif self.type.is_float and self.operator == '//':
4751 return "floor(%s / %s)" % (
4752 self.operand1.result(),
4753 self.operand2.result())
4754 elif self.truedivision or self.cdivision:
4755 op1 = self.operand1.result()
4756 op2 = self.operand2.result()
4757 if self.truedivision:
4758 if self.type != self.operand1.type:
4759 op1 = self.type.cast_code(op1)
4760 if self.type != self.operand2.type:
4761 op2 = self.type.cast_code(op2)
4762 return "(%s / %s)" % (op1, op2)
4763 else:
4764 return "__Pyx_div_%s(%s, %s)" % (
4765 self.type.specalization_name(),
4766 self.operand1.result(),
4767 self.operand2.result())
4770 class ModNode(DivNode):
4771 # '%' operator.
4773 def is_py_operation_types(self, type1, type2):
4774 return (type1.is_string
4775 or type2.is_string
4776 or NumBinopNode.is_py_operation_types(self, type1, type2))
4778 def zero_division_message(self):
4779 if self.type.is_int:
4780 return "integer division or modulo by zero"
4781 else:
4782 return "float divmod()"
4784 def generate_evaluation_code(self, code):
4785 if not self.type.is_pyobject:
4786 if self.cdivision is None:
4787 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4788 if not self.cdivision:
4789 if self.type.is_int:
4790 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4791 else:
4792 code.globalstate.use_utility_code(
4793 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4794 NumBinopNode.generate_evaluation_code(self, code)
4795 self.generate_div_warning_code(code)
4797 def calculate_result_code(self):
4798 if self.cdivision:
4799 if self.type.is_float:
4800 return "fmod%s(%s, %s)" % (
4801 self.type.math_h_modifier,
4802 self.operand1.result(),
4803 self.operand2.result())
4804 else:
4805 return "(%s %% %s)" % (
4806 self.operand1.result(),
4807 self.operand2.result())
4808 else:
4809 return "__Pyx_mod_%s(%s, %s)" % (
4810 self.type.specalization_name(),
4811 self.operand1.result(),
4812 self.operand2.result())
4814 class PowNode(NumBinopNode):
4815 # '**' operator.
4817 def analyse_c_operation(self, env):
4818 NumBinopNode.analyse_c_operation(self, env)
4819 if self.type.is_complex:
4820 error(self.pos, "complex powers not yet supported")
4821 self.pow_func = "<error>"
4822 elif self.type.is_float:
4823 self.pow_func = "pow"
4824 else:
4825 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4826 env.use_utility_code(
4827 int_pow_utility_code.specialize(func_name=self.pow_func,
4828 type=self.type.declaration_code('')))
4830 def calculate_result_code(self):
4831 return "%s(%s, %s)" % (
4832 self.pow_func,
4833 self.operand1.result(),
4834 self.operand2.result())
4837 # Note: This class is temporary "shut down" into an ineffective mode temp
4838 # allocation mode.
4840 # More sophisticated temp reuse was going on before,
4841 # one could have a look at adding this again after /all/ classes
4842 # are converted to the new temp scheme. (The temp juggling cannot work
4843 # otherwise).
4844 class BoolBinopNode(ExprNode):
4845 # Short-circuiting boolean operation.
4847 # operator string
4848 # operand1 ExprNode
4849 # operand2 ExprNode
4851 subexprs = ['operand1', 'operand2']
4853 def infer_type(self, env):
4854 type1 = self.operand1.infer_type(env)
4855 type2 = self.operand2.infer_type(env)
4856 return PyrexTypes.spanning_type(type1, type2)
4858 def calculate_constant_result(self):
4859 if self.operator == 'and':
4860 self.constant_result = \
4861 self.operand1.constant_result and \
4862 self.operand2.constant_result
4863 else:
4864 self.constant_result = \
4865 self.operand1.constant_result or \
4866 self.operand2.constant_result
4868 def compile_time_value(self, denv):
4869 if self.operator == 'and':
4870 return self.operand1.compile_time_value(denv) \
4871 and self.operand2.compile_time_value(denv)
4872 else:
4873 return self.operand1.compile_time_value(denv) \
4874 or self.operand2.compile_time_value(denv)
4876 def coerce_to_boolean(self, env):
4877 self.operand1 = self.operand1.coerce_to_boolean(env)
4878 self.operand2 = self.operand2.coerce_to_boolean(env)
4879 self.type = PyrexTypes.c_bint_type
4880 return self
4882 def analyse_types(self, env):
4883 self.operand1.analyse_types(env)
4884 self.operand2.analyse_types(env)
4885 self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
4886 self.operand1 = self.operand1.coerce_to(self.type, env)
4887 self.operand2 = self.operand2.coerce_to(self.type, env)
4889 # For what we're about to do, it's vital that
4890 # both operands be temp nodes.
4891 self.operand1 = self.operand1.coerce_to_simple(env)
4892 self.operand2 = self.operand2.coerce_to_simple(env)
4893 self.is_temp = 1
4895 gil_message = "Truth-testing Python object"
4897 def check_const(self):
4898 self.operand1.check_const()
4899 self.operand2.check_const()
4901 def generate_evaluation_code(self, code):
4902 code.mark_pos(self.pos)
4903 self.operand1.generate_evaluation_code(code)
4904 test_result, uses_temp = self.generate_operand1_test(code)
4905 if self.operator == 'and':
4906 sense = ""
4907 else:
4908 sense = "!"
4909 code.putln(
4910 "if (%s%s) {" % (
4911 sense,
4912 test_result))
4913 if uses_temp:
4914 code.funcstate.release_temp(test_result)
4915 self.operand1.generate_disposal_code(code)
4916 self.operand2.generate_evaluation_code(code)
4917 self.allocate_temp_result(code)
4918 self.operand2.make_owned_reference(code)
4919 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4920 self.operand2.generate_post_assignment_code(code)
4921 self.operand2.free_temps(code)
4922 code.putln("} else {")
4923 self.operand1.make_owned_reference(code)
4924 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4925 self.operand1.generate_post_assignment_code(code)
4926 self.operand1.free_temps(code)
4927 code.putln("}")
4929 def generate_operand1_test(self, code):
4930 # Generate code to test the truth of the first operand.
4931 if self.type.is_pyobject:
4932 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4933 manage_ref=False)
4934 code.putln(
4935 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4936 test_result,
4937 self.operand1.py_result(),
4938 code.error_goto_if_neg(test_result, self.pos)))
4939 else:
4940 test_result = self.operand1.result()
4941 return (test_result, self.type.is_pyobject)
4944 class CondExprNode(ExprNode):
4945 # Short-circuiting conditional expression.
4947 # test ExprNode
4948 # true_val ExprNode
4949 # false_val ExprNode
4951 true_val = None
4952 false_val = None
4954 subexprs = ['test', 'true_val', 'false_val']
4956 def type_dependencies(self, env):
4957 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
4959 def infer_type(self, env):
4960 return self.compute_result_type(self.true_val.infer_type(env),
4961 self.false_val.infer_type(env))
4963 def calculate_constant_result(self):
4964 if self.test.constant_result:
4965 self.constant_result = self.true_val.constant_result
4966 else:
4967 self.constant_result = self.false_val.constant_result
4969 def analyse_types(self, env):
4970 self.test.analyse_types(env)
4971 self.test = self.test.coerce_to_boolean(env)
4972 self.true_val.analyse_types(env)
4973 self.false_val.analyse_types(env)
4974 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4975 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4976 self.true_val = self.true_val.coerce_to(self.type, env)
4977 self.false_val = self.false_val.coerce_to(self.type, env)
4978 self.is_temp = 1
4979 if self.type == PyrexTypes.error_type:
4980 self.type_error()
4982 def compute_result_type(self, type1, type2):
4983 if type1 == type2:
4984 return type1
4985 elif type1.is_numeric and type2.is_numeric:
4986 return PyrexTypes.widest_numeric_type(type1, type2)
4987 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4988 return type2
4989 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4990 return type1
4991 elif type1.is_pyobject or type2.is_pyobject:
4992 return py_object_type
4993 elif type1.assignable_from(type2):
4994 return type1
4995 elif type2.assignable_from(type1):
4996 return type2
4997 else:
4998 return PyrexTypes.error_type
5000 def type_error(self):
5001 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5002 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5003 (self.true_val.type, self.false_val.type))
5004 self.type = PyrexTypes.error_type
5006 def check_const(self):
5007 self.test.check_const()
5008 self.true_val.check_const()
5009 self.false_val.check_const()
5011 def generate_evaluation_code(self, code):
5012 # Because subexprs may not be evaluated we can use a more optimal
5013 # subexpr allocation strategy than the default, so override evaluation_code.
5015 code.mark_pos(self.pos)
5016 self.allocate_temp_result(code)
5017 self.test.generate_evaluation_code(code)
5018 code.putln("if (%s) {" % self.test.result() )
5019 self.eval_and_get(code, self.true_val)
5020 code.putln("} else {")
5021 self.eval_and_get(code, self.false_val)
5022 code.putln("}")
5023 self.test.generate_disposal_code(code)
5024 self.test.free_temps(code)
5026 def eval_and_get(self, code, expr):
5027 expr.generate_evaluation_code(code)
5028 expr.make_owned_reference(code)
5029 code.putln("%s = %s;" % (self.result(), expr.result()))
5030 expr.generate_post_assignment_code(code)
5031 expr.free_temps(code)
5033 richcmp_constants = {
5034 "<" : "Py_LT",
5035 "<=": "Py_LE",
5036 "==": "Py_EQ",
5037 "!=": "Py_NE",
5038 "<>": "Py_NE",
5039 ">" : "Py_GT",
5040 ">=": "Py_GE",
5043 class CmpNode(object):
5044 # Mixin class containing code common to PrimaryCmpNodes
5045 # and CascadedCmpNodes.
5047 def infer_types(self, env):
5048 # TODO: Actually implement this (after merging with -unstable).
5049 return py_object_type
5051 def calculate_cascaded_constant_result(self, operand1_result):
5052 func = compile_time_binary_operators[self.operator]
5053 operand2_result = self.operand2.constant_result
5054 result = func(operand1_result, operand2_result)
5055 if result and self.cascade:
5056 result = result and \
5057 self.cascade.cascaded_compile_time_value(operand2_result)
5058 self.constant_result = result
5060 def cascaded_compile_time_value(self, operand1, denv):
5061 func = get_compile_time_binop(self)
5062 operand2 = self.operand2.compile_time_value(denv)
5063 try:
5064 result = func(operand1, operand2)
5065 except Exception, e:
5066 self.compile_time_value_error(e)
5067 result = None
5068 if result:
5069 cascade = self.cascade
5070 if cascade:
5071 # FIXME: I bet this must call cascaded_compile_time_value()
5072 result = result and cascade.compile_time_value(operand2, denv)
5073 return result
5075 def try_coerce_to_int_cmp(self, env, op, operand1, operand2):
5076 # type1 != type2 and at least one of the types is not a C int
5077 type1 = operand1.type
5078 type2 = operand2.type
5079 type1_can_be_int = False
5080 type2_can_be_int = False
5082 if isinstance(operand1, (StringNode, BytesNode)) \
5083 and operand1.can_coerce_to_char_literal():
5084 type1_can_be_int = True
5085 if isinstance(operand2, (StringNode, BytesNode)) \
5086 and operand2.can_coerce_to_char_literal():
5087 type2_can_be_int = True
5089 if type1.is_int:
5090 if type2_can_be_int:
5091 operand2 = operand2.coerce_to(type1, env)
5092 elif type2.is_int:
5093 if type1_can_be_int:
5094 operand1 = operand1.coerce_to(type2, env)
5095 elif type1_can_be_int:
5096 if type2_can_be_int:
5097 operand1 = operand1.coerce_to(PyrexTypes.c_uchar_type, env)
5098 operand2 = operand2.coerce_to(PyrexTypes.c_uchar_type, env)
5100 return operand1, operand2
5102 def coerce_operands(self, env, op, operand1, common_type=None):
5103 operand2 = self.operand2
5104 type1 = operand1.type
5105 type2 = operand2.type
5107 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5108 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5109 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5111 elif operand1.type.is_complex or operand2.type.is_complex:
5112 if op not in ('==', '!='):
5113 error(self.pos, "complex types unordered")
5114 if operand1.type.is_pyobject:
5115 operand2 = operand2.coerce_to(operand2.type, env)
5116 elif operand2.type.is_pyobject:
5117 operand1 = operand1.coerce_to(operand2.type, env)
5118 else:
5119 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5120 operand1 = operand1.coerce_to(common_type, env)
5121 operand2 = operand2.coerce_to(common_type, env)
5123 elif common_type is None or not common_type.is_pyobject:
5124 if not type1.is_int or not type2.is_int:
5125 operand1, operand2 = self.try_coerce_to_int_cmp(env, op, operand1, operand2)
5127 if operand1.type.is_pyobject or operand2.type.is_pyobject:
5128 # we could do a lot better by splitting the comparison
5129 # into a non-Python part and a Python part, but this is
5130 # safer for now
5131 if operand1.type == operand2.type:
5132 common_type = operand1.type
5133 else:
5134 common_type = py_object_type
5136 if self.cascade:
5137 operand2 = self.cascade.coerce_operands(env, self.operator, operand2, common_type)
5139 self.operand2 = operand2
5140 return operand1
5142 def is_python_comparison(self):
5143 return (self.has_python_operands()
5144 or (self.cascade and self.cascade.is_python_comparison())
5145 or self.operator in ('in', 'not_in'))
5147 def is_python_result(self):
5148 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
5149 or (self.cascade and self.cascade.is_python_result()))
5151 def check_types(self, env, operand1, op, operand2):
5152 if not self.types_okay(operand1, op, operand2):
5153 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5154 (self.operator, operand1.type, operand2.type))
5156 def types_okay(self, operand1, op, operand2):
5157 type1 = operand1.type
5158 type2 = operand2.type
5159 if type1.is_error or type2.is_error:
5160 return 1
5161 if type1.is_pyobject: # type2 will be, too
5162 return 1
5163 elif type1.is_ptr or type1.is_array:
5164 return type1.is_null_ptr or type2.is_null_ptr \
5165 or ((type2.is_ptr or type2.is_array)
5166 and type1.base_type.same_as(type2.base_type))
5167 elif ((type1.is_numeric and type2.is_numeric
5168 or type1.is_enum and (type1 is type2 or type2.is_int)
5169 or type1.is_int and type2.is_enum)
5170 and op not in ('is', 'is_not')):
5171 return 1
5172 else:
5173 return type1.is_cfunction and type1.is_cfunction and type1 == type2
5175 def generate_operation_code(self, code, result_code,
5176 operand1, op , operand2):
5177 if self.type is PyrexTypes.py_object_type:
5178 coerce_result = "__Pyx_PyBool_FromLong"
5179 else:
5180 coerce_result = ""
5181 if 'not' in op: negation = "!"
5182 else: negation = ""
5183 if op == 'in' or op == 'not_in':
5184 if operand2.type is dict_type:
5185 code.globalstate.use_utility_code(
5186 raise_none_iter_error_utility_code)
5187 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5188 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5189 code.error_goto(self.pos))
5190 code.putln("} else {")
5191 code.putln(
5192 "%s = %s(%sPyDict_Contains(%s, %s)); %s" % (
5193 result_code,
5194 coerce_result,
5195 negation,
5196 operand2.py_result(),
5197 operand1.py_result(),
5198 code.error_goto_if_neg(result_code, self.pos)))
5199 code.putln("}")
5200 else:
5201 code.putln(
5202 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
5203 result_code,
5204 coerce_result,
5205 negation,
5206 operand2.py_result(),
5207 operand1.py_result(),
5208 code.error_goto_if_neg(result_code, self.pos)))
5209 elif (operand1.type.is_pyobject
5210 and op not in ('is', 'is_not')):
5211 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5212 result_code,
5213 operand1.py_result(),
5214 operand2.py_result(),
5215 richcmp_constants[op],
5216 code.error_goto_if_null(result_code, self.pos)))
5217 code.put_gotref(result_code)
5218 elif operand1.type.is_complex:
5219 if op == "!=":
5220 negation = "!"
5221 else:
5222 negation = ""
5223 code.putln("%s = %s(%s%s(%s, %s));" % (
5224 result_code,
5225 coerce_result,
5226 negation,
5227 operand1.type.unary_op('eq'),
5228 operand1.result(),
5229 operand2.result()))
5230 else:
5231 type1 = operand1.type
5232 type2 = operand2.type
5233 if (type1.is_extension_type or type2.is_extension_type) \
5234 and not type1.same_as(type2):
5235 common_type = py_object_type
5236 elif type1.is_numeric:
5237 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5238 else:
5239 common_type = type1
5240 code1 = operand1.result_as(common_type)
5241 code2 = operand2.result_as(common_type)
5242 code.putln("%s = %s(%s %s %s);" % (
5243 result_code,
5244 coerce_result,
5245 code1,
5246 self.c_operator(op),
5247 code2))
5249 def c_operator(self, op):
5250 if op == 'is':
5251 return "=="
5252 elif op == 'is_not':
5253 return "!="
5254 else:
5255 return op
5258 class PrimaryCmpNode(ExprNode, CmpNode):
5259 # Non-cascaded comparison or first comparison of
5260 # a cascaded sequence.
5262 # operator string
5263 # operand1 ExprNode
5264 # operand2 ExprNode
5265 # cascade CascadedCmpNode
5267 # We don't use the subexprs mechanism, because
5268 # things here are too complicated for it to handle.
5269 # Instead, we override all the framework methods
5270 # which use it.
5272 child_attrs = ['operand1', 'operand2', 'cascade']
5274 cascade = None
5276 def infer_type(self, env):
5277 # TODO: Actually implement this (after merging with -unstable).
5278 return py_object_type
5280 def type_dependencies(self, env):
5281 return ()
5283 def calculate_constant_result(self):
5284 self.constant_result = self.calculate_cascaded_constant_result(
5285 self.operand1.constant_result)
5287 def compile_time_value(self, denv):
5288 operand1 = self.operand1.compile_time_value(denv)
5289 return self.cascaded_compile_time_value(operand1, denv)
5291 def analyse_types(self, env):
5292 self.operand1.analyse_types(env)
5293 self.operand2.analyse_types(env)
5294 if self.cascade:
5295 self.cascade.analyse_types(env, self.operand2)
5296 self.operand1 = self.coerce_operands(env, self.operator, self.operand1)
5297 self.is_pycmp = self.is_python_comparison()
5298 if self.is_pycmp:
5299 self.coerce_operands_to_pyobjects(env)
5300 if self.cascade:
5301 self.operand2 = self.operand2.coerce_to_simple(env)
5302 self.cascade.coerce_cascaded_operands_to_temp(env)
5303 self.check_operand_types(env)
5304 if self.is_python_result():
5305 self.type = PyrexTypes.py_object_type
5306 else:
5307 self.type = PyrexTypes.c_bint_type
5308 cdr = self.cascade
5309 while cdr:
5310 cdr.type = self.type
5311 cdr = cdr.cascade
5312 if self.is_pycmp or self.cascade:
5313 self.is_temp = 1
5315 def check_operand_types(self, env):
5316 self.check_types(env,
5317 self.operand1, self.operator, self.operand2)
5318 if self.cascade:
5319 self.cascade.check_operand_types(env, self.operand2)
5321 def has_python_operands(self):
5322 return (self.operand1.type.is_pyobject
5323 or self.operand2.type.is_pyobject)
5325 def coerce_operands_to_pyobjects(self, env):
5326 self.operand1 = self.operand1.coerce_to_pyobject(env)
5327 self.operand2 = self.operand2.coerce_to_pyobject(env)
5328 if self.cascade:
5329 self.cascade.coerce_operands_to_pyobjects(env)
5331 def check_const(self):
5332 self.operand1.check_const()
5333 self.operand2.check_const()
5334 if self.cascade:
5335 self.not_const()
5337 def calculate_result_code(self):
5338 if self.operand1.type.is_complex:
5339 if self.operator == "!=":
5340 negation = "!"
5341 else:
5342 negation = ""
5343 return "(%s%s(%s, %s))" % (
5344 negation,
5345 self.operand1.type.binary_op('=='),
5346 self.operand1.result(),
5347 self.operand2.result())
5348 else:
5349 return "(%s %s %s)" % (
5350 self.operand1.result(),
5351 self.c_operator(self.operator),
5352 self.operand2.result())
5354 def generate_evaluation_code(self, code):
5355 self.operand1.generate_evaluation_code(code)
5356 self.operand2.generate_evaluation_code(code)
5357 if self.is_temp:
5358 self.allocate_temp_result(code)
5359 self.generate_operation_code(code, self.result(),
5360 self.operand1, self.operator, self.operand2)
5361 if self.cascade:
5362 self.cascade.generate_evaluation_code(code,
5363 self.result(), self.operand2)
5364 self.operand1.generate_disposal_code(code)
5365 self.operand1.free_temps(code)
5366 self.operand2.generate_disposal_code(code)
5367 self.operand2.free_temps(code)
5369 def generate_subexpr_disposal_code(self, code):
5370 # If this is called, it is a non-cascaded cmp,
5371 # so only need to dispose of the two main operands.
5372 self.operand1.generate_disposal_code(code)
5373 self.operand2.generate_disposal_code(code)
5375 def free_subexpr_temps(self, code):
5376 # If this is called, it is a non-cascaded cmp,
5377 # so only need to dispose of the two main operands.
5378 self.operand1.free_temps(code)
5379 self.operand2.free_temps(code)
5381 def annotate(self, code):
5382 self.operand1.annotate(code)
5383 self.operand2.annotate(code)
5384 if self.cascade:
5385 self.cascade.annotate(code)
5388 class CascadedCmpNode(Node, CmpNode):
5389 # A CascadedCmpNode is not a complete expression node. It
5390 # hangs off the side of another comparison node, shares
5391 # its left operand with that node, and shares its result
5392 # with the PrimaryCmpNode at the head of the chain.
5394 # operator string
5395 # operand2 ExprNode
5396 # cascade CascadedCmpNode
5398 child_attrs = ['operand2', 'cascade']
5400 cascade = None
5401 constant_result = constant_value_not_set # FIXME: where to calculate this?
5403 def infer_type(self, env):
5404 # TODO: Actually implement this (after merging with -unstable).
5405 return py_object_type
5407 def type_dependencies(self, env):
5408 return ()
5410 def analyse_types(self, env, operand1):
5411 self.operand2.analyse_types(env)
5412 if self.cascade:
5413 self.cascade.analyse_types(env, self.operand2)
5415 def check_operand_types(self, env, operand1):
5416 self.check_types(env,
5417 operand1, self.operator, self.operand2)
5418 if self.cascade:
5419 self.cascade.check_operand_types(env, self.operand2)
5421 def has_python_operands(self):
5422 return self.operand2.type.is_pyobject
5424 def coerce_operands_to_pyobjects(self, env):
5425 self.operand2 = self.operand2.coerce_to_pyobject(env)
5426 if self.cascade:
5427 self.cascade.coerce_operands_to_pyobjects(env)
5429 def coerce_cascaded_operands_to_temp(self, env):
5430 if self.cascade:
5431 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5432 self.operand2 = self.operand2.coerce_to_simple(env)
5433 self.cascade.coerce_cascaded_operands_to_temp(env)
5435 def generate_evaluation_code(self, code, result, operand1):
5436 if self.type.is_pyobject:
5437 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5438 code.put_decref(result, self.type)
5439 else:
5440 code.putln("if (%s) {" % result)
5441 self.operand2.generate_evaluation_code(code)
5442 self.generate_operation_code(code, result,
5443 operand1, self.operator, self.operand2)
5444 if self.cascade:
5445 self.cascade.generate_evaluation_code(
5446 code, result, self.operand2)
5447 # Cascaded cmp result is always temp
5448 self.operand2.generate_disposal_code(code)
5449 self.operand2.free_temps(code)
5450 code.putln("}")
5452 def annotate(self, code):
5453 self.operand2.annotate(code)
5454 if self.cascade:
5455 self.cascade.annotate(code)
5458 binop_node_classes = {
5459 "or": BoolBinopNode,
5460 "and": BoolBinopNode,
5461 "|": IntBinopNode,
5462 "^": IntBinopNode,
5463 "&": IntBinopNode,
5464 "<<": IntBinopNode,
5465 ">>": IntBinopNode,
5466 "+": AddNode,
5467 "-": SubNode,
5468 "*": MulNode,
5469 "/": DivNode,
5470 "//": DivNode,
5471 "%": ModNode,
5472 "**": PowNode
5475 def binop_node(pos, operator, operand1, operand2):
5476 # Construct binop node of appropriate class for
5477 # given operator.
5478 return binop_node_classes[operator](pos,
5479 operator = operator,
5480 operand1 = operand1,
5481 operand2 = operand2)
5483 #-------------------------------------------------------------------
5485 # Coercion nodes
5487 # Coercion nodes are special in that they are created during
5488 # the analyse_types phase of parse tree processing.
5489 # Their __init__ methods consequently incorporate some aspects
5490 # of that phase.
5492 #-------------------------------------------------------------------
5494 class CoercionNode(ExprNode):
5495 # Abstract base class for coercion nodes.
5497 # arg ExprNode node being coerced
5499 subexprs = ['arg']
5501 def __init__(self, arg):
5502 self.pos = arg.pos
5503 self.arg = arg
5504 if debug_coercion:
5505 print("%s Coercing %s" % (self, self.arg))
5507 def calculate_constant_result(self):
5508 # constant folding can break type coercion, so this is disabled
5509 pass
5511 def annotate(self, code):
5512 self.arg.annotate(code)
5513 if self.arg.type != self.type:
5514 file, line, col = self.pos
5515 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5518 class CastNode(CoercionNode):
5519 # Wrap a node in a C type cast.
5521 def __init__(self, arg, new_type):
5522 CoercionNode.__init__(self, arg)
5523 self.type = new_type
5525 def calculate_result_code(self):
5526 return self.arg.result_as(self.type)
5528 def generate_result_code(self, code):
5529 self.arg.generate_result_code(code)
5532 class PyTypeTestNode(CoercionNode):
5533 # This node is used to check that a generic Python
5534 # object is an instance of a particular extension type.
5535 # This node borrows the result of its argument node.
5537 def __init__(self, arg, dst_type, env):
5538 # The arg is know to be a Python object, and
5539 # the dst_type is known to be an extension type.
5540 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5541 CoercionNode.__init__(self, arg)
5542 self.type = dst_type
5543 self.result_ctype = arg.ctype()
5545 nogil_check = Node.gil_error
5546 gil_message = "Python type test"
5548 def analyse_types(self, env):
5549 pass
5551 def result_in_temp(self):
5552 return self.arg.result_in_temp()
5554 def is_ephemeral(self):
5555 return self.arg.is_ephemeral()
5557 def calculate_constant_result(self):
5558 # FIXME
5559 pass
5561 def calculate_result_code(self):
5562 return self.arg.result()
5564 def generate_result_code(self, code):
5565 if self.type.typeobj_is_available():
5566 if not self.type.is_builtin_type:
5567 code.globalstate.use_utility_code(type_test_utility_code)
5568 code.putln(
5569 "if (!(%s)) %s" % (
5570 self.type.type_test_code(self.arg.py_result()),
5571 code.error_goto(self.pos)))
5572 else:
5573 error(self.pos, "Cannot test type of extern C class "
5574 "without type object name specification")
5576 def generate_post_assignment_code(self, code):
5577 self.arg.generate_post_assignment_code(code)
5579 def free_temps(self, code):
5580 self.arg.free_temps(code)
5583 class NoneCheckNode(CoercionNode):
5584 # This node is used to check that a Python object is not None and
5585 # raises an appropriate exception (as specified by the creating
5586 # transform).
5588 def __init__(self, arg, exception_type_cname, exception_message):
5589 CoercionNode.__init__(self, arg)
5590 self.type = arg.type
5591 self.result_ctype = arg.ctype()
5592 self.exception_type_cname = exception_type_cname
5593 self.exception_message = exception_message
5595 def analyse_types(self, env):
5596 pass
5598 def result_in_temp(self):
5599 return self.arg.result_in_temp()
5601 def calculate_result_code(self):
5602 return self.arg.result()
5604 def generate_result_code(self, code):
5605 code.putln(
5606 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5607 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5608 self.exception_type_cname,
5609 StringEncoding.escape_byte_string(
5610 self.exception_message.encode('UTF-8')),
5611 code.error_goto(self.pos)))
5612 code.putln("}")
5614 def generate_post_assignment_code(self, code):
5615 self.arg.generate_post_assignment_code(code)
5617 def free_temps(self, code):
5618 self.arg.free_temps(code)
5621 class CoerceToPyTypeNode(CoercionNode):
5622 # This node is used to convert a C data type
5623 # to a Python object.
5625 type = py_object_type
5626 is_temp = 1
5628 def __init__(self, arg, env):
5629 CoercionNode.__init__(self, arg)
5630 if not arg.type.create_to_py_utility_code(env):
5631 error(arg.pos,
5632 "Cannot convert '%s' to Python object" % arg.type)
5634 gil_message = "Converting to Python object"
5636 def coerce_to_boolean(self, env):
5637 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5639 def coerce_to_integer(self, env):
5640 # If not already some C integer type, coerce to longint.
5641 if self.arg.type.is_int:
5642 return self.arg
5643 else:
5644 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5646 def analyse_types(self, env):
5647 # The arg is always already analysed
5648 pass
5650 def generate_result_code(self, code):
5651 function = self.arg.type.to_py_function
5652 code.putln('%s = %s(%s); %s' % (
5653 self.result(),
5654 function,
5655 self.arg.result(),
5656 code.error_goto_if_null(self.result(), self.pos)))
5657 code.put_gotref(self.py_result())
5660 class CoerceFromPyTypeNode(CoercionNode):
5661 # This node is used to convert a Python object
5662 # to a C data type.
5664 def __init__(self, result_type, arg, env):
5665 CoercionNode.__init__(self, arg)
5666 self.type = result_type
5667 self.is_temp = 1
5668 if not result_type.create_from_py_utility_code(env):
5669 error(arg.pos,
5670 "Cannot convert Python object to '%s'" % result_type)
5671 if self.type.is_string and self.arg.is_ephemeral():
5672 error(arg.pos,
5673 "Obtaining char * from temporary Python value")
5675 def analyse_types(self, env):
5676 # The arg is always already analysed
5677 pass
5679 def generate_result_code(self, code):
5680 function = self.type.from_py_function
5681 operand = self.arg.py_result()
5682 rhs = "%s(%s)" % (function, operand)
5683 if self.type.is_enum:
5684 rhs = typecast(self.type, c_long_type, rhs)
5685 code.putln('%s = %s; %s' % (
5686 self.result(),
5687 rhs,
5688 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5689 if self.type.is_pyobject:
5690 code.put_gotref(self.py_result())
5693 class CoerceToBooleanNode(CoercionNode):
5694 # This node is used when a result needs to be used
5695 # in a boolean context.
5697 type = PyrexTypes.c_bint_type
5699 def __init__(self, arg, env):
5700 CoercionNode.__init__(self, arg)
5701 if arg.type.is_pyobject:
5702 self.is_temp = 1
5704 def nogil_check(self, env):
5705 if self.arg.type.is_pyobject:
5706 self.gil_error()
5708 gil_message = "Truth-testing Python object"
5710 def check_const(self):
5711 if self.is_temp:
5712 self.not_const()
5713 self.arg.check_const()
5715 def calculate_result_code(self):
5716 return "(%s != 0)" % self.arg.result()
5718 def generate_result_code(self, code):
5719 if self.arg.type.is_pyobject:
5720 code.putln(
5721 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5722 self.result(),
5723 self.arg.py_result(),
5724 code.error_goto_if_neg(self.result(), self.pos)))
5726 class CoerceToComplexNode(CoercionNode):
5728 def __init__(self, arg, dst_type, env):
5729 if arg.type.is_complex:
5730 arg = arg.coerce_to_simple(env)
5731 self.type = dst_type
5732 CoercionNode.__init__(self, arg)
5733 dst_type.create_declaration_utility_code(env)
5735 def calculate_result_code(self):
5736 if self.arg.type.is_complex:
5737 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
5738 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
5739 else:
5740 real_part = self.arg.result()
5741 imag_part = "0"
5742 return "%s(%s, %s)" % (
5743 self.type.from_parts,
5744 real_part,
5745 imag_part)
5747 def generate_result_code(self, code):
5748 pass
5750 class CoerceToTempNode(CoercionNode):
5751 # This node is used to force the result of another node
5752 # to be stored in a temporary. It is only used if the
5753 # argument node's result is not already in a temporary.
5755 def __init__(self, arg, env):
5756 CoercionNode.__init__(self, arg)
5757 self.type = self.arg.type
5758 self.is_temp = 1
5759 if self.type.is_pyobject:
5760 self.result_ctype = py_object_type
5762 gil_message = "Creating temporary Python reference"
5764 def analyse_types(self, env):
5765 # The arg is always already analysed
5766 pass
5768 def coerce_to_boolean(self, env):
5769 self.arg = self.arg.coerce_to_boolean(env)
5770 self.type = self.arg.type
5771 self.result_ctype = self.type
5772 return self
5774 def generate_result_code(self, code):
5775 #self.arg.generate_evaluation_code(code) # Already done
5776 # by generic generate_subexpr_evaluation_code!
5777 code.putln("%s = %s;" % (
5778 self.result(), self.arg.result_as(self.ctype())))
5779 if self.type.is_pyobject:
5780 code.put_incref(self.result(), self.ctype())
5783 class CloneNode(CoercionNode):
5784 # This node is employed when the result of another node needs
5785 # to be used multiple times. The argument node's result must
5786 # be in a temporary. This node "borrows" the result from the
5787 # argument node, and does not generate any evaluation or
5788 # disposal code for it. The original owner of the argument
5789 # node is responsible for doing those things.
5791 subexprs = [] # Arg is not considered a subexpr
5792 nogil_check = None
5794 def __init__(self, arg):
5795 CoercionNode.__init__(self, arg)
5796 if hasattr(arg, 'type'):
5797 self.type = arg.type
5798 self.result_ctype = arg.result_ctype
5799 if hasattr(arg, 'entry'):
5800 self.entry = arg.entry
5802 def result(self):
5803 return self.arg.result()
5805 def type_dependencies(self, env):
5806 return self.arg.type_dependencies(env)
5808 def infer_type(self, env):
5809 return self.arg.infer_type(env)
5811 def analyse_types(self, env):
5812 self.type = self.arg.type
5813 self.result_ctype = self.arg.result_ctype
5814 self.is_temp = 1
5815 if hasattr(self.arg, 'entry'):
5816 self.entry = self.arg.entry
5818 def generate_evaluation_code(self, code):
5819 pass
5821 def generate_result_code(self, code):
5822 pass
5824 def generate_disposal_code(self, code):
5825 pass
5827 def free_temps(self, code):
5828 pass
5831 class ModuleRefNode(ExprNode):
5832 # Simple returns the module object
5834 type = py_object_type
5835 is_temp = False
5836 subexprs = []
5838 def analyse_types(self, env):
5839 pass
5841 def calculate_result_code(self):
5842 return Naming.module_cname
5844 def generate_result_code(self, code):
5845 pass
5847 class DocstringRefNode(ExprNode):
5848 # Extracts the docstring of the body element
5850 subexprs = ['body']
5851 type = py_object_type
5852 is_temp = True
5854 def __init__(self, pos, body):
5855 ExprNode.__init__(self, pos)
5856 assert body.type.is_pyobject
5857 self.body = body
5859 def analyse_types(self, env):
5860 pass
5862 def generate_result_code(self, code):
5863 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
5864 (self.result(), self.body.result()))
5865 code.put_gotref(self.result())
5869 #------------------------------------------------------------------------------------
5871 # Runtime support code
5873 #------------------------------------------------------------------------------------
5875 get_name_interned_utility_code = UtilityCode(
5876 proto = """
5877 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5878 """,
5879 impl = """
5880 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5881 PyObject *result;
5882 result = PyObject_GetAttr(dict, name);
5883 if (!result)
5884 PyErr_SetObject(PyExc_NameError, name);
5885 return result;
5887 """)
5889 #------------------------------------------------------------------------------------
5891 import_utility_code = UtilityCode(
5892 proto = """
5893 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5894 """,
5895 impl = """
5896 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5897 PyObject *__import__ = 0;
5898 PyObject *empty_list = 0;
5899 PyObject *module = 0;
5900 PyObject *global_dict = 0;
5901 PyObject *empty_dict = 0;
5902 PyObject *list;
5903 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5904 if (!__import__)
5905 goto bad;
5906 if (from_list)
5907 list = from_list;
5908 else {
5909 empty_list = PyList_New(0);
5910 if (!empty_list)
5911 goto bad;
5912 list = empty_list;
5914 global_dict = PyModule_GetDict(%(GLOBALS)s);
5915 if (!global_dict)
5916 goto bad;
5917 empty_dict = PyDict_New();
5918 if (!empty_dict)
5919 goto bad;
5920 module = PyObject_CallFunctionObjArgs(__import__,
5921 name, global_dict, empty_dict, list, NULL);
5922 bad:
5923 Py_XDECREF(empty_list);
5924 Py_XDECREF(__import__);
5925 Py_XDECREF(empty_dict);
5926 return module;
5928 """ % {
5929 "BUILTINS": Naming.builtins_cname,
5930 "GLOBALS": Naming.module_cname,
5931 })
5933 #------------------------------------------------------------------------------------
5935 get_exception_utility_code = UtilityCode(
5936 proto = """
5937 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5938 """,
5939 impl = """
5940 static PyObject *__Pyx_GetExcValue(void) {
5941 PyObject *type = 0, *value = 0, *tb = 0;
5942 PyObject *tmp_type, *tmp_value, *tmp_tb;
5943 PyObject *result = 0;
5944 PyThreadState *tstate = PyThreadState_Get();
5945 PyErr_Fetch(&type, &value, &tb);
5946 PyErr_NormalizeException(&type, &value, &tb);
5947 if (PyErr_Occurred())
5948 goto bad;
5949 if (!value) {
5950 value = Py_None;
5951 Py_INCREF(value);
5953 tmp_type = tstate->exc_type;
5954 tmp_value = tstate->exc_value;
5955 tmp_tb = tstate->exc_traceback;
5956 tstate->exc_type = type;
5957 tstate->exc_value = value;
5958 tstate->exc_traceback = tb;
5959 /* Make sure tstate is in a consistent state when we XDECREF
5960 these objects (XDECREF may run arbitrary code). */
5961 Py_XDECREF(tmp_type);
5962 Py_XDECREF(tmp_value);
5963 Py_XDECREF(tmp_tb);
5964 result = value;
5965 Py_XINCREF(result);
5966 type = 0;
5967 value = 0;
5968 tb = 0;
5969 bad:
5970 Py_XDECREF(type);
5971 Py_XDECREF(value);
5972 Py_XDECREF(tb);
5973 return result;
5975 """)
5977 #------------------------------------------------------------------------------------
5979 type_test_utility_code = UtilityCode(
5980 proto = """
5981 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5982 """,
5983 impl = """
5984 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5985 if (!type) {
5986 PyErr_Format(PyExc_SystemError, "Missing type object");
5987 return 0;
5989 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5990 return 1;
5991 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5992 Py_TYPE(obj)->tp_name, type->tp_name);
5993 return 0;
5995 """)
5997 #------------------------------------------------------------------------------------
5999 create_class_utility_code = UtilityCode(
6000 proto = """
6001 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6002 """,
6003 impl = """
6004 static PyObject *__Pyx_CreateClass(
6005 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6007 PyObject *py_modname;
6008 PyObject *result = 0;
6010 #if PY_MAJOR_VERSION < 3
6011 py_modname = PyString_FromString(modname);
6012 #else
6013 py_modname = PyUnicode_FromString(modname);
6014 #endif
6015 if (!py_modname)
6016 goto bad;
6017 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6018 goto bad;
6019 #if PY_MAJOR_VERSION < 3
6020 result = PyClass_New(bases, dict, name);
6021 #else
6022 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6023 #endif
6024 bad:
6025 Py_XDECREF(py_modname);
6026 return result;
6028 """)
6030 #------------------------------------------------------------------------------------
6032 cpp_exception_utility_code = UtilityCode(
6033 proto = """
6034 #ifndef __Pyx_CppExn2PyErr
6035 static void __Pyx_CppExn2PyErr() {
6036 try {
6037 if (PyErr_Occurred())
6038 ; // let the latest Python exn pass through and ignore the current one
6039 else
6040 throw;
6041 } catch (const std::out_of_range& exn) {
6042 // catch out_of_range explicitly so the proper Python exn may be raised
6043 PyErr_SetString(PyExc_IndexError, exn.what());
6044 } catch (const std::exception& exn) {
6045 PyErr_SetString(PyExc_RuntimeError, exn.what());
6047 catch (...)
6049 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6052 #endif
6053 """,
6054 impl = ""
6057 #------------------------------------------------------------------------------------
6059 # If the is_unsigned flag is set, we need to do some extra work to make
6060 # sure the index doesn't become negative.
6062 getitem_int_utility_code = UtilityCode(
6063 proto = """
6065 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6066 PyObject *r;
6067 if (!j) return NULL;
6068 r = PyObject_GetItem(o, j);
6069 Py_DECREF(j);
6070 return r;
6073 """ + ''.join([
6074 """
6075 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6076 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6077 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6079 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6080 if (likely(o != Py_None)) {
6081 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6082 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6083 Py_INCREF(r);
6084 return r;
6086 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6087 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6088 Py_INCREF(r);
6089 return r;
6092 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6094 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6095 ]) + """
6097 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6098 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6099 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6101 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6102 PyObject *r;
6103 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6104 r = PyList_GET_ITEM(o, i);
6105 Py_INCREF(r);
6107 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6108 r = PyTuple_GET_ITEM(o, i);
6109 Py_INCREF(r);
6111 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6112 r = PySequence_GetItem(o, i);
6114 else {
6115 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6117 return r;
6119 """,
6120 impl = """
6121 """)
6125 #------------------------------------------------------------------------------------
6127 setitem_int_utility_code = UtilityCode(
6128 proto = """
6129 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6130 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6131 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6133 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6134 int r;
6135 if (!j) return -1;
6136 r = PyObject_SetItem(o, j, v);
6137 Py_DECREF(j);
6138 return r;
6141 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6142 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6143 Py_INCREF(v);
6144 Py_DECREF(PyList_GET_ITEM(o, i));
6145 PyList_SET_ITEM(o, i, v);
6146 return 1;
6148 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6149 return PySequence_SetItem(o, i, v);
6150 else {
6151 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6152 return __Pyx_SetItemInt_Generic(o, j, v);
6155 """,
6156 impl = """
6157 """)
6159 #------------------------------------------------------------------------------------
6161 delitem_int_utility_code = UtilityCode(
6162 proto = """
6163 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6164 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6165 __Pyx_DelItem_Generic(o, to_py_func(i)))
6167 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6168 int r;
6169 if (!j) return -1;
6170 r = PyObject_DelItem(o, j);
6171 Py_DECREF(j);
6172 return r;
6175 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6176 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6177 return PySequence_DelItem(o, i);
6178 else {
6179 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6180 return __Pyx_DelItem_Generic(o, j);
6183 """,
6184 impl = """
6185 """)
6187 #------------------------------------------------------------------------------------
6189 raise_noneattr_error_utility_code = UtilityCode(
6190 proto = """
6191 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6192 """,
6193 impl = '''
6194 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6195 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6197 ''')
6199 raise_noneindex_error_utility_code = UtilityCode(
6200 proto = """
6201 static INLINE void __Pyx_RaiseNoneIndexingError(void);
6202 """,
6203 impl = '''
6204 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
6205 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6207 ''')
6209 raise_none_iter_error_utility_code = UtilityCode(
6210 proto = """
6211 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
6212 """,
6213 impl = '''
6214 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6215 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6217 ''')
6219 raise_too_many_values_to_unpack = UtilityCode(
6220 proto = """
6221 static INLINE void __Pyx_RaiseTooManyValuesError(void);
6222 """,
6223 impl = '''
6224 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
6225 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6227 ''')
6229 raise_need_more_values_to_unpack = UtilityCode(
6230 proto = """
6231 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6232 """,
6233 impl = '''
6234 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6235 PyErr_Format(PyExc_ValueError,
6236 #if PY_VERSION_HEX < 0x02050000
6237 "need more than %d value%s to unpack", (int)index,
6238 #else
6239 "need more than %zd value%s to unpack", index,
6240 #endif
6241 (index == 1) ? "" : "s");
6243 ''')
6245 #------------------------------------------------------------------------------------
6247 tuple_unpacking_error_code = UtilityCode(
6248 proto = """
6249 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6250 """,
6251 impl = """
6252 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6253 if (t == Py_None) {
6254 __Pyx_RaiseNoneNotIterableError();
6255 } else if (PyTuple_GET_SIZE(t) < index) {
6256 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6257 } else {
6258 __Pyx_RaiseTooManyValuesError();
6261 """,
6262 requires = [raise_none_iter_error_utility_code,
6263 raise_need_more_values_to_unpack,
6264 raise_too_many_values_to_unpack]
6267 unpacking_utility_code = UtilityCode(
6268 proto = """
6269 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6270 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6271 """,
6272 impl = """
6273 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6274 PyObject *item;
6275 if (!(item = PyIter_Next(iter))) {
6276 if (!PyErr_Occurred()) {
6277 __Pyx_RaiseNeedMoreValuesError(index);
6280 return item;
6283 static int __Pyx_EndUnpack(PyObject *iter) {
6284 PyObject *item;
6285 if ((item = PyIter_Next(iter))) {
6286 Py_DECREF(item);
6287 __Pyx_RaiseTooManyValuesError();
6288 return -1;
6290 else if (!PyErr_Occurred())
6291 return 0;
6292 else
6293 return -1;
6295 """,
6296 requires = [raise_need_more_values_to_unpack,
6297 raise_too_many_values_to_unpack]
6301 #------------------------------------------------------------------------------------
6303 int_pow_utility_code = UtilityCode(
6304 proto="""
6305 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6306 """,
6307 impl="""
6308 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6309 %(type)s t = b;
6310 switch (e) {
6311 case 3:
6312 t *= b;
6313 case 2:
6314 t *= b;
6315 case 1:
6316 return t;
6317 case 0:
6318 return 1;
6320 if (unlikely(e<0)) return 0;
6321 t = 1;
6322 while (likely(e)) {
6323 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6324 b *= b;
6325 e >>= 1;
6327 return t;
6329 """)
6331 # ------------------------------ Division ------------------------------------
6333 div_int_utility_code = UtilityCode(
6334 proto="""
6335 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6336 """,
6337 impl="""
6338 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6339 %(type)s q = a / b;
6340 %(type)s r = a - q*b;
6341 q -= ((r != 0) & ((r ^ b) < 0));
6342 return q;
6344 """)
6346 mod_int_utility_code = UtilityCode(
6347 proto="""
6348 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6349 """,
6350 impl="""
6351 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6352 %(type)s r = a %% b;
6353 r += ((r != 0) & ((r ^ b) < 0)) * b;
6354 return r;
6356 """)
6358 mod_float_utility_code = UtilityCode(
6359 proto="""
6360 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6361 """,
6362 impl="""
6363 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6364 %(type)s r = fmod%(math_h_modifier)s(a, b);
6365 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6366 return r;
6368 """)
6370 cdivision_warning_utility_code = UtilityCode(
6371 proto="""
6372 static int __Pyx_cdivision_warning(void); /* proto */
6373 """,
6374 impl="""
6375 static int __Pyx_cdivision_warning(void) {
6376 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6377 "division with oppositely signed operands, C and Python semantics differ",
6378 %(FILENAME)s,
6379 %(LINENO)s,
6380 __Pyx_MODULE_NAME,
6381 NULL);
6383 """ % {
6384 'FILENAME': Naming.filename_cname,
6385 'LINENO': Naming.lineno_cname,
6386 })
6388 # from intobject.c
6389 division_overflow_test_code = UtilityCode(
6390 proto="""
6391 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6392 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6393 """)