Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 912:fe3d5f426ff2
Fix optional cdef arguments for c++, possible optimization when not all args are used.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Sun Aug 03 04:02:45 2008 -0700 (3 years ago) |
| parents | def99eb4f83c |
| children | a16c8e765fcf |
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 import Naming
10 from Nodes import Node
11 import PyrexTypes
12 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
13 from Builtin import list_type, tuple_type, dict_type
14 import Symtab
15 import Options
16 from Annotate import AnnotationItem
18 from Cython.Debugging import print_call_chain
19 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
20 debug_coercion
23 class ExprNode(Node):
24 # subexprs [string] Class var holding names of subexpr node attrs
25 # type PyrexType Type of the result
26 # result_code string Code fragment
27 # result_ctype string C type of result_code if different from type
28 # is_temp boolean Result is in a temporary variable
29 # is_sequence_constructor
30 # boolean Is a list or tuple constructor expression
31 # saved_subexpr_nodes
32 # [ExprNode or [ExprNode or None] or None]
33 # Cached result of subexpr_nodes()
35 result_ctype = None
36 type = None
38 # The Analyse Expressions phase for expressions is split
39 # into two sub-phases:
40 #
41 # Analyse Types
42 # Determines the result type of the expression based
43 # on the types of its sub-expressions, and inserts
44 # coercion nodes into the expression tree where needed.
45 # Marks nodes which will need to have temporary variables
46 # allocated.
47 #
48 # Allocate Temps
49 # Allocates temporary variables where needed, and fills
50 # in the result_code field of each node.
51 #
52 # ExprNode provides some convenience routines which
53 # perform both of the above phases. These should only
54 # be called from statement nodes, and only when no
55 # coercion nodes need to be added around the expression
56 # being analysed. In that case, the above two phases
57 # should be invoked separately.
58 #
59 # Framework code in ExprNode provides much of the common
60 # processing for the various phases. It makes use of the
61 # 'subexprs' class attribute of ExprNodes, which should
62 # contain a list of the names of attributes which can
63 # hold sub-nodes or sequences of sub-nodes.
64 #
65 # The framework makes use of a number of abstract methods.
66 # Their responsibilities are as follows.
67 #
68 # Declaration Analysis phase
69 #
70 # analyse_target_declaration
71 # Called during the Analyse Declarations phase to analyse
72 # the LHS of an assignment or argument of a del statement.
73 # Nodes which cannot be the LHS of an assignment need not
74 # implement it.
75 #
76 # Expression Analysis phase
77 #
78 # analyse_types
79 # - Call analyse_types on all sub-expressions.
80 # - Check operand types, and wrap coercion nodes around
81 # sub-expressions where needed.
82 # - Set the type of this node.
83 # - If a temporary variable will be required for the
84 # result, set the is_temp flag of this node.
85 #
86 # analyse_target_types
87 # Called during the Analyse Types phase to analyse
88 # the LHS of an assignment or argument of a del
89 # statement. Similar responsibilities to analyse_types.
90 #
91 # allocate_temps
92 # - Call allocate_temps for all sub-nodes.
93 # - Call allocate_temp for this node.
94 # - If a temporary was allocated, call release_temp on
95 # all sub-expressions.
96 #
97 # allocate_target_temps
98 # - Call allocate_temps on sub-nodes and allocate any other
99 # temps used during assignment.
100 # - Fill in result_code with a C lvalue if needed.
101 # - If a rhs node is supplied, call release_temp on it.
102 # - Call release_temp on sub-nodes and release any other
103 # temps used during assignment.
104 #
105 # calculate_result_code
106 # - Called during the Allocate Temps phase. Should return a
107 # C code fragment evaluating to the result. This is only
108 # called when the result is not a temporary.
109 #
110 # target_code
111 # Called by the default implementation of allocate_target_temps.
112 # Should return a C lvalue for assigning to the node. The default
113 # implementation calls calculate_result_code.
114 #
115 # check_const
116 # - Check that this node and its subnodes form a
117 # legal constant expression. If so, do nothing,
118 # otherwise call not_const.
119 #
120 # The default implementation of check_const
121 # assumes that the expression is not constant.
122 #
123 # check_const_addr
124 # - Same as check_const, except check that the
125 # expression is a C lvalue whose address is
126 # constant. Otherwise, call addr_not_const.
127 #
128 # The default implementation of calc_const_addr
129 # assumes that the expression is not a constant
130 # lvalue.
131 #
132 # Code Generation phase
133 #
134 # generate_evaluation_code
135 # - Call generate_evaluation_code for sub-expressions.
136 # - Perform the functions of generate_result_code
137 # (see below).
138 # - If result is temporary, call generate_disposal_code
139 # on all sub-expressions.
140 #
141 # A default implementation of generate_evaluation_code
142 # is provided which uses the following abstract method:
143 #
144 # generate_result_code
145 # - Generate any C statements necessary to calculate
146 # the result of this node from the results of its
147 # sub-expressions.
148 #
149 # generate_assignment_code
150 # Called on the LHS of an assignment.
151 # - Call generate_evaluation_code for sub-expressions.
152 # - Generate code to perform the assignment.
153 # - If the assignment absorbed a reference, call
154 # generate_post_assignment_code on the RHS,
155 # otherwise call generate_disposal_code on it.
156 #
157 # generate_deletion_code
158 # Called on an argument of a del statement.
159 # - Call generate_evaluation_code for sub-expressions.
160 # - Generate code to perform the deletion.
161 # - Call generate_disposal_code on all sub-expressions.
162 #
163 #
165 is_sequence_constructor = 0
166 is_attribute = 0
168 saved_subexpr_nodes = None
169 is_temp = 0
171 def get_child_attrs(self):
172 return self.subexprs
173 child_attrs = property(fget=get_child_attrs)
175 def not_implemented(self, method_name):
176 print_call_chain(method_name, "not implemented") ###
177 raise InternalError(
178 "%s.%s not implemented" %
179 (self.__class__.__name__, method_name))
181 def is_lvalue(self):
182 return 0
184 def is_ephemeral(self):
185 # An ephemeral node is one whose result is in
186 # a Python temporary and we suspect there are no
187 # other references to it. Certain operations are
188 # disallowed on such values, since they are
189 # likely to result in a dangling pointer.
190 return self.type.is_pyobject and self.is_temp
192 def subexpr_nodes(self):
193 # Extract a list of subexpression nodes based
194 # on the contents of the subexprs class attribute.
195 if self.saved_subexpr_nodes is None:
196 nodes = []
197 for name in self.subexprs:
198 item = getattr(self, name)
199 if item:
200 if isinstance(item, ExprNode):
201 nodes.append(item)
202 else:
203 nodes.extend(item)
204 self.saved_subexpr_nodes = nodes
205 return self.saved_subexpr_nodes
207 def result_as(self, type = None):
208 # Return the result code cast to the specified C type.
209 return typecast(type, self.ctype(), self.result_code)
211 def py_result(self):
212 # Return the result code cast to PyObject *.
213 return self.result_as(py_object_type)
215 def ctype(self):
216 # Return the native C type of the result (i.e. the
217 # C type of the result_code expression).
218 return self.result_ctype or self.type
220 def compile_time_value(self, denv):
221 # Return value of compile-time expression, or report error.
222 error(self.pos, "Invalid compile-time expression")
224 def compile_time_value_error(self, e):
225 error(self.pos, "Error in compile-time expression: %s: %s" % (
226 e.__class__.__name__, e))
228 # ------------- Declaration Analysis ----------------
230 def analyse_target_declaration(self, env):
231 error(self.pos, "Cannot assign to or delete this")
233 # ------------- Expression Analysis ----------------
235 def analyse_const_expression(self, env):
236 # Called during the analyse_declarations phase of a
237 # constant expression. Analyses the expression's type,
238 # checks whether it is a legal const expression,
239 # and determines its value.
240 self.analyse_types(env)
241 self.allocate_temps(env)
242 self.check_const()
244 def analyse_expressions(self, env):
245 # Convenience routine performing both the Type
246 # Analysis and Temp Allocation phases for a whole
247 # expression.
248 self.analyse_types(env)
249 self.allocate_temps(env)
251 def analyse_target_expression(self, env, rhs):
252 # Convenience routine performing both the Type
253 # Analysis and Temp Allocation phases for the LHS of
254 # an assignment.
255 self.analyse_target_types(env)
256 self.allocate_target_temps(env, rhs)
258 def analyse_boolean_expression(self, env):
259 # Analyse expression and coerce to a boolean.
260 self.analyse_types(env)
261 bool = self.coerce_to_boolean(env)
262 bool.allocate_temps(env)
263 return bool
265 def analyse_temp_boolean_expression(self, env):
266 # Analyse boolean expression and coerce result into
267 # a temporary. This is used when a branch is to be
268 # performed on the result and we won't have an
269 # opportunity to ensure disposal code is executed
270 # afterwards. By forcing the result into a temporary,
271 # we ensure that all disposal has been done by the
272 # time we get the result.
273 self.analyse_types(env)
274 bool = self.coerce_to_boolean(env)
275 temp_bool = bool.coerce_to_temp(env)
276 temp_bool.allocate_temps(env)
277 return temp_bool
279 # --------------- Type Analysis ------------------
281 def analyse_as_module(self, env):
282 # If this node can be interpreted as a reference to a
283 # cimported module, return its scope, else None.
284 return None
286 def analyse_as_extension_type(self, env):
287 # If this node can be interpreted as a reference to an
288 # extension type, return its type, else None.
289 return None
291 def analyse_types(self, env):
292 self.not_implemented("analyse_types")
294 def analyse_target_types(self, env):
295 self.analyse_types(env)
297 def gil_assignment_check(self, env):
298 if env.nogil and self.type.is_pyobject:
299 error(self.pos, "Assignment of Python object not allowed without gil")
301 def check_const(self):
302 self.not_const()
304 def not_const(self):
305 error(self.pos, "Not allowed in a constant expression")
307 def check_const_addr(self):
308 self.addr_not_const()
310 def addr_not_const(self):
311 error(self.pos, "Address is not constant")
313 def gil_check(self, env):
314 if env.nogil and self.type.is_pyobject:
315 self.gil_error()
317 # ----------------- Result Allocation -----------------
319 def result_in_temp(self):
320 # Return true if result is in a temporary owned by
321 # this node or one of its subexpressions. Overridden
322 # by certain nodes which can share the result of
323 # a subnode.
324 return self.is_temp
326 def allocate_target_temps(self, env, rhs):
327 # Perform temp allocation for the LHS of an assignment.
328 if debug_temp_alloc:
329 print("%s Allocating target temps" % self)
330 self.allocate_subexpr_temps(env)
331 self.result_code = self.target_code()
332 if rhs:
333 rhs.release_temp(env)
334 self.release_subexpr_temps(env)
336 def allocate_temps(self, env, result = None):
337 # Allocate temporary variables for this node and
338 # all its sub-expressions. If a result is specified,
339 # this must be a temp node and the specified variable
340 # is used as the result instead of allocating a new
341 # one.
342 if debug_temp_alloc:
343 print("%s Allocating temps" % self)
344 self.allocate_subexpr_temps(env)
345 self.allocate_temp(env, result)
346 if self.is_temp:
347 self.release_subexpr_temps(env)
349 def allocate_subexpr_temps(self, env):
350 # Allocate temporary variables for all sub-expressions
351 # of this node.
352 if debug_temp_alloc:
353 print("%s Allocating temps for: %s" % (self, self.subexprs))
354 for node in self.subexpr_nodes():
355 if node:
356 if debug_temp_alloc:
357 print("%s Allocating temps for %s" % (self, node))
358 node.allocate_temps(env)
360 def allocate_temp(self, env, result = None):
361 # If this node requires a temporary variable for its
362 # result, allocate one, otherwise set the result to
363 # a C code fragment. If a result is specified,
364 # this must be a temp node and the specified variable
365 # is used as the result instead of allocating a new
366 # one.
367 if debug_temp_alloc:
368 print("%s Allocating temp" % self)
369 if result:
370 if not self.is_temp:
371 raise InternalError("Result forced on non-temp node")
372 self.result_code = result
373 elif self.is_temp:
374 type = self.type
375 if not type.is_void:
376 if type.is_pyobject:
377 type = PyrexTypes.py_object_type
378 self.result_code = env.allocate_temp(type)
379 else:
380 self.result_code = None
381 if debug_temp_alloc:
382 print("%s Allocated result %s" % (self, self.result_code))
383 else:
384 self.result_code = self.calculate_result_code()
386 def target_code(self):
387 # Return code fragment for use as LHS of a C assignment.
388 return self.calculate_result_code()
390 def calculate_result_code(self):
391 self.not_implemented("calculate_result_code")
393 # def release_target_temp(self, env):
394 # # Release temporaries used by LHS of an assignment.
395 # self.release_subexpr_temps(env)
397 def release_temp(self, env):
398 # If this node owns a temporary result, release it,
399 # otherwise release results of its sub-expressions.
400 if self.is_temp:
401 if debug_temp_alloc:
402 print("%s Releasing result %s" % (self, self.result_code))
403 env.release_temp(self.result_code)
404 else:
405 self.release_subexpr_temps(env)
407 def release_subexpr_temps(self, env):
408 # Release the results of all sub-expressions of
409 # this node.
410 for node in self.subexpr_nodes():
411 if node:
412 node.release_temp(env)
414 # ---------------- Code Generation -----------------
416 def make_owned_reference(self, code):
417 # If result is a pyobject, make sure we own
418 # a reference to it.
419 if self.type.is_pyobject and not self.result_in_temp():
420 code.put_incref(self.result_code, self.ctype())
422 def generate_evaluation_code(self, code):
423 code.mark_pos(self.pos)
424 # Generate code to evaluate this node and
425 # its sub-expressions, and dispose of any
426 # temporary results of its sub-expressions.
427 self.generate_subexpr_evaluation_code(code)
428 self.generate_result_code(code)
429 if self.is_temp:
430 self.generate_subexpr_disposal_code(code)
432 def generate_subexpr_evaluation_code(self, code):
433 for node in self.subexpr_nodes():
434 node.generate_evaluation_code(code)
436 def generate_result_code(self, code):
437 self.not_implemented("generate_result_code")
439 def generate_disposal_code(self, code):
440 # If necessary, generate code to dispose of
441 # temporary Python reference.
442 if self.is_temp:
443 if self.type.is_pyobject:
444 code.put_decref_clear(self.result_code, self.ctype())
445 else:
446 self.generate_subexpr_disposal_code(code)
448 def generate_subexpr_disposal_code(self, code):
449 # Generate code to dispose of temporary results
450 # of all sub-expressions.
451 for node in self.subexpr_nodes():
452 node.generate_disposal_code(code)
454 def generate_post_assignment_code(self, code):
455 # Same as generate_disposal_code except that
456 # assignment will have absorbed a reference to
457 # the result if it is a Python object.
458 if self.is_temp:
459 if self.type.is_pyobject:
460 code.putln("%s = 0;" % self.result_code)
461 else:
462 self.generate_subexpr_disposal_code(code)
464 def generate_assignment_code(self, rhs, code):
465 # Stub method for nodes which are not legal as
466 # the LHS of an assignment. An error will have
467 # been reported earlier.
468 pass
470 def generate_deletion_code(self, code):
471 # Stub method for nodes that are not legal as
472 # the argument of a del statement. An error
473 # will have been reported earlier.
474 pass
476 # ---------------- Annotation ---------------------
478 def annotate(self, code):
479 for node in self.subexpr_nodes():
480 node.annotate(code)
482 # ----------------- Coercion ----------------------
484 def coerce_to(self, dst_type, env):
485 # Coerce the result so that it can be assigned to
486 # something of type dst_type. If processing is necessary,
487 # wraps this node in a coercion node and returns that.
488 # Otherwise, returns this node unchanged.
489 #
490 # This method is called during the analyse_expressions
491 # phase of the src_node's processing.
492 src = self
493 src_type = self.type
494 src_is_py_type = src_type.is_pyobject
495 dst_is_py_type = dst_type.is_pyobject
497 if dst_type.is_pyobject:
498 if not src.type.is_pyobject:
499 src = CoerceToPyTypeNode(src, env)
500 if not src.type.subtype_of(dst_type):
501 if not isinstance(src, NoneNode):
502 src = PyTypeTestNode(src, dst_type, env)
503 elif src.type.is_pyobject:
504 src = CoerceFromPyTypeNode(dst_type, src, env)
505 else: # neither src nor dst are py types
506 # Added the string comparison, since for c types that
507 # is enough, but Cython gets confused when the types are
508 # in different files.
509 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
510 error(self.pos, "Cannot assign type '%s' to '%s'" %
511 (src.type, dst_type))
512 return src
514 def coerce_to_pyobject(self, env):
515 return self.coerce_to(PyrexTypes.py_object_type, env)
517 def coerce_to_boolean(self, env):
518 # Coerce result to something acceptable as
519 # a boolean value.
520 type = self.type
521 if type.is_pyobject or type.is_ptr or type.is_float:
522 return CoerceToBooleanNode(self, env)
523 else:
524 if not type.is_int and not type.is_error:
525 error(self.pos,
526 "Type '%s' not acceptable as a boolean" % type)
527 return self
529 def coerce_to_integer(self, env):
530 # If not already some C integer type, coerce to longint.
531 if self.type.is_int:
532 return self
533 else:
534 return self.coerce_to(PyrexTypes.c_long_type, env)
536 def coerce_to_temp(self, env):
537 # Ensure that the result is in a temporary.
538 if self.result_in_temp():
539 return self
540 else:
541 return CoerceToTempNode(self, env)
543 def coerce_to_simple(self, env):
544 # Ensure that the result is simple (see is_simple).
545 if self.is_simple():
546 return self
547 else:
548 return self.coerce_to_temp(env)
550 def is_simple(self):
551 # A node is simple if its result is something that can
552 # be referred to without performing any operations, e.g.
553 # a constant, local var, C global var, struct member
554 # reference, or temporary.
555 return self.result_in_temp()
558 class AtomicExprNode(ExprNode):
559 # Abstract base class for expression nodes which have
560 # no sub-expressions.
562 subexprs = []
565 class PyConstNode(AtomicExprNode):
566 # Abstract base class for constant Python values.
568 is_literal = 1
570 def is_simple(self):
571 return 1
573 def analyse_types(self, env):
574 self.type = py_object_type
576 def calculate_result_code(self):
577 return self.value
579 def generate_result_code(self, code):
580 pass
583 class NoneNode(PyConstNode):
584 # The constant value None
586 value = "Py_None"
588 def compile_time_value(self, denv):
589 return None
591 class EllipsisNode(PyConstNode):
592 # '...' in a subscript list.
594 value = "Py_Ellipsis"
596 def compile_time_value(self, denv):
597 return Ellipsis
600 class ConstNode(AtomicExprNode):
601 # Abstract base type for literal constant nodes.
602 #
603 # value string C code fragment
605 is_literal = 1
607 def is_simple(self):
608 return 1
610 def analyse_types(self, env):
611 pass # Types are held in class variables
613 def check_const(self):
614 pass
616 def calculate_result_code(self):
617 return str(self.value)
619 def generate_result_code(self, code):
620 pass
623 class BoolNode(ConstNode):
624 type = PyrexTypes.c_bint_type
625 # The constant value True or False
627 def compile_time_value(self, denv):
628 return self.value
630 def calculate_result_code(self):
631 return int(self.value)
633 class NullNode(ConstNode):
634 type = PyrexTypes.c_null_ptr_type
635 value = "NULL"
638 class CharNode(ConstNode):
639 type = PyrexTypes.c_char_type
641 def compile_time_value(self, denv):
642 return ord(self.value)
644 def calculate_result_code(self):
645 return "'%s'" % self.value
648 class IntNode(ConstNode):
650 # unsigned "" or "U"
651 # longness "" or "L" or "LL"
653 unsigned = ""
654 longness = ""
655 type = PyrexTypes.c_long_type
657 def coerce_to(self, dst_type, env):
658 # Arrange for a Python version of the string to be pre-allocated
659 # when coercing to a Python type.
660 if dst_type.is_pyobject:
661 self.entry = env.get_py_num(self.value, self.longness)
662 self.type = PyrexTypes.py_object_type
663 # We still need to perform normal coerce_to processing on the
664 # result, because we might be coercing to an extension type,
665 # in which case a type test node will be needed.
666 return ConstNode.coerce_to(self, dst_type, env)
668 def calculate_result_code(self):
669 if self.type.is_pyobject:
670 return self.entry.cname
671 else:
672 return str(self.value) + self.unsigned + self.longness
674 def compile_time_value(self, denv):
675 return int(self.value, 0)
678 class FloatNode(ConstNode):
679 type = PyrexTypes.c_double_type
681 def compile_time_value(self, denv):
682 return float(self.value)
684 def calculate_result_code(self):
685 strval = str(self.value)
686 if strval == 'nan':
687 return "(Py_HUGE_VAL * 0)"
688 elif strval == 'inf':
689 return "Py_HUGE_VAL"
690 elif strval == '-inf':
691 return "(-Py_HUGE_VAL)"
692 else:
693 return strval
696 class StringNode(ConstNode):
697 # entry Symtab.Entry
699 type = PyrexTypes.c_char_ptr_type
701 def compile_time_value(self, denv):
702 return self.value
704 def analyse_types(self, env):
705 self.entry = env.add_string_const(self.value)
707 def coerce_to(self, dst_type, env):
708 if dst_type.is_int:
709 if not self.type.is_pyobject and len(self.entry.init) == 1:
710 # we use the *encoded* value here
711 return CharNode(self.pos, value=self.entry.init)
712 else:
713 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
714 return self
715 # Arrange for a Python version of the string to be pre-allocated
716 # when coercing to a Python type.
717 if dst_type.is_pyobject and not self.type.is_pyobject:
718 node = self.as_py_string_node(env)
719 else:
720 node = self
721 # We still need to perform normal coerce_to processing on the
722 # result, because we might be coercing to an extension type,
723 # in which case a type test node will be needed.
724 return ConstNode.coerce_to(node, dst_type, env)
726 def as_py_string_node(self, env):
727 # Return a new StringNode with the same entry as this node
728 # but whose type is a Python type instead of a C type.
729 entry = self.entry
730 env.add_py_string(entry)
731 return StringNode(self.pos, entry = entry, type = py_object_type)
733 def calculate_result_code(self):
734 if self.type.is_pyobject:
735 return self.entry.pystring_cname
736 else:
737 return self.entry.cname
740 class IdentifierStringNode(ConstNode):
741 # A Python string that behaves like an identifier, e.g. for
742 # keyword arguments in a call, or for imported names
743 type = PyrexTypes.py_object_type
745 def analyse_types(self, env):
746 self.cname = env.intern_identifier(self.value)
748 def calculate_result_code(self):
749 return self.cname
752 class LongNode(AtomicExprNode):
753 # Python long integer literal
754 #
755 # value string
757 def compile_time_value(self, denv):
758 return long(self.value)
760 gil_message = "Constructing Python long int"
762 def analyse_types(self, env):
763 self.type = py_object_type
764 self.gil_check(env)
765 self.is_temp = 1
767 gil_message = "Constructing Python long int"
769 def generate_evaluation_code(self, code):
770 code.putln(
771 '%s = PyLong_FromString("%s", 0, 0); %s' % (
772 self.result_code,
773 self.value,
774 code.error_goto_if_null(self.result_code, self.pos)))
777 class ImagNode(AtomicExprNode):
778 # Imaginary number literal
779 #
780 # value float imaginary part
782 def compile_time_value(self, denv):
783 return complex(0.0, self.value)
785 def analyse_types(self, env):
786 self.type = py_object_type
787 self.gil_check(env)
788 self.is_temp = 1
790 gil_message = "Constructing complex number"
792 def generate_evaluation_code(self, code):
793 code.putln(
794 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
795 self.result_code,
796 self.value,
797 code.error_goto_if_null(self.result_code, self.pos)))
800 class NameNode(AtomicExprNode):
801 # Reference to a local or global variable name.
802 #
803 # name string Python name of the variable
804 #
805 # entry Entry Symbol table entry
806 # interned_cname string
808 is_name = 1
809 skip_assignment_decref = False
810 entry = None
812 def create_analysed_rvalue(pos, env, entry):
813 node = NameNode(pos)
814 node.analyse_types(env, entry=entry)
815 return node
817 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
819 def compile_time_value(self, denv):
820 try:
821 return denv.lookup(self.name)
822 except KeyError:
823 error(self.pos, "Compile-time name '%s' not defined" % self.name)
825 def coerce_to(self, dst_type, env):
826 # If coercing to a generic pyobject and this is a builtin
827 # C function with a Python equivalent, manufacture a NameNode
828 # referring to the Python builtin.
829 #print "NameNode.coerce_to:", self.name, dst_type ###
830 if dst_type is py_object_type:
831 entry = self.entry
832 if entry and entry.is_cfunction:
833 var_entry = entry.as_variable
834 if var_entry:
835 if var_entry.is_builtin and Options.cache_builtins:
836 var_entry = env.declare_builtin(var_entry.name, self.pos)
837 node = NameNode(self.pos, name = self.name)
838 node.entry = var_entry
839 node.analyse_rvalue_entry(env)
840 return node
841 return AtomicExprNode.coerce_to(self, dst_type, env)
843 def analyse_as_module(self, env):
844 # Try to interpret this as a reference to a cimported module.
845 # Returns the module scope, or None.
846 entry = self.entry
847 if not entry:
848 entry = env.lookup(self.name)
849 if entry and entry.as_module:
850 return entry.as_module
851 return None
853 def analyse_as_extension_type(self, env):
854 # Try to interpret this as a reference to an extension type.
855 # Returns the extension type, or None.
856 entry = self.entry
857 if not entry:
858 entry = env.lookup(self.name)
859 if entry and entry.is_type and entry.type.is_extension_type:
860 return entry.type
861 else:
862 return None
864 def analyse_target_declaration(self, env):
865 if not self.entry:
866 self.entry = env.lookup_here(self.name)
867 if not self.entry:
868 self.entry = env.declare_var(self.name, py_object_type, self.pos)
869 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
870 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
871 if self.entry.is_declared_generic:
872 self.result_ctype = py_object_type
873 if self.entry.is_pyglobal and self.entry.is_member:
874 env.use_utility_code(type_cache_invalidation_code)
876 def analyse_types(self, env):
877 if self.entry is None:
878 self.entry = env.lookup(self.name)
879 if not self.entry:
880 self.entry = env.declare_builtin(self.name, self.pos)
881 if not self.entry:
882 self.type = PyrexTypes.error_type
883 return
884 self.analyse_rvalue_entry(env)
886 def analyse_target_types(self, env):
887 self.analyse_entry(env)
888 if not self.is_lvalue():
889 error(self.pos, "Assignment to non-lvalue '%s'"
890 % self.name)
891 self.type = PyrexTypes.error_type
892 self.entry.used = 1
893 if self.entry.type.is_buffer:
894 # Have an rhs temp just in case. All rhs I could
895 # think of had a single symbol result_code but better
896 # safe than sorry. Feel free to change this.
897 import Buffer
898 Buffer.used_buffer_aux_vars(self.entry)
900 def analyse_rvalue_entry(self, env):
901 #print "NameNode.analyse_rvalue_entry:", self.name ###
902 #print "Entry:", self.entry.__dict__ ###
903 self.analyse_entry(env)
904 entry = self.entry
905 if entry.is_declared_generic:
906 self.result_ctype = py_object_type
907 if entry.is_pyglobal or entry.is_builtin:
908 if Options.cache_builtins and entry.is_builtin:
909 self.is_temp = 0
910 else:
911 self.is_temp = 1
912 env.use_utility_code(get_name_interned_utility_code)
913 self.gil_check(env)
915 gil_message = "Accessing Python global or builtin"
917 def analyse_entry(self, env):
918 #print "NameNode.analyse_entry:", self.name ###
919 self.check_identifier_kind()
920 entry = self.entry
921 type = entry.type
922 self.type = type
923 if entry.is_pyglobal or entry.is_builtin:
924 assert type.is_pyobject, "Python global or builtin not a Python object"
925 self.interned_cname = self.entry.interned_cname = \
926 env.intern_identifier(self.entry.name)
928 def check_identifier_kind(self):
929 #print "NameNode.check_identifier_kind:", self.entry.name ###
930 #print self.entry.__dict__ ###
931 entry = self.entry
932 #entry.used = 1
933 if not (entry.is_const or entry.is_variable
934 or entry.is_builtin or entry.is_cfunction):
935 if self.entry.as_variable:
936 self.entry = self.entry.as_variable
937 else:
938 error(self.pos,
939 "'%s' is not a constant, variable or function identifier" % self.name)
941 def is_simple(self):
942 # If it's not a C variable, it'll be in a temp.
943 return 1
945 def calculate_target_results(self, env):
946 pass
948 def check_const(self):
949 entry = self.entry
950 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
951 self.not_const()
953 def check_const_addr(self):
954 entry = self.entry
955 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
956 self.addr_not_const()
958 def is_lvalue(self):
959 return self.entry.is_variable and \
960 not self.entry.type.is_array and \
961 not self.entry.is_readonly
963 def is_ephemeral(self):
964 # Name nodes are never ephemeral, even if the
965 # result is in a temporary.
966 return 0
968 def allocate_temp(self, env, result = None):
969 AtomicExprNode.allocate_temp(self, env, result)
970 entry = self.entry
971 if entry:
972 entry.used = 1
973 if entry.utility_code:
974 env.use_utility_code(entry.utility_code)
976 def calculate_result_code(self):
977 entry = self.entry
978 if not entry:
979 return "<error>" # There was an error earlier
980 return entry.cname
982 def generate_result_code(self, code):
983 assert hasattr(self, 'entry')
984 entry = self.entry
985 if entry is None:
986 return # There was an error earlier
987 if entry.is_builtin and Options.cache_builtins:
988 return # Lookup already cached
989 elif entry.is_pyglobal or entry.is_builtin:
990 if entry.is_builtin:
991 namespace = Naming.builtins_cname
992 else: # entry.is_pyglobal
993 namespace = entry.scope.namespace_cname
994 code.putln(
995 '%s = __Pyx_GetName(%s, %s); %s' % (
996 self.result_code,
997 namespace,
998 self.interned_cname,
999 code.error_goto_if_null(self.result_code, self.pos)))
1000 elif entry.is_local and False:
1001 # control flow not good enough yet
1002 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1003 if assigned is False:
1004 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1005 elif not Options.init_local_none and assigned is None:
1006 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1007 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1009 def generate_assignment_code(self, rhs, code):
1010 #print "NameNode.generate_assignment_code:", self.name ###
1011 entry = self.entry
1012 if entry is None:
1013 return # There was an error earlier
1015 # is_pyglobal seems to be True for module level-globals only.
1016 # We use this to access class->tp_dict if necessary.
1017 if entry.is_pyglobal:
1018 namespace = self.entry.scope.namespace_cname
1019 if entry.is_member:
1020 # if the entry is a member we have to cheat: SetAttr does not work
1021 # on types, so we create a descriptor which is then added to tp_dict
1022 code.put_error_if_neg(self.pos,
1023 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1024 namespace,
1025 self.interned_cname,
1026 rhs.py_result()))
1027 # in Py2.6+, we need to invalidate the method cache
1028 code.putln("__Pyx_TypeModified(%s);" %
1029 entry.scope.parent_type.typeptr_cname)
1030 else:
1031 code.put_error_if_neg(self.pos,
1032 'PyObject_SetAttr(%s, %s, %s)' % (
1033 namespace,
1034 self.interned_cname,
1035 rhs.py_result()))
1036 if debug_disposal_code:
1037 print("NameNode.generate_assignment_code:")
1038 print("...generating disposal code for %s" % rhs)
1039 rhs.generate_disposal_code(code)
1041 else:
1042 if self.type.is_buffer:
1043 # Generate code for doing the buffer release/acquisition.
1044 # This might raise an exception in which case the assignment (done
1045 # below) will not happen.
1046 #
1047 # The reason this is not in a typetest-like node is because the
1048 # variables that the acquired buffer info is stored to is allocated
1049 # per entry and coupled with it.
1050 self.generate_acquire_buffer(rhs, code)
1052 if self.type.is_pyobject:
1053 rhs.make_owned_reference(code)
1054 #print "NameNode.generate_assignment_code: to", self.name ###
1055 #print "...from", rhs ###
1056 #print "...LHS type", self.type, "ctype", self.ctype() ###
1057 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1058 if not self.skip_assignment_decref:
1059 if entry.is_local and not Options.init_local_none:
1060 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1061 if initalized is True:
1062 code.put_decref(self.result_code, self.ctype())
1063 elif initalized is None:
1064 code.put_xdecref(self.result_code, self.ctype())
1065 else:
1066 code.put_decref(self.result_code, self.ctype())
1067 code.putln('%s = %s;' % (self.result_code, rhs.result_as(self.ctype())))
1068 if debug_disposal_code:
1069 print("NameNode.generate_assignment_code:")
1070 print("...generating post-assignment code for %s" % rhs)
1071 rhs.generate_post_assignment_code(code)
1073 def generate_acquire_buffer(self, rhs, code):
1074 rhstmp = code.func.allocate_temp(self.entry.type)
1075 buffer_aux = self.entry.buffer_aux
1076 bufstruct = buffer_aux.buffer_info_var.cname
1077 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1079 import Buffer
1080 Buffer.put_assign_to_buffer(self.result_code, rhstmp, buffer_aux, self.entry.type,
1081 is_initialized=not self.skip_assignment_decref,
1082 pos=self.pos, code=code)
1083 code.putln("%s = 0;" % rhstmp)
1084 code.func.release_temp(rhstmp)
1086 def generate_deletion_code(self, code):
1087 if self.entry is None:
1088 return # There was an error earlier
1089 if not self.entry.is_pyglobal:
1090 error(self.pos, "Deletion of local or C global name not supported")
1091 return
1092 code.put_error_if_neg(self.pos,
1093 'PyObject_DelAttrString(%s, "%s")' % (
1094 Naming.module_cname,
1095 self.entry.name))
1097 def annotate(self, code):
1098 if hasattr(self, 'is_called') and self.is_called:
1099 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1100 if self.type.is_pyobject:
1101 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1102 else:
1103 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1105 class BackquoteNode(ExprNode):
1106 # `expr`
1107 #
1108 # arg ExprNode
1110 subexprs = ['arg']
1112 def analyse_types(self, env):
1113 self.arg.analyse_types(env)
1114 self.arg = self.arg.coerce_to_pyobject(env)
1115 self.type = py_object_type
1116 self.gil_check(env)
1117 self.is_temp = 1
1119 gil_message = "Backquote expression"
1121 def generate_result_code(self, code):
1122 code.putln(
1123 "%s = PyObject_Repr(%s); %s" % (
1124 self.result_code,
1125 self.arg.py_result(),
1126 code.error_goto_if_null(self.result_code, self.pos)))
1129 class ImportNode(ExprNode):
1130 # Used as part of import statement implementation.
1131 # Implements result =
1132 # __import__(module_name, globals(), None, name_list)
1133 #
1134 # module_name IdentifierStringNode dotted name of module
1135 # name_list ListNode or None list of names to be imported
1137 subexprs = ['module_name', 'name_list']
1139 def analyse_types(self, env):
1140 self.module_name.analyse_types(env)
1141 self.module_name = self.module_name.coerce_to_pyobject(env)
1142 if self.name_list:
1143 self.name_list.analyse_types(env)
1144 self.type = py_object_type
1145 self.gil_check(env)
1146 self.is_temp = 1
1147 env.use_utility_code(import_utility_code)
1149 gil_message = "Python import"
1151 def generate_result_code(self, code):
1152 if self.name_list:
1153 name_list_code = self.name_list.py_result()
1154 else:
1155 name_list_code = "0"
1156 code.putln(
1157 "%s = __Pyx_Import(%s, %s); %s" % (
1158 self.result_code,
1159 self.module_name.py_result(),
1160 name_list_code,
1161 code.error_goto_if_null(self.result_code, self.pos)))
1164 class IteratorNode(ExprNode):
1165 # Used as part of for statement implementation.
1166 # Implements result = iter(sequence)
1167 #
1168 # sequence ExprNode
1170 subexprs = ['sequence']
1172 def analyse_types(self, env):
1173 self.sequence.analyse_types(env)
1174 self.sequence = self.sequence.coerce_to_pyobject(env)
1175 self.type = py_object_type
1176 self.gil_check(env)
1177 self.is_temp = 1
1179 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1180 self.counter.allocate_temp(env)
1182 gil_message = "Iterating over Python object"
1184 def release_temp(self, env):
1185 env.release_temp(self.result_code)
1186 self.counter.release_temp(env)
1188 def generate_result_code(self, code):
1189 code.putln(
1190 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1191 self.sequence.py_result(),
1192 self.sequence.py_result()))
1193 code.putln(
1194 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1195 self.counter.result_code,
1196 self.result_code,
1197 self.sequence.py_result(),
1198 self.result_code))
1199 code.putln("} else {")
1200 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1201 self.counter.result_code,
1202 self.result_code,
1203 self.sequence.py_result(),
1204 code.error_goto_if_null(self.result_code, self.pos)))
1205 code.putln("}")
1208 class NextNode(AtomicExprNode):
1209 # Used as part of for statement implementation.
1210 # Implements result = iterator.next()
1211 # Created during analyse_types phase.
1212 # The iterator is not owned by this node.
1213 #
1214 # iterator ExprNode
1216 def __init__(self, iterator, env):
1217 self.pos = iterator.pos
1218 self.iterator = iterator
1219 self.type = py_object_type
1220 self.is_temp = 1
1222 def generate_result_code(self, code):
1223 for py_type in ["List", "Tuple"]:
1224 code.putln(
1225 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1226 code.putln(
1227 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1228 self.iterator.counter.result_code,
1229 py_type,
1230 self.iterator.py_result()))
1231 code.putln(
1232 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1233 self.result_code,
1234 py_type,
1235 self.iterator.py_result(),
1236 self.iterator.counter.result_code,
1237 self.result_code,
1238 self.iterator.counter.result_code))
1239 code.put("} else ")
1240 code.putln("{")
1241 code.putln(
1242 "%s = PyIter_Next(%s);" % (
1243 self.result_code,
1244 self.iterator.py_result()))
1245 code.putln(
1246 "if (!%s) {" %
1247 self.result_code)
1248 code.putln(code.error_goto_if_PyErr(self.pos))
1249 code.putln("break;")
1250 code.putln("}")
1251 code.putln("}")
1254 class ExcValueNode(AtomicExprNode):
1255 # Node created during analyse_types phase
1256 # of an ExceptClauseNode to fetch the current
1257 # exception value.
1259 def __init__(self, pos, env, var):
1260 ExprNode.__init__(self, pos)
1261 self.type = py_object_type
1262 self.var = var
1264 def calculate_result_code(self):
1265 return self.var
1267 def generate_result_code(self, code):
1268 pass
1270 def analyse_types(self, env):
1271 pass
1274 class TempNode(AtomicExprNode):
1275 # Node created during analyse_types phase
1276 # of some nodes to hold a temporary value.
1278 def __init__(self, pos, type, env):
1279 ExprNode.__init__(self, pos)
1280 self.type = type
1281 if type.is_pyobject:
1282 self.result_ctype = py_object_type
1283 self.is_temp = 1
1285 def analyse_types(self, env):
1286 return self.type
1288 def generate_result_code(self, code):
1289 pass
1292 class PyTempNode(TempNode):
1293 # TempNode holding a Python value.
1295 def __init__(self, pos, env):
1296 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1299 #-------------------------------------------------------------------
1300 #
1301 # Trailer nodes
1302 #
1303 #-------------------------------------------------------------------
1305 class IndexNode(ExprNode):
1306 # Sequence indexing.
1307 #
1308 # base ExprNode
1309 # index ExprNode
1310 # indices [ExprNode]
1311 # is_buffer_access boolean Whether this is a buffer access.
1312 #
1313 # indices is used on buffer access, index on non-buffer access.
1314 # The former contains a clean list of index parameters, the
1315 # latter whatever Python object is needed for index access.
1317 subexprs = ['base', 'index', 'indices']
1318 indices = None
1320 def __init__(self, pos, index, *args, **kw):
1321 ExprNode.__init__(self, pos, index=index, *args, **kw)
1322 self._index = index
1324 def compile_time_value(self, denv):
1325 base = self.base.compile_time_value(denv)
1326 index = self.index.compile_time_value(denv)
1327 try:
1328 return base[index]
1329 except Exception, e:
1330 self.compile_time_value_error(e)
1332 def is_ephemeral(self):
1333 return self.base.is_ephemeral()
1335 def analyse_target_declaration(self, env):
1336 pass
1338 def analyse_types(self, env):
1339 self.analyse_base_and_index_types(env, getting = 1)
1341 def analyse_target_types(self, env):
1342 self.analyse_base_and_index_types(env, setting = 1)
1344 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1345 # Note: This might be cleaned up by having IndexNode
1346 # parsed in a saner way and only construct the tuple if
1347 # needed.
1348 self.is_buffer_access = False
1350 self.base.analyse_types(env)
1352 skip_child_analysis = False
1353 buffer_access = False
1354 if self.base.type.is_buffer:
1355 assert isinstance(self.base, NameNode)
1356 if isinstance(self.index, TupleNode):
1357 indices = self.index.args
1358 else:
1359 indices = [self.index]
1360 if len(indices) == self.base.type.ndim:
1361 buffer_access = True
1362 skip_child_analysis = True
1363 for x in indices:
1364 x.analyse_types(env)
1365 if not x.type.is_int:
1366 buffer_access = False
1368 if buffer_access:
1369 self.indices = indices
1370 self.index = None
1371 self.type = self.base.type.dtype
1372 self.is_buffer_access = True
1374 if getting:
1375 # we only need a temp because result_code isn't refactored to
1376 # generation time, but this seems an ok shortcut to take
1377 self.is_temp = True
1378 if setting:
1379 if not self.base.entry.type.writable:
1380 error(self.pos, "Writing to readonly buffer")
1381 else:
1382 self.base.entry.buffer_aux.writable_needed = True
1383 else:
1384 if isinstance(self.index, TupleNode):
1385 self.index.analyse_types(env, skip_children=skip_child_analysis)
1386 elif not skip_child_analysis:
1387 self.index.analyse_types(env)
1388 if self.base.type.is_pyobject:
1389 if self.index.type.is_int:
1390 self.original_index_type = self.index.type
1391 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1392 if getting:
1393 env.use_utility_code(getitem_int_utility_code)
1394 if setting:
1395 env.use_utility_code(setitem_int_utility_code)
1396 else:
1397 self.index = self.index.coerce_to_pyobject(env)
1398 self.type = py_object_type
1399 self.gil_check(env)
1400 self.is_temp = 1
1401 else:
1402 if self.base.type.is_ptr or self.base.type.is_array:
1403 self.type = self.base.type.base_type
1404 else:
1405 error(self.pos,
1406 "Attempting to index non-array type '%s'" %
1407 self.base.type)
1408 self.type = PyrexTypes.error_type
1409 if self.index.type.is_pyobject:
1410 self.index = self.index.coerce_to(
1411 PyrexTypes.c_py_ssize_t_type, env)
1412 if not self.index.type.is_int:
1413 error(self.pos,
1414 "Invalid index type '%s'" %
1415 self.index.type)
1417 gil_message = "Indexing Python object"
1419 def check_const_addr(self):
1420 self.base.check_const_addr()
1421 self.index.check_const()
1423 def is_lvalue(self):
1424 return 1
1426 def calculate_result_code(self):
1427 if self.is_buffer_access:
1428 return "<not used>"
1429 else:
1430 return "(%s[%s])" % (
1431 self.base.result_code, self.index.result_code)
1433 def index_unsigned_parameter(self):
1434 if self.index.type.is_int:
1435 if self.original_index_type.signed:
1436 return ", 0"
1437 else:
1438 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1439 else:
1440 return ""
1442 def generate_subexpr_evaluation_code(self, code):
1443 self.base.generate_evaluation_code(code)
1444 if self.index is not None:
1445 self.index.generate_evaluation_code(code)
1446 else:
1447 for i in self.indices:
1448 i.generate_evaluation_code(code)
1450 def generate_subexpr_disposal_code(self, code):
1451 self.base.generate_disposal_code(code)
1452 if self.index is not None:
1453 self.index.generate_disposal_code(code)
1454 else:
1455 for i in self.indices:
1456 i.generate_disposal_code(code)
1458 def generate_result_code(self, code):
1459 if self.is_buffer_access:
1460 valuecode = self.buffer_access_code(code)
1461 code.putln("%s = %s;" % (self.result_code, valuecode))
1462 elif self.type.is_pyobject:
1463 if self.index.type.is_int:
1464 function = "__Pyx_GetItemInt"
1465 index_code = self.index.result_code
1466 else:
1467 function = "PyObject_GetItem"
1468 index_code = self.index.py_result()
1469 sign_code = ""
1470 code.putln(
1471 "%s = %s(%s, %s%s); if (!%s) %s" % (
1472 self.result_code,
1473 function,
1474 self.base.py_result(),
1475 index_code,
1476 self.index_unsigned_parameter(),
1477 self.result_code,
1478 code.error_goto(self.pos)))
1480 def generate_setitem_code(self, value_code, code):
1481 if self.index.type.is_int:
1482 function = "__Pyx_SetItemInt"
1483 index_code = self.index.result_code
1484 else:
1485 function = "PyObject_SetItem"
1486 index_code = self.index.py_result()
1487 code.putln(
1488 "if (%s(%s, %s, %s%s) < 0) %s" % (
1489 function,
1490 self.base.py_result(),
1491 index_code,
1492 value_code,
1493 self.index_unsigned_parameter(),
1494 code.error_goto(self.pos)))
1496 def generate_assignment_code(self, rhs, code):
1497 self.generate_subexpr_evaluation_code(code)
1498 if self.is_buffer_access:
1499 valuecode = self.buffer_access_code(code)
1500 code.putln("%s = %s;" % (valuecode, rhs.result_code))
1501 elif self.type.is_pyobject:
1502 self.generate_setitem_code(rhs.py_result(), code)
1503 else:
1504 code.putln(
1505 "%s = %s;" % (
1506 self.result_code, rhs.result_code))
1507 self.generate_subexpr_disposal_code(code)
1508 rhs.generate_disposal_code(code)
1510 def generate_deletion_code(self, code):
1511 self.generate_subexpr_evaluation_code(code)
1512 #if self.type.is_pyobject:
1513 if self.index.type.is_int:
1514 function = "PySequence_DelItem"
1515 index_code = self.index.result_code
1516 else:
1517 function = "PyObject_DelItem"
1518 index_code = self.index.py_result()
1519 code.putln(
1520 "if (%s(%s, %s) < 0) %s" % (
1521 function,
1522 self.base.py_result(),
1523 index_code,
1524 code.error_goto(self.pos)))
1525 self.generate_subexpr_disposal_code(code)
1527 def buffer_access_code(self, code):
1528 # Assign indices to temps
1529 index_temps = [code.func.allocate_temp(i.type) for i in self.indices]
1530 for temp, index in zip(index_temps, self.indices):
1531 code.putln("%s = %s;" % (temp, index.result_code))
1532 # Generate buffer access code using these temps
1533 import Buffer
1534 valuecode = Buffer.put_access(entry=self.base.entry,
1535 index_signeds=[i.type.signed for i in self.indices],
1536 index_cnames=index_temps,
1537 pos=self.pos, code=code)
1538 return valuecode
1541 class SliceIndexNode(ExprNode):
1542 # 2-element slice indexing
1543 #
1544 # base ExprNode
1545 # start ExprNode or None
1546 # stop ExprNode or None
1548 subexprs = ['base', 'start', 'stop']
1550 def compile_time_value(self, denv):
1551 base = self.base.compile_time_value(denv)
1552 start = self.start.compile_time_value(denv)
1553 stop = self.stop.compile_time_value(denv)
1554 try:
1555 return base[start:stop]
1556 except Exception, e:
1557 self.compile_time_value_error(e)
1559 def analyse_target_declaration(self, env):
1560 pass
1562 def analyse_types(self, env):
1563 self.base.analyse_types(env)
1564 if self.start:
1565 self.start.analyse_types(env)
1566 if self.stop:
1567 self.stop.analyse_types(env)
1568 self.base = self.base.coerce_to_pyobject(env)
1569 c_int = PyrexTypes.c_py_ssize_t_type
1570 if self.start:
1571 self.start = self.start.coerce_to(c_int, env)
1572 if self.stop:
1573 self.stop = self.stop.coerce_to(c_int, env)
1574 self.type = py_object_type
1575 self.gil_check(env)
1576 self.is_temp = 1
1578 gil_message = "Slicing Python object"
1580 def generate_result_code(self, code):
1581 code.putln(
1582 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1583 self.result_code,
1584 self.base.py_result(),
1585 self.start_code(),
1586 self.stop_code(),
1587 code.error_goto_if_null(self.result_code, self.pos)))
1589 def generate_assignment_code(self, rhs, code):
1590 self.generate_subexpr_evaluation_code(code)
1591 code.put_error_if_neg(self.pos,
1592 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1593 self.base.py_result(),
1594 self.start_code(),
1595 self.stop_code(),
1596 rhs.result_code))
1597 self.generate_subexpr_disposal_code(code)
1598 rhs.generate_disposal_code(code)
1600 def generate_deletion_code(self, code):
1601 self.generate_subexpr_evaluation_code(code)
1602 code.put_error_if_neg(self.pos,
1603 "PySequence_DelSlice(%s, %s, %s)" % (
1604 self.base.py_result(),
1605 self.start_code(),
1606 self.stop_code()))
1607 self.generate_subexpr_disposal_code(code)
1609 def start_code(self):
1610 if self.start:
1611 return self.start.result_code
1612 else:
1613 return "0"
1615 def stop_code(self):
1616 if self.stop:
1617 return self.stop.result_code
1618 else:
1619 return "PY_SSIZE_T_MAX"
1621 def calculate_result_code(self):
1622 # self.result_code is not used, but this method must exist
1623 return "<unused>"
1626 class SliceNode(ExprNode):
1627 # start:stop:step in subscript list
1628 #
1629 # start ExprNode
1630 # stop ExprNode
1631 # step ExprNode
1633 def compile_time_value(self, denv):
1634 start = self.start.compile_time_value(denv)
1635 stop = self.stop.compile_time_value(denv)
1636 step = step.step.compile_time_value(denv)
1637 try:
1638 return slice(start, stop, step)
1639 except Exception, e:
1640 self.compile_time_value_error(e)
1642 subexprs = ['start', 'stop', 'step']
1644 def analyse_types(self, env):
1645 self.start.analyse_types(env)
1646 self.stop.analyse_types(env)
1647 self.step.analyse_types(env)
1648 self.start = self.start.coerce_to_pyobject(env)
1649 self.stop = self.stop.coerce_to_pyobject(env)
1650 self.step = self.step.coerce_to_pyobject(env)
1651 self.type = py_object_type
1652 self.gil_check(env)
1653 self.is_temp = 1
1655 gil_message = "Constructing Python slice object"
1657 def generate_result_code(self, code):
1658 code.putln(
1659 "%s = PySlice_New(%s, %s, %s); %s" % (
1660 self.result_code,
1661 self.start.py_result(),
1662 self.stop.py_result(),
1663 self.step.py_result(),
1664 code.error_goto_if_null(self.result_code, self.pos)))
1667 class CallNode(ExprNode):
1668 def gil_check(self, env):
1669 # Make sure we're not in a nogil environment
1670 if env.nogil:
1671 error(self.pos, "Calling gil-requiring function without gil")
1674 class SimpleCallNode(CallNode):
1675 # Function call without keyword, * or ** args.
1676 #
1677 # function ExprNode
1678 # args [ExprNode]
1679 # arg_tuple ExprNode or None used internally
1680 # self ExprNode or None used internally
1681 # coerced_self ExprNode or None used internally
1682 # wrapper_call bool used internally
1683 # has_optional_args bool used internally
1685 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1687 self = None
1688 coerced_self = None
1689 arg_tuple = None
1690 wrapper_call = False
1691 has_optional_args = False
1693 def compile_time_value(self, denv):
1694 function = self.function.compile_time_value(denv)
1695 args = [arg.compile_time_value(denv) for arg in self.args]
1696 try:
1697 return function(*args)
1698 except Exception, e:
1699 self.compile_time_value_error(e)
1701 def analyse_types(self, env):
1702 function = self.function
1703 function.is_called = 1
1704 self.function.analyse_types(env)
1705 if function.is_attribute and function.is_py_attr and \
1706 function.attribute == "append" and len(self.args) == 1:
1707 # L.append(x) is almost always applied to a list
1708 self.py_func = self.function
1709 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1710 self.function.analyse_types(env)
1711 self.self = self.py_func.obj
1712 function.obj = CloneNode(self.self)
1713 env.use_utility_code(append_utility_code)
1714 if function.is_attribute and function.entry and function.entry.is_cmethod:
1715 # Take ownership of the object from which the attribute
1716 # was obtained, because we need to pass it as 'self'.
1717 self.self = function.obj
1718 function.obj = CloneNode(self.self)
1719 func_type = self.function_type()
1720 if func_type.is_pyobject:
1721 self.arg_tuple = TupleNode(self.pos, args = self.args)
1722 self.arg_tuple.analyse_types(env)
1723 self.args = None
1724 self.type = py_object_type
1725 self.gil_check(env)
1726 self.is_temp = 1
1727 else:
1728 for arg in self.args:
1729 arg.analyse_types(env)
1730 if self.self and func_type.args:
1731 # Coerce 'self' to the type expected by the method.
1732 expected_type = func_type.args[0].type
1733 self.coerced_self = CloneNode(self.self).coerce_to(
1734 expected_type, env)
1735 # Insert coerced 'self' argument into argument list.
1736 self.args.insert(0, self.coerced_self)
1737 self.analyse_c_function_call(env)
1739 def function_type(self):
1740 # Return the type of the function being called, coercing a function
1741 # pointer to a function if necessary.
1742 func_type = self.function.type
1743 if func_type.is_ptr:
1744 func_type = func_type.base_type
1745 return func_type
1747 def analyse_c_function_call(self, env):
1748 func_type = self.function_type()
1749 # Check function type
1750 if not func_type.is_cfunction:
1751 if not func_type.is_error:
1752 error(self.pos, "Calling non-function type '%s'" %
1753 func_type)
1754 self.type = PyrexTypes.error_type
1755 self.result_code = "<error>"
1756 return
1757 # Check no. of args
1758 max_nargs = len(func_type.args)
1759 expected_nargs = max_nargs - func_type.optional_arg_count
1760 actual_nargs = len(self.args)
1761 if actual_nargs < expected_nargs \
1762 or (not func_type.has_varargs and actual_nargs > max_nargs):
1763 expected_str = str(expected_nargs)
1764 if func_type.has_varargs:
1765 expected_str = "at least " + expected_str
1766 elif func_type.optional_arg_count:
1767 if actual_nargs < max_nargs:
1768 expected_str = "at least " + expected_str
1769 else:
1770 expected_str = "at most " + str(max_nargs)
1771 error(self.pos,
1772 "Call with wrong number of arguments (expected %s, got %s)"
1773 % (expected_str, actual_nargs))
1774 self.args = None
1775 self.type = PyrexTypes.error_type
1776 self.result_code = "<error>"
1777 return
1778 if func_type.optional_arg_count and expected_nargs != actual_nargs:
1779 self.has_optional_args = 1
1780 self.is_temp = 1
1781 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
1782 env.release_temp(self.opt_arg_struct)
1783 # Coerce arguments
1784 for i in range(min(max_nargs, actual_nargs)):
1785 formal_type = func_type.args[i].type
1786 self.args[i] = self.args[i].coerce_to(formal_type, env)
1787 for i in range(max_nargs, actual_nargs):
1788 if self.args[i].type.is_pyobject:
1789 error(self.args[i].pos,
1790 "Python object cannot be passed as a varargs parameter")
1791 # Calc result type and code fragment
1792 self.type = func_type.return_type
1793 if self.type.is_pyobject \
1794 or func_type.exception_value is not None \
1795 or func_type.exception_check:
1796 self.is_temp = 1
1797 if self.type.is_pyobject:
1798 self.result_ctype = py_object_type
1799 # C++ exception handler
1800 if func_type.exception_check == '+':
1801 if func_type.exception_value is None:
1802 env.use_utility_code(cpp_exception_utility_code)
1803 # Check gil
1804 if not func_type.nogil:
1805 self.gil_check(env)
1807 def calculate_result_code(self):
1808 return self.c_call_code()
1810 def c_call_code(self):
1811 func_type = self.function_type()
1812 if self.args is None or not func_type.is_cfunction:
1813 return "<error>"
1814 formal_args = func_type.args
1815 arg_list_code = []
1816 args = zip(formal_args, self.args)
1817 max_nargs = len(func_type.args)
1818 expected_nargs = max_nargs - func_type.optional_arg_count
1819 actual_nargs = len(self.args)
1820 for formal_arg, actual_arg in args[:expected_nargs]:
1821 arg_code = actual_arg.result_as(formal_arg.type)
1822 arg_list_code.append(arg_code)
1824 if func_type.optional_arg_count:
1825 if expected_nargs == actual_nargs:
1826 optional_args = 'NULL'
1827 else:
1828 optional_args = "&%s" % self.opt_arg_struct
1829 arg_list_code.append(optional_args)
1831 for actual_arg in self.args[len(formal_args):]:
1832 arg_list_code.append(actual_arg.result_code)
1833 result = "%s(%s)" % (self.function.result_code,
1834 join(arg_list_code, ", "))
1835 if self.wrapper_call or \
1836 self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1837 result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1838 return result
1840 def generate_result_code(self, code):
1841 func_type = self.function_type()
1842 if func_type.is_pyobject:
1843 arg_code = self.arg_tuple.py_result()
1844 code.putln(
1845 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1846 self.result_code,
1847 self.function.py_result(),
1848 arg_code,
1849 code.error_goto_if_null(self.result_code, self.pos)))
1850 elif func_type.is_cfunction:
1851 if self.has_optional_args:
1852 actual_nargs = len(self.args)
1853 expected_nargs = len(func_type.args) - func_type.optional_arg_count
1854 code.putln("%s.%s = %s;" % (
1855 self.opt_arg_struct,
1856 Naming.pyrex_prefix + "n",
1857 len(self.args) - expected_nargs))
1858 args = zip(func_type.args, self.args)
1859 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1860 code.putln("%s.%s = %s;" % (
1861 self.opt_arg_struct,
1862 formal_arg.name,
1863 actual_arg.result_as(formal_arg.type)))
1864 exc_checks = []
1865 if self.type.is_pyobject:
1866 exc_checks.append("!%s" % self.result_code)
1867 else:
1868 exc_val = func_type.exception_value
1869 exc_check = func_type.exception_check
1870 if exc_val is not None:
1871 exc_checks.append("%s == %s" % (self.result_code, exc_val))
1872 if exc_check:
1873 exc_checks.append("PyErr_Occurred()")
1874 if self.is_temp or exc_checks:
1875 rhs = self.c_call_code()
1876 if self.result_code:
1877 lhs = "%s = " % self.result_code
1878 if self.is_temp and self.type.is_pyobject:
1879 #return_type = self.type # func_type.return_type
1880 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1881 # "from", return_type, "to pyobject" ###
1882 rhs = typecast(py_object_type, self.type, rhs)
1883 else:
1884 lhs = ""
1885 if func_type.exception_check == '+':
1886 if func_type.exception_value is None:
1887 raise_py_exception = "__Pyx_CppExn2PyErr()"
1888 elif func_type.exception_value.type.is_pyobject:
1889 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
1890 else:
1891 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
1892 code.putln(
1893 "try {%s%s;} catch(...) {%s; %s}" % (
1894 lhs,
1895 rhs,
1896 raise_py_exception,
1897 code.error_goto(self.pos)))
1898 else:
1899 if exc_checks:
1900 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
1901 else:
1902 goto_error = ""
1903 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
1905 class GeneralCallNode(CallNode):
1906 # General Python function call, including keyword,
1907 # * and ** arguments.
1908 #
1909 # function ExprNode
1910 # positional_args ExprNode Tuple of positional arguments
1911 # keyword_args ExprNode or None Dict of keyword arguments
1912 # starstar_arg ExprNode or None Dict of extra keyword args
1914 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1916 def compile_time_value(self, denv):
1917 function = self.function.compile_time_value(denv)
1918 positional_args = self.positional_args.compile_time_value(denv)
1919 keyword_args = self.keyword_args.compile_time_value(denv)
1920 starstar_arg = self.starstar_arg.compile_time_value(denv)
1921 try:
1922 keyword_args.update(starstar_arg)
1923 return function(*positional_args, **keyword_args)
1924 except Exception, e:
1925 self.compile_time_value_error(e)
1927 def analyse_types(self, env):
1928 self.function.analyse_types(env)
1929 self.positional_args.analyse_types(env)
1930 if self.keyword_args:
1931 self.keyword_args.analyse_types(env)
1932 if self.starstar_arg:
1933 self.starstar_arg.analyse_types(env)
1934 self.function = self.function.coerce_to_pyobject(env)
1935 self.positional_args = \
1936 self.positional_args.coerce_to_pyobject(env)
1937 if self.starstar_arg:
1938 self.starstar_arg = \
1939 self.starstar_arg.coerce_to_pyobject(env)
1940 self.type = py_object_type
1941 self.gil_check(env)
1942 self.is_temp = 1
1944 def generate_result_code(self, code):
1945 if self.keyword_args and self.starstar_arg:
1946 code.put_error_if_neg(self.pos,
1947 "PyDict_Update(%s, %s)" % (
1948 self.keyword_args.py_result(),
1949 self.starstar_arg.py_result()))
1950 keyword_code = self.keyword_args.py_result()
1951 elif self.keyword_args:
1952 keyword_code = self.keyword_args.py_result()
1953 elif self.starstar_arg:
1954 keyword_code = self.starstar_arg.py_result()
1955 else:
1956 keyword_code = None
1957 if not keyword_code:
1958 call_code = "PyObject_Call(%s, %s, NULL)" % (
1959 self.function.py_result(),
1960 self.positional_args.py_result())
1961 else:
1962 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1963 self.function.py_result(),
1964 self.positional_args.py_result(),
1965 keyword_code)
1966 code.putln(
1967 "%s = %s; %s" % (
1968 self.result_code,
1969 call_code,
1970 code.error_goto_if_null(self.result_code, self.pos)))
1973 class AsTupleNode(ExprNode):
1974 # Convert argument to tuple. Used for normalising
1975 # the * argument of a function call.
1976 #
1977 # arg ExprNode
1979 subexprs = ['arg']
1981 def compile_time_value(self, denv):
1982 arg = self.arg.compile_time_value(denv)
1983 try:
1984 return tuple(arg)
1985 except Exception, e:
1986 self.compile_time_value_error(e)
1988 def analyse_types(self, env):
1989 self.arg.analyse_types(env)
1990 self.arg = self.arg.coerce_to_pyobject(env)
1991 self.type = py_object_type
1992 self.gil_check(env)
1993 self.is_temp = 1
1995 gil_message = "Constructing Python tuple"
1997 def generate_result_code(self, code):
1998 code.putln(
1999 "%s = PySequence_Tuple(%s); %s" % (
2000 self.result_code,
2001 self.arg.py_result(),
2002 code.error_goto_if_null(self.result_code, self.pos)))
2005 class AttributeNode(ExprNode):
2006 # obj.attribute
2007 #
2008 # obj ExprNode
2009 # attribute string
2010 #
2011 # Used internally:
2012 #
2013 # is_py_attr boolean Is a Python getattr operation
2014 # member string C name of struct member
2015 # is_called boolean Function call is being done on result
2016 # entry Entry Symbol table entry of attribute
2017 # interned_attr_cname string C name of interned attribute name
2019 is_attribute = 1
2020 subexprs = ['obj']
2022 type = PyrexTypes.error_type
2023 result = "<error>"
2024 entry = None
2025 is_called = 0
2027 def coerce_to(self, dst_type, env):
2028 # If coercing to a generic pyobject and this is a cpdef function
2029 # we can create the corresponding attribute
2030 if dst_type is py_object_type:
2031 entry = self.entry
2032 if entry and entry.is_cfunction and entry.as_variable:
2033 # must be a cpdef function
2034 self.is_temp = 1
2035 self.entry = entry.as_variable
2036 self.analyse_as_python_attribute(env)
2037 return self
2038 return ExprNode.coerce_to(self, dst_type, env)
2040 def compile_time_value(self, denv):
2041 attr = self.attribute
2042 if attr.beginswith("__") and attr.endswith("__"):
2043 self.error("Invalid attribute name '%s' in compile-time expression"
2044 % attr)
2045 return None
2046 obj = self.arg.compile_time_value(denv)
2047 try:
2048 return getattr(obj, attr)
2049 except Exception, e:
2050 self.compile_time_value_error(e)
2052 def analyse_target_declaration(self, env):
2053 pass
2055 def analyse_target_types(self, env):
2056 self.analyse_types(env, target = 1)
2058 def analyse_types(self, env, target = 0):
2059 if self.analyse_as_cimported_attribute(env, target):
2060 return
2061 if not target and self.analyse_as_unbound_cmethod(env):
2062 return
2063 self.analyse_as_ordinary_attribute(env, target)
2065 def analyse_as_cimported_attribute(self, env, target):
2066 # Try to interpret this as a reference to an imported
2067 # C const, type, var or function. If successful, mutates
2068 # this node into a NameNode and returns 1, otherwise
2069 # returns 0.
2070 module_scope = self.obj.analyse_as_module(env)
2071 if module_scope:
2072 entry = module_scope.lookup_here(self.attribute)
2073 if entry and (
2074 entry.is_cglobal or entry.is_cfunction
2075 or entry.is_type or entry.is_const):
2076 self.mutate_into_name_node(env, entry, target)
2077 return 1
2078 return 0
2080 def analyse_as_unbound_cmethod(self, env):
2081 # Try to interpret this as a reference to an unbound
2082 # C method of an extension type. If successful, mutates
2083 # this node into a NameNode and returns 1, otherwise
2084 # returns 0.
2085 type = self.obj.analyse_as_extension_type(env)
2086 if type:
2087 entry = type.scope.lookup_here(self.attribute)
2088 if entry and entry.is_cmethod:
2089 # Create a temporary entry describing the C method
2090 # as an ordinary function.
2091 ubcm_entry = Symtab.Entry(entry.name,
2092 "%s->%s" % (type.vtabptr_cname, entry.cname),
2093 entry.type)
2094 ubcm_entry.is_cfunction = 1
2095 ubcm_entry.func_cname = entry.func_cname
2096 ubcm_entry.is_unbound_cmethod = 1
2097 self.mutate_into_name_node(env, ubcm_entry, None)
2098 return 1
2099 return 0
2101 def analyse_as_extension_type(self, env):
2102 # Try to interpret this as a reference to an extension type
2103 # in a cimported module. Returns the extension type, or None.
2104 module_scope = self.obj.analyse_as_module(env)
2105 if module_scope:
2106 entry = module_scope.lookup_here(self.attribute)
2107 if entry and entry.is_type and entry.type.is_extension_type:
2108 return entry.type
2109 return None
2111 def analyse_as_module(self, env):
2112 # Try to interpret this as a reference to a cimported module
2113 # in another cimported module. Returns the module scope, or None.
2114 module_scope = self.obj.analyse_as_module(env)
2115 if module_scope:
2116 entry = module_scope.lookup_here(self.attribute)
2117 if entry and entry.as_module:
2118 return entry.as_module
2119 return None
2121 def mutate_into_name_node(self, env, entry, target):
2122 # Mutate this node into a NameNode and complete the
2123 # analyse_types phase.
2124 self.__class__ = NameNode
2125 self.name = self.attribute
2126 self.entry = entry
2127 del self.obj
2128 del self.attribute
2129 if target:
2130 NameNode.analyse_target_types(self, env)
2131 else:
2132 NameNode.analyse_rvalue_entry(self, env)
2134 def analyse_as_ordinary_attribute(self, env, target):
2135 self.obj.analyse_types(env)
2136 self.analyse_attribute(env)
2137 if self.entry and self.entry.is_cmethod and not self.is_called:
2138 # error(self.pos, "C method can only be called")
2139 pass
2140 ## Reference to C array turns into pointer to first element.
2141 #while self.type.is_array:
2142 # self.type = self.type.element_ptr_type()
2143 if self.is_py_attr:
2144 if not target:
2145 self.is_temp = 1
2146 self.result_ctype = py_object_type
2148 def analyse_attribute(self, env):
2149 # Look up attribute and set self.type and self.member.
2150 self.is_py_attr = 0
2151 self.member = self.attribute
2152 if self.obj.type.is_string:
2153 self.obj = self.obj.coerce_to_pyobject(env)
2154 obj_type = self.obj.type
2155 if obj_type.is_ptr or obj_type.is_array:
2156 obj_type = obj_type.base_type
2157 self.op = "->"
2158 elif obj_type.is_extension_type:
2159 self.op = "->"
2160 else:
2161 self.op = "."
2162 if obj_type.has_attributes:
2163 entry = None
2164 if obj_type.attributes_known():
2165 entry = obj_type.scope.lookup_here(self.attribute)
2166 if entry and entry.is_member:
2167 entry = None
2168 else:
2169 error(self.pos,
2170 "Cannot select attribute of incomplete type '%s'"
2171 % obj_type)
2172 self.type = PyrexTypes.error_type
2173 return
2174 self.entry = entry
2175 if entry:
2176 if obj_type.is_extension_type and entry.name == "__weakref__":
2177 error(self.pos, "Illegal use of special attribute __weakref__")
2178 # methods need the normal attribute lookup
2179 # because they do not have struct entries
2180 if entry.is_variable or entry.is_cmethod:
2181 self.type = entry.type
2182 self.member = entry.cname
2183 return
2184 else:
2185 # If it's not a variable or C method, it must be a Python
2186 # method of an extension type, so we treat it like a Python
2187 # attribute.
2188 pass
2189 # If we get here, the base object is not a struct/union/extension
2190 # type, or it is an extension type and the attribute is either not
2191 # declared or is declared as a Python method. Treat it as a Python
2192 # attribute reference.
2193 self.analyse_as_python_attribute(env)
2195 def analyse_as_python_attribute(self, env):
2196 obj_type = self.obj.type
2197 self.member = self.attribute
2198 if obj_type.is_pyobject:
2199 self.type = py_object_type
2200 self.is_py_attr = 1
2201 self.interned_attr_cname = env.intern_identifier(self.attribute)
2202 self.gil_check(env)
2203 else:
2204 if not obj_type.is_error:
2205 error(self.pos,
2206 "Object of type '%s' has no attribute '%s'" %
2207 (obj_type, self.attribute))
2209 gil_message = "Accessing Python attribute"
2211 def is_simple(self):
2212 if self.obj:
2213 return self.result_in_temp() or self.obj.is_simple()
2214 else:
2215 return NameNode.is_simple(self)
2217 def is_lvalue(self):
2218 if self.obj:
2219 return 1
2220 else:
2221 return NameNode.is_lvalue(self)
2223 def is_ephemeral(self):
2224 if self.obj:
2225 return self.obj.is_ephemeral()
2226 else:
2227 return NameNode.is_ephemeral(self)
2229 def calculate_result_code(self):
2230 #print "AttributeNode.calculate_result_code:", self.member ###
2231 #print "...obj node =", self.obj, "code", self.obj.result_code ###
2232 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2233 obj = self.obj
2234 obj_code = obj.result_as(obj.type)
2235 #print "...obj_code =", obj_code ###
2236 if self.entry and self.entry.is_cmethod:
2237 if obj.type.is_extension_type:
2238 return "((struct %s *)%s%s%s)->%s" % (
2239 obj.type.vtabstruct_cname, obj_code, self.op,
2240 obj.type.vtabslot_cname, self.member)
2241 else:
2242 return self.member
2243 else:
2244 return "%s%s%s" % (obj_code, self.op, self.member)
2246 def generate_result_code(self, code):
2247 if self.is_py_attr:
2248 code.putln(
2249 '%s = PyObject_GetAttr(%s, %s); %s' % (
2250 self.result_code,
2251 self.obj.py_result(),
2252 self.interned_attr_cname,
2253 code.error_goto_if_null(self.result_code, self.pos)))
2255 def generate_assignment_code(self, rhs, code):
2256 self.obj.generate_evaluation_code(code)
2257 if self.is_py_attr:
2258 code.put_error_if_neg(self.pos,
2259 'PyObject_SetAttr(%s, %s, %s)' % (
2260 self.obj.py_result(),
2261 self.interned_attr_cname,
2262 rhs.py_result()))
2263 rhs.generate_disposal_code(code)
2264 else:
2265 select_code = self.result_code
2266 if self.type.is_pyobject:
2267 rhs.make_owned_reference(code)
2268 code.put_decref(select_code, self.ctype())
2269 code.putln(
2270 "%s = %s;" % (
2271 select_code,
2272 rhs.result_as(self.ctype())))
2273 #rhs.result_code))
2274 rhs.generate_post_assignment_code(code)
2275 self.obj.generate_disposal_code(code)
2277 def generate_deletion_code(self, code):
2278 self.obj.generate_evaluation_code(code)
2279 if self.is_py_attr:
2280 code.put_error_if_neg(self.pos,
2281 'PyObject_DelAttr(%s, %s)' % (
2282 self.obj.py_result(),
2283 self.interned_attr_cname))
2284 else:
2285 error(self.pos, "Cannot delete C attribute of extension type")
2286 self.obj.generate_disposal_code(code)
2288 def annotate(self, code):
2289 if self.is_py_attr:
2290 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2291 else:
2292 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2294 #-------------------------------------------------------------------
2295 #
2296 # Constructor nodes
2297 #
2298 #-------------------------------------------------------------------
2300 class SequenceNode(ExprNode):
2301 # Base class for list and tuple constructor nodes.
2302 # Contains common code for performing sequence unpacking.
2303 #
2304 # args [ExprNode]
2305 # iterator ExprNode
2306 # unpacked_items [ExprNode] or None
2307 # coerced_unpacked_items [ExprNode] or None
2309 subexprs = ['args']
2311 is_sequence_constructor = 1
2312 unpacked_items = None
2314 def compile_time_value_list(self, denv):
2315 return [arg.compile_time_value(denv) for arg in self.args]
2317 def analyse_target_declaration(self, env):
2318 for arg in self.args:
2319 arg.analyse_target_declaration(env)
2321 def analyse_types(self, env, skip_children=False):
2322 for i in range(len(self.args)):
2323 arg = self.args[i]
2324 if not skip_children: arg.analyse_types(env)
2325 self.args[i] = arg.coerce_to_pyobject(env)
2326 self.type = py_object_type
2327 self.gil_check(env)
2328 self.is_temp = 1
2330 def analyse_target_types(self, env):
2331 self.iterator = PyTempNode(self.pos, env)
2332 self.unpacked_items = []
2333 self.coerced_unpacked_items = []
2334 for arg in self.args:
2335 arg.analyse_target_types(env)
2336 unpacked_item = PyTempNode(self.pos, env)
2337 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2338 self.unpacked_items.append(unpacked_item)
2339 self.coerced_unpacked_items.append(coerced_unpacked_item)
2340 self.type = py_object_type
2341 env.use_utility_code(unpacking_utility_code)
2343 def allocate_target_temps(self, env, rhs):
2344 self.iterator.allocate_temps(env)
2345 for arg, node in zip(self.args, self.coerced_unpacked_items):
2346 node.allocate_temps(env)
2347 arg.allocate_target_temps(env, node)
2348 #arg.release_target_temp(env)
2349 #node.release_temp(env)
2350 if rhs:
2351 rhs.release_temp(env)
2352 self.iterator.release_temp(env)
2354 # def release_target_temp(self, env):
2355 # #for arg in self.args:
2356 # # arg.release_target_temp(env)
2357 # #for node in self.coerced_unpacked_items:
2358 # # node.release_temp(env)
2359 # self.iterator.release_temp(env)
2361 def generate_result_code(self, code):
2362 self.generate_operation_code(code)
2364 def generate_assignment_code(self, rhs, code):
2365 code.putln(
2366 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2367 rhs.py_result(),
2368 rhs.py_result(),
2369 len(self.args)))
2370 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2371 for i in range(len(self.args)):
2372 item = self.unpacked_items[i]
2373 code.putln(
2374 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2375 item.result_code,
2376 i))
2377 code.put_incref(item.result_code, item.ctype())
2378 value_node = self.coerced_unpacked_items[i]
2379 value_node.generate_evaluation_code(code)
2380 self.args[i].generate_assignment_code(value_node, code)
2382 rhs.generate_disposal_code(code)
2383 code.putln("}")
2384 code.putln("else {")
2386 code.putln(
2387 "%s = PyObject_GetIter(%s); %s" % (
2388 self.iterator.result_code,
2389 rhs.py_result(),
2390 code.error_goto_if_null(self.iterator.result_code, self.pos)))
2391 rhs.generate_disposal_code(code)
2392 for i in range(len(self.args)):
2393 item = self.unpacked_items[i]
2394 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2395 self.iterator.py_result(), i)
2396 code.putln(
2397 "%s = %s; %s" % (
2398 item.result_code,
2399 typecast(item.ctype(), py_object_type, unpack_code),
2400 code.error_goto_if_null(item.result_code, self.pos)))
2401 value_node = self.coerced_unpacked_items[i]
2402 value_node.generate_evaluation_code(code)
2403 self.args[i].generate_assignment_code(value_node, code)
2404 code.put_error_if_neg(self.pos,
2405 "__Pyx_EndUnpack(%s)" % (
2406 self.iterator.py_result()))
2407 if debug_disposal_code:
2408 print("UnpackNode.generate_assignment_code:")
2409 print("...generating disposal code for %s" % self.iterator)
2410 self.iterator.generate_disposal_code(code)
2412 code.putln("}")
2414 def annotate(self, code):
2415 for arg in self.args:
2416 arg.annotate(code)
2417 if self.unpacked_items:
2418 for arg in self.unpacked_items:
2419 arg.annotate(code)
2420 for arg in self.coerced_unpacked_items:
2421 arg.annotate(code)
2424 class TupleNode(SequenceNode):
2425 # Tuple constructor.
2427 gil_message = "Constructing Python tuple"
2429 def analyse_types(self, env, skip_children=False):
2430 if len(self.args) == 0:
2431 self.is_temp = 0
2432 self.is_literal = 1
2433 else:
2434 SequenceNode.analyse_types(self, env, skip_children)
2435 self.type = tuple_type
2437 def calculate_result_code(self):
2438 if len(self.args) > 0:
2439 error(self.pos, "Positive length tuples must be constructed.")
2440 else:
2441 return Naming.empty_tuple
2443 def compile_time_value(self, denv):
2444 values = self.compile_time_value_list(denv)
2445 try:
2446 return tuple(values)
2447 except Exception, e:
2448 self.compile_time_value_error(e)
2450 def generate_operation_code(self, code):
2451 if len(self.args) == 0:
2452 # result_code is Naming.empty_tuple
2453 return
2454 code.putln(
2455 "%s = PyTuple_New(%s); %s" % (
2456 self.result_code,
2457 len(self.args),
2458 code.error_goto_if_null(self.result_code, self.pos)))
2459 for i in range(len(self.args)):
2460 arg = self.args[i]
2461 if not arg.result_in_temp():
2462 code.put_incref(arg.result_code, arg.ctype())
2463 code.putln(
2464 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2465 self.result_code,
2466 i,
2467 arg.py_result()))
2469 def generate_subexpr_disposal_code(self, code):
2470 # We call generate_post_assignment_code here instead
2471 # of generate_disposal_code, because values were stored
2472 # in the tuple using a reference-stealing operation.
2473 for arg in self.args:
2474 arg.generate_post_assignment_code(code)
2477 class ListNode(SequenceNode):
2478 # List constructor.
2480 gil_message = "Constructing Python list"
2482 def analyse_types(self, env):
2483 SequenceNode.analyse_types(self, env)
2484 self.type = list_type
2486 def compile_time_value(self, denv):
2487 return self.compile_time_value_list(denv)
2489 def generate_operation_code(self, code):
2490 code.putln("%s = PyList_New(%s); %s" %
2491 (self.result_code,
2492 len(self.args),
2493 code.error_goto_if_null(self.result_code, self.pos)))
2494 for i in range(len(self.args)):
2495 arg = self.args[i]
2496 #if not arg.is_temp:
2497 if not arg.result_in_temp():
2498 code.put_incref(arg.result_code, arg.ctype())
2499 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2500 (self.result_code,
2501 i,
2502 arg.py_result()))
2504 def generate_subexpr_disposal_code(self, code):
2505 # We call generate_post_assignment_code here instead
2506 # of generate_disposal_code, because values were stored
2507 # in the list using a reference-stealing operation.
2508 for arg in self.args:
2509 arg.generate_post_assignment_code(code)
2512 class ListComprehensionNode(SequenceNode):
2514 subexprs = []
2515 is_sequence_constructor = 0 # not unpackable
2517 def analyse_types(self, env):
2518 self.type = list_type
2519 self.is_temp = 1
2520 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2522 def allocate_temps(self, env, result = None):
2523 if debug_temp_alloc:
2524 print("%s Allocating temps" % self)
2525 self.allocate_temp(env, result)
2526 self.loop.analyse_declarations(env)
2527 self.loop.analyse_expressions(env)
2529 def generate_operation_code(self, code):
2530 code.putln("%s = PyList_New(%s); %s" %
2531 (self.result_code,
2532 0,
2533 code.error_goto_if_null(self.result_code, self.pos)))
2534 self.loop.generate_execution_code(code)
2536 def annotate(self, code):
2537 self.loop.annotate(code)
2540 class ListComprehensionAppendNode(ExprNode):
2542 subexprs = ['expr']
2544 def analyse_types(self, env):
2545 self.expr.analyse_types(env)
2546 if self.expr.type != py_object_type:
2547 self.expr = self.expr.coerce_to_pyobject(env)
2548 self.type = PyrexTypes.c_int_type
2549 self.is_temp = 1
2551 def generate_result_code(self, code):
2552 code.putln("%s = PyList_Append(%s, %s); %s" %
2553 (self.result_code,
2554 self.target.result_code,
2555 self.expr.result_code,
2556 code.error_goto_if(self.result_code, self.pos)))
2559 class DictNode(ExprNode):
2560 # Dictionary constructor.
2561 #
2562 # key_value_pairs [DictItemNode]
2564 subexprs = ['key_value_pairs']
2566 def compile_time_value(self, denv):
2567 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2568 for item in self.key_value_pairs]
2569 try:
2570 return dict(pairs)
2571 except Exception, e:
2572 self.compile_time_value_error(e)
2574 def analyse_types(self, env):
2575 for item in self.key_value_pairs:
2576 item.analyse_types(env)
2577 self.type = dict_type
2578 self.gil_check(env)
2579 self.is_temp = 1
2581 gil_message = "Constructing Python dict"
2583 def allocate_temps(self, env, result = None):
2584 # Custom method used here because key-value
2585 # pairs are evaluated and used one at a time.
2586 self.allocate_temp(env, result)
2587 for item in self.key_value_pairs:
2588 item.key.allocate_temps(env)
2589 item.value.allocate_temps(env)
2590 item.key.release_temp(env)
2591 item.value.release_temp(env)
2593 def generate_evaluation_code(self, code):
2594 # Custom method used here because key-value
2595 # pairs are evaluated and used one at a time.
2596 code.putln(
2597 "%s = PyDict_New(); %s" % (
2598 self.result_code,
2599 code.error_goto_if_null(self.result_code, self.pos)))
2600 for item in self.key_value_pairs:
2601 item.generate_evaluation_code(code)
2602 code.put_error_if_neg(self.pos,
2603 "PyDict_SetItem(%s, %s, %s)" % (
2604 self.result_code,
2605 item.key.py_result(),
2606 item.value.py_result()))
2607 item.generate_disposal_code(code)
2609 def annotate(self, code):
2610 for item in self.key_value_pairs:
2611 item.annotate(code)
2613 class DictItemNode(ExprNode):
2614 # Represents a single item in a DictNode
2615 #
2616 # key ExprNode
2617 # value ExprNode
2618 subexprs = ['key', 'value']
2620 def analyse_types(self, env):
2621 self.key.analyse_types(env)
2622 self.value.analyse_types(env)
2623 self.key = self.key.coerce_to_pyobject(env)
2624 self.value = self.value.coerce_to_pyobject(env)
2626 def generate_evaluation_code(self, code):
2627 self.key.generate_evaluation_code(code)
2628 self.value.generate_evaluation_code(code)
2630 def generate_disposal_code(self, code):
2631 self.key.generate_disposal_code(code)
2632 self.value.generate_disposal_code(code)
2635 class ClassNode(ExprNode):
2636 # Helper class used in the implementation of Python
2637 # class definitions. Constructs a class object given
2638 # a name, tuple of bases and class dictionary.
2639 #
2640 # name EncodedString Name of the class
2641 # cname string Class name as a Python string
2642 # bases ExprNode Base class tuple
2643 # dict ExprNode Class dict (not owned by this node)
2644 # doc ExprNode or None Doc string
2645 # module_name string Name of defining module
2647 subexprs = ['bases', 'doc']
2649 def analyse_types(self, env):
2650 self.cname = env.intern_identifier(self.name)
2651 self.bases.analyse_types(env)
2652 if self.doc:
2653 self.doc.analyse_types(env)
2654 self.doc = self.doc.coerce_to_pyobject(env)
2655 self.module_name = env.global_scope().qualified_name
2656 self.type = py_object_type
2657 self.gil_check(env)
2658 self.is_temp = 1
2659 env.use_utility_code(create_class_utility_code);
2661 gil_message = "Constructing Python class"
2663 def generate_result_code(self, code):
2664 if self.doc:
2665 code.put_error_if_neg(self.pos,
2666 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2667 self.dict.py_result(),
2668 self.doc.py_result()))
2669 code.putln(
2670 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2671 self.result_code,
2672 self.bases.py_result(),
2673 self.dict.py_result(),
2674 self.cname,
2675 self.module_name,
2676 code.error_goto_if_null(self.result_code, self.pos)))
2679 class UnboundMethodNode(ExprNode):
2680 # Helper class used in the implementation of Python
2681 # class definitions. Constructs an unbound method
2682 # object from a class and a function.
2683 #
2684 # class_cname string C var holding the class object
2685 # function ExprNode Function object
2687 subexprs = ['function']
2689 def analyse_types(self, env):
2690 self.function.analyse_types(env)
2691 self.type = py_object_type
2692 self.gil_check(env)
2693 self.is_temp = 1
2695 gil_message = "Constructing an unbound method"
2697 def generate_result_code(self, code):
2698 code.putln(
2699 "%s = PyMethod_New(%s, 0, %s); %s" % (
2700 self.result_code,
2701 self.function.py_result(),
2702 self.class_cname,
2703 code.error_goto_if_null(self.result_code, self.pos)))
2706 class PyCFunctionNode(AtomicExprNode):
2707 # Helper class used in the implementation of Python
2708 # class definitions. Constructs a PyCFunction object
2709 # from a PyMethodDef struct.
2710 #
2711 # pymethdef_cname string PyMethodDef structure
2713 def analyse_types(self, env):
2714 self.type = py_object_type
2715 self.gil_check(env)
2716 self.is_temp = 1
2718 gil_message = "Constructing Python function"
2720 def generate_result_code(self, code):
2721 code.putln(
2722 "%s = PyCFunction_New(&%s, 0); %s" % (
2723 self.result_code,
2724 self.pymethdef_cname,
2725 code.error_goto_if_null(self.result_code, self.pos)))
2727 #-------------------------------------------------------------------
2728 #
2729 # Unary operator nodes
2730 #
2731 #-------------------------------------------------------------------
2733 compile_time_unary_operators = {
2734 'not': operator.not_,
2735 '~': operator.inv,
2736 '-': operator.neg,
2737 '+': operator.pos,
2738 }
2740 class UnopNode(ExprNode):
2741 # operator string
2742 # operand ExprNode
2743 #
2744 # Processing during analyse_expressions phase:
2745 #
2746 # analyse_c_operation
2747 # Called when the operand is not a pyobject.
2748 # - Check operand type and coerce if needed.
2749 # - Determine result type and result code fragment.
2750 # - Allocate temporary for result if needed.
2752 subexprs = ['operand']
2754 def compile_time_value(self, denv):
2755 func = compile_time_unary_operators.get(self.operator)
2756 if not func:
2757 error(self.pos,
2758 "Unary '%s' not supported in compile-time expression"
2759 % self.operator)
2760 operand = self.operand.compile_time_value(denv)
2761 try:
2762 return func(operand)
2763 except Exception, e:
2764 self.compile_time_value_error(e)
2766 def analyse_types(self, env):
2767 self.operand.analyse_types(env)
2768 if self.is_py_operation():
2769 self.coerce_operand_to_pyobject(env)
2770 self.type = py_object_type
2771 self.gil_check(env)
2772 self.is_temp = 1
2773 else:
2774 self.analyse_c_operation(env)
2776 def check_const(self):
2777 self.operand.check_const()
2779 def is_py_operation(self):
2780 return self.operand.type.is_pyobject
2782 def coerce_operand_to_pyobject(self, env):
2783 self.operand = self.operand.coerce_to_pyobject(env)
2785 def generate_result_code(self, code):
2786 if self.operand.type.is_pyobject:
2787 self.generate_py_operation_code(code)
2788 else:
2789 if self.is_temp:
2790 self.generate_c_operation_code(code)
2792 def generate_py_operation_code(self, code):
2793 function = self.py_operation_function()
2794 code.putln(
2795 "%s = %s(%s); %s" % (
2796 self.result_code,
2797 function,
2798 self.operand.py_result(),
2799 code.error_goto_if_null(self.result_code, self.pos)))
2801 def type_error(self):
2802 if not self.operand.type.is_error:
2803 error(self.pos, "Invalid operand type for '%s' (%s)" %
2804 (self.operator, self.operand.type))
2805 self.type = PyrexTypes.error_type
2808 class NotNode(ExprNode):
2809 # 'not' operator
2810 #
2811 # operand ExprNode
2813 def compile_time_value(self, denv):
2814 operand = self.operand.compile_time_value(denv)
2815 try:
2816 return not operand
2817 except Exception, e:
2818 self.compile_time_value_error(e)
2820 subexprs = ['operand']
2822 def analyse_types(self, env):
2823 self.operand.analyse_types(env)
2824 self.operand = self.operand.coerce_to_boolean(env)
2825 self.type = PyrexTypes.c_bint_type
2827 def calculate_result_code(self):
2828 return "(!%s)" % self.operand.result_code
2830 def generate_result_code(self, code):
2831 pass
2834 class UnaryPlusNode(UnopNode):
2835 # unary '+' operator
2837 operator = '+'
2839 def analyse_c_operation(self, env):
2840 self.type = self.operand.type
2842 def py_operation_function(self):
2843 return "PyNumber_Positive"
2845 def calculate_result_code(self):
2846 return self.operand.result_code
2849 class UnaryMinusNode(UnopNode):
2850 # unary '-' operator
2852 operator = '-'
2854 def analyse_c_operation(self, env):
2855 if self.operand.type.is_numeric:
2856 self.type = self.operand.type
2857 else:
2858 self.type_error()
2860 def py_operation_function(self):
2861 return "PyNumber_Negative"
2863 def calculate_result_code(self):
2864 return "(-%s)" % self.operand.result_code
2867 class TildeNode(UnopNode):
2868 # unary '~' operator
2870 def analyse_c_operation(self, env):
2871 if self.operand.type.is_int:
2872 self.type = self.operand.type
2873 else:
2874 self.type_error()
2876 def py_operation_function(self):
2877 return "PyNumber_Invert"
2879 def calculate_result_code(self):
2880 return "(~%s)" % self.operand.result_code
2883 class AmpersandNode(ExprNode):
2884 # The C address-of operator.
2885 #
2886 # operand ExprNode
2888 subexprs = ['operand']
2890 def analyse_types(self, env):
2891 self.operand.analyse_types(env)
2892 argtype = self.operand.type
2893 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2894 self.error("Taking address of non-lvalue")
2895 return
2896 if argtype.is_pyobject:
2897 self.error("Cannot take address of Python variable")
2898 return
2899 self.type = PyrexTypes.c_ptr_type(argtype)
2901 def check_const(self):
2902 self.operand.check_const_addr()
2904 def error(self, mess):
2905 error(self.pos, mess)
2906 self.type = PyrexTypes.error_type
2907 self.result_code = "<error>"
2909 def calculate_result_code(self):
2910 return "(&%s)" % self.operand.result_code
2912 def generate_result_code(self, code):
2913 pass
2916 unop_node_classes = {
2917 "+": UnaryPlusNode,
2918 "-": UnaryMinusNode,
2919 "~": TildeNode,
2920 }
2922 def unop_node(pos, operator, operand):
2923 # Construct unnop node of appropriate class for
2924 # given operator.
2925 if isinstance(operand, IntNode) and operator == '-':
2926 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
2927 elif isinstance(operand, UnopNode) and operand.operator == operator:
2928 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
2929 return unop_node_classes[operator](pos,
2930 operator = operator,
2931 operand = operand)
2934 class TypecastNode(ExprNode):
2935 # C type cast
2936 #
2937 # operand ExprNode
2938 # base_type CBaseTypeNode
2939 # declarator CDeclaratorNode
2940 #
2941 # If used from a transform, one can if wanted specify the attribute
2942 # "type" directly and leave base_type and declarator to None
2944 subexprs = ['operand']
2945 base_type = declarator = type = None
2947 def analyse_types(self, env):
2948 if self.type is None:
2949 base_type = self.base_type.analyse(env)
2950 _, self.type = self.declarator.analyse(base_type, env)
2951 if self.type.is_cfunction:
2952 error(self.pos,
2953 "Cannot cast to a function type")
2954 self.type = PyrexTypes.error_type
2955 self.operand.analyse_types(env)
2956 to_py = self.type.is_pyobject
2957 from_py = self.operand.type.is_pyobject
2958 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
2959 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
2960 if to_py and not from_py:
2961 if self.operand.type.to_py_function:
2962 self.result_ctype = py_object_type
2963 self.operand = self.operand.coerce_to_pyobject(env)
2964 else:
2965 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
2966 self.operand = self.operand.coerce_to_simple(env)
2967 elif from_py and not to_py:
2968 if self.type.from_py_function:
2969 self.operand = self.operand.coerce_to(self.type, env)
2970 else:
2971 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
2972 elif from_py and to_py:
2973 if self.typecheck and self.type.is_extension_type:
2974 self.operand = PyTypeTestNode(self.operand, self.type, env)
2976 def check_const(self):
2977 self.operand.check_const()
2979 def calculate_result_code(self):
2980 opnd = self.operand
2981 result_code = self.type.cast_code(opnd.result_code)
2982 return result_code
2984 def result_as(self, type):
2985 if self.type.is_pyobject and not self.is_temp:
2986 # Optimise away some unnecessary casting
2987 return self.operand.result_as(type)
2988 else:
2989 return ExprNode.result_as(self, type)
2991 def generate_result_code(self, code):
2992 if self.is_temp:
2993 code.putln(
2994 "%s = (PyObject *)%s;" % (
2995 self.result_code,
2996 self.operand.result_code))
2997 code.put_incref(self.result_code, self.ctype())
3000 class SizeofNode(ExprNode):
3001 # Abstract base class for sizeof(x) expression nodes.
3003 def check_const(self):
3004 pass
3006 def generate_result_code(self, code):
3007 pass
3010 class SizeofTypeNode(SizeofNode):
3011 # C sizeof function applied to a type
3012 #
3013 # base_type CBaseTypeNode
3014 # declarator CDeclaratorNode
3016 subexprs = []
3018 def analyse_types(self, env):
3019 base_type = self.base_type.analyse(env)
3020 _, arg_type = self.declarator.analyse(base_type, env)
3021 self.arg_type = arg_type
3022 if arg_type.is_pyobject and not arg_type.is_extension_type:
3023 error(self.pos, "Cannot take sizeof Python object")
3024 elif arg_type.is_void:
3025 error(self.pos, "Cannot take sizeof void")
3026 elif not arg_type.is_complete():
3027 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3028 self.type = PyrexTypes.c_int_type
3030 def calculate_result_code(self):
3031 if self.arg_type.is_extension_type:
3032 # the size of the pointer is boring
3033 # we want the size of the actual struct
3034 arg_code = self.arg_type.declaration_code("", deref=1)
3035 else:
3036 arg_code = self.arg_type.declaration_code("")
3037 return "(sizeof(%s))" % arg_code
3040 class SizeofVarNode(SizeofNode):
3041 # C sizeof function applied to a variable
3042 #
3043 # operand ExprNode
3045 subexprs = ['operand']
3047 def analyse_types(self, env):
3048 self.operand.analyse_types(env)
3049 self.type = PyrexTypes.c_int_type
3051 def calculate_result_code(self):
3052 return "(sizeof(%s))" % self.operand.result_code
3054 def generate_result_code(self, code):
3055 pass
3058 #-------------------------------------------------------------------
3059 #
3060 # Binary operator nodes
3061 #
3062 #-------------------------------------------------------------------
3064 def _not_in(x, seq):
3065 return x not in seq
3067 compile_time_binary_operators = {
3068 '<': operator.lt,
3069 '<=': operator.le,
3070 '==': operator.eq,
3071 '!=': operator.ne,
3072 '>=': operator.ge,
3073 '>': operator.gt,
3074 'is': operator.is_,
3075 'is_not': operator.is_not,
3076 '+': operator.add,
3077 '&': operator.and_,
3078 '/': operator.div,
3079 '//': operator.floordiv,
3080 '<<': operator.lshift,
3081 '%': operator.mod,
3082 '*': operator.mul,
3083 '|': operator.or_,
3084 '**': operator.pow,
3085 '>>': operator.rshift,
3086 '-': operator.sub,
3087 #'/': operator.truediv,
3088 '^': operator.xor,
3089 'in': operator.contains,
3090 'not_in': _not_in,
3091 }
3093 def get_compile_time_binop(node):
3094 func = compile_time_binary_operators.get(node.operator)
3095 if not func:
3096 error(node.pos,
3097 "Binary '%s' not supported in compile-time expression"
3098 % node.operator)
3099 return func
3101 class BinopNode(ExprNode):
3102 # operator string
3103 # operand1 ExprNode
3104 # operand2 ExprNode
3105 #
3106 # Processing during analyse_expressions phase:
3107 #
3108 # analyse_c_operation
3109 # Called when neither operand is a pyobject.
3110 # - Check operand types and coerce if needed.
3111 # - Determine result type and result code fragment.
3112 # - Allocate temporary for result if needed.
3114 subexprs = ['operand1', 'operand2']
3116 def compile_time_value(self, denv):
3117 func = get_compile_time_binop(self)
3118 operand1 = self.operand1.compile_time_value(denv)
3119 operand2 = self.operand2.compile_time_value(denv)
3120 try:
3121 return func(operand1, operand2)
3122 except Exception, e:
3123 self.compile_time_value_error(e)
3125 def analyse_types(self, env):
3126 self.operand1.analyse_types(env)
3127 self.operand2.analyse_types(env)
3128 if self.is_py_operation():
3129 self.coerce_operands_to_pyobjects(env)
3130 self.type = py_object_type
3131 self.gil_check(env)
3132 self.is_temp = 1
3133 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3134 self.operand1 = self.operand1.coerce_to_temp(env)
3135 else:
3136 self.analyse_c_operation(env)
3138 def is_py_operation(self):
3139 return (self.operand1.type.is_pyobject
3140 or self.operand2.type.is_pyobject)
3142 def coerce_operands_to_pyobjects(self, env):
3143 self.operand1 = self.operand1.coerce_to_pyobject(env)
3144 self.operand2 = self.operand2.coerce_to_pyobject(env)
3146 def check_const(self):
3147 self.operand1.check_const()
3148 self.operand2.check_const()
3150 def generate_result_code(self, code):
3151 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3152 if self.operand1.type.is_pyobject:
3153 function = self.py_operation_function()
3154 if function == "PyNumber_Power":
3155 extra_args = ", Py_None"
3156 else:
3157 extra_args = ""
3158 code.putln(
3159 "%s = %s(%s, %s%s); %s" % (
3160 self.result_code,
3161 function,
3162 self.operand1.py_result(),
3163 self.operand2.py_result(),
3164 extra_args,
3165 code.error_goto_if_null(self.result_code, self.pos)))
3166 else:
3167 if self.is_temp:
3168 self.generate_c_operation_code(code)
3170 def type_error(self):
3171 if not (self.operand1.type.is_error
3172 or self.operand2.type.is_error):
3173 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3174 (self.operator, self.operand1.type,
3175 self.operand2.type))
3176 self.type = PyrexTypes.error_type
3179 class NumBinopNode(BinopNode):
3180 # Binary operation taking numeric arguments.
3182 def analyse_c_operation(self, env):
3183 type1 = self.operand1.type
3184 type2 = self.operand2.type
3185 if self.operator == "**" and type1.is_int and type2.is_int:
3186 error(self.pos, "** with two C int types is ambiguous")
3187 self.type = error_type
3188 return
3189 self.type = self.compute_c_result_type(type1, type2)
3190 if not self.type:
3191 self.type_error()
3193 def compute_c_result_type(self, type1, type2):
3194 if self.c_types_okay(type1, type2):
3195 return PyrexTypes.widest_numeric_type(type1, type2)
3196 else:
3197 return None
3199 def c_types_okay(self, type1, type2):
3200 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3201 return (type1.is_numeric or type1.is_enum) \
3202 and (type2.is_numeric or type2.is_enum)
3204 def calculate_result_code(self):
3205 return "(%s %s %s)" % (
3206 self.operand1.result_code,
3207 self.operator,
3208 self.operand2.result_code)
3210 def py_operation_function(self):
3211 return self.py_functions[self.operator]
3213 py_functions = {
3214 "|": "PyNumber_Or",
3215 "^": "PyNumber_Xor",
3216 "&": "PyNumber_And",
3217 "<<": "PyNumber_Lshift",
3218 ">>": "PyNumber_Rshift",
3219 "+": "PyNumber_Add",
3220 "-": "PyNumber_Subtract",
3221 "*": "PyNumber_Multiply",
3222 "/": "__Pyx_PyNumber_Divide",
3223 "//": "PyNumber_FloorDivide",
3224 "%": "PyNumber_Remainder",
3225 "**": "PyNumber_Power"
3226 }
3229 class IntBinopNode(NumBinopNode):
3230 # Binary operation taking integer arguments.
3232 def c_types_okay(self, type1, type2):
3233 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3234 return (type1.is_int or type1.is_enum) \
3235 and (type2.is_int or type2.is_enum)
3238 class AddNode(NumBinopNode):
3239 # '+' operator.
3241 def is_py_operation(self):
3242 if self.operand1.type.is_string \
3243 and self.operand2.type.is_string:
3244 return 1
3245 else:
3246 return NumBinopNode.is_py_operation(self)
3248 def compute_c_result_type(self, type1, type2):
3249 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3250 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3251 return type1
3252 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3253 return type2
3254 else:
3255 return NumBinopNode.compute_c_result_type(
3256 self, type1, type2)
3259 class SubNode(NumBinopNode):
3260 # '-' operator.
3262 def compute_c_result_type(self, type1, type2):
3263 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3264 return type1
3265 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3266 return PyrexTypes.c_int_type
3267 else:
3268 return NumBinopNode.compute_c_result_type(
3269 self, type1, type2)
3272 class MulNode(NumBinopNode):
3273 # '*' operator.
3275 def is_py_operation(self):
3276 type1 = self.operand1.type
3277 type2 = self.operand2.type
3278 if (type1.is_string and type2.is_int) \
3279 or (type2.is_string and type1.is_int):
3280 return 1
3281 else:
3282 return NumBinopNode.is_py_operation(self)
3285 class FloorDivNode(NumBinopNode):
3286 # '//' operator.
3288 def calculate_result_code(self):
3289 return "(%s %s %s)" % (
3290 self.operand1.result_code,
3291 "/", # c division is by default floor-div
3292 self.operand2.result_code)
3295 class ModNode(IntBinopNode):
3296 # '%' operator.
3298 def is_py_operation(self):
3299 return (self.operand1.type.is_string
3300 or self.operand2.type.is_string
3301 or IntBinopNode.is_py_operation(self))
3304 class PowNode(NumBinopNode):
3305 # '**' operator.
3307 def analyse_types(self, env):
3308 env.pow_function_used = 1
3309 NumBinopNode.analyse_types(self, env)
3311 def compute_c_result_type(self, type1, type2):
3312 if self.c_types_okay(type1, type2):
3313 return PyrexTypes.c_double_type
3314 else:
3315 return None
3317 def c_types_okay(self, type1, type2):
3318 return (type1.is_float or type2.is_float) and \
3319 NumBinopNode.c_types_okay(self, type1, type2)
3321 def type_error(self):
3322 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3323 if self.operand1.type.is_int and self.operand2.type.is_int:
3324 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3325 (self.operator, self.operand1.type, self.operand2.type))
3326 else:
3327 NumBinopNode.type_error(self)
3328 self.type = PyrexTypes.error_type
3330 def calculate_result_code(self):
3331 return "pow(%s, %s)" % (
3332 self.operand1.result_code, self.operand2.result_code)
3335 class BoolBinopNode(ExprNode):
3336 # Short-circuiting boolean operation.
3337 #
3338 # operator string
3339 # operand1 ExprNode
3340 # operand2 ExprNode
3341 # temp_bool ExprNode used internally
3343 temp_bool = None
3345 subexprs = ['operand1', 'operand2', 'temp_bool']
3347 def compile_time_value(self, denv):
3348 if self.operator == 'and':
3349 return self.operand1.compile_time_value(denv) \
3350 and self.operand2.compile_time_value(denv)
3351 else:
3352 return self.operand1.compile_time_value(denv) \
3353 or self.operand2.compile_time_value(denv)
3355 def analyse_types(self, env):
3356 self.operand1.analyse_types(env)
3357 self.operand2.analyse_types(env)
3358 if self.operand1.type.is_pyobject or \
3359 self.operand2.type.is_pyobject:
3360 self.operand1 = self.operand1.coerce_to_pyobject(env)
3361 self.operand2 = self.operand2.coerce_to_pyobject(env)
3362 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3363 self.type = py_object_type
3364 self.gil_check(env)
3365 else:
3366 self.operand1 = self.operand1.coerce_to_boolean(env)
3367 self.operand2 = self.operand2.coerce_to_boolean(env)
3368 self.type = PyrexTypes.c_bint_type
3369 # For what we're about to do, it's vital that
3370 # both operands be temp nodes.
3371 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3372 self.operand2 = self.operand2.coerce_to_temp(env)
3373 self.is_temp = 1
3375 gil_message = "Truth-testing Python object"
3377 def allocate_temps(self, env, result_code = None):
3378 # We don't need both operands at the same time, and
3379 # one of the operands will also be our result. So we
3380 # use an allocation strategy here which results in
3381 # this node and both its operands sharing the same
3382 # result variable. This allows us to avoid some
3383 # assignments and increfs/decrefs that would otherwise
3384 # be necessary.
3385 self.allocate_temp(env, result_code)
3386 self.operand1.allocate_temps(env, self.result_code)
3387 if self.temp_bool:
3388 self.temp_bool.allocate_temp(env)
3389 self.temp_bool.release_temp(env)
3390 self.operand2.allocate_temps(env, self.result_code)
3391 # We haven't called release_temp on either operand,
3392 # because although they are temp nodes, they don't own
3393 # their result variable. And because they are temp
3394 # nodes, any temps in their subnodes will have been
3395 # released before their allocate_temps returned.
3396 # Therefore, they contain no temp vars that need to
3397 # be released.
3399 def check_const(self):
3400 self.operand1.check_const()
3401 self.operand2.check_const()
3403 def calculate_result_code(self):
3404 return "(%s %s %s)" % (
3405 self.operand1.result_code,
3406 self.py_to_c_op[self.operator],
3407 self.operand2.result_code)
3409 py_to_c_op = {'and': "&&", 'or': "||"}
3411 def generate_evaluation_code(self, code):
3412 self.operand1.generate_evaluation_code(code)
3413 test_result = self.generate_operand1_test(code)
3414 if self.operator == 'and':
3415 sense = ""
3416 else:
3417 sense = "!"
3418 code.putln(
3419 "if (%s%s) {" % (
3420 sense,
3421 test_result))
3422 self.operand1.generate_disposal_code(code)
3423 self.operand2.generate_evaluation_code(code)
3424 code.putln(
3425 "}")
3427 def generate_operand1_test(self, code):
3428 # Generate code to test the truth of the first operand.
3429 if self.type.is_pyobject:
3430 test_result = self.temp_bool.result_code
3431 code.putln(
3432 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3433 test_result,
3434 self.operand1.py_result(),
3435 code.error_goto_if_neg(test_result, self.pos)))
3436 else:
3437 test_result = self.operand1.result_code
3438 return test_result
3441 class CondExprNode(ExprNode):
3442 # Short-circuiting conditional expression.
3443 #
3444 # test ExprNode
3445 # true_val ExprNode
3446 # false_val ExprNode
3448 temp_bool = None
3449 true_val = None
3450 false_val = None
3452 subexprs = ['test', 'true_val', 'false_val']
3454 def analyse_types(self, env):
3455 self.test.analyse_types(env)
3456 self.test = self.test.coerce_to_boolean(env)
3457 self.true_val.analyse_types(env)
3458 self.false_val.analyse_types(env)
3459 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3460 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3461 self.true_val = self.true_val.coerce_to(self.type, env)
3462 self.false_val = self.false_val.coerce_to(self.type, env)
3463 # must be tmp variables so they can share a result
3464 self.true_val = self.true_val.coerce_to_temp(env)
3465 self.false_val = self.false_val.coerce_to_temp(env)
3466 self.is_temp = 1
3467 if self.type == PyrexTypes.error_type:
3468 self.type_error()
3470 def allocate_temps(self, env, result_code = None):
3471 # We only ever evaluate one side, and this is
3472 # after evaluating the truth value, so we may
3473 # use an allocation strategy here which results in
3474 # this node and both its operands sharing the same
3475 # result variable. This allows us to avoid some
3476 # assignments and increfs/decrefs that would otherwise
3477 # be necessary.
3478 self.allocate_temp(env, result_code)
3479 self.test.allocate_temps(env, result_code)
3480 self.true_val.allocate_temps(env, self.result_code)
3481 self.false_val.allocate_temps(env, self.result_code)
3482 # We haven't called release_temp on either value,
3483 # because although they are temp nodes, they don't own
3484 # their result variable. And because they are temp
3485 # nodes, any temps in their subnodes will have been
3486 # released before their allocate_temps returned.
3487 # Therefore, they contain no temp vars that need to
3488 # be released.
3490 def compute_result_type(self, type1, type2):
3491 if type1 == type2:
3492 return type1
3493 elif type1.is_numeric and type2.is_numeric:
3494 return PyrexTypes.widest_numeric_type(type1, type2)
3495 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3496 return type2
3497 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3498 return type1
3499 elif type1.is_pyobject or type2.is_pyobject:
3500 return py_object_type
3501 elif type1.assignable_from(type2):
3502 return type1
3503 elif type2.assignable_from(type1):
3504 return type2
3505 else:
3506 return PyrexTypes.error_type
3508 def type_error(self):
3509 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3510 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3511 (self.true_val.type, self.false_val.type))
3512 self.type = PyrexTypes.error_type
3514 def check_const(self):
3515 self.test.check_const()
3516 self.true_val.check_const()
3517 self.false_val.check_const()
3519 def generate_evaluation_code(self, code):
3520 self.test.generate_evaluation_code(code)
3521 code.putln("if (%s) {" % self.test.result_code )
3522 self.true_val.generate_evaluation_code(code)
3523 code.putln("} else {")
3524 self.false_val.generate_evaluation_code(code)
3525 code.putln("}")
3526 self.test.generate_disposal_code(code)
3528 richcmp_constants = {
3529 "<" : "Py_LT",
3530 "<=": "Py_LE",
3531 "==": "Py_EQ",
3532 "!=": "Py_NE",
3533 "<>": "Py_NE",
3534 ">" : "Py_GT",
3535 ">=": "Py_GE",
3536 }
3538 class CmpNode:
3539 # Mixin class containing code common to PrimaryCmpNodes
3540 # and CascadedCmpNodes.
3542 def cascaded_compile_time_value(self, operand1, denv):
3543 func = get_compile_time_binop(self)
3544 operand2 = self.operand2.compile_time_value(denv)
3545 try:
3546 result = func(operand1, operand2)
3547 except Exception, e:
3548 self.compile_time_value_error(e)
3549 result = None
3550 if result:
3551 cascade = self.cascade
3552 if cascade:
3553 result = result and cascade.compile_time_value(operand2, denv)
3554 return result
3556 def is_python_comparison(self):
3557 return (self.has_python_operands()
3558 or (self.cascade and self.cascade.is_python_comparison())
3559 or self.operator in ('in', 'not_in'))
3561 def is_python_result(self):
3562 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3563 or (self.cascade and self.cascade.is_python_result()))
3565 def check_types(self, env, operand1, op, operand2):
3566 if not self.types_okay(operand1, op, operand2):
3567 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3568 (self.operator, operand1.type, operand2.type))
3570 def types_okay(self, operand1, op, operand2):
3571 type1 = operand1.type
3572 type2 = operand2.type
3573 if type1.is_error or type2.is_error:
3574 return 1
3575 if type1.is_pyobject: # type2 will be, too
3576 return 1
3577 elif type1.is_ptr or type1.is_array:
3578 return type1.is_null_ptr or type2.is_null_ptr \
3579 or ((type2.is_ptr or type2.is_array)
3580 and type1.base_type.same_as(type2.base_type))
3581 elif ((type1.is_numeric and type2.is_numeric
3582 or type1.is_enum and (type1 is type2 or type2.is_int)
3583 or type1.is_int and type2.is_enum)
3584 and op not in ('is', 'is_not')):
3585 return 1
3586 else:
3587 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3589 def generate_operation_code(self, code, result_code,
3590 operand1, op , operand2):
3591 if self.type is PyrexTypes.py_object_type:
3592 coerce_result = "__Pyx_PyBool_FromLong"
3593 else:
3594 coerce_result = ""
3595 if 'not' in op: negation = "!"
3596 else: negation = ""
3597 if op == 'in' or op == 'not_in':
3598 code.putln(
3599 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3600 result_code,
3601 coerce_result,
3602 negation,
3603 operand2.py_result(),
3604 operand1.py_result(),
3605 code.error_goto_if_neg(result_code, self.pos)))
3606 elif (operand1.type.is_pyobject
3607 and op not in ('is', 'is_not')):
3608 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3609 result_code,
3610 operand1.py_result(),
3611 operand2.py_result(),
3612 richcmp_constants[op],
3613 code.error_goto_if_null(result_code, self.pos)))
3614 else:
3615 type1 = operand1.type
3616 type2 = operand2.type
3617 if (type1.is_extension_type or type2.is_extension_type) \
3618 and not type1.same_as(type2):
3619 common_type = py_object_type
3620 elif type1.is_numeric:
3621 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3622 else:
3623 common_type = type1
3624 code1 = operand1.result_as(common_type)
3625 code2 = operand2.result_as(common_type)
3626 code.putln("%s = %s(%s %s %s);" % (
3627 result_code,
3628 coerce_result,
3629 code1,
3630 self.c_operator(op),
3631 code2))
3633 def c_operator(self, op):
3634 if op == 'is':
3635 return "=="
3636 elif op == 'is_not':
3637 return "!="
3638 else:
3639 return op
3642 class PrimaryCmpNode(ExprNode, CmpNode):
3643 # Non-cascaded comparison or first comparison of
3644 # a cascaded sequence.
3645 #
3646 # operator string
3647 # operand1 ExprNode
3648 # operand2 ExprNode
3649 # cascade CascadedCmpNode
3651 # We don't use the subexprs mechanism, because
3652 # things here are too complicated for it to handle.
3653 # Instead, we override all the framework methods
3654 # which use it.
3656 child_attrs = ['operand1', 'operand2', 'cascade']
3658 cascade = None
3660 def compile_time_value(self, denv):
3661 operand1 = self.operand1.compile_time_value(denv)
3662 return self.cascaded_compile_time_value(operand1, denv)
3664 def analyse_types(self, env):
3665 self.operand1.analyse_types(env)
3666 self.operand2.analyse_types(env)
3667 if self.cascade:
3668 self.cascade.analyse_types(env, self.operand2)
3669 self.is_pycmp = self.is_python_comparison()
3670 if self.is_pycmp:
3671 self.coerce_operands_to_pyobjects(env)
3672 if self.has_int_operands():
3673 self.coerce_chars_to_ints(env)
3674 if self.cascade:
3675 self.operand2 = self.operand2.coerce_to_simple(env)
3676 self.cascade.coerce_cascaded_operands_to_temp(env)
3677 self.check_operand_types(env)
3678 if self.is_python_result():
3679 self.type = PyrexTypes.py_object_type
3680 else:
3681 self.type = PyrexTypes.c_bint_type
3682 cdr = self.cascade
3683 while cdr:
3684 cdr.type = self.type
3685 cdr = cdr.cascade
3686 if self.is_pycmp or self.cascade:
3687 self.is_temp = 1
3689 def check_operand_types(self, env):
3690 self.check_types(env,
3691 self.operand1, self.operator, self.operand2)
3692 if self.cascade:
3693 self.cascade.check_operand_types(env, self.operand2)
3695 def has_python_operands(self):
3696 return (self.operand1.type.is_pyobject
3697 or self.operand2.type.is_pyobject)
3699 def coerce_operands_to_pyobjects(self, env):
3700 self.operand1 = self.operand1.coerce_to_pyobject(env)
3701 self.operand2 = self.operand2.coerce_to_pyobject(env)
3702 if self.cascade:
3703 self.cascade.coerce_operands_to_pyobjects(env)
3705 def has_int_operands(self):
3706 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3707 or (self.cascade and self.cascade.has_int_operands())
3709 def coerce_chars_to_ints(self, env):
3710 # coerce literal single-char strings to c chars
3711 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
3712 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3713 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3714 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3715 if self.cascade:
3716 self.cascade.coerce_chars_to_ints(env)
3718 def allocate_subexpr_temps(self, env):
3719 self.operand1.allocate_temps(env)
3720 self.operand2.allocate_temps(env)
3721 if self.cascade:
3722 self.cascade.allocate_subexpr_temps(env)
3724 def release_subexpr_temps(self, env):
3725 self.operand1.release_temp(env)
3726 self.operand2.release_temp(env)
3727 if self.cascade:
3728 self.cascade.release_subexpr_temps(env)
3730 def check_const(self):
3731 self.operand1.check_const()
3732 self.operand2.check_const()
3733 if self.cascade:
3734 self.not_const()
3736 def calculate_result_code(self):
3737 return "(%s %s %s)" % (
3738 self.operand1.result_code,
3739 self.c_operator(self.operator),
3740 self.operand2.result_code)
3742 def generate_evaluation_code(self, code):
3743 self.operand1.generate_evaluation_code(code)
3744 self.operand2.generate_evaluation_code(code)
3745 if self.is_temp:
3746 self.generate_operation_code(code, self.result_code,
3747 self.operand1, self.operator, self.operand2)
3748 if self.cascade:
3749 self.cascade.generate_evaluation_code(code,
3750 self.result_code, self.operand2)
3751 self.operand1.generate_disposal_code(code)
3752 self.operand2.generate_disposal_code(code)
3754 def generate_subexpr_disposal_code(self, code):
3755 # If this is called, it is a non-cascaded cmp,
3756 # so only need to dispose of the two main operands.
3757 self.operand1.generate_disposal_code(code)
3758 self.operand2.generate_disposal_code(code)
3760 def annotate(self, code):
3761 self.operand1.annotate(code)
3762 self.operand2.annotate(code)
3763 if self.cascade:
3764 self.cascade.annotate(code)
3767 class CascadedCmpNode(Node, CmpNode):
3768 # A CascadedCmpNode is not a complete expression node. It
3769 # hangs off the side of another comparison node, shares
3770 # its left operand with that node, and shares its result
3771 # with the PrimaryCmpNode at the head of the chain.
3772 #
3773 # operator string
3774 # operand2 ExprNode
3775 # cascade CascadedCmpNode
3777 child_attrs = ['operand2', 'cascade']
3779 cascade = None
3781 def analyse_types(self, env, operand1):
3782 self.operand2.analyse_types(env)
3783 if self.cascade:
3784 self.cascade.analyse_types(env, self.operand2)
3786 def check_operand_types(self, env, operand1):
3787 self.check_types(env,
3788 operand1, self.operator, self.operand2)
3789 if self.cascade:
3790 self.cascade.check_operand_types(env, self.operand2)
3792 def has_python_operands(self):
3793 return self.operand2.type.is_pyobject
3795 def coerce_operands_to_pyobjects(self, env):
3796 self.operand2 = self.operand2.coerce_to_pyobject(env)
3797 if self.cascade:
3798 self.cascade.coerce_operands_to_pyobjects(env)
3800 def has_int_operands(self):
3801 return self.operand2.type.is_int
3803 def coerce_chars_to_ints(self, env):
3804 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3805 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3807 def coerce_cascaded_operands_to_temp(self, env):
3808 if self.cascade:
3809 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3810 self.operand2 = self.operand2.coerce_to_simple(env)
3811 self.cascade.coerce_cascaded_operands_to_temp(env)
3813 def allocate_subexpr_temps(self, env):
3814 self.operand2.allocate_temps(env)
3815 if self.cascade:
3816 self.cascade.allocate_subexpr_temps(env)
3818 def release_subexpr_temps(self, env):
3819 self.operand2.release_temp(env)
3820 if self.cascade:
3821 self.cascade.release_subexpr_temps(env)
3823 def generate_evaluation_code(self, code, result, operand1):
3824 if self.type.is_pyobject:
3825 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
3826 else:
3827 code.putln("if (%s) {" % result)
3828 self.operand2.generate_evaluation_code(code)
3829 self.generate_operation_code(code, result,
3830 operand1, self.operator, self.operand2)
3831 if self.cascade:
3832 self.cascade.generate_evaluation_code(
3833 code, result, self.operand2)
3834 # Cascaded cmp result is always temp
3835 self.operand2.generate_disposal_code(code)
3836 code.putln("}")
3838 def annotate(self, code):
3839 self.operand2.annotate(code)
3840 if self.cascade:
3841 self.cascade.annotate(code)
3844 binop_node_classes = {
3845 "or": BoolBinopNode,
3846 "and": BoolBinopNode,
3847 "|": IntBinopNode,
3848 "^": IntBinopNode,
3849 "&": IntBinopNode,
3850 "<<": IntBinopNode,
3851 ">>": IntBinopNode,
3852 "+": AddNode,
3853 "-": SubNode,
3854 "*": MulNode,
3855 "/": NumBinopNode,
3856 "//": FloorDivNode,
3857 "%": ModNode,
3858 "**": PowNode
3859 }
3861 def binop_node(pos, operator, operand1, operand2):
3862 # Construct binop node of appropriate class for
3863 # given operator.
3864 return binop_node_classes[operator](pos,
3865 operator = operator,
3866 operand1 = operand1,
3867 operand2 = operand2)
3869 #-------------------------------------------------------------------
3870 #
3871 # Coercion nodes
3872 #
3873 # Coercion nodes are special in that they are created during
3874 # the analyse_types phase of parse tree processing.
3875 # Their __init__ methods consequently incorporate some aspects
3876 # of that phase.
3877 #
3878 #-------------------------------------------------------------------
3880 class CoercionNode(ExprNode):
3881 # Abstract base class for coercion nodes.
3882 #
3883 # arg ExprNode node being coerced
3885 subexprs = ['arg']
3887 def __init__(self, arg):
3888 self.pos = arg.pos
3889 self.arg = arg
3890 if debug_coercion:
3891 print("%s Coercing %s" % (self, self.arg))
3893 def annotate(self, code):
3894 self.arg.annotate(code)
3895 if self.arg.type != self.type:
3896 file, line, col = self.pos
3897 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
3900 class CastNode(CoercionNode):
3901 # Wrap a node in a C type cast.
3903 def __init__(self, arg, new_type):
3904 CoercionNode.__init__(self, arg)
3905 self.type = new_type
3907 def calculate_result_code(self):
3908 return self.arg.result_as(self.type)
3910 def generate_result_code(self, code):
3911 self.arg.generate_result_code(code)
3914 class PyTypeTestNode(CoercionNode):
3915 # This node is used to check that a generic Python
3916 # object is an instance of a particular extension type.
3917 # This node borrows the result of its argument node.
3919 def __init__(self, arg, dst_type, env):
3920 # The arg is know to be a Python object, and
3921 # the dst_type is known to be an extension type.
3922 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
3923 CoercionNode.__init__(self, arg)
3924 self.type = dst_type
3925 self.gil_check(env)
3926 self.result_ctype = arg.ctype()
3927 env.use_utility_code(type_test_utility_code)
3929 gil_message = "Python type test"
3931 def analyse_types(self, env):
3932 pass
3934 def result_in_temp(self):
3935 return self.arg.result_in_temp()
3937 def is_ephemeral(self):
3938 return self.arg.is_ephemeral()
3940 def calculate_result_code(self):
3941 return self.arg.result_code
3943 def generate_result_code(self, code):
3944 if self.type.typeobj_is_available():
3945 code.putln(
3946 "if (!(%s)) %s" % (
3947 self.type.type_test_code(self.arg.py_result()),
3948 code.error_goto(self.pos)))
3949 else:
3950 error(self.pos, "Cannot test type of extern C class "
3951 "without type object name specification")
3953 def generate_post_assignment_code(self, code):
3954 self.arg.generate_post_assignment_code(code)
3957 class CoerceToPyTypeNode(CoercionNode):
3958 # This node is used to convert a C data type
3959 # to a Python object.
3961 def __init__(self, arg, env):
3962 CoercionNode.__init__(self, arg)
3963 self.type = py_object_type
3964 self.gil_check(env)
3965 self.is_temp = 1
3966 if not arg.type.to_py_function:
3967 error(arg.pos,
3968 "Cannot convert '%s' to Python object" % arg.type)
3970 gil_message = "Converting to Python object"
3972 def analyse_types(self, env):
3973 # The arg is always already analysed
3974 pass
3976 def generate_result_code(self, code):
3977 function = self.arg.type.to_py_function
3978 code.putln('%s = %s(%s); %s' % (
3979 self.result_code,
3980 function,
3981 self.arg.result_code,
3982 code.error_goto_if_null(self.result_code, self.pos)))
3985 class CoerceFromPyTypeNode(CoercionNode):
3986 # This node is used to convert a Python object
3987 # to a C data type.
3989 def __init__(self, result_type, arg, env):
3990 CoercionNode.__init__(self, arg)
3991 self.type = result_type
3992 self.is_temp = 1
3993 if not result_type.from_py_function:
3994 error(arg.pos,
3995 "Cannot convert Python object to '%s'" % result_type)
3996 if self.type.is_string and self.arg.is_ephemeral():
3997 error(arg.pos,
3998 "Obtaining char * from temporary Python value")
4000 def analyse_types(self, env):
4001 # The arg is always already analysed
4002 pass
4004 def generate_result_code(self, code):
4005 function = self.type.from_py_function
4006 operand = self.arg.py_result()
4007 rhs = "%s(%s)" % (function, operand)
4008 if self.type.is_enum:
4009 rhs = typecast(self.type, c_long_type, rhs)
4010 code.putln('%s = %s; %s' % (
4011 self.result_code,
4012 rhs,
4013 code.error_goto_if(self.type.error_condition(self.result_code), self.pos)))
4016 class CoerceToBooleanNode(CoercionNode):
4017 # This node is used when a result needs to be used
4018 # in a boolean context.
4020 def __init__(self, arg, env):
4021 CoercionNode.__init__(self, arg)
4022 self.type = PyrexTypes.c_bint_type
4023 if arg.type.is_pyobject:
4024 if env.nogil:
4025 self.gil_error()
4026 self.is_temp = 1
4028 gil_message = "Truth-testing Python object"
4030 def check_const(self):
4031 if self.is_temp:
4032 self.not_const()
4033 self.arg.check_const()
4035 def calculate_result_code(self):
4036 return "(%s != 0)" % self.arg.result_code
4038 def generate_result_code(self, code):
4039 if self.arg.type.is_pyobject:
4040 code.putln(
4041 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4042 self.result_code,
4043 self.arg.py_result(),
4044 code.error_goto_if_neg(self.result_code, self.pos)))
4047 class CoerceToTempNode(CoercionNode):
4048 # This node is used to force the result of another node
4049 # to be stored in a temporary. It is only used if the
4050 # argument node's result is not already in a temporary.
4052 def __init__(self, arg, env):
4053 CoercionNode.__init__(self, arg)
4054 self.type = self.arg.type
4055 self.is_temp = 1
4056 if self.type.is_pyobject:
4057 self.gil_check(env)
4058 self.result_ctype = py_object_type
4060 gil_message = "Creating temporary Python reference"
4062 def analyse_types(self, env):
4063 # The arg is always already analysed
4064 pass
4066 def generate_result_code(self, code):
4067 #self.arg.generate_evaluation_code(code) # Already done
4068 # by generic generate_subexpr_evaluation_code!
4069 code.putln("%s = %s;" % (
4070 self.result_code, self.arg.result_as(self.ctype())))
4071 if self.type.is_pyobject:
4072 code.put_incref(self.result_code, self.ctype())
4075 class CloneNode(CoercionNode):
4076 # This node is employed when the result of another node needs
4077 # to be used multiple times. The argument node's result must
4078 # be in a temporary. This node "borrows" the result from the
4079 # argument node, and does not generate any evaluation or
4080 # disposal code for it. The original owner of the argument
4081 # node is responsible for doing those things.
4083 subexprs = [] # Arg is not considered a subexpr
4085 def __init__(self, arg):
4086 CoercionNode.__init__(self, arg)
4087 if hasattr(arg, 'type'):
4088 self.type = arg.type
4089 self.result_ctype = arg.result_ctype
4090 if hasattr(arg, 'entry'):
4091 self.entry = arg.entry
4093 def calculate_result_code(self):
4094 return self.arg.result_code
4096 def analyse_types(self, env):
4097 self.type = self.arg.type
4098 self.result_ctype = self.arg.result_ctype
4099 self.is_temp = 1
4100 if hasattr(self.arg, 'entry'):
4101 self.entry = self.arg.entry
4103 def generate_evaluation_code(self, code):
4104 pass
4106 def generate_result_code(self, code):
4107 pass
4109 def generate_disposal_code(self, code):
4110 pass
4112 def allocate_temps(self, env):
4113 self.result_code = self.calculate_result_code()
4115 def release_temp(self, env):
4116 pass
4118 class PersistentNode(ExprNode):
4119 # A PersistentNode is like a CloneNode except it handles the temporary
4120 # allocation itself by keeping track of the number of times it has been
4121 # used.
4123 subexprs = ["arg"]
4124 temp_counter = 0
4125 generate_counter = 0
4126 analyse_counter = 0
4127 result_code = None
4129 def __init__(self, arg, uses):
4130 self.pos = arg.pos
4131 self.arg = arg
4132 self.uses = uses
4134 def analyse_types(self, env):
4135 if self.analyse_counter == 0:
4136 self.arg.analyse_types(env)
4137 self.type = self.arg.type
4138 self.result_ctype = self.arg.result_ctype
4139 self.is_temp = 1
4140 self.analyse_counter += 1
4142 def calculate_result_code(self):
4143 return self.result_code
4145 def generate_evaluation_code(self, code):
4146 if self.generate_counter == 0:
4147 self.arg.generate_evaluation_code(code)
4148 code.putln("%s = %s;" % (
4149 self.result_code, self.arg.result_as(self.ctype())))
4150 if self.type.is_pyobject:
4151 code.put_incref(self.result_code, self.ctype())
4152 self.arg.generate_disposal_code(code)
4153 self.generate_counter += 1
4155 def generate_disposal_code(self, code):
4156 if self.generate_counter == self.uses:
4157 if self.type.is_pyobject:
4158 code.put_decref_clear(self.result_code, self.ctype())
4160 def allocate_temps(self, env, result=None):
4161 if self.temp_counter == 0:
4162 self.arg.allocate_temps(env)
4163 self.allocate_temp(env, result)
4164 self.arg.release_temp(env)
4165 self.temp_counter += 1
4167 def allocate_temp(self, env, result=None):
4168 if result is None:
4169 self.result_code = env.allocate_temp(self.type)
4170 else:
4171 self.result_code = result
4173 def release_temp(self, env):
4174 if self.temp_counter == self.uses:
4175 env.release_temp(self.result_code)
4177 #------------------------------------------------------------------------------------
4178 #
4179 # Runtime support code
4180 #
4181 #------------------------------------------------------------------------------------
4183 get_name_interned_utility_code = [
4184 """
4185 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4186 ""","""
4187 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4188 PyObject *result;
4189 result = PyObject_GetAttr(dict, name);
4190 if (!result)
4191 PyErr_SetObject(PyExc_NameError, name);
4192 return result;
4193 }
4194 """]
4196 #------------------------------------------------------------------------------------
4198 import_utility_code = [
4199 """
4200 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4201 ""","""
4202 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4203 PyObject *__import__ = 0;
4204 PyObject *empty_list = 0;
4205 PyObject *module = 0;
4206 PyObject *global_dict = 0;
4207 PyObject *empty_dict = 0;
4208 PyObject *list;
4209 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4210 if (!__import__)
4211 goto bad;
4212 if (from_list)
4213 list = from_list;
4214 else {
4215 empty_list = PyList_New(0);
4216 if (!empty_list)
4217 goto bad;
4218 list = empty_list;
4219 }
4220 global_dict = PyModule_GetDict(%(GLOBALS)s);
4221 if (!global_dict)
4222 goto bad;
4223 empty_dict = PyDict_New();
4224 if (!empty_dict)
4225 goto bad;
4226 module = PyObject_CallFunction(__import__, "OOOO",
4227 name, global_dict, empty_dict, list);
4228 bad:
4229 Py_XDECREF(empty_list);
4230 Py_XDECREF(__import__);
4231 Py_XDECREF(empty_dict);
4232 return module;
4233 }
4234 """ % {
4235 "BUILTINS": Naming.builtins_cname,
4236 "GLOBALS": Naming.module_cname,
4237 }]
4239 #------------------------------------------------------------------------------------
4241 get_exception_utility_code = [
4242 """
4243 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4244 ""","""
4245 static PyObject *__Pyx_GetExcValue(void) {
4246 PyObject *type = 0, *value = 0, *tb = 0;
4247 PyObject *tmp_type, *tmp_value, *tmp_tb;
4248 PyObject *result = 0;
4249 PyThreadState *tstate = PyThreadState_Get();
4250 PyErr_Fetch(&type, &value, &tb);
4251 PyErr_NormalizeException(&type, &value, &tb);
4252 if (PyErr_Occurred())
4253 goto bad;
4254 if (!value) {
4255 value = Py_None;
4256 Py_INCREF(value);
4257 }
4258 tmp_type = tstate->exc_type;
4259 tmp_value = tstate->exc_value;
4260 tmp_tb = tstate->exc_traceback;
4261 tstate->exc_type = type;
4262 tstate->exc_value = value;
4263 tstate->exc_traceback = tb;
4264 /* Make sure tstate is in a consistent state when we XDECREF
4265 these objects (XDECREF may run arbitrary code). */
4266 Py_XDECREF(tmp_type);
4267 Py_XDECREF(tmp_value);
4268 Py_XDECREF(tmp_tb);
4269 result = value;
4270 Py_XINCREF(result);
4271 type = 0;
4272 value = 0;
4273 tb = 0;
4274 bad:
4275 Py_XDECREF(type);
4276 Py_XDECREF(value);
4277 Py_XDECREF(tb);
4278 return result;
4279 }
4280 """]
4282 #------------------------------------------------------------------------------------
4284 unpacking_utility_code = [
4285 """
4286 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4287 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4288 ""","""
4289 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4290 PyObject *item;
4291 if (!(item = PyIter_Next(iter))) {
4292 if (!PyErr_Occurred()) {
4293 PyErr_Format(PyExc_ValueError,
4294 #if PY_VERSION_HEX < 0x02050000
4295 "need more than %d values to unpack", (int)index);
4296 #else
4297 "need more than %zd values to unpack", index);
4298 #endif
4299 }
4300 }
4301 return item;
4302 }
4304 static int __Pyx_EndUnpack(PyObject *iter) {
4305 PyObject *item;
4306 if ((item = PyIter_Next(iter))) {
4307 Py_DECREF(item);
4308 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4309 return -1;
4310 }
4311 else if (!PyErr_Occurred())
4312 return 0;
4313 else
4314 return -1;
4315 }
4316 """]
4318 #------------------------------------------------------------------------------------
4320 type_test_utility_code = [
4321 """
4322 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4323 ""","""
4324 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4325 if (!type) {
4326 PyErr_Format(PyExc_SystemError, "Missing type object");
4327 return 0;
4328 }
4329 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4330 return 1;
4331 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4332 Py_TYPE(obj)->tp_name, type->tp_name);
4333 return 0;
4334 }
4335 """]
4337 #------------------------------------------------------------------------------------
4339 create_class_utility_code = [
4340 """
4341 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4342 ""","""
4343 static PyObject *__Pyx_CreateClass(
4344 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4345 {
4346 PyObject *py_modname;
4347 PyObject *result = 0;
4349 #if PY_MAJOR_VERSION < 3
4350 py_modname = PyString_FromString(modname);
4351 #else
4352 py_modname = PyUnicode_FromString(modname);
4353 #endif
4354 if (!py_modname)
4355 goto bad;
4356 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4357 goto bad;
4358 #if PY_MAJOR_VERSION < 3
4359 result = PyClass_New(bases, dict, name);
4360 #else
4361 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4362 #endif
4363 bad:
4364 Py_XDECREF(py_modname);
4365 return result;
4366 }
4367 """]
4369 #------------------------------------------------------------------------------------
4371 cpp_exception_utility_code = [
4372 """
4373 #ifndef __Pyx_CppExn2PyErr
4374 static void __Pyx_CppExn2PyErr() {
4375 try {
4376 if (PyErr_Occurred())
4377 ; // let the latest Python exn pass through and ignore the current one
4378 else
4379 throw;
4380 } catch (const std::out_of_range& exn) {
4381 // catch out_of_range explicitly so the proper Python exn may be raised
4382 PyErr_SetString(PyExc_IndexError, exn.what());
4383 } catch (const std::exception& exn) {
4384 PyErr_SetString(PyExc_RuntimeError, exn.what());
4385 }
4386 catch (...)
4387 {
4388 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4389 }
4390 }
4391 #endif
4392 """,""]
4394 #------------------------------------------------------------------------------------
4396 append_utility_code = [
4397 """
4398 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4399 if (likely(PyList_CheckExact(L))) {
4400 if (PyList_Append(L, x) < 0) return NULL;
4401 Py_INCREF(Py_None);
4402 return Py_None; // this is just to have an accurate signature
4403 }
4404 else {
4405 return PyObject_CallMethod(L, "append", "(O)", x);
4406 }
4407 }
4408 """,""
4409 ]
4411 #------------------------------------------------------------------------------------
4413 type_cache_invalidation_code = [
4414 """
4415 #if PY_VERSION_HEX >= 0x02060000
4416 /* #define __Pyx_TypeModified(t) PyType_Modified(t) */ /* Py3.0beta1 */
4417 static void __Pyx_TypeModified(PyTypeObject* type); /*proto*/
4418 #else
4419 #define __Pyx_TypeModified(t)
4420 #endif
4421 ""","""
4422 #if PY_VERSION_HEX >= 0x02060000
4423 /* copied from typeobject.c in Python 3.0a5 */
4424 static void __Pyx_TypeModified(PyTypeObject* type) {
4425 PyObject *raw, *ref;
4426 Py_ssize_t i, n;
4428 if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
4429 return;
4431 raw = type->tp_subclasses;
4432 if (raw != NULL) {
4433 n = PyList_GET_SIZE(raw);
4434 for (i = 0; i < n; i++) {
4435 ref = PyList_GET_ITEM(raw, i);
4436 ref = PyWeakref_GET_OBJECT(ref);
4437 if (ref != Py_None) {
4438 __Pyx_TypeModified((PyTypeObject *)ref);
4439 }
4440 }
4441 }
4442 type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
4443 }
4444 #endif
4445 """
4446 ]
4448 #------------------------------------------------------------------------------------
4450 # If the is_unsigned flag is set, we need to do some extra work to make
4451 # sure the index doesn't become negative.
4453 getitem_int_utility_code = [
4454 """
4455 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4456 PyObject *r;
4457 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4458 r = PyList_GET_ITEM(o, i);
4459 Py_INCREF(r);
4460 }
4461 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4462 r = PyTuple_GET_ITEM(o, i);
4463 Py_INCREF(r);
4464 }
4465 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4466 r = PySequence_GetItem(o, i);
4467 else {
4468 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);
4469 if (!j)
4470 return 0;
4471 r = PyObject_GetItem(o, j);
4472 Py_DECREF(j);
4473 }
4474 return r;
4475 }
4476 """,
4477 """
4478 """]
4480 #------------------------------------------------------------------------------------
4482 setitem_int_utility_code = [
4483 """
4484 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4485 int r;
4486 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4487 Py_DECREF(PyList_GET_ITEM(o, i));
4488 Py_INCREF(v);
4489 PyList_SET_ITEM(o, i, v);
4490 return 1;
4491 }
4492 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4493 r = PySequence_SetItem(o, i, v);
4494 else {
4495 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);
4496 if (!j)
4497 return -1;
4498 r = PyObject_SetItem(o, j, v);
4499 Py_DECREF(j);
4500 }
4501 return r;
4502 }
4503 """,
4504 """
4505 """]
