Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 3484:b254c4dbc089
support for some Python 3 (or 2.6+) syntax features (found by test_grammar.py in Py3.1.1):
- oct/bin notation: 0o12345, 0b10101
- function annotations (only pure syntax support, not currently used)
also: allow decorators on inner functions
- oct/bin notation: 0o12345, 0b10101
- function annotations (only pure syntax support, not currently used)
also: allow decorators on inner functions
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Thu Jan 28 23:05:39 2010 +0100 (2 years ago) |
| parents | 51e3875b904b |
| children | 3e25233bbcc7 |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
7 from Errors import error, warning, warn_once, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Code import UtilityCode
10 import StringEncoding
11 import Naming
12 import Nodes
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, \
17 unicode_type, str_type, bytes_type, type_type
18 import Builtin
19 import Symtab
20 import Options
21 from Annotate import AnnotationItem
22 from Cython import Utils
24 from Cython.Debugging import print_call_chain
25 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
26 debug_coercion
28 try:
29 set
30 except NameError:
31 from sets import Set as set
33 class NotConstant(object): pass # just for the name
34 not_a_constant = NotConstant()
35 constant_value_not_set = object()
37 # error messages when coercing from key[0] to key[1]
38 find_coercion_error = {
39 # string related errors
40 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
41 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
42 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects do not support coercion to C types.",
43 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
44 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
45 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
46 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
47 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
48 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
49 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
50 }.get
53 class ExprNode(Node):
54 # subexprs [string] Class var holding names of subexpr node attrs
55 # type PyrexType Type of the result
56 # result_code string Code fragment
57 # result_ctype string C type of result_code if different from type
58 # is_temp boolean Result is in a temporary variable
59 # is_sequence_constructor
60 # boolean Is a list or tuple constructor expression
61 # is_starred boolean Is a starred expression (e.g. '*a')
62 # saved_subexpr_nodes
63 # [ExprNode or [ExprNode or None] or None]
64 # Cached result of subexpr_nodes()
65 # use_managed_ref boolean use ref-counted temps/assignments/etc.
67 result_ctype = None
68 type = None
69 temp_code = None
70 old_temp = None # error checker for multiple frees etc.
71 use_managed_ref = True # can be set by optimisation transforms
73 # The Analyse Expressions phase for expressions is split
74 # into two sub-phases:
75 #
76 # Analyse Types
77 # Determines the result type of the expression based
78 # on the types of its sub-expressions, and inserts
79 # coercion nodes into the expression tree where needed.
80 # Marks nodes which will need to have temporary variables
81 # allocated.
82 #
83 # Allocate Temps
84 # Allocates temporary variables where needed, and fills
85 # in the result_code field of each node.
86 #
87 # ExprNode provides some convenience routines which
88 # perform both of the above phases. These should only
89 # be called from statement nodes, and only when no
90 # coercion nodes need to be added around the expression
91 # being analysed. In that case, the above two phases
92 # should be invoked separately.
93 #
94 # Framework code in ExprNode provides much of the common
95 # processing for the various phases. It makes use of the
96 # 'subexprs' class attribute of ExprNodes, which should
97 # contain a list of the names of attributes which can
98 # hold sub-nodes or sequences of sub-nodes.
99 #
100 # The framework makes use of a number of abstract methods.
101 # Their responsibilities are as follows.
102 #
103 # Declaration Analysis phase
104 #
105 # analyse_target_declaration
106 # Called during the Analyse Declarations phase to analyse
107 # the LHS of an assignment or argument of a del statement.
108 # Nodes which cannot be the LHS of an assignment need not
109 # implement it.
110 #
111 # Expression Analysis phase
112 #
113 # analyse_types
114 # - Call analyse_types on all sub-expressions.
115 # - Check operand types, and wrap coercion nodes around
116 # sub-expressions where needed.
117 # - Set the type of this node.
118 # - If a temporary variable will be required for the
119 # result, set the is_temp flag of this node.
120 #
121 # analyse_target_types
122 # Called during the Analyse Types phase to analyse
123 # the LHS of an assignment or argument of a del
124 # statement. Similar responsibilities to analyse_types.
125 #
126 # target_code
127 # Called by the default implementation of allocate_target_temps.
128 # Should return a C lvalue for assigning to the node. The default
129 # implementation calls calculate_result_code.
130 #
131 # check_const
132 # - Check that this node and its subnodes form a
133 # legal constant expression. If so, do nothing,
134 # otherwise call not_const.
135 #
136 # The default implementation of check_const
137 # assumes that the expression is not constant.
138 #
139 # check_const_addr
140 # - Same as check_const, except check that the
141 # expression is a C lvalue whose address is
142 # constant. Otherwise, call addr_not_const.
143 #
144 # The default implementation of calc_const_addr
145 # assumes that the expression is not a constant
146 # lvalue.
147 #
148 # Code Generation phase
149 #
150 # generate_evaluation_code
151 # - Call generate_evaluation_code for sub-expressions.
152 # - Perform the functions of generate_result_code
153 # (see below).
154 # - If result is temporary, call generate_disposal_code
155 # on all sub-expressions.
156 #
157 # A default implementation of generate_evaluation_code
158 # is provided which uses the following abstract methods:
159 #
160 # generate_result_code
161 # - Generate any C statements necessary to calculate
162 # the result of this node from the results of its
163 # sub-expressions.
164 #
165 # calculate_result_code
166 # - Should return a C code fragment evaluating to the
167 # result. This is only called when the result is not
168 # a temporary.
169 #
170 # generate_assignment_code
171 # Called on the LHS of an assignment.
172 # - Call generate_evaluation_code for sub-expressions.
173 # - Generate code to perform the assignment.
174 # - If the assignment absorbed a reference, call
175 # generate_post_assignment_code on the RHS,
176 # otherwise call generate_disposal_code on it.
177 #
178 # generate_deletion_code
179 # Called on an argument of a del statement.
180 # - Call generate_evaluation_code for sub-expressions.
181 # - Generate code to perform the deletion.
182 # - Call generate_disposal_code on all sub-expressions.
183 #
184 #
186 is_sequence_constructor = 0
187 is_attribute = 0
189 saved_subexpr_nodes = None
190 is_temp = 0
191 is_target = 0
192 is_starred = 0
194 constant_result = constant_value_not_set
196 try:
197 _get_child_attrs = operator.attrgetter('subexprs')
198 except AttributeError:
199 # Python 2.3
200 def _get_child_attrs(self):
201 return self.subexprs
202 child_attrs = property(fget=_get_child_attrs)
204 def not_implemented(self, method_name):
205 print_call_chain(method_name, "not implemented") ###
206 raise InternalError(
207 "%s.%s not implemented" %
208 (self.__class__.__name__, method_name))
210 def is_lvalue(self):
211 return 0
213 def is_ephemeral(self):
214 # An ephemeral node is one whose result is in
215 # a Python temporary and we suspect there are no
216 # other references to it. Certain operations are
217 # disallowed on such values, since they are
218 # likely to result in a dangling pointer.
219 return self.type.is_pyobject and self.is_temp
221 def subexpr_nodes(self):
222 # Extract a list of subexpression nodes based
223 # on the contents of the subexprs class attribute.
224 nodes = []
225 for name in self.subexprs:
226 item = getattr(self, name)
227 if item is not None:
228 if type(item) is list:
229 nodes.extend(item)
230 else:
231 nodes.append(item)
232 return nodes
234 def result(self):
235 if self.is_temp:
236 return self.temp_code
237 else:
238 return self.calculate_result_code()
240 def result_as(self, type = None):
241 # Return the result code cast to the specified C type.
242 return typecast(type, self.ctype(), self.result())
244 def py_result(self):
245 # Return the result code cast to PyObject *.
246 return self.result_as(py_object_type)
248 def ctype(self):
249 # Return the native C type of the result (i.e. the
250 # C type of the result_code expression).
251 return self.result_ctype or self.type
253 def get_constant_c_result_code(self):
254 # Return the constant value of this node as a result code
255 # string, or None if the node is not constant. This method
256 # can be called when the constant result code is required
257 # before the code generation phase.
258 #
259 # The return value is a string that can represent a simple C
260 # value, a constant C name or a constant C expression. If the
261 # node type depends on Python code, this must return None.
262 return None
264 def calculate_constant_result(self):
265 # Calculate the constant compile time result value of this
266 # expression and store it in ``self.constant_result``. Does
267 # nothing by default, thus leaving ``self.constant_result``
268 # unknown. If valid, the result can be an arbitrary Python
269 # value.
270 #
271 # This must only be called when it is assured that all
272 # sub-expressions have a valid constant_result value. The
273 # ConstantFolding transform will do this.
274 pass
276 def compile_time_value(self, denv):
277 # Return value of compile-time expression, or report error.
278 error(self.pos, "Invalid compile-time expression")
280 def compile_time_value_error(self, e):
281 error(self.pos, "Error in compile-time expression: %s: %s" % (
282 e.__class__.__name__, e))
284 # ------------- Declaration Analysis ----------------
286 def analyse_target_declaration(self, env):
287 error(self.pos, "Cannot assign to or delete this")
289 # ------------- Expression Analysis ----------------
291 def analyse_const_expression(self, env):
292 # Called during the analyse_declarations phase of a
293 # constant expression. Analyses the expression's type,
294 # checks whether it is a legal const expression,
295 # and determines its value.
296 self.analyse_types(env)
297 return self.check_const()
299 def analyse_expressions(self, env):
300 # Convenience routine performing both the Type
301 # Analysis and Temp Allocation phases for a whole
302 # expression.
303 self.analyse_types(env)
305 def analyse_target_expression(self, env, rhs):
306 # Convenience routine performing both the Type
307 # Analysis and Temp Allocation phases for the LHS of
308 # an assignment.
309 self.analyse_target_types(env)
311 def analyse_boolean_expression(self, env):
312 # Analyse expression and coerce to a boolean.
313 self.analyse_types(env)
314 bool = self.coerce_to_boolean(env)
315 return bool
317 def analyse_temp_boolean_expression(self, env):
318 # Analyse boolean expression and coerce result into
319 # a temporary. This is used when a branch is to be
320 # performed on the result and we won't have an
321 # opportunity to ensure disposal code is executed
322 # afterwards. By forcing the result into a temporary,
323 # we ensure that all disposal has been done by the
324 # time we get the result.
325 self.analyse_types(env)
326 bool = self.coerce_to_boolean(env)
327 temp_bool = bool.coerce_to_temp(env)
328 return temp_bool
330 # --------------- Type Inference -----------------
332 def type_dependencies(self, env):
333 # Returns the list of entries whose types must be determined
334 # before the type of self can be infered.
335 if hasattr(self, 'type') and self.type is not None:
336 return ()
337 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
339 def infer_type(self, env):
340 # Attempt to deduce the type of self.
341 # Differs from analyse_types as it avoids unnecessary
342 # analysis of subexpressions, but can assume everything
343 # in self.type_dependencies() has been resolved.
344 if hasattr(self, 'type') and self.type is not None:
345 return self.type
346 elif hasattr(self, 'entry') and self.entry is not None:
347 return self.entry.type
348 else:
349 self.not_implemented("infer_type")
351 # --------------- Type Analysis ------------------
353 def analyse_as_module(self, env):
354 # If this node can be interpreted as a reference to a
355 # cimported module, return its scope, else None.
356 return None
358 def analyse_as_type(self, env):
359 # If this node can be interpreted as a reference to a
360 # type, return that type, else None.
361 return None
363 def analyse_as_extension_type(self, env):
364 # If this node can be interpreted as a reference to an
365 # extension type, return its type, else None.
366 return None
368 def analyse_types(self, env):
369 self.not_implemented("analyse_types")
371 def analyse_target_types(self, env):
372 self.analyse_types(env)
374 def nogil_check(self, env):
375 # By default, any expression based on Python objects is
376 # prevented in nogil environments. Subtypes must override
377 # this if they can work without the GIL.
378 if self.type.is_pyobject:
379 self.gil_error()
381 def gil_assignment_check(self, env):
382 if env.nogil and self.type.is_pyobject:
383 error(self.pos, "Assignment of Python object not allowed without gil")
385 def check_const(self):
386 self.not_const()
387 return False
389 def not_const(self):
390 error(self.pos, "Not allowed in a constant expression")
392 def check_const_addr(self):
393 self.addr_not_const()
394 return False
396 def addr_not_const(self):
397 error(self.pos, "Address is not constant")
399 # ----------------- Result Allocation -----------------
401 def result_in_temp(self):
402 # Return true if result is in a temporary owned by
403 # this node or one of its subexpressions. Overridden
404 # by certain nodes which can share the result of
405 # a subnode.
406 return self.is_temp
408 def target_code(self):
409 # Return code fragment for use as LHS of a C assignment.
410 return self.calculate_result_code()
412 def calculate_result_code(self):
413 self.not_implemented("calculate_result_code")
415 # def release_target_temp(self, env):
416 # # Release temporaries used by LHS of an assignment.
417 # self.release_subexpr_temps(env)
419 def allocate_temp_result(self, code):
420 if self.temp_code:
421 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
422 type = self.type
423 if not type.is_void:
424 if type.is_pyobject:
425 type = PyrexTypes.py_object_type
426 self.temp_code = code.funcstate.allocate_temp(
427 type, manage_ref=self.use_managed_ref)
428 else:
429 self.temp_code = None
431 def release_temp_result(self, code):
432 if not self.temp_code:
433 if self.old_temp:
434 raise RuntimeError("temp %s released multiple times in %s" % (
435 self.old_temp, self.__class__.__name__))
436 else:
437 raise RuntimeError("no temp, but release requested in %s" % (
438 self.__class__.__name__))
439 code.funcstate.release_temp(self.temp_code)
440 self.old_temp = self.temp_code
441 self.temp_code = None
443 # ---------------- Code Generation -----------------
445 def make_owned_reference(self, code):
446 # If result is a pyobject, make sure we own
447 # a reference to it.
448 if self.type.is_pyobject and not self.result_in_temp():
449 code.put_incref(self.result(), self.ctype())
451 def generate_evaluation_code(self, code):
452 code.mark_pos(self.pos)
454 # Generate code to evaluate this node and
455 # its sub-expressions, and dispose of any
456 # temporary results of its sub-expressions.
457 self.generate_subexpr_evaluation_code(code)
459 if self.is_temp:
460 self.allocate_temp_result(code)
462 self.generate_result_code(code)
463 if self.is_temp:
464 # If we are temp we do not need to wait until this node is disposed
465 # before disposing children.
466 self.generate_subexpr_disposal_code(code)
467 self.free_subexpr_temps(code)
469 def generate_subexpr_evaluation_code(self, code):
470 for node in self.subexpr_nodes():
471 node.generate_evaluation_code(code)
473 def generate_result_code(self, code):
474 self.not_implemented("generate_result_code")
476 def generate_disposal_code(self, code):
477 if self.is_temp:
478 if self.type.is_pyobject:
479 code.put_decref_clear(self.result(), self.ctype())
480 else:
481 # Already done if self.is_temp
482 self.generate_subexpr_disposal_code(code)
484 def generate_subexpr_disposal_code(self, code):
485 # Generate code to dispose of temporary results
486 # of all sub-expressions.
487 for node in self.subexpr_nodes():
488 node.generate_disposal_code(code)
490 def generate_post_assignment_code(self, code):
491 if self.is_temp:
492 if self.type.is_pyobject:
493 code.putln("%s = 0;" % self.result())
494 else:
495 self.generate_subexpr_disposal_code(code)
497 def generate_assignment_code(self, rhs, code):
498 # Stub method for nodes which are not legal as
499 # the LHS of an assignment. An error will have
500 # been reported earlier.
501 pass
503 def generate_deletion_code(self, code):
504 # Stub method for nodes that are not legal as
505 # the argument of a del statement. An error
506 # will have been reported earlier.
507 pass
509 def free_temps(self, code):
510 if self.is_temp:
511 if not self.type.is_void:
512 self.release_temp_result(code)
513 else:
514 self.free_subexpr_temps(code)
516 def free_subexpr_temps(self, code):
517 for sub in self.subexpr_nodes():
518 sub.free_temps(code)
520 # ---------------- Annotation ---------------------
522 def annotate(self, code):
523 for node in self.subexpr_nodes():
524 node.annotate(code)
526 # ----------------- Coercion ----------------------
528 def coerce_to(self, dst_type, env):
529 # Coerce the result so that it can be assigned to
530 # something of type dst_type. If processing is necessary,
531 # wraps this node in a coercion node and returns that.
532 # Otherwise, returns this node unchanged.
533 #
534 # This method is called during the analyse_expressions
535 # phase of the src_node's processing.
536 src = self
537 src_type = self.type
538 src_is_py_type = src_type.is_pyobject
539 dst_is_py_type = dst_type.is_pyobject
541 if self.check_for_coercion_error(dst_type):
542 return self
544 if dst_type.is_pyobject:
545 if not src.type.is_pyobject:
546 src = CoerceToPyTypeNode(src, env)
547 if not src.type.subtype_of(dst_type):
548 if not isinstance(src, NoneNode):
549 src = PyTypeTestNode(src, dst_type, env)
550 elif src.type.is_pyobject:
551 src = CoerceFromPyTypeNode(dst_type, src, env)
552 elif (dst_type.is_complex
553 and src_type != dst_type
554 and dst_type.assignable_from(src_type)):
555 src = CoerceToComplexNode(src, dst_type, env)
556 else: # neither src nor dst are py types
557 # Added the string comparison, since for c types that
558 # is enough, but Cython gets confused when the types are
559 # in different pxi files.
560 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
561 self.fail_assignment(dst_type)
562 return src
564 def fail_assignment(self, dst_type):
565 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
567 def check_for_coercion_error(self, dst_type, fail=False, default=None):
568 if fail and not default:
569 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
570 message = find_coercion_error((self.type, dst_type), default)
571 if message is not None:
572 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
573 return True
574 if fail:
575 self.fail_assignment(dst_type)
576 return True
577 return False
579 def coerce_to_pyobject(self, env):
580 return self.coerce_to(PyrexTypes.py_object_type, env)
582 def coerce_to_boolean(self, env):
583 # Coerce result to something acceptable as
584 # a boolean value.
585 type = self.type
586 if type.is_pyobject or type.is_ptr or type.is_float:
587 return CoerceToBooleanNode(self, env)
588 else:
589 if not type.is_int and not type.is_error:
590 error(self.pos,
591 "Type '%s' not acceptable as a boolean" % type)
592 return self
594 def coerce_to_integer(self, env):
595 # If not already some C integer type, coerce to longint.
596 if self.type.is_int:
597 return self
598 else:
599 return self.coerce_to(PyrexTypes.c_long_type, env)
601 def coerce_to_temp(self, env):
602 # Ensure that the result is in a temporary.
603 if self.result_in_temp():
604 return self
605 else:
606 return CoerceToTempNode(self, env)
608 def coerce_to_simple(self, env):
609 # Ensure that the result is simple (see is_simple).
610 if self.is_simple():
611 return self
612 else:
613 return self.coerce_to_temp(env)
615 def is_simple(self):
616 # A node is simple if its result is something that can
617 # be referred to without performing any operations, e.g.
618 # a constant, local var, C global var, struct member
619 # reference, or temporary.
620 return self.result_in_temp()
622 def as_cython_attribute(self):
623 return None
625 class AtomicExprNode(ExprNode):
626 # Abstract base class for expression nodes which have
627 # no sub-expressions.
629 subexprs = []
631 # Override to optimize -- we know we have no children
632 def generate_subexpr_evaluation_code(self, code):
633 pass
634 def generate_subexpr_disposal_code(self, code):
635 pass
637 class PyConstNode(AtomicExprNode):
638 # Abstract base class for constant Python values.
640 is_literal = 1
641 type = py_object_type
643 def is_simple(self):
644 return 1
646 def analyse_types(self, env):
647 pass
649 def calculate_result_code(self):
650 return self.value
652 def generate_result_code(self, code):
653 pass
656 class NoneNode(PyConstNode):
657 # The constant value None
659 value = "Py_None"
661 constant_result = None
663 nogil_check = None
665 def compile_time_value(self, denv):
666 return None
668 class EllipsisNode(PyConstNode):
669 # '...' in a subscript list.
671 value = "Py_Ellipsis"
673 constant_result = Ellipsis
675 def compile_time_value(self, denv):
676 return Ellipsis
679 class ConstNode(AtomicExprNode):
680 # Abstract base type for literal constant nodes.
681 #
682 # value string C code fragment
684 is_literal = 1
685 nogil_check = None
687 def is_simple(self):
688 return 1
690 def analyse_types(self, env):
691 pass # Types are held in class variables
693 def check_const(self):
694 return True
696 def get_constant_c_result_code(self):
697 return self.calculate_result_code()
699 def calculate_result_code(self):
700 return str(self.value)
702 def generate_result_code(self, code):
703 pass
706 class BoolNode(ConstNode):
707 type = PyrexTypes.c_bint_type
708 # The constant value True or False
710 def calculate_constant_result(self):
711 self.constant_result = self.value
713 def compile_time_value(self, denv):
714 return self.value
716 def calculate_result_code(self):
717 return str(int(self.value))
720 class NullNode(ConstNode):
721 type = PyrexTypes.c_null_ptr_type
722 value = "NULL"
723 constant_result = 0
725 def get_constant_c_result_code(self):
726 return self.value
729 class CharNode(ConstNode):
730 type = PyrexTypes.c_char_type
732 def calculate_constant_result(self):
733 self.constant_result = ord(self.value)
735 def compile_time_value(self, denv):
736 return ord(self.value)
738 def calculate_result_code(self):
739 return "'%s'" % StringEncoding.escape_char(self.value)
742 class IntNode(ConstNode):
744 # unsigned "" or "U"
745 # longness "" or "L" or "LL"
747 unsigned = ""
748 longness = ""
749 type = PyrexTypes.c_long_type
751 def coerce_to(self, dst_type, env):
752 if dst_type.is_numeric and not dst_type.is_complex:
753 self.type = PyrexTypes.c_long_type
754 return self
755 # Arrange for a Python version of the number to be pre-allocated
756 # when coercing to a Python type.
757 if dst_type.is_pyobject:
758 self.type = PyrexTypes.py_object_type
759 # We still need to perform normal coerce_to processing on the
760 # result, because we might be coercing to an extension type,
761 # in which case a type test node will be needed.
762 return ConstNode.coerce_to(self, dst_type, env)
764 def coerce_to_boolean(self, env):
765 self.type = PyrexTypes.c_bint_type
766 return self
768 def generate_evaluation_code(self, code):
769 if self.type.is_pyobject:
770 self.result_code = code.get_py_num(self.value, self.longness)
771 else:
772 self.result_code = self.get_constant_c_result_code()
774 def get_constant_c_result_code(self):
775 value = self.value
776 if isinstance(value, basestring) and len(value) > 2:
777 # must convert C-incompatible Py3 oct/bin notations
778 if value[1] in 'oO':
779 value = value[0] + value[2:] # '0o123' => '0123'
780 elif value[1] in 'bB':
781 value = int(value[2:], 2)
782 return str(value) + self.unsigned + self.longness
784 def calculate_result_code(self):
785 return self.result_code
787 def calculate_constant_result(self):
788 self.constant_result = Utils.str_to_number(self.value)
790 def compile_time_value(self, denv):
791 return Utils.str_to_number(self.value)
794 class FloatNode(ConstNode):
795 type = PyrexTypes.c_double_type
797 def calculate_constant_result(self):
798 self.constant_result = float(self.value)
800 def compile_time_value(self, denv):
801 return float(self.value)
803 def calculate_result_code(self):
804 strval = repr(float(self.value))
805 if strval == 'nan':
806 return "(Py_HUGE_VAL * 0)"
807 elif strval == 'inf':
808 return "Py_HUGE_VAL"
809 elif strval == '-inf':
810 return "(-Py_HUGE_VAL)"
811 else:
812 return strval
815 class BytesNode(ConstNode):
816 # A char* or bytes literal
817 #
818 # value BytesLiteral
820 type = PyrexTypes.c_char_ptr_type
822 def compile_time_value(self, denv):
823 return self.value
825 def analyse_as_type(self, env):
826 type = PyrexTypes.parse_basic_type(self.value)
827 if type is not None:
828 return type
829 from TreeFragment import TreeFragment
830 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
831 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
832 sizeof_node = declaration.root.stats[0].expr
833 sizeof_node.analyse_types(env)
834 if isinstance(sizeof_node, SizeofTypeNode):
835 return sizeof_node.arg_type
837 def can_coerce_to_char_literal(self):
838 return len(self.value) == 1
840 def coerce_to(self, dst_type, env):
841 if dst_type == PyrexTypes.c_char_ptr_type:
842 self.type = PyrexTypes.c_char_ptr_type
843 return self
844 elif dst_type == PyrexTypes.c_uchar_ptr_type:
845 self.type = PyrexTypes.c_char_ptr_type
846 return CastNode(self, PyrexTypes.c_uchar_ptr_type)
848 if dst_type.is_int:
849 if not self.can_coerce_to_char_literal():
850 error(self.pos, "Only single-character strings can be coerced into ints.")
851 return self
852 return CharNode(self.pos, value=self.value)
854 node = self
855 if not self.type.is_pyobject:
856 if dst_type in (py_object_type, Builtin.bytes_type):
857 node = self.as_py_string_node(env)
858 elif dst_type.is_pyobject:
859 self.fail_assignment(dst_type)
860 return self
861 else:
862 node = self
863 elif dst_type.is_pyobject and dst_type is not py_object_type:
864 self.check_for_coercion_error(dst_type, fail=True)
865 return self
867 # We still need to perform normal coerce_to processing on the
868 # result, because we might be coercing to an extension type,
869 # in which case a type test node will be needed.
870 return ConstNode.coerce_to(node, dst_type, env)
872 def as_py_string_node(self, env):
873 # Return a new BytesNode with the same value as this node
874 # but whose type is a Python type instead of a C type.
875 return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
877 def generate_evaluation_code(self, code):
878 if self.type.is_pyobject:
879 self.result_code = code.get_py_string_const(self.value)
880 else:
881 self.result_code = code.get_string_const(self.value)
883 def get_constant_c_result_code(self):
884 return None # FIXME
886 def calculate_result_code(self):
887 return self.result_code
890 class UnicodeNode(PyConstNode):
891 # A Python unicode object
892 #
893 # value EncodedString
895 type = unicode_type
897 def coerce_to(self, dst_type, env):
898 if dst_type is self.type:
899 pass
900 elif not dst_type.is_pyobject:
901 error(self.pos, "Unicode objects do not support coercion to C types.")
902 elif dst_type is not py_object_type:
903 if not self.check_for_coercion_error(dst_type):
904 self.fail_assignment(dst_type)
905 return self
907 def generate_evaluation_code(self, code):
908 self.result_code = code.get_py_string_const(self.value)
910 def calculate_result_code(self):
911 return self.result_code
913 def compile_time_value(self, env):
914 return self.value
917 class StringNode(PyConstNode):
918 # A Python str object, i.e. a byte string in Python 2.x and a
919 # unicode string in Python 3.x
920 #
921 # value BytesLiteral or EncodedString
922 # is_identifier boolean
924 type = str_type
925 is_identifier = None
927 def coerce_to(self, dst_type, env):
928 if dst_type is not py_object_type and dst_type is not str_type:
929 # if dst_type is Builtin.bytes_type:
930 # # special case: bytes = 'str literal'
931 # return BytesNode(self.pos, value=self.value)
932 if not dst_type.is_pyobject:
933 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
934 self.check_for_coercion_error(dst_type, fail=True)
936 # this will be a unicode string in Py3, so make sure we can decode it
937 if self.value.encoding:
938 encoding = self.value.encoding
939 try:
940 self.value.decode(encoding)
941 except UnicodeDecodeError:
942 error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
944 return self
946 def can_coerce_to_char_literal(self):
947 return not self.is_identifier and len(self.value) == 1
949 def generate_evaluation_code(self, code):
950 self.result_code = code.get_py_string_const(
951 self.value, identifier=self.is_identifier, is_str=True)
953 def get_constant_c_result_code(self):
954 return None
956 def calculate_result_code(self):
957 return self.result_code
959 def compile_time_value(self, env):
960 return self.value
963 class IdentifierStringNode(StringNode):
964 # A special str value that represents an identifier (bytes in Py2,
965 # unicode in Py3).
966 is_identifier = True
969 class LongNode(AtomicExprNode):
970 # Python long integer literal
971 #
972 # value string
974 type = py_object_type
976 def calculate_constant_result(self):
977 self.constant_result = Utils.str_to_number(self.value)
979 def compile_time_value(self, denv):
980 return Utils.str_to_number(self.value)
982 def analyse_types(self, env):
983 self.is_temp = 1
985 gil_message = "Constructing Python long int"
987 def generate_result_code(self, code):
988 code.putln(
989 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
990 self.result(),
991 self.value,
992 code.error_goto_if_null(self.result(), self.pos)))
993 code.put_gotref(self.py_result())
996 class ImagNode(AtomicExprNode):
997 # Imaginary number literal
998 #
999 # value float imaginary part
1001 type = PyrexTypes.c_double_complex_type
1003 def calculate_constant_result(self):
1004 self.constant_result = complex(0.0, self.value)
1006 def compile_time_value(self, denv):
1007 return complex(0.0, self.value)
1009 def analyse_types(self, env):
1010 self.type.create_declaration_utility_code(env)
1012 def coerce_to(self, dst_type, env):
1013 # Arrange for a Python version of the number to be pre-allocated
1014 # when coercing to a Python type.
1015 if dst_type.is_pyobject:
1016 self.is_temp = 1
1017 self.type = PyrexTypes.py_object_type
1018 # We still need to perform normal coerce_to processing on the
1019 # result, because we might be coercing to an extension type,
1020 # in which case a type test node will be needed.
1021 return AtomicExprNode.coerce_to(self, dst_type, env)
1023 gil_message = "Constructing complex number"
1025 def calculate_result_code(self):
1026 if self.type.is_pyobject:
1027 return self.result()
1028 else:
1029 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1031 def generate_result_code(self, code):
1032 if self.type.is_pyobject:
1033 code.putln(
1034 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1035 self.result(),
1036 float(self.value),
1037 code.error_goto_if_null(self.result(), self.pos)))
1038 code.put_gotref(self.py_result())
1042 class NameNode(AtomicExprNode):
1043 # Reference to a local or global variable name.
1044 #
1045 # name string Python name of the variable
1046 # entry Entry Symbol table entry
1047 # type_entry Entry For extension type names, the original type entry
1049 is_name = True
1050 is_cython_module = False
1051 cython_attribute = None
1052 lhs_of_first_assignment = False
1053 is_used_as_rvalue = 0
1054 entry = None
1055 type_entry = None
1057 def create_analysed_rvalue(pos, env, entry):
1058 node = NameNode(pos)
1059 node.analyse_types(env, entry=entry)
1060 return node
1062 def as_cython_attribute(self):
1063 return self.cython_attribute
1065 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1067 def type_dependencies(self, env):
1068 if self.entry is None:
1069 self.entry = env.lookup(self.name)
1070 if self.entry is not None and self.entry.type.is_unspecified:
1071 return (self.entry,)
1072 else:
1073 return ()
1075 def infer_type(self, env):
1076 if self.entry is None:
1077 self.entry = env.lookup(self.name)
1078 if self.entry is None:
1079 return py_object_type
1080 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1081 self.name == self.entry.type.name:
1082 # Unfortunately the type attribute of type objects
1083 # is used for the pointer to the type the represent.
1084 return type_type
1085 else:
1086 return self.entry.type
1088 def compile_time_value(self, denv):
1089 try:
1090 return denv.lookup(self.name)
1091 except KeyError:
1092 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1094 def get_constant_c_result_code(self):
1095 if not self.entry or self.entry.type.is_pyobject:
1096 return None
1097 return self.entry.cname
1099 def coerce_to(self, dst_type, env):
1100 # If coercing to a generic pyobject and this is a builtin
1101 # C function with a Python equivalent, manufacture a NameNode
1102 # referring to the Python builtin.
1103 #print "NameNode.coerce_to:", self.name, dst_type ###
1104 if dst_type is py_object_type:
1105 entry = self.entry
1106 if entry and entry.is_cfunction:
1107 var_entry = entry.as_variable
1108 if var_entry:
1109 if var_entry.is_builtin and Options.cache_builtins:
1110 var_entry = env.declare_builtin(var_entry.name, self.pos)
1111 node = NameNode(self.pos, name = self.name)
1112 node.entry = var_entry
1113 node.analyse_rvalue_entry(env)
1114 return node
1115 return super(NameNode, self).coerce_to(dst_type, env)
1117 def analyse_as_module(self, env):
1118 # Try to interpret this as a reference to a cimported module.
1119 # Returns the module scope, or None.
1120 entry = self.entry
1121 if not entry:
1122 entry = env.lookup(self.name)
1123 if entry and entry.as_module:
1124 return entry.as_module
1125 return None
1127 def analyse_as_type(self, env):
1128 if self.cython_attribute:
1129 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1130 else:
1131 type = PyrexTypes.parse_basic_type(self.name)
1132 if type:
1133 return type
1134 entry = self.entry
1135 if not entry:
1136 entry = env.lookup(self.name)
1137 if entry and entry.is_type:
1138 return entry.type
1139 else:
1140 return None
1142 def analyse_as_extension_type(self, env):
1143 # Try to interpret this as a reference to an extension type.
1144 # Returns the extension type, or None.
1145 entry = self.entry
1146 if not entry:
1147 entry = env.lookup(self.name)
1148 if entry and entry.is_type and entry.type.is_extension_type:
1149 return entry.type
1150 else:
1151 return None
1153 def analyse_target_declaration(self, env):
1154 if not self.entry:
1155 self.entry = env.lookup_here(self.name)
1156 if not self.entry:
1157 if env.directives['infer_types']:
1158 type = unspecified_type
1159 else:
1160 type = py_object_type
1161 self.entry = env.declare_var(self.name, type, self.pos)
1162 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1163 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1164 if self.entry.is_declared_generic:
1165 self.result_ctype = py_object_type
1167 def analyse_types(self, env):
1168 if self.entry is None:
1169 self.entry = env.lookup(self.name)
1170 if not self.entry:
1171 self.entry = env.declare_builtin(self.name, self.pos)
1172 if not self.entry:
1173 self.type = PyrexTypes.error_type
1174 return
1175 entry = self.entry
1176 if entry:
1177 entry.used = 1
1178 if entry.type.is_buffer:
1179 import Buffer
1180 Buffer.used_buffer_aux_vars(entry)
1181 if entry.utility_code:
1182 env.use_utility_code(entry.utility_code)
1183 self.analyse_rvalue_entry(env)
1185 def analyse_target_types(self, env):
1186 self.analyse_entry(env)
1187 if not self.is_lvalue():
1188 error(self.pos, "Assignment to non-lvalue '%s'"
1189 % self.name)
1190 self.type = PyrexTypes.error_type
1191 self.entry.used = 1
1192 if self.entry.type.is_buffer:
1193 import Buffer
1194 Buffer.used_buffer_aux_vars(self.entry)
1196 def analyse_rvalue_entry(self, env):
1197 #print "NameNode.analyse_rvalue_entry:", self.name ###
1198 #print "Entry:", self.entry.__dict__ ###
1199 self.analyse_entry(env)
1200 entry = self.entry
1201 if entry.is_declared_generic:
1202 self.result_ctype = py_object_type
1203 if entry.is_pyglobal or entry.is_builtin:
1204 if Options.cache_builtins and entry.is_builtin:
1205 self.is_temp = 0
1206 else:
1207 self.is_temp = 1
1208 self.is_used_as_rvalue = 1
1209 env.use_utility_code(get_name_interned_utility_code)
1211 def nogil_check(self, env):
1212 if self.is_used_as_rvalue:
1213 entry = self.entry
1214 if entry.is_builtin:
1215 # if not Options.cache_builtins: # cached builtins are ok
1216 self.gil_error()
1217 elif entry.is_pyglobal:
1218 self.gil_error()
1220 gil_message = "Accessing Python global or builtin"
1222 def analyse_entry(self, env):
1223 #print "NameNode.analyse_entry:", self.name ###
1224 self.check_identifier_kind()
1225 entry = self.entry
1226 type = entry.type
1227 self.type = type
1229 def check_identifier_kind(self):
1230 # Check that this is an appropriate kind of name for use in an
1231 # expression. Also finds the variable entry associated with
1232 # an extension type.
1233 entry = self.entry
1234 if entry.is_type and entry.type.is_extension_type:
1235 self.type_entry = entry
1236 if not (entry.is_const or entry.is_variable
1237 or entry.is_builtin or entry.is_cfunction):
1238 if self.entry.as_variable:
1239 self.entry = self.entry.as_variable
1240 else:
1241 error(self.pos,
1242 "'%s' is not a constant, variable or function identifier" % self.name)
1244 def is_simple(self):
1245 # If it's not a C variable, it'll be in a temp.
1246 return 1
1248 def calculate_target_results(self, env):
1249 pass
1251 def check_const(self):
1252 entry = self.entry
1253 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1254 self.not_const()
1255 return False
1256 return True
1258 def check_const_addr(self):
1259 entry = self.entry
1260 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1261 self.addr_not_const()
1262 return False
1263 return True
1265 def is_lvalue(self):
1266 return self.entry.is_variable and \
1267 not self.entry.type.is_array and \
1268 not self.entry.is_readonly
1270 def is_ephemeral(self):
1271 # Name nodes are never ephemeral, even if the
1272 # result is in a temporary.
1273 return 0
1275 def calculate_result_code(self):
1276 entry = self.entry
1277 if not entry:
1278 return "<error>" # There was an error earlier
1279 return entry.cname
1281 def generate_result_code(self, code):
1282 assert hasattr(self, 'entry')
1283 entry = self.entry
1284 if entry is None:
1285 return # There was an error earlier
1286 if entry.is_builtin and Options.cache_builtins:
1287 return # Lookup already cached
1288 elif entry.is_pyglobal or entry.is_builtin:
1289 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1290 interned_cname = code.intern_identifier(self.entry.name)
1291 if entry.is_builtin:
1292 namespace = Naming.builtins_cname
1293 else: # entry.is_pyglobal
1294 namespace = entry.scope.namespace_cname
1295 code.putln(
1296 '%s = __Pyx_GetName(%s, %s); %s' % (
1297 self.result(),
1298 namespace,
1299 interned_cname,
1300 code.error_goto_if_null(self.result(), self.pos)))
1301 code.put_gotref(self.py_result())
1303 elif entry.is_local and False:
1304 # control flow not good enough yet
1305 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1306 if assigned is False:
1307 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1308 elif not Options.init_local_none and assigned is None:
1309 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1310 (entry.cname, entry.name, code.error_goto(self.pos)))
1311 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1313 def generate_assignment_code(self, rhs, code):
1314 #print "NameNode.generate_assignment_code:", self.name ###
1315 entry = self.entry
1316 if entry is None:
1317 return # There was an error earlier
1319 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1320 and not self.lhs_of_first_assignment):
1321 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1323 # is_pyglobal seems to be True for module level-globals only.
1324 # We use this to access class->tp_dict if necessary.
1325 if entry.is_pyglobal:
1326 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1327 interned_cname = code.intern_identifier(self.entry.name)
1328 namespace = self.entry.scope.namespace_cname
1329 if entry.is_member:
1330 # if the entry is a member we have to cheat: SetAttr does not work
1331 # on types, so we create a descriptor which is then added to tp_dict
1332 code.put_error_if_neg(self.pos,
1333 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1334 namespace,
1335 interned_cname,
1336 rhs.py_result()))
1337 rhs.generate_disposal_code(code)
1338 rhs.free_temps(code)
1339 # in Py2.6+, we need to invalidate the method cache
1340 code.putln("PyType_Modified(%s);" %
1341 entry.scope.parent_type.typeptr_cname)
1342 else:
1343 code.put_error_if_neg(self.pos,
1344 'PyObject_SetAttr(%s, %s, %s)' % (
1345 namespace,
1346 interned_cname,
1347 rhs.py_result()))
1348 if debug_disposal_code:
1349 print("NameNode.generate_assignment_code:")
1350 print("...generating disposal code for %s" % rhs)
1351 rhs.generate_disposal_code(code)
1352 rhs.free_temps(code)
1353 else:
1354 if self.type.is_buffer:
1355 # Generate code for doing the buffer release/acquisition.
1356 # This might raise an exception in which case the assignment (done
1357 # below) will not happen.
1358 #
1359 # The reason this is not in a typetest-like node is because the
1360 # variables that the acquired buffer info is stored to is allocated
1361 # per entry and coupled with it.
1362 self.generate_acquire_buffer(rhs, code)
1364 if self.type.is_pyobject:
1365 #print "NameNode.generate_assignment_code: to", self.name ###
1366 #print "...from", rhs ###
1367 #print "...LHS type", self.type, "ctype", self.ctype() ###
1368 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1369 if self.use_managed_ref:
1370 rhs.make_owned_reference(code)
1371 if entry.is_cglobal:
1372 code.put_gotref(self.py_result())
1373 if self.use_managed_ref and not self.lhs_of_first_assignment:
1374 if entry.is_local and not Options.init_local_none:
1375 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1376 if initalized is True:
1377 code.put_decref(self.result(), self.ctype())
1378 elif initalized is None:
1379 code.put_xdecref(self.result(), self.ctype())
1380 else:
1381 code.put_decref(self.result(), self.ctype())
1382 if self.use_managed_ref:
1383 if entry.is_cglobal or entry.in_closure:
1384 code.put_giveref(rhs.py_result())
1385 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1386 if debug_disposal_code:
1387 print("NameNode.generate_assignment_code:")
1388 print("...generating post-assignment code for %s" % rhs)
1389 rhs.generate_post_assignment_code(code)
1390 rhs.free_temps(code)
1392 def generate_acquire_buffer(self, rhs, code):
1393 # rhstmp is only used in case the rhs is a complicated expression leading to
1394 # the object, to avoid repeating the same C expression for every reference
1395 # to the rhs. It does NOT hold a reference.
1396 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1397 if pretty_rhs:
1398 rhstmp = rhs.result_as(self.ctype())
1399 else:
1400 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1401 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1403 buffer_aux = self.entry.buffer_aux
1404 bufstruct = buffer_aux.buffer_info_var.cname
1405 import Buffer
1406 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1407 is_initialized=not self.lhs_of_first_assignment,
1408 pos=self.pos, code=code)
1410 if not pretty_rhs:
1411 code.putln("%s = 0;" % rhstmp)
1412 code.funcstate.release_temp(rhstmp)
1414 def generate_deletion_code(self, code):
1415 if self.entry is None:
1416 return # There was an error earlier
1417 if not self.entry.is_pyglobal:
1418 error(self.pos, "Deletion of local or C global name not supported")
1419 return
1420 code.put_error_if_neg(self.pos,
1421 '__Pyx_DelAttrString(%s, "%s")' % (
1422 Naming.module_cname,
1423 self.entry.name))
1425 def annotate(self, code):
1426 if hasattr(self, 'is_called') and self.is_called:
1427 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1428 if self.type.is_pyobject:
1429 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1430 else:
1431 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1433 class BackquoteNode(ExprNode):
1434 # `expr`
1435 #
1436 # arg ExprNode
1438 type = py_object_type
1440 subexprs = ['arg']
1442 def analyse_types(self, env):
1443 self.arg.analyse_types(env)
1444 self.arg = self.arg.coerce_to_pyobject(env)
1445 self.is_temp = 1
1447 gil_message = "Backquote expression"
1449 def calculate_constant_result(self):
1450 self.constant_result = repr(self.arg.constant_result)
1452 def generate_result_code(self, code):
1453 code.putln(
1454 "%s = PyObject_Repr(%s); %s" % (
1455 self.result(),
1456 self.arg.py_result(),
1457 code.error_goto_if_null(self.result(), self.pos)))
1458 code.put_gotref(self.py_result())
1462 class ImportNode(ExprNode):
1463 # Used as part of import statement implementation.
1464 # Implements result =
1465 # __import__(module_name, globals(), None, name_list)
1466 #
1467 # module_name StringNode dotted name of module
1468 # name_list ListNode or None list of names to be imported
1470 type = py_object_type
1472 subexprs = ['module_name', 'name_list']
1474 def analyse_types(self, env):
1475 self.module_name.analyse_types(env)
1476 self.module_name = self.module_name.coerce_to_pyobject(env)
1477 if self.name_list:
1478 self.name_list.analyse_types(env)
1479 self.name_list.coerce_to_pyobject(env)
1480 self.is_temp = 1
1481 env.use_utility_code(import_utility_code)
1483 gil_message = "Python import"
1485 def generate_result_code(self, code):
1486 if self.name_list:
1487 name_list_code = self.name_list.py_result()
1488 else:
1489 name_list_code = "0"
1490 code.putln(
1491 "%s = __Pyx_Import(%s, %s); %s" % (
1492 self.result(),
1493 self.module_name.py_result(),
1494 name_list_code,
1495 code.error_goto_if_null(self.result(), self.pos)))
1496 code.put_gotref(self.py_result())
1499 class IteratorNode(ExprNode):
1500 # Used as part of for statement implementation.
1501 #
1502 # allocate_counter_temp/release_counter_temp needs to be called
1503 # by parent (ForInStatNode)
1504 #
1505 # Implements result = iter(sequence)
1506 #
1507 # sequence ExprNode
1509 type = py_object_type
1511 subexprs = ['sequence']
1513 def analyse_types(self, env):
1514 self.sequence.analyse_types(env)
1515 self.sequence = self.sequence.coerce_to_pyobject(env)
1516 self.is_temp = 1
1518 gil_message = "Iterating over Python object"
1520 def allocate_counter_temp(self, code):
1521 self.counter_cname = code.funcstate.allocate_temp(
1522 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1524 def release_counter_temp(self, code):
1525 code.funcstate.release_temp(self.counter_cname)
1527 def generate_result_code(self, code):
1528 is_builtin_sequence = self.sequence.type is list_type or \
1529 self.sequence.type is tuple_type
1530 may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
1531 if is_builtin_sequence:
1532 code.putln(
1533 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1534 elif may_be_a_sequence:
1535 code.putln(
1536 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1537 self.sequence.py_result(),
1538 self.sequence.py_result()))
1539 if may_be_a_sequence:
1540 code.putln(
1541 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1542 self.counter_cname,
1543 self.result(),
1544 self.sequence.py_result(),
1545 self.result()))
1546 code.putln("} else {")
1547 if is_builtin_sequence:
1548 code.putln(
1549 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1550 code.error_goto(self.pos))
1551 else:
1552 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1553 self.counter_cname,
1554 self.result(),
1555 self.sequence.py_result(),
1556 code.error_goto_if_null(self.result(), self.pos)))
1557 code.put_gotref(self.py_result())
1558 if may_be_a_sequence:
1559 code.putln("}")
1562 class NextNode(AtomicExprNode):
1563 # Used as part of for statement implementation.
1564 # Implements result = iterator.next()
1565 # Created during analyse_types phase.
1566 # The iterator is not owned by this node.
1567 #
1568 # iterator ExprNode
1570 type = py_object_type
1572 def __init__(self, iterator, env):
1573 self.pos = iterator.pos
1574 self.iterator = iterator
1575 self.is_temp = 1
1577 def generate_result_code(self, code):
1578 sequence_type = self.iterator.sequence.type
1579 if sequence_type is list_type:
1580 type_checks = [(list_type, "List")]
1581 elif sequence_type is tuple_type:
1582 type_checks = [(tuple_type, "Tuple")]
1583 elif not sequence_type.is_builtin_type:
1584 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1585 else:
1586 type_checks = []
1588 for py_type, prefix in type_checks:
1589 if len(type_checks) > 1:
1590 code.putln(
1591 "if (likely(Py%s_CheckExact(%s))) {" % (
1592 prefix, self.iterator.py_result()))
1593 code.putln(
1594 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1595 self.iterator.counter_cname,
1596 prefix,
1597 self.iterator.py_result()))
1598 code.putln(
1599 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1600 self.result(),
1601 prefix,
1602 self.iterator.py_result(),
1603 self.iterator.counter_cname,
1604 self.result(),
1605 self.iterator.counter_cname))
1606 if len(type_checks) > 1:
1607 code.put("} else ")
1608 if len(type_checks) == 1:
1609 return
1610 code.putln("{")
1611 code.putln(
1612 "%s = PyIter_Next(%s);" % (
1613 self.result(),
1614 self.iterator.py_result()))
1615 code.putln(
1616 "if (!%s) {" %
1617 self.result())
1618 code.putln(code.error_goto_if_PyErr(self.pos))
1619 code.putln("break;")
1620 code.putln("}")
1621 code.put_gotref(self.py_result())
1622 code.putln("}")
1625 class ExcValueNode(AtomicExprNode):
1626 # Node created during analyse_types phase
1627 # of an ExceptClauseNode to fetch the current
1628 # exception value.
1630 type = py_object_type
1632 def __init__(self, pos, env):
1633 ExprNode.__init__(self, pos)
1635 def set_var(self, var):
1636 self.var = var
1638 def calculate_result_code(self):
1639 return self.var
1641 def generate_result_code(self, code):
1642 pass
1644 def analyse_types(self, env):
1645 pass
1648 class TempNode(ExprNode):
1649 # Node created during analyse_types phase
1650 # of some nodes to hold a temporary value.
1651 #
1652 # Note: One must call "allocate" and "release" on
1653 # the node during code generation to get/release the temp.
1654 # This is because the temp result is often used outside of
1655 # the regular cycle.
1657 subexprs = []
1659 def __init__(self, pos, type, env):
1660 ExprNode.__init__(self, pos)
1661 self.type = type
1662 if type.is_pyobject:
1663 self.result_ctype = py_object_type
1664 self.is_temp = 1
1666 def analyse_types(self, env):
1667 return self.type
1669 def generate_result_code(self, code):
1670 pass
1672 def allocate(self, code):
1673 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1675 def release(self, code):
1676 code.funcstate.release_temp(self.temp_cname)
1677 self.temp_cname = None
1679 def result(self):
1680 try:
1681 return self.temp_cname
1682 except:
1683 assert False, "Remember to call allocate/release on TempNode"
1684 raise
1686 # Do not participate in normal temp alloc/dealloc:
1687 def allocate_temp_result(self, code):
1688 pass
1690 def release_temp_result(self, code):
1691 pass
1693 class PyTempNode(TempNode):
1694 # TempNode holding a Python value.
1696 def __init__(self, pos, env):
1697 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1699 class RawCNameExprNode(ExprNode):
1700 subexprs = []
1702 def __init__(self, pos, type=None):
1703 self.pos = pos
1704 self.type = type
1706 def analyse_types(self, env):
1707 return self.type
1709 def set_cname(self, cname):
1710 self.cname = cname
1712 def result(self):
1713 return self.cname
1715 def generate_result_code(self, code):
1716 pass
1719 #-------------------------------------------------------------------
1720 #
1721 # Trailer nodes
1722 #
1723 #-------------------------------------------------------------------
1725 class IndexNode(ExprNode):
1726 # Sequence indexing.
1727 #
1728 # base ExprNode
1729 # index ExprNode
1730 # indices [ExprNode]
1731 # is_buffer_access boolean Whether this is a buffer access.
1732 #
1733 # indices is used on buffer access, index on non-buffer access.
1734 # The former contains a clean list of index parameters, the
1735 # latter whatever Python object is needed for index access.
1737 subexprs = ['base', 'index', 'indices']
1738 indices = None
1740 def __init__(self, pos, index, *args, **kw):
1741 ExprNode.__init__(self, pos, index=index, *args, **kw)
1742 self._index = index
1744 def calculate_constant_result(self):
1745 self.constant_result = \
1746 self.base.constant_result[self.index.constant_result]
1748 def compile_time_value(self, denv):
1749 base = self.base.compile_time_value(denv)
1750 index = self.index.compile_time_value(denv)
1751 try:
1752 return base[index]
1753 except Exception, e:
1754 self.compile_time_value_error(e)
1756 def is_ephemeral(self):
1757 return self.base.is_ephemeral()
1759 def analyse_target_declaration(self, env):
1760 pass
1762 def analyse_as_type(self, env):
1763 base_type = self.base.analyse_as_type(env)
1764 if base_type and not base_type.is_pyobject:
1765 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1766 return None
1768 def type_dependencies(self, env):
1769 return self.base.type_dependencies(env)
1771 def infer_type(self, env):
1772 if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1773 return py_object_type
1774 base_type = self.base.infer_type(env)
1775 if base_type.is_ptr or base_type.is_array:
1776 return base_type.base_type
1777 else:
1778 # TODO: Handle buffers (hopefully without too much redundancy).
1779 return py_object_type
1781 def analyse_types(self, env):
1782 self.analyse_base_and_index_types(env, getting = 1)
1784 def analyse_target_types(self, env):
1785 self.analyse_base_and_index_types(env, setting = 1)
1787 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1788 # Note: This might be cleaned up by having IndexNode
1789 # parsed in a saner way and only construct the tuple if
1790 # needed.
1792 # Note that this function must leave IndexNode in a cloneable state.
1793 # For buffers, self.index is packed out on the initial analysis, and
1794 # when cloning self.indices is copied.
1795 self.is_buffer_access = False
1797 self.base.analyse_types(env)
1798 if self.base.type.is_error:
1799 # Do not visit child tree if base is undeclared to avoid confusing
1800 # error messages
1801 self.type = PyrexTypes.error_type
1802 return
1804 # Handle the case where base is a literal char* (and we expect a string, not an int)
1805 if isinstance(self.base, BytesNode):
1806 self.base = self.base.coerce_to_pyobject(env)
1808 skip_child_analysis = False
1809 buffer_access = False
1810 if self.base.type.is_buffer:
1811 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1812 if self.indices:
1813 indices = self.indices
1814 else:
1815 if isinstance(self.index, TupleNode):
1816 indices = self.index.args
1817 else:
1818 indices = [self.index]
1819 if len(indices) == self.base.type.ndim:
1820 buffer_access = True
1821 skip_child_analysis = True
1822 for x in indices:
1823 x.analyse_types(env)
1824 if not x.type.is_int:
1825 buffer_access = False
1827 # On cloning, indices is cloned. Otherwise, unpack index into indices
1828 assert not (buffer_access and isinstance(self.index, CloneNode))
1830 if buffer_access:
1831 self.indices = indices
1832 self.index = None
1833 self.type = self.base.type.dtype
1834 self.is_buffer_access = True
1835 self.buffer_type = self.base.entry.type
1837 if getting and self.type.is_pyobject:
1838 self.is_temp = True
1839 if setting:
1840 if not self.base.entry.type.writable:
1841 error(self.pos, "Writing to readonly buffer")
1842 else:
1843 self.base.entry.buffer_aux.writable_needed = True
1844 else:
1845 if isinstance(self.index, TupleNode):
1846 self.index.analyse_types(env, skip_children=skip_child_analysis)
1847 elif not skip_child_analysis:
1848 self.index.analyse_types(env)
1849 self.original_index_type = self.index.type
1850 if self.base.type.is_pyobject:
1851 if self.index.type.is_int:
1852 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1853 else:
1854 self.index = self.index.coerce_to_pyobject(env)
1855 self.type = py_object_type
1856 self.is_temp = 1
1857 else:
1858 if self.base.type.is_ptr or self.base.type.is_array:
1859 self.type = self.base.type.base_type
1860 else:
1861 error(self.pos,
1862 "Attempting to index non-array type '%s'" %
1863 self.base.type)
1864 self.type = PyrexTypes.error_type
1865 if self.index.type.is_pyobject:
1866 self.index = self.index.coerce_to(
1867 PyrexTypes.c_py_ssize_t_type, env)
1868 if not self.index.type.is_int:
1869 error(self.pos,
1870 "Invalid index type '%s'" %
1871 self.index.type)
1872 gil_message = "Indexing Python object"
1874 def nogil_check(self, env):
1875 if self.is_buffer_access:
1876 if env.directives['boundscheck']:
1877 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1878 return
1879 elif self.type.is_pyobject:
1880 error(self.pos, "Cannot access buffer with object dtype without gil")
1881 return
1882 super(IndexNode, self).nogil_check(env)
1885 def check_const_addr(self):
1886 return self.base.check_const_addr() and self.index.check_const()
1888 def is_lvalue(self):
1889 return 1
1891 def calculate_result_code(self):
1892 if self.is_buffer_access:
1893 return "(*%s)" % self.buffer_ptr_code
1894 else:
1895 return "(%s[%s])" % (
1896 self.base.result(), self.index.result())
1898 def extra_index_params(self):
1899 if self.index.type.is_int:
1900 if self.original_index_type.signed:
1901 size_adjustment = ""
1902 else:
1903 size_adjustment = "+1"
1904 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1905 else:
1906 return ""
1908 def generate_subexpr_evaluation_code(self, code):
1909 self.base.generate_evaluation_code(code)
1910 if not self.indices:
1911 self.index.generate_evaluation_code(code)
1912 else:
1913 for i in self.indices:
1914 i.generate_evaluation_code(code)
1916 def generate_subexpr_disposal_code(self, code):
1917 self.base.generate_disposal_code(code)
1918 if not self.indices:
1919 self.index.generate_disposal_code(code)
1920 else:
1921 for i in self.indices:
1922 i.generate_disposal_code(code)
1924 def free_subexpr_temps(self, code):
1925 self.base.free_temps(code)
1926 if not self.indices:
1927 self.index.free_temps(code)
1928 else:
1929 for i in self.indices:
1930 i.free_temps(code)
1932 def generate_result_code(self, code):
1933 if self.is_buffer_access:
1934 if code.globalstate.directives['nonecheck']:
1935 self.put_nonecheck(code)
1936 self.buffer_ptr_code = self.buffer_lookup_code(code)
1937 if self.type.is_pyobject:
1938 # is_temp is True, so must pull out value and incref it.
1939 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1940 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1941 elif self.type.is_pyobject:
1942 if self.index.type.is_int:
1943 index_code = self.index.result()
1944 if self.base.type is list_type:
1945 function = "__Pyx_GetItemInt_List"
1946 elif self.base.type is tuple_type:
1947 function = "__Pyx_GetItemInt_Tuple"
1948 else:
1949 function = "__Pyx_GetItemInt"
1950 code.globalstate.use_utility_code(getitem_int_utility_code)
1951 else:
1952 function = "PyObject_GetItem"
1953 index_code = self.index.py_result()
1954 sign_code = ""
1955 code.putln(
1956 "%s = %s(%s, %s%s); if (!%s) %s" % (
1957 self.result(),
1958 function,
1959 self.base.py_result(),
1960 index_code,
1961 self.extra_index_params(),
1962 self.result(),
1963 code.error_goto(self.pos)))
1964 code.put_gotref(self.py_result())
1966 def generate_setitem_code(self, value_code, code):
1967 if self.index.type.is_int:
1968 function = "__Pyx_SetItemInt"
1969 index_code = self.index.result()
1970 code.globalstate.use_utility_code(setitem_int_utility_code)
1971 else:
1972 index_code = self.index.py_result()
1973 if self.base.type is dict_type:
1974 function = "PyDict_SetItem"
1975 # It would seem that we could specalized lists/tuples, but that
1976 # shouldn't happen here.
1977 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1978 # not a PyObject*, and bad conversion here would give the wrong
1979 # exception. Also, tuples are supposed to be immutable, and raise
1980 # TypeErrors when trying to set their entries (PyTuple_SetItem
1981 # is for creating new tuples from).
1982 else:
1983 function = "PyObject_SetItem"
1984 code.putln(
1985 "if (%s(%s, %s, %s%s) < 0) %s" % (
1986 function,
1987 self.base.py_result(),
1988 index_code,
1989 value_code,
1990 self.extra_index_params(),
1991 code.error_goto(self.pos)))
1993 def generate_buffer_setitem_code(self, rhs, code, op=""):
1994 # Used from generate_assignment_code and InPlaceAssignmentNode
1995 if code.globalstate.directives['nonecheck']:
1996 self.put_nonecheck(code)
1997 ptrexpr = self.buffer_lookup_code(code)
1998 if self.buffer_type.dtype.is_pyobject:
1999 # Must manage refcounts. Decref what is already there
2000 # and incref what we put in.
2001 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
2002 rhs_code = rhs.result()
2003 code.putln("%s = %s;" % (ptr, ptrexpr))
2004 code.put_gotref("*%s" % ptr)
2005 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
2006 ptr, rhs_code
2007 ))
2008 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
2009 code.put_giveref("*%s" % ptr)
2010 code.funcstate.release_temp(ptr)
2011 else:
2012 # Simple case
2013 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
2015 def generate_assignment_code(self, rhs, code):
2016 self.generate_subexpr_evaluation_code(code)
2017 if self.is_buffer_access:
2018 self.generate_buffer_setitem_code(rhs, code)
2019 elif self.type.is_pyobject:
2020 self.generate_setitem_code(rhs.py_result(), code)
2021 else:
2022 code.putln(
2023 "%s = %s;" % (
2024 self.result(), rhs.result()))
2025 self.generate_subexpr_disposal_code(code)
2026 self.free_subexpr_temps(code)
2027 rhs.generate_disposal_code(code)
2028 rhs.free_temps(code)
2030 def generate_deletion_code(self, code):
2031 self.generate_subexpr_evaluation_code(code)
2032 #if self.type.is_pyobject:
2033 if self.index.type.is_int:
2034 function = "__Pyx_DelItemInt"
2035 index_code = self.index.result()
2036 code.globalstate.use_utility_code(delitem_int_utility_code)
2037 else:
2038 index_code = self.index.py_result()
2039 if self.base.type is dict_type:
2040 function = "PyDict_DelItem"
2041 else:
2042 function = "PyObject_DelItem"
2043 code.putln(
2044 "if (%s(%s, %s%s) < 0) %s" % (
2045 function,
2046 self.base.py_result(),
2047 index_code,
2048 self.extra_index_params(),
2049 code.error_goto(self.pos)))
2050 self.generate_subexpr_disposal_code(code)
2051 self.free_subexpr_temps(code)
2053 def buffer_lookup_code(self, code):
2054 # Assign indices to temps
2055 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2056 for temp, index in zip(index_temps, self.indices):
2057 code.putln("%s = %s;" % (temp, index.result()))
2058 # Generate buffer access code using these temps
2059 import Buffer
2060 # The above could happen because child_attrs is wrong somewhere so that
2061 # options are not propagated.
2062 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2063 index_signeds=[i.type.signed for i in self.indices],
2064 index_cnames=index_temps,
2065 directives=code.globalstate.directives,
2066 pos=self.pos, code=code)
2068 def put_nonecheck(self, code):
2069 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2070 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2071 code.putln("__Pyx_RaiseNoneIndexingError();")
2072 code.putln(code.error_goto(self.pos))
2073 code.putln("}")
2075 class SliceIndexNode(ExprNode):
2076 # 2-element slice indexing
2077 #
2078 # base ExprNode
2079 # start ExprNode or None
2080 # stop ExprNode or None
2082 subexprs = ['base', 'start', 'stop']
2084 def calculate_constant_result(self):
2085 self.constant_result = self.base.constant_result[
2086 self.start.constant_result : self.stop.constant_result]
2088 def compile_time_value(self, denv):
2089 base = self.base.compile_time_value(denv)
2090 if self.start is None:
2091 start = 0
2092 else:
2093 start = self.start.compile_time_value(denv)
2094 if self.stop is None:
2095 stop = None
2096 else:
2097 stop = self.stop.compile_time_value(denv)
2098 try:
2099 return base[start:stop]
2100 except Exception, e:
2101 self.compile_time_value_error(e)
2103 def analyse_target_declaration(self, env):
2104 pass
2106 def analyse_target_types(self, env):
2107 self.analyse_types(env)
2108 # when assigning, we must accept any Python type
2109 if self.type.is_pyobject:
2110 self.type = py_object_type
2112 def analyse_types(self, env):
2113 self.base.analyse_types(env)
2114 if self.start:
2115 self.start.analyse_types(env)
2116 if self.stop:
2117 self.stop.analyse_types(env)
2118 base_type = self.base.type
2119 if base_type.is_string:
2120 self.type = bytes_type
2121 elif base_type.is_array or base_type.is_ptr:
2122 # we need a ptr type here instead of an array type, as
2123 # array types can result in invalid type casts in the C
2124 # code
2125 self.type = PyrexTypes.CPtrType(base_type.base_type)
2126 else:
2127 self.base = self.base.coerce_to_pyobject(env)
2128 self.type = py_object_type
2129 if base_type.is_builtin_type:
2130 # slicing builtin types returns something of the same type
2131 self.type = base_type
2132 c_int = PyrexTypes.c_py_ssize_t_type
2133 if self.start:
2134 self.start = self.start.coerce_to(c_int, env)
2135 if self.stop:
2136 self.stop = self.stop.coerce_to(c_int, env)
2137 self.is_temp = 1
2139 nogil_check = Node.gil_error
2140 gil_message = "Slicing Python object"
2142 def generate_result_code(self, code):
2143 if not self.type.is_pyobject:
2144 error(self.pos,
2145 "Slicing is not currently supported for '%s'." % self.type)
2146 return
2147 if self.base.type.is_string:
2148 if self.stop is None:
2149 code.putln(
2150 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2151 self.result(),
2152 self.base.result(),
2153 self.start_code(),
2154 code.error_goto_if_null(self.result(), self.pos)))
2155 else:
2156 code.putln(
2157 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2158 self.result(),
2159 self.base.result(),
2160 self.start_code(),
2161 self.stop_code(),
2162 self.start_code(),
2163 code.error_goto_if_null(self.result(), self.pos)))
2164 else:
2165 code.putln(
2166 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2167 self.result(),
2168 self.base.py_result(),
2169 self.start_code(),
2170 self.stop_code(),
2171 code.error_goto_if_null(self.result(), self.pos)))
2172 code.put_gotref(self.py_result())
2174 def generate_assignment_code(self, rhs, code):
2175 self.generate_subexpr_evaluation_code(code)
2176 if self.type.is_pyobject:
2177 code.put_error_if_neg(self.pos,
2178 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2179 self.base.py_result(),
2180 self.start_code(),
2181 self.stop_code(),
2182 rhs.result()))
2183 else:
2184 start_offset = ''
2185 if self.start:
2186 start_offset = self.start_code()
2187 if start_offset == '0':
2188 start_offset = ''
2189 else:
2190 start_offset += '+'
2191 if rhs.type.is_array:
2192 array_length = rhs.type.size
2193 self.generate_slice_guard_code(code, array_length)
2194 else:
2195 error(self.pos,
2196 "Slice assignments from pointers are not yet supported.")
2197 # FIXME: fix the array size according to start/stop
2198 array_length = self.base.type.size
2199 for i in range(array_length):
2200 code.putln("%s[%s%s] = %s[%d];" % (
2201 self.base.result(), start_offset, i,
2202 rhs.result(), i))
2203 self.generate_subexpr_disposal_code(code)
2204 self.free_subexpr_temps(code)
2205 rhs.generate_disposal_code(code)
2206 rhs.free_temps(code)
2208 def generate_deletion_code(self, code):
2209 if not self.base.type.is_pyobject:
2210 error(self.pos,
2211 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2212 return
2213 self.generate_subexpr_evaluation_code(code)
2214 code.put_error_if_neg(self.pos,
2215 "PySequence_DelSlice(%s, %s, %s)" % (
2216 self.base.py_result(),
2217 self.start_code(),
2218 self.stop_code()))
2219 self.generate_subexpr_disposal_code(code)
2221 def generate_slice_guard_code(self, code, target_size):
2222 if not self.base.type.is_array:
2223 return
2224 slice_size = self.base.type.size
2225 start = stop = None
2226 if self.stop:
2227 stop = self.stop.result()
2228 try:
2229 stop = int(stop)
2230 if stop < 0:
2231 slice_size = self.base.type.size + stop
2232 else:
2233 slice_size = stop
2234 stop = None
2235 except ValueError:
2236 pass
2237 if self.start:
2238 start = self.start.result()
2239 try:
2240 start = int(start)
2241 if start < 0:
2242 start = self.base.type.size + start
2243 slice_size -= start
2244 start = None
2245 except ValueError:
2246 pass
2247 check = None
2248 if slice_size < 0:
2249 if target_size > 0:
2250 error(self.pos, "Assignment to empty slice.")
2251 elif start is None and stop is None:
2252 # we know the exact slice length
2253 if target_size != slice_size:
2254 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2255 slice_size, target_size))
2256 elif start is not None:
2257 if stop is None:
2258 stop = slice_size
2259 check = "(%s)-(%s)" % (stop, start)
2260 else: # stop is not None:
2261 check = stop
2262 if check:
2263 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2264 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));' % (
2265 target_size, check))
2266 code.putln(code.error_goto(self.pos))
2267 code.putln("}")
2269 def start_code(self):
2270 if self.start:
2271 return self.start.result()
2272 else:
2273 return "0"
2275 def stop_code(self):
2276 if self.stop:
2277 return self.stop.result()
2278 elif self.base.type.is_array:
2279 return self.base.type.size
2280 else:
2281 return "PY_SSIZE_T_MAX"
2283 def calculate_result_code(self):
2284 # self.result() is not used, but this method must exist
2285 return "<unused>"
2288 class SliceNode(ExprNode):
2289 # start:stop:step in subscript list
2290 #
2291 # start ExprNode
2292 # stop ExprNode
2293 # step ExprNode
2295 type = py_object_type
2296 is_temp = 1
2298 def calculate_constant_result(self):
2299 self.constant_result = self.base.constant_result[
2300 self.start.constant_result : \
2301 self.stop.constant_result : \
2302 self.step.constant_result]
2304 def compile_time_value(self, denv):
2305 start = self.start.compile_time_value(denv)
2306 if self.stop is None:
2307 stop = None
2308 else:
2309 stop = self.stop.compile_time_value(denv)
2310 if self.step is None:
2311 step = None
2312 else:
2313 step = self.step.compile_time_value(denv)
2314 try:
2315 return slice(start, stop, step)
2316 except Exception, e:
2317 self.compile_time_value_error(e)
2319 subexprs = ['start', 'stop', 'step']
2321 def analyse_types(self, env):
2322 self.start.analyse_types(env)
2323 self.stop.analyse_types(env)
2324 self.step.analyse_types(env)
2325 self.start = self.start.coerce_to_pyobject(env)
2326 self.stop = self.stop.coerce_to_pyobject(env)
2327 self.step = self.step.coerce_to_pyobject(env)
2329 gil_message = "Constructing Python slice object"
2331 def generate_result_code(self, code):
2332 code.putln(
2333 "%s = PySlice_New(%s, %s, %s); %s" % (
2334 self.result(),
2335 self.start.py_result(),
2336 self.stop.py_result(),
2337 self.step.py_result(),
2338 code.error_goto_if_null(self.result(), self.pos)))
2339 code.put_gotref(self.py_result())
2342 class CallNode(ExprNode):
2344 def analyse_as_type_constructor(self, env):
2345 type = self.function.analyse_as_type(env)
2346 if type and type.is_struct_or_union:
2347 args, kwds = self.explicit_args_kwds()
2348 items = []
2349 for arg, member in zip(args, type.scope.var_entries):
2350 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2351 if kwds:
2352 items += kwds.key_value_pairs
2353 self.key_value_pairs = items
2354 self.__class__ = DictNode
2355 self.analyse_types(env)
2356 self.coerce_to(type, env)
2357 return True
2359 def nogil_check(self, env):
2360 func_type = self.function_type()
2361 if func_type.is_pyobject:
2362 self.gil_error()
2363 elif not getattr(func_type, 'nogil', False):
2364 self.gil_error()
2366 gil_message = "Calling gil-requiring function"
2369 class SimpleCallNode(CallNode):
2370 # Function call without keyword, * or ** args.
2371 #
2372 # function ExprNode
2373 # args [ExprNode]
2374 # arg_tuple ExprNode or None used internally
2375 # self ExprNode or None used internally
2376 # coerced_self ExprNode or None used internally
2377 # wrapper_call bool used internally
2378 # has_optional_args bool used internally
2380 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2382 self = None
2383 coerced_self = None
2384 arg_tuple = None
2385 wrapper_call = False
2386 has_optional_args = False
2388 def compile_time_value(self, denv):
2389 function = self.function.compile_time_value(denv)
2390 args = [arg.compile_time_value(denv) for arg in self.args]
2391 try:
2392 return function(*args)
2393 except Exception, e:
2394 self.compile_time_value_error(e)
2396 def type_dependencies(self, env):
2397 # TODO: Update when Danilo's C++ code merged in to handle the
2398 # the case of function overloading.
2399 return self.function.type_dependencies(env)
2401 def infer_type(self, env):
2402 func_type = self.function.infer_type(env)
2403 if func_type.is_ptr:
2404 func_type = func_type.base_type
2405 if func_type.is_cfunction:
2406 return func_type.return_type
2407 else:
2408 return py_object_type
2410 def analyse_as_type(self, env):
2411 attr = self.function.as_cython_attribute()
2412 if attr == 'pointer':
2413 if len(self.args) != 1:
2414 error(self.args.pos, "only one type allowed.")
2415 else:
2416 type = self.args[0].analyse_as_type(env)
2417 if not type:
2418 error(self.args[0].pos, "Unknown type")
2419 else:
2420 return PyrexTypes.CPtrType(type)
2422 def explicit_args_kwds(self):
2423 return self.args, None
2425 def analyse_types(self, env):
2426 if self.analyse_as_type_constructor(env):
2427 return
2428 function = self.function
2429 function.is_called = 1
2430 self.function.analyse_types(env)
2431 if function.is_attribute and function.entry and function.entry.is_cmethod:
2432 # Take ownership of the object from which the attribute
2433 # was obtained, because we need to pass it as 'self'.
2434 self.self = function.obj
2435 function.obj = CloneNode(self.self)
2436 func_type = self.function_type()
2437 if func_type.is_pyobject:
2438 self.arg_tuple = TupleNode(self.pos, args = self.args)
2439 self.arg_tuple.analyse_types(env)
2440 self.args = None
2441 if function.is_name and function.type_entry:
2442 # We are calling an extension type constructor. As
2443 # long as we do not support __new__(), the result type
2444 # is clear
2445 self.type = function.type_entry.type
2446 self.result_ctype = py_object_type
2447 else:
2448 self.type = py_object_type
2449 self.is_temp = 1
2450 else:
2451 for arg in self.args:
2452 arg.analyse_types(env)
2453 if self.self and func_type.args:
2454 # Coerce 'self' to the type expected by the method.
2455 expected_type = func_type.args[0].type
2456 self.coerced_self = CloneNode(self.self).coerce_to(
2457 expected_type, env)
2458 # Insert coerced 'self' argument into argument list.
2459 self.args.insert(0, self.coerced_self)
2460 self.analyse_c_function_call(env)
2462 def function_type(self):
2463 # Return the type of the function being called, coercing a function
2464 # pointer to a function if necessary.
2465 func_type = self.function.type
2466 if func_type.is_ptr:
2467 func_type = func_type.base_type
2468 return func_type
2470 def analyse_c_function_call(self, env):
2471 func_type = self.function_type()
2472 # Check function type
2473 if not func_type.is_cfunction:
2474 if not func_type.is_error:
2475 error(self.pos, "Calling non-function type '%s'" %
2476 func_type)
2477 self.type = PyrexTypes.error_type
2478 self.result_code = "<error>"
2479 return
2480 # Check no. of args
2481 max_nargs = len(func_type.args)
2482 expected_nargs = max_nargs - func_type.optional_arg_count
2483 actual_nargs = len(self.args)
2484 if actual_nargs < expected_nargs \
2485 or (not func_type.has_varargs and actual_nargs > max_nargs):
2486 expected_str = str(expected_nargs)
2487 if func_type.has_varargs:
2488 expected_str = "at least " + expected_str
2489 elif func_type.optional_arg_count:
2490 if actual_nargs < max_nargs:
2491 expected_str = "at least " + expected_str
2492 else:
2493 expected_str = "at most " + str(max_nargs)
2494 error(self.pos,
2495 "Call with wrong number of arguments (expected %s, got %s)"
2496 % (expected_str, actual_nargs))
2497 self.args = None
2498 self.type = PyrexTypes.error_type
2499 self.result_code = "<error>"
2500 return
2501 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2502 self.has_optional_args = 1
2503 self.is_temp = 1
2504 # Coerce arguments
2505 for i in range(min(max_nargs, actual_nargs)):
2506 formal_type = func_type.args[i].type
2507 self.args[i] = self.args[i].coerce_to(formal_type, env)
2508 for i in range(max_nargs, actual_nargs):
2509 if self.args[i].type.is_pyobject:
2510 error(self.args[i].pos,
2511 "Python object cannot be passed as a varargs parameter")
2512 # Calc result type and code fragment
2513 self.type = func_type.return_type
2514 if self.type.is_pyobject:
2515 self.result_ctype = py_object_type
2516 self.is_temp = 1
2517 elif func_type.exception_value is not None \
2518 or func_type.exception_check:
2519 self.is_temp = 1
2520 # C++ exception handler
2521 if func_type.exception_check == '+':
2522 if func_type.exception_value is None:
2523 env.use_utility_code(cpp_exception_utility_code)
2525 def calculate_result_code(self):
2526 return self.c_call_code()
2528 def c_call_code(self):
2529 func_type = self.function_type()
2530 if self.args is None or not func_type.is_cfunction:
2531 return "<error>"
2532 formal_args = func_type.args
2533 arg_list_code = []
2534 args = zip(formal_args, self.args)
2535 max_nargs = len(func_type.args)
2536 expected_nargs = max_nargs - func_type.optional_arg_count
2537 actual_nargs = len(self.args)
2538 for formal_arg, actual_arg in args[:expected_nargs]:
2539 arg_code = actual_arg.result_as(formal_arg.type)
2540 arg_list_code.append(arg_code)
2542 if func_type.is_overridable:
2543 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2545 if func_type.optional_arg_count:
2546 if expected_nargs == actual_nargs:
2547 optional_args = 'NULL'
2548 else:
2549 optional_args = "&%s" % self.opt_arg_struct
2550 arg_list_code.append(optional_args)
2552 for actual_arg in self.args[len(formal_args):]:
2553 arg_list_code.append(actual_arg.result())
2554 result = "%s(%s)" % (self.function.result(),
2555 ', '.join(arg_list_code))
2556 return result
2558 def generate_result_code(self, code):
2559 func_type = self.function_type()
2560 if func_type.is_pyobject:
2561 arg_code = self.arg_tuple.py_result()
2562 code.putln(
2563 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2564 self.result(),
2565 self.function.py_result(),
2566 arg_code,
2567 code.error_goto_if_null(self.result(), self.pos)))
2568 code.put_gotref(self.py_result())
2569 elif func_type.is_cfunction:
2570 if self.has_optional_args:
2571 actual_nargs = len(self.args)
2572 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2573 self.opt_arg_struct = code.funcstate.allocate_temp(
2574 func_type.op_arg_struct.base_type, manage_ref=True)
2575 code.putln("%s.%s = %s;" % (
2576 self.opt_arg_struct,
2577 Naming.pyrex_prefix + "n",
2578 len(self.args) - expected_nargs))
2579 args = zip(func_type.args, self.args)
2580 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2581 code.putln("%s.%s = %s;" % (
2582 self.opt_arg_struct,
2583 func_type.opt_arg_cname(formal_arg.name),
2584 actual_arg.result_as(formal_arg.type)))
2585 exc_checks = []
2586 if self.type.is_pyobject:
2587 exc_checks.append("!%s" % self.result())
2588 else:
2589 exc_val = func_type.exception_value
2590 exc_check = func_type.exception_check
2591 if exc_val is not None:
2592 exc_checks.append("%s == %s" % (self.result(), exc_val))
2593 if exc_check:
2594 exc_checks.append("PyErr_Occurred()")
2595 if self.is_temp or exc_checks:
2596 rhs = self.c_call_code()
2597 if self.result():
2598 lhs = "%s = " % self.result()
2599 if self.is_temp and self.type.is_pyobject:
2600 #return_type = self.type # func_type.return_type
2601 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2602 # "from", return_type, "to pyobject" ###
2603 rhs = typecast(py_object_type, self.type, rhs)
2604 else:
2605 lhs = ""
2606 if func_type.exception_check == '+':
2607 if func_type.exception_value is None:
2608 raise_py_exception = "__Pyx_CppExn2PyErr()"
2609 elif func_type.exception_value.type.is_pyobject:
2610 raise_py_exception = ' try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
2611 func_type.exception_value.entry.cname,
2612 func_type.exception_value.entry.cname)
2613 else:
2614 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2615 code.putln(
2616 "try {%s%s;} catch(...) {%s; %s}" % (
2617 lhs,
2618 rhs,
2619 raise_py_exception,
2620 code.error_goto(self.pos)))
2621 else:
2622 if exc_checks:
2623 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2624 else:
2625 goto_error = ""
2626 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2627 if self.type.is_pyobject and self.result():
2628 code.put_gotref(self.py_result())
2629 if self.has_optional_args:
2630 code.funcstate.release_temp(self.opt_arg_struct)
2633 class PythonCapiFunctionNode(ExprNode):
2634 subexprs = []
2635 def __init__(self, pos, name, func_type, utility_code = None):
2636 self.pos = pos
2637 self.name = name
2638 self.type = func_type
2639 self.utility_code = utility_code
2641 def generate_result_code(self, code):
2642 if self.utility_code:
2643 code.globalstate.use_utility_code(self.utility_code)
2645 def calculate_result_code(self):
2646 return self.name
2648 class PythonCapiCallNode(SimpleCallNode):
2649 # Python C-API Function call (only created in transforms)
2651 def __init__(self, pos, function_name, func_type,
2652 utility_code = None, **kwargs):
2653 self.type = func_type.return_type
2654 self.result_ctype = self.type
2655 self.function = PythonCapiFunctionNode(
2656 pos, function_name, func_type,
2657 utility_code = utility_code)
2658 # call this last so that we can override the constructed
2659 # attributes above with explicit keyword arguments if required
2660 SimpleCallNode.__init__(self, pos, **kwargs)
2663 class GeneralCallNode(CallNode):
2664 # General Python function call, including keyword,
2665 # * and ** arguments.
2666 #
2667 # function ExprNode
2668 # positional_args ExprNode Tuple of positional arguments
2669 # keyword_args ExprNode or None Dict of keyword arguments
2670 # starstar_arg ExprNode or None Dict of extra keyword args
2672 type = py_object_type
2674 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2676 nogil_check = Node.gil_error
2678 def compile_time_value(self, denv):
2679 function = self.function.compile_time_value(denv)
2680 positional_args = self.positional_args.compile_time_value(denv)
2681 keyword_args = self.keyword_args.compile_time_value(denv)
2682 starstar_arg = self.starstar_arg.compile_time_value(denv)
2683 try:
2684 keyword_args.update(starstar_arg)
2685 return function(*positional_args, **keyword_args)
2686 except Exception, e:
2687 self.compile_time_value_error(e)
2689 def explicit_args_kwds(self):
2690 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2691 raise PostParseError(self.pos,
2692 'Compile-time keyword arguments must be explicit.')
2693 return self.positional_args.args, self.keyword_args
2695 def analyse_types(self, env):
2696 if self.analyse_as_type_constructor(env):
2697 return
2698 self.function.analyse_types(env)
2699 self.positional_args.analyse_types(env)
2700 if self.keyword_args:
2701 self.keyword_args.analyse_types(env)
2702 if self.starstar_arg:
2703 self.starstar_arg.analyse_types(env)
2704 if not self.function.type.is_pyobject:
2705 if self.function.type.is_error:
2706 self.type = error_type
2707 return error_type
2708 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2709 error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
2710 else:
2711 self.function = self.function.coerce_to_pyobject(env)
2712 self.positional_args = \
2713 self.positional_args.coerce_to_pyobject(env)
2714 if self.starstar_arg:
2715 self.starstar_arg = \
2716 self.starstar_arg.coerce_to_pyobject(env)
2717 function = self.function
2718 if function.is_name and function.type_entry:
2719 # We are calling an extension type constructor. As long
2720 # as we do not support __new__(), the result type is clear
2721 self.type = function.type_entry.type
2722 self.result_ctype = py_object_type
2723 else:
2724 self.type = py_object_type
2725 self.is_temp = 1
2727 def generate_result_code(self, code):
2728 if self.type.is_error: return
2729 if self.keyword_args and self.starstar_arg:
2730 code.put_error_if_neg(self.pos,
2731 "PyDict_Update(%s, %s)" % (
2732 self.keyword_args.py_result(),
2733 self.starstar_arg.py_result()))
2734 keyword_code = self.keyword_args.py_result()
2735 elif self.keyword_args:
2736 keyword_code = self.keyword_args.py_result()
2737 elif self.starstar_arg:
2738 keyword_code = self.starstar_arg.py_result()
2739 else:
2740 keyword_code = None
2741 if not keyword_code:
2742 call_code = "PyObject_Call(%s, %s, NULL)" % (
2743 self.function.py_result(),
2744 self.positional_args.py_result())
2745 else:
2746 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2747 self.function.py_result(),
2748 self.positional_args.py_result(),
2749 keyword_code)
2750 code.putln(
2751 "%s = %s; %s" % (
2752 self.result(),
2753 call_code,
2754 code.error_goto_if_null(self.result(), self.pos)))
2755 code.put_gotref(self.py_result())
2758 class AsTupleNode(ExprNode):
2759 # Convert argument to tuple. Used for normalising
2760 # the * argument of a function call.
2761 #
2762 # arg ExprNode
2764 subexprs = ['arg']
2766 def calculate_constant_result(self):
2767 self.constant_result = tuple(self.base.constant_result)
2769 def compile_time_value(self, denv):
2770 arg = self.arg.compile_time_value(denv)
2771 try:
2772 return tuple(arg)
2773 except Exception, e:
2774 self.compile_time_value_error(e)
2776 def analyse_types(self, env):
2777 self.arg.analyse_types(env)
2778 self.arg = self.arg.coerce_to_pyobject(env)
2779 self.type = tuple_type
2780 self.is_temp = 1
2782 nogil_check = Node.gil_error
2783 gil_message = "Constructing Python tuple"
2785 def generate_result_code(self, code):
2786 code.putln(
2787 "%s = PySequence_Tuple(%s); %s" % (
2788 self.result(),
2789 self.arg.py_result(),
2790 code.error_goto_if_null(self.result(), self.pos)))
2791 code.put_gotref(self.py_result())
2794 class AttributeNode(ExprNode):
2795 # obj.attribute
2796 #
2797 # obj ExprNode
2798 # attribute string
2799 # needs_none_check boolean Used if obj is an extension type.
2800 # If set to True, it is known that the type is not None.
2801 #
2802 # Used internally:
2803 #
2804 # is_py_attr boolean Is a Python getattr operation
2805 # member string C name of struct member
2806 # is_called boolean Function call is being done on result
2807 # entry Entry Symbol table entry of attribute
2809 is_attribute = 1
2810 subexprs = ['obj']
2812 type = PyrexTypes.error_type
2813 entry = None
2814 is_called = 0
2815 needs_none_check = True
2817 def as_cython_attribute(self):
2818 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2819 return self.attribute
2821 def coerce_to(self, dst_type, env):
2822 # If coercing to a generic pyobject and this is a cpdef function
2823 # we can create the corresponding attribute
2824 if dst_type is py_object_type:
2825 entry = self.entry
2826 if entry and entry.is_cfunction and entry.as_variable:
2827 # must be a cpdef function
2828 self.is_temp = 1
2829 self.entry = entry.as_variable
2830 self.analyse_as_python_attribute(env)
2831 return self
2832 return ExprNode.coerce_to(self, dst_type, env)
2834 def calculate_constant_result(self):
2835 attr = self.attribute
2836 if attr.startswith("__") and attr.endswith("__"):
2837 return
2838 self.constant_result = getattr(self.obj.constant_result, attr)
2840 def compile_time_value(self, denv):
2841 attr = self.attribute
2842 if attr.startswith("__") and attr.endswith("__"):
2843 error(self.pos,
2844 "Invalid attribute name '%s' in compile-time expression" % attr)
2845 return None
2846 obj = self.obj.compile_time_value(denv)
2847 try:
2848 return getattr(obj, attr)
2849 except Exception, e:
2850 self.compile_time_value_error(e)
2852 def type_dependencies(self, env):
2853 return self.obj.type_dependencies(env)
2855 def infer_type(self, env):
2856 if self.analyse_as_cimported_attribute(env, 0):
2857 return self.entry.type
2858 elif self.analyse_as_unbound_cmethod(env):
2859 return self.entry.type
2860 else:
2861 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2862 return self.type
2864 def analyse_target_declaration(self, env):
2865 pass
2867 def analyse_target_types(self, env):
2868 self.analyse_types(env, target = 1)
2870 def analyse_types(self, env, target = 0):
2871 if self.analyse_as_cimported_attribute(env, target):
2872 return
2873 if not target and self.analyse_as_unbound_cmethod(env):
2874 return
2875 self.analyse_as_ordinary_attribute(env, target)
2877 def analyse_as_cimported_attribute(self, env, target):
2878 # Try to interpret this as a reference to an imported
2879 # C const, type, var or function. If successful, mutates
2880 # this node into a NameNode and returns 1, otherwise
2881 # returns 0.
2882 module_scope = self.obj.analyse_as_module(env)
2883 if module_scope:
2884 entry = module_scope.lookup_here(self.attribute)
2885 if entry and (
2886 entry.is_cglobal or entry.is_cfunction
2887 or entry.is_type or entry.is_const):
2888 self.mutate_into_name_node(env, entry, target)
2889 return 1
2890 return 0
2892 def analyse_as_unbound_cmethod(self, env):
2893 # Try to interpret this as a reference to an unbound
2894 # C method of an extension type. If successful, mutates
2895 # this node into a NameNode and returns 1, otherwise
2896 # returns 0.
2897 type = self.obj.analyse_as_extension_type(env)
2898 if type:
2899 entry = type.scope.lookup_here(self.attribute)
2900 if entry and entry.is_cmethod:
2901 # Create a temporary entry describing the C method
2902 # as an ordinary function.
2903 ubcm_entry = Symtab.Entry(entry.name,
2904 "%s->%s" % (type.vtabptr_cname, entry.cname),
2905 entry.type)
2906 ubcm_entry.is_cfunction = 1
2907 ubcm_entry.func_cname = entry.func_cname
2908 ubcm_entry.is_unbound_cmethod = 1
2909 self.mutate_into_name_node(env, ubcm_entry, None)
2910 return 1
2911 return 0
2913 def analyse_as_type(self, env):
2914 module_scope = self.obj.analyse_as_module(env)
2915 if module_scope:
2916 return module_scope.lookup_type(self.attribute)
2917 return None
2919 def analyse_as_extension_type(self, env):
2920 # Try to interpret this as a reference to an extension type
2921 # in a cimported module. Returns the extension type, or None.
2922 module_scope = self.obj.analyse_as_module(env)
2923 if module_scope:
2924 entry = module_scope.lookup_here(self.attribute)
2925 if entry and entry.is_type and entry.type.is_extension_type:
2926 return entry.type
2927 return None
2929 def analyse_as_module(self, env):
2930 # Try to interpret this as a reference to a cimported module
2931 # in another cimported module. Returns the module scope, or None.
2932 module_scope = self.obj.analyse_as_module(env)
2933 if module_scope:
2934 entry = module_scope.lookup_here(self.attribute)
2935 if entry and entry.as_module:
2936 return entry.as_module
2937 return None
2939 def mutate_into_name_node(self, env, entry, target):
2940 # Mutate this node into a NameNode and complete the
2941 # analyse_types phase.
2942 self.__class__ = NameNode
2943 self.name = self.attribute
2944 self.entry = entry
2945 del self.obj
2946 del self.attribute
2947 if target:
2948 NameNode.analyse_target_types(self, env)
2949 else:
2950 NameNode.analyse_rvalue_entry(self, env)
2952 def analyse_as_ordinary_attribute(self, env, target):
2953 self.obj.analyse_types(env)
2954 self.analyse_attribute(env)
2955 if self.entry and self.entry.is_cmethod and not self.is_called:
2956 # error(self.pos, "C method can only be called")
2957 pass
2958 ## Reference to C array turns into pointer to first element.
2959 #while self.type.is_array:
2960 # self.type = self.type.element_ptr_type()
2961 if self.is_py_attr:
2962 if not target:
2963 self.is_temp = 1
2964 self.result_ctype = py_object_type
2966 def analyse_attribute(self, env, obj_type = None):
2967 # Look up attribute and set self.type and self.member.
2968 self.is_py_attr = 0
2969 self.member = self.attribute
2970 if obj_type is None:
2971 if self.obj.type.is_string:
2972 self.obj = self.obj.coerce_to_pyobject(env)
2973 obj_type = self.obj.type
2974 else:
2975 if obj_type.is_string:
2976 obj_type = py_object_type
2977 if obj_type.is_ptr or obj_type.is_array:
2978 obj_type = obj_type.base_type
2979 self.op = "->"
2980 elif obj_type.is_extension_type:
2981 self.op = "->"
2982 else:
2983 self.op = "."
2984 if obj_type.has_attributes:
2985 entry = None
2986 if obj_type.attributes_known():
2987 entry = obj_type.scope.lookup_here(self.attribute)
2988 if entry and entry.is_member:
2989 entry = None
2990 else:
2991 error(self.pos,
2992 "Cannot select attribute of incomplete type '%s'"
2993 % obj_type)
2994 self.type = PyrexTypes.error_type
2995 return
2996 self.entry = entry
2997 if entry:
2998 if obj_type.is_extension_type and entry.name == "__weakref__":
2999 error(self.pos, "Illegal use of special attribute __weakref__")
3000 # methods need the normal attribute lookup
3001 # because they do not have struct entries
3002 if entry.is_variable or entry.is_cmethod:
3003 self.type = entry.type
3004 self.member = entry.cname
3005 return
3006 else:
3007 # If it's not a variable or C method, it must be a Python
3008 # method of an extension type, so we treat it like a Python
3009 # attribute.
3010 pass
3011 # If we get here, the base object is not a struct/union/extension
3012 # type, or it is an extension type and the attribute is either not
3013 # declared or is declared as a Python method. Treat it as a Python
3014 # attribute reference.
3015 self.analyse_as_python_attribute(env, obj_type)
3017 def analyse_as_python_attribute(self, env, obj_type = None):
3018 if obj_type is None:
3019 obj_type = self.obj.type
3020 self.member = self.attribute
3021 if obj_type.is_pyobject:
3022 self.type = py_object_type
3023 self.is_py_attr = 1
3024 else:
3025 if not obj_type.is_error:
3026 error(self.pos,
3027 "Object of type '%s' has no attribute '%s'" %
3028 (obj_type, self.attribute))
3030 def nogil_check(self, env):
3031 if self.is_py_attr:
3032 self.gil_error()
3034 gil_message = "Accessing Python attribute"
3036 def is_simple(self):
3037 if self.obj:
3038 return self.result_in_temp() or self.obj.is_simple()
3039 else:
3040 return NameNode.is_simple(self)
3042 def is_lvalue(self):
3043 if self.obj:
3044 return 1
3045 else:
3046 return NameNode.is_lvalue(self)
3048 def is_ephemeral(self):
3049 if self.obj:
3050 return self.obj.is_ephemeral()
3051 else:
3052 return NameNode.is_ephemeral(self)
3054 def calculate_result_code(self):
3055 #print "AttributeNode.calculate_result_code:", self.member ###
3056 #print "...obj node =", self.obj, "code", self.obj.result() ###
3057 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3058 obj = self.obj
3059 obj_code = obj.result_as(obj.type)
3060 #print "...obj_code =", obj_code ###
3061 if self.entry and self.entry.is_cmethod:
3062 if obj.type.is_extension_type:
3063 return "((struct %s *)%s%s%s)->%s" % (
3064 obj.type.vtabstruct_cname, obj_code, self.op,
3065 obj.type.vtabslot_cname, self.member)
3066 else:
3067 return self.member
3068 elif obj.type.is_complex:
3069 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3070 else:
3071 return "%s%s%s" % (obj_code, self.op, self.member)
3073 def generate_result_code(self, code):
3074 interned_attr_cname = code.intern_identifier(self.attribute)
3075 if self.is_py_attr:
3076 code.putln(
3077 '%s = PyObject_GetAttr(%s, %s); %s' % (
3078 self.result(),
3079 self.obj.py_result(),
3080 interned_attr_cname,
3081 code.error_goto_if_null(self.result(), self.pos)))
3082 code.put_gotref(self.py_result())
3083 else:
3084 # result_code contains what is needed, but we may need to insert
3085 # a check and raise an exception
3086 if (self.obj.type.is_extension_type
3087 and self.needs_none_check
3088 and code.globalstate.directives['nonecheck']):
3089 self.put_nonecheck(code)
3091 def generate_assignment_code(self, rhs, code):
3092 interned_attr_cname = code.intern_identifier(self.attribute)
3093 self.obj.generate_evaluation_code(code)
3094 if self.is_py_attr:
3095 code.put_error_if_neg(self.pos,
3096 'PyObject_SetAttr(%s, %s, %s)' % (
3097 self.obj.py_result(),
3098 interned_attr_cname,
3099 rhs.py_result()))
3100 rhs.generate_disposal_code(code)
3101 rhs.free_temps(code)
3102 elif self.obj.type.is_complex:
3103 code.putln("__Pyx_SET_C%s(%s, %s);" % (
3104 self.member.upper(),
3105 self.obj.result_as(self.obj.type),
3106 rhs.result_as(self.ctype())))
3107 else:
3108 if (self.obj.type.is_extension_type
3109 and self.needs_none_check
3110 and code.globalstate.directives['nonecheck']):
3111 self.put_nonecheck(code)
3113 select_code = self.result()
3114 if self.type.is_pyobject and self.use_managed_ref:
3115 rhs.make_owned_reference(code)
3116 code.put_giveref(rhs.py_result())
3117 code.put_gotref(select_code)
3118 code.put_decref(select_code, self.ctype())
3119 code.putln(
3120 "%s = %s;" % (
3121 select_code,
3122 rhs.result_as(self.ctype())))
3123 #rhs.result()))
3124 rhs.generate_post_assignment_code(code)
3125 rhs.free_temps(code)
3126 self.obj.generate_disposal_code(code)
3127 self.obj.free_temps(code)
3129 def generate_deletion_code(self, code):
3130 interned_attr_cname = code.intern_identifier(self.attribute)
3131 self.obj.generate_evaluation_code(code)
3132 if self.is_py_attr:
3133 code.put_error_if_neg(self.pos,
3134 'PyObject_DelAttr(%s, %s)' % (
3135 self.obj.py_result(),
3136 interned_attr_cname))
3137 else:
3138 error(self.pos, "Cannot delete C attribute of extension type")
3139 self.obj.generate_disposal_code(code)
3140 self.obj.free_temps(code)
3142 def annotate(self, code):
3143 if self.is_py_attr:
3144 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3145 else:
3146 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3148 def put_nonecheck(self, code):
3149 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3150 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3151 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3152 code.putln(code.error_goto(self.pos))
3153 code.putln("}")
3156 #-------------------------------------------------------------------
3157 #
3158 # Constructor nodes
3159 #
3160 #-------------------------------------------------------------------
3162 class StarredTargetNode(ExprNode):
3163 # A starred expression like "*a"
3164 #
3165 # This is only allowed in sequence assignment targets such as
3166 #
3167 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3168 #
3169 # and will be removed during type analysis (or generate an error
3170 # if it's found at unexpected places).
3171 #
3172 # target ExprNode
3174 subexprs = ['target']
3175 is_starred = 1
3176 type = py_object_type
3177 is_temp = 1
3179 def __init__(self, pos, target):
3180 self.pos = pos
3181 self.target = target
3183 def analyse_declarations(self, env):
3184 error(self.pos, "can use starred expression only as assignment target")
3185 self.target.analyse_declarations(env)
3187 def analyse_types(self, env):
3188 error(self.pos, "can use starred expression only as assignment target")
3189 self.target.analyse_types(env)
3190 self.type = self.target.type
3192 def analyse_target_declaration(self, env):
3193 self.target.analyse_target_declaration(env)
3195 def analyse_target_types(self, env):
3196 self.target.analyse_target_types(env)
3197 self.type = self.target.type
3199 def calculate_result_code(self):
3200 return ""
3202 def generate_result_code(self, code):
3203 pass
3206 class SequenceNode(ExprNode):
3207 # Base class for list and tuple constructor nodes.
3208 # Contains common code for performing sequence unpacking.
3209 #
3210 # args [ExprNode]
3211 # iterator ExprNode
3212 # unpacked_items [ExprNode] or None
3213 # coerced_unpacked_items [ExprNode] or None
3215 subexprs = ['args']
3217 is_sequence_constructor = 1
3218 unpacked_items = None
3220 def compile_time_value_list(self, denv):
3221 return [arg.compile_time_value(denv) for arg in self.args]
3223 def replace_starred_target_node(self):
3224 # replace a starred node in the targets by the contained expression
3225 self.starred_assignment = False
3226 args = []
3227 for arg in self.args:
3228 if arg.is_starred:
3229 if self.starred_assignment:
3230 error(arg.pos, "more than 1 starred expression in assignment")
3231 self.starred_assignment = True
3232 arg = arg.target
3233 arg.is_starred = True
3234 args.append(arg)
3235 self.args = args
3237 def analyse_target_declaration(self, env):
3238 self.replace_starred_target_node()
3239 for arg in self.args:
3240 arg.analyse_target_declaration(env)
3242 def analyse_types(self, env, skip_children=False):
3243 for i in range(len(self.args)):
3244 arg = self.args[i]
3245 if not skip_children: arg.analyse_types(env)
3246 self.args[i] = arg.coerce_to_pyobject(env)
3247 self.type = py_object_type
3248 self.is_temp = 1
3250 def analyse_target_types(self, env):
3251 self.iterator = PyTempNode(self.pos, env)
3252 self.unpacked_items = []
3253 self.coerced_unpacked_items = []
3254 for arg in self.args:
3255 arg.analyse_target_types(env)
3256 if arg.is_starred:
3257 if not arg.type.assignable_from(Builtin.list_type):
3258 error(arg.pos,
3259 "starred target must have Python object (list) type")
3260 if arg.type is py_object_type:
3261 arg.type = Builtin.list_type
3262 unpacked_item = PyTempNode(self.pos, env)
3263 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3264 self.unpacked_items.append(unpacked_item)
3265 self.coerced_unpacked_items.append(coerced_unpacked_item)
3266 self.type = py_object_type
3268 def generate_result_code(self, code):
3269 self.generate_operation_code(code)
3271 def generate_assignment_code(self, rhs, code):
3272 if self.starred_assignment:
3273 self.generate_starred_assignment_code(rhs, code)
3274 else:
3275 self.generate_parallel_assignment_code(rhs, code)
3277 for item in self.unpacked_items:
3278 item.release(code)
3279 rhs.free_temps(code)
3281 def generate_parallel_assignment_code(self, rhs, code):
3282 # Need to work around the fact that generate_evaluation_code
3283 # allocates the temps in a rather hacky way -- the assignment
3284 # is evaluated twice, within each if-block.
3286 code.globalstate.use_utility_code(unpacking_utility_code)
3288 if rhs.type is tuple_type:
3289 tuple_check = "likely(%s != Py_None)"
3290 else:
3291 tuple_check = "PyTuple_CheckExact(%s)"
3292 code.putln(
3293 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3294 tuple_check % rhs.py_result(),
3295 rhs.py_result(),
3296 len(self.args)))
3297 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3298 for item in self.unpacked_items:
3299 item.allocate(code)
3300 for i in range(len(self.args)):
3301 item = self.unpacked_items[i]
3302 code.put(
3303 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3304 item.result(),
3305 i))
3306 code.put_incref(item.result(), item.ctype())
3307 value_node = self.coerced_unpacked_items[i]
3308 value_node.generate_evaluation_code(code)
3309 rhs.generate_disposal_code(code)
3311 for i in range(len(self.args)):
3312 self.args[i].generate_assignment_code(
3313 self.coerced_unpacked_items[i], code)
3315 code.putln("} else {")
3317 if rhs.type is tuple_type:
3318 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3319 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3320 rhs.py_result(), len(self.args)))
3321 code.putln(code.error_goto(self.pos))
3322 else:
3323 self.iterator.allocate(code)
3324 code.putln(
3325 "%s = PyObject_GetIter(%s); %s" % (
3326 self.iterator.result(),
3327 rhs.py_result(),
3328 code.error_goto_if_null(self.iterator.result(), self.pos)))
3329 code.put_gotref(self.iterator.py_result())
3330 rhs.generate_disposal_code(code)
3331 for i in range(len(self.args)):
3332 item = self.unpacked_items[i]
3333 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3334 self.iterator.py_result(), i)
3335 code.putln(
3336 "%s = %s; %s" % (
3337 item.result(),
3338 typecast(item.ctype(), py_object_type, unpack_code),
3339 code.error_goto_if_null(item.result(), self.pos)))
3340 code.put_gotref(item.py_result())
3341 value_node = self.coerced_unpacked_items[i]
3342 value_node.generate_evaluation_code(code)
3343 code.put_error_if_neg(self.pos,
3344 "__Pyx_EndUnpack(%s)" % (
3345 self.iterator.py_result()))
3346 if debug_disposal_code:
3347 print("UnpackNode.generate_assignment_code:")
3348 print("...generating disposal code for %s" % self.iterator)
3349 self.iterator.generate_disposal_code(code)
3350 self.iterator.free_temps(code)
3351 self.iterator.release(code)
3353 for i in range(len(self.args)):
3354 self.args[i].generate_assignment_code(
3355 self.coerced_unpacked_items[i], code)
3357 code.putln("}")
3359 def generate_starred_assignment_code(self, rhs, code):
3360 code.globalstate.use_utility_code(unpacking_utility_code)
3362 for i, arg in enumerate(self.args):
3363 if arg.is_starred:
3364 starred_target = self.unpacked_items[i]
3365 fixed_args_left = self.args[:i]
3366 fixed_args_right = self.args[i+1:]
3367 break
3369 self.iterator.allocate(code)
3370 code.putln(
3371 "%s = PyObject_GetIter(%s); %s" % (
3372 self.iterator.result(),
3373 rhs.py_result(),
3374 code.error_goto_if_null(self.iterator.result(), self.pos)))
3375 code.put_gotref(self.iterator.py_result())
3376 rhs.generate_disposal_code(code)
3378 for item in self.unpacked_items:
3379 item.allocate(code)
3380 for i in range(len(fixed_args_left)):
3381 item = self.unpacked_items[i]
3382 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3383 self.iterator.py_result(), i)
3384 code.putln(
3385 "%s = %s; %s" % (
3386 item.result(),
3387 typecast(item.ctype(), py_object_type, unpack_code),
3388 code.error_goto_if_null(item.result(), self.pos)))
3389 code.put_gotref(item.py_result())
3390 value_node = self.coerced_unpacked_items[i]
3391 value_node.generate_evaluation_code(code)
3393 target_list = starred_target.result()
3394 code.putln("%s = PySequence_List(%s); %s" % (
3395 target_list, self.iterator.py_result(),
3396 code.error_goto_if_null(target_list, self.pos)))
3397 code.put_gotref(target_list)
3398 if fixed_args_right:
3399 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3400 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3401 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3402 (target_list, len(unpacked_right_args))))
3403 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3404 len(fixed_args_left), target_list,
3405 code.error_goto(self.pos)))
3406 code.putln('}')
3407 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3408 self.coerced_unpacked_items[::-1])):
3409 code.putln(
3410 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3411 arg.py_result(),
3412 target_list, target_list))
3413 # resize the list the hard way
3414 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3415 code.put_gotref(arg.py_result())
3416 coerced_arg.generate_evaluation_code(code)
3418 self.iterator.generate_disposal_code(code)
3419 self.iterator.free_temps(code)
3420 self.iterator.release(code)
3422 for i in range(len(self.args)):
3423 self.args[i].generate_assignment_code(
3424 self.coerced_unpacked_items[i], code)
3426 def annotate(self, code):
3427 for arg in self.args:
3428 arg.annotate(code)
3429 if self.unpacked_items:
3430 for arg in self.unpacked_items:
3431 arg.annotate(code)
3432 for arg in self.coerced_unpacked_items:
3433 arg.annotate(code)
3436 class TupleNode(SequenceNode):
3437 # Tuple constructor.
3439 type = tuple_type
3441 gil_message = "Constructing Python tuple"
3443 def analyse_types(self, env, skip_children=False):
3444 if len(self.args) == 0:
3445 self.is_temp = 0
3446 self.is_literal = 1
3447 else:
3448 SequenceNode.analyse_types(self, env, skip_children)
3450 def calculate_result_code(self):
3451 if len(self.args) > 0:
3452 error(self.pos, "Positive length tuples must be constructed.")
3453 else:
3454 return Naming.empty_tuple
3456 def calculate_constant_result(self):
3457 self.constant_result = tuple([
3458 arg.constant_result for arg in self.args])
3460 def compile_time_value(self, denv):
3461 values = self.compile_time_value_list(denv)
3462 try:
3463 return tuple(values)
3464 except Exception, e:
3465 self.compile_time_value_error(e)
3467 def generate_operation_code(self, code):
3468 if len(self.args) == 0:
3469 # result_code is Naming.empty_tuple
3470 return
3471 code.putln(
3472 "%s = PyTuple_New(%s); %s" % (
3473 self.result(),
3474 len(self.args),
3475 code.error_goto_if_null(self.result(), self.pos)))
3476 code.put_gotref(self.py_result())
3477 for i in range(len(self.args)):
3478 arg = self.args[i]
3479 if not arg.result_in_temp():
3480 code.put_incref(arg.result(), arg.ctype())
3481 code.putln(
3482 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3483 self.result(),
3484 i,
3485 arg.py_result()))
3486 code.put_giveref(arg.py_result())
3488 def generate_subexpr_disposal_code(self, code):
3489 # We call generate_post_assignment_code here instead
3490 # of generate_disposal_code, because values were stored
3491 # in the tuple using a reference-stealing operation.
3492 for arg in self.args:
3493 arg.generate_post_assignment_code(code)
3494 # Should NOT call free_temps -- this is invoked by the default
3495 # generate_evaluation_code which will do that.
3498 class ListNode(SequenceNode):
3499 # List constructor.
3501 # obj_conversion_errors [PyrexError] used internally
3502 # orignial_args [ExprNode] used internally
3504 obj_conversion_errors = []
3506 gil_message = "Constructing Python list"
3508 def type_dependencies(self, env):
3509 return ()
3511 def infer_type(self, env):
3512 # TOOD: Infer non-object list arrays.
3513 return list_type
3515 def analyse_expressions(self, env):
3516 SequenceNode.analyse_expressions(self, env)
3517 self.coerce_to_pyobject(env)
3519 def analyse_types(self, env):
3520 hold_errors()
3521 self.original_args = list(self.args)
3522 SequenceNode.analyse_types(self, env)
3523 self.type = list_type
3524 self.obj_conversion_errors = held_errors()
3525 release_errors(ignore=True)
3527 def coerce_to(self, dst_type, env):
3528 if dst_type.is_pyobject:
3529 for err in self.obj_conversion_errors:
3530 report_error(err)
3531 self.obj_conversion_errors = []
3532 if not self.type.subtype_of(dst_type):
3533 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3534 elif dst_type.is_ptr:
3535 base_type = dst_type.base_type
3536 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3537 for i in range(len(self.original_args)):
3538 arg = self.args[i]
3539 if isinstance(arg, CoerceToPyTypeNode):
3540 arg = arg.arg
3541 self.args[i] = arg.coerce_to(base_type, env)
3542 elif dst_type.is_struct:
3543 if len(self.args) > len(dst_type.scope.var_entries):
3544 error(self.pos, "Too may members for '%s'" % dst_type)
3545 else:
3546 if len(self.args) < len(dst_type.scope.var_entries):
3547 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3548 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3549 if isinstance(arg, CoerceToPyTypeNode):
3550 arg = arg.arg
3551 self.args[i] = arg.coerce_to(member.type, env)
3552 self.type = dst_type
3553 else:
3554 self.type = error_type
3555 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3556 return self
3558 def release_temp(self, env):
3559 if self.type.is_array:
3560 # To be valid C++, we must allocate the memory on the stack
3561 # manually and be sure not to reuse it for something else.
3562 pass
3563 else:
3564 SequenceNode.release_temp(self, env)
3566 def calculate_constant_result(self):
3567 self.constant_result = [
3568 arg.constant_result for arg in self.args]
3570 def compile_time_value(self, denv):
3571 return self.compile_time_value_list(denv)
3573 def generate_operation_code(self, code):
3574 if self.type.is_pyobject:
3575 for err in self.obj_conversion_errors:
3576 report_error(err)
3577 code.putln("%s = PyList_New(%s); %s" %
3578 (self.result(),
3579 len(self.args),
3580 code.error_goto_if_null(self.result(), self.pos)))
3581 code.put_gotref(self.py_result())
3582 for i in range(len(self.args)):
3583 arg = self.args[i]
3584 #if not arg.is_temp:
3585 if not arg.result_in_temp():
3586 code.put_incref(arg.result(), arg.ctype())
3587 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3588 (self.result(),
3589 i,
3590 arg.py_result()))
3591 code.put_giveref(arg.py_result())
3592 elif self.type.is_array:
3593 for i, arg in enumerate(self.args):
3594 code.putln("%s[%s] = %s;" % (
3595 self.result(),
3596 i,
3597 arg.result()))
3598 elif self.type.is_struct:
3599 for arg, member in zip(self.args, self.type.scope.var_entries):
3600 code.putln("%s.%s = %s;" % (
3601 self.result(),
3602 member.cname,
3603 arg.result()))
3604 else:
3605 raise InternalError("List type never specified")
3607 def generate_subexpr_disposal_code(self, code):
3608 # We call generate_post_assignment_code here instead
3609 # of generate_disposal_code, because values were stored
3610 # in the list using a reference-stealing operation.
3611 for arg in self.args:
3612 arg.generate_post_assignment_code(code)
3613 # Should NOT call free_temps -- this is invoked by the default
3614 # generate_evaluation_code which will do that.
3617 class ComprehensionNode(ExprNode):
3618 subexprs = ["target"]
3619 child_attrs = ["loop", "append"]
3621 def infer_type(self, env):
3622 return self.target.infer_type(env)
3624 def analyse_types(self, env):
3625 self.target.analyse_expressions(env)
3626 self.type = self.target.type
3627 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3628 # We are analysing declarations to late.
3629 self.loop.target.analyse_target_declaration(env)
3630 env.infer_types()
3631 self.loop.analyse_declarations(env)
3632 self.loop.analyse_expressions(env)
3634 def calculate_result_code(self):
3635 return self.target.result()
3637 def generate_result_code(self, code):
3638 self.generate_operation_code(code)
3640 def generate_operation_code(self, code):
3641 self.loop.generate_execution_code(code)
3643 def annotate(self, code):
3644 self.loop.annotate(code)
3647 class ComprehensionAppendNode(ExprNode):
3648 # Need to be careful to avoid infinite recursion:
3649 # target must not be in child_attrs/subexprs
3650 subexprs = ['expr']
3652 type = PyrexTypes.c_int_type
3654 def analyse_types(self, env):
3655 self.expr.analyse_types(env)
3656 if not self.expr.type.is_pyobject:
3657 self.expr = self.expr.coerce_to_pyobject(env)
3658 self.is_temp = 1
3660 def generate_result_code(self, code):
3661 if self.target.type is list_type:
3662 function = "PyList_Append"
3663 elif self.target.type is set_type:
3664 function = "PySet_Add"
3665 else:
3666 raise InternalError(
3667 "Invalid type for comprehension node: %s" % self.target.type)
3669 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3670 (self.result(),
3671 function,
3672 self.target.result(),
3673 self.expr.result(),
3674 code.error_goto_if(self.result(), self.pos)))
3676 class DictComprehensionAppendNode(ComprehensionAppendNode):
3677 subexprs = ['key_expr', 'value_expr']
3679 def analyse_types(self, env):
3680 self.key_expr.analyse_types(env)
3681 if not self.key_expr.type.is_pyobject:
3682 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3683 self.value_expr.analyse_types(env)
3684 if not self.value_expr.type.is_pyobject:
3685 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3686 self.is_temp = 1
3688 def generate_result_code(self, code):
3689 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3690 (self.result(),
3691 self.target.result(),
3692 self.key_expr.result(),
3693 self.value_expr.result(),
3694 code.error_goto_if(self.result(), self.pos)))
3697 class SetNode(ExprNode):
3698 # Set constructor.
3700 type = set_type
3702 subexprs = ['args']
3704 gil_message = "Constructing Python set"
3706 def analyse_types(self, env):
3707 for i in range(len(self.args)):
3708 arg = self.args[i]
3709 arg.analyse_types(env)
3710 self.args[i] = arg.coerce_to_pyobject(env)
3711 self.type = set_type
3712 self.is_temp = 1
3714 def calculate_constant_result(self):
3715 self.constant_result = set([
3716 arg.constant_result for arg in self.args])
3718 def compile_time_value(self, denv):
3719 values = [arg.compile_time_value(denv) for arg in self.args]
3720 try:
3721 return set(values)
3722 except Exception, e:
3723 self.compile_time_value_error(e)
3725 def generate_evaluation_code(self, code):
3726 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3727 self.allocate_temp_result(code)
3728 code.putln(
3729 "%s = PySet_New(0); %s" % (
3730 self.result(),
3731 code.error_goto_if_null(self.result(), self.pos)))
3732 code.put_gotref(self.py_result())
3733 for arg in self.args:
3734 arg.generate_evaluation_code(code)
3735 code.putln(
3736 code.error_goto_if_neg(
3737 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3738 self.pos))
3739 arg.generate_disposal_code(code)
3740 arg.free_temps(code)
3743 class DictNode(ExprNode):
3744 # Dictionary constructor.
3745 #
3746 # key_value_pairs [DictItemNode]
3747 #
3748 # obj_conversion_errors [PyrexError] used internally
3750 subexprs = ['key_value_pairs']
3751 is_temp = 1
3752 type = dict_type
3754 obj_conversion_errors = []
3756 def calculate_constant_result(self):
3757 self.constant_result = dict([
3758 item.constant_result for item in self.key_value_pairs])
3760 def compile_time_value(self, denv):
3761 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3762 for item in self.key_value_pairs]
3763 try:
3764 return dict(pairs)
3765 except Exception, e:
3766 self.compile_time_value_error(e)
3768 def type_dependencies(self, env):
3769 return ()
3771 def infer_type(self, env):
3772 # TOOD: Infer struct constructors.
3773 return dict_type
3775 def analyse_types(self, env):
3776 hold_errors()
3777 for item in self.key_value_pairs:
3778 item.analyse_types(env)
3779 self.obj_conversion_errors = held_errors()
3780 release_errors(ignore=True)
3782 def coerce_to(self, dst_type, env):
3783 if dst_type.is_pyobject:
3784 self.release_errors()
3785 if not self.type.subtype_of(dst_type):
3786 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3787 elif dst_type.is_struct_or_union:
3788 self.type = dst_type
3789 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3790 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3791 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3792 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3793 for item in self.key_value_pairs:
3794 if isinstance(item.key, CoerceToPyTypeNode):
3795 item.key = item.key.arg
3796 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3797 error(item.key.pos, "Invalid struct field identifier")
3798 item.key = StringNode(item.key.pos, value="<error>")
3799 else:
3800 key = str(item.key.value) # converts string literals to unicode in Py3
3801 member = dst_type.scope.lookup_here(key)
3802 if not member:
3803 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3804 else:
3805 value = item.value
3806 if isinstance(value, CoerceToPyTypeNode):
3807 value = value.arg
3808 item.value = value.coerce_to(member.type, env)
3809 else:
3810 self.type = error_type
3811 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3812 return self
3814 def release_errors(self):
3815 for err in self.obj_conversion_errors:
3816 report_error(err)
3817 self.obj_conversion_errors = []
3819 gil_message = "Constructing Python dict"
3821 def generate_evaluation_code(self, code):
3822 # Custom method used here because key-value
3823 # pairs are evaluated and used one at a time.
3824 code.mark_pos(self.pos)
3825 self.allocate_temp_result(code)
3826 if self.type.is_pyobject:
3827 self.release_errors()
3828 code.putln(
3829 "%s = PyDict_New(); %s" % (
3830 self.result(),
3831 code.error_goto_if_null(self.result(), self.pos)))
3832 code.put_gotref(self.py_result())
3833 for item in self.key_value_pairs:
3834 item.generate_evaluation_code(code)
3835 if self.type.is_pyobject:
3836 code.put_error_if_neg(self.pos,
3837 "PyDict_SetItem(%s, %s, %s)" % (
3838 self.result(),
3839 item.key.py_result(),
3840 item.value.py_result()))
3841 else:
3842 code.putln("%s.%s = %s;" % (
3843 self.result(),
3844 item.key.value,
3845 item.value.result()))
3846 item.generate_disposal_code(code)
3847 item.free_temps(code)
3849 def annotate(self, code):
3850 for item in self.key_value_pairs:
3851 item.annotate(code)
3853 class DictItemNode(ExprNode):
3854 # Represents a single item in a DictNode
3855 #
3856 # key ExprNode
3857 # value ExprNode
3858 subexprs = ['key', 'value']
3860 nogil_check = None # Parent DictNode takes care of it
3862 def calculate_constant_result(self):
3863 self.constant_result = (
3864 self.key.constant_result, self.value.constant_result)
3866 def analyse_types(self, env):
3867 self.key.analyse_types(env)
3868 self.value.analyse_types(env)
3869 self.key = self.key.coerce_to_pyobject(env)
3870 self.value = self.value.coerce_to_pyobject(env)
3872 def generate_evaluation_code(self, code):
3873 self.key.generate_evaluation_code(code)
3874 self.value.generate_evaluation_code(code)
3876 def generate_disposal_code(self, code):
3877 self.key.generate_disposal_code(code)
3878 self.value.generate_disposal_code(code)
3880 def free_temps(self, code):
3881 self.key.free_temps(code)
3882 self.value.free_temps(code)
3884 def __iter__(self):
3885 return iter([self.key, self.value])
3888 class ClassNode(ExprNode):
3889 # Helper class used in the implementation of Python
3890 # class definitions. Constructs a class object given
3891 # a name, tuple of bases and class dictionary.
3892 #
3893 # name EncodedString Name of the class
3894 # bases ExprNode Base class tuple
3895 # dict ExprNode Class dict (not owned by this node)
3896 # doc ExprNode or None Doc string
3897 # module_name string Name of defining module
3899 subexprs = ['bases', 'doc']
3901 def analyse_types(self, env):
3902 self.bases.analyse_types(env)
3903 if self.doc:
3904 self.doc.analyse_types(env)
3905 self.doc = self.doc.coerce_to_pyobject(env)
3906 self.module_name = env.global_scope().qualified_name
3907 self.type = py_object_type
3908 self.is_temp = 1
3909 env.use_utility_code(create_class_utility_code);
3911 gil_message = "Constructing Python class"
3913 def generate_result_code(self, code):
3914 cname = code.intern_identifier(self.name)
3915 if self.doc:
3916 code.put_error_if_neg(self.pos,
3917 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3918 self.dict.py_result(),
3919 self.doc.py_result()))
3920 code.putln(
3921 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3922 self.result(),
3923 self.bases.py_result(),
3924 self.dict.py_result(),
3925 cname,
3926 self.module_name,
3927 code.error_goto_if_null(self.result(), self.pos)))
3928 code.put_gotref(self.py_result())
3930 class BoundMethodNode(ExprNode):
3931 # Helper class used in the implementation of Python
3932 # class definitions. Constructs an bound method
3933 # object from a class and a function.
3934 #
3935 # function ExprNode Function object
3936 # self_object ExprNode self object
3938 subexprs = ['function']
3940 def analyse_types(self, env):
3941 self.function.analyse_types(env)
3942 self.type = py_object_type
3943 self.is_temp = 1
3945 gil_message = "Constructing an bound method"
3947 def generate_result_code(self, code):
3948 code.putln(
3949 "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % (
3950 self.result(),
3951 self.function.py_result(),
3952 self.self_object.py_result(),
3953 self.self_object.py_result(),
3954 code.error_goto_if_null(self.result(), self.pos)))
3955 code.put_gotref(self.py_result())
3957 class UnboundMethodNode(ExprNode):
3958 # Helper class used in the implementation of Python
3959 # class definitions. Constructs an unbound method
3960 # object from a class and a function.
3961 #
3962 # function ExprNode Function object
3964 type = py_object_type
3965 is_temp = 1
3967 subexprs = ['function']
3969 def analyse_types(self, env):
3970 self.function.analyse_types(env)
3972 gil_message = "Constructing an unbound method"
3974 def generate_result_code(self, code):
3975 class_cname = code.pyclass_stack[-1].classobj.result()
3976 code.putln(
3977 "%s = PyMethod_New(%s, 0, %s); %s" % (
3978 self.result(),
3979 self.function.py_result(),
3980 class_cname,
3981 code.error_goto_if_null(self.result(), self.pos)))
3982 code.put_gotref(self.py_result())
3984 class PyCFunctionNode(ExprNode):
3985 # Helper class used in the implementation of Python
3986 # class definitions. Constructs a PyCFunction object
3987 # from a PyMethodDef struct.
3988 #
3989 # pymethdef_cname string PyMethodDef structure
3990 # self_object ExprNode or None
3992 subexprs = []
3993 self_object = None
3995 type = py_object_type
3996 is_temp = 1
3998 def analyse_types(self, env):
3999 pass
4001 gil_message = "Constructing Python function"
4003 def self_result_code(self):
4004 if self.self_object is None:
4005 self_result = "NULL"
4006 else:
4007 self_result = self.self_object.py_result()
4008 return self_result
4010 def generate_result_code(self, code):
4011 code.putln(
4012 "%s = PyCFunction_New(&%s, %s); %s" % (
4013 self.result(),
4014 self.pymethdef_cname,
4015 self.self_result_code(),
4016 code.error_goto_if_null(self.result(), self.pos)))
4017 code.put_gotref(self.py_result())
4019 class InnerFunctionNode(PyCFunctionNode):
4020 # Special PyCFunctionNode that depends on a closure class
4021 #
4022 def self_result_code(self):
4023 return "((PyObject*)%s)" % Naming.cur_scope_cname
4025 class LambdaNode(InnerFunctionNode):
4026 # Lambda expression node (only used as a function reference)
4027 #
4028 # args [CArgDeclNode] formal arguments
4029 # star_arg PyArgDeclNode or None * argument
4030 # starstar_arg PyArgDeclNode or None ** argument
4031 # lambda_name string a module-globally unique lambda name
4032 # result_expr ExprNode
4033 # def_node DefNode the underlying function 'def' node
4035 child_attrs = ['def_node']
4037 def_node = None
4038 name = StringEncoding.EncodedString('<lambda>')
4040 def analyse_declarations(self, env):
4041 #self.def_node.needs_closure = self.needs_closure
4042 self.def_node.analyse_declarations(env)
4043 self.pymethdef_cname = self.def_node.entry.pymethdef_cname
4044 env.add_lambda_def(self.def_node)
4046 class YieldExprNode(ExprNode):
4047 # Yield expression node
4048 #
4049 # arg ExprNode the value to return from the generator
4050 # label_name string name of the C label used for this yield
4052 subexprs = []
4053 type = py_object_type
4055 def analyse_types(self, env):
4056 self.is_temp = 1
4057 if self.arg is not None:
4058 self.arg.analyse_types(env)
4059 if not self.arg.type.is_pyobject:
4060 self.arg = self.arg.coerce_to_pyobject(env)
4062 def generate_result_code(self, code):
4063 self.label_name = code.new_label('resume_from_yield')
4064 code.use_label(self.label_name)
4065 code.putln("/* FIXME: save temporary variables */")
4066 code.putln("/* FIXME: return from function, yielding value */")
4067 code.put_label(self.label_name)
4068 code.putln("/* FIXME: restore temporary variables and */")
4069 code.putln("/* FIXME: extract sent value from closure */")
4072 #-------------------------------------------------------------------
4073 #
4074 # Unary operator nodes
4075 #
4076 #-------------------------------------------------------------------
4078 compile_time_unary_operators = {
4079 'not': operator.not_,
4080 '~': operator.inv,
4081 '-': operator.neg,
4082 '+': operator.pos,
4083 }
4085 class UnopNode(ExprNode):
4086 # operator string
4087 # operand ExprNode
4088 #
4089 # Processing during analyse_expressions phase:
4090 #
4091 # analyse_c_operation
4092 # Called when the operand is not a pyobject.
4093 # - Check operand type and coerce if needed.
4094 # - Determine result type and result code fragment.
4095 # - Allocate temporary for result if needed.
4097 subexprs = ['operand']
4098 infix = True
4100 def calculate_constant_result(self):
4101 func = compile_time_unary_operators[self.operator]
4102 self.constant_result = func(self.operand.constant_result)
4104 def compile_time_value(self, denv):
4105 func = compile_time_unary_operators.get(self.operator)
4106 if not func:
4107 error(self.pos,
4108 "Unary '%s' not supported in compile-time expression"
4109 % self.operator)
4110 operand = self.operand.compile_time_value(denv)
4111 try:
4112 return func(operand)
4113 except Exception, e:
4114 self.compile_time_value_error(e)
4116 def infer_type(self, env):
4117 return self.operand.infer_type(env)
4119 def analyse_types(self, env):
4120 self.operand.analyse_types(env)
4121 if self.is_py_operation():
4122 self.coerce_operand_to_pyobject(env)
4123 self.type = py_object_type
4124 self.is_temp = 1
4125 else:
4126 self.analyse_c_operation(env)
4128 def check_const(self):
4129 return self.operand.check_const()
4131 def is_py_operation(self):
4132 return self.operand.type.is_pyobject
4134 def nogil_check(self, env):
4135 if self.is_py_operation():
4136 self.gil_error()
4138 def coerce_operand_to_pyobject(self, env):
4139 self.operand = self.operand.coerce_to_pyobject(env)
4141 def generate_result_code(self, code):
4142 if self.operand.type.is_pyobject:
4143 self.generate_py_operation_code(code)
4145 def generate_py_operation_code(self, code):
4146 function = self.py_operation_function()
4147 code.putln(
4148 "%s = %s(%s); %s" % (
4149 self.result(),
4150 function,
4151 self.operand.py_result(),
4152 code.error_goto_if_null(self.result(), self.pos)))
4153 code.put_gotref(self.py_result())
4155 def type_error(self):
4156 if not self.operand.type.is_error:
4157 error(self.pos, "Invalid operand type for '%s' (%s)" %
4158 (self.operator, self.operand.type))
4159 self.type = PyrexTypes.error_type
4162 class NotNode(ExprNode):
4163 # 'not' operator
4164 #
4165 # operand ExprNode
4167 type = PyrexTypes.c_bint_type
4169 subexprs = ['operand']
4171 def calculate_constant_result(self):
4172 self.constant_result = not self.operand.constant_result
4174 def compile_time_value(self, denv):
4175 operand = self.operand.compile_time_value(denv)
4176 try:
4177 return not operand
4178 except Exception, e:
4179 self.compile_time_value_error(e)
4181 def infer_type(self, env):
4182 return PyrexTypes.c_bint_type
4184 def analyse_types(self, env):
4185 self.operand.analyse_types(env)
4186 self.operand = self.operand.coerce_to_boolean(env)
4188 def calculate_result_code(self):
4189 return "(!%s)" % self.operand.result()
4191 def generate_result_code(self, code):
4192 pass
4195 class UnaryPlusNode(UnopNode):
4196 # unary '+' operator
4198 operator = '+'
4200 def analyse_c_operation(self, env):
4201 self.type = self.operand.type
4203 def py_operation_function(self):
4204 return "PyNumber_Positive"
4206 def calculate_result_code(self):
4207 return self.operand.result()
4210 class UnaryMinusNode(UnopNode):
4211 # unary '-' operator
4213 operator = '-'
4215 def analyse_c_operation(self, env):
4216 if self.operand.type.is_numeric:
4217 self.type = self.operand.type
4218 else:
4219 self.type_error()
4220 if self.type.is_complex:
4221 self.infix = False
4223 def py_operation_function(self):
4224 return "PyNumber_Negative"
4226 def calculate_result_code(self):
4227 if self.infix:
4228 return "(-%s)" % self.operand.result()
4229 else:
4230 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4232 def get_constant_c_result_code(self):
4233 value = self.operand.get_constant_c_result_code()
4234 if value:
4235 return "(-%s)" % (value)
4237 class TildeNode(UnopNode):
4238 # unary '~' operator
4240 def analyse_c_operation(self, env):
4241 if self.operand.type.is_int:
4242 self.type = self.operand.type
4243 else:
4244 self.type_error()
4246 def py_operation_function(self):
4247 return "PyNumber_Invert"
4249 def calculate_result_code(self):
4250 return "(~%s)" % self.operand.result()
4253 class AmpersandNode(ExprNode):
4254 # The C address-of operator.
4255 #
4256 # operand ExprNode
4258 subexprs = ['operand']
4260 def infer_type(self, env):
4261 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4263 def analyse_types(self, env):
4264 self.operand.analyse_types(env)
4265 argtype = self.operand.type
4266 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4267 self.error("Taking address of non-lvalue")
4268 return
4269 if argtype.is_pyobject:
4270 self.error("Cannot take address of Python variable")
4271 return
4272 self.type = PyrexTypes.c_ptr_type(argtype)
4274 def check_const(self):
4275 return self.operand.check_const_addr()
4277 def error(self, mess):
4278 error(self.pos, mess)
4279 self.type = PyrexTypes.error_type
4280 self.result_code = "<error>"
4282 def calculate_result_code(self):
4283 return "(&%s)" % self.operand.result()
4285 def generate_result_code(self, code):
4286 pass
4289 unop_node_classes = {
4290 "+": UnaryPlusNode,
4291 "-": UnaryMinusNode,
4292 "~": TildeNode,
4293 }
4295 def unop_node(pos, operator, operand):
4296 # Construct unnop node of appropriate class for
4297 # given operator.
4298 if isinstance(operand, IntNode) and operator == '-':
4299 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4300 elif isinstance(operand, UnopNode) and operand.operator == operator:
4301 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4302 return unop_node_classes[operator](pos,
4303 operator = operator,
4304 operand = operand)
4307 class TypecastNode(ExprNode):
4308 # C type cast
4309 #
4310 # operand ExprNode
4311 # base_type CBaseTypeNode
4312 # declarator CDeclaratorNode
4313 #
4314 # If used from a transform, one can if wanted specify the attribute
4315 # "type" directly and leave base_type and declarator to None
4317 subexprs = ['operand']
4318 base_type = declarator = type = None
4320 def type_dependencies(self, env):
4321 return ()
4323 def infer_type(self, env):
4324 if self.type is None:
4325 base_type = self.base_type.analyse(env)
4326 _, self.type = self.declarator.analyse(base_type, env)
4327 return self.type
4329 def analyse_types(self, env):
4330 if self.type is None:
4331 base_type = self.base_type.analyse(env)
4332 _, self.type = self.declarator.analyse(base_type, env)
4333 if self.type.is_cfunction:
4334 error(self.pos,
4335 "Cannot cast to a function type")
4336 self.type = PyrexTypes.error_type
4337 self.operand.analyse_types(env)
4338 to_py = self.type.is_pyobject
4339 from_py = self.operand.type.is_pyobject
4340 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4341 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4342 if to_py and not from_py:
4343 if self.operand.type.create_to_py_utility_code(env):
4344 self.result_ctype = py_object_type
4345 self.operand = self.operand.coerce_to_pyobject(env)
4346 else:
4347 if self.operand.type.is_ptr:
4348 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
4349 error(self.pos, "Python objects cannot be cast from pointers of primitive types")
4350 else:
4351 # Should this be an error?
4352 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4353 self.operand = self.operand.coerce_to_simple(env)
4354 elif from_py and not to_py:
4355 if self.type.create_from_py_utility_code(env):
4356 self.operand = self.operand.coerce_to(self.type, env)
4357 elif self.type.is_ptr:
4358 if not (self.type.base_type.is_void or self.type.base_type.is_struct):
4359 error(self.pos, "Python objects cannot be cast to pointers of primitive types")
4360 else:
4361 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4362 elif from_py and to_py:
4363 if self.typecheck and self.type.is_extension_type:
4364 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
4366 def nogil_check(self, env):
4367 if self.type and self.type.is_pyobject and self.is_temp:
4368 self.gil_error()
4370 def check_const(self):
4371 return self.operand.check_const()
4373 def calculate_constant_result(self):
4374 # we usually do not know the result of a type cast at code
4375 # generation time
4376 pass
4378 def calculate_result_code(self):
4379 opnd = self.operand
4380 return self.type.cast_code(opnd.result())
4382 def get_constant_c_result_code(self):
4383 operand_result = self.operand.get_constant_c_result_code()
4384 if operand_result:
4385 return self.type.cast_code(operand_result)
4387 def result_as(self, type):
4388 if self.type.is_pyobject and not self.is_temp:
4389 # Optimise away some unnecessary casting
4390 return self.operand.result_as(type)
4391 else:
4392 return ExprNode.result_as(self, type)
4394 def generate_result_code(self, code):
4395 if self.is_temp:
4396 code.putln(
4397 "%s = (PyObject *)%s;" % (
4398 self.result(),
4399 self.operand.result()))
4400 code.put_incref(self.result(), self.ctype())
4403 class SizeofNode(ExprNode):
4404 # Abstract base class for sizeof(x) expression nodes.
4406 type = PyrexTypes.c_size_t_type
4408 def check_const(self):
4409 return True
4411 def generate_result_code(self, code):
4412 pass
4415 class SizeofTypeNode(SizeofNode):
4416 # C sizeof function applied to a type
4417 #
4418 # base_type CBaseTypeNode
4419 # declarator CDeclaratorNode
4421 subexprs = []
4422 arg_type = None
4424 def analyse_types(self, env):
4425 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4426 # this could be better handled by more uniformly treating types as runtime-available objects
4427 if 0 and self.base_type.module_path:
4428 path = self.base_type.module_path
4429 obj = env.lookup(path[0])
4430 if obj.as_module is None:
4431 operand = NameNode(pos=self.pos, name=path[0])
4432 for attr in path[1:]:
4433 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4434 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4435 self.operand = operand
4436 self.__class__ = SizeofVarNode
4437 self.analyse_types(env)
4438 return
4439 if self.arg_type is None:
4440 base_type = self.base_type.analyse(env)
4441 _, arg_type = self.declarator.analyse(base_type, env)
4442 self.arg_type = arg_type
4443 self.check_type()
4445 def check_type(self):
4446 arg_type = self.arg_type
4447 if arg_type.is_pyobject and not arg_type.is_extension_type:
4448 error(self.pos, "Cannot take sizeof Python object")
4449 elif arg_type.is_void:
4450 error(self.pos, "Cannot take sizeof void")
4451 elif not arg_type.is_complete():
4452 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4454 def calculate_result_code(self):
4455 if self.arg_type.is_extension_type:
4456 # the size of the pointer is boring
4457 # we want the size of the actual struct
4458 arg_code = self.arg_type.declaration_code("", deref=1)
4459 else:
4460 arg_code = self.arg_type.declaration_code("")
4461 return "(sizeof(%s))" % arg_code
4464 class SizeofVarNode(SizeofNode):
4465 # C sizeof function applied to a variable
4466 #
4467 # operand ExprNode
4469 subexprs = ['operand']
4471 def analyse_types(self, env):
4472 # We may actually be looking at a type rather than a variable...
4473 # If we are, traditional analysis would fail...
4474 operand_as_type = self.operand.analyse_as_type(env)
4475 if operand_as_type:
4476 self.arg_type = operand_as_type
4477 self.__class__ = SizeofTypeNode
4478 self.check_type()
4479 else:
4480 self.operand.analyse_types(env)
4482 def calculate_result_code(self):
4483 return "(sizeof(%s))" % self.operand.result()
4485 def generate_result_code(self, code):
4486 pass
4488 class TypeofNode(ExprNode):
4489 # Compile-time type of an expression, as a string.
4490 #
4491 # operand ExprNode
4492 # literal StringNode # internal
4494 literal = None
4495 type = py_object_type
4497 subexprs = ['operand', 'literal']
4499 def analyse_types(self, env):
4500 self.operand.analyse_types(env)
4501 self.literal = StringNode(
4502 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4503 self.literal.analyse_types(env)
4504 self.literal = self.literal.coerce_to_pyobject(env)
4506 def generate_evaluation_code(self, code):
4507 self.literal.generate_evaluation_code(code)
4509 def calculate_result_code(self):
4510 return self.literal.calculate_result_code()
4512 #-------------------------------------------------------------------
4513 #
4514 # Binary operator nodes
4515 #
4516 #-------------------------------------------------------------------
4518 def _not_in(x, seq):
4519 return x not in seq
4521 compile_time_binary_operators = {
4522 '<': operator.lt,
4523 '<=': operator.le,
4524 '==': operator.eq,
4525 '!=': operator.ne,
4526 '>=': operator.ge,
4527 '>': operator.gt,
4528 'is': operator.is_,
4529 'is_not': operator.is_not,
4530 '+': operator.add,
4531 '&': operator.and_,
4532 '/': operator.truediv,
4533 '//': operator.floordiv,
4534 '<<': operator.lshift,
4535 '%': operator.mod,
4536 '*': operator.mul,
4537 '|': operator.or_,
4538 '**': operator.pow,
4539 '>>': operator.rshift,
4540 '-': operator.sub,
4541 '^': operator.xor,
4542 'in': operator.contains,
4543 'not_in': _not_in,
4544 }
4546 def get_compile_time_binop(node):
4547 func = compile_time_binary_operators.get(node.operator)
4548 if not func:
4549 error(node.pos,
4550 "Binary '%s' not supported in compile-time expression"
4551 % node.operator)
4552 return func
4554 class BinopNode(ExprNode):
4555 # operator string
4556 # operand1 ExprNode
4557 # operand2 ExprNode
4558 #
4559 # Processing during analyse_expressions phase:
4560 #
4561 # analyse_c_operation
4562 # Called when neither operand is a pyobject.
4563 # - Check operand types and coerce if needed.
4564 # - Determine result type and result code fragment.
4565 # - Allocate temporary for result if needed.
4567 subexprs = ['operand1', 'operand2']
4569 def calculate_constant_result(self):
4570 func = compile_time_binary_operators[self.operator]
4571 self.constant_result = func(
4572 self.operand1.constant_result,
4573 self.operand2.constant_result)
4575 def compile_time_value(self, denv):
4576 func = get_compile_time_binop(self)
4577 operand1 = self.operand1.compile_time_value(denv)
4578 operand2 = self.operand2.compile_time_value(denv)
4579 try:
4580 return func(operand1, operand2)
4581 except Exception, e:
4582 self.compile_time_value_error(e)
4584 def infer_type(self, env):
4585 return self.result_type(self.operand1.infer_type(env),
4586 self.operand2.infer_type(env))
4588 def analyse_types(self, env):
4589 self.operand1.analyse_types(env)
4590 self.operand2.analyse_types(env)
4591 if self.is_py_operation():
4592 self.coerce_operands_to_pyobjects(env)
4593 self.type = py_object_type
4594 self.is_temp = 1
4595 else:
4596 self.analyse_c_operation(env)
4598 def is_py_operation(self):
4599 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4601 def is_py_operation_types(self, type1, type2):
4602 return type1.is_pyobject or type2.is_pyobject
4604 def result_type(self, type1, type2):
4605 if self.is_py_operation_types(type1, type2):
4606 return py_object_type
4607 else:
4608 return self.compute_c_result_type(type1, type2)
4610 def nogil_check(self, env):
4611 if self.is_py_operation():
4612 self.gil_error()
4614 def coerce_operands_to_pyobjects(self, env):
4615 self.operand1 = self.operand1.coerce_to_pyobject(env)
4616 self.operand2 = self.operand2.coerce_to_pyobject(env)
4618 def check_const(self):
4619 return self.operand1.check_const() and self.operand2.check_const()
4621 def generate_result_code(self, code):
4622 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4623 if self.operand1.type.is_pyobject:
4624 function = self.py_operation_function()
4625 if function == "PyNumber_Power":
4626 extra_args = ", Py_None"
4627 else:
4628 extra_args = ""
4629 code.putln(
4630 "%s = %s(%s, %s%s); %s" % (
4631 self.result(),
4632 function,
4633 self.operand1.py_result(),
4634 self.operand2.py_result(),
4635 extra_args,
4636 code.error_goto_if_null(self.result(), self.pos)))
4637 code.put_gotref(self.py_result())
4639 def type_error(self):
4640 if not (self.operand1.type.is_error
4641 or self.operand2.type.is_error):
4642 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4643 (self.operator, self.operand1.type,
4644 self.operand2.type))
4645 self.type = PyrexTypes.error_type
4648 class NumBinopNode(BinopNode):
4649 # Binary operation taking numeric arguments.
4651 infix = True
4653 def analyse_c_operation(self, env):
4654 type1 = self.operand1.type
4655 type2 = self.operand2.type
4656 self.type = self.compute_c_result_type(type1, type2)
4657 if not self.type:
4658 self.type_error()
4659 return
4660 if self.type.is_complex:
4661 self.infix = False
4662 if not self.infix:
4663 self.operand1 = self.operand1.coerce_to(self.type, env)
4664 self.operand2 = self.operand2.coerce_to(self.type, env)
4666 def compute_c_result_type(self, type1, type2):
4667 if self.c_types_okay(type1, type2):
4668 return PyrexTypes.widest_numeric_type(type1, type2)
4669 else:
4670 return None
4672 def get_constant_c_result_code(self):
4673 value1 = self.operand1.get_constant_c_result_code()
4674 value2 = self.operand2.get_constant_c_result_code()
4675 if value1 and value2:
4676 return "(%s %s %s)" % (value1, self.operator, value2)
4677 else:
4678 return None
4680 def c_types_okay(self, type1, type2):
4681 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4682 return (type1.is_numeric or type1.is_enum) \
4683 and (type2.is_numeric or type2.is_enum)
4685 def calculate_result_code(self):
4686 if self.infix:
4687 return "(%s %s %s)" % (
4688 self.operand1.result(),
4689 self.operator,
4690 self.operand2.result())
4691 else:
4692 func = self.type.binary_op(self.operator)
4693 if func is None:
4694 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4695 return "%s(%s, %s)" % (
4696 func,
4697 self.operand1.result(),
4698 self.operand2.result())
4700 def py_operation_function(self):
4701 return self.py_functions[self.operator]
4703 py_functions = {
4704 "|": "PyNumber_Or",
4705 "^": "PyNumber_Xor",
4706 "&": "PyNumber_And",
4707 "<<": "PyNumber_Lshift",
4708 ">>": "PyNumber_Rshift",
4709 "+": "PyNumber_Add",
4710 "-": "PyNumber_Subtract",
4711 "*": "PyNumber_Multiply",
4712 "/": "__Pyx_PyNumber_Divide",
4713 "//": "PyNumber_FloorDivide",
4714 "%": "PyNumber_Remainder",
4715 "**": "PyNumber_Power"
4716 }
4719 class IntBinopNode(NumBinopNode):
4720 # Binary operation taking integer arguments.
4722 def c_types_okay(self, type1, type2):
4723 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4724 return (type1.is_int or type1.is_enum) \
4725 and (type2.is_int or type2.is_enum)
4728 class AddNode(NumBinopNode):
4729 # '+' operator.
4731 def is_py_operation_types(self, type1, type2):
4732 if type1.is_string and type2.is_string:
4733 return 1
4734 else:
4735 return NumBinopNode.is_py_operation_types(self, type1, type2)
4737 def compute_c_result_type(self, type1, type2):
4738 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4739 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4740 return type1
4741 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4742 return type2
4743 else:
4744 return NumBinopNode.compute_c_result_type(
4745 self, type1, type2)
4748 class SubNode(NumBinopNode):
4749 # '-' operator.
4751 def compute_c_result_type(self, type1, type2):
4752 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4753 return type1
4754 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4755 return PyrexTypes.c_int_type
4756 else:
4757 return NumBinopNode.compute_c_result_type(
4758 self, type1, type2)
4761 class MulNode(NumBinopNode):
4762 # '*' operator.
4764 def is_py_operation_types(self, type1, type2):
4765 if (type1.is_string and type2.is_int) \
4766 or (type2.is_string and type1.is_int):
4767 return 1
4768 else:
4769 return NumBinopNode.is_py_operation_types(self, type1, type2)
4772 class DivNode(NumBinopNode):
4773 # '/' or '//' operator.
4775 cdivision = None
4776 truedivision = None # == "unknown" if operator == '/'
4777 ctruedivision = False
4778 cdivision_warnings = False
4779 zerodivision_check = None
4781 def find_compile_time_binary_operator(self, op1, op2):
4782 func = compile_time_binary_operators[self.operator]
4783 if self.operator == '/' and self.truedivision is None:
4784 # => true div for floats, floor div for integers
4785 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4786 func = compile_time_binary_operators['//']
4787 return func
4789 def calculate_constant_result(self):
4790 op1 = self.operand1.constant_result
4791 op2 = self.operand2.constant_result
4792 func = self.find_compile_time_binary_operator(op1, op2)
4793 self.constant_result = func(
4794 self.operand1.constant_result,
4795 self.operand2.constant_result)
4797 def compile_time_value(self, denv):
4798 operand1 = self.operand1.compile_time_value(denv)
4799 operand2 = self.operand2.compile_time_value(denv)
4800 try:
4801 func = self.find_compile_time_binary_operator(
4802 self, operand1, operand2)
4803 return func(operand1, operand2)
4804 except Exception, e:
4805 self.compile_time_value_error(e)
4807 def analyse_types(self, env):
4808 if self.cdivision or env.directives['cdivision']:
4809 self.ctruedivision = False
4810 else:
4811 self.ctruedivision = self.truedivision
4812 NumBinopNode.analyse_types(self, env)
4813 if not self.type.is_pyobject:
4814 self.zerodivision_check = (
4815 self.cdivision is None and not env.directives['cdivision']
4816 and (self.operand2.constant_result is not_a_constant or
4817 self.operand2.constant_result == 0))
4818 if self.zerodivision_check or env.directives['cdivision_warnings']:
4819 # Need to check ahead of time to warn or raise zero division error
4820 self.operand1 = self.operand1.coerce_to_simple(env)
4821 self.operand2 = self.operand2.coerce_to_simple(env)
4822 if env.nogil:
4823 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4825 def compute_c_result_type(self, type1, type2):
4826 if self.operator == '/' and self.ctruedivision:
4827 if not type1.is_float and not type2.is_float:
4828 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4829 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4830 return widest_type
4831 return NumBinopNode.compute_c_result_type(self, type1, type2)
4833 def zero_division_message(self):
4834 if self.type.is_int:
4835 return "integer division or modulo by zero"
4836 else:
4837 return "float division"
4839 def generate_evaluation_code(self, code):
4840 if not self.type.is_pyobject and not self.type.is_complex:
4841 if self.cdivision is None:
4842 self.cdivision = (code.globalstate.directives['cdivision']
4843 or not self.type.signed
4844 or self.type.is_float)
4845 if not self.cdivision:
4846 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4847 NumBinopNode.generate_evaluation_code(self, code)
4848 self.generate_div_warning_code(code)
4850 def generate_div_warning_code(self, code):
4851 if not self.type.is_pyobject:
4852 if self.zerodivision_check:
4853 if not self.infix:
4854 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4855 else:
4856 zero_test = "%s == 0" % self.operand2.result()
4857 code.putln("if (unlikely(%s)) {" % zero_test)
4858 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4859 code.putln(code.error_goto(self.pos))
4860 code.putln("}")
4861 if self.type.is_int and self.type.signed and self.operator != '%':
4862 code.globalstate.use_utility_code(division_overflow_test_code)
4863 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4864 self.type.declaration_code(''),
4865 self.operand2.result(),
4866 self.operand1.result()))
4867 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4868 code.putln(code.error_goto(self.pos))
4869 code.putln("}")
4870 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4871 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4872 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4873 self.operand1.result(),
4874 self.operand2.result()))
4875 code.putln(code.set_error_info(self.pos));
4876 code.put("if (__Pyx_cdivision_warning()) ")
4877 code.put_goto(code.error_label)
4878 code.putln("}")
4880 def calculate_result_code(self):
4881 if self.type.is_complex:
4882 return NumBinopNode.calculate_result_code(self)
4883 elif self.type.is_float and self.operator == '//':
4884 return "floor(%s / %s)" % (
4885 self.operand1.result(),
4886 self.operand2.result())
4887 elif self.truedivision or self.cdivision:
4888 op1 = self.operand1.result()
4889 op2 = self.operand2.result()
4890 if self.truedivision:
4891 if self.type != self.operand1.type:
4892 op1 = self.type.cast_code(op1)
4893 if self.type != self.operand2.type:
4894 op2 = self.type.cast_code(op2)
4895 return "(%s / %s)" % (op1, op2)
4896 else:
4897 return "__Pyx_div_%s(%s, %s)" % (
4898 self.type.specalization_name(),
4899 self.operand1.result(),
4900 self.operand2.result())
4903 class ModNode(DivNode):
4904 # '%' operator.
4906 def is_py_operation_types(self, type1, type2):
4907 return (type1.is_string
4908 or type2.is_string
4909 or NumBinopNode.is_py_operation_types(self, type1, type2))
4911 def zero_division_message(self):
4912 if self.type.is_int:
4913 return "integer division or modulo by zero"
4914 else:
4915 return "float divmod()"
4917 def generate_evaluation_code(self, code):
4918 if not self.type.is_pyobject:
4919 if self.cdivision is None:
4920 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4921 if not self.cdivision:
4922 if self.type.is_int:
4923 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4924 else:
4925 code.globalstate.use_utility_code(
4926 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4927 NumBinopNode.generate_evaluation_code(self, code)
4928 self.generate_div_warning_code(code)
4930 def calculate_result_code(self):
4931 if self.cdivision:
4932 if self.type.is_float:
4933 return "fmod%s(%s, %s)" % (
4934 self.type.math_h_modifier,
4935 self.operand1.result(),
4936 self.operand2.result())
4937 else:
4938 return "(%s %% %s)" % (
4939 self.operand1.result(),
4940 self.operand2.result())
4941 else:
4942 return "__Pyx_mod_%s(%s, %s)" % (
4943 self.type.specalization_name(),
4944 self.operand1.result(),
4945 self.operand2.result())
4947 class PowNode(NumBinopNode):
4948 # '**' operator.
4950 def analyse_c_operation(self, env):
4951 NumBinopNode.analyse_c_operation(self, env)
4952 if self.type.is_complex:
4953 error(self.pos, "complex powers not yet supported")
4954 self.pow_func = "<error>"
4955 elif self.type.is_float:
4956 self.pow_func = "pow"
4957 else:
4958 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4959 env.use_utility_code(
4960 int_pow_utility_code.specialize(func_name=self.pow_func,
4961 type=self.type.declaration_code('')))
4963 def calculate_result_code(self):
4964 return "%s(%s, %s)" % (
4965 self.pow_func,
4966 self.operand1.result(),
4967 self.operand2.result())
4970 # Note: This class is temporary "shut down" into an ineffective mode temp
4971 # allocation mode.
4972 #
4973 # More sophisticated temp reuse was going on before,
4974 # one could have a look at adding this again after /all/ classes
4975 # are converted to the new temp scheme. (The temp juggling cannot work
4976 # otherwise).
4977 class BoolBinopNode(ExprNode):
4978 # Short-circuiting boolean operation.
4979 #
4980 # operator string
4981 # operand1 ExprNode
4982 # operand2 ExprNode
4984 subexprs = ['operand1', 'operand2']
4986 def infer_type(self, env):
4987 type1 = self.operand1.infer_type(env)
4988 type2 = self.operand2.infer_type(env)
4989 return PyrexTypes.spanning_type(type1, type2)
4991 def calculate_constant_result(self):
4992 if self.operator == 'and':
4993 self.constant_result = \
4994 self.operand1.constant_result and \
4995 self.operand2.constant_result
4996 else:
4997 self.constant_result = \
4998 self.operand1.constant_result or \
4999 self.operand2.constant_result
5001 def compile_time_value(self, denv):
5002 if self.operator == 'and':
5003 return self.operand1.compile_time_value(denv) \
5004 and self.operand2.compile_time_value(denv)
5005 else:
5006 return self.operand1.compile_time_value(denv) \
5007 or self.operand2.compile_time_value(denv)
5009 def coerce_to_boolean(self, env):
5010 self.operand1 = self.operand1.coerce_to_boolean(env)
5011 self.operand2 = self.operand2.coerce_to_boolean(env)
5012 self.type = PyrexTypes.c_bint_type
5013 return self
5015 def analyse_types(self, env):
5016 self.operand1.analyse_types(env)
5017 self.operand2.analyse_types(env)
5018 self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
5019 self.operand1 = self.operand1.coerce_to(self.type, env)
5020 self.operand2 = self.operand2.coerce_to(self.type, env)
5022 # For what we're about to do, it's vital that
5023 # both operands be temp nodes.
5024 self.operand1 = self.operand1.coerce_to_simple(env)
5025 self.operand2 = self.operand2.coerce_to_simple(env)
5026 self.is_temp = 1
5028 gil_message = "Truth-testing Python object"
5030 def check_const(self):
5031 return self.operand1.check_const() and self.operand2.check_const()
5033 def generate_evaluation_code(self, code):
5034 code.mark_pos(self.pos)
5035 self.operand1.generate_evaluation_code(code)
5036 test_result, uses_temp = self.generate_operand1_test(code)
5037 if self.operator == 'and':
5038 sense = ""
5039 else:
5040 sense = "!"
5041 code.putln(
5042 "if (%s%s) {" % (
5043 sense,
5044 test_result))
5045 if uses_temp:
5046 code.funcstate.release_temp(test_result)
5047 self.operand1.generate_disposal_code(code)
5048 self.operand2.generate_evaluation_code(code)
5049 self.allocate_temp_result(code)
5050 self.operand2.make_owned_reference(code)
5051 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
5052 self.operand2.generate_post_assignment_code(code)
5053 self.operand2.free_temps(code)
5054 code.putln("} else {")
5055 self.operand1.make_owned_reference(code)
5056 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
5057 self.operand1.generate_post_assignment_code(code)
5058 self.operand1.free_temps(code)
5059 code.putln("}")
5061 def generate_operand1_test(self, code):
5062 # Generate code to test the truth of the first operand.
5063 if self.type.is_pyobject:
5064 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
5065 manage_ref=False)
5066 code.putln(
5067 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5068 test_result,
5069 self.operand1.py_result(),
5070 code.error_goto_if_neg(test_result, self.pos)))
5071 else:
5072 test_result = self.operand1.result()
5073 return (test_result, self.type.is_pyobject)
5076 class CondExprNode(ExprNode):
5077 # Short-circuiting conditional expression.
5078 #
5079 # test ExprNode
5080 # true_val ExprNode
5081 # false_val ExprNode
5083 true_val = None
5084 false_val = None
5086 subexprs = ['test', 'true_val', 'false_val']
5088 def type_dependencies(self, env):
5089 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
5091 def infer_type(self, env):
5092 return self.compute_result_type(self.true_val.infer_type(env),
5093 self.false_val.infer_type(env))
5095 def calculate_constant_result(self):
5096 if self.test.constant_result:
5097 self.constant_result = self.true_val.constant_result
5098 else:
5099 self.constant_result = self.false_val.constant_result
5101 def analyse_types(self, env):
5102 self.test.analyse_types(env)
5103 self.test = self.test.coerce_to_boolean(env)
5104 self.true_val.analyse_types(env)
5105 self.false_val.analyse_types(env)
5106 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
5107 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
5108 self.true_val = self.true_val.coerce_to(self.type, env)
5109 self.false_val = self.false_val.coerce_to(self.type, env)
5110 self.is_temp = 1
5111 if self.type == PyrexTypes.error_type:
5112 self.type_error()
5114 def compute_result_type(self, type1, type2):
5115 if type1 == type2:
5116 return type1
5117 elif type1.is_numeric and type2.is_numeric:
5118 return PyrexTypes.widest_numeric_type(type1, type2)
5119 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
5120 return type2
5121 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
5122 return type1
5123 elif type1.is_pyobject or type2.is_pyobject:
5124 return py_object_type
5125 elif type1.assignable_from(type2):
5126 return type1
5127 elif type2.assignable_from(type1):
5128 return type2
5129 else:
5130 return PyrexTypes.error_type
5132 def type_error(self):
5133 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5134 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5135 (self.true_val.type, self.false_val.type))
5136 self.type = PyrexTypes.error_type
5138 def check_const(self):
5139 return (self.test.check_const()
5140 and self.true_val.check_const()
5141 and self.false_val.check_const())
5143 def generate_evaluation_code(self, code):
5144 # Because subexprs may not be evaluated we can use a more optimal
5145 # subexpr allocation strategy than the default, so override evaluation_code.
5147 code.mark_pos(self.pos)
5148 self.allocate_temp_result(code)
5149 self.test.generate_evaluation_code(code)
5150 code.putln("if (%s) {" % self.test.result() )
5151 self.eval_and_get(code, self.true_val)
5152 code.putln("} else {")
5153 self.eval_and_get(code, self.false_val)
5154 code.putln("}")
5155 self.test.generate_disposal_code(code)
5156 self.test.free_temps(code)
5158 def eval_and_get(self, code, expr):
5159 expr.generate_evaluation_code(code)
5160 expr.make_owned_reference(code)
5161 code.putln("%s = %s;" % (self.result(), expr.result()))
5162 expr.generate_post_assignment_code(code)
5163 expr.free_temps(code)
5165 richcmp_constants = {
5166 "<" : "Py_LT",
5167 "<=": "Py_LE",
5168 "==": "Py_EQ",
5169 "!=": "Py_NE",
5170 "<>": "Py_NE",
5171 ">" : "Py_GT",
5172 ">=": "Py_GE",
5173 }
5175 class CmpNode(object):
5176 # Mixin class containing code common to PrimaryCmpNodes
5177 # and CascadedCmpNodes.
5179 def infer_types(self, env):
5180 # TODO: Actually implement this (after merging with -unstable).
5181 return py_object_type
5183 def calculate_cascaded_constant_result(self, operand1_result):
5184 func = compile_time_binary_operators[self.operator]
5185 operand2_result = self.operand2.constant_result
5186 result = func(operand1_result, operand2_result)
5187 if result and self.cascade:
5188 result = result and \
5189 self.cascade.cascaded_compile_time_value(operand2_result)
5190 self.constant_result = result
5192 def cascaded_compile_time_value(self, operand1, denv):
5193 func = get_compile_time_binop(self)
5194 operand2 = self.operand2.compile_time_value(denv)
5195 try:
5196 result = func(operand1, operand2)
5197 except Exception, e:
5198 self.compile_time_value_error(e)
5199 result = None
5200 if result:
5201 cascade = self.cascade
5202 if cascade:
5203 # FIXME: I bet this must call cascaded_compile_time_value()
5204 result = result and cascade.compile_time_value(operand2, denv)
5205 return result
5207 def find_common_int_type(self, env, op, operand1, operand2):
5208 # type1 != type2 and at least one of the types is not a C int
5209 type1 = operand1.type
5210 type2 = operand2.type
5211 type1_can_be_int = False
5212 type2_can_be_int = False
5214 if isinstance(operand1, (StringNode, BytesNode)) \
5215 and operand1.can_coerce_to_char_literal():
5216 type1_can_be_int = True
5217 if isinstance(operand2, (StringNode, BytesNode)) \
5218 and operand2.can_coerce_to_char_literal():
5219 type2_can_be_int = True
5221 if type1.is_int:
5222 if type2_can_be_int:
5223 return type1
5224 elif type2.is_int:
5225 if type1_can_be_int:
5226 return type2
5227 elif type1_can_be_int:
5228 if type2_can_be_int:
5229 return PyrexTypes.c_uchar_type
5231 return None
5233 def find_common_type(self, env, op, operand1, common_type=None):
5234 operand2 = self.operand2
5235 type1 = operand1.type
5236 type2 = operand2.type
5238 new_common_type = None
5240 # catch general errors
5241 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
5242 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
5243 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
5244 new_common_type = error_type
5246 # try to use numeric comparisons where possible
5247 elif type1.is_complex or type2.is_complex:
5248 if op not in ('==', '!='):
5249 error(self.pos, "complex types are unordered")
5250 new_common_type = error_type
5251 if type1.is_pyobject:
5252 new_common_type = type1
5253 elif type2.is_pyobject:
5254 new_common_type = type2
5255 else:
5256 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5257 elif type1.is_numeric and type2.is_numeric:
5258 new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
5259 elif common_type is None or not common_type.is_pyobject:
5260 new_common_type = self.find_common_int_type(env, op, operand1, operand2)
5262 if new_common_type is None:
5263 # fall back to generic type compatibility tests
5264 if type1 == type2:
5265 new_common_type = type1
5266 elif type1.is_pyobject or type2.is_pyobject:
5267 if type2.is_numeric or type2.is_string:
5268 if operand2.check_for_coercion_error(type1):
5269 new_common_type = error_type
5270 else:
5271 new_common_type = py_object_type
5272 elif type1.is_numeric or type1.is_string:
5273 if operand1.check_for_coercion_error(type2):
5274 new_common_type = error_type
5275 else:
5276 new_common_type = py_object_type
5277 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2):
5278 new_common_type = py_object_type
5279 else:
5280 # one Python type and one non-Python type, not assignable
5281 self.invalid_types_error(operand1, op, operand2)
5282 new_common_type = error_type
5283 elif type1.assignable_from(type2):
5284 new_common_type = type1
5285 elif type2.assignable_from(type1):
5286 new_common_type = type2
5287 else:
5288 # C types that we couldn't handle up to here are an error
5289 self.invalid_types_error(operand1, op, operand2)
5290 new_common_type = error_type
5292 # recursively merge types
5293 if common_type is None or new_common_type.is_error:
5294 common_type = new_common_type
5295 else:
5296 # we could do a lot better by splitting the comparison
5297 # into a non-Python part and a Python part, but this is
5298 # safer for now
5299 common_type = PyrexTypes.spanning_type(common_type, new_common_type)
5301 if self.cascade:
5302 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
5304 return common_type
5306 def invalid_types_error(self, operand1, op, operand2):
5307 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5308 (op, operand1.type, operand2.type))
5310 def is_python_comparison(self):
5311 return (self.has_python_operands()
5312 or (self.cascade and self.cascade.is_python_comparison())
5313 or self.operator in ('in', 'not_in'))
5315 def coerce_operands_to(self, dst_type, env):
5316 operand2 = self.operand2
5317 if operand2.type != dst_type:
5318 self.operand2 = operand2.coerce_to(dst_type, env)
5319 if self.cascade:
5320 self.cascade.coerce_operands_to(dst_type, env)
5322 def is_python_result(self):
5323 return ((self.has_python_operands() and
5324 self.operator not in ('is', 'is_not', 'in', 'not_in'))
5325 or (self.cascade and self.cascade.is_python_result()))
5327 def generate_operation_code(self, code, result_code,
5328 operand1, op , operand2):
5329 if self.type is PyrexTypes.py_object_type:
5330 coerce_result = "__Pyx_PyBool_FromLong"
5331 else:
5332 coerce_result = ""
5333 if 'not' in op:
5334 negation = "!"
5335 else:
5336 negation = ""
5337 if op == 'in' or op == 'not_in':
5338 code.globalstate.use_utility_code(contians_utility_code)
5339 if self.type is PyrexTypes.py_object_type:
5340 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
5341 if op == 'not_in':
5342 negation = "__Pyx_NegateNonNeg"
5343 if operand2.type is dict_type:
5344 code.globalstate.use_utility_code(
5345 raise_none_iter_error_utility_code)
5346 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5347 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5348 code.error_goto(self.pos))
5349 code.putln("} else {")
5350 method = "PyDict_Contains"
5351 else:
5352 method = "PySequence_Contains"
5353 if self.type is PyrexTypes.py_object_type:
5354 error_clause = code.error_goto_if_null
5355 got_ref = "__Pyx_XGOTREF(%s); " % result_code
5356 else:
5357 error_clause = code.error_goto_if_neg
5358 got_ref = ""
5359 code.putln(
5360 "%s = %s(%s(%s(%s, %s))); %s%s" % (
5361 result_code,
5362 coerce_result,
5363 negation,
5364 method,
5365 operand2.py_result(),
5366 operand1.py_result(),
5367 got_ref,
5368 error_clause(result_code, self.pos)))
5369 if operand2.type is dict_type:
5370 code.putln("}")
5372 elif (operand1.type.is_pyobject
5373 and op not in ('is', 'is_not')):
5374 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5375 result_code,
5376 operand1.py_result(),
5377 operand2.py_result(),
5378 richcmp_constants[op],
5379 code.error_goto_if_null(result_code, self.pos)))
5380 code.put_gotref(result_code)
5381 elif operand1.type.is_complex:
5382 if op == "!=":
5383 negation = "!"
5384 else:
5385 negation = ""
5386 code.putln("%s = %s(%s%s(%s, %s));" % (
5387 result_code,
5388 coerce_result,
5389 negation,
5390 operand1.type.unary_op('eq'),
5391 operand1.result(),
5392 operand2.result()))
5393 else:
5394 type1 = operand1.type
5395 type2 = operand2.type
5396 if (type1.is_extension_type or type2.is_extension_type) \
5397 and not type1.same_as(type2):
5398 common_type = py_object_type
5399 elif type1.is_numeric:
5400 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5401 else:
5402 common_type = type1
5403 code1 = operand1.result_as(common_type)
5404 code2 = operand2.result_as(common_type)
5405 code.putln("%s = %s(%s %s %s);" % (
5406 result_code,
5407 coerce_result,
5408 code1,
5409 self.c_operator(op),
5410 code2))
5412 def c_operator(self, op):
5413 if op == 'is':
5414 return "=="
5415 elif op == 'is_not':
5416 return "!="
5417 else:
5418 return op
5420 contians_utility_code = UtilityCode(
5421 proto="""
5422 static INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
5423 static INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
5424 return unlikely(b < 0) ? NULL : __Pyx_PyBool_FromLong(b);
5425 }
5426 """)
5429 class PrimaryCmpNode(ExprNode, CmpNode):
5430 # Non-cascaded comparison or first comparison of
5431 # a cascaded sequence.
5432 #
5433 # operator string
5434 # operand1 ExprNode
5435 # operand2 ExprNode
5436 # cascade CascadedCmpNode
5438 # We don't use the subexprs mechanism, because
5439 # things here are too complicated for it to handle.
5440 # Instead, we override all the framework methods
5441 # which use it.
5443 child_attrs = ['operand1', 'operand2', 'cascade']
5445 cascade = None
5447 def infer_type(self, env):
5448 # TODO: Actually implement this (after merging with -unstable).
5449 return py_object_type
5451 def type_dependencies(self, env):
5452 return ()
5454 def calculate_constant_result(self):
5455 self.constant_result = self.calculate_cascaded_constant_result(
5456 self.operand1.constant_result)
5458 def compile_time_value(self, denv):
5459 operand1 = self.operand1.compile_time_value(denv)
5460 return self.cascaded_compile_time_value(operand1, denv)
5462 def analyse_types(self, env):
5463 self.operand1.analyse_types(env)
5464 self.operand2.analyse_types(env)
5465 if self.cascade:
5466 self.cascade.analyse_types(env)
5468 if self.operator in ('in', 'not_in'):
5469 common_type = py_object_type
5470 self.is_pycmp = True
5471 else:
5472 common_type = self.find_common_type(env, self.operator, self.operand1)
5473 self.is_pycmp = common_type.is_pyobject
5475 if not common_type.is_error:
5476 if self.operand1.type != common_type:
5477 self.operand1 = self.operand1.coerce_to(common_type, env)
5478 self.coerce_operands_to(common_type, env)
5480 if self.cascade:
5481 self.operand2 = self.operand2.coerce_to_simple(env)
5482 self.cascade.coerce_cascaded_operands_to_temp(env)
5483 if self.is_python_result():
5484 self.type = PyrexTypes.py_object_type
5485 else:
5486 self.type = PyrexTypes.c_bint_type
5487 cdr = self.cascade
5488 while cdr:
5489 cdr.type = self.type
5490 cdr = cdr.cascade
5491 if self.is_pycmp or self.cascade:
5492 self.is_temp = 1
5494 def has_python_operands(self):
5495 return (self.operand1.type.is_pyobject
5496 or self.operand2.type.is_pyobject)
5498 def check_const(self):
5499 if self.cascade:
5500 self.not_const()
5501 return False
5502 else:
5503 return self.operand1.check_const() and self.operand2.check_const()
5505 def calculate_result_code(self):
5506 if self.operand1.type.is_complex:
5507 if self.operator == "!=":
5508 negation = "!"
5509 else:
5510 negation = ""
5511 return "(%s%s(%s, %s))" % (
5512 negation,
5513 self.operand1.type.binary_op('=='),
5514 self.operand1.result(),
5515 self.operand2.result())
5516 else:
5517 return "(%s %s %s)" % (
5518 self.operand1.result(),
5519 self.c_operator(self.operator),
5520 self.operand2.result())
5522 def generate_evaluation_code(self, code):
5523 self.operand1.generate_evaluation_code(code)
5524 self.operand2.generate_evaluation_code(code)
5525 if self.is_temp:
5526 self.allocate_temp_result(code)
5527 self.generate_operation_code(code, self.result(),
5528 self.operand1, self.operator, self.operand2)
5529 if self.cascade:
5530 self.cascade.generate_evaluation_code(code,
5531 self.result(), self.operand2)
5532 self.operand1.generate_disposal_code(code)
5533 self.operand1.free_temps(code)
5534 self.operand2.generate_disposal_code(code)
5535 self.operand2.free_temps(code)
5537 def generate_subexpr_disposal_code(self, code):
5538 # If this is called, it is a non-cascaded cmp,
5539 # so only need to dispose of the two main operands.
5540 self.operand1.generate_disposal_code(code)
5541 self.operand2.generate_disposal_code(code)
5543 def free_subexpr_temps(self, code):
5544 # If this is called, it is a non-cascaded cmp,
5545 # so only need to dispose of the two main operands.
5546 self.operand1.free_temps(code)
5547 self.operand2.free_temps(code)
5549 def annotate(self, code):
5550 self.operand1.annotate(code)
5551 self.operand2.annotate(code)
5552 if self.cascade:
5553 self.cascade.annotate(code)
5556 class CascadedCmpNode(Node, CmpNode):
5557 # A CascadedCmpNode is not a complete expression node. It
5558 # hangs off the side of another comparison node, shares
5559 # its left operand with that node, and shares its result
5560 # with the PrimaryCmpNode at the head of the chain.
5561 #
5562 # operator string
5563 # operand2 ExprNode
5564 # cascade CascadedCmpNode
5566 child_attrs = ['operand2', 'cascade']
5568 cascade = None
5569 constant_result = constant_value_not_set # FIXME: where to calculate this?
5571 def infer_type(self, env):
5572 # TODO: Actually implement this (after merging with -unstable).
5573 return py_object_type
5575 def type_dependencies(self, env):
5576 return ()
5578 def analyse_types(self, env):
5579 self.operand2.analyse_types(env)
5580 if self.cascade:
5581 self.cascade.analyse_types(env)
5583 def has_python_operands(self):
5584 return self.operand2.type.is_pyobject
5586 def coerce_operands_to_pyobjects(self, env):
5587 self.operand2 = self.operand2.coerce_to_pyobject(env)
5588 if self.cascade:
5589 self.cascade.coerce_operands_to_pyobjects(env)
5591 def coerce_cascaded_operands_to_temp(self, env):
5592 if self.cascade:
5593 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5594 self.operand2 = self.operand2.coerce_to_simple(env)
5595 self.cascade.coerce_cascaded_operands_to_temp(env)
5597 def generate_evaluation_code(self, code, result, operand1):
5598 if self.type.is_pyobject:
5599 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5600 code.put_decref(result, self.type)
5601 else:
5602 code.putln("if (%s) {" % result)
5603 self.operand2.generate_evaluation_code(code)
5604 self.generate_operation_code(code, result,
5605 operand1, self.operator, self.operand2)
5606 if self.cascade:
5607 self.cascade.generate_evaluation_code(
5608 code, result, self.operand2)
5609 # Cascaded cmp result is always temp
5610 self.operand2.generate_disposal_code(code)
5611 self.operand2.free_temps(code)
5612 code.putln("}")
5614 def annotate(self, code):
5615 self.operand2.annotate(code)
5616 if self.cascade:
5617 self.cascade.annotate(code)
5620 binop_node_classes = {
5621 "or": BoolBinopNode,
5622 "and": BoolBinopNode,
5623 "|": IntBinopNode,
5624 "^": IntBinopNode,
5625 "&": IntBinopNode,
5626 "<<": IntBinopNode,
5627 ">>": IntBinopNode,
5628 "+": AddNode,
5629 "-": SubNode,
5630 "*": MulNode,
5631 "/": DivNode,
5632 "//": DivNode,
5633 "%": ModNode,
5634 "**": PowNode
5635 }
5637 def binop_node(pos, operator, operand1, operand2):
5638 # Construct binop node of appropriate class for
5639 # given operator.
5640 return binop_node_classes[operator](pos,
5641 operator = operator,
5642 operand1 = operand1,
5643 operand2 = operand2)
5645 #-------------------------------------------------------------------
5646 #
5647 # Coercion nodes
5648 #
5649 # Coercion nodes are special in that they are created during
5650 # the analyse_types phase of parse tree processing.
5651 # Their __init__ methods consequently incorporate some aspects
5652 # of that phase.
5653 #
5654 #-------------------------------------------------------------------
5656 class CoercionNode(ExprNode):
5657 # Abstract base class for coercion nodes.
5658 #
5659 # arg ExprNode node being coerced
5661 subexprs = ['arg']
5662 constant_result = not_a_constant
5664 def __init__(self, arg):
5665 self.pos = arg.pos
5666 self.arg = arg
5667 if debug_coercion:
5668 print("%s Coercing %s" % (self, self.arg))
5670 def calculate_constant_result(self):
5671 # constant folding can break type coercion, so this is disabled
5672 pass
5674 def annotate(self, code):
5675 self.arg.annotate(code)
5676 if self.arg.type != self.type:
5677 file, line, col = self.pos
5678 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5681 class CastNode(CoercionNode):
5682 # Wrap a node in a C type cast.
5684 def __init__(self, arg, new_type):
5685 CoercionNode.__init__(self, arg)
5686 self.type = new_type
5688 def calculate_result_code(self):
5689 return self.arg.result_as(self.type)
5691 def generate_result_code(self, code):
5692 self.arg.generate_result_code(code)
5695 class PyTypeTestNode(CoercionNode):
5696 # This node is used to check that a generic Python
5697 # object is an instance of a particular extension type.
5698 # This node borrows the result of its argument node.
5700 def __init__(self, arg, dst_type, env, notnone=False):
5701 # The arg is know to be a Python object, and
5702 # the dst_type is known to be an extension type.
5703 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5704 CoercionNode.__init__(self, arg)
5705 self.type = dst_type
5706 self.result_ctype = arg.ctype()
5707 self.notnone = notnone
5709 nogil_check = Node.gil_error
5710 gil_message = "Python type test"
5712 def analyse_types(self, env):
5713 pass
5715 def result_in_temp(self):
5716 return self.arg.result_in_temp()
5718 def is_ephemeral(self):
5719 return self.arg.is_ephemeral()
5721 def calculate_constant_result(self):
5722 # FIXME
5723 pass
5725 def calculate_result_code(self):
5726 return self.arg.result()
5728 def generate_result_code(self, code):
5729 if self.type.typeobj_is_available():
5730 if not self.type.is_builtin_type:
5731 code.globalstate.use_utility_code(type_test_utility_code)
5732 code.putln(
5733 "if (!(%s)) %s" % (
5734 self.type.type_test_code(self.arg.py_result(), self.notnone),
5735 code.error_goto(self.pos)))
5736 else:
5737 error(self.pos, "Cannot test type of extern C class "
5738 "without type object name specification")
5740 def generate_post_assignment_code(self, code):
5741 self.arg.generate_post_assignment_code(code)
5743 def free_temps(self, code):
5744 self.arg.free_temps(code)
5747 class NoneCheckNode(CoercionNode):
5748 # This node is used to check that a Python object is not None and
5749 # raises an appropriate exception (as specified by the creating
5750 # transform).
5752 def __init__(self, arg, exception_type_cname, exception_message):
5753 CoercionNode.__init__(self, arg)
5754 self.type = arg.type
5755 self.result_ctype = arg.ctype()
5756 self.exception_type_cname = exception_type_cname
5757 self.exception_message = exception_message
5759 def analyse_types(self, env):
5760 pass
5762 def result_in_temp(self):
5763 return self.arg.result_in_temp()
5765 def calculate_result_code(self):
5766 return self.arg.result()
5768 def generate_result_code(self, code):
5769 code.putln(
5770 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5771 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5772 self.exception_type_cname,
5773 StringEncoding.escape_byte_string(
5774 self.exception_message.encode('UTF-8')),
5775 code.error_goto(self.pos)))
5776 code.putln("}")
5778 def generate_post_assignment_code(self, code):
5779 self.arg.generate_post_assignment_code(code)
5781 def free_temps(self, code):
5782 self.arg.free_temps(code)
5785 class CoerceToPyTypeNode(CoercionNode):
5786 # This node is used to convert a C data type
5787 # to a Python object.
5789 type = py_object_type
5790 is_temp = 1
5792 def __init__(self, arg, env):
5793 CoercionNode.__init__(self, arg)
5794 if not arg.type.create_to_py_utility_code(env):
5795 error(arg.pos,
5796 "Cannot convert '%s' to Python object" % arg.type)
5798 gil_message = "Converting to Python object"
5800 def coerce_to_boolean(self, env):
5801 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5803 def coerce_to_integer(self, env):
5804 # If not already some C integer type, coerce to longint.
5805 if self.arg.type.is_int:
5806 return self.arg
5807 else:
5808 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5810 def analyse_types(self, env):
5811 # The arg is always already analysed
5812 pass
5814 def generate_result_code(self, code):
5815 function = self.arg.type.to_py_function
5816 code.putln('%s = %s(%s); %s' % (
5817 self.result(),
5818 function,
5819 self.arg.result(),
5820 code.error_goto_if_null(self.result(), self.pos)))
5821 code.put_gotref(self.py_result())
5824 class CoerceFromPyTypeNode(CoercionNode):
5825 # This node is used to convert a Python object
5826 # to a C data type.
5828 def __init__(self, result_type, arg, env):
5829 CoercionNode.__init__(self, arg)
5830 self.type = result_type
5831 self.is_temp = 1
5832 if not result_type.create_from_py_utility_code(env):
5833 error(arg.pos,
5834 "Cannot convert Python object to '%s'" % result_type)
5835 if self.type.is_string and self.arg.is_ephemeral():
5836 error(arg.pos,
5837 "Obtaining char * from temporary Python value")
5839 def analyse_types(self, env):
5840 # The arg is always already analysed
5841 pass
5843 def generate_result_code(self, code):
5844 function = self.type.from_py_function
5845 operand = self.arg.py_result()
5846 rhs = "%s(%s)" % (function, operand)
5847 if self.type.is_enum:
5848 rhs = typecast(self.type, c_long_type, rhs)
5849 code.putln('%s = %s; %s' % (
5850 self.result(),
5851 rhs,
5852 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5853 if self.type.is_pyobject:
5854 code.put_gotref(self.py_result())
5857 class CoerceToBooleanNode(CoercionNode):
5858 # This node is used when a result needs to be used
5859 # in a boolean context.
5861 type = PyrexTypes.c_bint_type
5863 def __init__(self, arg, env):
5864 CoercionNode.__init__(self, arg)
5865 if arg.type.is_pyobject:
5866 self.is_temp = 1
5868 def nogil_check(self, env):
5869 if self.arg.type.is_pyobject:
5870 self.gil_error()
5872 gil_message = "Truth-testing Python object"
5874 def check_const(self):
5875 if self.is_temp:
5876 self.not_const()
5877 return False
5878 return self.arg.check_const()
5880 def calculate_result_code(self):
5881 return "(%s != 0)" % self.arg.result()
5883 def generate_result_code(self, code):
5884 if self.arg.type.is_pyobject:
5885 code.putln(
5886 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5887 self.result(),
5888 self.arg.py_result(),
5889 code.error_goto_if_neg(self.result(), self.pos)))
5891 class CoerceToComplexNode(CoercionNode):
5893 def __init__(self, arg, dst_type, env):
5894 if arg.type.is_complex:
5895 arg = arg.coerce_to_simple(env)
5896 self.type = dst_type
5897 CoercionNode.__init__(self, arg)
5898 dst_type.create_declaration_utility_code(env)
5900 def calculate_result_code(self):
5901 if self.arg.type.is_complex:
5902 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
5903 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
5904 else:
5905 real_part = self.arg.result()
5906 imag_part = "0"
5907 return "%s(%s, %s)" % (
5908 self.type.from_parts,
5909 real_part,
5910 imag_part)
5912 def generate_result_code(self, code):
5913 pass
5915 class CoerceToTempNode(CoercionNode):
5916 # This node is used to force the result of another node
5917 # to be stored in a temporary. It is only used if the
5918 # argument node's result is not already in a temporary.
5920 def __init__(self, arg, env):
5921 CoercionNode.__init__(self, arg)
5922 self.type = self.arg.type
5923 self.is_temp = 1
5924 if self.type.is_pyobject:
5925 self.result_ctype = py_object_type
5927 gil_message = "Creating temporary Python reference"
5929 def analyse_types(self, env):
5930 # The arg is always already analysed
5931 pass
5933 def coerce_to_boolean(self, env):
5934 self.arg = self.arg.coerce_to_boolean(env)
5935 self.type = self.arg.type
5936 self.result_ctype = self.type
5937 return self
5939 def generate_result_code(self, code):
5940 #self.arg.generate_evaluation_code(code) # Already done
5941 # by generic generate_subexpr_evaluation_code!
5942 code.putln("%s = %s;" % (
5943 self.result(), self.arg.result_as(self.ctype())))
5944 if self.type.is_pyobject and self.use_managed_ref:
5945 code.put_incref(self.result(), self.ctype())
5948 class CloneNode(CoercionNode):
5949 # This node is employed when the result of another node needs
5950 # to be used multiple times. The argument node's result must
5951 # be in a temporary. This node "borrows" the result from the
5952 # argument node, and does not generate any evaluation or
5953 # disposal code for it. The original owner of the argument
5954 # node is responsible for doing those things.
5956 subexprs = [] # Arg is not considered a subexpr
5957 nogil_check = None
5959 def __init__(self, arg):
5960 CoercionNode.__init__(self, arg)
5961 if hasattr(arg, 'type'):
5962 self.type = arg.type
5963 self.result_ctype = arg.result_ctype
5964 if hasattr(arg, 'entry'):
5965 self.entry = arg.entry
5967 def result(self):
5968 return self.arg.result()
5970 def type_dependencies(self, env):
5971 return self.arg.type_dependencies(env)
5973 def infer_type(self, env):
5974 return self.arg.infer_type(env)
5976 def analyse_types(self, env):
5977 self.type = self.arg.type
5978 self.result_ctype = self.arg.result_ctype
5979 self.is_temp = 1
5980 if hasattr(self.arg, 'entry'):
5981 self.entry = self.arg.entry
5983 def generate_evaluation_code(self, code):
5984 pass
5986 def generate_result_code(self, code):
5987 pass
5989 def generate_disposal_code(self, code):
5990 pass
5992 def free_temps(self, code):
5993 pass
5996 class ModuleRefNode(ExprNode):
5997 # Simple returns the module object
5999 type = py_object_type
6000 is_temp = False
6001 subexprs = []
6003 def analyse_types(self, env):
6004 pass
6006 def calculate_result_code(self):
6007 return Naming.module_cname
6009 def generate_result_code(self, code):
6010 pass
6012 class DocstringRefNode(ExprNode):
6013 # Extracts the docstring of the body element
6015 subexprs = ['body']
6016 type = py_object_type
6017 is_temp = True
6019 def __init__(self, pos, body):
6020 ExprNode.__init__(self, pos)
6021 assert body.type.is_pyobject
6022 self.body = body
6024 def analyse_types(self, env):
6025 pass
6027 def generate_result_code(self, code):
6028 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
6029 (self.result(), self.body.result()))
6030 code.put_gotref(self.result())
6034 #------------------------------------------------------------------------------------
6035 #
6036 # Runtime support code
6037 #
6038 #------------------------------------------------------------------------------------
6040 get_name_interned_utility_code = UtilityCode(
6041 proto = """
6042 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
6043 """,
6044 impl = """
6045 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
6046 PyObject *result;
6047 result = PyObject_GetAttr(dict, name);
6048 if (!result)
6049 PyErr_SetObject(PyExc_NameError, name);
6050 return result;
6051 }
6052 """)
6054 #------------------------------------------------------------------------------------
6056 import_utility_code = UtilityCode(
6057 proto = """
6058 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
6059 """,
6060 impl = """
6061 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
6062 PyObject *__import__ = 0;
6063 PyObject *empty_list = 0;
6064 PyObject *module = 0;
6065 PyObject *global_dict = 0;
6066 PyObject *empty_dict = 0;
6067 PyObject *list;
6068 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
6069 if (!__import__)
6070 goto bad;
6071 if (from_list)
6072 list = from_list;
6073 else {
6074 empty_list = PyList_New(0);
6075 if (!empty_list)
6076 goto bad;
6077 list = empty_list;
6078 }
6079 global_dict = PyModule_GetDict(%(GLOBALS)s);
6080 if (!global_dict)
6081 goto bad;
6082 empty_dict = PyDict_New();
6083 if (!empty_dict)
6084 goto bad;
6085 module = PyObject_CallFunctionObjArgs(__import__,
6086 name, global_dict, empty_dict, list, NULL);
6087 bad:
6088 Py_XDECREF(empty_list);
6089 Py_XDECREF(__import__);
6090 Py_XDECREF(empty_dict);
6091 return module;
6092 }
6093 """ % {
6094 "BUILTINS": Naming.builtins_cname,
6095 "GLOBALS": Naming.module_cname,
6096 })
6098 #------------------------------------------------------------------------------------
6100 get_exception_utility_code = UtilityCode(
6101 proto = """
6102 static PyObject *__Pyx_GetExcValue(void); /*proto*/
6103 """,
6104 impl = """
6105 static PyObject *__Pyx_GetExcValue(void) {
6106 PyObject *type = 0, *value = 0, *tb = 0;
6107 PyObject *tmp_type, *tmp_value, *tmp_tb;
6108 PyObject *result = 0;
6109 PyThreadState *tstate = PyThreadState_Get();
6110 PyErr_Fetch(&type, &value, &tb);
6111 PyErr_NormalizeException(&type, &value, &tb);
6112 if (PyErr_Occurred())
6113 goto bad;
6114 if (!value) {
6115 value = Py_None;
6116 Py_INCREF(value);
6117 }
6118 tmp_type = tstate->exc_type;
6119 tmp_value = tstate->exc_value;
6120 tmp_tb = tstate->exc_traceback;
6121 tstate->exc_type = type;
6122 tstate->exc_value = value;
6123 tstate->exc_traceback = tb;
6124 /* Make sure tstate is in a consistent state when we XDECREF
6125 these objects (XDECREF may run arbitrary code). */
6126 Py_XDECREF(tmp_type);
6127 Py_XDECREF(tmp_value);
6128 Py_XDECREF(tmp_tb);
6129 result = value;
6130 Py_XINCREF(result);
6131 type = 0;
6132 value = 0;
6133 tb = 0;
6134 bad:
6135 Py_XDECREF(type);
6136 Py_XDECREF(value);
6137 Py_XDECREF(tb);
6138 return result;
6139 }
6140 """)
6142 #------------------------------------------------------------------------------------
6144 type_test_utility_code = UtilityCode(
6145 proto = """
6146 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
6147 """,
6148 impl = """
6149 static INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
6150 if (unlikely(!type)) {
6151 PyErr_Format(PyExc_SystemError, "Missing type object");
6152 return 0;
6153 }
6154 if (likely(PyObject_TypeCheck(obj, type)))
6155 return 1;
6156 PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
6157 Py_TYPE(obj)->tp_name, type->tp_name);
6158 return 0;
6159 }
6160 """)
6162 #------------------------------------------------------------------------------------
6164 create_class_utility_code = UtilityCode(
6165 proto = """
6166 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
6167 """,
6168 impl = """
6169 static PyObject *__Pyx_CreateClass(
6170 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
6171 {
6172 PyObject *py_modname;
6173 PyObject *result = 0;
6175 #if PY_MAJOR_VERSION < 3
6176 py_modname = PyString_FromString(modname);
6177 #else
6178 py_modname = PyUnicode_FromString(modname);
6179 #endif
6180 if (!py_modname)
6181 goto bad;
6182 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
6183 goto bad;
6184 #if PY_MAJOR_VERSION < 3
6185 result = PyClass_New(bases, dict, name);
6186 #else
6187 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
6188 #endif
6189 bad:
6190 Py_XDECREF(py_modname);
6191 return result;
6192 }
6193 """)
6195 #------------------------------------------------------------------------------------
6197 cpp_exception_utility_code = UtilityCode(
6198 proto = """
6199 #ifndef __Pyx_CppExn2PyErr
6200 static void __Pyx_CppExn2PyErr() {
6201 try {
6202 if (PyErr_Occurred())
6203 ; // let the latest Python exn pass through and ignore the current one
6204 else
6205 throw;
6206 } catch (const std::out_of_range& exn) {
6207 // catch out_of_range explicitly so the proper Python exn may be raised
6208 PyErr_SetString(PyExc_IndexError, exn.what());
6209 } catch (const std::exception& exn) {
6210 PyErr_SetString(PyExc_RuntimeError, exn.what());
6211 }
6212 catch (...)
6213 {
6214 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6215 }
6216 }
6217 #endif
6218 """,
6219 impl = ""
6220 )
6222 #------------------------------------------------------------------------------------
6224 # If the is_unsigned flag is set, we need to do some extra work to make
6225 # sure the index doesn't become negative.
6227 getitem_int_utility_code = UtilityCode(
6228 proto = """
6230 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6231 PyObject *r;
6232 if (!j) return NULL;
6233 r = PyObject_GetItem(o, j);
6234 Py_DECREF(j);
6235 return r;
6236 }
6238 """ + ''.join([
6239 """
6240 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6241 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6242 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6244 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6245 if (likely(o != Py_None)) {
6246 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6247 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6248 Py_INCREF(r);
6249 return r;
6250 }
6251 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6252 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6253 Py_INCREF(r);
6254 return r;
6255 }
6256 }
6257 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6258 }
6259 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6260 ]) + """
6262 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6263 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6264 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6266 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6267 PyObject *r;
6268 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6269 r = PyList_GET_ITEM(o, i);
6270 Py_INCREF(r);
6271 }
6272 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6273 r = PyTuple_GET_ITEM(o, i);
6274 Py_INCREF(r);
6275 }
6276 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6277 r = PySequence_GetItem(o, i);
6278 }
6279 else {
6280 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6281 }
6282 return r;
6283 }
6284 """,
6285 impl = """
6286 """)
6290 #------------------------------------------------------------------------------------
6292 setitem_int_utility_code = UtilityCode(
6293 proto = """
6294 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6295 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6296 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6298 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6299 int r;
6300 if (!j) return -1;
6301 r = PyObject_SetItem(o, j, v);
6302 Py_DECREF(j);
6303 return r;
6304 }
6306 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6307 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6308 Py_INCREF(v);
6309 Py_DECREF(PyList_GET_ITEM(o, i));
6310 PyList_SET_ITEM(o, i, v);
6311 return 1;
6312 }
6313 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6314 return PySequence_SetItem(o, i, v);
6315 else {
6316 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6317 return __Pyx_SetItemInt_Generic(o, j, v);
6318 }
6319 }
6320 """,
6321 impl = """
6322 """)
6324 #------------------------------------------------------------------------------------
6326 delitem_int_utility_code = UtilityCode(
6327 proto = """
6328 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6329 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6330 __Pyx_DelItem_Generic(o, to_py_func(i)))
6332 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6333 int r;
6334 if (!j) return -1;
6335 r = PyObject_DelItem(o, j);
6336 Py_DECREF(j);
6337 return r;
6338 }
6340 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6341 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6342 return PySequence_DelItem(o, i);
6343 else {
6344 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6345 return __Pyx_DelItem_Generic(o, j);
6346 }
6347 }
6348 """,
6349 impl = """
6350 """)
6352 #------------------------------------------------------------------------------------
6354 raise_noneattr_error_utility_code = UtilityCode(
6355 proto = """
6356 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6357 """,
6358 impl = '''
6359 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6360 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6361 }
6362 ''')
6364 raise_noneindex_error_utility_code = UtilityCode(
6365 proto = """
6366 static INLINE void __Pyx_RaiseNoneIndexingError(void);
6367 """,
6368 impl = '''
6369 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
6370 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6371 }
6372 ''')
6374 raise_none_iter_error_utility_code = UtilityCode(
6375 proto = """
6376 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
6377 """,
6378 impl = '''
6379 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6380 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6381 }
6382 ''')
6384 raise_too_many_values_to_unpack = UtilityCode(
6385 proto = """
6386 static INLINE void __Pyx_RaiseTooManyValuesError(void);
6387 """,
6388 impl = '''
6389 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
6390 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6391 }
6392 ''')
6394 raise_need_more_values_to_unpack = UtilityCode(
6395 proto = """
6396 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6397 """,
6398 impl = '''
6399 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6400 PyErr_Format(PyExc_ValueError,
6401 #if PY_VERSION_HEX < 0x02050000
6402 "need more than %d value%s to unpack", (int)index,
6403 #else
6404 "need more than %zd value%s to unpack", index,
6405 #endif
6406 (index == 1) ? "" : "s");
6407 }
6408 ''')
6410 #------------------------------------------------------------------------------------
6412 tuple_unpacking_error_code = UtilityCode(
6413 proto = """
6414 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6415 """,
6416 impl = """
6417 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6418 if (t == Py_None) {
6419 __Pyx_RaiseNoneNotIterableError();
6420 } else if (PyTuple_GET_SIZE(t) < index) {
6421 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6422 } else {
6423 __Pyx_RaiseTooManyValuesError();
6424 }
6425 }
6426 """,
6427 requires = [raise_none_iter_error_utility_code,
6428 raise_need_more_values_to_unpack,
6429 raise_too_many_values_to_unpack]
6430 )
6432 unpacking_utility_code = UtilityCode(
6433 proto = """
6434 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6435 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6436 """,
6437 impl = """
6438 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6439 PyObject *item;
6440 if (!(item = PyIter_Next(iter))) {
6441 if (!PyErr_Occurred()) {
6442 __Pyx_RaiseNeedMoreValuesError(index);
6443 }
6444 }
6445 return item;
6446 }
6448 static int __Pyx_EndUnpack(PyObject *iter) {
6449 PyObject *item;
6450 if ((item = PyIter_Next(iter))) {
6451 Py_DECREF(item);
6452 __Pyx_RaiseTooManyValuesError();
6453 return -1;
6454 }
6455 else if (!PyErr_Occurred())
6456 return 0;
6457 else
6458 return -1;
6459 }
6460 """,
6461 requires = [raise_need_more_values_to_unpack,
6462 raise_too_many_values_to_unpack]
6463 )
6466 #------------------------------------------------------------------------------------
6468 int_pow_utility_code = UtilityCode(
6469 proto="""
6470 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6471 """,
6472 impl="""
6473 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6474 %(type)s t = b;
6475 switch (e) {
6476 case 3:
6477 t *= b;
6478 case 2:
6479 t *= b;
6480 case 1:
6481 return t;
6482 case 0:
6483 return 1;
6484 }
6485 if (unlikely(e<0)) return 0;
6486 t = 1;
6487 while (likely(e)) {
6488 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6489 b *= b;
6490 e >>= 1;
6491 }
6492 return t;
6493 }
6494 """)
6496 # ------------------------------ Division ------------------------------------
6498 div_int_utility_code = UtilityCode(
6499 proto="""
6500 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6501 """,
6502 impl="""
6503 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6504 %(type)s q = a / b;
6505 %(type)s r = a - q*b;
6506 q -= ((r != 0) & ((r ^ b) < 0));
6507 return q;
6508 }
6509 """)
6511 mod_int_utility_code = UtilityCode(
6512 proto="""
6513 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6514 """,
6515 impl="""
6516 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6517 %(type)s r = a %% b;
6518 r += ((r != 0) & ((r ^ b) < 0)) * b;
6519 return r;
6520 }
6521 """)
6523 mod_float_utility_code = UtilityCode(
6524 proto="""
6525 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6526 """,
6527 impl="""
6528 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6529 %(type)s r = fmod%(math_h_modifier)s(a, b);
6530 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6531 return r;
6532 }
6533 """)
6535 cdivision_warning_utility_code = UtilityCode(
6536 proto="""
6537 static int __Pyx_cdivision_warning(void); /* proto */
6538 """,
6539 impl="""
6540 static int __Pyx_cdivision_warning(void) {
6541 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6542 "division with oppositely signed operands, C and Python semantics differ",
6543 %(FILENAME)s,
6544 %(LINENO)s,
6545 __Pyx_MODULE_NAME,
6546 NULL);
6547 }
6548 """ % {
6549 'FILENAME': Naming.filename_cname,
6550 'LINENO': Naming.lineno_cname,
6551 })
6553 # from intobject.c
6554 division_overflow_test_code = UtilityCode(
6555 proto="""
6556 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6557 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6558 """)
