Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 1445:6dbd25167239
More fixes for new temps
| author | Dag Sverre Seljebotn <dagss@student.matnat.uio.no> |
|---|---|
| date | Mon Dec 01 01:06:57 2008 +0100 (3 years ago) |
| parents | dbcb1b2a2fce |
| children | 0041a6d8b29c |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
6 from string import join
8 from Errors import error, warning, InternalError
9 from Errors import hold_errors, release_errors, held_errors, report_error
10 from Cython.Utils import UtilityCode
11 import StringEncoding
12 import Naming
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
16 from Builtin import list_type, tuple_type, dict_type, unicode_type
17 import Symtab
18 import Options
19 from Annotate import AnnotationItem
21 from Cython.Debugging import print_call_chain
22 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
23 debug_coercion
26 class ExprNode(Node):
27 # subexprs [string] Class var holding names of subexpr node attrs
28 # type PyrexType Type of the result
29 # result_code string Code fragment
30 # result_ctype string C type of result_code if different from type
31 # is_temp boolean Result is in a temporary variable
32 # is_sequence_constructor
33 # boolean Is a list or tuple constructor expression
34 # saved_subexpr_nodes
35 # [ExprNode or [ExprNode or None] or None]
36 # Cached result of subexpr_nodes()
38 result_ctype = None
39 type = None
41 # The Analyse Expressions phase for expressions is split
42 # into two sub-phases:
43 #
44 # Analyse Types
45 # Determines the result type of the expression based
46 # on the types of its sub-expressions, and inserts
47 # coercion nodes into the expression tree where needed.
48 # Marks nodes which will need to have temporary variables
49 # allocated.
50 #
51 # Allocate Temps
52 # Allocates temporary variables where needed, and fills
53 # in the result_code field of each node.
54 #
55 # ExprNode provides some convenience routines which
56 # perform both of the above phases. These should only
57 # be called from statement nodes, and only when no
58 # coercion nodes need to be added around the expression
59 # being analysed. In that case, the above two phases
60 # should be invoked separately.
61 #
62 # Framework code in ExprNode provides much of the common
63 # processing for the various phases. It makes use of the
64 # 'subexprs' class attribute of ExprNodes, which should
65 # contain a list of the names of attributes which can
66 # hold sub-nodes or sequences of sub-nodes.
67 #
68 # The framework makes use of a number of abstract methods.
69 # Their responsibilities are as follows.
70 #
71 # Declaration Analysis phase
72 #
73 # analyse_target_declaration
74 # Called during the Analyse Declarations phase to analyse
75 # the LHS of an assignment or argument of a del statement.
76 # Nodes which cannot be the LHS of an assignment need not
77 # implement it.
78 #
79 # Expression Analysis phase
80 #
81 # analyse_types
82 # - Call analyse_types on all sub-expressions.
83 # - Check operand types, and wrap coercion nodes around
84 # sub-expressions where needed.
85 # - Set the type of this node.
86 # - If a temporary variable will be required for the
87 # result, set the is_temp flag of this node.
88 #
89 # analyse_target_types
90 # Called during the Analyse Types phase to analyse
91 # the LHS of an assignment or argument of a del
92 # statement. Similar responsibilities to analyse_types.
93 #
94 # allocate_temps
95 # - Call allocate_temps for all sub-nodes.
96 # - Call allocate_temp for this node.
97 # - If a temporary was allocated, call release_temp on
98 # all sub-expressions.
99 #
100 # allocate_target_temps
101 # - Call allocate_temps on sub-nodes and allocate any other
102 # temps used during assignment.
103 # - Fill in result_code with a C lvalue if needed.
104 # - If a rhs node is supplied, call release_temp on it.
105 # - Call release_temp on sub-nodes and release any other
106 # temps used during assignment.
107 #
108 # target_code
109 # Called by the default implementation of allocate_target_temps.
110 # Should return a C lvalue for assigning to the node. The default
111 # implementation calls calculate_result_code.
112 #
113 # check_const
114 # - Check that this node and its subnodes form a
115 # legal constant expression. If so, do nothing,
116 # otherwise call not_const.
117 #
118 # The default implementation of check_const
119 # assumes that the expression is not constant.
120 #
121 # check_const_addr
122 # - Same as check_const, except check that the
123 # expression is a C lvalue whose address is
124 # constant. Otherwise, call addr_not_const.
125 #
126 # The default implementation of calc_const_addr
127 # assumes that the expression is not a constant
128 # lvalue.
129 #
130 # Code Generation phase
131 #
132 # generate_evaluation_code
133 # - Call generate_evaluation_code for sub-expressions.
134 # - Perform the functions of generate_result_code
135 # (see below).
136 # - If result is temporary, call generate_disposal_code
137 # on all sub-expressions.
138 #
139 # A default implementation of generate_evaluation_code
140 # is provided which uses the following abstract methods:
141 #
142 # generate_result_code
143 # - Generate any C statements necessary to calculate
144 # the result of this node from the results of its
145 # sub-expressions.
146 #
147 # calculate_result_code
148 # - Should return a C code fragment evaluating to the
149 # result. This is only called when the result is not
150 # a temporary.
151 #
152 # generate_assignment_code
153 # Called on the LHS of an assignment.
154 # - Call generate_evaluation_code for sub-expressions.
155 # - Generate code to perform the assignment.
156 # - If the assignment absorbed a reference, call
157 # generate_post_assignment_code on the RHS,
158 # otherwise call generate_disposal_code on it.
159 #
160 # generate_deletion_code
161 # Called on an argument of a del statement.
162 # - Call generate_evaluation_code for sub-expressions.
163 # - Generate code to perform the deletion.
164 # - Call generate_disposal_code on all sub-expressions.
165 #
166 #
168 is_sequence_constructor = 0
169 is_attribute = 0
171 saved_subexpr_nodes = None
172 is_temp = 0
173 is_target = 0
175 def get_child_attrs(self):
176 return self.subexprs
177 child_attrs = property(fget=get_child_attrs)
179 def not_implemented(self, method_name):
180 print_call_chain(method_name, "not implemented") ###
181 raise InternalError(
182 "%s.%s not implemented" %
183 (self.__class__.__name__, method_name))
185 def is_lvalue(self):
186 return 0
188 def is_ephemeral(self):
189 # An ephemeral node is one whose result is in
190 # a Python temporary and we suspect there are no
191 # other references to it. Certain operations are
192 # disallowed on such values, since they are
193 # likely to result in a dangling pointer.
194 return self.type.is_pyobject and self.is_temp
196 def subexpr_nodes(self):
197 # Extract a list of subexpression nodes based
198 # on the contents of the subexprs class attribute.
199 nodes = []
200 for name in self.subexprs:
201 item = getattr(self, name)
202 if item:
203 if isinstance(item, ExprNode):
204 nodes.append(item)
205 else:
206 nodes.extend(item)
207 return nodes
209 def result(self):
210 if not self.is_temp or self.is_target:
211 return self.calculate_result_code()
212 else: # i.e. self.is_temp:
213 return self.result_code
215 def result_as(self, type = None):
216 # Return the result code cast to the specified C type.
217 return typecast(type, self.ctype(), self.result())
219 def py_result(self):
220 # Return the result code cast to PyObject *.
221 return self.result_as(py_object_type)
223 def ctype(self):
224 # Return the native C type of the result (i.e. the
225 # C type of the result_code expression).
226 return self.result_ctype or self.type
228 def compile_time_value(self, denv):
229 # Return value of compile-time expression, or report error.
230 error(self.pos, "Invalid compile-time expression")
232 def compile_time_value_error(self, e):
233 error(self.pos, "Error in compile-time expression: %s: %s" % (
234 e.__class__.__name__, e))
236 # ------------- Declaration Analysis ----------------
238 def analyse_target_declaration(self, env):
239 error(self.pos, "Cannot assign to or delete this")
241 # ------------- Expression Analysis ----------------
243 def analyse_const_expression(self, env):
244 # Called during the analyse_declarations phase of a
245 # constant expression. Analyses the expression's type,
246 # checks whether it is a legal const expression,
247 # and determines its value.
248 self.analyse_types(env)
249 self.allocate_temps(env)
250 self.check_const()
252 def analyse_expressions(self, env):
253 # Convenience routine performing both the Type
254 # Analysis and Temp Allocation phases for a whole
255 # expression.
256 self.analyse_types(env)
257 self.allocate_temps(env)
259 def analyse_target_expression(self, env, rhs):
260 # Convenience routine performing both the Type
261 # Analysis and Temp Allocation phases for the LHS of
262 # an assignment.
263 self.analyse_target_types(env)
264 self.allocate_target_temps(env, rhs)
266 def analyse_boolean_expression(self, env):
267 # Analyse expression and coerce to a boolean.
268 self.analyse_types(env)
269 bool = self.coerce_to_boolean(env)
270 bool.allocate_temps(env)
271 return bool
273 def analyse_temp_boolean_expression(self, env):
274 # Analyse boolean expression and coerce result into
275 # a temporary. This is used when a branch is to be
276 # performed on the result and we won't have an
277 # opportunity to ensure disposal code is executed
278 # afterwards. By forcing the result into a temporary,
279 # we ensure that all disposal has been done by the
280 # time we get the result.
281 self.analyse_types(env)
282 bool = self.coerce_to_boolean(env)
283 temp_bool = bool.coerce_to_temp(env)
284 temp_bool.allocate_temps(env)
285 return temp_bool
287 # --------------- Type Analysis ------------------
289 def analyse_as_module(self, env):
290 # If this node can be interpreted as a reference to a
291 # cimported module, return its scope, else None.
292 return None
294 def analyse_as_type(self, env):
295 # If this node can be interpreted as a reference to a
296 # type, return that type, else None.
297 return None
299 def analyse_as_extension_type(self, env):
300 # If this node can be interpreted as a reference to an
301 # extension type, return its type, else None.
302 return None
304 def analyse_types(self, env):
305 self.not_implemented("analyse_types")
307 def analyse_target_types(self, env):
308 self.analyse_types(env)
310 def gil_assignment_check(self, env):
311 if env.nogil and self.type.is_pyobject:
312 error(self.pos, "Assignment of Python object not allowed without gil")
314 def check_const(self):
315 self.not_const()
317 def not_const(self):
318 error(self.pos, "Not allowed in a constant expression")
320 def check_const_addr(self):
321 self.addr_not_const()
323 def addr_not_const(self):
324 error(self.pos, "Address is not constant")
326 def gil_check(self, env):
327 if env.nogil and self.type.is_pyobject:
328 self.gil_error()
330 # ----------------- Result Allocation -----------------
332 def result_in_temp(self):
333 # Return true if result is in a temporary owned by
334 # this node or one of its subexpressions. Overridden
335 # by certain nodes which can share the result of
336 # a subnode.
337 return self.is_temp
339 def allocate_target_temps(self, env, rhs):
340 # Perform temp allocation for the LHS of an assignment.
341 if debug_temp_alloc:
342 print("%s Allocating target temps" % self)
343 self.allocate_subexpr_temps(env)
344 self.is_target = True
345 if rhs:
346 rhs.release_temp(env)
347 self.release_subexpr_temps(env)
349 def allocate_temps(self, env, result = None):
350 # Allocate temporary variables for this node and
351 # all its sub-expressions. If a result is specified,
352 # this must be a temp node and the specified variable
353 # is used as the result instead of allocating a new
354 # one.
355 if debug_temp_alloc:
356 print("%s Allocating temps" % self)
357 self.allocate_subexpr_temps(env)
358 self.allocate_temp(env, result)
359 if self.is_temp:
360 self.release_subexpr_temps(env)
362 def allocate_subexpr_temps(self, env):
363 # Allocate temporary variables for all sub-expressions
364 # of this node.
365 if debug_temp_alloc:
366 print("%s Allocating temps for: %s" % (self, self.subexprs))
367 for node in self.subexpr_nodes():
368 if node:
369 if debug_temp_alloc:
370 print("%s Allocating temps for %s" % (self, node))
371 node.allocate_temps(env)
373 def allocate_temp(self, env, result = None):
374 # If this node requires a temporary variable for its
375 # result, allocate one, otherwise set the result to
376 # a C code fragment. If a result is specified,
377 # this must be a temp node and the specified variable
378 # is used as the result instead of allocating a new
379 # one.
380 if debug_temp_alloc:
381 print("%s Allocating temp" % self)
382 if result:
383 if not self.is_temp:
384 raise InternalError("Result forced on non-temp node")
385 self.result_code = result
386 elif self.is_temp:
387 type = self.type
388 if not type.is_void:
389 if type.is_pyobject:
390 type = PyrexTypes.py_object_type
391 self.result_code = env.allocate_temp(type)
392 else:
393 self.result_code = None
394 if debug_temp_alloc:
395 print("%s Allocated result %s" % (self, self.result_code))
397 def target_code(self):
398 # Return code fragment for use as LHS of a C assignment.
399 return self.calculate_result_code()
401 def calculate_result_code(self):
402 self.not_implemented("calculate_result_code")
404 # def release_target_temp(self, env):
405 # # Release temporaries used by LHS of an assignment.
406 # self.release_subexpr_temps(env)
408 def release_temp(self, env):
409 # If this node owns a temporary result, release it,
410 # otherwise release results of its sub-expressions.
411 if self.is_temp:
412 if debug_temp_alloc:
413 print("%s Releasing result %s" % (self, self.result_code))
414 env.release_temp(self.result_code)
415 else:
416 self.release_subexpr_temps(env)
418 def release_subexpr_temps(self, env):
419 # Release the results of all sub-expressions of
420 # this node.
421 for node in self.subexpr_nodes():
422 if node:
423 node.release_temp(env)
425 # ---------------- Code Generation -----------------
427 def make_owned_reference(self, code):
428 # If result is a pyobject, make sure we own
429 # a reference to it.
430 if self.type.is_pyobject and not self.result_in_temp():
431 code.put_incref(self.result(), self.ctype())
433 def generate_evaluation_code(self, code):
434 code.mark_pos(self.pos)
435 # Generate code to evaluate this node and
436 # its sub-expressions, and dispose of any
437 # temporary results of its sub-expressions.
438 self.generate_subexpr_evaluation_code(code)
439 self.generate_result_code(code)
440 if self.is_temp:
441 self.generate_subexpr_disposal_code(code)
442 self.free_subexpr_temps(code)
444 def generate_subexpr_evaluation_code(self, code):
445 for node in self.subexpr_nodes():
446 node.generate_evaluation_code(code)
448 def generate_result_code(self, code):
449 self.not_implemented("generate_result_code")
451 def generate_disposal_code(self, code):
452 # If necessary, generate code to dispose of
453 # temporary Python reference.
454 if self.is_temp:
455 if self.type.is_pyobject:
456 code.put_decref_clear(self.result(), self.ctype())
457 else:
458 self.generate_subexpr_disposal_code(code)
460 def generate_subexpr_disposal_code(self, code):
461 # Generate code to dispose of temporary results
462 # of all sub-expressions.
463 for node in self.subexpr_nodes():
464 node.generate_disposal_code(code)
466 def generate_post_assignment_code(self, code):
467 # Same as generate_disposal_code except that
468 # assignment will have absorbed a reference to
469 # the result if it is a Python object.
470 if self.is_temp:
471 if self.type.is_pyobject:
472 code.putln("%s = 0;" % self.result())
473 else:
474 self.generate_subexpr_disposal_code(code)
476 def generate_assignment_code(self, rhs, code):
477 # Stub method for nodes which are not legal as
478 # the LHS of an assignment. An error will have
479 # been reported earlier.
480 pass
482 def generate_deletion_code(self, code):
483 # Stub method for nodes that are not legal as
484 # the argument of a del statement. An error
485 # will have been reported earlier.
486 pass
488 def free_temps(self, code):
489 pass
491 def free_subexpr_temps(self, code):
492 for sub in self.subexpr_nodes():
493 sub.free_temps(code)
495 # ---------------- Annotation ---------------------
497 def annotate(self, code):
498 for node in self.subexpr_nodes():
499 node.annotate(code)
501 # ----------------- Coercion ----------------------
503 def coerce_to(self, dst_type, env):
504 # Coerce the result so that it can be assigned to
505 # something of type dst_type. If processing is necessary,
506 # wraps this node in a coercion node and returns that.
507 # Otherwise, returns this node unchanged.
508 #
509 # This method is called during the analyse_expressions
510 # phase of the src_node's processing.
511 src = self
512 src_type = self.type
513 src_is_py_type = src_type.is_pyobject
514 dst_is_py_type = dst_type.is_pyobject
516 if dst_type.is_pyobject:
517 if not src.type.is_pyobject:
518 src = CoerceToPyTypeNode(src, env)
519 if not src.type.subtype_of(dst_type):
520 if not isinstance(src, NoneNode):
521 src = PyTypeTestNode(src, dst_type, env)
522 elif src.type.is_pyobject:
523 src = CoerceFromPyTypeNode(dst_type, src, env)
524 else: # neither src nor dst are py types
525 # Added the string comparison, since for c types that
526 # is enough, but Cython gets confused when the types are
527 # in different files.
528 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
529 error(self.pos, "Cannot assign type '%s' to '%s'" %
530 (src.type, dst_type))
531 return src
533 def coerce_to_pyobject(self, env):
534 return self.coerce_to(PyrexTypes.py_object_type, env)
536 def coerce_to_boolean(self, env):
537 # Coerce result to something acceptable as
538 # a boolean value.
539 type = self.type
540 if type.is_pyobject or type.is_ptr or type.is_float:
541 return CoerceToBooleanNode(self, env)
542 else:
543 if not type.is_int and not type.is_error:
544 error(self.pos,
545 "Type '%s' not acceptable as a boolean" % type)
546 return self
548 def coerce_to_integer(self, env):
549 # If not already some C integer type, coerce to longint.
550 if self.type.is_int:
551 return self
552 else:
553 return self.coerce_to(PyrexTypes.c_long_type, env)
555 def coerce_to_temp(self, env):
556 # Ensure that the result is in a temporary.
557 if self.result_in_temp():
558 return self
559 else:
560 return CoerceToTempNode(self, env)
562 def coerce_to_simple(self, env):
563 # Ensure that the result is simple (see is_simple).
564 if self.is_simple():
565 return self
566 else:
567 return self.coerce_to_temp(env)
569 def is_simple(self):
570 # A node is simple if its result is something that can
571 # be referred to without performing any operations, e.g.
572 # a constant, local var, C global var, struct member
573 # reference, or temporary.
574 return self.result_in_temp()
576 def as_cython_attribute(self):
577 return None
580 class RemoveAllocateTemps(type):
581 def __init__(cls, name, bases, dct):
582 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
583 def noop(self, env): pass
584 setattr(cls, 'allocate_temps', noop)
585 setattr(cls, 'allocate_temp', noop)
586 setattr(cls, 'release_temp', noop)
588 class NewTempExprNode(ExprNode):
589 backwards_compatible_result = None
590 temp_code = None
592 # Do not enable this unless you are trying to make all ExprNodes
593 # NewTempExprNodes (child nodes reached via recursion may not have
594 # transferred).
595 # __metaclass__ = RemoveAllocateTemps
597 def result(self):
598 if self.is_temp:
599 return self.temp_code
600 else:
601 return self.calculate_result_code()
603 def allocate_target_temps(self, env, rhs):
604 self.allocate_subexpr_temps(env)
605 self.is_target = True
606 if rhs:
607 rhs.release_temp(env)
608 self.release_subexpr_temps(env)
610 def allocate_temps(self, env, result = None):
611 self.allocate_subexpr_temps(env)
612 self.backwards_compatible_result = result
613 if self.is_temp:
614 self.release_subexpr_temps(env)
616 def allocate_temp(self, env, result = None):
617 assert result is None
619 def release_temp(self, env):
620 if self.is_temp:
621 pass
622 else:
623 self.release_subexpr_temps(env)
625 def allocate_temp_result(self, code):
626 if self.temp_code:
627 raise RuntimeError("Temp allocated multiple times")
628 type = self.type
629 if not type.is_void:
630 if type.is_pyobject:
631 type = PyrexTypes.py_object_type
632 if self.backwards_compatible_result:
633 self.temp_code = self.backwards_compatible_result
634 else:
635 self.temp_code = code.funcstate.allocate_temp(
636 type, manage_ref=True)
637 else:
638 self.temp_code = None
640 def release_temp_result(self, code):
641 if not self.temp_code:
642 raise RuntimeError("No temp (perhaps released multiple times? See self.old_temp)")
643 code.funcstate.release_temp(self.temp_code)
644 self.old_temp = self.temp_code
645 self.temp_code = None
647 def generate_evaluation_code(self, code):
648 code.mark_pos(self.pos)
650 # Generate code to evaluate this node and
651 # its sub-expressions, and dispose of any
652 # temporary results of its sub-expressions.
653 self.generate_subexpr_evaluation_code(code)
655 if self.is_temp:
656 self.allocate_temp_result(code)
658 self.generate_result_code(code)
659 if self.is_temp:
660 # If we are temp we do not need to wait until this node is disposed
661 # before disposing children.
662 self.generate_subexpr_disposal_code(code)
663 self.free_subexpr_temps(code)
665 def generate_disposal_code(self, code):
666 if self.is_temp:
667 if self.type.is_pyobject:
668 code.put_decref_clear(self.result(), self.ctype())
669 else:
670 # Already done if self.is_temp
671 self.generate_subexpr_disposal_code(code)
673 def generate_post_assignment_code(self, code):
674 if self.is_temp:
675 if self.type.is_pyobject:
676 code.putln("%s = 0;" % self.result())
677 else:
678 self.generate_subexpr_disposal_code(code)
680 def free_temps(self, code):
681 if self.is_temp:
682 self.release_temp_result(code)
683 else:
684 self.free_subexpr_temps(code)
686 # ExprNode = NewTempExprNode
688 class AtomicExprNode(ExprNode):
689 # Abstract base class for expression nodes which have
690 # no sub-expressions.
692 subexprs = []
694 class AtomicNewTempExprNode(NewTempExprNode):
695 # I do not dare to convert NameNode yet. This is now
696 # ancestor of all former AtomicExprNode except
697 # NameNode. Should be renamed to AtomicExprNode
698 # when done.
700 # Abstract base class for expression nodes which have
701 # no sub-expressions.
703 subexprs = []
705 # Override to optimize -- we know we have no children
706 def generate_subexpr_evaluation_code(self, code):
707 pass
708 def generate_subexpr_disposal_code(self, code):
709 pass
711 class PyConstNode(AtomicNewTempExprNode):
712 # Abstract base class for constant Python values.
714 is_literal = 1
716 def is_simple(self):
717 return 1
719 def analyse_types(self, env):
720 self.type = py_object_type
722 def calculate_result_code(self):
723 return self.value
725 def generate_result_code(self, code):
726 pass
729 class NoneNode(PyConstNode):
730 # The constant value None
732 value = "Py_None"
734 def compile_time_value(self, denv):
735 return None
737 class EllipsisNode(PyConstNode):
738 # '...' in a subscript list.
740 value = "Py_Ellipsis"
742 def compile_time_value(self, denv):
743 return Ellipsis
746 class ConstNode(AtomicNewTempExprNode):
747 # Abstract base type for literal constant nodes.
748 #
749 # value string C code fragment
751 is_literal = 1
753 def is_simple(self):
754 return 1
756 def analyse_types(self, env):
757 pass # Types are held in class variables
759 def check_const(self):
760 pass
762 def calculate_result_code(self):
763 return str(self.value)
765 def generate_result_code(self, code):
766 pass
769 class BoolNode(ConstNode):
770 type = PyrexTypes.c_bint_type
771 # The constant value True or False
773 def compile_time_value(self, denv):
774 return self.value
776 def calculate_result_code(self):
777 return str(int(self.value))
779 class NullNode(ConstNode):
780 type = PyrexTypes.c_null_ptr_type
781 value = "NULL"
784 class CharNode(ConstNode):
785 type = PyrexTypes.c_char_type
787 def compile_time_value(self, denv):
788 return ord(self.value)
790 def calculate_result_code(self):
791 return "'%s'" % StringEncoding.escape_character(self.value)
794 class IntNode(ConstNode):
796 # unsigned "" or "U"
797 # longness "" or "L" or "LL"
799 unsigned = ""
800 longness = ""
801 type = PyrexTypes.c_long_type
803 def coerce_to(self, dst_type, env):
804 if dst_type.is_numeric:
805 self.type = PyrexTypes.c_long_type
806 return self
807 # Arrange for a Python version of the number to be pre-allocated
808 # when coercing to a Python type.
809 if dst_type.is_pyobject:
810 self.entry = env.get_py_num(self.value, self.longness)
811 self.type = PyrexTypes.py_object_type
812 # We still need to perform normal coerce_to processing on the
813 # result, because we might be coercing to an extension type,
814 # in which case a type test node will be needed.
815 return ConstNode.coerce_to(self, dst_type, env)
817 def coerce_to_boolean(self, env):
818 self.type = PyrexTypes.c_bint_type
819 return self
821 def calculate_result_code(self):
822 if self.type.is_pyobject:
823 return self.entry.cname
824 else:
825 return str(self.value) + self.unsigned + self.longness
827 def compile_time_value(self, denv):
828 return int(self.value, 0)
831 class FloatNode(ConstNode):
832 type = PyrexTypes.c_double_type
834 def compile_time_value(self, denv):
835 return float(self.value)
837 def calculate_result_code(self):
838 strval = str(self.value)
839 if strval == 'nan':
840 return "(Py_HUGE_VAL * 0)"
841 elif strval == 'inf':
842 return "Py_HUGE_VAL"
843 elif strval == '-inf':
844 return "(-Py_HUGE_VAL)"
845 else:
846 return strval
849 class StringNode(ConstNode):
850 # entry Symtab.Entry
852 type = PyrexTypes.c_char_ptr_type
854 def compile_time_value(self, denv):
855 return self.value
857 def analyse_types(self, env):
858 self.entry = env.add_string_const(self.value)
860 def analyse_as_type(self, env):
861 type = PyrexTypes.parse_basic_type(self.value)
862 if type is not None:
863 return type
864 from TreeFragment import TreeFragment
865 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
866 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
867 sizeof_node = declaration.root.stats[0].expr
868 sizeof_node.analyse_types(env)
869 if isinstance(sizeof_node, SizeofTypeNode):
870 return sizeof_node.arg_type
872 def coerce_to(self, dst_type, env):
873 if dst_type == PyrexTypes.c_char_ptr_type:
874 self.type = PyrexTypes.c_char_ptr_type
875 return self
877 if dst_type.is_int:
878 if not self.type.is_pyobject and len(self.entry.init) == 1:
879 return CharNode(self.pos, value=self.value)
880 else:
881 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
882 return self
883 # Arrange for a Python version of the string to be pre-allocated
884 # when coercing to a Python type.
885 if dst_type.is_pyobject and not self.type.is_pyobject:
886 node = self.as_py_string_node(env)
887 else:
888 node = self
889 # We still need to perform normal coerce_to processing on the
890 # result, because we might be coercing to an extension type,
891 # in which case a type test node will be needed.
892 return ConstNode.coerce_to(node, dst_type, env)
894 def as_py_string_node(self, env):
895 # Return a new StringNode with the same entry as this node
896 # but whose type is a Python type instead of a C type.
897 entry = self.entry
898 env.add_py_string(entry)
899 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
901 def calculate_result_code(self):
902 if self.type.is_pyobject:
903 return self.entry.pystring_cname
904 else:
905 return self.entry.cname
908 class UnicodeNode(PyConstNode):
909 # entry Symtab.Entry
911 type = unicode_type
913 def analyse_types(self, env):
914 self.entry = env.add_string_const(self.value)
915 env.add_py_string(self.entry)
917 def calculate_result_code(self):
918 return self.entry.pystring_cname
920 def _coerce_to(self, dst_type, env):
921 if not dst_type.is_pyobject:
922 node = StringNode(self.pos, entry = entry, type = py_object_type)
923 return ConstNode.coerce_to(node, dst_type, env)
924 else:
925 return self
926 # We still need to perform normal coerce_to processing on the
927 # result, because we might be coercing to an extension type,
928 # in which case a type test node will be needed.
930 def compile_time_value(self, env):
931 return self.value
934 class IdentifierStringNode(ConstNode):
935 # A Python string that behaves like an identifier, e.g. for
936 # keyword arguments in a call, or for imported names
937 type = PyrexTypes.py_object_type
939 def analyse_types(self, env):
940 self.cname = env.intern_identifier(self.value)
942 def calculate_result_code(self):
943 return self.cname
946 class LongNode(AtomicNewTempExprNode):
947 # Python long integer literal
948 #
949 # value string
951 def compile_time_value(self, denv):
952 return long(self.value)
954 gil_message = "Constructing Python long int"
956 def analyse_types(self, env):
957 self.type = py_object_type
958 self.gil_check(env)
959 self.is_temp = 1
961 gil_message = "Constructing Python long int"
963 def generate_result_code(self, code):
964 code.putln(
965 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
966 self.result(),
967 self.value,
968 code.error_goto_if_null(self.result(), self.pos)))
971 class ImagNode(AtomicNewTempExprNode):
972 # Imaginary number literal
973 #
974 # value float imaginary part
976 def compile_time_value(self, denv):
977 return complex(0.0, self.value)
979 def analyse_types(self, env):
980 self.type = py_object_type
981 self.gil_check(env)
982 self.is_temp = 1
984 gil_message = "Constructing complex number"
986 def generate_result_code(self, code):
987 code.putln(
988 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
989 self.result(),
990 self.value,
991 code.error_goto_if_null(self.result(), self.pos)))
994 class NameNode(AtomicExprNode):
995 # Reference to a local or global variable name.
996 #
997 # name string Python name of the variable
998 #
999 # entry Entry Symbol table entry
1000 # interned_cname string
1002 is_name = True
1003 is_cython_module = False
1004 cython_attribute = None
1005 lhs_of_first_assignment = False
1006 entry = None
1008 def create_analysed_rvalue(pos, env, entry):
1009 node = NameNode(pos)
1010 node.analyse_types(env, entry=entry)
1011 return node
1013 def as_cython_attribute(self):
1014 return self.cython_attribute
1016 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1018 def compile_time_value(self, denv):
1019 try:
1020 return denv.lookup(self.name)
1021 except KeyError:
1022 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1024 def coerce_to(self, dst_type, env):
1025 # If coercing to a generic pyobject and this is a builtin
1026 # C function with a Python equivalent, manufacture a NameNode
1027 # referring to the Python builtin.
1028 #print "NameNode.coerce_to:", self.name, dst_type ###
1029 if dst_type is py_object_type:
1030 entry = self.entry
1031 if entry and entry.is_cfunction:
1032 var_entry = entry.as_variable
1033 if var_entry:
1034 if var_entry.is_builtin and Options.cache_builtins:
1035 var_entry = env.declare_builtin(var_entry.name, self.pos)
1036 node = NameNode(self.pos, name = self.name)
1037 node.entry = var_entry
1038 node.analyse_rvalue_entry(env)
1039 return node
1040 return AtomicExprNode.coerce_to(self, dst_type, env)
1042 def analyse_as_module(self, env):
1043 # Try to interpret this as a reference to a cimported module.
1044 # Returns the module scope, or None.
1045 entry = self.entry
1046 if not entry:
1047 entry = env.lookup(self.name)
1048 if entry and entry.as_module:
1049 return entry.as_module
1050 return None
1052 def analyse_as_type(self, env):
1053 if self.cython_attribute:
1054 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1055 else:
1056 type = PyrexTypes.parse_basic_type(self.name)
1057 if type:
1058 return type
1059 entry = self.entry
1060 if not entry:
1061 entry = env.lookup(self.name)
1062 if entry and entry.is_type:
1063 return entry.type
1064 else:
1065 return None
1067 def analyse_as_extension_type(self, env):
1068 # Try to interpret this as a reference to an extension type.
1069 # Returns the extension type, or None.
1070 entry = self.entry
1071 if not entry:
1072 entry = env.lookup(self.name)
1073 if entry and entry.is_type and entry.type.is_extension_type:
1074 return entry.type
1075 else:
1076 return None
1078 def analyse_target_declaration(self, env):
1079 if not self.entry:
1080 self.entry = env.lookup_here(self.name)
1081 if not self.entry:
1082 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1083 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1084 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1085 if self.entry.is_declared_generic:
1086 self.result_ctype = py_object_type
1088 def analyse_types(self, env):
1089 if self.entry is None:
1090 self.entry = env.lookup(self.name)
1091 if not self.entry:
1092 self.entry = env.declare_builtin(self.name, self.pos)
1093 if not self.entry:
1094 self.type = PyrexTypes.error_type
1095 return
1096 self.analyse_rvalue_entry(env)
1098 def analyse_target_types(self, env):
1099 self.analyse_entry(env)
1100 if not self.is_lvalue():
1101 error(self.pos, "Assignment to non-lvalue '%s'"
1102 % self.name)
1103 self.type = PyrexTypes.error_type
1104 self.entry.used = 1
1105 if self.entry.type.is_buffer:
1106 import Buffer
1107 Buffer.used_buffer_aux_vars(self.entry)
1109 def analyse_rvalue_entry(self, env):
1110 #print "NameNode.analyse_rvalue_entry:", self.name ###
1111 #print "Entry:", self.entry.__dict__ ###
1112 self.analyse_entry(env)
1113 entry = self.entry
1114 if entry.is_declared_generic:
1115 self.result_ctype = py_object_type
1116 if entry.is_pyglobal or entry.is_builtin:
1117 if Options.cache_builtins and entry.is_builtin:
1118 self.is_temp = 0
1119 else:
1120 self.is_temp = 1
1121 env.use_utility_code(get_name_interned_utility_code)
1122 self.gil_check(env)
1124 gil_message = "Accessing Python global or builtin"
1126 def analyse_entry(self, env):
1127 #print "NameNode.analyse_entry:", self.name ###
1128 self.check_identifier_kind()
1129 entry = self.entry
1130 type = entry.type
1131 self.type = type
1132 if entry.is_pyglobal or entry.is_builtin:
1133 assert type.is_pyobject, "Python global or builtin not a Python object"
1134 self.interned_cname = self.entry.interned_cname = \
1135 env.intern_identifier(self.entry.name)
1137 def check_identifier_kind(self):
1138 #print "NameNode.check_identifier_kind:", self.entry.name ###
1139 #print self.entry.__dict__ ###
1140 entry = self.entry
1141 #entry.used = 1
1142 if not (entry.is_const or entry.is_variable
1143 or entry.is_builtin or entry.is_cfunction):
1144 if self.entry.as_variable:
1145 self.entry = self.entry.as_variable
1146 else:
1147 error(self.pos,
1148 "'%s' is not a constant, variable or function identifier" % self.name)
1150 def is_simple(self):
1151 # If it's not a C variable, it'll be in a temp.
1152 return 1
1154 def calculate_target_results(self, env):
1155 pass
1157 def check_const(self):
1158 entry = self.entry
1159 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1160 self.not_const()
1162 def check_const_addr(self):
1163 entry = self.entry
1164 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1165 self.addr_not_const()
1167 def is_lvalue(self):
1168 return self.entry.is_variable and \
1169 not self.entry.type.is_array and \
1170 not self.entry.is_readonly
1172 def is_ephemeral(self):
1173 # Name nodes are never ephemeral, even if the
1174 # result is in a temporary.
1175 return 0
1177 def allocate_temp(self, env, result = None):
1178 AtomicExprNode.allocate_temp(self, env, result)
1179 entry = self.entry
1180 if entry:
1181 entry.used = 1
1182 if entry.type.is_buffer:
1183 import Buffer
1184 Buffer.used_buffer_aux_vars(entry)
1185 if entry.utility_code:
1186 env.use_utility_code(entry.utility_code)
1188 def calculate_result_code(self):
1189 entry = self.entry
1190 if not entry:
1191 return "<error>" # There was an error earlier
1192 return entry.cname
1194 def generate_result_code(self, code):
1195 assert hasattr(self, 'entry')
1196 entry = self.entry
1197 if entry is None:
1198 return # There was an error earlier
1199 if entry.is_builtin and Options.cache_builtins:
1200 return # Lookup already cached
1201 elif entry.is_pyglobal or entry.is_builtin:
1202 if entry.is_builtin:
1203 namespace = Naming.builtins_cname
1204 else: # entry.is_pyglobal
1205 namespace = entry.scope.namespace_cname
1206 code.putln(
1207 '%s = __Pyx_GetName(%s, %s); %s' % (
1208 self.result(),
1209 namespace,
1210 self.interned_cname,
1211 code.error_goto_if_null(self.result(), self.pos)))
1212 elif entry.is_local and False:
1213 # control flow not good enough yet
1214 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1215 if assigned is False:
1216 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1217 elif not Options.init_local_none and assigned is None:
1218 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1219 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1221 def generate_assignment_code(self, rhs, code):
1222 #print "NameNode.generate_assignment_code:", self.name ###
1223 entry = self.entry
1224 if entry is None:
1225 return # There was an error earlier
1227 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1228 and not self.lhs_of_first_assignment):
1229 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1231 # is_pyglobal seems to be True for module level-globals only.
1232 # We use this to access class->tp_dict if necessary.
1233 if entry.is_pyglobal:
1234 namespace = self.entry.scope.namespace_cname
1235 if entry.is_member:
1236 # if the entry is a member we have to cheat: SetAttr does not work
1237 # on types, so we create a descriptor which is then added to tp_dict
1238 code.put_error_if_neg(self.pos,
1239 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1240 namespace,
1241 self.interned_cname,
1242 rhs.py_result()))
1243 # in Py2.6+, we need to invalidate the method cache
1244 code.putln("PyType_Modified(%s);" %
1245 entry.scope.parent_type.typeptr_cname)
1246 else:
1247 code.put_error_if_neg(self.pos,
1248 'PyObject_SetAttr(%s, %s, %s)' % (
1249 namespace,
1250 self.interned_cname,
1251 rhs.py_result()))
1252 if debug_disposal_code:
1253 print("NameNode.generate_assignment_code:")
1254 print("...generating disposal code for %s" % rhs)
1255 rhs.generate_disposal_code(code)
1256 rhs.free_temps(code)
1257 else:
1258 if self.type.is_buffer:
1259 # Generate code for doing the buffer release/acquisition.
1260 # This might raise an exception in which case the assignment (done
1261 # below) will not happen.
1262 #
1263 # The reason this is not in a typetest-like node is because the
1264 # variables that the acquired buffer info is stored to is allocated
1265 # per entry and coupled with it.
1266 self.generate_acquire_buffer(rhs, code)
1268 if self.type.is_pyobject:
1269 rhs.make_owned_reference(code)
1270 #print "NameNode.generate_assignment_code: to", self.name ###
1271 #print "...from", rhs ###
1272 #print "...LHS type", self.type, "ctype", self.ctype() ###
1273 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1274 if not self.lhs_of_first_assignment:
1275 if entry.is_local and not Options.init_local_none:
1276 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1277 if initalized is True:
1278 code.put_decref(self.result(), self.ctype())
1279 elif initalized is None:
1280 code.put_xdecref(self.result(), self.ctype())
1281 else:
1282 code.put_decref(self.result(), self.ctype())
1283 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1284 if debug_disposal_code:
1285 print("NameNode.generate_assignment_code:")
1286 print("...generating post-assignment code for %s" % rhs)
1287 rhs.generate_post_assignment_code(code)
1288 rhs.free_temps(code)
1290 def generate_acquire_buffer(self, rhs, code):
1291 # rhstmp is only used in case the rhs is a complicated expression leading to
1292 # the object, to avoid repeating the same C expression for every reference
1293 # to the rhs. It does NOT hold a reference.
1294 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1295 if pretty_rhs:
1296 rhstmp = rhs.result_as(self.ctype())
1297 else:
1298 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1299 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1301 buffer_aux = self.entry.buffer_aux
1302 bufstruct = buffer_aux.buffer_info_var.cname
1303 import Buffer
1304 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1305 is_initialized=not self.lhs_of_first_assignment,
1306 pos=self.pos, code=code)
1308 if not pretty_rhs:
1309 code.putln("%s = 0;" % rhstmp)
1310 code.funcstate.release_temp(rhstmp)
1312 def generate_deletion_code(self, code):
1313 if self.entry is None:
1314 return # There was an error earlier
1315 if not self.entry.is_pyglobal:
1316 error(self.pos, "Deletion of local or C global name not supported")
1317 return
1318 code.put_error_if_neg(self.pos,
1319 'PyObject_DelAttrString(%s, "%s")' % (
1320 Naming.module_cname,
1321 self.entry.name))
1323 def annotate(self, code):
1324 if hasattr(self, 'is_called') and self.is_called:
1325 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1326 if self.type.is_pyobject:
1327 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1328 else:
1329 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1331 class BackquoteNode(ExprNode):
1332 # `expr`
1333 #
1334 # arg ExprNode
1336 subexprs = ['arg']
1338 def analyse_types(self, env):
1339 self.arg.analyse_types(env)
1340 self.arg = self.arg.coerce_to_pyobject(env)
1341 self.type = py_object_type
1342 self.gil_check(env)
1343 self.is_temp = 1
1345 gil_message = "Backquote expression"
1347 def generate_result_code(self, code):
1348 code.putln(
1349 "%s = PyObject_Repr(%s); %s" % (
1350 self.result(),
1351 self.arg.py_result(),
1352 code.error_goto_if_null(self.result(), self.pos)))
1355 class ImportNode(ExprNode):
1356 # Used as part of import statement implementation.
1357 # Implements result =
1358 # __import__(module_name, globals(), None, name_list)
1359 #
1360 # module_name IdentifierStringNode dotted name of module
1361 # name_list ListNode or None list of names to be imported
1363 subexprs = ['module_name', 'name_list']
1365 def analyse_types(self, env):
1366 self.module_name.analyse_types(env)
1367 self.module_name = self.module_name.coerce_to_pyobject(env)
1368 if self.name_list:
1369 self.name_list.analyse_types(env)
1370 self.name_list.coerce_to_pyobject(env)
1371 self.type = py_object_type
1372 self.gil_check(env)
1373 self.is_temp = 1
1374 env.use_utility_code(import_utility_code)
1376 gil_message = "Python import"
1378 def generate_result_code(self, code):
1379 if self.name_list:
1380 name_list_code = self.name_list.py_result()
1381 else:
1382 name_list_code = "0"
1383 code.putln(
1384 "%s = __Pyx_Import(%s, %s); %s" % (
1385 self.result(),
1386 self.module_name.py_result(),
1387 name_list_code,
1388 code.error_goto_if_null(self.result(), self.pos)))
1391 class IteratorNode(NewTempExprNode):
1392 # Used as part of for statement implementation.
1393 #
1394 # allocate_counter_temp/release_counter_temp needs to be called
1395 # by parent (ForInStatNode)
1396 #
1397 # Implements result = iter(sequence)
1398 #
1399 # sequence ExprNode
1401 subexprs = ['sequence']
1403 def analyse_types(self, env):
1404 self.sequence.analyse_types(env)
1405 self.sequence = self.sequence.coerce_to_pyobject(env)
1406 self.type = py_object_type
1407 self.gil_check(env)
1408 self.is_temp = 1
1410 gil_message = "Iterating over Python object"
1412 def allocate_counter_temp(self, code):
1413 self.counter_cname = code.funcstate.allocate_temp(
1414 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1416 def release_counter_temp(self, code):
1417 code.funcstate.release_temp(self.counter_cname)
1419 def generate_result_code(self, code):
1420 is_builtin_sequence = self.sequence.type is list_type or \
1421 self.sequence.type is tuple_type
1422 if is_builtin_sequence:
1423 code.putln(
1424 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1425 else:
1426 code.putln(
1427 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1428 self.sequence.py_result(),
1429 self.sequence.py_result()))
1430 code.putln(
1431 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1432 self.counter_cname,
1433 self.result(),
1434 self.sequence.py_result(),
1435 self.result()))
1436 code.putln("} else {")
1437 if is_builtin_sequence:
1438 code.putln(
1439 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1440 code.error_goto(self.pos))
1441 else:
1442 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1443 self.counter_cname,
1444 self.result(),
1445 self.sequence.py_result(),
1446 code.error_goto_if_null(self.result(), self.pos)))
1447 code.putln("}")
1450 class NextNode(AtomicNewTempExprNode):
1451 # Used as part of for statement implementation.
1452 # Implements result = iterator.next()
1453 # Created during analyse_types phase.
1454 # The iterator is not owned by this node.
1455 #
1456 # iterator ExprNode
1458 def __init__(self, iterator, env):
1459 self.pos = iterator.pos
1460 self.iterator = iterator
1461 self.type = py_object_type
1462 self.is_temp = 1
1464 def generate_result_code(self, code):
1465 if self.iterator.sequence.type is list_type:
1466 type_checks = [(list_type, "List")]
1467 elif self.iterator.sequence.type is tuple_type:
1468 type_checks = [(tuple_type, "Tuple")]
1469 else:
1470 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1472 for py_type, prefix in type_checks:
1473 if len(type_checks) > 1:
1474 code.putln(
1475 "if (likely(Py%s_CheckExact(%s))) {" % (
1476 prefix, self.iterator.py_result()))
1477 code.putln(
1478 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1479 self.iterator.counter_cname,
1480 prefix,
1481 self.iterator.py_result()))
1482 code.putln(
1483 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1484 self.result(),
1485 prefix,
1486 self.iterator.py_result(),
1487 self.iterator.counter_cname,
1488 self.result(),
1489 self.iterator.counter_cname))
1490 if len(type_checks) > 1:
1491 code.put("} else ")
1492 if len(type_checks) == 1:
1493 return
1494 code.putln("{")
1495 code.putln(
1496 "%s = PyIter_Next(%s);" % (
1497 self.result(),
1498 self.iterator.py_result()))
1499 code.putln(
1500 "if (!%s) {" %
1501 self.result())
1502 code.putln(code.error_goto_if_PyErr(self.pos))
1503 code.putln("break;")
1504 code.putln("}")
1505 code.putln("}")
1508 class ExcValueNode(AtomicNewTempExprNode):
1509 # Node created during analyse_types phase
1510 # of an ExceptClauseNode to fetch the current
1511 # exception value.
1513 def __init__(self, pos, env, var):
1514 ExprNode.__init__(self, pos)
1515 self.type = py_object_type
1516 self.var = var
1518 def calculate_result_code(self):
1519 return self.var
1521 def generate_result_code(self, code):
1522 pass
1524 def analyse_types(self, env):
1525 pass
1528 class TempNode(ExprNode):
1529 # Node created during analyse_types phase
1530 # of some nodes to hold a temporary value.
1532 subexprs = []
1534 def __init__(self, pos, type, env):
1535 ExprNode.__init__(self, pos)
1536 self.type = type
1537 if type.is_pyobject:
1538 self.result_ctype = py_object_type
1539 self.is_temp = 1
1541 def analyse_types(self, env):
1542 return self.type
1544 def generate_result_code(self, code):
1545 pass
1548 class PyTempNode(TempNode):
1549 # TempNode holding a Python value.
1551 def __init__(self, pos, env):
1552 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1555 #-------------------------------------------------------------------
1556 #
1557 # Trailer nodes
1558 #
1559 #-------------------------------------------------------------------
1561 class IndexNode(ExprNode):
1562 # Sequence indexing.
1563 #
1564 # base ExprNode
1565 # index ExprNode
1566 # indices [ExprNode]
1567 # is_buffer_access boolean Whether this is a buffer access.
1568 #
1569 # indices is used on buffer access, index on non-buffer access.
1570 # The former contains a clean list of index parameters, the
1571 # latter whatever Python object is needed for index access.
1573 subexprs = ['base', 'index', 'indices']
1574 indices = None
1576 def __init__(self, pos, index, *args, **kw):
1577 ExprNode.__init__(self, pos, index=index, *args, **kw)
1578 self._index = index
1580 def compile_time_value(self, denv):
1581 base = self.base.compile_time_value(denv)
1582 index = self.index.compile_time_value(denv)
1583 try:
1584 return base[index]
1585 except Exception, e:
1586 self.compile_time_value_error(e)
1588 def is_ephemeral(self):
1589 return self.base.is_ephemeral()
1591 def analyse_target_declaration(self, env):
1592 pass
1594 def analyse_as_type(self, env):
1595 base_type = self.base.analyse_as_type(env)
1596 if base_type and not base_type.is_pyobject:
1597 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1598 return None
1600 def analyse_types(self, env):
1601 self.analyse_base_and_index_types(env, getting = 1)
1603 def analyse_target_types(self, env):
1604 self.analyse_base_and_index_types(env, setting = 1)
1606 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1607 # Note: This might be cleaned up by having IndexNode
1608 # parsed in a saner way and only construct the tuple if
1609 # needed.
1611 # Note that this function must leave IndexNode in a cloneable state.
1612 # For buffers, self.index is packed out on the initial analysis, and
1613 # when cloning self.indices is copied.
1614 self.is_buffer_access = False
1616 self.base.analyse_types(env)
1617 # Handle the case where base is a literal char* (and we expect a string, not an int)
1618 if isinstance(self.base, StringNode):
1619 self.base = self.base.coerce_to_pyobject(env)
1621 skip_child_analysis = False
1622 buffer_access = False
1623 if self.base.type.is_buffer:
1624 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1625 if self.indices:
1626 indices = self.indices
1627 else:
1628 # On cloning, indices is cloned. Otherwise, unpack index into indices
1629 assert not isinstance(self.index, CloneNode)
1630 if isinstance(self.index, TupleNode):
1631 indices = self.index.args
1632 else:
1633 indices = [self.index]
1634 if len(indices) == self.base.type.ndim:
1635 buffer_access = True
1636 skip_child_analysis = True
1637 for x in indices:
1638 x.analyse_types(env)
1639 if not x.type.is_int:
1640 buffer_access = False
1642 if buffer_access:
1643 self.indices = indices
1644 self.index = None
1645 self.type = self.base.type.dtype
1646 self.is_buffer_access = True
1647 self.buffer_type = self.base.entry.type
1649 if getting and self.type.is_pyobject:
1650 self.is_temp = True
1651 if setting:
1652 if not self.base.entry.type.writable:
1653 error(self.pos, "Writing to readonly buffer")
1654 else:
1655 self.base.entry.buffer_aux.writable_needed = True
1656 else:
1657 if isinstance(self.index, TupleNode):
1658 self.index.analyse_types(env, skip_children=skip_child_analysis)
1659 elif not skip_child_analysis:
1660 self.index.analyse_types(env)
1661 self.original_index_type = self.index.type
1662 if self.base.type.is_pyobject:
1663 if self.index.type.is_int and not self.index.type.is_longlong:
1664 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1665 else:
1666 self.index = self.index.coerce_to_pyobject(env)
1667 self.type = py_object_type
1668 self.gil_check(env)
1669 self.is_temp = 1
1670 else:
1671 if self.base.type.is_ptr or self.base.type.is_array:
1672 self.type = self.base.type.base_type
1673 else:
1674 error(self.pos,
1675 "Attempting to index non-array type '%s'" %
1676 self.base.type)
1677 self.type = PyrexTypes.error_type
1678 if self.index.type.is_pyobject:
1679 self.index = self.index.coerce_to(
1680 PyrexTypes.c_py_ssize_t_type, env)
1681 if not self.index.type.is_int:
1682 error(self.pos,
1683 "Invalid index type '%s'" %
1684 self.index.type)
1686 gil_message = "Indexing Python object"
1688 def check_const_addr(self):
1689 self.base.check_const_addr()
1690 self.index.check_const()
1692 def is_lvalue(self):
1693 return 1
1695 def calculate_result_code(self):
1696 if self.is_buffer_access:
1697 return "(*%s)" % self.buffer_ptr_code
1698 else:
1699 return "(%s[%s])" % (
1700 self.base.result(), self.index.result())
1702 def index_unsigned_parameter(self):
1703 if self.index.type.is_int:
1704 if self.original_index_type.signed:
1705 return ", 0"
1706 else:
1707 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1708 else:
1709 return ""
1711 def generate_subexpr_evaluation_code(self, code):
1712 self.base.generate_evaluation_code(code)
1713 if not self.indices:
1714 self.index.generate_evaluation_code(code)
1715 else:
1716 for i in self.indices:
1717 i.generate_evaluation_code(code)
1719 def generate_subexpr_disposal_code(self, code):
1720 self.base.generate_disposal_code(code)
1721 if not self.indices:
1722 self.index.generate_disposal_code(code)
1723 else:
1724 for i in self.indices:
1725 i.generate_disposal_code(code)
1727 def free_subexpr_temps(self, code):
1728 self.base.free_temps(code)
1729 if not self.indices:
1730 self.index.free_temps(code)
1731 else:
1732 for i in self.indices:
1733 i.free_temps(code)
1735 def generate_result_code(self, code):
1736 if self.is_buffer_access:
1737 if code.globalstate.directives['nonecheck']:
1738 self.put_nonecheck(code)
1739 self.buffer_ptr_code = self.buffer_lookup_code(code)
1740 if self.type.is_pyobject:
1741 # is_temp is True, so must pull out value and incref it.
1742 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1743 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1744 elif self.type.is_pyobject:
1745 if self.index.type.is_int:
1746 function = "__Pyx_GetItemInt"
1747 index_code = self.index.result()
1748 code.globalstate.use_utility_code(getitem_int_utility_code)
1749 else:
1750 function = "PyObject_GetItem"
1751 index_code = self.index.py_result()
1752 sign_code = ""
1753 code.putln(
1754 "%s = %s(%s, %s%s); if (!%s) %s" % (
1755 self.result(),
1756 function,
1757 self.base.py_result(),
1758 index_code,
1759 self.index_unsigned_parameter(),
1760 self.result(),
1761 code.error_goto(self.pos)))
1763 def generate_setitem_code(self, value_code, code):
1764 if self.index.type.is_int:
1765 function = "__Pyx_SetItemInt"
1766 index_code = self.index.result()
1767 code.globalstate.use_utility_code(setitem_int_utility_code)
1768 else:
1769 index_code = self.index.py_result()
1770 if self.base.type is dict_type:
1771 function = "PyDict_SetItem"
1772 elif self.base.type is list_type:
1773 function = "PyList_SetItem"
1774 # don't use PyTuple_SetItem(), as we'd normally get a
1775 # TypeError when changing a tuple, while PyTuple_SetItem()
1776 # would allow updates
1777 #
1778 #elif self.base.type is tuple_type:
1779 # function = "PyTuple_SetItem"
1780 else:
1781 function = "PyObject_SetItem"
1782 code.putln(
1783 "if (%s(%s, %s, %s%s) < 0) %s" % (
1784 function,
1785 self.base.py_result(),
1786 index_code,
1787 value_code,
1788 self.index_unsigned_parameter(),
1789 code.error_goto(self.pos)))
1791 def generate_buffer_setitem_code(self, rhs, code, op=""):
1792 # Used from generate_assignment_code and InPlaceAssignmentNode
1793 if code.globalstate.directives['nonecheck']:
1794 self.put_nonecheck(code)
1795 ptrexpr = self.buffer_lookup_code(code)
1796 if self.buffer_type.dtype.is_pyobject:
1797 # Must manage refcounts. Decref what is already there
1798 # and incref what we put in.
1799 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1800 rhs_code = rhs.result()
1801 code.putln("%s = %s;" % (ptr, ptrexpr))
1802 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1803 ptr, rhs_code
1804 ))
1805 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1806 code.funcstate.release_temp(ptr)
1807 else:
1808 # Simple case
1809 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1811 def generate_assignment_code(self, rhs, code):
1812 self.generate_subexpr_evaluation_code(code)
1813 if self.is_buffer_access:
1814 self.generate_buffer_setitem_code(rhs, code)
1815 elif self.type.is_pyobject:
1816 self.generate_setitem_code(rhs.py_result(), code)
1817 else:
1818 code.putln(
1819 "%s = %s;" % (
1820 self.result(), rhs.result()))
1821 self.generate_subexpr_disposal_code(code)
1822 self.free_subexpr_temps(code)
1823 rhs.generate_disposal_code(code)
1824 rhs.free_temps(code)
1826 def generate_deletion_code(self, code):
1827 self.generate_subexpr_evaluation_code(code)
1828 #if self.type.is_pyobject:
1829 if self.index.type.is_int:
1830 function = "__Pyx_DelItemInt"
1831 index_code = self.index.result()
1832 code.globalstate.use_utility_code(delitem_int_utility_code)
1833 else:
1834 index_code = self.index.py_result()
1835 if self.base.type is dict_type:
1836 function = "PyDict_DelItem"
1837 else:
1838 function = "PyObject_DelItem"
1839 code.putln(
1840 "if (%s(%s, %s%s) < 0) %s" % (
1841 function,
1842 self.base.py_result(),
1843 index_code,
1844 self.index_unsigned_parameter(),
1845 code.error_goto(self.pos)))
1846 self.generate_subexpr_disposal_code(code)
1848 def buffer_lookup_code(self, code):
1849 # Assign indices to temps
1850 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1851 for temp, index in zip(index_temps, self.indices):
1852 code.putln("%s = %s;" % (temp, index.result()))
1853 # Generate buffer access code using these temps
1854 import Buffer
1855 # The above could happen because child_attrs is wrong somewhere so that
1856 # options are not propagated.
1857 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1858 index_signeds=[i.type.signed for i in self.indices],
1859 index_cnames=index_temps,
1860 options=code.globalstate.directives,
1861 pos=self.pos, code=code)
1863 def put_nonecheck(self, code):
1864 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1865 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1866 code.putln("__Pyx_RaiseNoneIndexingError();")
1867 code.putln(code.error_goto(self.pos))
1868 code.putln("}")
1870 class SliceIndexNode(ExprNode):
1871 # 2-element slice indexing
1872 #
1873 # base ExprNode
1874 # start ExprNode or None
1875 # stop ExprNode or None
1877 subexprs = ['base', 'start', 'stop']
1879 def compile_time_value(self, denv):
1880 base = self.base.compile_time_value(denv)
1881 if self.start is None:
1882 start = 0
1883 else:
1884 start = self.start.compile_time_value(denv)
1885 if self.stop is None:
1886 stop = None
1887 else:
1888 stop = self.stop.compile_time_value(denv)
1889 try:
1890 return base[start:stop]
1891 except Exception, e:
1892 self.compile_time_value_error(e)
1894 def analyse_target_declaration(self, env):
1895 pass
1897 def analyse_types(self, env):
1898 self.base.analyse_types(env)
1899 if self.start:
1900 self.start.analyse_types(env)
1901 if self.stop:
1902 self.stop.analyse_types(env)
1903 if self.base.type.is_array or self.base.type.is_ptr:
1904 # we need a ptr type here instead of an array type, as
1905 # array types can result in invalid type casts in the C
1906 # code
1907 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
1908 else:
1909 self.base = self.base.coerce_to_pyobject(env)
1910 self.type = py_object_type
1911 c_int = PyrexTypes.c_py_ssize_t_type
1912 if self.start:
1913 self.start = self.start.coerce_to(c_int, env)
1914 if self.stop:
1915 self.stop = self.stop.coerce_to(c_int, env)
1916 self.gil_check(env)
1917 self.is_temp = 1
1919 gil_message = "Slicing Python object"
1921 def generate_result_code(self, code):
1922 if not self.type.is_pyobject:
1923 error(self.pos,
1924 "Slicing is not currently supported for '%s'." % self.type)
1925 return
1926 code.putln(
1927 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1928 self.result(),
1929 self.base.py_result(),
1930 self.start_code(),
1931 self.stop_code(),
1932 code.error_goto_if_null(self.result(), self.pos)))
1934 def generate_assignment_code(self, rhs, code):
1935 self.generate_subexpr_evaluation_code(code)
1936 if self.type.is_pyobject:
1937 code.put_error_if_neg(self.pos,
1938 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1939 self.base.py_result(),
1940 self.start_code(),
1941 self.stop_code(),
1942 rhs.result()))
1943 else:
1944 start_offset = ''
1945 if self.start:
1946 start_offset = self.start_code()
1947 if start_offset == '0':
1948 start_offset = ''
1949 else:
1950 start_offset += '+'
1951 if rhs.type.is_array:
1952 array_length = rhs.type.size
1953 self.generate_slice_guard_code(code, array_length)
1954 else:
1955 error("Slice assignments from pointers are not yet supported.")
1956 # FIXME: fix the array size according to start/stop
1957 array_length = self.base.type.size
1958 for i in range(array_length):
1959 code.putln("%s[%s%s] = %s[%d];" % (
1960 self.base.result(), start_offset, i,
1961 rhs.result(), i))
1962 self.generate_subexpr_disposal_code(code)
1963 rhs.generate_disposal_code(code)
1964 rhs.free_temps(code)
1966 def generate_deletion_code(self, code):
1967 if not self.type.is_pyobject:
1968 error(self.pos,
1969 "Deleting slices is only supported for Python types, not '%s'." % self.type)
1970 return
1971 self.generate_subexpr_evaluation_code(code)
1972 code.put_error_if_neg(self.pos,
1973 "PySequence_DelSlice(%s, %s, %s)" % (
1974 self.base.py_result(),
1975 self.start_code(),
1976 self.stop_code()))
1977 self.generate_subexpr_disposal_code(code)
1979 def generate_slice_guard_code(self, code, target_size):
1980 if not self.base.type.is_array:
1981 return
1982 slice_size = self.base.type.size
1983 start = stop = None
1984 if self.stop:
1985 stop = self.stop.result()
1986 try:
1987 stop = int(stop)
1988 if stop < 0:
1989 slice_size = self.base.type.size + stop
1990 else:
1991 slice_size = stop
1992 stop = None
1993 except ValueError:
1994 pass
1995 if self.start:
1996 start = self.start.result()
1997 try:
1998 start = int(start)
1999 if start < 0:
2000 start = self.base.type.size + start
2001 slice_size -= start
2002 start = None
2003 except ValueError:
2004 pass
2005 check = None
2006 if slice_size < 0:
2007 if target_size > 0:
2008 error(self.pos, "Assignment to empty slice.")
2009 elif start is None and stop is None:
2010 # we know the exact slice length
2011 if target_size != slice_size:
2012 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2013 slice_size, target_size))
2014 elif start is not None:
2015 if stop is None:
2016 stop = slice_size
2017 check = "(%s)-(%s)" % (stop, start)
2018 else: # stop is not None:
2019 check = stop
2020 if check:
2021 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2022 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2023 target_size, check))
2024 code.putln(code.error_goto(self.pos))
2025 code.putln("}")
2027 def start_code(self):
2028 if self.start:
2029 return self.start.result()
2030 else:
2031 return "0"
2033 def stop_code(self):
2034 if self.stop:
2035 return self.stop.result()
2036 elif self.base.type.is_array:
2037 return self.base.type.size
2038 else:
2039 return "PY_SSIZE_T_MAX"
2041 def calculate_result_code(self):
2042 # self.result() is not used, but this method must exist
2043 return "<unused>"
2046 class SliceNode(ExprNode):
2047 # start:stop:step in subscript list
2048 #
2049 # start ExprNode
2050 # stop ExprNode
2051 # step ExprNode
2053 def compile_time_value(self, denv):
2054 start = self.start.compile_time_value(denv)
2055 if self.stop is None:
2056 stop = None
2057 else:
2058 stop = self.stop.compile_time_value(denv)
2059 if self.step is None:
2060 step = None
2061 else:
2062 step = self.step.compile_time_value(denv)
2063 try:
2064 return slice(start, stop, step)
2065 except Exception, e:
2066 self.compile_time_value_error(e)
2068 subexprs = ['start', 'stop', 'step']
2070 def analyse_types(self, env):
2071 self.start.analyse_types(env)
2072 self.stop.analyse_types(env)
2073 self.step.analyse_types(env)
2074 self.start = self.start.coerce_to_pyobject(env)
2075 self.stop = self.stop.coerce_to_pyobject(env)
2076 self.step = self.step.coerce_to_pyobject(env)
2077 self.type = py_object_type
2078 self.gil_check(env)
2079 self.is_temp = 1
2081 gil_message = "Constructing Python slice object"
2083 def generate_result_code(self, code):
2084 code.putln(
2085 "%s = PySlice_New(%s, %s, %s); %s" % (
2086 self.result(),
2087 self.start.py_result(),
2088 self.stop.py_result(),
2089 self.step.py_result(),
2090 code.error_goto_if_null(self.result(), self.pos)))
2093 class CallNode(ExprNode):
2094 def gil_check(self, env):
2095 # Make sure we're not in a nogil environment
2096 if env.nogil:
2097 error(self.pos, "Calling gil-requiring function without gil")
2099 def analyse_as_type_constructor(self, env):
2100 type = self.function.analyse_as_type(env)
2101 if type and type.is_struct_or_union:
2102 args, kwds = self.explicit_args_kwds()
2103 items = []
2104 for arg, member in zip(args, type.scope.var_entries):
2105 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2106 if kwds:
2107 items += kwds.key_value_pairs
2108 self.key_value_pairs = items
2109 self.__class__ = DictNode
2110 self.analyse_types(env)
2111 self.coerce_to(type, env)
2112 return True
2115 class SimpleCallNode(CallNode):
2116 # Function call without keyword, * or ** args.
2117 #
2118 # function ExprNode
2119 # args [ExprNode]
2120 # arg_tuple ExprNode or None used internally
2121 # self ExprNode or None used internally
2122 # coerced_self ExprNode or None used internally
2123 # wrapper_call bool used internally
2124 # has_optional_args bool used internally
2126 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2128 self = None
2129 coerced_self = None
2130 arg_tuple = None
2131 wrapper_call = False
2132 has_optional_args = False
2134 def compile_time_value(self, denv):
2135 function = self.function.compile_time_value(denv)
2136 args = [arg.compile_time_value(denv) for arg in self.args]
2137 try:
2138 return function(*args)
2139 except Exception, e:
2140 self.compile_time_value_error(e)
2142 def analyse_as_type(self, env):
2143 attr = self.function.as_cython_attribute()
2144 if attr == 'pointer':
2145 if len(self.args) != 1:
2146 error(self.args.pos, "only one type allowed.")
2147 else:
2148 type = self.args[0].analyse_as_type(env)
2149 if not type:
2150 error(self.args[0].pos, "Unknown type")
2151 else:
2152 return PyrexTypes.CPtrType(type)
2154 def explicit_args_kwds(self):
2155 return self.args, None
2157 def analyse_types(self, env):
2158 if self.analyse_as_type_constructor(env):
2159 return
2160 function = self.function
2161 function.is_called = 1
2162 self.function.analyse_types(env)
2163 if function.is_attribute and function.is_py_attr and \
2164 function.attribute == "append" and len(self.args) == 1:
2165 # L.append(x) is almost always applied to a list
2166 self.py_func = self.function
2167 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2168 self.function.analyse_types(env)
2169 self.self = self.py_func.obj
2170 function.obj = CloneNode(self.self)
2171 env.use_utility_code(append_utility_code)
2172 if function.is_attribute and function.entry and function.entry.is_cmethod:
2173 # Take ownership of the object from which the attribute
2174 # was obtained, because we need to pass it as 'self'.
2175 self.self = function.obj
2176 function.obj = CloneNode(self.self)
2177 func_type = self.function_type()
2178 if func_type.is_pyobject:
2179 self.arg_tuple = TupleNode(self.pos, args = self.args)
2180 self.arg_tuple.analyse_types(env)
2181 self.args = None
2182 self.type = py_object_type
2183 self.gil_check(env)
2184 self.is_temp = 1
2185 else:
2186 for arg in self.args:
2187 arg.analyse_types(env)
2188 if self.self and func_type.args:
2189 # Coerce 'self' to the type expected by the method.
2190 expected_type = func_type.args[0].type
2191 self.coerced_self = CloneNode(self.self).coerce_to(
2192 expected_type, env)
2193 # Insert coerced 'self' argument into argument list.
2194 self.args.insert(0, self.coerced_self)
2195 self.analyse_c_function_call(env)
2197 def function_type(self):
2198 # Return the type of the function being called, coercing a function
2199 # pointer to a function if necessary.
2200 func_type = self.function.type
2201 if func_type.is_ptr:
2202 func_type = func_type.base_type
2203 return func_type
2205 def analyse_c_function_call(self, env):
2206 func_type = self.function_type()
2207 # Check function type
2208 if not func_type.is_cfunction:
2209 if not func_type.is_error:
2210 error(self.pos, "Calling non-function type '%s'" %
2211 func_type)
2212 self.type = PyrexTypes.error_type
2213 self.result_code = "<error>"
2214 return
2215 # Check no. of args
2216 max_nargs = len(func_type.args)
2217 expected_nargs = max_nargs - func_type.optional_arg_count
2218 actual_nargs = len(self.args)
2219 if actual_nargs < expected_nargs \
2220 or (not func_type.has_varargs and actual_nargs > max_nargs):
2221 expected_str = str(expected_nargs)
2222 if func_type.has_varargs:
2223 expected_str = "at least " + expected_str
2224 elif func_type.optional_arg_count:
2225 if actual_nargs < max_nargs:
2226 expected_str = "at least " + expected_str
2227 else:
2228 expected_str = "at most " + str(max_nargs)
2229 error(self.pos,
2230 "Call with wrong number of arguments (expected %s, got %s)"
2231 % (expected_str, actual_nargs))
2232 self.args = None
2233 self.type = PyrexTypes.error_type
2234 self.result_code = "<error>"
2235 return
2236 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2237 self.has_optional_args = 1
2238 self.is_temp = 1
2239 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2240 env.release_temp(self.opt_arg_struct)
2241 # Coerce arguments
2242 for i in range(min(max_nargs, actual_nargs)):
2243 formal_type = func_type.args[i].type
2244 self.args[i] = self.args[i].coerce_to(formal_type, env)
2245 for i in range(max_nargs, actual_nargs):
2246 if self.args[i].type.is_pyobject:
2247 error(self.args[i].pos,
2248 "Python object cannot be passed as a varargs parameter")
2249 # Calc result type and code fragment
2250 self.type = func_type.return_type
2251 if self.type.is_pyobject \
2252 or func_type.exception_value is not None \
2253 or func_type.exception_check:
2254 self.is_temp = 1
2255 if self.type.is_pyobject:
2256 self.result_ctype = py_object_type
2257 # C++ exception handler
2258 if func_type.exception_check == '+':
2259 if func_type.exception_value is None:
2260 env.use_utility_code(cpp_exception_utility_code)
2261 # Check gil
2262 if not func_type.nogil:
2263 self.gil_check(env)
2265 def calculate_result_code(self):
2266 return self.c_call_code()
2268 def c_call_code(self):
2269 func_type = self.function_type()
2270 if self.args is None or not func_type.is_cfunction:
2271 return "<error>"
2272 formal_args = func_type.args
2273 arg_list_code = []
2274 args = zip(formal_args, self.args)
2275 max_nargs = len(func_type.args)
2276 expected_nargs = max_nargs - func_type.optional_arg_count
2277 actual_nargs = len(self.args)
2278 for formal_arg, actual_arg in args[:expected_nargs]:
2279 arg_code = actual_arg.result_as(formal_arg.type)
2280 arg_list_code.append(arg_code)
2282 if func_type.is_overridable:
2283 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2285 if func_type.optional_arg_count:
2286 if expected_nargs == actual_nargs:
2287 optional_args = 'NULL'
2288 else:
2289 optional_args = "&%s" % self.opt_arg_struct
2290 arg_list_code.append(optional_args)
2292 for actual_arg in self.args[len(formal_args):]:
2293 arg_list_code.append(actual_arg.result())
2294 result = "%s(%s)" % (self.function.result(),
2295 join(arg_list_code, ", "))
2296 # if self.wrapper_call or \
2297 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2298 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2299 return result
2301 def generate_result_code(self, code):
2302 func_type = self.function_type()
2303 if func_type.is_pyobject:
2304 arg_code = self.arg_tuple.py_result()
2305 code.putln(
2306 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2307 self.result(),
2308 self.function.py_result(),
2309 arg_code,
2310 code.error_goto_if_null(self.result(), self.pos)))
2311 elif func_type.is_cfunction:
2312 if self.has_optional_args:
2313 actual_nargs = len(self.args)
2314 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2315 code.putln("%s.%s = %s;" % (
2316 self.opt_arg_struct,
2317 Naming.pyrex_prefix + "n",
2318 len(self.args) - expected_nargs))
2319 args = zip(func_type.args, self.args)
2320 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2321 code.putln("%s.%s = %s;" % (
2322 self.opt_arg_struct,
2323 formal_arg.name,
2324 actual_arg.result_as(formal_arg.type)))
2325 exc_checks = []
2326 if self.type.is_pyobject:
2327 exc_checks.append("!%s" % self.result())
2328 else:
2329 exc_val = func_type.exception_value
2330 exc_check = func_type.exception_check
2331 if exc_val is not None:
2332 exc_checks.append("%s == %s" % (self.result(), exc_val))
2333 if exc_check:
2334 exc_checks.append("PyErr_Occurred()")
2335 if self.is_temp or exc_checks:
2336 rhs = self.c_call_code()
2337 if self.result():
2338 lhs = "%s = " % self.result()
2339 if self.is_temp and self.type.is_pyobject:
2340 #return_type = self.type # func_type.return_type
2341 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2342 # "from", return_type, "to pyobject" ###
2343 rhs = typecast(py_object_type, self.type, rhs)
2344 else:
2345 lhs = ""
2346 if func_type.exception_check == '+':
2347 if func_type.exception_value is None:
2348 raise_py_exception = "__Pyx_CppExn2PyErr()"
2349 elif func_type.exception_value.type.is_pyobject:
2350 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2351 else:
2352 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2353 code.putln(
2354 "try {%s%s;} catch(...) {%s; %s}" % (
2355 lhs,
2356 rhs,
2357 raise_py_exception,
2358 code.error_goto(self.pos)))
2359 else:
2360 if exc_checks:
2361 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2362 else:
2363 goto_error = ""
2364 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2366 class GeneralCallNode(CallNode):
2367 # General Python function call, including keyword,
2368 # * and ** arguments.
2369 #
2370 # function ExprNode
2371 # positional_args ExprNode Tuple of positional arguments
2372 # keyword_args ExprNode or None Dict of keyword arguments
2373 # starstar_arg ExprNode or None Dict of extra keyword args
2375 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2377 def compile_time_value(self, denv):
2378 function = self.function.compile_time_value(denv)
2379 positional_args = self.positional_args.compile_time_value(denv)
2380 keyword_args = self.keyword_args.compile_time_value(denv)
2381 starstar_arg = self.starstar_arg.compile_time_value(denv)
2382 try:
2383 keyword_args.update(starstar_arg)
2384 return function(*positional_args, **keyword_args)
2385 except Exception, e:
2386 self.compile_time_value_error(e)
2388 def explicit_args_kwds(self):
2389 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2390 raise PostParseError(self.pos,
2391 'Compile-time keyword arguments must be explicit.')
2392 return self.positional_args.args, self.keyword_args
2394 def analyse_types(self, env):
2395 if self.analyse_as_type_constructor(env):
2396 return
2397 self.function.analyse_types(env)
2398 self.positional_args.analyse_types(env)
2399 if self.keyword_args:
2400 self.keyword_args.analyse_types(env)
2401 if self.starstar_arg:
2402 self.starstar_arg.analyse_types(env)
2403 self.function = self.function.coerce_to_pyobject(env)
2404 self.positional_args = \
2405 self.positional_args.coerce_to_pyobject(env)
2406 if self.starstar_arg:
2407 self.starstar_arg = \
2408 self.starstar_arg.coerce_to_pyobject(env)
2409 self.type = py_object_type
2410 self.gil_check(env)
2411 self.is_temp = 1
2413 def generate_result_code(self, code):
2414 if self.keyword_args and self.starstar_arg:
2415 code.put_error_if_neg(self.pos,
2416 "PyDict_Update(%s, %s)" % (
2417 self.keyword_args.py_result(),
2418 self.starstar_arg.py_result()))
2419 keyword_code = self.keyword_args.py_result()
2420 elif self.keyword_args:
2421 keyword_code = self.keyword_args.py_result()
2422 elif self.starstar_arg:
2423 keyword_code = self.starstar_arg.py_result()
2424 else:
2425 keyword_code = None
2426 if not keyword_code:
2427 call_code = "PyObject_Call(%s, %s, NULL)" % (
2428 self.function.py_result(),
2429 self.positional_args.py_result())
2430 else:
2431 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2432 self.function.py_result(),
2433 self.positional_args.py_result(),
2434 keyword_code)
2435 code.putln(
2436 "%s = %s; %s" % (
2437 self.result(),
2438 call_code,
2439 code.error_goto_if_null(self.result(), self.pos)))
2442 class AsTupleNode(ExprNode):
2443 # Convert argument to tuple. Used for normalising
2444 # the * argument of a function call.
2445 #
2446 # arg ExprNode
2448 subexprs = ['arg']
2450 def compile_time_value(self, denv):
2451 arg = self.arg.compile_time_value(denv)
2452 try:
2453 return tuple(arg)
2454 except Exception, e:
2455 self.compile_time_value_error(e)
2457 def analyse_types(self, env):
2458 self.arg.analyse_types(env)
2459 self.arg = self.arg.coerce_to_pyobject(env)
2460 self.type = tuple_type
2461 self.gil_check(env)
2462 self.is_temp = 1
2464 gil_message = "Constructing Python tuple"
2466 def generate_result_code(self, code):
2467 code.putln(
2468 "%s = PySequence_Tuple(%s); %s" % (
2469 self.result(),
2470 self.arg.py_result(),
2471 code.error_goto_if_null(self.result(), self.pos)))
2474 class AttributeNode(ExprNode):
2475 # obj.attribute
2476 #
2477 # obj ExprNode
2478 # attribute string
2479 # needs_none_check boolean Used if obj is an extension type.
2480 # If set to True, it is known that the type is not None.
2481 #
2482 # Used internally:
2483 #
2484 # is_py_attr boolean Is a Python getattr operation
2485 # member string C name of struct member
2486 # is_called boolean Function call is being done on result
2487 # entry Entry Symbol table entry of attribute
2488 # interned_attr_cname string C name of interned attribute name
2490 is_attribute = 1
2491 subexprs = ['obj']
2493 type = PyrexTypes.error_type
2494 entry = None
2495 is_called = 0
2496 needs_none_check = True
2498 def as_cython_attribute(self):
2499 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2500 return self.attribute
2502 def coerce_to(self, dst_type, env):
2503 # If coercing to a generic pyobject and this is a cpdef function
2504 # we can create the corresponding attribute
2505 if dst_type is py_object_type:
2506 entry = self.entry
2507 if entry and entry.is_cfunction and entry.as_variable:
2508 # must be a cpdef function
2509 self.is_temp = 1
2510 self.entry = entry.as_variable
2511 self.analyse_as_python_attribute(env)
2512 return self
2513 return ExprNode.coerce_to(self, dst_type, env)
2515 def compile_time_value(self, denv):
2516 attr = self.attribute
2517 if attr.beginswith("__") and attr.endswith("__"):
2518 self.error("Invalid attribute name '%s' in compile-time expression"
2519 % attr)
2520 return None
2521 obj = self.arg.compile_time_value(denv)
2522 try:
2523 return getattr(obj, attr)
2524 except Exception, e:
2525 self.compile_time_value_error(e)
2527 def analyse_target_declaration(self, env):
2528 pass
2530 def analyse_target_types(self, env):
2531 self.analyse_types(env, target = 1)
2533 def analyse_types(self, env, target = 0):
2534 if self.analyse_as_cimported_attribute(env, target):
2535 return
2536 if not target and self.analyse_as_unbound_cmethod(env):
2537 return
2538 self.analyse_as_ordinary_attribute(env, target)
2540 def analyse_as_cimported_attribute(self, env, target):
2541 # Try to interpret this as a reference to an imported
2542 # C const, type, var or function. If successful, mutates
2543 # this node into a NameNode and returns 1, otherwise
2544 # returns 0.
2545 module_scope = self.obj.analyse_as_module(env)
2546 if module_scope:
2547 entry = module_scope.lookup_here(self.attribute)
2548 if entry and (
2549 entry.is_cglobal or entry.is_cfunction
2550 or entry.is_type or entry.is_const):
2551 self.mutate_into_name_node(env, entry, target)
2552 return 1
2553 return 0
2555 def analyse_as_unbound_cmethod(self, env):
2556 # Try to interpret this as a reference to an unbound
2557 # C method of an extension type. If successful, mutates
2558 # this node into a NameNode and returns 1, otherwise
2559 # returns 0.
2560 type = self.obj.analyse_as_extension_type(env)
2561 if type:
2562 entry = type.scope.lookup_here(self.attribute)
2563 if entry and entry.is_cmethod:
2564 # Create a temporary entry describing the C method
2565 # as an ordinary function.
2566 ubcm_entry = Symtab.Entry(entry.name,
2567 "%s->%s" % (type.vtabptr_cname, entry.cname),
2568 entry.type)
2569 ubcm_entry.is_cfunction = 1
2570 ubcm_entry.func_cname = entry.func_cname
2571 ubcm_entry.is_unbound_cmethod = 1
2572 self.mutate_into_name_node(env, ubcm_entry, None)
2573 return 1
2574 return 0
2576 def analyse_as_type(self, env):
2577 module_scope = self.obj.analyse_as_module(env)
2578 if module_scope:
2579 return module_scope.lookup_type(self.attribute)
2580 return None
2582 def analyse_as_extension_type(self, env):
2583 # Try to interpret this as a reference to an extension type
2584 # in a cimported module. Returns the extension type, or None.
2585 module_scope = self.obj.analyse_as_module(env)
2586 if module_scope:
2587 entry = module_scope.lookup_here(self.attribute)
2588 if entry and entry.is_type and entry.type.is_extension_type:
2589 return entry.type
2590 return None
2592 def analyse_as_module(self, env):
2593 # Try to interpret this as a reference to a cimported module
2594 # in another cimported module. Returns the module scope, or None.
2595 module_scope = self.obj.analyse_as_module(env)
2596 if module_scope:
2597 entry = module_scope.lookup_here(self.attribute)
2598 if entry and entry.as_module:
2599 return entry.as_module
2600 return None
2602 def mutate_into_name_node(self, env, entry, target):
2603 # Mutate this node into a NameNode and complete the
2604 # analyse_types phase.
2605 self.__class__ = NameNode
2606 self.name = self.attribute
2607 self.entry = entry
2608 del self.obj
2609 del self.attribute
2610 if target:
2611 NameNode.analyse_target_types(self, env)
2612 else:
2613 NameNode.analyse_rvalue_entry(self, env)
2615 def analyse_as_ordinary_attribute(self, env, target):
2616 self.obj.analyse_types(env)
2617 self.analyse_attribute(env)
2618 if self.entry and self.entry.is_cmethod and not self.is_called:
2619 # error(self.pos, "C method can only be called")
2620 pass
2621 ## Reference to C array turns into pointer to first element.
2622 #while self.type.is_array:
2623 # self.type = self.type.element_ptr_type()
2624 if self.is_py_attr:
2625 if not target:
2626 self.is_temp = 1
2627 self.result_ctype = py_object_type
2629 def analyse_attribute(self, env):
2630 # Look up attribute and set self.type and self.member.
2631 self.is_py_attr = 0
2632 self.member = self.attribute
2633 if self.obj.type.is_string:
2634 self.obj = self.obj.coerce_to_pyobject(env)
2635 obj_type = self.obj.type
2636 if obj_type.is_ptr or obj_type.is_array:
2637 obj_type = obj_type.base_type
2638 self.op = "->"
2639 elif obj_type.is_extension_type:
2640 self.op = "->"
2641 else:
2642 self.op = "."
2643 if obj_type.has_attributes:
2644 entry = None
2645 if obj_type.attributes_known():
2646 entry = obj_type.scope.lookup_here(self.attribute)
2647 if entry and entry.is_member:
2648 entry = None
2649 else:
2650 error(self.pos,
2651 "Cannot select attribute of incomplete type '%s'"
2652 % obj_type)
2653 self.type = PyrexTypes.error_type
2654 return
2655 self.entry = entry
2656 if entry:
2657 if obj_type.is_extension_type and entry.name == "__weakref__":
2658 error(self.pos, "Illegal use of special attribute __weakref__")
2659 # methods need the normal attribute lookup
2660 # because they do not have struct entries
2661 if entry.is_variable or entry.is_cmethod:
2662 self.type = entry.type
2663 self.member = entry.cname
2664 return
2665 else:
2666 # If it's not a variable or C method, it must be a Python
2667 # method of an extension type, so we treat it like a Python
2668 # attribute.
2669 pass
2670 # If we get here, the base object is not a struct/union/extension
2671 # type, or it is an extension type and the attribute is either not
2672 # declared or is declared as a Python method. Treat it as a Python
2673 # attribute reference.
2674 self.analyse_as_python_attribute(env)
2676 def analyse_as_python_attribute(self, env):
2677 obj_type = self.obj.type
2678 self.member = self.attribute
2679 if obj_type.is_pyobject:
2680 self.type = py_object_type
2681 self.is_py_attr = 1
2682 self.interned_attr_cname = env.intern_identifier(self.attribute)
2683 self.gil_check(env)
2684 else:
2685 if not obj_type.is_error:
2686 error(self.pos,
2687 "Object of type '%s' has no attribute '%s'" %
2688 (obj_type, self.attribute))
2690 gil_message = "Accessing Python attribute"
2692 def is_simple(self):
2693 if self.obj:
2694 return self.result_in_temp() or self.obj.is_simple()
2695 else:
2696 return NameNode.is_simple(self)
2698 def is_lvalue(self):
2699 if self.obj:
2700 return 1
2701 else:
2702 return NameNode.is_lvalue(self)
2704 def is_ephemeral(self):
2705 if self.obj:
2706 return self.obj.is_ephemeral()
2707 else:
2708 return NameNode.is_ephemeral(self)
2710 def calculate_result_code(self):
2711 #print "AttributeNode.calculate_result_code:", self.member ###
2712 #print "...obj node =", self.obj, "code", self.obj.result() ###
2713 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2714 obj = self.obj
2715 obj_code = obj.result_as(obj.type)
2716 #print "...obj_code =", obj_code ###
2717 if self.entry and self.entry.is_cmethod:
2718 if obj.type.is_extension_type:
2719 return "((struct %s *)%s%s%s)->%s" % (
2720 obj.type.vtabstruct_cname, obj_code, self.op,
2721 obj.type.vtabslot_cname, self.member)
2722 else:
2723 return self.member
2724 else:
2725 return "%s%s%s" % (obj_code, self.op, self.member)
2727 def generate_result_code(self, code):
2728 if self.is_py_attr:
2729 code.putln(
2730 '%s = PyObject_GetAttr(%s, %s); %s' % (
2731 self.result(),
2732 self.obj.py_result(),
2733 self.interned_attr_cname,
2734 code.error_goto_if_null(self.result(), self.pos)))
2735 else:
2736 # result_code contains what is needed, but we may need to insert
2737 # a check and raise an exception
2738 if (self.obj.type.is_extension_type
2739 and self.needs_none_check
2740 and code.globalstate.directives['nonecheck']):
2741 self.put_nonecheck(code)
2743 def generate_assignment_code(self, rhs, code):
2744 self.obj.generate_evaluation_code(code)
2745 if self.is_py_attr:
2746 code.put_error_if_neg(self.pos,
2747 'PyObject_SetAttr(%s, %s, %s)' % (
2748 self.obj.py_result(),
2749 self.interned_attr_cname,
2750 rhs.py_result()))
2751 rhs.generate_disposal_code(code)
2752 rhs.free_temps(code)
2753 else:
2754 if (self.obj.type.is_extension_type
2755 and self.needs_none_check
2756 and code.globalstate.directives['nonecheck']):
2757 self.put_nonecheck(code)
2759 select_code = self.result()
2760 if self.type.is_pyobject:
2761 rhs.make_owned_reference(code)
2762 code.put_decref(select_code, self.ctype())
2763 code.putln(
2764 "%s = %s;" % (
2765 select_code,
2766 rhs.result_as(self.ctype())))
2767 #rhs.result()))
2768 rhs.generate_post_assignment_code(code)
2769 rhs.free_temps(code)
2770 self.obj.generate_disposal_code(code)
2771 self.obj.free_temps(code)
2773 def generate_deletion_code(self, code):
2774 self.obj.generate_evaluation_code(code)
2775 if self.is_py_attr:
2776 code.put_error_if_neg(self.pos,
2777 'PyObject_DelAttr(%s, %s)' % (
2778 self.obj.py_result(),
2779 self.interned_attr_cname))
2780 else:
2781 error(self.pos, "Cannot delete C attribute of extension type")
2782 self.obj.generate_disposal_code(code)
2783 self.obj.free_temps(code)
2785 def annotate(self, code):
2786 if self.is_py_attr:
2787 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2788 else:
2789 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2791 def put_nonecheck(self, code):
2792 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2793 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2794 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2795 code.putln(code.error_goto(self.pos))
2796 code.putln("}")
2799 #-------------------------------------------------------------------
2800 #
2801 # Constructor nodes
2802 #
2803 #-------------------------------------------------------------------
2805 class SequenceNode(NewTempExprNode):
2806 # Base class for list and tuple constructor nodes.
2807 # Contains common code for performing sequence unpacking.
2808 #
2809 # args [ExprNode]
2810 # iterator ExprNode
2811 # unpacked_items [ExprNode] or None
2812 # coerced_unpacked_items [ExprNode] or None
2814 subexprs = ['args']
2816 is_sequence_constructor = 1
2817 unpacked_items = None
2819 def compile_time_value_list(self, denv):
2820 return [arg.compile_time_value(denv) for arg in self.args]
2822 def analyse_target_declaration(self, env):
2823 for arg in self.args:
2824 arg.analyse_target_declaration(env)
2826 def analyse_types(self, env, skip_children=False):
2827 for i in range(len(self.args)):
2828 arg = self.args[i]
2829 if not skip_children: arg.analyse_types(env)
2830 self.args[i] = arg.coerce_to_pyobject(env)
2831 self.type = py_object_type
2832 self.gil_check(env)
2833 self.is_temp = 1
2835 def analyse_target_types(self, env):
2836 self.iterator = PyTempNode(self.pos, env)
2837 self.unpacked_items = []
2838 self.coerced_unpacked_items = []
2839 for arg in self.args:
2840 arg.analyse_target_types(env)
2841 unpacked_item = PyTempNode(self.pos, env)
2842 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2843 self.unpacked_items.append(unpacked_item)
2844 self.coerced_unpacked_items.append(coerced_unpacked_item)
2845 self.type = py_object_type
2846 env.use_utility_code(unpacking_utility_code)
2848 def allocate_target_temps(self, env, rhs):
2849 self.iterator.allocate_temps(env)
2850 for arg, node in zip(self.args, self.coerced_unpacked_items):
2851 node.allocate_temps(env)
2852 arg.allocate_target_temps(env, None)
2853 #arg.release_target_temp(env)
2854 #node.release_temp(env)
2855 if rhs:
2856 rhs.release_temp(env)
2857 self.iterator.release_temp(env)
2858 for node in self.coerced_unpacked_items:
2859 node.release_temp(env)
2861 # def release_target_temp(self, env):
2862 # #for arg in self.args:
2863 # # arg.release_target_temp(env)
2864 # #for node in self.coerced_unpacked_items:
2865 # # node.release_temp(env)
2866 # self.iterator.release_temp(env)
2868 def generate_result_code(self, code):
2869 self.generate_operation_code(code)
2871 def generate_assignment_code(self, rhs, code):
2872 # Need to work around the fact that generate_evaluation_code
2873 # allocates the temps in a rather hacky way -- the assignment
2874 # is evaluated twice, within each if-block.
2876 code.putln(
2877 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2878 rhs.py_result(),
2879 rhs.py_result(),
2880 len(self.args)))
2881 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2882 for i in range(len(self.args)):
2883 item = self.unpacked_items[i]
2884 code.put(
2885 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
2886 item.result(),
2887 i))
2888 code.put_incref(item.result(), item.ctype())
2889 value_node = self.coerced_unpacked_items[i]
2890 value_node.generate_evaluation_code(code)
2891 rhs.generate_disposal_code(code)
2893 for i in range(len(self.args)):
2894 self.args[i].generate_assignment_code(
2895 self.coerced_unpacked_items[i], code)
2897 code.putln("} else {")
2899 code.putln(
2900 "%s = PyObject_GetIter(%s); %s" % (
2901 self.iterator.result(),
2902 rhs.py_result(),
2903 code.error_goto_if_null(self.iterator.result(), self.pos)))
2904 rhs.generate_disposal_code(code)
2905 for i in range(len(self.args)):
2906 item = self.unpacked_items[i]
2907 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2908 self.iterator.py_result(), i)
2909 code.putln(
2910 "%s = %s; %s" % (
2911 item.result(),
2912 typecast(item.ctype(), py_object_type, unpack_code),
2913 code.error_goto_if_null(item.result(), self.pos)))
2914 value_node = self.coerced_unpacked_items[i]
2915 value_node.generate_evaluation_code(code)
2916 code.put_error_if_neg(self.pos,
2917 "__Pyx_EndUnpack(%s)" % (
2918 self.iterator.py_result()))
2919 if debug_disposal_code:
2920 print("UnpackNode.generate_assignment_code:")
2921 print("...generating disposal code for %s" % self.iterator)
2922 self.iterator.generate_disposal_code(code)
2923 self.iterator.free_temps(code)
2925 for i in range(len(self.args)):
2926 self.args[i].generate_assignment_code(
2927 self.coerced_unpacked_items[i], code)
2928 code.putln("}")
2929 rhs.free_temps(code)
2931 def annotate(self, code):
2932 for arg in self.args:
2933 arg.annotate(code)
2934 if self.unpacked_items:
2935 for arg in self.unpacked_items:
2936 arg.annotate(code)
2937 for arg in self.coerced_unpacked_items:
2938 arg.annotate(code)
2941 class TupleNode(SequenceNode):
2942 # Tuple constructor.
2944 gil_message = "Constructing Python tuple"
2946 def analyse_types(self, env, skip_children=False):
2947 if len(self.args) == 0:
2948 self.is_temp = 0
2949 self.is_literal = 1
2950 else:
2951 SequenceNode.analyse_types(self, env, skip_children)
2952 self.type = tuple_type
2954 def calculate_result_code(self):
2955 if len(self.args) > 0:
2956 error(self.pos, "Positive length tuples must be constructed.")
2957 else:
2958 return Naming.empty_tuple
2960 def compile_time_value(self, denv):
2961 values = self.compile_time_value_list(denv)
2962 try:
2963 return tuple(values)
2964 except Exception, e:
2965 self.compile_time_value_error(e)
2967 def generate_operation_code(self, code):
2968 if len(self.args) == 0:
2969 # result_code is Naming.empty_tuple
2970 return
2971 code.putln(
2972 "%s = PyTuple_New(%s); %s" % (
2973 self.result(),
2974 len(self.args),
2975 code.error_goto_if_null(self.result(), self.pos)))
2976 for i in range(len(self.args)):
2977 arg = self.args[i]
2978 if not arg.result_in_temp():
2979 code.put_incref(arg.result(), arg.ctype())
2980 code.putln(
2981 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2982 self.result(),
2983 i,
2984 arg.py_result()))
2986 def generate_subexpr_disposal_code(self, code):
2987 # We call generate_post_assignment_code here instead
2988 # of generate_disposal_code, because values were stored
2989 # in the tuple using a reference-stealing operation.
2990 for arg in self.args:
2991 arg.generate_post_assignment_code(code)
2992 # Should NOT call free_temps -- this is invoked by the default
2993 # generate_evaluation_code which will do that.
2996 class ListNode(SequenceNode):
2997 # List constructor.
2999 # obj_conversion_errors [PyrexError] used internally
3000 # orignial_args [ExprNode] used internally
3002 gil_message = "Constructing Python list"
3004 def analyse_expressions(self, env):
3005 ExprNode.analyse_expressions(self, env)
3006 self.coerce_to_pyobject(env)
3008 def analyse_types(self, env):
3009 hold_errors()
3010 self.original_args = list(self.args)
3011 SequenceNode.analyse_types(self, env)
3012 self.type = list_type
3013 self.obj_conversion_errors = held_errors()
3014 release_errors(ignore=True)
3016 def coerce_to(self, dst_type, env):
3017 if dst_type.is_pyobject:
3018 for err in self.obj_conversion_errors:
3019 report_error(err)
3020 self.obj_conversion_errors = []
3021 if not self.type.subtype_of(dst_type):
3022 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3023 elif dst_type.is_ptr:
3024 base_type = dst_type.base_type
3025 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3026 for i in range(len(self.original_args)):
3027 arg = self.args[i]
3028 if isinstance(arg, CoerceToPyTypeNode):
3029 arg = arg.arg
3030 self.args[i] = arg.coerce_to(base_type, env)
3031 elif dst_type.is_struct:
3032 if len(self.args) > len(dst_type.scope.var_entries):
3033 error(self.pos, "Too may members for '%s'" % dst_type)
3034 else:
3035 if len(self.args) < len(dst_type.scope.var_entries):
3036 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3037 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3038 if isinstance(arg, CoerceToPyTypeNode):
3039 arg = arg.arg
3040 self.args[i] = arg.coerce_to(member.type, env)
3041 self.type = dst_type
3042 else:
3043 self.type = error_type
3044 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3045 return self
3047 def release_temp(self, env):
3048 if self.type.is_array:
3049 # To be valid C++, we must allocate the memory on the stack
3050 # manually and be sure not to reuse it for something else.
3051 pass
3052 else:
3053 SequenceNode.release_temp(self, env)
3055 def compile_time_value(self, denv):
3056 return self.compile_time_value_list(denv)
3058 def generate_operation_code(self, code):
3059 if self.type.is_pyobject:
3060 for err in self.obj_conversion_errors:
3061 report_error(err)
3062 code.putln("%s = PyList_New(%s); %s" %
3063 (self.result(),
3064 len(self.args),
3065 code.error_goto_if_null(self.result(), self.pos)))
3066 for i in range(len(self.args)):
3067 arg = self.args[i]
3068 #if not arg.is_temp:
3069 if not arg.result_in_temp():
3070 code.put_incref(arg.result(), arg.ctype())
3071 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3072 (self.result(),
3073 i,
3074 arg.py_result()))
3075 elif self.type.is_array:
3076 for i, arg in enumerate(self.args):
3077 code.putln("%s[%s] = %s;" % (
3078 self.result(),
3079 i,
3080 arg.result()))
3081 elif self.type.is_struct:
3082 for arg, member in zip(self.args, self.type.scope.var_entries):
3083 code.putln("%s.%s = %s;" % (
3084 self.result(),
3085 member.cname,
3086 arg.result()))
3087 else:
3088 raise InternalError("List type never specified")
3090 def generate_subexpr_disposal_code(self, code):
3091 # We call generate_post_assignment_code here instead
3092 # of generate_disposal_code, because values were stored
3093 # in the list using a reference-stealing operation.
3094 for arg in self.args:
3095 arg.generate_post_assignment_code(code)
3096 # Should NOT call free_temps -- this is invoked by the default
3097 # generate_evaluation_code which will do that.
3100 class ListComprehensionNode(SequenceNode):
3102 subexprs = []
3103 is_sequence_constructor = 0 # not unpackable
3105 child_attrs = ["loop", "append"]
3107 def analyse_types(self, env):
3108 self.type = list_type
3109 self.is_temp = 1
3110 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3112 def allocate_temps(self, env, result = None):
3113 if debug_temp_alloc:
3114 print("%s Allocating temps" % self)
3115 self.allocate_temp(env, result)
3116 self.loop.analyse_declarations(env)
3117 self.loop.analyse_expressions(env)
3119 def generate_operation_code(self, code):
3120 code.putln("%s = PyList_New(%s); %s" %
3121 (self.result(),
3122 0,
3123 code.error_goto_if_null(self.result(), self.pos)))
3124 self.loop.generate_execution_code(code)
3126 def annotate(self, code):
3127 self.loop.annotate(code)
3130 class ListComprehensionAppendNode(ExprNode):
3132 # Need to be careful to avoid infinite recursion:
3133 # target must not be in child_attrs/subexprs
3134 subexprs = ['expr']
3136 def analyse_types(self, env):
3137 self.expr.analyse_types(env)
3138 if self.expr.type != py_object_type:
3139 self.expr = self.expr.coerce_to_pyobject(env)
3140 self.type = PyrexTypes.c_int_type
3141 self.is_temp = 1
3143 def generate_result_code(self, code):
3144 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
3145 (self.result(),
3146 self.target.result(),
3147 self.expr.result(),
3148 code.error_goto_if(self.result(), self.pos)))
3151 class DictNode(ExprNode):
3152 # Dictionary constructor.
3153 #
3154 # key_value_pairs [DictItemNode]
3155 #
3156 # obj_conversion_errors [PyrexError] used internally
3158 subexprs = ['key_value_pairs']
3160 def compile_time_value(self, denv):
3161 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3162 for item in self.key_value_pairs]
3163 try:
3164 return dict(pairs)
3165 except Exception, e:
3166 self.compile_time_value_error(e)
3168 def analyse_types(self, env):
3169 hold_errors()
3170 self.type = dict_type
3171 for item in self.key_value_pairs:
3172 item.analyse_types(env)
3173 self.gil_check(env)
3174 self.obj_conversion_errors = held_errors()
3175 release_errors(ignore=True)
3176 self.is_temp = 1
3178 def coerce_to(self, dst_type, env):
3179 if dst_type.is_pyobject:
3180 self.release_errors()
3181 if not self.type.subtype_of(dst_type):
3182 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3183 elif dst_type.is_struct_or_union:
3184 self.type = dst_type
3185 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3186 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3187 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3188 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3189 for item in self.key_value_pairs:
3190 if isinstance(item.key, CoerceToPyTypeNode):
3191 item.key = item.key.arg
3192 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3193 error(item.key.pos, "Invalid struct field identifier")
3194 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3195 else:
3196 member = dst_type.scope.lookup_here(item.key.value)
3197 if not member:
3198 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3199 else:
3200 value = item.value
3201 if isinstance(value, CoerceToPyTypeNode):
3202 value = value.arg
3203 item.value = value.coerce_to(member.type, env)
3204 else:
3205 self.type = error_type
3206 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3207 return self
3209 def release_errors(self):
3210 for err in self.obj_conversion_errors:
3211 report_error(err)
3212 self.obj_conversion_errors = []
3214 gil_message = "Constructing Python dict"
3216 def allocate_temps(self, env, result = None):
3217 # Custom method used here because key-value
3218 # pairs are evaluated and used one at a time.
3219 self.allocate_temp(env, result)
3220 for item in self.key_value_pairs:
3221 item.key.allocate_temps(env)
3222 item.value.allocate_temps(env)
3223 item.key.release_temp(env)
3224 item.value.release_temp(env)
3226 def generate_evaluation_code(self, code):
3227 # Custom method used here because key-value
3228 # pairs are evaluated and used one at a time.
3229 if self.type.is_pyobject:
3230 self.release_errors()
3231 code.putln(
3232 "%s = PyDict_New(); %s" % (
3233 self.result(),
3234 code.error_goto_if_null(self.result(), self.pos)))
3235 for item in self.key_value_pairs:
3236 item.generate_evaluation_code(code)
3237 if self.type.is_pyobject:
3238 code.put_error_if_neg(self.pos,
3239 "PyDict_SetItem(%s, %s, %s)" % (
3240 self.result(),
3241 item.key.py_result(),
3242 item.value.py_result()))
3243 else:
3244 code.putln("%s.%s = %s;" % (
3245 self.result(),
3246 item.key.value,
3247 item.value.result()))
3248 item.generate_disposal_code(code)
3249 item.free_temps(code)
3251 def annotate(self, code):
3252 for item in self.key_value_pairs:
3253 item.annotate(code)
3255 class DictItemNode(ExprNode):
3256 # Represents a single item in a DictNode
3257 #
3258 # key ExprNode
3259 # value ExprNode
3260 subexprs = ['key', 'value']
3262 def analyse_types(self, env):
3263 self.key.analyse_types(env)
3264 self.value.analyse_types(env)
3265 self.key = self.key.coerce_to_pyobject(env)
3266 self.value = self.value.coerce_to_pyobject(env)
3268 def generate_evaluation_code(self, code):
3269 self.key.generate_evaluation_code(code)
3270 self.value.generate_evaluation_code(code)
3272 def generate_disposal_code(self, code):
3273 self.key.generate_disposal_code(code)
3274 self.value.generate_disposal_code(code)
3276 def free_temps(self, code):
3277 self.key.free_temps(code)
3278 self.value.free_temps(code)
3280 def __iter__(self):
3281 return iter([self.key, self.value])
3284 class ClassNode(ExprNode):
3285 # Helper class used in the implementation of Python
3286 # class definitions. Constructs a class object given
3287 # a name, tuple of bases and class dictionary.
3288 #
3289 # name EncodedString Name of the class
3290 # cname string Class name as a Python string
3291 # bases ExprNode Base class tuple
3292 # dict ExprNode Class dict (not owned by this node)
3293 # doc ExprNode or None Doc string
3294 # module_name string Name of defining module
3296 subexprs = ['bases', 'doc']
3298 def analyse_types(self, env):
3299 self.cname = env.intern_identifier(self.name)
3300 self.bases.analyse_types(env)
3301 if self.doc:
3302 self.doc.analyse_types(env)
3303 self.doc = self.doc.coerce_to_pyobject(env)
3304 self.module_name = env.global_scope().qualified_name
3305 self.type = py_object_type
3306 self.gil_check(env)
3307 self.is_temp = 1
3308 env.use_utility_code(create_class_utility_code);
3310 gil_message = "Constructing Python class"
3312 def generate_result_code(self, code):
3313 if self.doc:
3314 code.put_error_if_neg(self.pos,
3315 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3316 self.dict.py_result(),
3317 self.doc.py_result()))
3318 code.putln(
3319 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3320 self.result(),
3321 self.bases.py_result(),
3322 self.dict.py_result(),
3323 self.cname,
3324 self.module_name,
3325 code.error_goto_if_null(self.result(), self.pos)))
3328 class UnboundMethodNode(ExprNode):
3329 # Helper class used in the implementation of Python
3330 # class definitions. Constructs an unbound method
3331 # object from a class and a function.
3332 #
3333 # class_cname string C var holding the class object
3334 # function ExprNode Function object
3336 subexprs = ['function']
3338 def analyse_types(self, env):
3339 self.function.analyse_types(env)
3340 self.type = py_object_type
3341 self.gil_check(env)
3342 self.is_temp = 1
3344 gil_message = "Constructing an unbound method"
3346 def generate_result_code(self, code):
3347 code.putln(
3348 "%s = PyMethod_New(%s, 0, %s); %s" % (
3349 self.result(),
3350 self.function.py_result(),
3351 self.class_cname,
3352 code.error_goto_if_null(self.result(), self.pos)))
3355 class PyCFunctionNode(AtomicNewTempExprNode):
3356 # Helper class used in the implementation of Python
3357 # class definitions. Constructs a PyCFunction object
3358 # from a PyMethodDef struct.
3359 #
3360 # pymethdef_cname string PyMethodDef structure
3362 def analyse_types(self, env):
3363 self.type = py_object_type
3364 self.gil_check(env)
3365 self.is_temp = 1
3367 gil_message = "Constructing Python function"
3369 def generate_result_code(self, code):
3370 code.putln(
3371 "%s = PyCFunction_New(&%s, 0); %s" % (
3372 self.result(),
3373 self.pymethdef_cname,
3374 code.error_goto_if_null(self.result(), self.pos)))
3376 #-------------------------------------------------------------------
3377 #
3378 # Unary operator nodes
3379 #
3380 #-------------------------------------------------------------------
3382 compile_time_unary_operators = {
3383 'not': operator.not_,
3384 '~': operator.inv,
3385 '-': operator.neg,
3386 '+': operator.pos,
3387 }
3389 class UnopNode(ExprNode):
3390 # operator string
3391 # operand ExprNode
3392 #
3393 # Processing during analyse_expressions phase:
3394 #
3395 # analyse_c_operation
3396 # Called when the operand is not a pyobject.
3397 # - Check operand type and coerce if needed.
3398 # - Determine result type and result code fragment.
3399 # - Allocate temporary for result if needed.
3401 subexprs = ['operand']
3403 def compile_time_value(self, denv):
3404 func = compile_time_unary_operators.get(self.operator)
3405 if not func:
3406 error(self.pos,
3407 "Unary '%s' not supported in compile-time expression"
3408 % self.operator)
3409 operand = self.operand.compile_time_value(denv)
3410 try:
3411 return func(operand)
3412 except Exception, e:
3413 self.compile_time_value_error(e)
3415 def analyse_types(self, env):
3416 self.operand.analyse_types(env)
3417 if self.is_py_operation():
3418 self.coerce_operand_to_pyobject(env)
3419 self.type = py_object_type
3420 self.gil_check(env)
3421 self.is_temp = 1
3422 else:
3423 self.analyse_c_operation(env)
3425 def check_const(self):
3426 self.operand.check_const()
3428 def is_py_operation(self):
3429 return self.operand.type.is_pyobject
3431 def coerce_operand_to_pyobject(self, env):
3432 self.operand = self.operand.coerce_to_pyobject(env)
3434 def generate_result_code(self, code):
3435 if self.operand.type.is_pyobject:
3436 self.generate_py_operation_code(code)
3437 else:
3438 if self.is_temp:
3439 self.generate_c_operation_code(code)
3441 def generate_py_operation_code(self, code):
3442 function = self.py_operation_function()
3443 code.putln(
3444 "%s = %s(%s); %s" % (
3445 self.result(),
3446 function,
3447 self.operand.py_result(),
3448 code.error_goto_if_null(self.result(), self.pos)))
3450 def type_error(self):
3451 if not self.operand.type.is_error:
3452 error(self.pos, "Invalid operand type for '%s' (%s)" %
3453 (self.operator, self.operand.type))
3454 self.type = PyrexTypes.error_type
3457 class NotNode(ExprNode):
3458 # 'not' operator
3459 #
3460 # operand ExprNode
3462 def compile_time_value(self, denv):
3463 operand = self.operand.compile_time_value(denv)
3464 try:
3465 return not operand
3466 except Exception, e:
3467 self.compile_time_value_error(e)
3469 subexprs = ['operand']
3471 def analyse_types(self, env):
3472 self.operand.analyse_types(env)
3473 self.operand = self.operand.coerce_to_boolean(env)
3474 self.type = PyrexTypes.c_bint_type
3476 def calculate_result_code(self):
3477 return "(!%s)" % self.operand.result()
3479 def generate_result_code(self, code):
3480 pass
3483 class UnaryPlusNode(UnopNode):
3484 # unary '+' operator
3486 operator = '+'
3488 def analyse_c_operation(self, env):
3489 self.type = self.operand.type
3491 def py_operation_function(self):
3492 return "PyNumber_Positive"
3494 def calculate_result_code(self):
3495 return self.operand.result()
3498 class UnaryMinusNode(UnopNode):
3499 # unary '-' operator
3501 operator = '-'
3503 def analyse_c_operation(self, env):
3504 if self.operand.type.is_numeric:
3505 self.type = self.operand.type
3506 else:
3507 self.type_error()
3509 def py_operation_function(self):
3510 return "PyNumber_Negative"
3512 def calculate_result_code(self):
3513 return "(-%s)" % self.operand.result()
3516 class TildeNode(UnopNode):
3517 # unary '~' operator
3519 def analyse_c_operation(self, env):
3520 if self.operand.type.is_int:
3521 self.type = self.operand.type
3522 else:
3523 self.type_error()
3525 def py_operation_function(self):
3526 return "PyNumber_Invert"
3528 def calculate_result_code(self):
3529 return "(~%s)" % self.operand.result()
3532 class AmpersandNode(ExprNode):
3533 # The C address-of operator.
3534 #
3535 # operand ExprNode
3537 subexprs = ['operand']
3539 def analyse_types(self, env):
3540 self.operand.analyse_types(env)
3541 argtype = self.operand.type
3542 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3543 self.error("Taking address of non-lvalue")
3544 return
3545 if argtype.is_pyobject:
3546 self.error("Cannot take address of Python variable")
3547 return
3548 self.type = PyrexTypes.c_ptr_type(argtype)
3550 def check_const(self):
3551 self.operand.check_const_addr()
3553 def error(self, mess):
3554 error(self.pos, mess)
3555 self.type = PyrexTypes.error_type
3556 self.result_code = "<error>"
3558 def calculate_result_code(self):
3559 return "(&%s)" % self.operand.result()
3561 def generate_result_code(self, code):
3562 pass
3565 unop_node_classes = {
3566 "+": UnaryPlusNode,
3567 "-": UnaryMinusNode,
3568 "~": TildeNode,
3569 }
3571 def unop_node(pos, operator, operand):
3572 # Construct unnop node of appropriate class for
3573 # given operator.
3574 if isinstance(operand, IntNode) and operator == '-':
3575 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3576 elif isinstance(operand, UnopNode) and operand.operator == operator:
3577 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3578 return unop_node_classes[operator](pos,
3579 operator = operator,
3580 operand = operand)
3583 class TypecastNode(ExprNode):
3584 # C type cast
3585 #
3586 # operand ExprNode
3587 # base_type CBaseTypeNode
3588 # declarator CDeclaratorNode
3589 #
3590 # If used from a transform, one can if wanted specify the attribute
3591 # "type" directly and leave base_type and declarator to None
3593 subexprs = ['operand']
3594 base_type = declarator = type = None
3596 def analyse_types(self, env):
3597 if self.type is None:
3598 base_type = self.base_type.analyse(env)
3599 _, self.type = self.declarator.analyse(base_type, env)
3600 if self.type.is_cfunction:
3601 error(self.pos,
3602 "Cannot cast to a function type")
3603 self.type = PyrexTypes.error_type
3604 self.operand.analyse_types(env)
3605 to_py = self.type.is_pyobject
3606 from_py = self.operand.type.is_pyobject
3607 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3608 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3609 if to_py and not from_py:
3610 if (self.operand.type.to_py_function and
3611 self.operand.type.create_convert_utility_code(env)):
3612 self.result_ctype = py_object_type
3613 self.operand = self.operand.coerce_to_pyobject(env)
3614 else:
3615 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3616 self.operand = self.operand.coerce_to_simple(env)
3617 elif from_py and not to_py:
3618 if self.type.from_py_function:
3619 self.operand = self.operand.coerce_to(self.type, env)
3620 else:
3621 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3622 elif from_py and to_py:
3623 if self.typecheck and self.type.is_extension_type:
3624 self.operand = PyTypeTestNode(self.operand, self.type, env)
3626 def check_const(self):
3627 self.operand.check_const()
3629 def calculate_result_code(self):
3630 opnd = self.operand
3631 return self.type.cast_code(opnd.result())
3633 def result_as(self, type):
3634 if self.type.is_pyobject and not self.is_temp:
3635 # Optimise away some unnecessary casting
3636 return self.operand.result_as(type)
3637 else:
3638 return ExprNode.result_as(self, type)
3640 def generate_result_code(self, code):
3641 if self.is_temp:
3642 code.putln(
3643 "%s = (PyObject *)%s;" % (
3644 self.result(),
3645 self.operand.result()))
3646 code.put_incref(self.result(), self.ctype())
3649 class SizeofNode(ExprNode):
3650 # Abstract base class for sizeof(x) expression nodes.
3652 type = PyrexTypes.c_int_type
3654 def check_const(self):
3655 pass
3657 def generate_result_code(self, code):
3658 pass
3661 class SizeofTypeNode(SizeofNode):
3662 # C sizeof function applied to a type
3663 #
3664 # base_type CBaseTypeNode
3665 # declarator CDeclaratorNode
3667 subexprs = []
3668 arg_type = None
3670 def analyse_types(self, env):
3671 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3672 # this could be better handled by more uniformly treating types as runtime-available objects
3673 if 0 and self.base_type.module_path:
3674 path = self.base_type.module_path
3675 obj = env.lookup(path[0])
3676 if obj.as_module is None:
3677 operand = NameNode(pos=self.pos, name=path[0])
3678 for attr in path[1:]:
3679 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3680 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3681 self.operand = operand
3682 self.__class__ = SizeofVarNode
3683 self.analyse_types(env)
3684 return
3685 if self.arg_type is None:
3686 base_type = self.base_type.analyse(env)
3687 _, arg_type = self.declarator.analyse(base_type, env)
3688 self.arg_type = arg_type
3689 self.check_type()
3691 def check_type(self):
3692 arg_type = self.arg_type
3693 if arg_type.is_pyobject and not arg_type.is_extension_type:
3694 error(self.pos, "Cannot take sizeof Python object")
3695 elif arg_type.is_void:
3696 error(self.pos, "Cannot take sizeof void")
3697 elif not arg_type.is_complete():
3698 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3700 def calculate_result_code(self):
3701 if self.arg_type.is_extension_type:
3702 # the size of the pointer is boring
3703 # we want the size of the actual struct
3704 arg_code = self.arg_type.declaration_code("", deref=1)
3705 else:
3706 arg_code = self.arg_type.declaration_code("")
3707 return "(sizeof(%s))" % arg_code
3710 class SizeofVarNode(SizeofNode):
3711 # C sizeof function applied to a variable
3712 #
3713 # operand ExprNode
3715 subexprs = ['operand']
3717 def analyse_types(self, env):
3718 # We may actually be looking at a type rather than a variable...
3719 # If we are, traditional analysis would fail...
3720 operand_as_type = self.operand.analyse_as_type(env)
3721 if operand_as_type:
3722 self.arg_type = operand_as_type
3723 self.__class__ = SizeofTypeNode
3724 self.check_type()
3725 else:
3726 self.operand.analyse_types(env)
3728 def calculate_result_code(self):
3729 return "(sizeof(%s))" % self.operand.result()
3731 def generate_result_code(self, code):
3732 pass
3735 #-------------------------------------------------------------------
3736 #
3737 # Binary operator nodes
3738 #
3739 #-------------------------------------------------------------------
3741 def _not_in(x, seq):
3742 return x not in seq
3744 compile_time_binary_operators = {
3745 '<': operator.lt,
3746 '<=': operator.le,
3747 '==': operator.eq,
3748 '!=': operator.ne,
3749 '>=': operator.ge,
3750 '>': operator.gt,
3751 'is': operator.is_,
3752 'is_not': operator.is_not,
3753 '+': operator.add,
3754 '&': operator.and_,
3755 '/': operator.div,
3756 '//': operator.floordiv,
3757 '<<': operator.lshift,
3758 '%': operator.mod,
3759 '*': operator.mul,
3760 '|': operator.or_,
3761 '**': operator.pow,
3762 '>>': operator.rshift,
3763 '-': operator.sub,
3764 #'/': operator.truediv,
3765 '^': operator.xor,
3766 'in': operator.contains,
3767 'not_in': _not_in,
3768 }
3770 def get_compile_time_binop(node):
3771 func = compile_time_binary_operators.get(node.operator)
3772 if not func:
3773 error(node.pos,
3774 "Binary '%s' not supported in compile-time expression"
3775 % node.operator)
3776 return func
3778 class BinopNode(NewTempExprNode):
3779 # operator string
3780 # operand1 ExprNode
3781 # operand2 ExprNode
3782 #
3783 # Processing during analyse_expressions phase:
3784 #
3785 # analyse_c_operation
3786 # Called when neither operand is a pyobject.
3787 # - Check operand types and coerce if needed.
3788 # - Determine result type and result code fragment.
3789 # - Allocate temporary for result if needed.
3791 subexprs = ['operand1', 'operand2']
3793 def compile_time_value(self, denv):
3794 func = get_compile_time_binop(self)
3795 operand1 = self.operand1.compile_time_value(denv)
3796 operand2 = self.operand2.compile_time_value(denv)
3797 try:
3798 return func(operand1, operand2)
3799 except Exception, e:
3800 self.compile_time_value_error(e)
3802 def analyse_types(self, env):
3803 self.operand1.analyse_types(env)
3804 self.operand2.analyse_types(env)
3805 if self.is_py_operation():
3806 self.coerce_operands_to_pyobjects(env)
3807 self.type = py_object_type
3808 self.gil_check(env)
3809 self.is_temp = 1
3810 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3811 self.operand1 = self.operand1.coerce_to_temp(env)
3812 else:
3813 self.analyse_c_operation(env)
3815 def is_py_operation(self):
3816 return (self.operand1.type.is_pyobject
3817 or self.operand2.type.is_pyobject)
3819 def coerce_operands_to_pyobjects(self, env):
3820 self.operand1 = self.operand1.coerce_to_pyobject(env)
3821 self.operand2 = self.operand2.coerce_to_pyobject(env)
3823 def check_const(self):
3824 self.operand1.check_const()
3825 self.operand2.check_const()
3827 def generate_result_code(self, code):
3828 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3829 if self.operand1.type.is_pyobject:
3830 function = self.py_operation_function()
3831 if function == "PyNumber_Power":
3832 extra_args = ", Py_None"
3833 else:
3834 extra_args = ""
3835 code.putln(
3836 "%s = %s(%s, %s%s); %s" % (
3837 self.result(),
3838 function,
3839 self.operand1.py_result(),
3840 self.operand2.py_result(),
3841 extra_args,
3842 code.error_goto_if_null(self.result(), self.pos)))
3843 else:
3844 if self.is_temp:
3845 self.generate_c_operation_code(code)
3847 def type_error(self):
3848 if not (self.operand1.type.is_error
3849 or self.operand2.type.is_error):
3850 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3851 (self.operator, self.operand1.type,
3852 self.operand2.type))
3853 self.type = PyrexTypes.error_type
3856 class NumBinopNode(BinopNode):
3857 # Binary operation taking numeric arguments.
3859 def analyse_c_operation(self, env):
3860 type1 = self.operand1.type
3861 type2 = self.operand2.type
3862 if self.operator == "**" and type1.is_int and type2.is_int:
3863 error(self.pos, "** with two C int types is ambiguous")
3864 self.type = error_type
3865 return
3866 self.type = self.compute_c_result_type(type1, type2)
3867 if not self.type:
3868 self.type_error()
3870 def compute_c_result_type(self, type1, type2):
3871 if self.c_types_okay(type1, type2):
3872 return PyrexTypes.widest_numeric_type(type1, type2)
3873 else:
3874 return None
3876 def c_types_okay(self, type1, type2):
3877 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3878 return (type1.is_numeric or type1.is_enum) \
3879 and (type2.is_numeric or type2.is_enum)
3881 def calculate_result_code(self):
3882 return "(%s %s %s)" % (
3883 self.operand1.result(),
3884 self.operator,
3885 self.operand2.result())
3887 def py_operation_function(self):
3888 return self.py_functions[self.operator]
3890 py_functions = {
3891 "|": "PyNumber_Or",
3892 "^": "PyNumber_Xor",
3893 "&": "PyNumber_And",
3894 "<<": "PyNumber_Lshift",
3895 ">>": "PyNumber_Rshift",
3896 "+": "PyNumber_Add",
3897 "-": "PyNumber_Subtract",
3898 "*": "PyNumber_Multiply",
3899 "/": "__Pyx_PyNumber_Divide",
3900 "//": "PyNumber_FloorDivide",
3901 "%": "PyNumber_Remainder",
3902 "**": "PyNumber_Power"
3903 }
3906 class IntBinopNode(NumBinopNode):
3907 # Binary operation taking integer arguments.
3909 def c_types_okay(self, type1, type2):
3910 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3911 return (type1.is_int or type1.is_enum) \
3912 and (type2.is_int or type2.is_enum)
3915 class AddNode(NumBinopNode):
3916 # '+' operator.
3918 def is_py_operation(self):
3919 if self.operand1.type.is_string \
3920 and self.operand2.type.is_string:
3921 return 1
3922 else:
3923 return NumBinopNode.is_py_operation(self)
3925 def compute_c_result_type(self, type1, type2):
3926 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3927 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3928 return type1
3929 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3930 return type2
3931 else:
3932 return NumBinopNode.compute_c_result_type(
3933 self, type1, type2)
3936 class SubNode(NumBinopNode):
3937 # '-' operator.
3939 def compute_c_result_type(self, type1, type2):
3940 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3941 return type1
3942 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3943 return PyrexTypes.c_int_type
3944 else:
3945 return NumBinopNode.compute_c_result_type(
3946 self, type1, type2)
3949 class MulNode(NumBinopNode):
3950 # '*' operator.
3952 def is_py_operation(self):
3953 type1 = self.operand1.type
3954 type2 = self.operand2.type
3955 if (type1.is_string and type2.is_int) \
3956 or (type2.is_string and type1.is_int):
3957 return 1
3958 else:
3959 return NumBinopNode.is_py_operation(self)
3962 class FloorDivNode(NumBinopNode):
3963 # '//' operator.
3965 def calculate_result_code(self):
3966 return "(%s %s %s)" % (
3967 self.operand1.result(),
3968 "/", # c division is by default floor-div
3969 self.operand2.result())
3972 class ModNode(NumBinopNode):
3973 # '%' operator.
3975 def is_py_operation(self):
3976 return (self.operand1.type.is_string
3977 or self.operand2.type.is_string
3978 or NumBinopNode.is_py_operation(self))
3980 def calculate_result_code(self):
3981 if self.operand1.type.is_float or self.operand2.type.is_float:
3982 return "fmod(%s, %s)" % (
3983 self.operand1.result(),
3984 self.operand2.result())
3985 else:
3986 return "(%s %% %s)" % (
3987 self.operand1.result(),
3988 self.operand2.result())
3990 class PowNode(NumBinopNode):
3991 # '**' operator.
3993 def compute_c_result_type(self, type1, type2):
3994 if self.c_types_okay(type1, type2):
3995 return PyrexTypes.c_double_type
3996 else:
3997 return None
3999 def c_types_okay(self, type1, type2):
4000 return (type1.is_float or type2.is_float) and \
4001 NumBinopNode.c_types_okay(self, type1, type2)
4003 def type_error(self):
4004 if not (self.operand1.type.is_error or self.operand2.type.is_error):
4005 if self.operand1.type.is_int and self.operand2.type.is_int:
4006 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
4007 (self.operator, self.operand1.type, self.operand2.type))
4008 else:
4009 NumBinopNode.type_error(self)
4010 self.type = PyrexTypes.error_type
4012 def calculate_result_code(self):
4013 return "pow(%s, %s)" % (
4014 self.operand1.result(), self.operand2.result())
4017 # Note: This class is temporary "shut down" into an ineffective mode temp
4018 # allocation mode.
4019 #
4020 # More sophisticated temp reuse was going on before,
4021 # one could have a look at adding this again after /all/ classes
4022 # are converted to the new temp scheme. (The temp juggling cannot work
4023 # otherwise).
4024 class BoolBinopNode(NewTempExprNode):
4025 # Short-circuiting boolean operation.
4026 #
4027 # operator string
4028 # operand1 ExprNode
4029 # operand2 ExprNode
4031 subexprs = ['operand1', 'operand2']
4033 def compile_time_value(self, denv):
4034 if self.operator == 'and':
4035 return self.operand1.compile_time_value(denv) \
4036 and self.operand2.compile_time_value(denv)
4037 else:
4038 return self.operand1.compile_time_value(denv) \
4039 or self.operand2.compile_time_value(denv)
4041 def coerce_to_boolean(self, env):
4042 self.operand1 = self.operand1.coerce_to_boolean(env)
4043 self.operand2 = self.operand2.coerce_to_boolean(env)
4044 self.type = PyrexTypes.c_bint_type
4045 return self
4047 def analyse_types(self, env):
4048 self.operand1.analyse_types(env)
4049 self.operand2.analyse_types(env)
4050 if self.operand1.type.is_pyobject or \
4051 self.operand2.type.is_pyobject:
4052 self.operand1 = self.operand1.coerce_to_pyobject(env)
4053 self.operand2 = self.operand2.coerce_to_pyobject(env)
4054 self.type = py_object_type
4055 self.gil_check(env)
4056 else:
4057 self.operand1 = self.operand1.coerce_to_boolean(env)
4058 self.operand2 = self.operand2.coerce_to_boolean(env)
4059 self.type = PyrexTypes.c_bint_type
4061 # Below disabled for
4063 # For what we're about to do, it's vital that
4064 # both operands be temp nodes.
4065 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4066 # self.operand2 = self.operand2.coerce_to_temp(env)
4067 self.is_temp = 1
4069 gil_message = "Truth-testing Python object"
4071 ## def allocate_temps(self, env, result_code = None):
4072 ## # We don't need both operands at the same time, and
4073 ## # one of the operands will also be our result. So we
4074 ## # use an allocation strategy here which results in
4075 ## # this node and both its operands sharing the same
4076 ## # result variable. This allows us to avoid some
4077 ## # assignments and increfs/decrefs that would otherwise
4078 ## # be necessary.
4079 ## self.allocate_temp(env, result_code)
4080 ## self.operand1.allocate_temps(env, self.result())
4081 ## self.operand2.allocate_temps(env, self.result())
4082 ## # We haven't called release_temp on either operand,
4083 ## # because although they are temp nodes, they don't own
4084 ## # their result variable. And because they are temp
4085 ## # nodes, any temps in their subnodes will have been
4086 ## # released before their allocate_temps returned.
4087 ## # Therefore, they contain no temp vars that need to
4088 ## # be released.
4090 def check_const(self):
4091 self.operand1.check_const()
4092 self.operand2.check_const()
4094 def calculate_result_code(self):
4095 return "(%s %s %s)" % (
4096 self.operand1.result(),
4097 self.py_to_c_op[self.operator],
4098 self.operand2.result())
4100 py_to_c_op = {'and': "&&", 'or': "||"}
4102 def generate_evaluation_code(self, code):
4103 code.mark_pos(self.pos)
4104 self.operand1.generate_evaluation_code(code)
4105 test_result, uses_temp = self.generate_operand1_test(code)
4106 if self.operator == 'and':
4107 sense = ""
4108 else:
4109 sense = "!"
4110 code.putln(
4111 "if (%s%s) {" % (
4112 sense,
4113 test_result))
4114 if uses_temp:
4115 code.funcstate.release_temp(test_result)
4116 self.operand1.generate_disposal_code(code)
4117 self.operand2.generate_evaluation_code(code)
4118 self.allocate_temp_result(code)
4119 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4120 self.operand2.generate_post_assignment_code(code)
4121 self.operand2.free_temps(code)
4122 code.putln("} else {")
4123 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4124 self.operand1.generate_post_assignment_code(code)
4125 self.operand1.free_temps(code)
4126 code.putln("}")
4128 def generate_operand1_test(self, code):
4129 # Generate code to test the truth of the first operand.
4130 if self.type.is_pyobject:
4131 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4132 manage_ref=False)
4133 code.putln(
4134 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4135 test_result,
4136 self.operand1.py_result(),
4137 code.error_goto_if_neg(test_result, self.pos)))
4138 else:
4139 test_result = self.operand1.result()
4140 return (test_result, self.type.is_pyobject)
4143 class CondExprNode(ExprNode):
4144 # Short-circuiting conditional expression.
4145 #
4146 # test ExprNode
4147 # true_val ExprNode
4148 # false_val ExprNode
4150 true_val = None
4151 false_val = None
4153 subexprs = ['test', 'true_val', 'false_val']
4155 def analyse_types(self, env):
4156 self.test.analyse_types(env)
4157 self.test = self.test.coerce_to_boolean(env)
4158 self.true_val.analyse_types(env)
4159 self.false_val.analyse_types(env)
4160 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4161 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4162 self.true_val = self.true_val.coerce_to(self.type, env)
4163 self.false_val = self.false_val.coerce_to(self.type, env)
4164 # must be tmp variables so they can share a result
4165 self.true_val = self.true_val.coerce_to_temp(env)
4166 self.false_val = self.false_val.coerce_to_temp(env)
4167 self.is_temp = 1
4168 if self.type == PyrexTypes.error_type:
4169 self.type_error()
4171 def allocate_temps(self, env, result_code = None):
4172 # We only ever evaluate one side, and this is
4173 # after evaluating the truth value, so we may
4174 # use an allocation strategy here which results in
4175 # this node and both its operands sharing the same
4176 # result variable. This allows us to avoid some
4177 # assignments and increfs/decrefs that would otherwise
4178 # be necessary.
4179 self.allocate_temp(env, result_code)
4180 self.test.allocate_temps(env, result_code)
4181 self.true_val.allocate_temps(env, self.result())
4182 self.false_val.allocate_temps(env, self.result())
4183 # We haven't called release_temp on either value,
4184 # because although they are temp nodes, they don't own
4185 # their result variable. And because they are temp
4186 # nodes, any temps in their subnodes will have been
4187 # released before their allocate_temps returned.
4188 # Therefore, they contain no temp vars that need to
4189 # be released.
4191 def compute_result_type(self, type1, type2):
4192 if type1 == type2:
4193 return type1
4194 elif type1.is_numeric and type2.is_numeric:
4195 return PyrexTypes.widest_numeric_type(type1, type2)
4196 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4197 return type2
4198 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4199 return type1
4200 elif type1.is_pyobject or type2.is_pyobject:
4201 return py_object_type
4202 elif type1.assignable_from(type2):
4203 return type1
4204 elif type2.assignable_from(type1):
4205 return type2
4206 else:
4207 return PyrexTypes.error_type
4209 def type_error(self):
4210 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4211 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4212 (self.true_val.type, self.false_val.type))
4213 self.type = PyrexTypes.error_type
4215 def check_const(self):
4216 self.test.check_const()
4217 self.true_val.check_const()
4218 self.false_val.check_const()
4220 def generate_evaluation_code(self, code):
4221 self.test.generate_evaluation_code(code)
4222 code.putln("if (%s) {" % self.test.result() )
4223 self.true_val.generate_evaluation_code(code)
4224 code.putln("} else {")
4225 self.false_val.generate_evaluation_code(code)
4226 code.putln("}")
4227 self.test.generate_disposal_code(code)
4228 self.test.free_temps(code)
4230 richcmp_constants = {
4231 "<" : "Py_LT",
4232 "<=": "Py_LE",
4233 "==": "Py_EQ",
4234 "!=": "Py_NE",
4235 "<>": "Py_NE",
4236 ">" : "Py_GT",
4237 ">=": "Py_GE",
4238 }
4240 class CmpNode:
4241 # Mixin class containing code common to PrimaryCmpNodes
4242 # and CascadedCmpNodes.
4244 def cascaded_compile_time_value(self, operand1, denv):
4245 func = get_compile_time_binop(self)
4246 operand2 = self.operand2.compile_time_value(denv)
4247 try:
4248 result = func(operand1, operand2)
4249 except Exception, e:
4250 self.compile_time_value_error(e)
4251 result = None
4252 if result:
4253 cascade = self.cascade
4254 if cascade:
4255 result = result and cascade.compile_time_value(operand2, denv)
4256 return result
4258 def is_python_comparison(self):
4259 return (self.has_python_operands()
4260 or (self.cascade and self.cascade.is_python_comparison())
4261 or self.operator in ('in', 'not_in'))
4263 def is_python_result(self):
4264 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4265 or (self.cascade and self.cascade.is_python_result()))
4267 def check_types(self, env, operand1, op, operand2):
4268 if not self.types_okay(operand1, op, operand2):
4269 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4270 (self.operator, operand1.type, operand2.type))
4272 def types_okay(self, operand1, op, operand2):
4273 type1 = operand1.type
4274 type2 = operand2.type
4275 if type1.is_error or type2.is_error:
4276 return 1
4277 if type1.is_pyobject: # type2 will be, too
4278 return 1
4279 elif type1.is_ptr or type1.is_array:
4280 return type1.is_null_ptr or type2.is_null_ptr \
4281 or ((type2.is_ptr or type2.is_array)
4282 and type1.base_type.same_as(type2.base_type))
4283 elif ((type1.is_numeric and type2.is_numeric
4284 or type1.is_enum and (type1 is type2 or type2.is_int)
4285 or type1.is_int and type2.is_enum)
4286 and op not in ('is', 'is_not')):
4287 return 1
4288 else:
4289 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4291 def generate_operation_code(self, code, result_code,
4292 operand1, op , operand2):
4293 if self.type is PyrexTypes.py_object_type:
4294 coerce_result = "__Pyx_PyBool_FromLong"
4295 else:
4296 coerce_result = ""
4297 if 'not' in op: negation = "!"
4298 else: negation = ""
4299 if op == 'in' or op == 'not_in':
4300 code.putln(
4301 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4302 result_code,
4303 coerce_result,
4304 negation,
4305 operand2.py_result(),
4306 operand1.py_result(),
4307 code.error_goto_if_neg(result_code, self.pos)))
4308 elif (operand1.type.is_pyobject
4309 and op not in ('is', 'is_not')):
4310 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4311 result_code,
4312 operand1.py_result(),
4313 operand2.py_result(),
4314 richcmp_constants[op],
4315 code.error_goto_if_null(result_code, self.pos)))
4316 else:
4317 type1 = operand1.type
4318 type2 = operand2.type
4319 if (type1.is_extension_type or type2.is_extension_type) \
4320 and not type1.same_as(type2):
4321 common_type = py_object_type
4322 elif type1.is_numeric:
4323 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4324 else:
4325 common_type = type1
4326 code1 = operand1.result_as(common_type)
4327 code2 = operand2.result_as(common_type)
4328 code.putln("%s = %s(%s %s %s);" % (
4329 result_code,
4330 coerce_result,
4331 code1,
4332 self.c_operator(op),
4333 code2))
4335 def c_operator(self, op):
4336 if op == 'is':
4337 return "=="
4338 elif op == 'is_not':
4339 return "!="
4340 else:
4341 return op
4344 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4345 # Non-cascaded comparison or first comparison of
4346 # a cascaded sequence.
4347 #
4348 # operator string
4349 # operand1 ExprNode
4350 # operand2 ExprNode
4351 # cascade CascadedCmpNode
4353 # We don't use the subexprs mechanism, because
4354 # things here are too complicated for it to handle.
4355 # Instead, we override all the framework methods
4356 # which use it.
4358 child_attrs = ['operand1', 'operand2', 'cascade']
4360 cascade = None
4362 def compile_time_value(self, denv):
4363 operand1 = self.operand1.compile_time_value(denv)
4364 return self.cascaded_compile_time_value(operand1, denv)
4366 def analyse_types(self, env):
4367 self.operand1.analyse_types(env)
4368 self.operand2.analyse_types(env)
4369 if self.cascade:
4370 self.cascade.analyse_types(env, self.operand2)
4371 self.is_pycmp = self.is_python_comparison()
4372 if self.is_pycmp:
4373 self.coerce_operands_to_pyobjects(env)
4374 if self.has_int_operands():
4375 self.coerce_chars_to_ints(env)
4376 if self.cascade:
4377 self.operand2 = self.operand2.coerce_to_simple(env)
4378 self.cascade.coerce_cascaded_operands_to_temp(env)
4379 self.check_operand_types(env)
4380 if self.is_python_result():
4381 self.type = PyrexTypes.py_object_type
4382 else:
4383 self.type = PyrexTypes.c_bint_type
4384 cdr = self.cascade
4385 while cdr:
4386 cdr.type = self.type
4387 cdr = cdr.cascade
4388 if self.is_pycmp or self.cascade:
4389 self.is_temp = 1
4391 def check_operand_types(self, env):
4392 self.check_types(env,
4393 self.operand1, self.operator, self.operand2)
4394 if self.cascade:
4395 self.cascade.check_operand_types(env, self.operand2)
4397 def has_python_operands(self):
4398 return (self.operand1.type.is_pyobject
4399 or self.operand2.type.is_pyobject)
4401 def coerce_operands_to_pyobjects(self, env):
4402 self.operand1 = self.operand1.coerce_to_pyobject(env)
4403 self.operand2 = self.operand2.coerce_to_pyobject(env)
4404 if self.cascade:
4405 self.cascade.coerce_operands_to_pyobjects(env)
4407 def has_int_operands(self):
4408 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4409 or (self.cascade and self.cascade.has_int_operands())
4411 def coerce_chars_to_ints(self, env):
4412 # coerce literal single-char strings to c chars
4413 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4414 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4415 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4416 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4417 if self.cascade:
4418 self.cascade.coerce_chars_to_ints(env)
4420 def allocate_subexpr_temps(self, env):
4421 self.operand1.allocate_temps(env)
4422 self.operand2.allocate_temps(env)
4423 if self.cascade:
4424 self.cascade.allocate_subexpr_temps(env)
4426 def release_subexpr_temps(self, env):
4427 self.operand1.release_temp(env)
4428 self.operand2.release_temp(env)
4429 if self.cascade:
4430 self.cascade.release_subexpr_temps(env)
4432 def check_const(self):
4433 self.operand1.check_const()
4434 self.operand2.check_const()
4435 if self.cascade:
4436 self.not_const()
4438 def calculate_result_code(self):
4439 return "(%s %s %s)" % (
4440 self.operand1.result(),
4441 self.c_operator(self.operator),
4442 self.operand2.result())
4444 def generate_evaluation_code(self, code):
4445 self.operand1.generate_evaluation_code(code)
4446 self.operand2.generate_evaluation_code(code)
4447 if self.is_temp:
4448 self.allocate_temp_result(code)
4449 self.generate_operation_code(code, self.result(),
4450 self.operand1, self.operator, self.operand2)
4451 if self.cascade:
4452 self.cascade.generate_evaluation_code(code,
4453 self.result(), self.operand2)
4454 self.operand1.generate_disposal_code(code)
4455 self.operand2.generate_disposal_code(code)
4456 self.operand1.free_temps(code)
4457 self.operand2.free_temps(code)
4459 def generate_subexpr_disposal_code(self, code):
4460 # If this is called, it is a non-cascaded cmp,
4461 # so only need to dispose of the two main operands.
4462 self.operand1.generate_disposal_code(code)
4463 self.operand2.generate_disposal_code(code)
4465 def free_subexpr_temps(self, code):
4466 # If this is called, it is a non-cascaded cmp,
4467 # so only need to dispose of the two main operands.
4468 self.operand1.free_temps(code)
4469 self.operand2.free_temps(code)
4471 def annotate(self, code):
4472 self.operand1.annotate(code)
4473 self.operand2.annotate(code)
4474 if self.cascade:
4475 self.cascade.annotate(code)
4478 class CascadedCmpNode(Node, CmpNode):
4479 # A CascadedCmpNode is not a complete expression node. It
4480 # hangs off the side of another comparison node, shares
4481 # its left operand with that node, and shares its result
4482 # with the PrimaryCmpNode at the head of the chain.
4483 #
4484 # operator string
4485 # operand2 ExprNode
4486 # cascade CascadedCmpNode
4488 child_attrs = ['operand2', 'cascade']
4490 cascade = None
4492 def analyse_types(self, env, operand1):
4493 self.operand2.analyse_types(env)
4494 if self.cascade:
4495 self.cascade.analyse_types(env, self.operand2)
4497 def check_operand_types(self, env, operand1):
4498 self.check_types(env,
4499 operand1, self.operator, self.operand2)
4500 if self.cascade:
4501 self.cascade.check_operand_types(env, self.operand2)
4503 def has_python_operands(self):
4504 return self.operand2.type.is_pyobject
4506 def coerce_operands_to_pyobjects(self, env):
4507 self.operand2 = self.operand2.coerce_to_pyobject(env)
4508 if self.cascade:
4509 self.cascade.coerce_operands_to_pyobjects(env)
4511 def has_int_operands(self):
4512 return self.operand2.type.is_int
4514 def coerce_chars_to_ints(self, env):
4515 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4516 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4518 def coerce_cascaded_operands_to_temp(self, env):
4519 if self.cascade:
4520 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4521 self.operand2 = self.operand2.coerce_to_simple(env)
4522 self.cascade.coerce_cascaded_operands_to_temp(env)
4524 def allocate_subexpr_temps(self, env):
4525 self.operand2.allocate_temps(env)
4526 if self.cascade:
4527 self.cascade.allocate_subexpr_temps(env)
4529 def release_subexpr_temps(self, env):
4530 self.operand2.release_temp(env)
4531 if self.cascade:
4532 self.cascade.release_subexpr_temps(env)
4534 def generate_evaluation_code(self, code, result, operand1):
4535 if self.type.is_pyobject:
4536 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4537 else:
4538 code.putln("if (%s) {" % result)
4539 self.operand2.generate_evaluation_code(code)
4540 self.generate_operation_code(code, result,
4541 operand1, self.operator, self.operand2)
4542 if self.cascade:
4543 self.cascade.generate_evaluation_code(
4544 code, result, self.operand2)
4545 # Cascaded cmp result is always temp
4546 self.operand2.generate_disposal_code(code)
4547 self.operand2.free_temps(code)
4548 code.putln("}")
4550 def annotate(self, code):
4551 self.operand2.annotate(code)
4552 if self.cascade:
4553 self.cascade.annotate(code)
4556 binop_node_classes = {
4557 "or": BoolBinopNode,
4558 "and": BoolBinopNode,
4559 "|": IntBinopNode,
4560 "^": IntBinopNode,
4561 "&": IntBinopNode,
4562 "<<": IntBinopNode,
4563 ">>": IntBinopNode,
4564 "+": AddNode,
4565 "-": SubNode,
4566 "*": MulNode,
4567 "/": NumBinopNode,
4568 "//": FloorDivNode,
4569 "%": ModNode,
4570 "**": PowNode
4571 }
4573 def binop_node(pos, operator, operand1, operand2):
4574 # Construct binop node of appropriate class for
4575 # given operator.
4576 return binop_node_classes[operator](pos,
4577 operator = operator,
4578 operand1 = operand1,
4579 operand2 = operand2)
4581 #-------------------------------------------------------------------
4582 #
4583 # Coercion nodes
4584 #
4585 # Coercion nodes are special in that they are created during
4586 # the analyse_types phase of parse tree processing.
4587 # Their __init__ methods consequently incorporate some aspects
4588 # of that phase.
4589 #
4590 #-------------------------------------------------------------------
4592 class CoercionNode(NewTempExprNode):
4593 # Abstract base class for coercion nodes.
4594 #
4595 # arg ExprNode node being coerced
4597 subexprs = ['arg']
4599 def __init__(self, arg):
4600 self.pos = arg.pos
4601 self.arg = arg
4602 if debug_coercion:
4603 print("%s Coercing %s" % (self, self.arg))
4605 def annotate(self, code):
4606 self.arg.annotate(code)
4607 if self.arg.type != self.type:
4608 file, line, col = self.pos
4609 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4612 class CastNode(CoercionNode):
4613 # Wrap a node in a C type cast.
4615 def __init__(self, arg, new_type):
4616 CoercionNode.__init__(self, arg)
4617 self.type = new_type
4619 def calculate_result_code(self):
4620 return self.arg.result_as(self.type)
4622 def generate_result_code(self, code):
4623 self.arg.generate_result_code(code)
4626 class PyTypeTestNode(CoercionNode):
4627 # This node is used to check that a generic Python
4628 # object is an instance of a particular extension type.
4629 # This node borrows the result of its argument node.
4631 def __init__(self, arg, dst_type, env):
4632 # The arg is know to be a Python object, and
4633 # the dst_type is known to be an extension type.
4634 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4635 CoercionNode.__init__(self, arg)
4636 self.type = dst_type
4637 self.gil_check(env)
4638 self.result_ctype = arg.ctype()
4640 gil_message = "Python type test"
4642 def analyse_types(self, env):
4643 pass
4645 def result_in_temp(self):
4646 return self.arg.result_in_temp()
4648 def is_ephemeral(self):
4649 return self.arg.is_ephemeral()
4651 def calculate_result_code(self):
4652 return self.arg.result()
4654 def generate_result_code(self, code):
4655 if self.type.typeobj_is_available():
4656 if not self.type.is_builtin_type:
4657 code.globalstate.use_utility_code(type_test_utility_code)
4658 code.putln(
4659 "if (!(%s)) %s" % (
4660 self.type.type_test_code(self.arg.py_result()),
4661 code.error_goto(self.pos)))
4662 else:
4663 error(self.pos, "Cannot test type of extern C class "
4664 "without type object name specification")
4666 def generate_post_assignment_code(self, code):
4667 self.arg.generate_post_assignment_code(code)
4669 def free_temps(self, code):
4670 self.arg.free_temps(code)
4673 class CoerceToPyTypeNode(CoercionNode):
4674 # This node is used to convert a C data type
4675 # to a Python object.
4677 def __init__(self, arg, env):
4678 CoercionNode.__init__(self, arg)
4679 self.type = py_object_type
4680 self.gil_check(env)
4681 self.is_temp = 1
4682 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4683 error(arg.pos,
4684 "Cannot convert '%s' to Python object" % arg.type)
4686 gil_message = "Converting to Python object"
4688 def coerce_to_boolean(self, env):
4689 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
4691 def analyse_types(self, env):
4692 # The arg is always already analysed
4693 pass
4695 def generate_result_code(self, code):
4696 function = self.arg.type.to_py_function
4697 code.putln('%s = %s(%s); %s' % (
4698 self.result(),
4699 function,
4700 self.arg.result(),
4701 code.error_goto_if_null(self.result(), self.pos)))
4704 class CoerceFromPyTypeNode(CoercionNode):
4705 # This node is used to convert a Python object
4706 # to a C data type.
4708 def __init__(self, result_type, arg, env):
4709 CoercionNode.__init__(self, arg)
4710 self.type = result_type
4711 self.is_temp = 1
4712 if not result_type.from_py_function:
4713 error(arg.pos,
4714 "Cannot convert Python object to '%s'" % result_type)
4715 if self.type.is_string and self.arg.is_ephemeral():
4716 error(arg.pos,
4717 "Obtaining char * from temporary Python value")
4719 def analyse_types(self, env):
4720 # The arg is always already analysed
4721 pass
4723 def generate_result_code(self, code):
4724 function = self.type.from_py_function
4725 operand = self.arg.py_result()
4726 rhs = "%s(%s)" % (function, operand)
4727 if self.type.is_enum:
4728 rhs = typecast(self.type, c_long_type, rhs)
4729 code.putln('%s = %s; %s' % (
4730 self.result(),
4731 rhs,
4732 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4735 class CoerceToBooleanNode(CoercionNode):
4736 # This node is used when a result needs to be used
4737 # in a boolean context.
4739 def __init__(self, arg, env):
4740 CoercionNode.__init__(self, arg)
4741 self.type = PyrexTypes.c_bint_type
4742 if arg.type.is_pyobject:
4743 if env.nogil:
4744 self.gil_error()
4745 self.is_temp = 1
4747 gil_message = "Truth-testing Python object"
4749 def check_const(self):
4750 if self.is_temp:
4751 self.not_const()
4752 self.arg.check_const()
4754 def calculate_result_code(self):
4755 return "(%s != 0)" % self.arg.result()
4757 def generate_result_code(self, code):
4758 if self.arg.type.is_pyobject:
4759 code.putln(
4760 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4761 self.result(),
4762 self.arg.py_result(),
4763 code.error_goto_if_neg(self.result(), self.pos)))
4766 class CoerceToTempNode(CoercionNode):
4767 # This node is used to force the result of another node
4768 # to be stored in a temporary. It is only used if the
4769 # argument node's result is not already in a temporary.
4771 def __init__(self, arg, env):
4772 CoercionNode.__init__(self, arg)
4773 self.type = self.arg.type
4774 self.is_temp = 1
4775 if self.type.is_pyobject:
4776 self.gil_check(env)
4777 self.result_ctype = py_object_type
4779 gil_message = "Creating temporary Python reference"
4781 def analyse_types(self, env):
4782 # The arg is always already analysed
4783 pass
4785 def coerce_to_boolean(self, env):
4786 self.arg = self.arg.coerce_to_boolean(env)
4787 self.type = self.arg.type
4788 self.result_ctype = self.type
4789 return self
4791 def generate_result_code(self, code):
4792 #self.arg.generate_evaluation_code(code) # Already done
4793 # by generic generate_subexpr_evaluation_code!
4794 code.putln("%s = %s;" % (
4795 self.result(), self.arg.result_as(self.ctype())))
4796 if self.type.is_pyobject:
4797 code.put_incref(self.result(), self.ctype())
4800 class CloneNode(CoercionNode):
4801 # This node is employed when the result of another node needs
4802 # to be used multiple times. The argument node's result must
4803 # be in a temporary. This node "borrows" the result from the
4804 # argument node, and does not generate any evaluation or
4805 # disposal code for it. The original owner of the argument
4806 # node is responsible for doing those things.
4808 subexprs = [] # Arg is not considered a subexpr
4810 def __init__(self, arg):
4811 CoercionNode.__init__(self, arg)
4812 if hasattr(arg, 'type'):
4813 self.type = arg.type
4814 self.result_ctype = arg.result_ctype
4815 if hasattr(arg, 'entry'):
4816 self.entry = arg.entry
4818 def result(self):
4819 return self.arg.result()
4821 def analyse_types(self, env):
4822 self.type = self.arg.type
4823 self.result_ctype = self.arg.result_ctype
4824 self.is_temp = 1
4825 if hasattr(self.arg, 'entry'):
4826 self.entry = self.arg.entry
4828 def generate_evaluation_code(self, code):
4829 pass
4831 def generate_result_code(self, code):
4832 pass
4834 def generate_disposal_code(self, code):
4835 pass
4837 def allocate_temps(self, env):
4838 pass
4840 def release_temp(self, env):
4841 pass
4843 def free_temps(self, code):
4844 pass
4847 class DISABLED_PersistentNode(ExprNode):
4848 # A PersistentNode is like a CloneNode except it handles the temporary
4849 # allocation itself by keeping track of the number of times it has been
4850 # used.
4852 subexprs = ["arg"]
4853 temp_counter = 0
4854 generate_counter = 0
4855 analyse_counter = 0
4856 result_code = None
4858 def __init__(self, arg, uses):
4859 self.pos = arg.pos
4860 self.arg = arg
4861 self.uses = uses
4863 def analyse_types(self, env):
4864 if self.analyse_counter == 0:
4865 self.arg.analyse_types(env)
4866 self.type = self.arg.type
4867 self.result_ctype = self.arg.result_ctype
4868 self.is_temp = 1
4869 self.analyse_counter += 1
4871 def calculate_result_code(self):
4872 return self.result()
4874 def generate_evaluation_code(self, code):
4875 if self.generate_counter == 0:
4876 self.arg.generate_evaluation_code(code)
4877 code.putln("%s = %s;" % (
4878 self.result(), self.arg.result_as(self.ctype())))
4879 if self.type.is_pyobject:
4880 code.put_incref(self.result(), self.ctype())
4881 self.arg.generate_disposal_code(code)
4882 self.generate_counter += 1
4884 def generate_disposal_code(self, code):
4885 if self.generate_counter == self.uses:
4886 if self.type.is_pyobject:
4887 code.put_decref_clear(self.result(), self.ctype())
4889 def allocate_temps(self, env, result=None):
4890 if self.temp_counter == 0:
4891 self.arg.allocate_temps(env)
4892 self.allocate_temp(env, result)
4893 self.arg.release_temp(env)
4894 self.temp_counter += 1
4896 def allocate_temp(self, env, result=None):
4897 if result is None:
4898 self.result_code = env.allocate_temp(self.type)
4899 else:
4900 self.result_code = result
4902 def release_temp(self, env):
4903 if self.temp_counter == self.uses:
4904 env.release_temp(self.result())
4906 #------------------------------------------------------------------------------------
4907 #
4908 # Runtime support code
4909 #
4910 #------------------------------------------------------------------------------------
4912 get_name_interned_utility_code = UtilityCode(
4913 proto = """
4914 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4915 """,
4916 impl = """
4917 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4918 PyObject *result;
4919 result = PyObject_GetAttr(dict, name);
4920 if (!result)
4921 PyErr_SetObject(PyExc_NameError, name);
4922 return result;
4923 }
4924 """)
4926 #------------------------------------------------------------------------------------
4928 import_utility_code = UtilityCode(
4929 proto = """
4930 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4931 """,
4932 impl = """
4933 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4934 PyObject *__import__ = 0;
4935 PyObject *empty_list = 0;
4936 PyObject *module = 0;
4937 PyObject *global_dict = 0;
4938 PyObject *empty_dict = 0;
4939 PyObject *list;
4940 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4941 if (!__import__)
4942 goto bad;
4943 if (from_list)
4944 list = from_list;
4945 else {
4946 empty_list = PyList_New(0);
4947 if (!empty_list)
4948 goto bad;
4949 list = empty_list;
4950 }
4951 global_dict = PyModule_GetDict(%(GLOBALS)s);
4952 if (!global_dict)
4953 goto bad;
4954 empty_dict = PyDict_New();
4955 if (!empty_dict)
4956 goto bad;
4957 module = PyObject_CallFunctionObjArgs(__import__,
4958 name, global_dict, empty_dict, list, NULL);
4959 bad:
4960 Py_XDECREF(empty_list);
4961 Py_XDECREF(__import__);
4962 Py_XDECREF(empty_dict);
4963 return module;
4964 }
4965 """ % {
4966 "BUILTINS": Naming.builtins_cname,
4967 "GLOBALS": Naming.module_cname,
4968 })
4970 #------------------------------------------------------------------------------------
4972 get_exception_utility_code = UtilityCode(
4973 proto = """
4974 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4975 """,
4976 impl = """
4977 static PyObject *__Pyx_GetExcValue(void) {
4978 PyObject *type = 0, *value = 0, *tb = 0;
4979 PyObject *tmp_type, *tmp_value, *tmp_tb;
4980 PyObject *result = 0;
4981 PyThreadState *tstate = PyThreadState_Get();
4982 PyErr_Fetch(&type, &value, &tb);
4983 PyErr_NormalizeException(&type, &value, &tb);
4984 if (PyErr_Occurred())
4985 goto bad;
4986 if (!value) {
4987 value = Py_None;
4988 Py_INCREF(value);
4989 }
4990 tmp_type = tstate->exc_type;
4991 tmp_value = tstate->exc_value;
4992 tmp_tb = tstate->exc_traceback;
4993 tstate->exc_type = type;
4994 tstate->exc_value = value;
4995 tstate->exc_traceback = tb;
4996 /* Make sure tstate is in a consistent state when we XDECREF
4997 these objects (XDECREF may run arbitrary code). */
4998 Py_XDECREF(tmp_type);
4999 Py_XDECREF(tmp_value);
5000 Py_XDECREF(tmp_tb);
5001 result = value;
5002 Py_XINCREF(result);
5003 type = 0;
5004 value = 0;
5005 tb = 0;
5006 bad:
5007 Py_XDECREF(type);
5008 Py_XDECREF(value);
5009 Py_XDECREF(tb);
5010 return result;
5011 }
5012 """)
5014 #------------------------------------------------------------------------------------
5016 unpacking_utility_code = UtilityCode(
5017 proto = """
5018 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5019 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5020 """,
5021 impl = """
5022 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5023 PyObject *item;
5024 if (!(item = PyIter_Next(iter))) {
5025 if (!PyErr_Occurred()) {
5026 PyErr_Format(PyExc_ValueError,
5027 #if PY_VERSION_HEX < 0x02050000
5028 "need more than %d values to unpack", (int)index);
5029 #else
5030 "need more than %zd values to unpack", index);
5031 #endif
5032 }
5033 }
5034 return item;
5035 }
5037 static int __Pyx_EndUnpack(PyObject *iter) {
5038 PyObject *item;
5039 if ((item = PyIter_Next(iter))) {
5040 Py_DECREF(item);
5041 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5042 return -1;
5043 }
5044 else if (!PyErr_Occurred())
5045 return 0;
5046 else
5047 return -1;
5048 }
5049 """)
5051 #------------------------------------------------------------------------------------
5053 type_test_utility_code = UtilityCode(
5054 proto = """
5055 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5056 """,
5057 impl = """
5058 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5059 if (!type) {
5060 PyErr_Format(PyExc_SystemError, "Missing type object");
5061 return 0;
5062 }
5063 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5064 return 1;
5065 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5066 Py_TYPE(obj)->tp_name, type->tp_name);
5067 return 0;
5068 }
5069 """)
5071 #------------------------------------------------------------------------------------
5073 create_class_utility_code = UtilityCode(
5074 proto = """
5075 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5076 """,
5077 impl = """
5078 static PyObject *__Pyx_CreateClass(
5079 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5080 {
5081 PyObject *py_modname;
5082 PyObject *result = 0;
5084 #if PY_MAJOR_VERSION < 3
5085 py_modname = PyString_FromString(modname);
5086 #else
5087 py_modname = PyUnicode_FromString(modname);
5088 #endif
5089 if (!py_modname)
5090 goto bad;
5091 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5092 goto bad;
5093 #if PY_MAJOR_VERSION < 3
5094 result = PyClass_New(bases, dict, name);
5095 #else
5096 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5097 #endif
5098 bad:
5099 Py_XDECREF(py_modname);
5100 return result;
5101 }
5102 """)
5104 #------------------------------------------------------------------------------------
5106 cpp_exception_utility_code = UtilityCode(
5107 proto = """
5108 #ifndef __Pyx_CppExn2PyErr
5109 static void __Pyx_CppExn2PyErr() {
5110 try {
5111 if (PyErr_Occurred())
5112 ; // let the latest Python exn pass through and ignore the current one
5113 else
5114 throw;
5115 } catch (const std::out_of_range& exn) {
5116 // catch out_of_range explicitly so the proper Python exn may be raised
5117 PyErr_SetString(PyExc_IndexError, exn.what());
5118 } catch (const std::exception& exn) {
5119 PyErr_SetString(PyExc_RuntimeError, exn.what());
5120 }
5121 catch (...)
5122 {
5123 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5124 }
5125 }
5126 #endif
5127 """,
5128 impl = ""
5129 )
5131 #------------------------------------------------------------------------------------
5133 append_utility_code = UtilityCode(
5134 proto = """
5135 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5136 if (likely(PyList_CheckExact(L))) {
5137 if (PyList_Append(L, x) < 0) return NULL;
5138 Py_INCREF(Py_None);
5139 return Py_None; // this is just to have an accurate signature
5140 }
5141 else {
5142 PyObject *r, *m;
5143 m = PyObject_GetAttrString(L, "append");
5144 if (!m) return NULL;
5145 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5146 Py_DECREF(m);
5147 return r;
5148 }
5149 }
5150 """,
5151 impl = ""
5152 )
5154 #------------------------------------------------------------------------------------
5156 # If the is_unsigned flag is set, we need to do some extra work to make
5157 # sure the index doesn't become negative.
5159 getitem_int_utility_code = UtilityCode(
5160 proto = """
5161 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5162 PyObject *r;
5163 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5164 r = PyList_GET_ITEM(o, i);
5165 Py_INCREF(r);
5166 }
5167 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
5168 r = PyTuple_GET_ITEM(o, i);
5169 Py_INCREF(r);
5170 }
5171 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
5172 r = PySequence_GetItem(o, i);
5173 else {
5174 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);
5175 if (!j)
5176 return 0;
5177 r = PyObject_GetItem(o, j);
5178 Py_DECREF(j);
5179 }
5180 return r;
5181 }
5182 """,
5183 impl = """
5184 """)
5186 #------------------------------------------------------------------------------------
5188 setitem_int_utility_code = UtilityCode(
5189 proto = """
5190 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
5191 int r;
5192 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5193 Py_DECREF(PyList_GET_ITEM(o, i));
5194 Py_INCREF(v);
5195 PyList_SET_ITEM(o, i, v);
5196 return 1;
5197 }
5198 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5199 r = PySequence_SetItem(o, i, v);
5200 else {
5201 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);
5202 if (!j)
5203 return -1;
5204 r = PyObject_SetItem(o, j, v);
5205 Py_DECREF(j);
5206 }
5207 return r;
5208 }
5209 """,
5210 impl = """
5211 """)
5213 #------------------------------------------------------------------------------------
5215 delitem_int_utility_code = UtilityCode(
5216 proto = """
5217 static INLINE int __Pyx_DelItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5218 int r;
5219 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5220 r = PySequence_DelItem(o, i);
5221 else {
5222 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);
5223 if (!j)
5224 return -1;
5225 r = PyObject_DelItem(o, j);
5226 Py_DECREF(j);
5227 }
5228 return r;
5229 }
5230 """,
5231 impl = """
5232 """)
5234 #------------------------------------------------------------------------------------
5236 raise_noneattr_error_utility_code = UtilityCode(
5237 proto = """
5238 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5239 """,
5240 impl = """
5241 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5242 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5243 }
5244 """)
5246 raise_noneindex_error_utility_code = UtilityCode(
5247 proto = """
5248 static INLINE void __Pyx_RaiseNoneIndexingError();
5249 """,
5250 impl = """
5251 static INLINE void __Pyx_RaiseNoneIndexingError() {
5252 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5253 }
5254 """)
