Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 1376:e490ccfecad0
handle value coercion correctly in dict iteration
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Tue Nov 25 18:24:52 2008 +0100 (3 years ago) |
| parents | c1d296417c38 |
| children | 55b1d1027506 |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
6 from string import join
8 from Errors import error, warning, InternalError
9 from Errors import hold_errors, release_errors, held_errors, report_error
10 from Cython.Utils import UtilityCode
11 import StringEncoding
12 import Naming
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
16 from Builtin import list_type, tuple_type, dict_type, unicode_type
17 import Symtab
18 import Options
19 from Annotate import AnnotationItem
21 from Cython.Debugging import print_call_chain
22 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
23 debug_coercion
26 class ExprNode(Node):
27 # subexprs [string] Class var holding names of subexpr node attrs
28 # type PyrexType Type of the result
29 # result_code string Code fragment
30 # result_ctype string C type of result_code if different from type
31 # is_temp boolean Result is in a temporary variable
32 # is_sequence_constructor
33 # boolean Is a list or tuple constructor expression
34 # saved_subexpr_nodes
35 # [ExprNode or [ExprNode or None] or None]
36 # Cached result of subexpr_nodes()
38 result_ctype = None
39 type = None
41 # The Analyse Expressions phase for expressions is split
42 # into two sub-phases:
43 #
44 # Analyse Types
45 # Determines the result type of the expression based
46 # on the types of its sub-expressions, and inserts
47 # coercion nodes into the expression tree where needed.
48 # Marks nodes which will need to have temporary variables
49 # allocated.
50 #
51 # Allocate Temps
52 # Allocates temporary variables where needed, and fills
53 # in the result_code field of each node.
54 #
55 # ExprNode provides some convenience routines which
56 # perform both of the above phases. These should only
57 # be called from statement nodes, and only when no
58 # coercion nodes need to be added around the expression
59 # being analysed. In that case, the above two phases
60 # should be invoked separately.
61 #
62 # Framework code in ExprNode provides much of the common
63 # processing for the various phases. It makes use of the
64 # 'subexprs' class attribute of ExprNodes, which should
65 # contain a list of the names of attributes which can
66 # hold sub-nodes or sequences of sub-nodes.
67 #
68 # The framework makes use of a number of abstract methods.
69 # Their responsibilities are as follows.
70 #
71 # Declaration Analysis phase
72 #
73 # analyse_target_declaration
74 # Called during the Analyse Declarations phase to analyse
75 # the LHS of an assignment or argument of a del statement.
76 # Nodes which cannot be the LHS of an assignment need not
77 # implement it.
78 #
79 # Expression Analysis phase
80 #
81 # analyse_types
82 # - Call analyse_types on all sub-expressions.
83 # - Check operand types, and wrap coercion nodes around
84 # sub-expressions where needed.
85 # - Set the type of this node.
86 # - If a temporary variable will be required for the
87 # result, set the is_temp flag of this node.
88 #
89 # analyse_target_types
90 # Called during the Analyse Types phase to analyse
91 # the LHS of an assignment or argument of a del
92 # statement. Similar responsibilities to analyse_types.
93 #
94 # allocate_temps
95 # - Call allocate_temps for all sub-nodes.
96 # - Call allocate_temp for this node.
97 # - If a temporary was allocated, call release_temp on
98 # all sub-expressions.
99 #
100 # allocate_target_temps
101 # - Call allocate_temps on sub-nodes and allocate any other
102 # temps used during assignment.
103 # - Fill in result_code with a C lvalue if needed.
104 # - If a rhs node is supplied, call release_temp on it.
105 # - Call release_temp on sub-nodes and release any other
106 # temps used during assignment.
107 #
108 # target_code
109 # Called by the default implementation of allocate_target_temps.
110 # Should return a C lvalue for assigning to the node. The default
111 # implementation calls calculate_result_code.
112 #
113 # check_const
114 # - Check that this node and its subnodes form a
115 # legal constant expression. If so, do nothing,
116 # otherwise call not_const.
117 #
118 # The default implementation of check_const
119 # assumes that the expression is not constant.
120 #
121 # check_const_addr
122 # - Same as check_const, except check that the
123 # expression is a C lvalue whose address is
124 # constant. Otherwise, call addr_not_const.
125 #
126 # The default implementation of calc_const_addr
127 # assumes that the expression is not a constant
128 # lvalue.
129 #
130 # Code Generation phase
131 #
132 # generate_evaluation_code
133 # - Call generate_evaluation_code for sub-expressions.
134 # - Perform the functions of generate_result_code
135 # (see below).
136 # - If result is temporary, call generate_disposal_code
137 # on all sub-expressions.
138 #
139 # A default implementation of generate_evaluation_code
140 # is provided which uses the following abstract methods:
141 #
142 # generate_result_code
143 # - Generate any C statements necessary to calculate
144 # the result of this node from the results of its
145 # sub-expressions.
146 #
147 # calculate_result_code
148 # - Should return a C code fragment evaluating to the
149 # result. This is only called when the result is not
150 # a temporary.
151 #
152 # generate_assignment_code
153 # Called on the LHS of an assignment.
154 # - Call generate_evaluation_code for sub-expressions.
155 # - Generate code to perform the assignment.
156 # - If the assignment absorbed a reference, call
157 # generate_post_assignment_code on the RHS,
158 # otherwise call generate_disposal_code on it.
159 #
160 # generate_deletion_code
161 # Called on an argument of a del statement.
162 # - Call generate_evaluation_code for sub-expressions.
163 # - Generate code to perform the deletion.
164 # - Call generate_disposal_code on all sub-expressions.
165 #
166 #
168 is_sequence_constructor = 0
169 is_attribute = 0
171 saved_subexpr_nodes = None
172 is_temp = 0
173 is_target = 0
175 def get_child_attrs(self):
176 return self.subexprs
177 child_attrs = property(fget=get_child_attrs)
179 def not_implemented(self, method_name):
180 print_call_chain(method_name, "not implemented") ###
181 raise InternalError(
182 "%s.%s not implemented" %
183 (self.__class__.__name__, method_name))
185 def is_lvalue(self):
186 return 0
188 def is_ephemeral(self):
189 # An ephemeral node is one whose result is in
190 # a Python temporary and we suspect there are no
191 # other references to it. Certain operations are
192 # disallowed on such values, since they are
193 # likely to result in a dangling pointer.
194 return self.type.is_pyobject and self.is_temp
196 def subexpr_nodes(self):
197 # Extract a list of subexpression nodes based
198 # on the contents of the subexprs class attribute.
199 if self.saved_subexpr_nodes is None:
200 nodes = []
201 for name in self.subexprs:
202 item = getattr(self, name)
203 if item:
204 if isinstance(item, ExprNode):
205 nodes.append(item)
206 else:
207 nodes.extend(item)
208 self.saved_subexpr_nodes = nodes
209 return self.saved_subexpr_nodes
211 def result(self):
212 if not self.is_temp or self.is_target:
213 return self.calculate_result_code()
214 else: # i.e. self.is_temp:
215 return self.result_code
217 def result_as(self, type = None):
218 # Return the result code cast to the specified C type.
219 return typecast(type, self.ctype(), self.result())
221 def py_result(self):
222 # Return the result code cast to PyObject *.
223 return self.result_as(py_object_type)
225 def ctype(self):
226 # Return the native C type of the result (i.e. the
227 # C type of the result_code expression).
228 return self.result_ctype or self.type
230 def compile_time_value(self, denv):
231 # Return value of compile-time expression, or report error.
232 error(self.pos, "Invalid compile-time expression")
234 def compile_time_value_error(self, e):
235 error(self.pos, "Error in compile-time expression: %s: %s" % (
236 e.__class__.__name__, e))
238 # ------------- Declaration Analysis ----------------
240 def analyse_target_declaration(self, env):
241 error(self.pos, "Cannot assign to or delete this")
243 # ------------- Expression Analysis ----------------
245 def analyse_const_expression(self, env):
246 # Called during the analyse_declarations phase of a
247 # constant expression. Analyses the expression's type,
248 # checks whether it is a legal const expression,
249 # and determines its value.
250 self.analyse_types(env)
251 self.allocate_temps(env)
252 self.check_const()
254 def analyse_expressions(self, env):
255 # Convenience routine performing both the Type
256 # Analysis and Temp Allocation phases for a whole
257 # expression.
258 self.analyse_types(env)
259 self.allocate_temps(env)
261 def analyse_target_expression(self, env, rhs):
262 # Convenience routine performing both the Type
263 # Analysis and Temp Allocation phases for the LHS of
264 # an assignment.
265 self.analyse_target_types(env)
266 self.allocate_target_temps(env, rhs)
268 def analyse_boolean_expression(self, env):
269 # Analyse expression and coerce to a boolean.
270 self.analyse_types(env)
271 bool = self.coerce_to_boolean(env)
272 bool.allocate_temps(env)
273 return bool
275 def analyse_temp_boolean_expression(self, env):
276 # Analyse boolean expression and coerce result into
277 # a temporary. This is used when a branch is to be
278 # performed on the result and we won't have an
279 # opportunity to ensure disposal code is executed
280 # afterwards. By forcing the result into a temporary,
281 # we ensure that all disposal has been done by the
282 # time we get the result.
283 self.analyse_types(env)
284 bool = self.coerce_to_boolean(env)
285 temp_bool = bool.coerce_to_temp(env)
286 temp_bool.allocate_temps(env)
287 return temp_bool
289 # --------------- Type Analysis ------------------
291 def analyse_as_module(self, env):
292 # If this node can be interpreted as a reference to a
293 # cimported module, return its scope, else None.
294 return None
296 def analyse_as_type(self, env):
297 # If this node can be interpreted as a reference to a
298 # type, return that type, else None.
299 return None
301 def analyse_as_extension_type(self, env):
302 # If this node can be interpreted as a reference to an
303 # extension type, return its type, else None.
304 return None
306 def analyse_types(self, env):
307 self.not_implemented("analyse_types")
309 def analyse_target_types(self, env):
310 self.analyse_types(env)
312 def gil_assignment_check(self, env):
313 if env.nogil and self.type.is_pyobject:
314 error(self.pos, "Assignment of Python object not allowed without gil")
316 def check_const(self):
317 self.not_const()
319 def not_const(self):
320 error(self.pos, "Not allowed in a constant expression")
322 def check_const_addr(self):
323 self.addr_not_const()
325 def addr_not_const(self):
326 error(self.pos, "Address is not constant")
328 def gil_check(self, env):
329 if env.nogil and self.type.is_pyobject:
330 self.gil_error()
332 # ----------------- Result Allocation -----------------
334 def result_in_temp(self):
335 # Return true if result is in a temporary owned by
336 # this node or one of its subexpressions. Overridden
337 # by certain nodes which can share the result of
338 # a subnode.
339 return self.is_temp
341 def allocate_target_temps(self, env, rhs):
342 # Perform temp allocation for the LHS of an assignment.
343 if debug_temp_alloc:
344 print("%s Allocating target temps" % self)
345 self.allocate_subexpr_temps(env)
346 self.is_target = True
347 if rhs:
348 rhs.release_temp(env)
349 self.release_subexpr_temps(env)
351 def allocate_temps(self, env, result = None):
352 # Allocate temporary variables for this node and
353 # all its sub-expressions. If a result is specified,
354 # this must be a temp node and the specified variable
355 # is used as the result instead of allocating a new
356 # one.
357 if debug_temp_alloc:
358 print("%s Allocating temps" % self)
359 self.allocate_subexpr_temps(env)
360 self.allocate_temp(env, result)
361 if self.is_temp:
362 self.release_subexpr_temps(env)
364 def allocate_subexpr_temps(self, env):
365 # Allocate temporary variables for all sub-expressions
366 # of this node.
367 if debug_temp_alloc:
368 print("%s Allocating temps for: %s" % (self, self.subexprs))
369 for node in self.subexpr_nodes():
370 if node:
371 if debug_temp_alloc:
372 print("%s Allocating temps for %s" % (self, node))
373 node.allocate_temps(env)
375 def allocate_temp(self, env, result = None):
376 # If this node requires a temporary variable for its
377 # result, allocate one, otherwise set the result to
378 # a C code fragment. If a result is specified,
379 # this must be a temp node and the specified variable
380 # is used as the result instead of allocating a new
381 # one.
382 if debug_temp_alloc:
383 print("%s Allocating temp" % self)
384 if result:
385 if not self.is_temp:
386 raise InternalError("Result forced on non-temp node")
387 self.result_code = result
388 elif self.is_temp:
389 type = self.type
390 if not type.is_void:
391 if type.is_pyobject:
392 type = PyrexTypes.py_object_type
393 self.result_code = env.allocate_temp(type)
394 else:
395 self.result_code = None
396 if debug_temp_alloc:
397 print("%s Allocated result %s" % (self, self.result_code))
399 def target_code(self):
400 # Return code fragment for use as LHS of a C assignment.
401 return self.calculate_result_code()
403 def calculate_result_code(self):
404 self.not_implemented("calculate_result_code")
406 # def release_target_temp(self, env):
407 # # Release temporaries used by LHS of an assignment.
408 # self.release_subexpr_temps(env)
410 def release_temp(self, env):
411 # If this node owns a temporary result, release it,
412 # otherwise release results of its sub-expressions.
413 if self.is_temp:
414 if debug_temp_alloc:
415 print("%s Releasing result %s" % (self, self.result_code))
416 env.release_temp(self.result_code)
417 else:
418 self.release_subexpr_temps(env)
420 def release_subexpr_temps(self, env):
421 # Release the results of all sub-expressions of
422 # this node.
423 for node in self.subexpr_nodes():
424 if node:
425 node.release_temp(env)
427 # ---------------- Code Generation -----------------
429 def make_owned_reference(self, code):
430 # If result is a pyobject, make sure we own
431 # a reference to it.
432 if self.type.is_pyobject and not self.result_in_temp():
433 code.put_incref(self.result(), self.ctype())
435 def generate_evaluation_code(self, code):
436 code.mark_pos(self.pos)
437 # Generate code to evaluate this node and
438 # its sub-expressions, and dispose of any
439 # temporary results of its sub-expressions.
440 self.generate_subexpr_evaluation_code(code)
441 self.pre_generate_result_code(code)
442 self.generate_result_code(code)
443 if self.is_temp:
444 self.generate_subexpr_disposal_code(code)
446 def pre_generate_result_code(self, code):
447 pass
449 def generate_subexpr_evaluation_code(self, code):
450 for node in self.subexpr_nodes():
451 node.generate_evaluation_code(code)
453 def generate_result_code(self, code):
454 self.not_implemented("generate_result_code")
456 def generate_disposal_code(self, code):
457 # If necessary, generate code to dispose of
458 # temporary Python reference.
459 if self.is_temp:
460 if self.type.is_pyobject:
461 code.put_decref_clear(self.result(), self.ctype())
462 else:
463 self.generate_subexpr_disposal_code(code)
465 def generate_subexpr_disposal_code(self, code):
466 # Generate code to dispose of temporary results
467 # of all sub-expressions.
468 for node in self.subexpr_nodes():
469 node.generate_disposal_code(code)
471 def generate_post_assignment_code(self, code):
472 # Same as generate_disposal_code except that
473 # assignment will have absorbed a reference to
474 # the result if it is a Python object.
475 if self.is_temp:
476 if self.type.is_pyobject:
477 code.putln("%s = 0;" % self.result())
478 else:
479 self.generate_subexpr_disposal_code(code)
481 def generate_assignment_code(self, rhs, code):
482 # Stub method for nodes which are not legal as
483 # the LHS of an assignment. An error will have
484 # been reported earlier.
485 pass
487 def generate_deletion_code(self, code):
488 # Stub method for nodes that are not legal as
489 # the argument of a del statement. An error
490 # will have been reported earlier.
491 pass
493 # ---------------- Annotation ---------------------
495 def annotate(self, code):
496 for node in self.subexpr_nodes():
497 node.annotate(code)
499 # ----------------- Coercion ----------------------
501 def coerce_to(self, dst_type, env):
502 # Coerce the result so that it can be assigned to
503 # something of type dst_type. If processing is necessary,
504 # wraps this node in a coercion node and returns that.
505 # Otherwise, returns this node unchanged.
506 #
507 # This method is called during the analyse_expressions
508 # phase of the src_node's processing.
509 src = self
510 src_type = self.type
511 src_is_py_type = src_type.is_pyobject
512 dst_is_py_type = dst_type.is_pyobject
514 if dst_type.is_pyobject:
515 if not src.type.is_pyobject:
516 src = CoerceToPyTypeNode(src, env)
517 if not src.type.subtype_of(dst_type):
518 if not isinstance(src, NoneNode):
519 src = PyTypeTestNode(src, dst_type, env)
520 elif src.type.is_pyobject:
521 src = CoerceFromPyTypeNode(dst_type, src, env)
522 else: # neither src nor dst are py types
523 # Added the string comparison, since for c types that
524 # is enough, but Cython gets confused when the types are
525 # in different files.
526 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
527 error(self.pos, "Cannot assign type '%s' to '%s'" %
528 (src.type, dst_type))
529 return src
531 def coerce_to_pyobject(self, env):
532 return self.coerce_to(PyrexTypes.py_object_type, env)
534 def coerce_to_boolean(self, env):
535 # Coerce result to something acceptable as
536 # a boolean value.
537 type = self.type
538 if type.is_pyobject or type.is_ptr or type.is_float:
539 return CoerceToBooleanNode(self, env)
540 else:
541 if not type.is_int and not type.is_error:
542 error(self.pos,
543 "Type '%s' not acceptable as a boolean" % type)
544 return self
546 def coerce_to_integer(self, env):
547 # If not already some C integer type, coerce to longint.
548 if self.type.is_int:
549 return self
550 else:
551 return self.coerce_to(PyrexTypes.c_long_type, env)
553 def coerce_to_temp(self, env):
554 # Ensure that the result is in a temporary.
555 if self.result_in_temp():
556 return self
557 else:
558 return CoerceToTempNode(self, env)
560 def coerce_to_simple(self, env):
561 # Ensure that the result is simple (see is_simple).
562 if self.is_simple():
563 return self
564 else:
565 return self.coerce_to_temp(env)
567 def is_simple(self):
568 # A node is simple if its result is something that can
569 # be referred to without performing any operations, e.g.
570 # a constant, local var, C global var, struct member
571 # reference, or temporary.
572 return self.result_in_temp()
574 def as_cython_attribute(self):
575 return None
578 class NewTempExprNode(ExprNode):
579 backwards_compatible_result = None
581 def result(self):
582 if self.is_temp:
583 return self.temp_code
584 else:
585 return self.calculate_result_code()
587 def allocate_target_temps(self, env, rhs):
588 self.allocate_subexpr_temps(env)
589 rhs.release_temp(rhs)
590 self.release_subexpr_temps(env)
592 def allocate_temps(self, env, result = None):
593 self.allocate_subexpr_temps(env)
594 self.backwards_compatible_result = result
595 if self.is_temp:
596 self.release_subexpr_temps(env)
598 def allocate_temp(self, env, result = None):
599 assert result is None
601 def release_temp(self, env):
602 if self.is_temp:
603 pass
604 else:
605 self.release_subexpr_temps(env)
607 def pre_generate_result_code(self, code):
608 if self.is_temp:
609 type = self.type
610 if not type.is_void:
611 if type.is_pyobject:
612 type = PyrexTypes.py_object_type
613 if self.backwards_compatible_result:
614 self.temp_code = self.backwards_compatible_result
615 else:
616 self.temp_code = code.funcstate.allocate_temp(type)
617 else:
618 self.temp_code = None
620 def generate_disposal_code(self, code):
621 if self.is_temp:
622 if self.type.is_pyobject:
623 code.put_decref_clear(self.result(), self.ctype())
624 if not self.backwards_compatible_result:
625 code.funcstate.release_temp(self.temp_code)
626 else:
627 self.generate_subexpr_disposal_code(code)
629 def generate_post_assignment_code(self, code):
630 if self.is_temp:
631 if self.type.is_pyobject:
632 code.putln("%s = 0;" % self.temp_code)
633 if not self.backwards_compatible_result:
634 code.funcstate.release_temp(self.temp_code)
635 else:
636 self.generate_subexpr_disposal_code(code)
641 class AtomicExprNode(ExprNode):
642 # Abstract base class for expression nodes which have
643 # no sub-expressions.
645 subexprs = []
648 class PyConstNode(AtomicExprNode):
649 # Abstract base class for constant Python values.
651 is_literal = 1
653 def is_simple(self):
654 return 1
656 def analyse_types(self, env):
657 self.type = py_object_type
659 def calculate_result_code(self):
660 return self.value
662 def generate_result_code(self, code):
663 pass
666 class NoneNode(PyConstNode):
667 # The constant value None
669 value = "Py_None"
671 def compile_time_value(self, denv):
672 return None
674 class EllipsisNode(PyConstNode):
675 # '...' in a subscript list.
677 value = "Py_Ellipsis"
679 def compile_time_value(self, denv):
680 return Ellipsis
683 class ConstNode(AtomicExprNode):
684 # Abstract base type for literal constant nodes.
685 #
686 # value string C code fragment
688 is_literal = 1
690 def is_simple(self):
691 return 1
693 def analyse_types(self, env):
694 pass # Types are held in class variables
696 def check_const(self):
697 pass
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 compile_time_value(self, denv):
711 return self.value
713 def calculate_result_code(self):
714 return str(int(self.value))
716 class NullNode(ConstNode):
717 type = PyrexTypes.c_null_ptr_type
718 value = "NULL"
721 class CharNode(ConstNode):
722 type = PyrexTypes.c_char_type
724 def compile_time_value(self, denv):
725 return ord(self.value)
727 def calculate_result_code(self):
728 return "'%s'" % StringEncoding.escape_character(self.value)
731 class IntNode(ConstNode):
733 # unsigned "" or "U"
734 # longness "" or "L" or "LL"
736 unsigned = ""
737 longness = ""
738 type = PyrexTypes.c_long_type
740 def coerce_to(self, dst_type, env):
741 if dst_type.is_numeric:
742 self.type = PyrexTypes.c_long_type
743 return self
744 # Arrange for a Python version of the number to be pre-allocated
745 # when coercing to a Python type.
746 if dst_type.is_pyobject:
747 self.entry = env.get_py_num(self.value, self.longness)
748 self.type = PyrexTypes.py_object_type
749 # We still need to perform normal coerce_to processing on the
750 # result, because we might be coercing to an extension type,
751 # in which case a type test node will be needed.
752 return ConstNode.coerce_to(self, dst_type, env)
754 def coerce_to_boolean(self, env):
755 self.type = PyrexTypes.c_bint_type
756 return self
758 def calculate_result_code(self):
759 if self.type.is_pyobject:
760 return self.entry.cname
761 else:
762 return str(self.value) + self.unsigned + self.longness
764 def compile_time_value(self, denv):
765 return int(self.value, 0)
768 class FloatNode(ConstNode):
769 type = PyrexTypes.c_double_type
771 def compile_time_value(self, denv):
772 return float(self.value)
774 def calculate_result_code(self):
775 strval = str(self.value)
776 if strval == 'nan':
777 return "(Py_HUGE_VAL * 0)"
778 elif strval == 'inf':
779 return "Py_HUGE_VAL"
780 elif strval == '-inf':
781 return "(-Py_HUGE_VAL)"
782 else:
783 return strval
786 class StringNode(ConstNode):
787 # entry Symtab.Entry
789 type = PyrexTypes.c_char_ptr_type
791 def compile_time_value(self, denv):
792 return self.value
794 def analyse_types(self, env):
795 self.entry = env.add_string_const(self.value)
797 def analyse_as_type(self, env):
798 type = PyrexTypes.parse_basic_type(self.value)
799 if type is not None:
800 return type
801 from TreeFragment import TreeFragment
802 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
803 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
804 sizeof_node = declaration.root.stats[0].expr
805 sizeof_node.analyse_types(env)
806 if isinstance(sizeof_node, SizeofTypeNode):
807 return sizeof_node.arg_type
809 def coerce_to(self, dst_type, env):
810 if dst_type == PyrexTypes.c_char_ptr_type:
811 self.type = PyrexTypes.c_char_ptr_type
812 return self
814 if dst_type.is_int:
815 if not self.type.is_pyobject and len(self.entry.init) == 1:
816 return CharNode(self.pos, value=self.value)
817 else:
818 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
819 return self
820 # Arrange for a Python version of the string to be pre-allocated
821 # when coercing to a Python type.
822 if dst_type.is_pyobject and not self.type.is_pyobject:
823 node = self.as_py_string_node(env)
824 else:
825 node = self
826 # We still need to perform normal coerce_to processing on the
827 # result, because we might be coercing to an extension type,
828 # in which case a type test node will be needed.
829 return ConstNode.coerce_to(node, dst_type, env)
831 def as_py_string_node(self, env):
832 # Return a new StringNode with the same entry as this node
833 # but whose type is a Python type instead of a C type.
834 entry = self.entry
835 env.add_py_string(entry)
836 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
838 def calculate_result_code(self):
839 if self.type.is_pyobject:
840 return self.entry.pystring_cname
841 else:
842 return self.entry.cname
845 class UnicodeNode(PyConstNode):
846 # entry Symtab.Entry
848 type = unicode_type
850 def analyse_types(self, env):
851 self.entry = env.add_string_const(self.value)
852 env.add_py_string(self.entry)
854 def calculate_result_code(self):
855 return self.entry.pystring_cname
857 def _coerce_to(self, dst_type, env):
858 if not dst_type.is_pyobject:
859 node = StringNode(self.pos, entry = entry, type = py_object_type)
860 return ConstNode.coerce_to(node, dst_type, env)
861 else:
862 return self
863 # We still need to perform normal coerce_to processing on the
864 # result, because we might be coercing to an extension type,
865 # in which case a type test node will be needed.
867 def compile_time_value(self, env):
868 return self.value
871 class IdentifierStringNode(ConstNode):
872 # A Python string that behaves like an identifier, e.g. for
873 # keyword arguments in a call, or for imported names
874 type = PyrexTypes.py_object_type
876 def analyse_types(self, env):
877 self.cname = env.intern_identifier(self.value)
879 def calculate_result_code(self):
880 return self.cname
883 class LongNode(AtomicExprNode):
884 # Python long integer literal
885 #
886 # value string
888 def compile_time_value(self, denv):
889 return long(self.value)
891 gil_message = "Constructing Python long int"
893 def analyse_types(self, env):
894 self.type = py_object_type
895 self.gil_check(env)
896 self.is_temp = 1
898 gil_message = "Constructing Python long int"
900 def generate_evaluation_code(self, code):
901 code.putln(
902 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
903 self.result(),
904 self.value,
905 code.error_goto_if_null(self.result(), self.pos)))
908 class ImagNode(AtomicExprNode):
909 # Imaginary number literal
910 #
911 # value float imaginary part
913 def compile_time_value(self, denv):
914 return complex(0.0, self.value)
916 def analyse_types(self, env):
917 self.type = py_object_type
918 self.gil_check(env)
919 self.is_temp = 1
921 gil_message = "Constructing complex number"
923 def generate_evaluation_code(self, code):
924 code.putln(
925 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
926 self.result(),
927 self.value,
928 code.error_goto_if_null(self.result(), self.pos)))
931 class NameNode(AtomicExprNode):
932 # Reference to a local or global variable name.
933 #
934 # name string Python name of the variable
935 #
936 # entry Entry Symbol table entry
937 # interned_cname string
939 is_name = True
940 is_cython_module = False
941 cython_attribute = None
942 lhs_of_first_assignment = False
943 entry = None
945 def create_analysed_rvalue(pos, env, entry):
946 node = NameNode(pos)
947 node.analyse_types(env, entry=entry)
948 return node
950 def as_cython_attribute(self):
951 return self.cython_attribute
953 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
955 def compile_time_value(self, denv):
956 try:
957 return denv.lookup(self.name)
958 except KeyError:
959 error(self.pos, "Compile-time name '%s' not defined" % self.name)
961 def coerce_to(self, dst_type, env):
962 # If coercing to a generic pyobject and this is a builtin
963 # C function with a Python equivalent, manufacture a NameNode
964 # referring to the Python builtin.
965 #print "NameNode.coerce_to:", self.name, dst_type ###
966 if dst_type is py_object_type:
967 entry = self.entry
968 if entry and entry.is_cfunction:
969 var_entry = entry.as_variable
970 if var_entry:
971 if var_entry.is_builtin and Options.cache_builtins:
972 var_entry = env.declare_builtin(var_entry.name, self.pos)
973 node = NameNode(self.pos, name = self.name)
974 node.entry = var_entry
975 node.analyse_rvalue_entry(env)
976 return node
977 return AtomicExprNode.coerce_to(self, dst_type, env)
979 def analyse_as_module(self, env):
980 # Try to interpret this as a reference to a cimported module.
981 # Returns the module scope, or None.
982 entry = self.entry
983 if not entry:
984 entry = env.lookup(self.name)
985 if entry and entry.as_module:
986 return entry.as_module
987 return None
989 def analyse_as_type(self, env):
990 if self.cython_attribute:
991 type = PyrexTypes.parse_basic_type(self.cython_attribute)
992 else:
993 type = PyrexTypes.parse_basic_type(self.name)
994 if type:
995 return type
996 entry = self.entry
997 if not entry:
998 entry = env.lookup(self.name)
999 if entry and entry.is_type:
1000 return entry.type
1001 else:
1002 return None
1004 def analyse_as_extension_type(self, env):
1005 # Try to interpret this as a reference to an extension type.
1006 # Returns the extension type, or None.
1007 entry = self.entry
1008 if not entry:
1009 entry = env.lookup(self.name)
1010 if entry and entry.is_type and entry.type.is_extension_type:
1011 return entry.type
1012 else:
1013 return None
1015 def analyse_target_declaration(self, env):
1016 if not self.entry:
1017 self.entry = env.lookup_here(self.name)
1018 if not self.entry:
1019 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1020 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1021 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1022 if self.entry.is_declared_generic:
1023 self.result_ctype = py_object_type
1025 def analyse_types(self, env):
1026 if self.entry is None:
1027 self.entry = env.lookup(self.name)
1028 if not self.entry:
1029 self.entry = env.declare_builtin(self.name, self.pos)
1030 if not self.entry:
1031 self.type = PyrexTypes.error_type
1032 return
1033 self.analyse_rvalue_entry(env)
1035 def analyse_target_types(self, env):
1036 self.analyse_entry(env)
1037 if not self.is_lvalue():
1038 error(self.pos, "Assignment to non-lvalue '%s'"
1039 % self.name)
1040 self.type = PyrexTypes.error_type
1041 self.entry.used = 1
1042 if self.entry.type.is_buffer:
1043 import Buffer
1044 Buffer.used_buffer_aux_vars(self.entry)
1046 def analyse_rvalue_entry(self, env):
1047 #print "NameNode.analyse_rvalue_entry:", self.name ###
1048 #print "Entry:", self.entry.__dict__ ###
1049 self.analyse_entry(env)
1050 entry = self.entry
1051 if entry.is_declared_generic:
1052 self.result_ctype = py_object_type
1053 if entry.is_pyglobal or entry.is_builtin:
1054 if Options.cache_builtins and entry.is_builtin:
1055 self.is_temp = 0
1056 else:
1057 self.is_temp = 1
1058 env.use_utility_code(get_name_interned_utility_code)
1059 self.gil_check(env)
1061 gil_message = "Accessing Python global or builtin"
1063 def analyse_entry(self, env):
1064 #print "NameNode.analyse_entry:", self.name ###
1065 self.check_identifier_kind()
1066 entry = self.entry
1067 type = entry.type
1068 self.type = type
1069 if entry.is_pyglobal or entry.is_builtin:
1070 assert type.is_pyobject, "Python global or builtin not a Python object"
1071 self.interned_cname = self.entry.interned_cname = \
1072 env.intern_identifier(self.entry.name)
1074 def check_identifier_kind(self):
1075 #print "NameNode.check_identifier_kind:", self.entry.name ###
1076 #print self.entry.__dict__ ###
1077 entry = self.entry
1078 #entry.used = 1
1079 if not (entry.is_const or entry.is_variable
1080 or entry.is_builtin or entry.is_cfunction):
1081 if self.entry.as_variable:
1082 self.entry = self.entry.as_variable
1083 else:
1084 error(self.pos,
1085 "'%s' is not a constant, variable or function identifier" % self.name)
1087 def is_simple(self):
1088 # If it's not a C variable, it'll be in a temp.
1089 return 1
1091 def calculate_target_results(self, env):
1092 pass
1094 def check_const(self):
1095 entry = self.entry
1096 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1097 self.not_const()
1099 def check_const_addr(self):
1100 entry = self.entry
1101 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1102 self.addr_not_const()
1104 def is_lvalue(self):
1105 return self.entry.is_variable and \
1106 not self.entry.type.is_array and \
1107 not self.entry.is_readonly
1109 def is_ephemeral(self):
1110 # Name nodes are never ephemeral, even if the
1111 # result is in a temporary.
1112 return 0
1114 def allocate_temp(self, env, result = None):
1115 AtomicExprNode.allocate_temp(self, env, result)
1116 entry = self.entry
1117 if entry:
1118 entry.used = 1
1119 if entry.type.is_buffer:
1120 import Buffer
1121 Buffer.used_buffer_aux_vars(entry)
1122 if entry.utility_code:
1123 env.use_utility_code(entry.utility_code)
1125 def calculate_result_code(self):
1126 entry = self.entry
1127 if not entry:
1128 return "<error>" # There was an error earlier
1129 return entry.cname
1131 def generate_result_code(self, code):
1132 assert hasattr(self, 'entry')
1133 entry = self.entry
1134 if entry is None:
1135 return # There was an error earlier
1136 if entry.is_builtin and Options.cache_builtins:
1137 return # Lookup already cached
1138 elif entry.is_pyglobal or entry.is_builtin:
1139 if entry.is_builtin:
1140 namespace = Naming.builtins_cname
1141 else: # entry.is_pyglobal
1142 namespace = entry.scope.namespace_cname
1143 code.putln(
1144 '%s = __Pyx_GetName(%s, %s); %s' % (
1145 self.result(),
1146 namespace,
1147 self.interned_cname,
1148 code.error_goto_if_null(self.result(), self.pos)))
1149 elif entry.is_local and False:
1150 # control flow not good enough yet
1151 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1152 if assigned is False:
1153 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1154 elif not Options.init_local_none and assigned is None:
1155 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1156 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1158 def generate_assignment_code(self, rhs, code):
1159 #print "NameNode.generate_assignment_code:", self.name ###
1160 entry = self.entry
1161 if entry is None:
1162 return # There was an error earlier
1164 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1165 and not self.lhs_of_first_assignment):
1166 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1168 # is_pyglobal seems to be True for module level-globals only.
1169 # We use this to access class->tp_dict if necessary.
1170 if entry.is_pyglobal:
1171 namespace = self.entry.scope.namespace_cname
1172 if entry.is_member:
1173 # if the entry is a member we have to cheat: SetAttr does not work
1174 # on types, so we create a descriptor which is then added to tp_dict
1175 code.put_error_if_neg(self.pos,
1176 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1177 namespace,
1178 self.interned_cname,
1179 rhs.py_result()))
1180 # in Py2.6+, we need to invalidate the method cache
1181 code.putln("PyType_Modified(%s);" %
1182 entry.scope.parent_type.typeptr_cname)
1183 else:
1184 code.put_error_if_neg(self.pos,
1185 'PyObject_SetAttr(%s, %s, %s)' % (
1186 namespace,
1187 self.interned_cname,
1188 rhs.py_result()))
1189 if debug_disposal_code:
1190 print("NameNode.generate_assignment_code:")
1191 print("...generating disposal code for %s" % rhs)
1192 rhs.generate_disposal_code(code)
1194 else:
1195 if self.type.is_buffer:
1196 # Generate code for doing the buffer release/acquisition.
1197 # This might raise an exception in which case the assignment (done
1198 # below) will not happen.
1199 #
1200 # The reason this is not in a typetest-like node is because the
1201 # variables that the acquired buffer info is stored to is allocated
1202 # per entry and coupled with it.
1203 self.generate_acquire_buffer(rhs, code)
1205 if self.type.is_pyobject:
1206 rhs.make_owned_reference(code)
1207 #print "NameNode.generate_assignment_code: to", self.name ###
1208 #print "...from", rhs ###
1209 #print "...LHS type", self.type, "ctype", self.ctype() ###
1210 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1211 if not self.lhs_of_first_assignment:
1212 if entry.is_local and not Options.init_local_none:
1213 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1214 if initalized is True:
1215 code.put_decref(self.result(), self.ctype())
1216 elif initalized is None:
1217 code.put_xdecref(self.result(), self.ctype())
1218 else:
1219 code.put_decref(self.result(), self.ctype())
1220 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1221 if debug_disposal_code:
1222 print("NameNode.generate_assignment_code:")
1223 print("...generating post-assignment code for %s" % rhs)
1224 rhs.generate_post_assignment_code(code)
1226 def generate_acquire_buffer(self, rhs, code):
1227 rhstmp = code.funcstate.allocate_temp(self.entry.type)
1228 buffer_aux = self.entry.buffer_aux
1229 bufstruct = buffer_aux.buffer_info_var.cname
1230 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1232 import Buffer
1233 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1234 is_initialized=not self.lhs_of_first_assignment,
1235 pos=self.pos, code=code)
1236 code.putln("%s = 0;" % rhstmp)
1237 code.funcstate.release_temp(rhstmp)
1239 def generate_deletion_code(self, code):
1240 if self.entry is None:
1241 return # There was an error earlier
1242 if not self.entry.is_pyglobal:
1243 error(self.pos, "Deletion of local or C global name not supported")
1244 return
1245 code.put_error_if_neg(self.pos,
1246 'PyObject_DelAttrString(%s, "%s")' % (
1247 Naming.module_cname,
1248 self.entry.name))
1250 def annotate(self, code):
1251 if hasattr(self, 'is_called') and self.is_called:
1252 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1253 if self.type.is_pyobject:
1254 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1255 else:
1256 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1258 class BackquoteNode(ExprNode):
1259 # `expr`
1260 #
1261 # arg ExprNode
1263 subexprs = ['arg']
1265 def analyse_types(self, env):
1266 self.arg.analyse_types(env)
1267 self.arg = self.arg.coerce_to_pyobject(env)
1268 self.type = py_object_type
1269 self.gil_check(env)
1270 self.is_temp = 1
1272 gil_message = "Backquote expression"
1274 def generate_result_code(self, code):
1275 code.putln(
1276 "%s = PyObject_Repr(%s); %s" % (
1277 self.result(),
1278 self.arg.py_result(),
1279 code.error_goto_if_null(self.result(), self.pos)))
1282 class ImportNode(ExprNode):
1283 # Used as part of import statement implementation.
1284 # Implements result =
1285 # __import__(module_name, globals(), None, name_list)
1286 #
1287 # module_name IdentifierStringNode dotted name of module
1288 # name_list ListNode or None list of names to be imported
1290 subexprs = ['module_name', 'name_list']
1292 def analyse_types(self, env):
1293 self.module_name.analyse_types(env)
1294 self.module_name = self.module_name.coerce_to_pyobject(env)
1295 if self.name_list:
1296 self.name_list.analyse_types(env)
1297 self.name_list.coerce_to_pyobject(env)
1298 self.type = py_object_type
1299 self.gil_check(env)
1300 self.is_temp = 1
1301 env.use_utility_code(import_utility_code)
1303 gil_message = "Python import"
1305 def generate_result_code(self, code):
1306 if self.name_list:
1307 name_list_code = self.name_list.py_result()
1308 else:
1309 name_list_code = "0"
1310 code.putln(
1311 "%s = __Pyx_Import(%s, %s); %s" % (
1312 self.result(),
1313 self.module_name.py_result(),
1314 name_list_code,
1315 code.error_goto_if_null(self.result(), self.pos)))
1318 class IteratorNode(ExprNode):
1319 # Used as part of for statement implementation.
1320 # Implements result = iter(sequence)
1321 #
1322 # sequence ExprNode
1324 subexprs = ['sequence']
1326 def analyse_types(self, env):
1327 self.sequence.analyse_types(env)
1328 self.sequence = self.sequence.coerce_to_pyobject(env)
1329 self.type = py_object_type
1330 self.gil_check(env)
1331 self.is_temp = 1
1333 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1334 self.counter.allocate_temp(env)
1336 gil_message = "Iterating over Python object"
1338 def release_temp(self, env):
1339 env.release_temp(self.result())
1340 self.counter.release_temp(env)
1342 def generate_result_code(self, code):
1343 is_builtin_sequence = self.sequence.type is list_type or \
1344 self.sequence.type is tuple_type
1345 if is_builtin_sequence:
1346 code.putln(
1347 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1348 else:
1349 code.putln(
1350 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1351 self.sequence.py_result(),
1352 self.sequence.py_result()))
1353 code.putln(
1354 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1355 self.counter.result(),
1356 self.result(),
1357 self.sequence.py_result(),
1358 self.result()))
1359 code.putln("} else {")
1360 if is_builtin_sequence:
1361 code.putln(
1362 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1363 code.error_goto(self.pos))
1364 else:
1365 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1366 self.counter.result(),
1367 self.result(),
1368 self.sequence.py_result(),
1369 code.error_goto_if_null(self.result(), self.pos)))
1370 code.putln("}")
1373 class NextNode(AtomicExprNode):
1374 # Used as part of for statement implementation.
1375 # Implements result = iterator.next()
1376 # Created during analyse_types phase.
1377 # The iterator is not owned by this node.
1378 #
1379 # iterator ExprNode
1381 def __init__(self, iterator, env):
1382 self.pos = iterator.pos
1383 self.iterator = iterator
1384 self.type = py_object_type
1385 self.is_temp = 1
1387 def generate_result_code(self, code):
1388 if self.iterator.sequence.type is list_type:
1389 type_checks = [(list_type, "List")]
1390 elif self.iterator.sequence.type is tuple_type:
1391 type_checks = [(tuple_type, "Tuple")]
1392 else:
1393 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1395 for py_type, prefix in type_checks:
1396 if len(type_checks) > 1:
1397 code.putln(
1398 "if (likely(Py%s_CheckExact(%s))) {" % (
1399 prefix, self.iterator.py_result()))
1400 code.putln(
1401 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1402 self.iterator.counter.result(),
1403 prefix,
1404 self.iterator.py_result()))
1405 code.putln(
1406 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1407 self.result(),
1408 prefix,
1409 self.iterator.py_result(),
1410 self.iterator.counter.result(),
1411 self.result(),
1412 self.iterator.counter.result()))
1413 if len(type_checks) > 1:
1414 code.put("} else ")
1415 if len(type_checks) == 1:
1416 return
1417 code.putln("{")
1418 code.putln(
1419 "%s = PyIter_Next(%s);" % (
1420 self.result(),
1421 self.iterator.py_result()))
1422 code.putln(
1423 "if (!%s) {" %
1424 self.result())
1425 code.putln(code.error_goto_if_PyErr(self.pos))
1426 code.putln("break;")
1427 code.putln("}")
1428 code.putln("}")
1431 class ExcValueNode(AtomicExprNode):
1432 # Node created during analyse_types phase
1433 # of an ExceptClauseNode to fetch the current
1434 # exception value.
1436 def __init__(self, pos, env, var):
1437 ExprNode.__init__(self, pos)
1438 self.type = py_object_type
1439 self.var = var
1441 def calculate_result_code(self):
1442 return self.var
1444 def generate_result_code(self, code):
1445 pass
1447 def analyse_types(self, env):
1448 pass
1451 class TempNode(AtomicExprNode):
1452 # Node created during analyse_types phase
1453 # of some nodes to hold a temporary value.
1455 def __init__(self, pos, type, env):
1456 ExprNode.__init__(self, pos)
1457 self.type = type
1458 if type.is_pyobject:
1459 self.result_ctype = py_object_type
1460 self.is_temp = 1
1462 def analyse_types(self, env):
1463 return self.type
1465 def generate_result_code(self, code):
1466 pass
1469 class PyTempNode(TempNode):
1470 # TempNode holding a Python value.
1472 def __init__(self, pos, env):
1473 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1476 #-------------------------------------------------------------------
1477 #
1478 # Trailer nodes
1479 #
1480 #-------------------------------------------------------------------
1482 class IndexNode(ExprNode):
1483 # Sequence indexing.
1484 #
1485 # base ExprNode
1486 # index ExprNode
1487 # indices [ExprNode]
1488 # is_buffer_access boolean Whether this is a buffer access.
1489 #
1490 # indices is used on buffer access, index on non-buffer access.
1491 # The former contains a clean list of index parameters, the
1492 # latter whatever Python object is needed for index access.
1494 subexprs = ['base', 'index', 'indices']
1495 indices = None
1497 def __init__(self, pos, index, *args, **kw):
1498 ExprNode.__init__(self, pos, index=index, *args, **kw)
1499 self._index = index
1501 def compile_time_value(self, denv):
1502 base = self.base.compile_time_value(denv)
1503 index = self.index.compile_time_value(denv)
1504 try:
1505 return base[index]
1506 except Exception, e:
1507 self.compile_time_value_error(e)
1509 def is_ephemeral(self):
1510 return self.base.is_ephemeral()
1512 def analyse_target_declaration(self, env):
1513 pass
1515 def analyse_as_type(self, env):
1516 base_type = self.base.analyse_as_type(env)
1517 if base_type and not base_type.is_pyobject:
1518 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1519 return None
1521 def analyse_types(self, env):
1522 self.analyse_base_and_index_types(env, getting = 1)
1524 def analyse_target_types(self, env):
1525 self.analyse_base_and_index_types(env, setting = 1)
1527 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1528 # Note: This might be cleaned up by having IndexNode
1529 # parsed in a saner way and only construct the tuple if
1530 # needed.
1532 # Note that this function must leave IndexNode in a cloneable state.
1533 # For buffers, self.index is packed out on the initial analysis, and
1534 # when cloning self.indices is copied.
1535 self.is_buffer_access = False
1537 self.base.analyse_types(env)
1538 # Handle the case where base is a literal char* (and we expect a string, not an int)
1539 if isinstance(self.base, StringNode):
1540 self.base = self.base.coerce_to_pyobject(env)
1542 skip_child_analysis = False
1543 buffer_access = False
1544 if self.base.type.is_buffer:
1545 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1546 if self.indices:
1547 indices = self.indices
1548 else:
1549 # On cloning, indices is cloned. Otherwise, unpack index into indices
1550 assert not isinstance(self.index, CloneNode)
1551 if isinstance(self.index, TupleNode):
1552 indices = self.index.args
1553 else:
1554 indices = [self.index]
1555 if len(indices) == self.base.type.ndim:
1556 buffer_access = True
1557 skip_child_analysis = True
1558 for x in indices:
1559 x.analyse_types(env)
1560 if not x.type.is_int:
1561 buffer_access = False
1563 if buffer_access:
1564 self.indices = indices
1565 self.index = None
1566 self.type = self.base.type.dtype
1567 self.is_buffer_access = True
1568 self.buffer_type = self.base.entry.type
1570 if getting and self.type.is_pyobject:
1571 self.is_temp = True
1572 if setting:
1573 if not self.base.entry.type.writable:
1574 error(self.pos, "Writing to readonly buffer")
1575 else:
1576 self.base.entry.buffer_aux.writable_needed = True
1577 else:
1578 if isinstance(self.index, TupleNode):
1579 self.index.analyse_types(env, skip_children=skip_child_analysis)
1580 elif not skip_child_analysis:
1581 self.index.analyse_types(env)
1582 self.original_index_type = self.index.type
1583 if self.base.type.is_pyobject:
1584 if self.index.type.is_int and not self.index.type.is_longlong:
1585 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1586 else:
1587 self.index = self.index.coerce_to_pyobject(env)
1588 self.type = py_object_type
1589 self.gil_check(env)
1590 self.is_temp = 1
1591 else:
1592 if self.base.type.is_ptr or self.base.type.is_array:
1593 self.type = self.base.type.base_type
1594 else:
1595 error(self.pos,
1596 "Attempting to index non-array type '%s'" %
1597 self.base.type)
1598 self.type = PyrexTypes.error_type
1599 if self.index.type.is_pyobject:
1600 self.index = self.index.coerce_to(
1601 PyrexTypes.c_py_ssize_t_type, env)
1602 if not self.index.type.is_int:
1603 error(self.pos,
1604 "Invalid index type '%s'" %
1605 self.index.type)
1607 gil_message = "Indexing Python object"
1609 def check_const_addr(self):
1610 self.base.check_const_addr()
1611 self.index.check_const()
1613 def is_lvalue(self):
1614 return 1
1616 def calculate_result_code(self):
1617 if self.is_buffer_access:
1618 return "(*%s)" % self.buffer_ptr_code
1619 else:
1620 return "(%s[%s])" % (
1621 self.base.result(), self.index.result())
1623 def index_unsigned_parameter(self):
1624 if self.index.type.is_int:
1625 if self.original_index_type.signed:
1626 return ", 0"
1627 else:
1628 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1629 else:
1630 return ""
1632 def generate_subexpr_evaluation_code(self, code):
1633 self.base.generate_evaluation_code(code)
1634 if not self.indices:
1635 self.index.generate_evaluation_code(code)
1636 else:
1637 for i in self.indices:
1638 i.generate_evaluation_code(code)
1640 def generate_subexpr_disposal_code(self, code):
1641 self.base.generate_disposal_code(code)
1642 if not self.indices:
1643 self.index.generate_disposal_code(code)
1644 else:
1645 for i in self.indices:
1646 i.generate_disposal_code(code)
1648 def generate_result_code(self, code):
1649 if self.is_buffer_access:
1650 if code.globalstate.directives['nonecheck']:
1651 self.put_nonecheck(code)
1652 self.buffer_ptr_code = self.buffer_lookup_code(code)
1653 if self.type.is_pyobject:
1654 # is_temp is True, so must pull out value and incref it.
1655 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1656 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1657 elif self.type.is_pyobject:
1658 if self.index.type.is_int:
1659 function = "__Pyx_GetItemInt"
1660 index_code = self.index.result()
1661 code.globalstate.use_utility_code(getitem_int_utility_code)
1662 else:
1663 function = "PyObject_GetItem"
1664 index_code = self.index.py_result()
1665 sign_code = ""
1666 code.putln(
1667 "%s = %s(%s, %s%s); if (!%s) %s" % (
1668 self.result(),
1669 function,
1670 self.base.py_result(),
1671 index_code,
1672 self.index_unsigned_parameter(),
1673 self.result(),
1674 code.error_goto(self.pos)))
1676 def generate_setitem_code(self, value_code, code):
1677 if self.index.type.is_int:
1678 function = "__Pyx_SetItemInt"
1679 index_code = self.index.result()
1680 code.globalstate.use_utility_code(setitem_int_utility_code)
1681 else:
1682 index_code = self.index.py_result()
1683 if self.base.type is dict_type:
1684 function = "PyDict_SetItem"
1685 elif self.base.type is list_type:
1686 function = "PyList_SetItem"
1687 # don't use PyTuple_SetItem(), as we'd normally get a
1688 # TypeError when changing a tuple, while PyTuple_SetItem()
1689 # would allow updates
1690 #
1691 #elif self.base.type is tuple_type:
1692 # function = "PyTuple_SetItem"
1693 else:
1694 function = "PyObject_SetItem"
1695 code.putln(
1696 "if (%s(%s, %s, %s%s) < 0) %s" % (
1697 function,
1698 self.base.py_result(),
1699 index_code,
1700 value_code,
1701 self.index_unsigned_parameter(),
1702 code.error_goto(self.pos)))
1704 def generate_buffer_setitem_code(self, rhs, code, op=""):
1705 # Used from generate_assignment_code and InPlaceAssignmentNode
1706 if code.globalstate.directives['nonecheck']:
1707 self.put_nonecheck(code)
1708 ptrexpr = self.buffer_lookup_code(code)
1709 if self.buffer_type.dtype.is_pyobject:
1710 # Must manage refcounts. Decref what is already there
1711 # and incref what we put in.
1712 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
1713 if rhs.is_temp:
1714 rhs_code = code.funcstate.allocate_temp(rhs.type)
1715 else:
1716 rhs_code = rhs.result()
1717 code.putln("%s = %s;" % (ptr, ptrexpr))
1718 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1719 ptr, rhs_code
1720 ))
1721 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1722 if rhs.is_temp:
1723 code.funcstate.release_temp(rhs_code)
1724 code.funcstate.release_temp(ptr)
1725 else:
1726 # Simple case
1727 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1729 def generate_assignment_code(self, rhs, code):
1730 self.generate_subexpr_evaluation_code(code)
1731 if self.is_buffer_access:
1732 self.generate_buffer_setitem_code(rhs, code)
1733 elif self.type.is_pyobject:
1734 self.generate_setitem_code(rhs.py_result(), code)
1735 else:
1736 code.putln(
1737 "%s = %s;" % (
1738 self.result(), rhs.result()))
1739 self.generate_subexpr_disposal_code(code)
1740 rhs.generate_disposal_code(code)
1742 def generate_deletion_code(self, code):
1743 self.generate_subexpr_evaluation_code(code)
1744 #if self.type.is_pyobject:
1745 if self.index.type.is_int:
1746 function = "__Pyx_DelItemInt"
1747 index_code = self.index.result()
1748 code.globalstate.use_utility_code(delitem_int_utility_code)
1749 else:
1750 index_code = self.index.py_result()
1751 if self.base.type is dict_type:
1752 function = "PyDict_DelItem"
1753 else:
1754 function = "PyObject_DelItem"
1755 code.putln(
1756 "if (%s(%s, %s%s) < 0) %s" % (
1757 function,
1758 self.base.py_result(),
1759 index_code,
1760 self.index_unsigned_parameter(),
1761 code.error_goto(self.pos)))
1762 self.generate_subexpr_disposal_code(code)
1764 def buffer_lookup_code(self, code):
1765 # Assign indices to temps
1766 index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
1767 for temp, index in zip(index_temps, self.indices):
1768 code.putln("%s = %s;" % (temp, index.result()))
1769 # Generate buffer access code using these temps
1770 import Buffer
1771 # The above could happen because child_attrs is wrong somewhere so that
1772 # options are not propagated.
1773 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1774 index_signeds=[i.type.signed for i in self.indices],
1775 index_cnames=index_temps,
1776 options=code.globalstate.directives,
1777 pos=self.pos, code=code)
1779 def put_nonecheck(self, code):
1780 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1781 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1782 code.putln("__Pyx_RaiseNoneIndexingError();")
1783 code.putln(code.error_goto(self.pos))
1784 code.putln("}")
1786 class SliceIndexNode(ExprNode):
1787 # 2-element slice indexing
1788 #
1789 # base ExprNode
1790 # start ExprNode or None
1791 # stop ExprNode or None
1793 subexprs = ['base', 'start', 'stop']
1795 def compile_time_value(self, denv):
1796 base = self.base.compile_time_value(denv)
1797 if self.start is None:
1798 start = 0
1799 else:
1800 start = self.start.compile_time_value(denv)
1801 if self.stop is None:
1802 stop = None
1803 else:
1804 stop = self.stop.compile_time_value(denv)
1805 try:
1806 return base[start:stop]
1807 except Exception, e:
1808 self.compile_time_value_error(e)
1810 def analyse_target_declaration(self, env):
1811 pass
1813 def analyse_types(self, env):
1814 self.base.analyse_types(env)
1815 if self.start:
1816 self.start.analyse_types(env)
1817 if self.stop:
1818 self.stop.analyse_types(env)
1819 if self.base.type.is_array or self.base.type.is_ptr:
1820 # we need a ptr type here instead of an array type, as
1821 # array types can result in invalid type casts in the C
1822 # code
1823 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
1824 else:
1825 self.base = self.base.coerce_to_pyobject(env)
1826 self.type = py_object_type
1827 c_int = PyrexTypes.c_py_ssize_t_type
1828 if self.start:
1829 self.start = self.start.coerce_to(c_int, env)
1830 if self.stop:
1831 self.stop = self.stop.coerce_to(c_int, env)
1832 self.gil_check(env)
1833 self.is_temp = 1
1835 gil_message = "Slicing Python object"
1837 def generate_result_code(self, code):
1838 if not self.type.is_pyobject:
1839 error(self.pos,
1840 "Slicing is not currently supported for '%s'." % self.type)
1841 return
1842 code.putln(
1843 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1844 self.result(),
1845 self.base.py_result(),
1846 self.start_code(),
1847 self.stop_code(),
1848 code.error_goto_if_null(self.result(), self.pos)))
1850 def generate_assignment_code(self, rhs, code):
1851 self.generate_subexpr_evaluation_code(code)
1852 if self.type.is_pyobject:
1853 code.put_error_if_neg(self.pos,
1854 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1855 self.base.py_result(),
1856 self.start_code(),
1857 self.stop_code(),
1858 rhs.result()))
1859 else:
1860 start_offset = ''
1861 if self.start:
1862 start_offset = self.start_code()
1863 if start_offset == '0':
1864 start_offset = ''
1865 else:
1866 start_offset += '+'
1867 if rhs.type.is_array:
1868 array_length = rhs.type.size
1869 self.generate_slice_guard_code(code, array_length)
1870 else:
1871 error("Slice assignments from pointers are not yet supported.")
1872 # FIXME: fix the array size according to start/stop
1873 array_length = self.base.type.size
1874 for i in range(array_length):
1875 code.putln("%s[%s%s] = %s[%d];" % (
1876 self.base.result(), start_offset, i,
1877 rhs.result(), i))
1878 self.generate_subexpr_disposal_code(code)
1879 rhs.generate_disposal_code(code)
1881 def generate_deletion_code(self, code):
1882 if not self.type.is_pyobject:
1883 error(self.pos,
1884 "Deleting slices is only supported for Python types, not '%s'." % self.type)
1885 return
1886 self.generate_subexpr_evaluation_code(code)
1887 code.put_error_if_neg(self.pos,
1888 "PySequence_DelSlice(%s, %s, %s)" % (
1889 self.base.py_result(),
1890 self.start_code(),
1891 self.stop_code()))
1892 self.generate_subexpr_disposal_code(code)
1894 def generate_slice_guard_code(self, code, target_size):
1895 if not self.base.type.is_array:
1896 return
1897 slice_size = self.base.type.size
1898 start = stop = None
1899 if self.stop:
1900 stop = self.stop.result()
1901 try:
1902 stop = int(stop)
1903 if stop < 0:
1904 slice_size = self.base.type.size + stop
1905 else:
1906 slice_size = stop
1907 stop = None
1908 except ValueError:
1909 pass
1910 if self.start:
1911 start = self.start.result()
1912 try:
1913 start = int(start)
1914 if start < 0:
1915 start = self.base.type.size + start
1916 slice_size -= start
1917 start = None
1918 except ValueError:
1919 pass
1920 check = None
1921 if slice_size < 0:
1922 if target_size > 0:
1923 error(self.pos, "Assignment to empty slice.")
1924 elif start is None and stop is None:
1925 # we know the exact slice length
1926 if target_size != slice_size:
1927 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
1928 slice_size, target_size))
1929 elif start is not None:
1930 if stop is None:
1931 stop = slice_size
1932 check = "(%s)-(%s)" % (stop, start)
1933 else: # stop is not None:
1934 check = stop
1935 if check:
1936 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
1937 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
1938 target_size, check))
1939 code.putln(code.error_goto(self.pos))
1940 code.putln("}")
1942 def start_code(self):
1943 if self.start:
1944 return self.start.result()
1945 else:
1946 return "0"
1948 def stop_code(self):
1949 if self.stop:
1950 return self.stop.result()
1951 elif self.base.type.is_array:
1952 return self.base.type.size
1953 else:
1954 return "PY_SSIZE_T_MAX"
1956 def calculate_result_code(self):
1957 # self.result() is not used, but this method must exist
1958 return "<unused>"
1961 class SliceNode(ExprNode):
1962 # start:stop:step in subscript list
1963 #
1964 # start ExprNode
1965 # stop ExprNode
1966 # step ExprNode
1968 def compile_time_value(self, denv):
1969 start = self.start.compile_time_value(denv)
1970 if self.stop is None:
1971 stop = None
1972 else:
1973 stop = self.stop.compile_time_value(denv)
1974 if self.step is None:
1975 step = None
1976 else:
1977 step = self.step.compile_time_value(denv)
1978 try:
1979 return slice(start, stop, step)
1980 except Exception, e:
1981 self.compile_time_value_error(e)
1983 subexprs = ['start', 'stop', 'step']
1985 def analyse_types(self, env):
1986 self.start.analyse_types(env)
1987 self.stop.analyse_types(env)
1988 self.step.analyse_types(env)
1989 self.start = self.start.coerce_to_pyobject(env)
1990 self.stop = self.stop.coerce_to_pyobject(env)
1991 self.step = self.step.coerce_to_pyobject(env)
1992 self.type = py_object_type
1993 self.gil_check(env)
1994 self.is_temp = 1
1996 gil_message = "Constructing Python slice object"
1998 def generate_result_code(self, code):
1999 code.putln(
2000 "%s = PySlice_New(%s, %s, %s); %s" % (
2001 self.result(),
2002 self.start.py_result(),
2003 self.stop.py_result(),
2004 self.step.py_result(),
2005 code.error_goto_if_null(self.result(), self.pos)))
2008 class CallNode(ExprNode):
2009 def gil_check(self, env):
2010 # Make sure we're not in a nogil environment
2011 if env.nogil:
2012 error(self.pos, "Calling gil-requiring function without gil")
2014 def analyse_as_type_constructor(self, env):
2015 type = self.function.analyse_as_type(env)
2016 if type and type.is_struct_or_union:
2017 args, kwds = self.explicit_args_kwds()
2018 items = []
2019 for arg, member in zip(args, type.scope.var_entries):
2020 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2021 if kwds:
2022 items += kwds.key_value_pairs
2023 self.key_value_pairs = items
2024 self.__class__ = DictNode
2025 self.analyse_types(env)
2026 self.coerce_to(type, env)
2027 return True
2030 class SimpleCallNode(CallNode):
2031 # Function call without keyword, * or ** args.
2032 #
2033 # function ExprNode
2034 # args [ExprNode]
2035 # arg_tuple ExprNode or None used internally
2036 # self ExprNode or None used internally
2037 # coerced_self ExprNode or None used internally
2038 # wrapper_call bool used internally
2039 # has_optional_args bool used internally
2041 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2043 self = None
2044 coerced_self = None
2045 arg_tuple = None
2046 wrapper_call = False
2047 has_optional_args = False
2049 def compile_time_value(self, denv):
2050 function = self.function.compile_time_value(denv)
2051 args = [arg.compile_time_value(denv) for arg in self.args]
2052 try:
2053 return function(*args)
2054 except Exception, e:
2055 self.compile_time_value_error(e)
2057 def analyse_as_type(self, env):
2058 attr = self.function.as_cython_attribute()
2059 if attr == 'pointer':
2060 if len(self.args) != 1:
2061 error(self.args.pos, "only one type allowed.")
2062 else:
2063 type = self.args[0].analyse_as_type(env)
2064 if not type:
2065 error(self.args[0].pos, "Unknown type")
2066 else:
2067 return PyrexTypes.CPtrType(type)
2069 def explicit_args_kwds(self):
2070 return self.args, None
2072 def analyse_types(self, env):
2073 if self.analyse_as_type_constructor(env):
2074 return
2075 function = self.function
2076 function.is_called = 1
2077 self.function.analyse_types(env)
2078 if function.is_attribute and function.is_py_attr and \
2079 function.attribute == "append" and len(self.args) == 1:
2080 # L.append(x) is almost always applied to a list
2081 self.py_func = self.function
2082 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2083 self.function.analyse_types(env)
2084 self.self = self.py_func.obj
2085 function.obj = CloneNode(self.self)
2086 env.use_utility_code(append_utility_code)
2087 if function.is_attribute and function.entry and function.entry.is_cmethod:
2088 # Take ownership of the object from which the attribute
2089 # was obtained, because we need to pass it as 'self'.
2090 self.self = function.obj
2091 function.obj = CloneNode(self.self)
2092 func_type = self.function_type()
2093 if func_type.is_pyobject:
2094 self.arg_tuple = TupleNode(self.pos, args = self.args)
2095 self.arg_tuple.analyse_types(env)
2096 self.args = None
2097 self.type = py_object_type
2098 self.gil_check(env)
2099 self.is_temp = 1
2100 else:
2101 for arg in self.args:
2102 arg.analyse_types(env)
2103 if self.self and func_type.args:
2104 # Coerce 'self' to the type expected by the method.
2105 expected_type = func_type.args[0].type
2106 self.coerced_self = CloneNode(self.self).coerce_to(
2107 expected_type, env)
2108 # Insert coerced 'self' argument into argument list.
2109 self.args.insert(0, self.coerced_self)
2110 self.analyse_c_function_call(env)
2112 def function_type(self):
2113 # Return the type of the function being called, coercing a function
2114 # pointer to a function if necessary.
2115 func_type = self.function.type
2116 if func_type.is_ptr:
2117 func_type = func_type.base_type
2118 return func_type
2120 def analyse_c_function_call(self, env):
2121 func_type = self.function_type()
2122 # Check function type
2123 if not func_type.is_cfunction:
2124 if not func_type.is_error:
2125 error(self.pos, "Calling non-function type '%s'" %
2126 func_type)
2127 self.type = PyrexTypes.error_type
2128 self.result_code = "<error>"
2129 return
2130 # Check no. of args
2131 max_nargs = len(func_type.args)
2132 expected_nargs = max_nargs - func_type.optional_arg_count
2133 actual_nargs = len(self.args)
2134 if actual_nargs < expected_nargs \
2135 or (not func_type.has_varargs and actual_nargs > max_nargs):
2136 expected_str = str(expected_nargs)
2137 if func_type.has_varargs:
2138 expected_str = "at least " + expected_str
2139 elif func_type.optional_arg_count:
2140 if actual_nargs < max_nargs:
2141 expected_str = "at least " + expected_str
2142 else:
2143 expected_str = "at most " + str(max_nargs)
2144 error(self.pos,
2145 "Call with wrong number of arguments (expected %s, got %s)"
2146 % (expected_str, actual_nargs))
2147 self.args = None
2148 self.type = PyrexTypes.error_type
2149 self.result_code = "<error>"
2150 return
2151 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2152 self.has_optional_args = 1
2153 self.is_temp = 1
2154 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2155 env.release_temp(self.opt_arg_struct)
2156 # Coerce arguments
2157 for i in range(min(max_nargs, actual_nargs)):
2158 formal_type = func_type.args[i].type
2159 self.args[i] = self.args[i].coerce_to(formal_type, env)
2160 for i in range(max_nargs, actual_nargs):
2161 if self.args[i].type.is_pyobject:
2162 error(self.args[i].pos,
2163 "Python object cannot be passed as a varargs parameter")
2164 # Calc result type and code fragment
2165 self.type = func_type.return_type
2166 if self.type.is_pyobject \
2167 or func_type.exception_value is not None \
2168 or func_type.exception_check:
2169 self.is_temp = 1
2170 if self.type.is_pyobject:
2171 self.result_ctype = py_object_type
2172 # C++ exception handler
2173 if func_type.exception_check == '+':
2174 if func_type.exception_value is None:
2175 env.use_utility_code(cpp_exception_utility_code)
2176 # Check gil
2177 if not func_type.nogil:
2178 self.gil_check(env)
2180 def calculate_result_code(self):
2181 return self.c_call_code()
2183 def c_call_code(self):
2184 func_type = self.function_type()
2185 if self.args is None or not func_type.is_cfunction:
2186 return "<error>"
2187 formal_args = func_type.args
2188 arg_list_code = []
2189 args = zip(formal_args, self.args)
2190 max_nargs = len(func_type.args)
2191 expected_nargs = max_nargs - func_type.optional_arg_count
2192 actual_nargs = len(self.args)
2193 for formal_arg, actual_arg in args[:expected_nargs]:
2194 arg_code = actual_arg.result_as(formal_arg.type)
2195 arg_list_code.append(arg_code)
2197 if func_type.is_overridable:
2198 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2200 if func_type.optional_arg_count:
2201 if expected_nargs == actual_nargs:
2202 optional_args = 'NULL'
2203 else:
2204 optional_args = "&%s" % self.opt_arg_struct
2205 arg_list_code.append(optional_args)
2207 for actual_arg in self.args[len(formal_args):]:
2208 arg_list_code.append(actual_arg.result())
2209 result = "%s(%s)" % (self.function.result(),
2210 join(arg_list_code, ", "))
2211 # if self.wrapper_call or \
2212 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2213 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2214 return result
2216 def generate_result_code(self, code):
2217 func_type = self.function_type()
2218 if func_type.is_pyobject:
2219 arg_code = self.arg_tuple.py_result()
2220 code.putln(
2221 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2222 self.result(),
2223 self.function.py_result(),
2224 arg_code,
2225 code.error_goto_if_null(self.result(), self.pos)))
2226 elif func_type.is_cfunction:
2227 if self.has_optional_args:
2228 actual_nargs = len(self.args)
2229 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2230 code.putln("%s.%s = %s;" % (
2231 self.opt_arg_struct,
2232 Naming.pyrex_prefix + "n",
2233 len(self.args) - expected_nargs))
2234 args = zip(func_type.args, self.args)
2235 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2236 code.putln("%s.%s = %s;" % (
2237 self.opt_arg_struct,
2238 formal_arg.name,
2239 actual_arg.result_as(formal_arg.type)))
2240 exc_checks = []
2241 if self.type.is_pyobject:
2242 exc_checks.append("!%s" % self.result())
2243 else:
2244 exc_val = func_type.exception_value
2245 exc_check = func_type.exception_check
2246 if exc_val is not None:
2247 exc_checks.append("%s == %s" % (self.result(), exc_val))
2248 if exc_check:
2249 exc_checks.append("PyErr_Occurred()")
2250 if self.is_temp or exc_checks:
2251 rhs = self.c_call_code()
2252 if self.result():
2253 lhs = "%s = " % self.result()
2254 if self.is_temp and self.type.is_pyobject:
2255 #return_type = self.type # func_type.return_type
2256 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2257 # "from", return_type, "to pyobject" ###
2258 rhs = typecast(py_object_type, self.type, rhs)
2259 else:
2260 lhs = ""
2261 if func_type.exception_check == '+':
2262 if func_type.exception_value is None:
2263 raise_py_exception = "__Pyx_CppExn2PyErr()"
2264 elif func_type.exception_value.type.is_pyobject:
2265 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2266 else:
2267 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2268 code.putln(
2269 "try {%s%s;} catch(...) {%s; %s}" % (
2270 lhs,
2271 rhs,
2272 raise_py_exception,
2273 code.error_goto(self.pos)))
2274 else:
2275 if exc_checks:
2276 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2277 else:
2278 goto_error = ""
2279 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2281 class GeneralCallNode(CallNode):
2282 # General Python function call, including keyword,
2283 # * and ** arguments.
2284 #
2285 # function ExprNode
2286 # positional_args ExprNode Tuple of positional arguments
2287 # keyword_args ExprNode or None Dict of keyword arguments
2288 # starstar_arg ExprNode or None Dict of extra keyword args
2290 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2292 def compile_time_value(self, denv):
2293 function = self.function.compile_time_value(denv)
2294 positional_args = self.positional_args.compile_time_value(denv)
2295 keyword_args = self.keyword_args.compile_time_value(denv)
2296 starstar_arg = self.starstar_arg.compile_time_value(denv)
2297 try:
2298 keyword_args.update(starstar_arg)
2299 return function(*positional_args, **keyword_args)
2300 except Exception, e:
2301 self.compile_time_value_error(e)
2303 def explicit_args_kwds(self):
2304 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2305 raise PostParseError(self.pos,
2306 'Compile-time keyword arguments must be explicit.')
2307 return self.positional_args.args, self.keyword_args
2309 def analyse_types(self, env):
2310 if self.analyse_as_type_constructor(env):
2311 return
2312 self.function.analyse_types(env)
2313 self.positional_args.analyse_types(env)
2314 if self.keyword_args:
2315 self.keyword_args.analyse_types(env)
2316 if self.starstar_arg:
2317 self.starstar_arg.analyse_types(env)
2318 self.function = self.function.coerce_to_pyobject(env)
2319 self.positional_args = \
2320 self.positional_args.coerce_to_pyobject(env)
2321 if self.starstar_arg:
2322 self.starstar_arg = \
2323 self.starstar_arg.coerce_to_pyobject(env)
2324 self.type = py_object_type
2325 self.gil_check(env)
2326 self.is_temp = 1
2328 def generate_result_code(self, code):
2329 if self.keyword_args and self.starstar_arg:
2330 code.put_error_if_neg(self.pos,
2331 "PyDict_Update(%s, %s)" % (
2332 self.keyword_args.py_result(),
2333 self.starstar_arg.py_result()))
2334 keyword_code = self.keyword_args.py_result()
2335 elif self.keyword_args:
2336 keyword_code = self.keyword_args.py_result()
2337 elif self.starstar_arg:
2338 keyword_code = self.starstar_arg.py_result()
2339 else:
2340 keyword_code = None
2341 if not keyword_code:
2342 call_code = "PyObject_Call(%s, %s, NULL)" % (
2343 self.function.py_result(),
2344 self.positional_args.py_result())
2345 else:
2346 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2347 self.function.py_result(),
2348 self.positional_args.py_result(),
2349 keyword_code)
2350 code.putln(
2351 "%s = %s; %s" % (
2352 self.result(),
2353 call_code,
2354 code.error_goto_if_null(self.result(), self.pos)))
2357 class AsTupleNode(ExprNode):
2358 # Convert argument to tuple. Used for normalising
2359 # the * argument of a function call.
2360 #
2361 # arg ExprNode
2363 subexprs = ['arg']
2365 def compile_time_value(self, denv):
2366 arg = self.arg.compile_time_value(denv)
2367 try:
2368 return tuple(arg)
2369 except Exception, e:
2370 self.compile_time_value_error(e)
2372 def analyse_types(self, env):
2373 self.arg.analyse_types(env)
2374 self.arg = self.arg.coerce_to_pyobject(env)
2375 self.type = py_object_type
2376 self.gil_check(env)
2377 self.is_temp = 1
2379 gil_message = "Constructing Python tuple"
2381 def generate_result_code(self, code):
2382 code.putln(
2383 "%s = PySequence_Tuple(%s); %s" % (
2384 self.result(),
2385 self.arg.py_result(),
2386 code.error_goto_if_null(self.result(), self.pos)))
2389 class AttributeNode(ExprNode):
2390 # obj.attribute
2391 #
2392 # obj ExprNode
2393 # attribute string
2394 # needs_none_check boolean Used if obj is an extension type.
2395 # If set to True, it is known that the type is not None.
2396 #
2397 # Used internally:
2398 #
2399 # is_py_attr boolean Is a Python getattr operation
2400 # member string C name of struct member
2401 # is_called boolean Function call is being done on result
2402 # entry Entry Symbol table entry of attribute
2403 # interned_attr_cname string C name of interned attribute name
2405 is_attribute = 1
2406 subexprs = ['obj']
2408 type = PyrexTypes.error_type
2409 entry = None
2410 is_called = 0
2411 needs_none_check = True
2413 def as_cython_attribute(self):
2414 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2415 return self.attribute
2417 def coerce_to(self, dst_type, env):
2418 # If coercing to a generic pyobject and this is a cpdef function
2419 # we can create the corresponding attribute
2420 if dst_type is py_object_type:
2421 entry = self.entry
2422 if entry and entry.is_cfunction and entry.as_variable:
2423 # must be a cpdef function
2424 self.is_temp = 1
2425 self.entry = entry.as_variable
2426 self.analyse_as_python_attribute(env)
2427 return self
2428 return ExprNode.coerce_to(self, dst_type, env)
2430 def compile_time_value(self, denv):
2431 attr = self.attribute
2432 if attr.beginswith("__") and attr.endswith("__"):
2433 self.error("Invalid attribute name '%s' in compile-time expression"
2434 % attr)
2435 return None
2436 obj = self.arg.compile_time_value(denv)
2437 try:
2438 return getattr(obj, attr)
2439 except Exception, e:
2440 self.compile_time_value_error(e)
2442 def analyse_target_declaration(self, env):
2443 pass
2445 def analyse_target_types(self, env):
2446 self.analyse_types(env, target = 1)
2448 def analyse_types(self, env, target = 0):
2449 if self.analyse_as_cimported_attribute(env, target):
2450 return
2451 if not target and self.analyse_as_unbound_cmethod(env):
2452 return
2453 self.analyse_as_ordinary_attribute(env, target)
2455 def analyse_as_cimported_attribute(self, env, target):
2456 # Try to interpret this as a reference to an imported
2457 # C const, type, var or function. If successful, mutates
2458 # this node into a NameNode and returns 1, otherwise
2459 # returns 0.
2460 module_scope = self.obj.analyse_as_module(env)
2461 if module_scope:
2462 entry = module_scope.lookup_here(self.attribute)
2463 if entry and (
2464 entry.is_cglobal or entry.is_cfunction
2465 or entry.is_type or entry.is_const):
2466 self.mutate_into_name_node(env, entry, target)
2467 return 1
2468 return 0
2470 def analyse_as_unbound_cmethod(self, env):
2471 # Try to interpret this as a reference to an unbound
2472 # C method of an extension type. If successful, mutates
2473 # this node into a NameNode and returns 1, otherwise
2474 # returns 0.
2475 type = self.obj.analyse_as_extension_type(env)
2476 if type:
2477 entry = type.scope.lookup_here(self.attribute)
2478 if entry and entry.is_cmethod:
2479 # Create a temporary entry describing the C method
2480 # as an ordinary function.
2481 ubcm_entry = Symtab.Entry(entry.name,
2482 "%s->%s" % (type.vtabptr_cname, entry.cname),
2483 entry.type)
2484 ubcm_entry.is_cfunction = 1
2485 ubcm_entry.func_cname = entry.func_cname
2486 ubcm_entry.is_unbound_cmethod = 1
2487 self.mutate_into_name_node(env, ubcm_entry, None)
2488 return 1
2489 return 0
2491 def analyse_as_type(self, env):
2492 module_scope = self.obj.analyse_as_module(env)
2493 if module_scope:
2494 return module_scope.lookup_type(self.attribute)
2495 return None
2497 def analyse_as_extension_type(self, env):
2498 # Try to interpret this as a reference to an extension type
2499 # in a cimported module. Returns the extension type, or None.
2500 module_scope = self.obj.analyse_as_module(env)
2501 if module_scope:
2502 entry = module_scope.lookup_here(self.attribute)
2503 if entry and entry.is_type and entry.type.is_extension_type:
2504 return entry.type
2505 return None
2507 def analyse_as_module(self, env):
2508 # Try to interpret this as a reference to a cimported module
2509 # in another cimported module. Returns the module scope, or None.
2510 module_scope = self.obj.analyse_as_module(env)
2511 if module_scope:
2512 entry = module_scope.lookup_here(self.attribute)
2513 if entry and entry.as_module:
2514 return entry.as_module
2515 return None
2517 def mutate_into_name_node(self, env, entry, target):
2518 # Mutate this node into a NameNode and complete the
2519 # analyse_types phase.
2520 self.__class__ = NameNode
2521 self.name = self.attribute
2522 self.entry = entry
2523 del self.obj
2524 del self.attribute
2525 if target:
2526 NameNode.analyse_target_types(self, env)
2527 else:
2528 NameNode.analyse_rvalue_entry(self, env)
2530 def analyse_as_ordinary_attribute(self, env, target):
2531 self.obj.analyse_types(env)
2532 self.analyse_attribute(env)
2533 if self.entry and self.entry.is_cmethod and not self.is_called:
2534 # error(self.pos, "C method can only be called")
2535 pass
2536 ## Reference to C array turns into pointer to first element.
2537 #while self.type.is_array:
2538 # self.type = self.type.element_ptr_type()
2539 if self.is_py_attr:
2540 if not target:
2541 self.is_temp = 1
2542 self.result_ctype = py_object_type
2544 def analyse_attribute(self, env):
2545 # Look up attribute and set self.type and self.member.
2546 self.is_py_attr = 0
2547 self.member = self.attribute
2548 if self.obj.type.is_string:
2549 self.obj = self.obj.coerce_to_pyobject(env)
2550 obj_type = self.obj.type
2551 if obj_type.is_ptr or obj_type.is_array:
2552 obj_type = obj_type.base_type
2553 self.op = "->"
2554 elif obj_type.is_extension_type:
2555 self.op = "->"
2556 else:
2557 self.op = "."
2558 if obj_type.has_attributes:
2559 entry = None
2560 if obj_type.attributes_known():
2561 entry = obj_type.scope.lookup_here(self.attribute)
2562 if entry and entry.is_member:
2563 entry = None
2564 else:
2565 error(self.pos,
2566 "Cannot select attribute of incomplete type '%s'"
2567 % obj_type)
2568 self.type = PyrexTypes.error_type
2569 return
2570 self.entry = entry
2571 if entry:
2572 if obj_type.is_extension_type and entry.name == "__weakref__":
2573 error(self.pos, "Illegal use of special attribute __weakref__")
2574 # methods need the normal attribute lookup
2575 # because they do not have struct entries
2576 if entry.is_variable or entry.is_cmethod:
2577 self.type = entry.type
2578 self.member = entry.cname
2579 return
2580 else:
2581 # If it's not a variable or C method, it must be a Python
2582 # method of an extension type, so we treat it like a Python
2583 # attribute.
2584 pass
2585 # If we get here, the base object is not a struct/union/extension
2586 # type, or it is an extension type and the attribute is either not
2587 # declared or is declared as a Python method. Treat it as a Python
2588 # attribute reference.
2589 self.analyse_as_python_attribute(env)
2591 def analyse_as_python_attribute(self, env):
2592 obj_type = self.obj.type
2593 self.member = self.attribute
2594 if obj_type.is_pyobject:
2595 self.type = py_object_type
2596 self.is_py_attr = 1
2597 self.interned_attr_cname = env.intern_identifier(self.attribute)
2598 self.gil_check(env)
2599 else:
2600 if not obj_type.is_error:
2601 error(self.pos,
2602 "Object of type '%s' has no attribute '%s'" %
2603 (obj_type, self.attribute))
2605 gil_message = "Accessing Python attribute"
2607 def is_simple(self):
2608 if self.obj:
2609 return self.result_in_temp() or self.obj.is_simple()
2610 else:
2611 return NameNode.is_simple(self)
2613 def is_lvalue(self):
2614 if self.obj:
2615 return 1
2616 else:
2617 return NameNode.is_lvalue(self)
2619 def is_ephemeral(self):
2620 if self.obj:
2621 return self.obj.is_ephemeral()
2622 else:
2623 return NameNode.is_ephemeral(self)
2625 def calculate_result_code(self):
2626 #print "AttributeNode.calculate_result_code:", self.member ###
2627 #print "...obj node =", self.obj, "code", self.obj.result() ###
2628 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2629 obj = self.obj
2630 obj_code = obj.result_as(obj.type)
2631 #print "...obj_code =", obj_code ###
2632 if self.entry and self.entry.is_cmethod:
2633 if obj.type.is_extension_type:
2634 return "((struct %s *)%s%s%s)->%s" % (
2635 obj.type.vtabstruct_cname, obj_code, self.op,
2636 obj.type.vtabslot_cname, self.member)
2637 else:
2638 return self.member
2639 else:
2640 return "%s%s%s" % (obj_code, self.op, self.member)
2642 def generate_result_code(self, code):
2643 if self.is_py_attr:
2644 code.putln(
2645 '%s = PyObject_GetAttr(%s, %s); %s' % (
2646 self.result(),
2647 self.obj.py_result(),
2648 self.interned_attr_cname,
2649 code.error_goto_if_null(self.result(), self.pos)))
2650 else:
2651 # result_code contains what is needed, but we may need to insert
2652 # a check and raise an exception
2653 if (self.obj.type.is_extension_type
2654 and self.needs_none_check
2655 and code.globalstate.directives['nonecheck']):
2656 self.put_nonecheck(code)
2658 def generate_assignment_code(self, rhs, code):
2659 self.obj.generate_evaluation_code(code)
2660 if self.is_py_attr:
2661 code.put_error_if_neg(self.pos,
2662 'PyObject_SetAttr(%s, %s, %s)' % (
2663 self.obj.py_result(),
2664 self.interned_attr_cname,
2665 rhs.py_result()))
2666 rhs.generate_disposal_code(code)
2667 else:
2668 if (self.obj.type.is_extension_type
2669 and self.needs_none_check
2670 and code.globalstate.directives['nonecheck']):
2671 self.put_nonecheck(code)
2673 select_code = self.result()
2674 if self.type.is_pyobject:
2675 rhs.make_owned_reference(code)
2676 code.put_decref(select_code, self.ctype())
2677 code.putln(
2678 "%s = %s;" % (
2679 select_code,
2680 rhs.result_as(self.ctype())))
2681 #rhs.result()))
2682 rhs.generate_post_assignment_code(code)
2683 self.obj.generate_disposal_code(code)
2685 def generate_deletion_code(self, code):
2686 self.obj.generate_evaluation_code(code)
2687 if self.is_py_attr:
2688 code.put_error_if_neg(self.pos,
2689 'PyObject_DelAttr(%s, %s)' % (
2690 self.obj.py_result(),
2691 self.interned_attr_cname))
2692 else:
2693 error(self.pos, "Cannot delete C attribute of extension type")
2694 self.obj.generate_disposal_code(code)
2696 def annotate(self, code):
2697 if self.is_py_attr:
2698 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2699 else:
2700 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2702 def put_nonecheck(self, code):
2703 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2704 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2705 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2706 code.putln(code.error_goto(self.pos))
2707 code.putln("}")
2710 #-------------------------------------------------------------------
2711 #
2712 # Constructor nodes
2713 #
2714 #-------------------------------------------------------------------
2716 class SequenceNode(ExprNode):
2717 # Base class for list and tuple constructor nodes.
2718 # Contains common code for performing sequence unpacking.
2719 #
2720 # args [ExprNode]
2721 # iterator ExprNode
2722 # unpacked_items [ExprNode] or None
2723 # coerced_unpacked_items [ExprNode] or None
2725 subexprs = ['args']
2727 is_sequence_constructor = 1
2728 unpacked_items = None
2730 def compile_time_value_list(self, denv):
2731 return [arg.compile_time_value(denv) for arg in self.args]
2733 def analyse_target_declaration(self, env):
2734 for arg in self.args:
2735 arg.analyse_target_declaration(env)
2737 def analyse_types(self, env, skip_children=False):
2738 for i in range(len(self.args)):
2739 arg = self.args[i]
2740 if not skip_children: arg.analyse_types(env)
2741 self.args[i] = arg.coerce_to_pyobject(env)
2742 self.type = py_object_type
2743 self.gil_check(env)
2744 self.is_temp = 1
2746 def analyse_target_types(self, env):
2747 self.iterator = PyTempNode(self.pos, env)
2748 self.unpacked_items = []
2749 self.coerced_unpacked_items = []
2750 for arg in self.args:
2751 arg.analyse_target_types(env)
2752 unpacked_item = PyTempNode(self.pos, env)
2753 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2754 self.unpacked_items.append(unpacked_item)
2755 self.coerced_unpacked_items.append(coerced_unpacked_item)
2756 self.type = py_object_type
2757 env.use_utility_code(unpacking_utility_code)
2759 def allocate_target_temps(self, env, rhs):
2760 self.iterator.allocate_temps(env)
2761 for arg, node in zip(self.args, self.coerced_unpacked_items):
2762 node.allocate_temps(env)
2763 arg.allocate_target_temps(env, None)
2764 #arg.release_target_temp(env)
2765 #node.release_temp(env)
2766 if rhs:
2767 rhs.release_temp(env)
2768 self.iterator.release_temp(env)
2769 for node in self.coerced_unpacked_items:
2770 node.release_temp(env)
2772 # def release_target_temp(self, env):
2773 # #for arg in self.args:
2774 # # arg.release_target_temp(env)
2775 # #for node in self.coerced_unpacked_items:
2776 # # node.release_temp(env)
2777 # self.iterator.release_temp(env)
2779 def generate_result_code(self, code):
2780 self.generate_operation_code(code)
2782 def generate_assignment_code(self, rhs, code):
2783 code.putln(
2784 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2785 rhs.py_result(),
2786 rhs.py_result(),
2787 len(self.args)))
2788 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2789 for i in range(len(self.args)):
2790 item = self.unpacked_items[i]
2791 code.put(
2792 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
2793 item.result(),
2794 i))
2795 code.put_incref(item.result(), item.ctype())
2796 value_node = self.coerced_unpacked_items[i]
2797 value_node.generate_evaluation_code(code)
2798 rhs.generate_disposal_code(code)
2800 code.putln("} else {")
2802 code.putln(
2803 "%s = PyObject_GetIter(%s); %s" % (
2804 self.iterator.result(),
2805 rhs.py_result(),
2806 code.error_goto_if_null(self.iterator.result(), self.pos)))
2807 rhs.generate_disposal_code(code)
2808 for i in range(len(self.args)):
2809 item = self.unpacked_items[i]
2810 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2811 self.iterator.py_result(), i)
2812 code.putln(
2813 "%s = %s; %s" % (
2814 item.result(),
2815 typecast(item.ctype(), py_object_type, unpack_code),
2816 code.error_goto_if_null(item.result(), self.pos)))
2817 value_node = self.coerced_unpacked_items[i]
2818 value_node.generate_evaluation_code(code)
2819 code.put_error_if_neg(self.pos,
2820 "__Pyx_EndUnpack(%s)" % (
2821 self.iterator.py_result()))
2822 if debug_disposal_code:
2823 print("UnpackNode.generate_assignment_code:")
2824 print("...generating disposal code for %s" % self.iterator)
2825 self.iterator.generate_disposal_code(code)
2827 code.putln("}")
2828 for i in range(len(self.args)):
2829 self.args[i].generate_assignment_code(
2830 self.coerced_unpacked_items[i], code)
2832 def annotate(self, code):
2833 for arg in self.args:
2834 arg.annotate(code)
2835 if self.unpacked_items:
2836 for arg in self.unpacked_items:
2837 arg.annotate(code)
2838 for arg in self.coerced_unpacked_items:
2839 arg.annotate(code)
2842 class TupleNode(SequenceNode):
2843 # Tuple constructor.
2845 gil_message = "Constructing Python tuple"
2847 def analyse_types(self, env, skip_children=False):
2848 if len(self.args) == 0:
2849 self.is_temp = 0
2850 self.is_literal = 1
2851 else:
2852 SequenceNode.analyse_types(self, env, skip_children)
2853 self.type = tuple_type
2855 def calculate_result_code(self):
2856 if len(self.args) > 0:
2857 error(self.pos, "Positive length tuples must be constructed.")
2858 else:
2859 return Naming.empty_tuple
2861 def compile_time_value(self, denv):
2862 values = self.compile_time_value_list(denv)
2863 try:
2864 return tuple(values)
2865 except Exception, e:
2866 self.compile_time_value_error(e)
2868 def generate_operation_code(self, code):
2869 if len(self.args) == 0:
2870 # result_code is Naming.empty_tuple
2871 return
2872 code.putln(
2873 "%s = PyTuple_New(%s); %s" % (
2874 self.result(),
2875 len(self.args),
2876 code.error_goto_if_null(self.result(), self.pos)))
2877 for i in range(len(self.args)):
2878 arg = self.args[i]
2879 if not arg.result_in_temp():
2880 code.put_incref(arg.result(), arg.ctype())
2881 code.putln(
2882 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2883 self.result(),
2884 i,
2885 arg.py_result()))
2887 def generate_subexpr_disposal_code(self, code):
2888 # We call generate_post_assignment_code here instead
2889 # of generate_disposal_code, because values were stored
2890 # in the tuple using a reference-stealing operation.
2891 for arg in self.args:
2892 arg.generate_post_assignment_code(code)
2895 class ListNode(SequenceNode):
2896 # List constructor.
2898 # obj_conversion_errors [PyrexError] used internally
2899 # orignial_args [ExprNode] used internally
2901 gil_message = "Constructing Python list"
2903 def analyse_expressions(self, env):
2904 ExprNode.analyse_expressions(self, env)
2905 self.coerce_to_pyobject(env)
2907 def analyse_types(self, env):
2908 hold_errors()
2909 self.original_args = list(self.args)
2910 SequenceNode.analyse_types(self, env)
2911 self.type = list_type
2912 self.obj_conversion_errors = held_errors()
2913 release_errors(ignore=True)
2915 def coerce_to(self, dst_type, env):
2916 if dst_type.is_pyobject:
2917 for err in self.obj_conversion_errors:
2918 report_error(err)
2919 self.obj_conversion_errors = []
2920 if not self.type.subtype_of(dst_type):
2921 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2922 elif dst_type.is_ptr:
2923 base_type = dst_type.base_type
2924 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
2925 for i in range(len(self.original_args)):
2926 arg = self.args[i]
2927 if isinstance(arg, CoerceToPyTypeNode):
2928 arg = arg.arg
2929 self.args[i] = arg.coerce_to(base_type, env)
2930 elif dst_type.is_struct:
2931 if len(self.args) > len(dst_type.scope.var_entries):
2932 error(self.pos, "Too may members for '%s'" % dst_type)
2933 else:
2934 if len(self.args) < len(dst_type.scope.var_entries):
2935 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
2936 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
2937 if isinstance(arg, CoerceToPyTypeNode):
2938 arg = arg.arg
2939 self.args[i] = arg.coerce_to(member.type, env)
2940 self.type = dst_type
2941 else:
2942 self.type = error_type
2943 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2944 return self
2946 def release_temp(self, env):
2947 if self.type.is_array:
2948 # To be valid C++, we must allocate the memory on the stack
2949 # manually and be sure not to reuse it for something else.
2950 pass
2951 else:
2952 SequenceNode.release_temp(self, env)
2954 def compile_time_value(self, denv):
2955 return self.compile_time_value_list(denv)
2957 def generate_operation_code(self, code):
2958 if self.type.is_pyobject:
2959 for err in self.obj_conversion_errors:
2960 report_error(err)
2961 code.putln("%s = PyList_New(%s); %s" %
2962 (self.result(),
2963 len(self.args),
2964 code.error_goto_if_null(self.result(), self.pos)))
2965 for i in range(len(self.args)):
2966 arg = self.args[i]
2967 #if not arg.is_temp:
2968 if not arg.result_in_temp():
2969 code.put_incref(arg.result(), arg.ctype())
2970 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2971 (self.result(),
2972 i,
2973 arg.py_result()))
2974 elif self.type.is_array:
2975 for i, arg in enumerate(self.args):
2976 code.putln("%s[%s] = %s;" % (
2977 self.result(),
2978 i,
2979 arg.result()))
2980 elif self.type.is_struct:
2981 for arg, member in zip(self.args, self.type.scope.var_entries):
2982 code.putln("%s.%s = %s;" % (
2983 self.result(),
2984 member.cname,
2985 arg.result()))
2986 else:
2987 raise InternalError("List type never specified")
2989 def generate_subexpr_disposal_code(self, code):
2990 # We call generate_post_assignment_code here instead
2991 # of generate_disposal_code, because values were stored
2992 # in the list using a reference-stealing operation.
2993 for arg in self.args:
2994 arg.generate_post_assignment_code(code)
2997 class ListComprehensionNode(SequenceNode):
2999 subexprs = []
3000 is_sequence_constructor = 0 # not unpackable
3002 child_attrs = ["loop", "append"]
3004 def analyse_types(self, env):
3005 self.type = list_type
3006 self.is_temp = 1
3007 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3009 def allocate_temps(self, env, result = None):
3010 if debug_temp_alloc:
3011 print("%s Allocating temps" % self)
3012 self.allocate_temp(env, result)
3013 self.loop.analyse_declarations(env)
3014 self.loop.analyse_expressions(env)
3016 def generate_operation_code(self, code):
3017 code.putln("%s = PyList_New(%s); %s" %
3018 (self.result(),
3019 0,
3020 code.error_goto_if_null(self.result(), self.pos)))
3021 self.loop.generate_execution_code(code)
3023 def annotate(self, code):
3024 self.loop.annotate(code)
3027 class ListComprehensionAppendNode(ExprNode):
3029 # Need to be careful to avoid infinite recursion:
3030 # target must not be in child_attrs/subexprs
3031 subexprs = ['expr']
3033 def analyse_types(self, env):
3034 self.expr.analyse_types(env)
3035 if self.expr.type != py_object_type:
3036 self.expr = self.expr.coerce_to_pyobject(env)
3037 self.type = PyrexTypes.c_int_type
3038 self.is_temp = 1
3040 def generate_result_code(self, code):
3041 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
3042 (self.result(),
3043 self.target.result(),
3044 self.expr.result(),
3045 code.error_goto_if(self.result(), self.pos)))
3048 class DictNode(ExprNode):
3049 # Dictionary constructor.
3050 #
3051 # key_value_pairs [DictItemNode]
3052 #
3053 # obj_conversion_errors [PyrexError] used internally
3055 subexprs = ['key_value_pairs']
3057 def compile_time_value(self, denv):
3058 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3059 for item in self.key_value_pairs]
3060 try:
3061 return dict(pairs)
3062 except Exception, e:
3063 self.compile_time_value_error(e)
3065 def analyse_types(self, env):
3066 hold_errors()
3067 self.type = dict_type
3068 for item in self.key_value_pairs:
3069 item.analyse_types(env)
3070 self.gil_check(env)
3071 self.obj_conversion_errors = held_errors()
3072 release_errors(ignore=True)
3073 self.is_temp = 1
3075 def coerce_to(self, dst_type, env):
3076 if dst_type.is_pyobject:
3077 self.release_errors()
3078 if not self.type.subtype_of(dst_type):
3079 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3080 elif dst_type.is_struct_or_union:
3081 self.type = dst_type
3082 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3083 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3084 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3085 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3086 for item in self.key_value_pairs:
3087 if isinstance(item.key, CoerceToPyTypeNode):
3088 item.key = item.key.arg
3089 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3090 error(item.key.pos, "Invalid struct field identifier")
3091 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3092 else:
3093 member = dst_type.scope.lookup_here(item.key.value)
3094 if not member:
3095 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3096 else:
3097 value = item.value
3098 if isinstance(value, CoerceToPyTypeNode):
3099 value = value.arg
3100 item.value = value.coerce_to(member.type, env)
3101 else:
3102 self.type = error_type
3103 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3104 return self
3106 def release_errors(self):
3107 for err in self.obj_conversion_errors:
3108 report_error(err)
3109 self.obj_conversion_errors = []
3111 gil_message = "Constructing Python dict"
3113 def allocate_temps(self, env, result = None):
3114 # Custom method used here because key-value
3115 # pairs are evaluated and used one at a time.
3116 self.allocate_temp(env, result)
3117 for item in self.key_value_pairs:
3118 item.key.allocate_temps(env)
3119 item.value.allocate_temps(env)
3120 item.key.release_temp(env)
3121 item.value.release_temp(env)
3123 def generate_evaluation_code(self, code):
3124 # Custom method used here because key-value
3125 # pairs are evaluated and used one at a time.
3126 if self.type.is_pyobject:
3127 self.release_errors()
3128 code.putln(
3129 "%s = PyDict_New(); %s" % (
3130 self.result(),
3131 code.error_goto_if_null(self.result(), self.pos)))
3132 for item in self.key_value_pairs:
3133 item.generate_evaluation_code(code)
3134 if self.type.is_pyobject:
3135 code.put_error_if_neg(self.pos,
3136 "PyDict_SetItem(%s, %s, %s)" % (
3137 self.result(),
3138 item.key.py_result(),
3139 item.value.py_result()))
3140 else:
3141 code.putln("%s.%s = %s;" % (
3142 self.result(),
3143 item.key.value,
3144 item.value.result()))
3145 item.generate_disposal_code(code)
3147 def annotate(self, code):
3148 for item in self.key_value_pairs:
3149 item.annotate(code)
3151 class DictItemNode(ExprNode):
3152 # Represents a single item in a DictNode
3153 #
3154 # key ExprNode
3155 # value ExprNode
3156 subexprs = ['key', 'value']
3158 def analyse_types(self, env):
3159 self.key.analyse_types(env)
3160 self.value.analyse_types(env)
3161 self.key = self.key.coerce_to_pyobject(env)
3162 self.value = self.value.coerce_to_pyobject(env)
3164 def generate_evaluation_code(self, code):
3165 self.key.generate_evaluation_code(code)
3166 self.value.generate_evaluation_code(code)
3168 def generate_disposal_code(self, code):
3169 self.key.generate_disposal_code(code)
3170 self.value.generate_disposal_code(code)
3172 def __iter__(self):
3173 return iter([self.key, self.value])
3176 class ClassNode(ExprNode):
3177 # Helper class used in the implementation of Python
3178 # class definitions. Constructs a class object given
3179 # a name, tuple of bases and class dictionary.
3180 #
3181 # name EncodedString Name of the class
3182 # cname string Class name as a Python string
3183 # bases ExprNode Base class tuple
3184 # dict ExprNode Class dict (not owned by this node)
3185 # doc ExprNode or None Doc string
3186 # module_name string Name of defining module
3188 subexprs = ['bases', 'doc']
3190 def analyse_types(self, env):
3191 self.cname = env.intern_identifier(self.name)
3192 self.bases.analyse_types(env)
3193 if self.doc:
3194 self.doc.analyse_types(env)
3195 self.doc = self.doc.coerce_to_pyobject(env)
3196 self.module_name = env.global_scope().qualified_name
3197 self.type = py_object_type
3198 self.gil_check(env)
3199 self.is_temp = 1
3200 env.use_utility_code(create_class_utility_code);
3202 gil_message = "Constructing Python class"
3204 def generate_result_code(self, code):
3205 if self.doc:
3206 code.put_error_if_neg(self.pos,
3207 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3208 self.dict.py_result(),
3209 self.doc.py_result()))
3210 code.putln(
3211 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3212 self.result(),
3213 self.bases.py_result(),
3214 self.dict.py_result(),
3215 self.cname,
3216 self.module_name,
3217 code.error_goto_if_null(self.result(), self.pos)))
3220 class UnboundMethodNode(ExprNode):
3221 # Helper class used in the implementation of Python
3222 # class definitions. Constructs an unbound method
3223 # object from a class and a function.
3224 #
3225 # class_cname string C var holding the class object
3226 # function ExprNode Function object
3228 subexprs = ['function']
3230 def analyse_types(self, env):
3231 self.function.analyse_types(env)
3232 self.type = py_object_type
3233 self.gil_check(env)
3234 self.is_temp = 1
3236 gil_message = "Constructing an unbound method"
3238 def generate_result_code(self, code):
3239 code.putln(
3240 "%s = PyMethod_New(%s, 0, %s); %s" % (
3241 self.result(),
3242 self.function.py_result(),
3243 self.class_cname,
3244 code.error_goto_if_null(self.result(), self.pos)))
3247 class PyCFunctionNode(AtomicExprNode):
3248 # Helper class used in the implementation of Python
3249 # class definitions. Constructs a PyCFunction object
3250 # from a PyMethodDef struct.
3251 #
3252 # pymethdef_cname string PyMethodDef structure
3254 def analyse_types(self, env):
3255 self.type = py_object_type
3256 self.gil_check(env)
3257 self.is_temp = 1
3259 gil_message = "Constructing Python function"
3261 def generate_result_code(self, code):
3262 code.putln(
3263 "%s = PyCFunction_New(&%s, 0); %s" % (
3264 self.result(),
3265 self.pymethdef_cname,
3266 code.error_goto_if_null(self.result(), self.pos)))
3268 #-------------------------------------------------------------------
3269 #
3270 # Unary operator nodes
3271 #
3272 #-------------------------------------------------------------------
3274 compile_time_unary_operators = {
3275 'not': operator.not_,
3276 '~': operator.inv,
3277 '-': operator.neg,
3278 '+': operator.pos,
3279 }
3281 class UnopNode(ExprNode):
3282 # operator string
3283 # operand ExprNode
3284 #
3285 # Processing during analyse_expressions phase:
3286 #
3287 # analyse_c_operation
3288 # Called when the operand is not a pyobject.
3289 # - Check operand type and coerce if needed.
3290 # - Determine result type and result code fragment.
3291 # - Allocate temporary for result if needed.
3293 subexprs = ['operand']
3295 def compile_time_value(self, denv):
3296 func = compile_time_unary_operators.get(self.operator)
3297 if not func:
3298 error(self.pos,
3299 "Unary '%s' not supported in compile-time expression"
3300 % self.operator)
3301 operand = self.operand.compile_time_value(denv)
3302 try:
3303 return func(operand)
3304 except Exception, e:
3305 self.compile_time_value_error(e)
3307 def analyse_types(self, env):
3308 self.operand.analyse_types(env)
3309 if self.is_py_operation():
3310 self.coerce_operand_to_pyobject(env)
3311 self.type = py_object_type
3312 self.gil_check(env)
3313 self.is_temp = 1
3314 else:
3315 self.analyse_c_operation(env)
3317 def check_const(self):
3318 self.operand.check_const()
3320 def is_py_operation(self):
3321 return self.operand.type.is_pyobject
3323 def coerce_operand_to_pyobject(self, env):
3324 self.operand = self.operand.coerce_to_pyobject(env)
3326 def generate_result_code(self, code):
3327 if self.operand.type.is_pyobject:
3328 self.generate_py_operation_code(code)
3329 else:
3330 if self.is_temp:
3331 self.generate_c_operation_code(code)
3333 def generate_py_operation_code(self, code):
3334 function = self.py_operation_function()
3335 code.putln(
3336 "%s = %s(%s); %s" % (
3337 self.result(),
3338 function,
3339 self.operand.py_result(),
3340 code.error_goto_if_null(self.result(), self.pos)))
3342 def type_error(self):
3343 if not self.operand.type.is_error:
3344 error(self.pos, "Invalid operand type for '%s' (%s)" %
3345 (self.operator, self.operand.type))
3346 self.type = PyrexTypes.error_type
3349 class NotNode(ExprNode):
3350 # 'not' operator
3351 #
3352 # operand ExprNode
3354 def compile_time_value(self, denv):
3355 operand = self.operand.compile_time_value(denv)
3356 try:
3357 return not operand
3358 except Exception, e:
3359 self.compile_time_value_error(e)
3361 subexprs = ['operand']
3363 def analyse_types(self, env):
3364 self.operand.analyse_types(env)
3365 self.operand = self.operand.coerce_to_boolean(env)
3366 self.type = PyrexTypes.c_bint_type
3368 def calculate_result_code(self):
3369 return "(!%s)" % self.operand.result()
3371 def generate_result_code(self, code):
3372 pass
3375 class UnaryPlusNode(UnopNode):
3376 # unary '+' operator
3378 operator = '+'
3380 def analyse_c_operation(self, env):
3381 self.type = self.operand.type
3383 def py_operation_function(self):
3384 return "PyNumber_Positive"
3386 def calculate_result_code(self):
3387 return self.operand.result()
3390 class UnaryMinusNode(UnopNode):
3391 # unary '-' operator
3393 operator = '-'
3395 def analyse_c_operation(self, env):
3396 if self.operand.type.is_numeric:
3397 self.type = self.operand.type
3398 else:
3399 self.type_error()
3401 def py_operation_function(self):
3402 return "PyNumber_Negative"
3404 def calculate_result_code(self):
3405 return "(-%s)" % self.operand.result()
3408 class TildeNode(UnopNode):
3409 # unary '~' operator
3411 def analyse_c_operation(self, env):
3412 if self.operand.type.is_int:
3413 self.type = self.operand.type
3414 else:
3415 self.type_error()
3417 def py_operation_function(self):
3418 return "PyNumber_Invert"
3420 def calculate_result_code(self):
3421 return "(~%s)" % self.operand.result()
3424 class AmpersandNode(ExprNode):
3425 # The C address-of operator.
3426 #
3427 # operand ExprNode
3429 subexprs = ['operand']
3431 def analyse_types(self, env):
3432 self.operand.analyse_types(env)
3433 argtype = self.operand.type
3434 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3435 self.error("Taking address of non-lvalue")
3436 return
3437 if argtype.is_pyobject:
3438 self.error("Cannot take address of Python variable")
3439 return
3440 self.type = PyrexTypes.c_ptr_type(argtype)
3442 def check_const(self):
3443 self.operand.check_const_addr()
3445 def error(self, mess):
3446 error(self.pos, mess)
3447 self.type = PyrexTypes.error_type
3448 self.result_code = "<error>"
3450 def calculate_result_code(self):
3451 return "(&%s)" % self.operand.result()
3453 def generate_result_code(self, code):
3454 pass
3457 unop_node_classes = {
3458 "+": UnaryPlusNode,
3459 "-": UnaryMinusNode,
3460 "~": TildeNode,
3461 }
3463 def unop_node(pos, operator, operand):
3464 # Construct unnop node of appropriate class for
3465 # given operator.
3466 if isinstance(operand, IntNode) and operator == '-':
3467 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3468 elif isinstance(operand, UnopNode) and operand.operator == operator:
3469 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3470 return unop_node_classes[operator](pos,
3471 operator = operator,
3472 operand = operand)
3475 class TypecastNode(ExprNode):
3476 # C type cast
3477 #
3478 # operand ExprNode
3479 # base_type CBaseTypeNode
3480 # declarator CDeclaratorNode
3481 #
3482 # If used from a transform, one can if wanted specify the attribute
3483 # "type" directly and leave base_type and declarator to None
3485 subexprs = ['operand']
3486 base_type = declarator = type = None
3488 def analyse_types(self, env):
3489 if self.type is None:
3490 base_type = self.base_type.analyse(env)
3491 _, self.type = self.declarator.analyse(base_type, env)
3492 if self.type.is_cfunction:
3493 error(self.pos,
3494 "Cannot cast to a function type")
3495 self.type = PyrexTypes.error_type
3496 self.operand.analyse_types(env)
3497 to_py = self.type.is_pyobject
3498 from_py = self.operand.type.is_pyobject
3499 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3500 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3501 if to_py and not from_py:
3502 if (self.operand.type.to_py_function and
3503 self.operand.type.create_convert_utility_code(env)):
3504 self.result_ctype = py_object_type
3505 self.operand = self.operand.coerce_to_pyobject(env)
3506 else:
3507 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3508 self.operand = self.operand.coerce_to_simple(env)
3509 elif from_py and not to_py:
3510 if self.type.from_py_function:
3511 self.operand = self.operand.coerce_to(self.type, env)
3512 else:
3513 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3514 elif from_py and to_py:
3515 if self.typecheck and self.type.is_extension_type:
3516 self.operand = PyTypeTestNode(self.operand, self.type, env)
3518 def check_const(self):
3519 self.operand.check_const()
3521 def calculate_result_code(self):
3522 opnd = self.operand
3523 return self.type.cast_code(opnd.result())
3525 def result_as(self, type):
3526 if self.type.is_pyobject and not self.is_temp:
3527 # Optimise away some unnecessary casting
3528 return self.operand.result_as(type)
3529 else:
3530 return ExprNode.result_as(self, type)
3532 def generate_result_code(self, code):
3533 if self.is_temp:
3534 code.putln(
3535 "%s = (PyObject *)%s;" % (
3536 self.result(),
3537 self.operand.result()))
3538 code.put_incref(self.result(), self.ctype())
3541 class SizeofNode(ExprNode):
3542 # Abstract base class for sizeof(x) expression nodes.
3544 type = PyrexTypes.c_int_type
3546 def check_const(self):
3547 pass
3549 def generate_result_code(self, code):
3550 pass
3553 class SizeofTypeNode(SizeofNode):
3554 # C sizeof function applied to a type
3555 #
3556 # base_type CBaseTypeNode
3557 # declarator CDeclaratorNode
3559 subexprs = []
3560 arg_type = None
3562 def analyse_types(self, env):
3563 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3564 # this could be better handled by more uniformly treating types as runtime-available objects
3565 if 0 and self.base_type.module_path:
3566 path = self.base_type.module_path
3567 obj = env.lookup(path[0])
3568 if obj.as_module is None:
3569 operand = NameNode(pos=self.pos, name=path[0])
3570 for attr in path[1:]:
3571 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3572 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3573 self.operand = operand
3574 self.__class__ = SizeofVarNode
3575 self.analyse_types(env)
3576 return
3577 if self.arg_type is None:
3578 base_type = self.base_type.analyse(env)
3579 _, arg_type = self.declarator.analyse(base_type, env)
3580 self.arg_type = arg_type
3581 self.check_type()
3583 def check_type(self):
3584 arg_type = self.arg_type
3585 if arg_type.is_pyobject and not arg_type.is_extension_type:
3586 error(self.pos, "Cannot take sizeof Python object")
3587 elif arg_type.is_void:
3588 error(self.pos, "Cannot take sizeof void")
3589 elif not arg_type.is_complete():
3590 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3592 def calculate_result_code(self):
3593 if self.arg_type.is_extension_type:
3594 # the size of the pointer is boring
3595 # we want the size of the actual struct
3596 arg_code = self.arg_type.declaration_code("", deref=1)
3597 else:
3598 arg_code = self.arg_type.declaration_code("")
3599 return "(sizeof(%s))" % arg_code
3602 class SizeofVarNode(SizeofNode):
3603 # C sizeof function applied to a variable
3604 #
3605 # operand ExprNode
3607 subexprs = ['operand']
3609 def analyse_types(self, env):
3610 # We may actually be looking at a type rather than a variable...
3611 # If we are, traditional analysis would fail...
3612 operand_as_type = self.operand.analyse_as_type(env)
3613 if operand_as_type:
3614 self.arg_type = operand_as_type
3615 self.__class__ = SizeofTypeNode
3616 self.check_type()
3617 else:
3618 self.operand.analyse_types(env)
3620 def calculate_result_code(self):
3621 return "(sizeof(%s))" % self.operand.result()
3623 def generate_result_code(self, code):
3624 pass
3627 #-------------------------------------------------------------------
3628 #
3629 # Binary operator nodes
3630 #
3631 #-------------------------------------------------------------------
3633 def _not_in(x, seq):
3634 return x not in seq
3636 compile_time_binary_operators = {
3637 '<': operator.lt,
3638 '<=': operator.le,
3639 '==': operator.eq,
3640 '!=': operator.ne,
3641 '>=': operator.ge,
3642 '>': operator.gt,
3643 'is': operator.is_,
3644 'is_not': operator.is_not,
3645 '+': operator.add,
3646 '&': operator.and_,
3647 '/': operator.div,
3648 '//': operator.floordiv,
3649 '<<': operator.lshift,
3650 '%': operator.mod,
3651 '*': operator.mul,
3652 '|': operator.or_,
3653 '**': operator.pow,
3654 '>>': operator.rshift,
3655 '-': operator.sub,
3656 #'/': operator.truediv,
3657 '^': operator.xor,
3658 'in': operator.contains,
3659 'not_in': _not_in,
3660 }
3662 def get_compile_time_binop(node):
3663 func = compile_time_binary_operators.get(node.operator)
3664 if not func:
3665 error(node.pos,
3666 "Binary '%s' not supported in compile-time expression"
3667 % node.operator)
3668 return func
3670 class BinopNode(NewTempExprNode):
3671 # operator string
3672 # operand1 ExprNode
3673 # operand2 ExprNode
3674 #
3675 # Processing during analyse_expressions phase:
3676 #
3677 # analyse_c_operation
3678 # Called when neither operand is a pyobject.
3679 # - Check operand types and coerce if needed.
3680 # - Determine result type and result code fragment.
3681 # - Allocate temporary for result if needed.
3683 subexprs = ['operand1', 'operand2']
3685 def compile_time_value(self, denv):
3686 func = get_compile_time_binop(self)
3687 operand1 = self.operand1.compile_time_value(denv)
3688 operand2 = self.operand2.compile_time_value(denv)
3689 try:
3690 return func(operand1, operand2)
3691 except Exception, e:
3692 self.compile_time_value_error(e)
3694 def analyse_types(self, env):
3695 self.operand1.analyse_types(env)
3696 self.operand2.analyse_types(env)
3697 if self.is_py_operation():
3698 self.coerce_operands_to_pyobjects(env)
3699 self.type = py_object_type
3700 self.gil_check(env)
3701 self.is_temp = 1
3702 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3703 self.operand1 = self.operand1.coerce_to_temp(env)
3704 else:
3705 self.analyse_c_operation(env)
3707 def is_py_operation(self):
3708 return (self.operand1.type.is_pyobject
3709 or self.operand2.type.is_pyobject)
3711 def coerce_operands_to_pyobjects(self, env):
3712 self.operand1 = self.operand1.coerce_to_pyobject(env)
3713 self.operand2 = self.operand2.coerce_to_pyobject(env)
3715 def check_const(self):
3716 self.operand1.check_const()
3717 self.operand2.check_const()
3719 def generate_result_code(self, code):
3720 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3721 if self.operand1.type.is_pyobject:
3722 function = self.py_operation_function()
3723 if function == "PyNumber_Power":
3724 extra_args = ", Py_None"
3725 else:
3726 extra_args = ""
3727 code.putln(
3728 "%s = %s(%s, %s%s); %s" % (
3729 self.result(),
3730 function,
3731 self.operand1.py_result(),
3732 self.operand2.py_result(),
3733 extra_args,
3734 code.error_goto_if_null(self.result(), self.pos)))
3735 else:
3736 if self.is_temp:
3737 self.generate_c_operation_code(code)
3739 def type_error(self):
3740 if not (self.operand1.type.is_error
3741 or self.operand2.type.is_error):
3742 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3743 (self.operator, self.operand1.type,
3744 self.operand2.type))
3745 self.type = PyrexTypes.error_type
3748 class NumBinopNode(BinopNode):
3749 # Binary operation taking numeric arguments.
3751 def analyse_c_operation(self, env):
3752 type1 = self.operand1.type
3753 type2 = self.operand2.type
3754 if self.operator == "**" and type1.is_int and type2.is_int:
3755 error(self.pos, "** with two C int types is ambiguous")
3756 self.type = error_type
3757 return
3758 self.type = self.compute_c_result_type(type1, type2)
3759 if not self.type:
3760 self.type_error()
3762 def compute_c_result_type(self, type1, type2):
3763 if self.c_types_okay(type1, type2):
3764 return PyrexTypes.widest_numeric_type(type1, type2)
3765 else:
3766 return None
3768 def c_types_okay(self, type1, type2):
3769 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3770 return (type1.is_numeric or type1.is_enum) \
3771 and (type2.is_numeric or type2.is_enum)
3773 def calculate_result_code(self):
3774 return "(%s %s %s)" % (
3775 self.operand1.result(),
3776 self.operator,
3777 self.operand2.result())
3779 def py_operation_function(self):
3780 return self.py_functions[self.operator]
3782 py_functions = {
3783 "|": "PyNumber_Or",
3784 "^": "PyNumber_Xor",
3785 "&": "PyNumber_And",
3786 "<<": "PyNumber_Lshift",
3787 ">>": "PyNumber_Rshift",
3788 "+": "PyNumber_Add",
3789 "-": "PyNumber_Subtract",
3790 "*": "PyNumber_Multiply",
3791 "/": "__Pyx_PyNumber_Divide",
3792 "//": "PyNumber_FloorDivide",
3793 "%": "PyNumber_Remainder",
3794 "**": "PyNumber_Power"
3795 }
3798 class IntBinopNode(NumBinopNode):
3799 # Binary operation taking integer arguments.
3801 def c_types_okay(self, type1, type2):
3802 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3803 return (type1.is_int or type1.is_enum) \
3804 and (type2.is_int or type2.is_enum)
3807 class AddNode(NumBinopNode):
3808 # '+' operator.
3810 def is_py_operation(self):
3811 if self.operand1.type.is_string \
3812 and self.operand2.type.is_string:
3813 return 1
3814 else:
3815 return NumBinopNode.is_py_operation(self)
3817 def compute_c_result_type(self, type1, type2):
3818 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3819 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3820 return type1
3821 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3822 return type2
3823 else:
3824 return NumBinopNode.compute_c_result_type(
3825 self, type1, type2)
3828 class SubNode(NumBinopNode):
3829 # '-' operator.
3831 def compute_c_result_type(self, type1, type2):
3832 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3833 return type1
3834 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3835 return PyrexTypes.c_int_type
3836 else:
3837 return NumBinopNode.compute_c_result_type(
3838 self, type1, type2)
3841 class MulNode(NumBinopNode):
3842 # '*' operator.
3844 def is_py_operation(self):
3845 type1 = self.operand1.type
3846 type2 = self.operand2.type
3847 if (type1.is_string and type2.is_int) \
3848 or (type2.is_string and type1.is_int):
3849 return 1
3850 else:
3851 return NumBinopNode.is_py_operation(self)
3854 class FloorDivNode(NumBinopNode):
3855 # '//' operator.
3857 def calculate_result_code(self):
3858 return "(%s %s %s)" % (
3859 self.operand1.result(),
3860 "/", # c division is by default floor-div
3861 self.operand2.result())
3864 class ModNode(NumBinopNode):
3865 # '%' operator.
3867 def is_py_operation(self):
3868 return (self.operand1.type.is_string
3869 or self.operand2.type.is_string
3870 or NumBinopNode.is_py_operation(self))
3872 def calculate_result_code(self):
3873 if self.operand1.type.is_float or self.operand2.type.is_float:
3874 return "fmod(%s, %s)" % (
3875 self.operand1.result(),
3876 self.operand2.result())
3877 else:
3878 return "(%s %% %s)" % (
3879 self.operand1.result(),
3880 self.operand2.result())
3882 class PowNode(NumBinopNode):
3883 # '**' operator.
3885 def compute_c_result_type(self, type1, type2):
3886 if self.c_types_okay(type1, type2):
3887 return PyrexTypes.c_double_type
3888 else:
3889 return None
3891 def c_types_okay(self, type1, type2):
3892 return (type1.is_float or type2.is_float) and \
3893 NumBinopNode.c_types_okay(self, type1, type2)
3895 def type_error(self):
3896 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3897 if self.operand1.type.is_int and self.operand2.type.is_int:
3898 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3899 (self.operator, self.operand1.type, self.operand2.type))
3900 else:
3901 NumBinopNode.type_error(self)
3902 self.type = PyrexTypes.error_type
3904 def calculate_result_code(self):
3905 return "pow(%s, %s)" % (
3906 self.operand1.result(), self.operand2.result())
3909 class BoolBinopNode(ExprNode):
3910 # Short-circuiting boolean operation.
3911 #
3912 # operator string
3913 # operand1 ExprNode
3914 # operand2 ExprNode
3915 # temp_bool ExprNode used internally
3917 temp_bool = None
3919 subexprs = ['operand1', 'operand2', 'temp_bool']
3921 def compile_time_value(self, denv):
3922 if self.operator == 'and':
3923 return self.operand1.compile_time_value(denv) \
3924 and self.operand2.compile_time_value(denv)
3925 else:
3926 return self.operand1.compile_time_value(denv) \
3927 or self.operand2.compile_time_value(denv)
3929 def coerce_to_boolean(self, env):
3930 self.operand1 = self.operand1.coerce_to_boolean(env)
3931 self.operand2 = self.operand2.coerce_to_boolean(env)
3932 self.type = PyrexTypes.c_bint_type
3933 return self
3935 def analyse_types(self, env):
3936 self.operand1.analyse_types(env)
3937 self.operand2.analyse_types(env)
3938 if self.operand1.type.is_pyobject or \
3939 self.operand2.type.is_pyobject:
3940 self.operand1 = self.operand1.coerce_to_pyobject(env)
3941 self.operand2 = self.operand2.coerce_to_pyobject(env)
3942 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3943 self.type = py_object_type
3944 self.gil_check(env)
3945 else:
3946 self.operand1 = self.operand1.coerce_to_boolean(env)
3947 self.operand2 = self.operand2.coerce_to_boolean(env)
3948 self.type = PyrexTypes.c_bint_type
3949 # For what we're about to do, it's vital that
3950 # both operands be temp nodes.
3951 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3952 self.operand2 = self.operand2.coerce_to_temp(env)
3953 self.is_temp = 1
3955 gil_message = "Truth-testing Python object"
3957 def allocate_temps(self, env, result_code = None):
3958 # We don't need both operands at the same time, and
3959 # one of the operands will also be our result. So we
3960 # use an allocation strategy here which results in
3961 # this node and both its operands sharing the same
3962 # result variable. This allows us to avoid some
3963 # assignments and increfs/decrefs that would otherwise
3964 # be necessary.
3965 self.allocate_temp(env, result_code)
3966 self.operand1.allocate_temps(env, self.result())
3967 if self.temp_bool:
3968 self.temp_bool.allocate_temp(env)
3969 self.temp_bool.release_temp(env)
3970 self.operand2.allocate_temps(env, self.result())
3971 # We haven't called release_temp on either operand,
3972 # because although they are temp nodes, they don't own
3973 # their result variable. And because they are temp
3974 # nodes, any temps in their subnodes will have been
3975 # released before their allocate_temps returned.
3976 # Therefore, they contain no temp vars that need to
3977 # be released.
3979 def check_const(self):
3980 self.operand1.check_const()
3981 self.operand2.check_const()
3983 def calculate_result_code(self):
3984 return "(%s %s %s)" % (
3985 self.operand1.result(),
3986 self.py_to_c_op[self.operator],
3987 self.operand2.result())
3989 py_to_c_op = {'and': "&&", 'or': "||"}
3991 def generate_evaluation_code(self, code):
3992 self.operand1.generate_evaluation_code(code)
3993 test_result = self.generate_operand1_test(code)
3994 if self.operator == 'and':
3995 sense = ""
3996 else:
3997 sense = "!"
3998 code.putln(
3999 "if (%s%s) {" % (
4000 sense,
4001 test_result))
4002 self.operand1.generate_disposal_code(code)
4003 self.operand2.generate_evaluation_code(code)
4004 code.putln(
4005 "}")
4007 def generate_operand1_test(self, code):
4008 # Generate code to test the truth of the first operand.
4009 if self.type.is_pyobject:
4010 test_result = self.temp_bool.result()
4011 code.putln(
4012 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4013 test_result,
4014 self.operand1.py_result(),
4015 code.error_goto_if_neg(test_result, self.pos)))
4016 else:
4017 test_result = self.operand1.result()
4018 return test_result
4021 class CondExprNode(ExprNode):
4022 # Short-circuiting conditional expression.
4023 #
4024 # test ExprNode
4025 # true_val ExprNode
4026 # false_val ExprNode
4028 temp_bool = None
4029 true_val = None
4030 false_val = None
4032 subexprs = ['test', 'true_val', 'false_val']
4034 def analyse_types(self, env):
4035 self.test.analyse_types(env)
4036 self.test = self.test.coerce_to_boolean(env)
4037 self.true_val.analyse_types(env)
4038 self.false_val.analyse_types(env)
4039 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4040 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4041 self.true_val = self.true_val.coerce_to(self.type, env)
4042 self.false_val = self.false_val.coerce_to(self.type, env)
4043 # must be tmp variables so they can share a result
4044 self.true_val = self.true_val.coerce_to_temp(env)
4045 self.false_val = self.false_val.coerce_to_temp(env)
4046 self.is_temp = 1
4047 if self.type == PyrexTypes.error_type:
4048 self.type_error()
4050 def allocate_temps(self, env, result_code = None):
4051 # We only ever evaluate one side, and this is
4052 # after evaluating the truth value, so we may
4053 # use an allocation strategy here which results in
4054 # this node and both its operands sharing the same
4055 # result variable. This allows us to avoid some
4056 # assignments and increfs/decrefs that would otherwise
4057 # be necessary.
4058 self.allocate_temp(env, result_code)
4059 self.test.allocate_temps(env, result_code)
4060 self.true_val.allocate_temps(env, self.result())
4061 self.false_val.allocate_temps(env, self.result())
4062 # We haven't called release_temp on either value,
4063 # because although they are temp nodes, they don't own
4064 # their result variable. And because they are temp
4065 # nodes, any temps in their subnodes will have been
4066 # released before their allocate_temps returned.
4067 # Therefore, they contain no temp vars that need to
4068 # be released.
4070 def compute_result_type(self, type1, type2):
4071 if type1 == type2:
4072 return type1
4073 elif type1.is_numeric and type2.is_numeric:
4074 return PyrexTypes.widest_numeric_type(type1, type2)
4075 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4076 return type2
4077 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4078 return type1
4079 elif type1.is_pyobject or type2.is_pyobject:
4080 return py_object_type
4081 elif type1.assignable_from(type2):
4082 return type1
4083 elif type2.assignable_from(type1):
4084 return type2
4085 else:
4086 return PyrexTypes.error_type
4088 def type_error(self):
4089 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4090 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4091 (self.true_val.type, self.false_val.type))
4092 self.type = PyrexTypes.error_type
4094 def check_const(self):
4095 self.test.check_const()
4096 self.true_val.check_const()
4097 self.false_val.check_const()
4099 def generate_evaluation_code(self, code):
4100 self.test.generate_evaluation_code(code)
4101 code.putln("if (%s) {" % self.test.result() )
4102 self.true_val.generate_evaluation_code(code)
4103 code.putln("} else {")
4104 self.false_val.generate_evaluation_code(code)
4105 code.putln("}")
4106 self.test.generate_disposal_code(code)
4108 richcmp_constants = {
4109 "<" : "Py_LT",
4110 "<=": "Py_LE",
4111 "==": "Py_EQ",
4112 "!=": "Py_NE",
4113 "<>": "Py_NE",
4114 ">" : "Py_GT",
4115 ">=": "Py_GE",
4116 }
4118 class CmpNode:
4119 # Mixin class containing code common to PrimaryCmpNodes
4120 # and CascadedCmpNodes.
4122 def cascaded_compile_time_value(self, operand1, denv):
4123 func = get_compile_time_binop(self)
4124 operand2 = self.operand2.compile_time_value(denv)
4125 try:
4126 result = func(operand1, operand2)
4127 except Exception, e:
4128 self.compile_time_value_error(e)
4129 result = None
4130 if result:
4131 cascade = self.cascade
4132 if cascade:
4133 result = result and cascade.compile_time_value(operand2, denv)
4134 return result
4136 def is_python_comparison(self):
4137 return (self.has_python_operands()
4138 or (self.cascade and self.cascade.is_python_comparison())
4139 or self.operator in ('in', 'not_in'))
4141 def is_python_result(self):
4142 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4143 or (self.cascade and self.cascade.is_python_result()))
4145 def check_types(self, env, operand1, op, operand2):
4146 if not self.types_okay(operand1, op, operand2):
4147 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4148 (self.operator, operand1.type, operand2.type))
4150 def types_okay(self, operand1, op, operand2):
4151 type1 = operand1.type
4152 type2 = operand2.type
4153 if type1.is_error or type2.is_error:
4154 return 1
4155 if type1.is_pyobject: # type2 will be, too
4156 return 1
4157 elif type1.is_ptr or type1.is_array:
4158 return type1.is_null_ptr or type2.is_null_ptr \
4159 or ((type2.is_ptr or type2.is_array)
4160 and type1.base_type.same_as(type2.base_type))
4161 elif ((type1.is_numeric and type2.is_numeric
4162 or type1.is_enum and (type1 is type2 or type2.is_int)
4163 or type1.is_int and type2.is_enum)
4164 and op not in ('is', 'is_not')):
4165 return 1
4166 else:
4167 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4169 def generate_operation_code(self, code, result_code,
4170 operand1, op , operand2):
4171 if self.type is PyrexTypes.py_object_type:
4172 coerce_result = "__Pyx_PyBool_FromLong"
4173 else:
4174 coerce_result = ""
4175 if 'not' in op: negation = "!"
4176 else: negation = ""
4177 if op == 'in' or op == 'not_in':
4178 code.putln(
4179 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4180 result_code,
4181 coerce_result,
4182 negation,
4183 operand2.py_result(),
4184 operand1.py_result(),
4185 code.error_goto_if_neg(result_code, self.pos)))
4186 elif (operand1.type.is_pyobject
4187 and op not in ('is', 'is_not')):
4188 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4189 result_code,
4190 operand1.py_result(),
4191 operand2.py_result(),
4192 richcmp_constants[op],
4193 code.error_goto_if_null(result_code, self.pos)))
4194 else:
4195 type1 = operand1.type
4196 type2 = operand2.type
4197 if (type1.is_extension_type or type2.is_extension_type) \
4198 and not type1.same_as(type2):
4199 common_type = py_object_type
4200 elif type1.is_numeric:
4201 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4202 else:
4203 common_type = type1
4204 code1 = operand1.result_as(common_type)
4205 code2 = operand2.result_as(common_type)
4206 code.putln("%s = %s(%s %s %s);" % (
4207 result_code,
4208 coerce_result,
4209 code1,
4210 self.c_operator(op),
4211 code2))
4213 def c_operator(self, op):
4214 if op == 'is':
4215 return "=="
4216 elif op == 'is_not':
4217 return "!="
4218 else:
4219 return op
4222 class PrimaryCmpNode(ExprNode, CmpNode):
4223 # Non-cascaded comparison or first comparison of
4224 # a cascaded sequence.
4225 #
4226 # operator string
4227 # operand1 ExprNode
4228 # operand2 ExprNode
4229 # cascade CascadedCmpNode
4231 # We don't use the subexprs mechanism, because
4232 # things here are too complicated for it to handle.
4233 # Instead, we override all the framework methods
4234 # which use it.
4236 child_attrs = ['operand1', 'operand2', 'cascade']
4238 cascade = None
4240 def compile_time_value(self, denv):
4241 operand1 = self.operand1.compile_time_value(denv)
4242 return self.cascaded_compile_time_value(operand1, denv)
4244 def analyse_types(self, env):
4245 self.operand1.analyse_types(env)
4246 self.operand2.analyse_types(env)
4247 if self.cascade:
4248 self.cascade.analyse_types(env, self.operand2)
4249 self.is_pycmp = self.is_python_comparison()
4250 if self.is_pycmp:
4251 self.coerce_operands_to_pyobjects(env)
4252 if self.has_int_operands():
4253 self.coerce_chars_to_ints(env)
4254 if self.cascade:
4255 self.operand2 = self.operand2.coerce_to_simple(env)
4256 self.cascade.coerce_cascaded_operands_to_temp(env)
4257 self.check_operand_types(env)
4258 if self.is_python_result():
4259 self.type = PyrexTypes.py_object_type
4260 else:
4261 self.type = PyrexTypes.c_bint_type
4262 cdr = self.cascade
4263 while cdr:
4264 cdr.type = self.type
4265 cdr = cdr.cascade
4266 if self.is_pycmp or self.cascade:
4267 self.is_temp = 1
4269 def check_operand_types(self, env):
4270 self.check_types(env,
4271 self.operand1, self.operator, self.operand2)
4272 if self.cascade:
4273 self.cascade.check_operand_types(env, self.operand2)
4275 def has_python_operands(self):
4276 return (self.operand1.type.is_pyobject
4277 or self.operand2.type.is_pyobject)
4279 def coerce_operands_to_pyobjects(self, env):
4280 self.operand1 = self.operand1.coerce_to_pyobject(env)
4281 self.operand2 = self.operand2.coerce_to_pyobject(env)
4282 if self.cascade:
4283 self.cascade.coerce_operands_to_pyobjects(env)
4285 def has_int_operands(self):
4286 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4287 or (self.cascade and self.cascade.has_int_operands())
4289 def coerce_chars_to_ints(self, env):
4290 # coerce literal single-char strings to c chars
4291 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4292 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4293 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4294 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4295 if self.cascade:
4296 self.cascade.coerce_chars_to_ints(env)
4298 def allocate_subexpr_temps(self, env):
4299 self.operand1.allocate_temps(env)
4300 self.operand2.allocate_temps(env)
4301 if self.cascade:
4302 self.cascade.allocate_subexpr_temps(env)
4304 def release_subexpr_temps(self, env):
4305 self.operand1.release_temp(env)
4306 self.operand2.release_temp(env)
4307 if self.cascade:
4308 self.cascade.release_subexpr_temps(env)
4310 def check_const(self):
4311 self.operand1.check_const()
4312 self.operand2.check_const()
4313 if self.cascade:
4314 self.not_const()
4316 def calculate_result_code(self):
4317 return "(%s %s %s)" % (
4318 self.operand1.result(),
4319 self.c_operator(self.operator),
4320 self.operand2.result())
4322 def generate_evaluation_code(self, code):
4323 self.operand1.generate_evaluation_code(code)
4324 self.operand2.generate_evaluation_code(code)
4325 if self.is_temp:
4326 self.generate_operation_code(code, self.result(),
4327 self.operand1, self.operator, self.operand2)
4328 if self.cascade:
4329 self.cascade.generate_evaluation_code(code,
4330 self.result(), self.operand2)
4331 self.operand1.generate_disposal_code(code)
4332 self.operand2.generate_disposal_code(code)
4334 def generate_subexpr_disposal_code(self, code):
4335 # If this is called, it is a non-cascaded cmp,
4336 # so only need to dispose of the two main operands.
4337 self.operand1.generate_disposal_code(code)
4338 self.operand2.generate_disposal_code(code)
4340 def annotate(self, code):
4341 self.operand1.annotate(code)
4342 self.operand2.annotate(code)
4343 if self.cascade:
4344 self.cascade.annotate(code)
4347 class CascadedCmpNode(Node, CmpNode):
4348 # A CascadedCmpNode is not a complete expression node. It
4349 # hangs off the side of another comparison node, shares
4350 # its left operand with that node, and shares its result
4351 # with the PrimaryCmpNode at the head of the chain.
4352 #
4353 # operator string
4354 # operand2 ExprNode
4355 # cascade CascadedCmpNode
4357 child_attrs = ['operand2', 'cascade']
4359 cascade = None
4361 def analyse_types(self, env, operand1):
4362 self.operand2.analyse_types(env)
4363 if self.cascade:
4364 self.cascade.analyse_types(env, self.operand2)
4366 def check_operand_types(self, env, operand1):
4367 self.check_types(env,
4368 operand1, self.operator, self.operand2)
4369 if self.cascade:
4370 self.cascade.check_operand_types(env, self.operand2)
4372 def has_python_operands(self):
4373 return self.operand2.type.is_pyobject
4375 def coerce_operands_to_pyobjects(self, env):
4376 self.operand2 = self.operand2.coerce_to_pyobject(env)
4377 if self.cascade:
4378 self.cascade.coerce_operands_to_pyobjects(env)
4380 def has_int_operands(self):
4381 return self.operand2.type.is_int
4383 def coerce_chars_to_ints(self, env):
4384 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4385 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4387 def coerce_cascaded_operands_to_temp(self, env):
4388 if self.cascade:
4389 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4390 self.operand2 = self.operand2.coerce_to_simple(env)
4391 self.cascade.coerce_cascaded_operands_to_temp(env)
4393 def allocate_subexpr_temps(self, env):
4394 self.operand2.allocate_temps(env)
4395 if self.cascade:
4396 self.cascade.allocate_subexpr_temps(env)
4398 def release_subexpr_temps(self, env):
4399 self.operand2.release_temp(env)
4400 if self.cascade:
4401 self.cascade.release_subexpr_temps(env)
4403 def generate_evaluation_code(self, code, result, operand1):
4404 if self.type.is_pyobject:
4405 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4406 else:
4407 code.putln("if (%s) {" % result)
4408 self.operand2.generate_evaluation_code(code)
4409 self.generate_operation_code(code, result,
4410 operand1, self.operator, self.operand2)
4411 if self.cascade:
4412 self.cascade.generate_evaluation_code(
4413 code, result, self.operand2)
4414 # Cascaded cmp result is always temp
4415 self.operand2.generate_disposal_code(code)
4416 code.putln("}")
4418 def annotate(self, code):
4419 self.operand2.annotate(code)
4420 if self.cascade:
4421 self.cascade.annotate(code)
4424 binop_node_classes = {
4425 "or": BoolBinopNode,
4426 "and": BoolBinopNode,
4427 "|": IntBinopNode,
4428 "^": IntBinopNode,
4429 "&": IntBinopNode,
4430 "<<": IntBinopNode,
4431 ">>": IntBinopNode,
4432 "+": AddNode,
4433 "-": SubNode,
4434 "*": MulNode,
4435 "/": NumBinopNode,
4436 "//": FloorDivNode,
4437 "%": ModNode,
4438 "**": PowNode
4439 }
4441 def binop_node(pos, operator, operand1, operand2):
4442 # Construct binop node of appropriate class for
4443 # given operator.
4444 return binop_node_classes[operator](pos,
4445 operator = operator,
4446 operand1 = operand1,
4447 operand2 = operand2)
4449 #-------------------------------------------------------------------
4450 #
4451 # Coercion nodes
4452 #
4453 # Coercion nodes are special in that they are created during
4454 # the analyse_types phase of parse tree processing.
4455 # Their __init__ methods consequently incorporate some aspects
4456 # of that phase.
4457 #
4458 #-------------------------------------------------------------------
4460 class CoercionNode(ExprNode):
4461 # Abstract base class for coercion nodes.
4462 #
4463 # arg ExprNode node being coerced
4465 subexprs = ['arg']
4467 def __init__(self, arg):
4468 self.pos = arg.pos
4469 self.arg = arg
4470 if debug_coercion:
4471 print("%s Coercing %s" % (self, self.arg))
4473 def annotate(self, code):
4474 self.arg.annotate(code)
4475 if self.arg.type != self.type:
4476 file, line, col = self.pos
4477 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4480 class CastNode(CoercionNode):
4481 # Wrap a node in a C type cast.
4483 def __init__(self, arg, new_type):
4484 CoercionNode.__init__(self, arg)
4485 self.type = new_type
4487 def calculate_result_code(self):
4488 return self.arg.result_as(self.type)
4490 def generate_result_code(self, code):
4491 self.arg.generate_result_code(code)
4494 class PyTypeTestNode(CoercionNode):
4495 # This node is used to check that a generic Python
4496 # object is an instance of a particular extension type.
4497 # This node borrows the result of its argument node.
4499 def __init__(self, arg, dst_type, env):
4500 # The arg is know to be a Python object, and
4501 # the dst_type is known to be an extension type.
4502 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4503 CoercionNode.__init__(self, arg)
4504 self.type = dst_type
4505 self.gil_check(env)
4506 self.result_ctype = arg.ctype()
4508 gil_message = "Python type test"
4510 def analyse_types(self, env):
4511 pass
4513 def result_in_temp(self):
4514 return self.arg.result_in_temp()
4516 def is_ephemeral(self):
4517 return self.arg.is_ephemeral()
4519 def calculate_result_code(self):
4520 return self.arg.result()
4522 def generate_result_code(self, code):
4523 if self.type.typeobj_is_available():
4524 if not dst_type.is_builtin_type:
4525 code.globalstate.use_utility_code(type_test_utility_code)
4526 code.putln(
4527 "if (!(%s)) %s" % (
4528 self.type.type_test_code(self.arg.py_result()),
4529 code.error_goto(self.pos)))
4530 else:
4531 error(self.pos, "Cannot test type of extern C class "
4532 "without type object name specification")
4534 def generate_post_assignment_code(self, code):
4535 self.arg.generate_post_assignment_code(code)
4538 class CoerceToPyTypeNode(CoercionNode):
4539 # This node is used to convert a C data type
4540 # to a Python object.
4542 def __init__(self, arg, env):
4543 CoercionNode.__init__(self, arg)
4544 self.type = py_object_type
4545 self.gil_check(env)
4546 self.is_temp = 1
4547 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4548 error(arg.pos,
4549 "Cannot convert '%s' to Python object" % arg.type)
4551 gil_message = "Converting to Python object"
4553 def coerce_to_boolean(self, env):
4554 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
4556 def analyse_types(self, env):
4557 # The arg is always already analysed
4558 pass
4560 def generate_result_code(self, code):
4561 function = self.arg.type.to_py_function
4562 code.putln('%s = %s(%s); %s' % (
4563 self.result(),
4564 function,
4565 self.arg.result(),
4566 code.error_goto_if_null(self.result(), self.pos)))
4569 class CoerceFromPyTypeNode(CoercionNode):
4570 # This node is used to convert a Python object
4571 # to a C data type.
4573 def __init__(self, result_type, arg, env):
4574 CoercionNode.__init__(self, arg)
4575 self.type = result_type
4576 self.is_temp = 1
4577 if not result_type.from_py_function:
4578 error(arg.pos,
4579 "Cannot convert Python object to '%s'" % result_type)
4580 if self.type.is_string and self.arg.is_ephemeral():
4581 error(arg.pos,
4582 "Obtaining char * from temporary Python value")
4584 def analyse_types(self, env):
4585 # The arg is always already analysed
4586 pass
4588 def generate_result_code(self, code):
4589 function = self.type.from_py_function
4590 operand = self.arg.py_result()
4591 rhs = "%s(%s)" % (function, operand)
4592 if self.type.is_enum:
4593 rhs = typecast(self.type, c_long_type, rhs)
4594 code.putln('%s = %s; %s' % (
4595 self.result(),
4596 rhs,
4597 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4600 class CoerceToBooleanNode(CoercionNode):
4601 # This node is used when a result needs to be used
4602 # in a boolean context.
4604 def __init__(self, arg, env):
4605 CoercionNode.__init__(self, arg)
4606 self.type = PyrexTypes.c_bint_type
4607 if arg.type.is_pyobject:
4608 if env.nogil:
4609 self.gil_error()
4610 self.is_temp = 1
4612 gil_message = "Truth-testing Python object"
4614 def check_const(self):
4615 if self.is_temp:
4616 self.not_const()
4617 self.arg.check_const()
4619 def calculate_result_code(self):
4620 return "(%s != 0)" % self.arg.result()
4622 def generate_result_code(self, code):
4623 if self.arg.type.is_pyobject:
4624 code.putln(
4625 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4626 self.result(),
4627 self.arg.py_result(),
4628 code.error_goto_if_neg(self.result(), self.pos)))
4631 class CoerceToTempNode(CoercionNode):
4632 # This node is used to force the result of another node
4633 # to be stored in a temporary. It is only used if the
4634 # argument node's result is not already in a temporary.
4636 def __init__(self, arg, env):
4637 CoercionNode.__init__(self, arg)
4638 self.type = self.arg.type
4639 self.is_temp = 1
4640 if self.type.is_pyobject:
4641 self.gil_check(env)
4642 self.result_ctype = py_object_type
4644 gil_message = "Creating temporary Python reference"
4646 def analyse_types(self, env):
4647 # The arg is always already analysed
4648 pass
4650 def coerce_to_boolean(self, env):
4651 self.arg = self.arg.coerce_to_boolean(env)
4652 self.type = self.arg.type
4653 self.result_ctype = self.type
4654 return self
4656 def generate_result_code(self, code):
4657 #self.arg.generate_evaluation_code(code) # Already done
4658 # by generic generate_subexpr_evaluation_code!
4659 code.putln("%s = %s;" % (
4660 self.result(), self.arg.result_as(self.ctype())))
4661 if self.type.is_pyobject:
4662 code.put_incref(self.result(), self.ctype())
4665 class CloneNode(CoercionNode):
4666 # This node is employed when the result of another node needs
4667 # to be used multiple times. The argument node's result must
4668 # be in a temporary. This node "borrows" the result from the
4669 # argument node, and does not generate any evaluation or
4670 # disposal code for it. The original owner of the argument
4671 # node is responsible for doing those things.
4673 subexprs = [] # Arg is not considered a subexpr
4675 def __init__(self, arg):
4676 CoercionNode.__init__(self, arg)
4677 if hasattr(arg, 'type'):
4678 self.type = arg.type
4679 self.result_ctype = arg.result_ctype
4680 if hasattr(arg, 'entry'):
4681 self.entry = arg.entry
4683 def result(self):
4684 return self.arg.result()
4686 def analyse_types(self, env):
4687 self.type = self.arg.type
4688 self.result_ctype = self.arg.result_ctype
4689 self.is_temp = 1
4690 if hasattr(self.arg, 'entry'):
4691 self.entry = self.arg.entry
4693 def generate_evaluation_code(self, code):
4694 pass
4696 def generate_result_code(self, code):
4697 pass
4699 def generate_disposal_code(self, code):
4700 pass
4702 def allocate_temps(self, env):
4703 pass
4705 def release_temp(self, env):
4706 pass
4708 class PersistentNode(ExprNode):
4709 # A PersistentNode is like a CloneNode except it handles the temporary
4710 # allocation itself by keeping track of the number of times it has been
4711 # used.
4713 subexprs = ["arg"]
4714 temp_counter = 0
4715 generate_counter = 0
4716 analyse_counter = 0
4717 result_code = None
4719 def __init__(self, arg, uses):
4720 self.pos = arg.pos
4721 self.arg = arg
4722 self.uses = uses
4724 def analyse_types(self, env):
4725 if self.analyse_counter == 0:
4726 self.arg.analyse_types(env)
4727 self.type = self.arg.type
4728 self.result_ctype = self.arg.result_ctype
4729 self.is_temp = 1
4730 self.analyse_counter += 1
4732 def calculate_result_code(self):
4733 return self.result()
4735 def generate_evaluation_code(self, code):
4736 if self.generate_counter == 0:
4737 self.arg.generate_evaluation_code(code)
4738 code.putln("%s = %s;" % (
4739 self.result(), self.arg.result_as(self.ctype())))
4740 if self.type.is_pyobject:
4741 code.put_incref(self.result(), self.ctype())
4742 self.arg.generate_disposal_code(code)
4743 self.generate_counter += 1
4745 def generate_disposal_code(self, code):
4746 if self.generate_counter == self.uses:
4747 if self.type.is_pyobject:
4748 code.put_decref_clear(self.result(), self.ctype())
4750 def allocate_temps(self, env, result=None):
4751 if self.temp_counter == 0:
4752 self.arg.allocate_temps(env)
4753 self.allocate_temp(env, result)
4754 self.arg.release_temp(env)
4755 self.temp_counter += 1
4757 def allocate_temp(self, env, result=None):
4758 if result is None:
4759 self.result_code = env.allocate_temp(self.type)
4760 else:
4761 self.result_code = result
4763 def release_temp(self, env):
4764 if self.temp_counter == self.uses:
4765 env.release_temp(self.result())
4767 #------------------------------------------------------------------------------------
4768 #
4769 # Runtime support code
4770 #
4771 #------------------------------------------------------------------------------------
4773 get_name_interned_utility_code = UtilityCode(
4774 proto = """
4775 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4776 """,
4777 impl = """
4778 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4779 PyObject *result;
4780 result = PyObject_GetAttr(dict, name);
4781 if (!result)
4782 PyErr_SetObject(PyExc_NameError, name);
4783 return result;
4784 }
4785 """)
4787 #------------------------------------------------------------------------------------
4789 import_utility_code = UtilityCode(
4790 proto = """
4791 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4792 """,
4793 impl = """
4794 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4795 PyObject *__import__ = 0;
4796 PyObject *empty_list = 0;
4797 PyObject *module = 0;
4798 PyObject *global_dict = 0;
4799 PyObject *empty_dict = 0;
4800 PyObject *list;
4801 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4802 if (!__import__)
4803 goto bad;
4804 if (from_list)
4805 list = from_list;
4806 else {
4807 empty_list = PyList_New(0);
4808 if (!empty_list)
4809 goto bad;
4810 list = empty_list;
4811 }
4812 global_dict = PyModule_GetDict(%(GLOBALS)s);
4813 if (!global_dict)
4814 goto bad;
4815 empty_dict = PyDict_New();
4816 if (!empty_dict)
4817 goto bad;
4818 module = PyObject_CallFunctionObjArgs(__import__,
4819 name, global_dict, empty_dict, list, NULL);
4820 bad:
4821 Py_XDECREF(empty_list);
4822 Py_XDECREF(__import__);
4823 Py_XDECREF(empty_dict);
4824 return module;
4825 }
4826 """ % {
4827 "BUILTINS": Naming.builtins_cname,
4828 "GLOBALS": Naming.module_cname,
4829 })
4831 #------------------------------------------------------------------------------------
4833 get_exception_utility_code = UtilityCode(
4834 proto = """
4835 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4836 """,
4837 impl = """
4838 static PyObject *__Pyx_GetExcValue(void) {
4839 PyObject *type = 0, *value = 0, *tb = 0;
4840 PyObject *tmp_type, *tmp_value, *tmp_tb;
4841 PyObject *result = 0;
4842 PyThreadState *tstate = PyThreadState_Get();
4843 PyErr_Fetch(&type, &value, &tb);
4844 PyErr_NormalizeException(&type, &value, &tb);
4845 if (PyErr_Occurred())
4846 goto bad;
4847 if (!value) {
4848 value = Py_None;
4849 Py_INCREF(value);
4850 }
4851 tmp_type = tstate->exc_type;
4852 tmp_value = tstate->exc_value;
4853 tmp_tb = tstate->exc_traceback;
4854 tstate->exc_type = type;
4855 tstate->exc_value = value;
4856 tstate->exc_traceback = tb;
4857 /* Make sure tstate is in a consistent state when we XDECREF
4858 these objects (XDECREF may run arbitrary code). */
4859 Py_XDECREF(tmp_type);
4860 Py_XDECREF(tmp_value);
4861 Py_XDECREF(tmp_tb);
4862 result = value;
4863 Py_XINCREF(result);
4864 type = 0;
4865 value = 0;
4866 tb = 0;
4867 bad:
4868 Py_XDECREF(type);
4869 Py_XDECREF(value);
4870 Py_XDECREF(tb);
4871 return result;
4872 }
4873 """)
4875 #------------------------------------------------------------------------------------
4877 unpacking_utility_code = UtilityCode(
4878 proto = """
4879 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4880 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4881 """,
4882 impl = """
4883 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4884 PyObject *item;
4885 if (!(item = PyIter_Next(iter))) {
4886 if (!PyErr_Occurred()) {
4887 PyErr_Format(PyExc_ValueError,
4888 #if PY_VERSION_HEX < 0x02050000
4889 "need more than %d values to unpack", (int)index);
4890 #else
4891 "need more than %zd values to unpack", index);
4892 #endif
4893 }
4894 }
4895 return item;
4896 }
4898 static int __Pyx_EndUnpack(PyObject *iter) {
4899 PyObject *item;
4900 if ((item = PyIter_Next(iter))) {
4901 Py_DECREF(item);
4902 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4903 return -1;
4904 }
4905 else if (!PyErr_Occurred())
4906 return 0;
4907 else
4908 return -1;
4909 }
4910 """)
4912 #------------------------------------------------------------------------------------
4914 type_test_utility_code = UtilityCode(
4915 proto = """
4916 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4917 """,
4918 impl = """
4919 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4920 if (!type) {
4921 PyErr_Format(PyExc_SystemError, "Missing type object");
4922 return 0;
4923 }
4924 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4925 return 1;
4926 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4927 Py_TYPE(obj)->tp_name, type->tp_name);
4928 return 0;
4929 }
4930 """)
4932 #------------------------------------------------------------------------------------
4934 create_class_utility_code = UtilityCode(
4935 proto = """
4936 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
4937 """,
4938 impl = """
4939 static PyObject *__Pyx_CreateClass(
4940 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
4941 {
4942 PyObject *py_modname;
4943 PyObject *result = 0;
4945 #if PY_MAJOR_VERSION < 3
4946 py_modname = PyString_FromString(modname);
4947 #else
4948 py_modname = PyUnicode_FromString(modname);
4949 #endif
4950 if (!py_modname)
4951 goto bad;
4952 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4953 goto bad;
4954 #if PY_MAJOR_VERSION < 3
4955 result = PyClass_New(bases, dict, name);
4956 #else
4957 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4958 #endif
4959 bad:
4960 Py_XDECREF(py_modname);
4961 return result;
4962 }
4963 """)
4965 #------------------------------------------------------------------------------------
4967 cpp_exception_utility_code = UtilityCode(
4968 proto = """
4969 #ifndef __Pyx_CppExn2PyErr
4970 static void __Pyx_CppExn2PyErr() {
4971 try {
4972 if (PyErr_Occurred())
4973 ; // let the latest Python exn pass through and ignore the current one
4974 else
4975 throw;
4976 } catch (const std::out_of_range& exn) {
4977 // catch out_of_range explicitly so the proper Python exn may be raised
4978 PyErr_SetString(PyExc_IndexError, exn.what());
4979 } catch (const std::exception& exn) {
4980 PyErr_SetString(PyExc_RuntimeError, exn.what());
4981 }
4982 catch (...)
4983 {
4984 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4985 }
4986 }
4987 #endif
4988 """,
4989 impl = ""
4990 )
4992 #------------------------------------------------------------------------------------
4994 append_utility_code = UtilityCode(
4995 proto = """
4996 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4997 if (likely(PyList_CheckExact(L))) {
4998 if (PyList_Append(L, x) < 0) return NULL;
4999 Py_INCREF(Py_None);
5000 return Py_None; // this is just to have an accurate signature
5001 }
5002 else {
5003 PyObject *r, *m;
5004 m = PyObject_GetAttrString(L, "append");
5005 if (!m) return NULL;
5006 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5007 Py_DECREF(m);
5008 return r;
5009 }
5010 }
5011 """,
5012 impl = ""
5013 )
5015 #------------------------------------------------------------------------------------
5017 # If the is_unsigned flag is set, we need to do some extra work to make
5018 # sure the index doesn't become negative.
5020 getitem_int_utility_code = UtilityCode(
5021 proto = """
5022 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5023 PyObject *r;
5024 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5025 r = PyList_GET_ITEM(o, i);
5026 Py_INCREF(r);
5027 }
5028 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
5029 r = PyTuple_GET_ITEM(o, i);
5030 Py_INCREF(r);
5031 }
5032 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
5033 r = PySequence_GetItem(o, i);
5034 else {
5035 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5036 if (!j)
5037 return 0;
5038 r = PyObject_GetItem(o, j);
5039 Py_DECREF(j);
5040 }
5041 return r;
5042 }
5043 """,
5044 impl = """
5045 """)
5047 #------------------------------------------------------------------------------------
5049 setitem_int_utility_code = UtilityCode(
5050 proto = """
5051 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
5052 int r;
5053 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5054 Py_DECREF(PyList_GET_ITEM(o, i));
5055 Py_INCREF(v);
5056 PyList_SET_ITEM(o, i, v);
5057 return 1;
5058 }
5059 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5060 r = PySequence_SetItem(o, i, v);
5061 else {
5062 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5063 if (!j)
5064 return -1;
5065 r = PyObject_SetItem(o, j, v);
5066 Py_DECREF(j);
5067 }
5068 return r;
5069 }
5070 """,
5071 impl = """
5072 """)
5074 #------------------------------------------------------------------------------------
5076 delitem_int_utility_code = UtilityCode(
5077 proto = """
5078 static INLINE int __Pyx_DelItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5079 int r;
5080 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5081 r = PySequence_DelItem(o, i);
5082 else {
5083 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5084 if (!j)
5085 return -1;
5086 r = PyObject_DelItem(o, j);
5087 Py_DECREF(j);
5088 }
5089 return r;
5090 }
5091 """,
5092 impl = """
5093 """)
5095 #------------------------------------------------------------------------------------
5097 raise_noneattr_error_utility_code = UtilityCode(
5098 proto = """
5099 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5100 """,
5101 impl = """
5102 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5103 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5104 }
5105 """)
5107 raise_noneindex_error_utility_code = UtilityCode(
5108 proto = """
5109 static INLINE void __Pyx_RaiseNoneIndexingError();
5110 """,
5111 impl = """
5112 static INLINE void __Pyx_RaiseNoneIndexingError() {
5113 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5114 }
5115 """)
