Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 2203:4495287d2fdb

NoneCheckNode to enforce runtime None checks for object references
author Stefan Behnel <scoder@users.berlios.de>
date Sun Mar 29 20:55:51 2009 +0200 (3 years ago)
parents 0afd7738bd5e
children d7e5ef4c6af9
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
7 from Errors import error, warning, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Cython.Utils import UtilityCode
10 import StringEncoding
11 import Naming
12 import Nodes
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type
17 import Builtin
18 import Symtab
19 import Options
20 from Annotate import AnnotationItem
22 from Cython.Debugging import print_call_chain
23 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
24 debug_coercion
26 try:
27 set
28 except NameError:
29 from sets import Set as set
31 class NotConstant(object): pass # just for the name
32 not_a_constant = NotConstant()
33 constant_value_not_set = object()
35 class ExprNode(Node):
36 # subexprs [string] Class var holding names of subexpr node attrs
37 # type PyrexType Type of the result
38 # result_code string Code fragment
39 # result_ctype string C type of result_code if different from type
40 # is_temp boolean Result is in a temporary variable
41 # is_sequence_constructor
42 # boolean Is a list or tuple constructor expression
43 # saved_subexpr_nodes
44 # [ExprNode or [ExprNode or None] or None]
45 # Cached result of subexpr_nodes()
47 result_ctype = None
48 type = None
50 # The Analyse Expressions phase for expressions is split
51 # into two sub-phases:
52 #
53 # Analyse Types
54 # Determines the result type of the expression based
55 # on the types of its sub-expressions, and inserts
56 # coercion nodes into the expression tree where needed.
57 # Marks nodes which will need to have temporary variables
58 # allocated.
59 #
60 # Allocate Temps
61 # Allocates temporary variables where needed, and fills
62 # in the result_code field of each node.
63 #
64 # ExprNode provides some convenience routines which
65 # perform both of the above phases. These should only
66 # be called from statement nodes, and only when no
67 # coercion nodes need to be added around the expression
68 # being analysed. In that case, the above two phases
69 # should be invoked separately.
70 #
71 # Framework code in ExprNode provides much of the common
72 # processing for the various phases. It makes use of the
73 # 'subexprs' class attribute of ExprNodes, which should
74 # contain a list of the names of attributes which can
75 # hold sub-nodes or sequences of sub-nodes.
76 #
77 # The framework makes use of a number of abstract methods.
78 # Their responsibilities are as follows.
79 #
80 # Declaration Analysis phase
81 #
82 # analyse_target_declaration
83 # Called during the Analyse Declarations phase to analyse
84 # the LHS of an assignment or argument of a del statement.
85 # Nodes which cannot be the LHS of an assignment need not
86 # implement it.
87 #
88 # Expression Analysis phase
89 #
90 # analyse_types
91 # - Call analyse_types on all sub-expressions.
92 # - Check operand types, and wrap coercion nodes around
93 # sub-expressions where needed.
94 # - Set the type of this node.
95 # - If a temporary variable will be required for the
96 # result, set the is_temp flag of this node.
97 #
98 # analyse_target_types
99 # Called during the Analyse Types phase to analyse
100 # the LHS of an assignment or argument of a del
101 # statement. Similar responsibilities to analyse_types.
102 #
103 # allocate_temps
104 # - Call allocate_temps for all sub-nodes.
105 # - Call allocate_temp for this node.
106 # - If a temporary was allocated, call release_temp on
107 # all sub-expressions.
108 #
109 # allocate_target_temps
110 # - Call allocate_temps on sub-nodes and allocate any other
111 # temps used during assignment.
112 # - Fill in result_code with a C lvalue if needed.
113 # - If a rhs node is supplied, call release_temp on it.
114 # - Call release_temp on sub-nodes and release any other
115 # temps used during assignment.
116 #
117 # target_code
118 # Called by the default implementation of allocate_target_temps.
119 # Should return a C lvalue for assigning to the node. The default
120 # implementation calls calculate_result_code.
121 #
122 # check_const
123 # - Check that this node and its subnodes form a
124 # legal constant expression. If so, do nothing,
125 # otherwise call not_const.
126 #
127 # The default implementation of check_const
128 # assumes that the expression is not constant.
129 #
130 # check_const_addr
131 # - Same as check_const, except check that the
132 # expression is a C lvalue whose address is
133 # constant. Otherwise, call addr_not_const.
134 #
135 # The default implementation of calc_const_addr
136 # assumes that the expression is not a constant
137 # lvalue.
138 #
139 # Code Generation phase
140 #
141 # generate_evaluation_code
142 # - Call generate_evaluation_code for sub-expressions.
143 # - Perform the functions of generate_result_code
144 # (see below).
145 # - If result is temporary, call generate_disposal_code
146 # on all sub-expressions.
147 #
148 # A default implementation of generate_evaluation_code
149 # is provided which uses the following abstract methods:
150 #
151 # generate_result_code
152 # - Generate any C statements necessary to calculate
153 # the result of this node from the results of its
154 # sub-expressions.
155 #
156 # calculate_result_code
157 # - Should return a C code fragment evaluating to the
158 # result. This is only called when the result is not
159 # a temporary.
160 #
161 # generate_assignment_code
162 # Called on the LHS of an assignment.
163 # - Call generate_evaluation_code for sub-expressions.
164 # - Generate code to perform the assignment.
165 # - If the assignment absorbed a reference, call
166 # generate_post_assignment_code on the RHS,
167 # otherwise call generate_disposal_code on it.
168 #
169 # generate_deletion_code
170 # Called on an argument of a del statement.
171 # - Call generate_evaluation_code for sub-expressions.
172 # - Generate code to perform the deletion.
173 # - Call generate_disposal_code on all sub-expressions.
174 #
175 #
177 is_sequence_constructor = 0
178 is_attribute = 0
180 saved_subexpr_nodes = None
181 is_temp = 0
182 is_target = 0
184 constant_result = constant_value_not_set
186 try:
187 _get_child_attrs = operator.attrgetter('subexprs')
188 except AttributeError:
189 # Python 2.3
190 def _get_child_attrs(self):
191 return self.subexprs
192 child_attrs = property(fget=_get_child_attrs)
194 def not_implemented(self, method_name):
195 print_call_chain(method_name, "not implemented") ###
196 raise InternalError(
197 "%s.%s not implemented" %
198 (self.__class__.__name__, method_name))
200 def is_lvalue(self):
201 return 0
203 def is_ephemeral(self):
204 # An ephemeral node is one whose result is in
205 # a Python temporary and we suspect there are no
206 # other references to it. Certain operations are
207 # disallowed on such values, since they are
208 # likely to result in a dangling pointer.
209 return self.type.is_pyobject and self.is_temp
211 def subexpr_nodes(self):
212 # Extract a list of subexpression nodes based
213 # on the contents of the subexprs class attribute.
214 nodes = []
215 for name in self.subexprs:
216 item = getattr(self, name)
217 if item is not None:
218 if type(item) is list:
219 nodes.extend(item)
220 else:
221 nodes.append(item)
222 return nodes
224 def result(self):
225 if not self.is_temp or self.is_target:
226 return self.calculate_result_code()
227 else: # i.e. self.is_temp:
228 return self.result_code
230 def result_as(self, type = None):
231 # Return the result code cast to the specified C type.
232 return typecast(type, self.ctype(), self.result())
234 def py_result(self):
235 # Return the result code cast to PyObject *.
236 return self.result_as(py_object_type)
238 def ctype(self):
239 # Return the native C type of the result (i.e. the
240 # C type of the result_code expression).
241 return self.result_ctype or self.type
243 def get_constant_result_code(self):
244 # Return the constant value of this node as a result code
245 # string, or None if the node is not constant.
246 return None
248 def calculate_constant_result(self):
249 # Calculate the constant result of this expression and store
250 # it in ``self.constant_result``. Does nothing by default,
251 # thus leaving ``self.constant_result`` unknown.
252 #
253 # This must only be called when it is assured that all
254 # sub-expressions have a valid constant_result value. The
255 # ConstantFolding transform will do this.
256 pass
258 def compile_time_value(self, denv):
259 # Return value of compile-time expression, or report error.
260 error(self.pos, "Invalid compile-time expression")
262 def compile_time_value_error(self, e):
263 error(self.pos, "Error in compile-time expression: %s: %s" % (
264 e.__class__.__name__, e))
266 # ------------- Declaration Analysis ----------------
268 def analyse_target_declaration(self, env):
269 error(self.pos, "Cannot assign to or delete this")
271 # ------------- Expression Analysis ----------------
273 def analyse_const_expression(self, env):
274 # Called during the analyse_declarations phase of a
275 # constant expression. Analyses the expression's type,
276 # checks whether it is a legal const expression,
277 # and determines its value.
278 self.analyse_types(env)
279 self.allocate_temps(env)
280 self.check_const()
282 def analyse_expressions(self, env):
283 # Convenience routine performing both the Type
284 # Analysis and Temp Allocation phases for a whole
285 # expression.
286 self.analyse_types(env)
287 self.allocate_temps(env)
289 def analyse_target_expression(self, env, rhs):
290 # Convenience routine performing both the Type
291 # Analysis and Temp Allocation phases for the LHS of
292 # an assignment.
293 self.analyse_target_types(env)
294 self.allocate_target_temps(env, rhs)
296 def analyse_boolean_expression(self, env):
297 # Analyse expression and coerce to a boolean.
298 self.analyse_types(env)
299 bool = self.coerce_to_boolean(env)
300 bool.allocate_temps(env)
301 return bool
303 def analyse_temp_boolean_expression(self, env):
304 # Analyse boolean expression and coerce result into
305 # a temporary. This is used when a branch is to be
306 # performed on the result and we won't have an
307 # opportunity to ensure disposal code is executed
308 # afterwards. By forcing the result into a temporary,
309 # we ensure that all disposal has been done by the
310 # time we get the result.
311 self.analyse_types(env)
312 bool = self.coerce_to_boolean(env)
313 temp_bool = bool.coerce_to_temp(env)
314 temp_bool.allocate_temps(env)
315 return temp_bool
317 # --------------- Type Analysis ------------------
319 def analyse_as_module(self, env):
320 # If this node can be interpreted as a reference to a
321 # cimported module, return its scope, else None.
322 return None
324 def analyse_as_type(self, env):
325 # If this node can be interpreted as a reference to a
326 # type, return that type, else None.
327 return None
329 def analyse_as_extension_type(self, env):
330 # If this node can be interpreted as a reference to an
331 # extension type, return its type, else None.
332 return None
334 def analyse_types(self, env):
335 self.not_implemented("analyse_types")
337 def analyse_target_types(self, env):
338 self.analyse_types(env)
340 def gil_check(self, env):
341 # By default, any expression based on Python objects is
342 # prevented in nogil environments. Subtypes must override
343 # this if they can work without the GIL.
344 if self.type.is_pyobject:
345 self._gil_check(env)
347 def gil_assignment_check(self, env):
348 if env.nogil and self.type.is_pyobject:
349 error(self.pos, "Assignment of Python object not allowed without gil")
351 def check_const(self):
352 self.not_const()
354 def not_const(self):
355 error(self.pos, "Not allowed in a constant expression")
357 def check_const_addr(self):
358 self.addr_not_const()
360 def addr_not_const(self):
361 error(self.pos, "Address is not constant")
363 # ----------------- Result Allocation -----------------
365 def result_in_temp(self):
366 # Return true if result is in a temporary owned by
367 # this node or one of its subexpressions. Overridden
368 # by certain nodes which can share the result of
369 # a subnode.
370 return self.is_temp
372 def allocate_target_temps(self, env, rhs):
373 # Perform temp allocation for the LHS of an assignment.
374 if debug_temp_alloc:
375 print("%s Allocating target temps" % self)
376 self.allocate_subexpr_temps(env)
377 self.is_target = True
378 if rhs:
379 rhs.release_temp(env)
380 self.release_subexpr_temps(env)
382 def allocate_temps(self, env, result = None):
383 # Allocate temporary variables for this node and
384 # all its sub-expressions. If a result is specified,
385 # this must be a temp node and the specified variable
386 # is used as the result instead of allocating a new
387 # one.
388 assert result is None, "deprecated, contact dagss if this triggers"
389 if debug_temp_alloc:
390 print("%s Allocating temps" % self)
391 self.allocate_subexpr_temps(env)
392 self.allocate_temp(env, result)
393 if self.is_temp:
394 self.release_subexpr_temps(env)
396 def allocate_subexpr_temps(self, env):
397 # Allocate temporary variables for all sub-expressions
398 # of this node.
399 if debug_temp_alloc:
400 print("%s Allocating temps for: %s" % (self, self.subexprs))
401 for node in self.subexpr_nodes():
402 if node:
403 if debug_temp_alloc:
404 print("%s Allocating temps for %s" % (self, node))
405 node.allocate_temps(env)
407 def allocate_temp(self, env, result = None):
408 # If this node requires a temporary variable for its
409 # result, allocate one, otherwise set the result to
410 # a C code fragment. If a result is specified,
411 # this must be a temp node and the specified variable
412 # is used as the result instead of allocating a new
413 # one.
414 if debug_temp_alloc:
415 print("%s Allocating temp" % self)
416 if result:
417 if not self.is_temp:
418 raise InternalError("Result forced on non-temp node")
419 self.result_code = result
420 elif self.is_temp:
421 type = self.type
422 if not type.is_void:
423 if type.is_pyobject:
424 type = PyrexTypes.py_object_type
425 self.result_code = env.allocate_temp(type)
426 else:
427 self.result_code = None
428 if debug_temp_alloc:
429 print("%s Allocated result %s" % (self, self.result_code))
431 def target_code(self):
432 # Return code fragment for use as LHS of a C assignment.
433 return self.calculate_result_code()
435 def calculate_result_code(self):
436 self.not_implemented("calculate_result_code")
438 # def release_target_temp(self, env):
439 # # Release temporaries used by LHS of an assignment.
440 # self.release_subexpr_temps(env)
442 def release_temp(self, env):
443 # If this node owns a temporary result, release it,
444 # otherwise release results of its sub-expressions.
445 if self.is_temp:
446 if debug_temp_alloc:
447 print("%s Releasing result %s" % (self, self.result_code))
448 env.release_temp(self.result_code)
449 else:
450 self.release_subexpr_temps(env)
452 def release_subexpr_temps(self, env):
453 # Release the results of all sub-expressions of
454 # this node.
455 for node in self.subexpr_nodes():
456 if node:
457 node.release_temp(env)
459 # ---------------- Code Generation -----------------
461 def make_owned_reference(self, code):
462 # If result is a pyobject, make sure we own
463 # a reference to it.
464 if self.type.is_pyobject and not self.result_in_temp():
465 code.put_incref(self.result(), self.ctype())
467 def generate_evaluation_code(self, code):
468 code.mark_pos(self.pos)
469 # Generate code to evaluate this node and
470 # its sub-expressions, and dispose of any
471 # temporary results of its sub-expressions.
472 self.generate_subexpr_evaluation_code(code)
473 self.generate_result_code(code)
474 if self.is_temp:
475 self.generate_subexpr_disposal_code(code)
476 self.free_subexpr_temps(code)
478 def generate_subexpr_evaluation_code(self, code):
479 for node in self.subexpr_nodes():
480 node.generate_evaluation_code(code)
482 def generate_result_code(self, code):
483 self.not_implemented("generate_result_code")
485 def generate_disposal_code(self, code):
486 # If necessary, generate code to dispose of
487 # temporary Python reference.
488 if self.is_temp:
489 if self.type.is_pyobject:
490 code.put_decref_clear(self.result(), self.ctype())
491 else:
492 self.generate_subexpr_disposal_code(code)
494 def generate_subexpr_disposal_code(self, code):
495 # Generate code to dispose of temporary results
496 # of all sub-expressions.
497 for node in self.subexpr_nodes():
498 node.generate_disposal_code(code)
500 def generate_post_assignment_code(self, code):
501 # Same as generate_disposal_code except that
502 # assignment will have absorbed a reference to
503 # the result if it is a Python object.
504 if self.is_temp:
505 if self.type.is_pyobject:
506 code.putln("%s = 0;" % self.result())
507 else:
508 self.generate_subexpr_disposal_code(code)
510 def generate_assignment_code(self, rhs, code):
511 # Stub method for nodes which are not legal as
512 # the LHS of an assignment. An error will have
513 # been reported earlier.
514 pass
516 def generate_deletion_code(self, code):
517 # Stub method for nodes that are not legal as
518 # the argument of a del statement. An error
519 # will have been reported earlier.
520 pass
522 def free_temps(self, code):
523 if not self.is_temp:
524 self.free_subexpr_temps(code)
525 # otherwise, already freed in generate_evaluation_code
527 def free_subexpr_temps(self, code):
528 for sub in self.subexpr_nodes():
529 sub.free_temps(code)
531 # ---------------- Annotation ---------------------
533 def annotate(self, code):
534 for node in self.subexpr_nodes():
535 node.annotate(code)
537 # ----------------- Coercion ----------------------
539 def coerce_to(self, dst_type, env):
540 # Coerce the result so that it can be assigned to
541 # something of type dst_type. If processing is necessary,
542 # wraps this node in a coercion node and returns that.
543 # Otherwise, returns this node unchanged.
544 #
545 # This method is called during the analyse_expressions
546 # phase of the src_node's processing.
547 src = self
548 src_type = self.type
549 src_is_py_type = src_type.is_pyobject
550 dst_is_py_type = dst_type.is_pyobject
552 if dst_type.is_pyobject:
553 if not src.type.is_pyobject:
554 src = CoerceToPyTypeNode(src, env)
555 if not src.type.subtype_of(dst_type):
556 if not isinstance(src, NoneNode):
557 src = PyTypeTestNode(src, dst_type, env)
558 elif src.type.is_pyobject:
559 src = CoerceFromPyTypeNode(dst_type, src, env)
560 else: # neither src nor dst are py types
561 # Added the string comparison, since for c types that
562 # is enough, but Cython gets confused when the types are
563 # in different files.
564 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
565 error(self.pos, "Cannot assign type '%s' to '%s'" %
566 (src.type, dst_type))
567 return src
569 def coerce_to_pyobject(self, env):
570 return self.coerce_to(PyrexTypes.py_object_type, env)
572 def coerce_to_boolean(self, env):
573 # Coerce result to something acceptable as
574 # a boolean value.
575 type = self.type
576 if type.is_pyobject or type.is_ptr or type.is_float:
577 return CoerceToBooleanNode(self, env)
578 else:
579 if not type.is_int and not type.is_error:
580 error(self.pos,
581 "Type '%s' not acceptable as a boolean" % type)
582 return self
584 def coerce_to_integer(self, env):
585 # If not already some C integer type, coerce to longint.
586 if self.type.is_int:
587 return self
588 else:
589 return self.coerce_to(PyrexTypes.c_long_type, env)
591 def coerce_to_temp(self, env):
592 # Ensure that the result is in a temporary.
593 if self.result_in_temp():
594 return self
595 else:
596 return CoerceToTempNode(self, env)
598 def coerce_to_simple(self, env):
599 # Ensure that the result is simple (see is_simple).
600 if self.is_simple():
601 return self
602 else:
603 return self.coerce_to_temp(env)
605 def is_simple(self):
606 # A node is simple if its result is something that can
607 # be referred to without performing any operations, e.g.
608 # a constant, local var, C global var, struct member
609 # reference, or temporary.
610 return self.result_in_temp()
612 def as_cython_attribute(self):
613 return None
616 class RemoveAllocateTemps(type):
617 def __init__(cls, name, bases, dct):
618 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
619 def noop(self, env): pass
620 setattr(cls, 'allocate_temps', noop)
621 setattr(cls, 'allocate_temp', noop)
622 setattr(cls, 'release_temp', noop)
624 class NewTempExprNode(ExprNode):
625 temp_code = None
626 old_temp = None # error checker for multiple frees etc.
628 # Do not enable this unless you are trying to make all ExprNodes
629 # NewTempExprNodes (child nodes reached via recursion may not have
630 # transferred).
631 # __metaclass__ = RemoveAllocateTemps
633 def result(self):
634 if self.is_temp:
635 return self.temp_code
636 else:
637 return self.calculate_result_code()
639 def allocate_target_temps(self, env, rhs):
640 self.allocate_subexpr_temps(env)
641 self.is_target = True
642 if rhs:
643 rhs.release_temp(env)
644 self.release_subexpr_temps(env)
646 def allocate_temps(self, env, result = None):
647 assert result is None, "deprecated, contact dagss if this triggers"
648 self.allocate_subexpr_temps(env)
649 if self.is_temp:
650 self.release_subexpr_temps(env)
652 def allocate_temp(self, env, result = None):
653 assert result is None
655 def release_temp(self, env):
656 if self.is_temp:
657 pass
658 else:
659 self.release_subexpr_temps(env)
661 def allocate_temp_result(self, code):
662 if self.temp_code:
663 raise RuntimeError("Temp allocated multiple times")
664 type = self.type
665 if not type.is_void:
666 if type.is_pyobject:
667 type = PyrexTypes.py_object_type
668 self.temp_code = code.funcstate.allocate_temp(
669 type, manage_ref=True)
670 else:
671 self.temp_code = None
673 def release_temp_result(self, code):
674 if not self.temp_code:
675 if self.old_temp:
676 raise RuntimeError("temp %s released multiple times in %s" % (
677 self.old_temp, self.__class__.__name__))
678 else:
679 raise RuntimeError("no temp, but release requested in %s" % (
680 self.__class__.__name__))
681 code.funcstate.release_temp(self.temp_code)
682 self.old_temp = self.temp_code
683 self.temp_code = None
685 def generate_evaluation_code(self, code):
686 code.mark_pos(self.pos)
688 # Generate code to evaluate this node and
689 # its sub-expressions, and dispose of any
690 # temporary results of its sub-expressions.
691 self.generate_subexpr_evaluation_code(code)
693 if self.is_temp:
694 self.allocate_temp_result(code)
696 self.generate_result_code(code)
697 if self.is_temp:
698 # If we are temp we do not need to wait until this node is disposed
699 # before disposing children.
700 self.generate_subexpr_disposal_code(code)
701 self.free_subexpr_temps(code)
703 def generate_disposal_code(self, code):
704 if self.is_temp:
705 if self.type.is_pyobject:
706 code.put_decref_clear(self.result(), self.ctype())
707 else:
708 # Already done if self.is_temp
709 self.generate_subexpr_disposal_code(code)
711 def generate_post_assignment_code(self, code):
712 if self.is_temp:
713 if self.type.is_pyobject:
714 code.putln("%s = 0;" % self.result())
715 else:
716 self.generate_subexpr_disposal_code(code)
718 def free_temps(self, code):
719 if self.is_temp:
720 if not self.type.is_void:
721 self.release_temp_result(code)
722 else:
723 self.free_subexpr_temps(code)
725 # ExprNode = NewTempExprNode
727 class AtomicExprNode(ExprNode):
728 # Abstract base class for expression nodes which have
729 # no sub-expressions.
731 subexprs = []
733 class AtomicNewTempExprNode(NewTempExprNode):
734 # I do not dare to convert NameNode yet. This is now
735 # ancestor of all former AtomicExprNode except
736 # NameNode. Should be renamed to AtomicExprNode
737 # when done.
739 # Abstract base class for expression nodes which have
740 # no sub-expressions.
742 subexprs = []
744 # Override to optimize -- we know we have no children
745 def generate_subexpr_evaluation_code(self, code):
746 pass
747 def generate_subexpr_disposal_code(self, code):
748 pass
750 class PyConstNode(AtomicNewTempExprNode):
751 # Abstract base class for constant Python values.
753 is_literal = 1
755 def is_simple(self):
756 return 1
758 def analyse_types(self, env):
759 self.type = py_object_type
761 def calculate_result_code(self):
762 return self.value
764 def generate_result_code(self, code):
765 pass
768 class NoneNode(PyConstNode):
769 # The constant value None
771 value = "Py_None"
773 constant_result = None
774 gil_check = None
776 def compile_time_value(self, denv):
777 return None
779 class EllipsisNode(PyConstNode):
780 # '...' in a subscript list.
782 value = "Py_Ellipsis"
784 constant_result = Ellipsis
786 def compile_time_value(self, denv):
787 return Ellipsis
790 class ConstNode(AtomicNewTempExprNode):
791 # Abstract base type for literal constant nodes.
792 #
793 # value string C code fragment
795 is_literal = 1
796 gil_check = None
798 def is_simple(self):
799 return 1
801 def analyse_types(self, env):
802 pass # Types are held in class variables
804 def check_const(self):
805 pass
807 def get_constant_result_code(self):
808 return self.calculate_result_code()
810 def calculate_result_code(self):
811 return str(self.value)
813 def generate_result_code(self, code):
814 pass
817 class BoolNode(ConstNode):
818 type = PyrexTypes.c_bint_type
819 # The constant value True or False
821 def calculate_constant_result(self):
822 self.constant_result = self.value
824 def compile_time_value(self, denv):
825 return self.value
827 def calculate_result_code(self):
828 return str(int(self.value))
831 class NullNode(ConstNode):
832 type = PyrexTypes.c_null_ptr_type
833 value = "NULL"
834 constant_result = 0
836 def get_constant_result_code(self):
837 return self.value
840 class CharNode(ConstNode):
841 type = PyrexTypes.c_char_type
843 def calculate_constant_result(self):
844 self.constant_result = ord(self.value)
846 def compile_time_value(self, denv):
847 return ord(self.value)
849 def calculate_result_code(self):
850 return "'%s'" % StringEncoding.escape_character(self.value)
853 class IntNode(ConstNode):
855 # unsigned "" or "U"
856 # longness "" or "L" or "LL"
858 unsigned = ""
859 longness = ""
860 type = PyrexTypes.c_long_type
862 def coerce_to(self, dst_type, env):
863 if dst_type.is_numeric:
864 self.type = PyrexTypes.c_long_type
865 return self
866 # Arrange for a Python version of the number to be pre-allocated
867 # when coercing to a Python type.
868 if dst_type.is_pyobject:
869 self.type = PyrexTypes.py_object_type
870 # We still need to perform normal coerce_to processing on the
871 # result, because we might be coercing to an extension type,
872 # in which case a type test node will be needed.
873 return ConstNode.coerce_to(self, dst_type, env)
875 def coerce_to_boolean(self, env):
876 self.type = PyrexTypes.c_bint_type
877 return self
879 def generate_evaluation_code(self, code):
880 if self.type.is_pyobject:
881 self.result_code = code.get_py_num(self.value, self.longness)
882 else:
883 self.result_code = self.get_constant_result_code()
885 def get_constant_result_code(self):
886 return str(self.value) + self.unsigned + self.longness
888 def calculate_result_code(self):
889 return self.result_code
891 def calculate_constant_result(self):
892 self.constant_result = int(self.value, 0)
894 def compile_time_value(self, denv):
895 return int(self.value, 0)
898 class FloatNode(ConstNode):
899 type = PyrexTypes.c_double_type
901 def calculate_constant_result(self):
902 # calculating float values is usually not a good idea
903 #self.constant_result = float(self.value)
904 pass
906 def compile_time_value(self, denv):
907 return float(self.value)
909 def calculate_result_code(self):
910 strval = repr(float(self.value))
911 if strval == 'nan':
912 return "(Py_HUGE_VAL * 0)"
913 elif strval == 'inf':
914 return "Py_HUGE_VAL"
915 elif strval == '-inf':
916 return "(-Py_HUGE_VAL)"
917 else:
918 return strval
921 class StringNode(ConstNode):
922 type = PyrexTypes.c_char_ptr_type
924 def compile_time_value(self, denv):
925 return self.value
927 def analyse_as_type(self, env):
928 type = PyrexTypes.parse_basic_type(self.value)
929 if type is not None:
930 return type
931 from TreeFragment import TreeFragment
932 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
933 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
934 sizeof_node = declaration.root.stats[0].expr
935 sizeof_node.analyse_types(env)
936 if isinstance(sizeof_node, SizeofTypeNode):
937 return sizeof_node.arg_type
939 def coerce_to(self, dst_type, env):
940 if dst_type == PyrexTypes.c_char_ptr_type:
941 self.type = PyrexTypes.c_char_ptr_type
942 return self
944 if dst_type.is_int:
945 if not self.type.is_pyobject and len(self.value) == 1:
946 return CharNode(self.pos, value=self.value)
947 else:
948 error(self.pos, "Only single-character byte strings can be coerced into ints.")
949 return self
950 # Arrange for a Python version of the string to be pre-allocated
951 # when coercing to a Python type.
952 if dst_type.is_pyobject and not self.type.is_pyobject:
953 node = self.as_py_string_node(env)
954 else:
955 node = self
956 # We still need to perform normal coerce_to processing on the
957 # result, because we might be coercing to an extension type,
958 # in which case a type test node will be needed.
959 return ConstNode.coerce_to(node, dst_type, env)
961 def as_py_string_node(self, env):
962 # Return a new StringNode with the same value as this node
963 # but whose type is a Python type instead of a C type.
964 return StringNode(self.pos, value = self.value, type = py_object_type)
966 def generate_evaluation_code(self, code):
967 if self.type.is_pyobject:
968 self.result_code = code.get_py_string_const(self.value)
969 else:
970 self.result_code = code.get_string_const(self.value)
972 def get_constant_result_code(self):
973 return None # FIXME
975 def calculate_result_code(self):
976 return self.result_code
979 class UnicodeNode(PyConstNode):
980 type = unicode_type
982 def coerce_to(self, dst_type, env):
983 if dst_type.is_pyobject:
984 return self
985 else:
986 error(self.pos, "Unicode objects do not support coercion to C types.")
987 return self
989 def generate_evaluation_code(self, code):
990 if self.type.is_pyobject:
991 self.result_code = code.get_py_string_const(self.value)
992 else:
993 self.result_code = code.get_string_const(self.value)
995 def calculate_result_code(self):
996 return self.result_code
998 def compile_time_value(self, env):
999 return self.value
1002 class IdentifierStringNode(ConstNode):
1003 # A Python string that behaves like an identifier, e.g. for
1004 # keyword arguments in a call, or for imported names
1005 type = PyrexTypes.py_object_type
1007 def generate_evaluation_code(self, code):
1008 if self.type.is_pyobject:
1009 self.result_code = code.get_py_string_const(self.value, True)
1010 else:
1011 self.result_code = code.get_string_const(self.value)
1013 def get_constant_result_code(self):
1014 return None
1016 def calculate_result_code(self):
1017 return self.result_code
1020 class LongNode(AtomicNewTempExprNode):
1021 # Python long integer literal
1023 # value string
1025 def calculate_constant_result(self):
1026 self.constant_result = long(self.value)
1028 def compile_time_value(self, denv):
1029 return long(self.value)
1031 def analyse_types(self, env):
1032 self.type = py_object_type
1033 self.is_temp = 1
1035 gil_message = "Constructing Python long int"
1037 def generate_result_code(self, code):
1038 code.putln(
1039 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1040 self.result(),
1041 self.value,
1042 code.error_goto_if_null(self.result(), self.pos)))
1043 code.put_gotref(self.py_result())
1046 class ImagNode(AtomicNewTempExprNode):
1047 # Imaginary number literal
1049 # value float imaginary part
1051 def calculate_constant_result(self):
1052 self.constant_result = complex(0.0, self.value)
1054 def compile_time_value(self, denv):
1055 return complex(0.0, self.value)
1057 def analyse_types(self, env):
1058 self.type = py_object_type
1059 self.is_temp = 1
1061 gil_message = "Constructing complex number"
1063 def generate_result_code(self, code):
1064 code.putln(
1065 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1066 self.result(),
1067 float(self.value),
1068 code.error_goto_if_null(self.result(), self.pos)))
1069 code.put_gotref(self.py_result())
1073 class NameNode(AtomicNewTempExprNode):
1074 # Reference to a local or global variable name.
1076 # name string Python name of the variable
1077 # entry Entry Symbol table entry
1078 # type_entry Entry For extension type names, the original type entry
1080 is_name = True
1081 is_cython_module = False
1082 cython_attribute = None
1083 lhs_of_first_assignment = False
1084 is_used_as_rvalue = 0
1085 entry = None
1086 type_entry = None
1088 def create_analysed_rvalue(pos, env, entry):
1089 node = NameNode(pos)
1090 node.analyse_types(env, entry=entry)
1091 return node
1093 def as_cython_attribute(self):
1094 return self.cython_attribute
1096 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1098 def compile_time_value(self, denv):
1099 try:
1100 return denv.lookup(self.name)
1101 except KeyError:
1102 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1104 def coerce_to(self, dst_type, env):
1105 # If coercing to a generic pyobject and this is a builtin
1106 # C function with a Python equivalent, manufacture a NameNode
1107 # referring to the Python builtin.
1108 #print "NameNode.coerce_to:", self.name, dst_type ###
1109 if dst_type is py_object_type:
1110 entry = self.entry
1111 if entry and entry.is_cfunction:
1112 var_entry = entry.as_variable
1113 if var_entry:
1114 if var_entry.is_builtin and Options.cache_builtins:
1115 var_entry = env.declare_builtin(var_entry.name, self.pos)
1116 node = NameNode(self.pos, name = self.name)
1117 node.entry = var_entry
1118 node.analyse_rvalue_entry(env)
1119 return node
1120 return super(NameNode, self).coerce_to(dst_type, env)
1122 def analyse_as_module(self, env):
1123 # Try to interpret this as a reference to a cimported module.
1124 # Returns the module scope, or None.
1125 entry = self.entry
1126 if not entry:
1127 entry = env.lookup(self.name)
1128 if entry and entry.as_module:
1129 return entry.as_module
1130 return None
1132 def analyse_as_type(self, env):
1133 if self.cython_attribute:
1134 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1135 else:
1136 type = PyrexTypes.parse_basic_type(self.name)
1137 if type:
1138 return type
1139 entry = self.entry
1140 if not entry:
1141 entry = env.lookup(self.name)
1142 if entry and entry.is_type:
1143 return entry.type
1144 else:
1145 return None
1147 def analyse_as_extension_type(self, env):
1148 # Try to interpret this as a reference to an extension type.
1149 # Returns the extension type, or None.
1150 entry = self.entry
1151 if not entry:
1152 entry = env.lookup(self.name)
1153 if entry and entry.is_type and entry.type.is_extension_type:
1154 return entry.type
1155 else:
1156 return None
1158 def analyse_target_declaration(self, env):
1159 if not self.entry:
1160 self.entry = env.lookup_here(self.name)
1161 if not self.entry:
1162 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1163 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1164 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1165 if self.entry.is_declared_generic:
1166 self.result_ctype = py_object_type
1168 def analyse_types(self, env):
1169 if self.entry is None:
1170 self.entry = env.lookup(self.name)
1171 if not self.entry:
1172 self.entry = env.declare_builtin(self.name, self.pos)
1173 if not self.entry:
1174 self.type = PyrexTypes.error_type
1175 return
1176 entry = self.entry
1177 if entry:
1178 entry.used = 1
1179 if entry.type.is_buffer:
1180 import Buffer
1181 Buffer.used_buffer_aux_vars(entry)
1182 if entry.utility_code:
1183 env.use_utility_code(entry.utility_code)
1184 self.analyse_rvalue_entry(env)
1186 def analyse_target_types(self, env):
1187 self.analyse_entry(env)
1188 if not self.is_lvalue():
1189 error(self.pos, "Assignment to non-lvalue '%s'"
1190 % self.name)
1191 self.type = PyrexTypes.error_type
1192 self.entry.used = 1
1193 if self.entry.type.is_buffer:
1194 import Buffer
1195 Buffer.used_buffer_aux_vars(self.entry)
1197 def analyse_rvalue_entry(self, env):
1198 #print "NameNode.analyse_rvalue_entry:", self.name ###
1199 #print "Entry:", self.entry.__dict__ ###
1200 self.analyse_entry(env)
1201 entry = self.entry
1202 if entry.is_declared_generic:
1203 self.result_ctype = py_object_type
1204 if entry.is_pyglobal or entry.is_builtin:
1205 if Options.cache_builtins and entry.is_builtin:
1206 self.is_temp = 0
1207 else:
1208 self.is_temp = 1
1209 self.is_used_as_rvalue = 1
1210 env.use_utility_code(get_name_interned_utility_code)
1212 def gil_check(self, env):
1213 if self.is_used_as_rvalue:
1214 entry = self.entry
1215 if entry.is_builtin:
1216 # if not Options.cache_builtins: # cached builtins are ok
1217 self._gil_check(env)
1218 elif entry.is_pyglobal:
1219 self._gil_check(env)
1221 gil_message = "Accessing Python global or builtin"
1223 def analyse_entry(self, env):
1224 #print "NameNode.analyse_entry:", self.name ###
1225 self.check_identifier_kind()
1226 entry = self.entry
1227 type = entry.type
1228 self.type = type
1230 def check_identifier_kind(self):
1231 # Check that this is an appropriate kind of name for use in an
1232 # expression. Also finds the variable entry associated with
1233 # an extension type.
1234 entry = self.entry
1235 if entry.is_type and entry.type.is_extension_type:
1236 self.type_entry = entry
1237 if not (entry.is_const or entry.is_variable
1238 or entry.is_builtin or entry.is_cfunction):
1239 if self.entry.as_variable:
1240 self.entry = self.entry.as_variable
1241 else:
1242 error(self.pos,
1243 "'%s' is not a constant, variable or function identifier" % self.name)
1245 def is_simple(self):
1246 # If it's not a C variable, it'll be in a temp.
1247 return 1
1249 def calculate_target_results(self, env):
1250 pass
1252 def check_const(self):
1253 entry = self.entry
1254 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1255 self.not_const()
1257 def check_const_addr(self):
1258 entry = self.entry
1259 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1260 self.addr_not_const()
1262 def is_lvalue(self):
1263 return self.entry.is_variable and \
1264 not self.entry.type.is_array and \
1265 not self.entry.is_readonly
1267 def is_ephemeral(self):
1268 # Name nodes are never ephemeral, even if the
1269 # result is in a temporary.
1270 return 0
1272 def calculate_result_code(self):
1273 entry = self.entry
1274 if not entry:
1275 return "<error>" # There was an error earlier
1276 return entry.cname
1278 def generate_result_code(self, code):
1279 assert hasattr(self, 'entry')
1280 entry = self.entry
1281 if entry is None:
1282 return # There was an error earlier
1283 if entry.is_builtin and Options.cache_builtins:
1284 return # Lookup already cached
1285 elif entry.is_pyglobal or entry.is_builtin:
1286 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1287 interned_cname = code.intern_identifier(self.entry.name)
1288 if entry.is_builtin:
1289 namespace = Naming.builtins_cname
1290 else: # entry.is_pyglobal
1291 namespace = entry.scope.namespace_cname
1292 code.putln(
1293 '%s = __Pyx_GetName(%s, %s); %s' % (
1294 self.result(),
1295 namespace,
1296 interned_cname,
1297 code.error_goto_if_null(self.result(), self.pos)))
1298 code.put_gotref(self.py_result())
1300 elif entry.is_local and False:
1301 # control flow not good enough yet
1302 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1303 if assigned is False:
1304 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1305 elif not Options.init_local_none and assigned is None:
1306 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1307 (entry.cname, entry.name, code.error_goto(self.pos)))
1308 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1310 def generate_assignment_code(self, rhs, code):
1311 #print "NameNode.generate_assignment_code:", self.name ###
1312 entry = self.entry
1313 if entry is None:
1314 return # There was an error earlier
1316 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1317 and not self.lhs_of_first_assignment):
1318 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1320 # is_pyglobal seems to be True for module level-globals only.
1321 # We use this to access class->tp_dict if necessary.
1322 if entry.is_pyglobal:
1323 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1324 interned_cname = code.intern_identifier(self.entry.name)
1325 namespace = self.entry.scope.namespace_cname
1326 if entry.is_member:
1327 # if the entry is a member we have to cheat: SetAttr does not work
1328 # on types, so we create a descriptor which is then added to tp_dict
1329 code.put_error_if_neg(self.pos,
1330 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1331 namespace,
1332 interned_cname,
1333 rhs.py_result()))
1334 rhs.generate_disposal_code(code)
1335 rhs.free_temps(code)
1336 # in Py2.6+, we need to invalidate the method cache
1337 code.putln("PyType_Modified(%s);" %
1338 entry.scope.parent_type.typeptr_cname)
1339 else:
1340 code.put_error_if_neg(self.pos,
1341 'PyObject_SetAttr(%s, %s, %s)' % (
1342 namespace,
1343 interned_cname,
1344 rhs.py_result()))
1345 if debug_disposal_code:
1346 print("NameNode.generate_assignment_code:")
1347 print("...generating disposal code for %s" % rhs)
1348 rhs.generate_disposal_code(code)
1349 rhs.free_temps(code)
1350 else:
1351 if self.type.is_buffer:
1352 # Generate code for doing the buffer release/acquisition.
1353 # This might raise an exception in which case the assignment (done
1354 # below) will not happen.
1356 # The reason this is not in a typetest-like node is because the
1357 # variables that the acquired buffer info is stored to is allocated
1358 # per entry and coupled with it.
1359 self.generate_acquire_buffer(rhs, code)
1361 if self.type.is_pyobject:
1362 rhs.make_owned_reference(code)
1363 #print "NameNode.generate_assignment_code: to", self.name ###
1364 #print "...from", rhs ###
1365 #print "...LHS type", self.type, "ctype", self.ctype() ###
1366 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1367 if entry.is_cglobal:
1368 code.put_gotref(self.py_result())
1369 if not self.lhs_of_first_assignment:
1370 if entry.is_local and not Options.init_local_none:
1371 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1372 if initalized is True:
1373 code.put_decref(self.result(), self.ctype())
1374 elif initalized is None:
1375 code.put_xdecref(self.result(), self.ctype())
1376 else:
1377 code.put_decref(self.result(), self.ctype())
1378 if entry.is_cglobal:
1379 code.put_giveref(rhs.py_result())
1380 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1381 if debug_disposal_code:
1382 print("NameNode.generate_assignment_code:")
1383 print("...generating post-assignment code for %s" % rhs)
1384 rhs.generate_post_assignment_code(code)
1385 rhs.free_temps(code)
1387 def generate_acquire_buffer(self, rhs, code):
1388 # rhstmp is only used in case the rhs is a complicated expression leading to
1389 # the object, to avoid repeating the same C expression for every reference
1390 # to the rhs. It does NOT hold a reference.
1391 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1392 if pretty_rhs:
1393 rhstmp = rhs.result_as(self.ctype())
1394 else:
1395 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1396 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1398 buffer_aux = self.entry.buffer_aux
1399 bufstruct = buffer_aux.buffer_info_var.cname
1400 import Buffer
1401 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1402 is_initialized=not self.lhs_of_first_assignment,
1403 pos=self.pos, code=code)
1405 if not pretty_rhs:
1406 code.putln("%s = 0;" % rhstmp)
1407 code.funcstate.release_temp(rhstmp)
1409 def generate_deletion_code(self, code):
1410 if self.entry is None:
1411 return # There was an error earlier
1412 if not self.entry.is_pyglobal:
1413 error(self.pos, "Deletion of local or C global name not supported")
1414 return
1415 code.put_error_if_neg(self.pos,
1416 '__Pyx_DelAttrString(%s, "%s")' % (
1417 Naming.module_cname,
1418 self.entry.name))
1420 def annotate(self, code):
1421 if hasattr(self, 'is_called') and self.is_called:
1422 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1423 if self.type.is_pyobject:
1424 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1425 else:
1426 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1428 class BackquoteNode(NewTempExprNode):
1429 # `expr`
1431 # arg ExprNode
1433 subexprs = ['arg']
1435 def analyse_types(self, env):
1436 self.arg.analyse_types(env)
1437 self.arg = self.arg.coerce_to_pyobject(env)
1438 self.type = py_object_type
1439 self.is_temp = 1
1441 gil_message = "Backquote expression"
1443 def calculate_constant_result(self):
1444 self.constant_result = repr(self.arg.constant_result)
1446 def generate_result_code(self, code):
1447 code.putln(
1448 "%s = PyObject_Repr(%s); %s" % (
1449 self.result(),
1450 self.arg.py_result(),
1451 code.error_goto_if_null(self.result(), self.pos)))
1452 code.put_gotref(self.py_result())
1456 class ImportNode(NewTempExprNode):
1457 # Used as part of import statement implementation.
1458 # Implements result =
1459 # __import__(module_name, globals(), None, name_list)
1461 # module_name IdentifierStringNode dotted name of module
1462 # name_list ListNode or None list of names to be imported
1464 subexprs = ['module_name', 'name_list']
1466 def analyse_types(self, env):
1467 self.module_name.analyse_types(env)
1468 self.module_name = self.module_name.coerce_to_pyobject(env)
1469 if self.name_list:
1470 self.name_list.analyse_types(env)
1471 self.name_list.coerce_to_pyobject(env)
1472 self.type = py_object_type
1473 self.is_temp = 1
1474 env.use_utility_code(import_utility_code)
1476 gil_message = "Python import"
1478 def generate_result_code(self, code):
1479 if self.name_list:
1480 name_list_code = self.name_list.py_result()
1481 else:
1482 name_list_code = "0"
1483 code.putln(
1484 "%s = __Pyx_Import(%s, %s); %s" % (
1485 self.result(),
1486 self.module_name.py_result(),
1487 name_list_code,
1488 code.error_goto_if_null(self.result(), self.pos)))
1489 code.put_gotref(self.py_result())
1492 class IteratorNode(NewTempExprNode):
1493 # Used as part of for statement implementation.
1495 # allocate_counter_temp/release_counter_temp needs to be called
1496 # by parent (ForInStatNode)
1498 # Implements result = iter(sequence)
1500 # sequence ExprNode
1502 subexprs = ['sequence']
1504 def analyse_types(self, env):
1505 self.sequence.analyse_types(env)
1506 self.sequence = self.sequence.coerce_to_pyobject(env)
1507 self.type = py_object_type
1508 self.is_temp = 1
1510 gil_message = "Iterating over Python object"
1512 def allocate_counter_temp(self, code):
1513 self.counter_cname = code.funcstate.allocate_temp(
1514 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1516 def release_counter_temp(self, code):
1517 code.funcstate.release_temp(self.counter_cname)
1519 def generate_result_code(self, code):
1520 is_builtin_sequence = self.sequence.type is list_type or \
1521 self.sequence.type is tuple_type
1522 if is_builtin_sequence:
1523 code.putln(
1524 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1525 else:
1526 code.putln(
1527 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1528 self.sequence.py_result(),
1529 self.sequence.py_result()))
1530 code.putln(
1531 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1532 self.counter_cname,
1533 self.result(),
1534 self.sequence.py_result(),
1535 self.result()))
1536 code.putln("} else {")
1537 if is_builtin_sequence:
1538 code.putln(
1539 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1540 code.error_goto(self.pos))
1541 else:
1542 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1543 self.counter_cname,
1544 self.result(),
1545 self.sequence.py_result(),
1546 code.error_goto_if_null(self.result(), self.pos)))
1547 code.put_gotref(self.py_result())
1548 code.putln("}")
1551 class NextNode(AtomicNewTempExprNode):
1552 # Used as part of for statement implementation.
1553 # Implements result = iterator.next()
1554 # Created during analyse_types phase.
1555 # The iterator is not owned by this node.
1557 # iterator ExprNode
1559 def __init__(self, iterator, env):
1560 self.pos = iterator.pos
1561 self.iterator = iterator
1562 self.type = py_object_type
1563 self.is_temp = 1
1565 def generate_result_code(self, code):
1566 if self.iterator.sequence.type is list_type:
1567 type_checks = [(list_type, "List")]
1568 elif self.iterator.sequence.type is tuple_type:
1569 type_checks = [(tuple_type, "Tuple")]
1570 else:
1571 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1573 for py_type, prefix in type_checks:
1574 if len(type_checks) > 1:
1575 code.putln(
1576 "if (likely(Py%s_CheckExact(%s))) {" % (
1577 prefix, self.iterator.py_result()))
1578 code.putln(
1579 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1580 self.iterator.counter_cname,
1581 prefix,
1582 self.iterator.py_result()))
1583 code.putln(
1584 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1585 self.result(),
1586 prefix,
1587 self.iterator.py_result(),
1588 self.iterator.counter_cname,
1589 self.result(),
1590 self.iterator.counter_cname))
1591 if len(type_checks) > 1:
1592 code.put("} else ")
1593 if len(type_checks) == 1:
1594 return
1595 code.putln("{")
1596 code.putln(
1597 "%s = PyIter_Next(%s);" % (
1598 self.result(),
1599 self.iterator.py_result()))
1600 code.putln(
1601 "if (!%s) {" %
1602 self.result())
1603 code.putln(code.error_goto_if_PyErr(self.pos))
1604 code.putln("break;")
1605 code.putln("}")
1606 code.put_gotref(self.py_result())
1607 code.putln("}")
1610 class ExcValueNode(AtomicNewTempExprNode):
1611 # Node created during analyse_types phase
1612 # of an ExceptClauseNode to fetch the current
1613 # exception value.
1615 def __init__(self, pos, env, var):
1616 ExprNode.__init__(self, pos)
1617 self.type = py_object_type
1618 self.var = var
1620 def calculate_result_code(self):
1621 return self.var
1623 def generate_result_code(self, code):
1624 pass
1626 def analyse_types(self, env):
1627 pass
1630 class TempNode(ExprNode):
1631 # Node created during analyse_types phase
1632 # of some nodes to hold a temporary value.
1634 subexprs = []
1636 def __init__(self, pos, type, env):
1637 ExprNode.__init__(self, pos)
1638 self.type = type
1639 if type.is_pyobject:
1640 self.result_ctype = py_object_type
1641 self.is_temp = 1
1643 def analyse_types(self, env):
1644 return self.type
1646 def generate_result_code(self, code):
1647 pass
1650 class PyTempNode(TempNode):
1651 # TempNode holding a Python value.
1653 def __init__(self, pos, env):
1654 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1657 #-------------------------------------------------------------------
1659 # Trailer nodes
1661 #-------------------------------------------------------------------
1663 class IndexNode(NewTempExprNode):
1664 # Sequence indexing.
1666 # base ExprNode
1667 # index ExprNode
1668 # indices [ExprNode]
1669 # is_buffer_access boolean Whether this is a buffer access.
1671 # indices is used on buffer access, index on non-buffer access.
1672 # The former contains a clean list of index parameters, the
1673 # latter whatever Python object is needed for index access.
1675 subexprs = ['base', 'index', 'indices']
1676 indices = None
1678 def __init__(self, pos, index, *args, **kw):
1679 ExprNode.__init__(self, pos, index=index, *args, **kw)
1680 self._index = index
1682 def calculate_constant_result(self):
1683 self.constant_result = \
1684 self.base.constant_result[self.index.constant_result]
1686 def compile_time_value(self, denv):
1687 base = self.base.compile_time_value(denv)
1688 index = self.index.compile_time_value(denv)
1689 try:
1690 return base[index]
1691 except Exception, e:
1692 self.compile_time_value_error(e)
1694 def is_ephemeral(self):
1695 return self.base.is_ephemeral()
1697 def analyse_target_declaration(self, env):
1698 pass
1700 def analyse_as_type(self, env):
1701 base_type = self.base.analyse_as_type(env)
1702 if base_type and not base_type.is_pyobject:
1703 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1704 return None
1706 def analyse_types(self, env):
1707 self.analyse_base_and_index_types(env, getting = 1)
1709 def analyse_target_types(self, env):
1710 self.analyse_base_and_index_types(env, setting = 1)
1712 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1713 # Note: This might be cleaned up by having IndexNode
1714 # parsed in a saner way and only construct the tuple if
1715 # needed.
1717 # Note that this function must leave IndexNode in a cloneable state.
1718 # For buffers, self.index is packed out on the initial analysis, and
1719 # when cloning self.indices is copied.
1720 self.is_buffer_access = False
1722 self.base.analyse_types(env)
1723 # Handle the case where base is a literal char* (and we expect a string, not an int)
1724 if isinstance(self.base, StringNode):
1725 self.base = self.base.coerce_to_pyobject(env)
1727 skip_child_analysis = False
1728 buffer_access = False
1729 if self.base.type.is_buffer:
1730 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1731 if self.indices:
1732 indices = self.indices
1733 else:
1734 # On cloning, indices is cloned. Otherwise, unpack index into indices
1735 assert not isinstance(self.index, CloneNode)
1736 if isinstance(self.index, TupleNode):
1737 indices = self.index.args
1738 else:
1739 indices = [self.index]
1740 if len(indices) == self.base.type.ndim:
1741 buffer_access = True
1742 skip_child_analysis = True
1743 for x in indices:
1744 x.analyse_types(env)
1745 if not x.type.is_int:
1746 buffer_access = False
1748 if buffer_access:
1749 self.indices = indices
1750 self.index = None
1751 self.type = self.base.type.dtype
1752 self.is_buffer_access = True
1753 self.buffer_type = self.base.entry.type
1755 if getting and self.type.is_pyobject:
1756 self.is_temp = True
1757 if setting:
1758 if not self.base.entry.type.writable:
1759 error(self.pos, "Writing to readonly buffer")
1760 else:
1761 self.base.entry.buffer_aux.writable_needed = True
1762 else:
1763 if isinstance(self.index, TupleNode):
1764 self.index.analyse_types(env, skip_children=skip_child_analysis)
1765 elif not skip_child_analysis:
1766 self.index.analyse_types(env)
1767 self.original_index_type = self.index.type
1768 if self.base.type.is_pyobject:
1769 if self.index.type.is_int:
1770 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1771 else:
1772 self.index = self.index.coerce_to_pyobject(env)
1773 self.type = py_object_type
1774 self.is_temp = 1
1775 else:
1776 if self.base.type.is_ptr or self.base.type.is_array:
1777 self.type = self.base.type.base_type
1778 else:
1779 error(self.pos,
1780 "Attempting to index non-array type '%s'" %
1781 self.base.type)
1782 self.type = PyrexTypes.error_type
1783 if self.index.type.is_pyobject:
1784 self.index = self.index.coerce_to(
1785 PyrexTypes.c_py_ssize_t_type, env)
1786 if not self.index.type.is_int:
1787 error(self.pos,
1788 "Invalid index type '%s'" %
1789 self.index.type)
1791 def gil_check(self, env):
1792 if not self.is_buffer_access:
1793 if self.base.type.is_pyobject:
1794 self._gil_check(env)
1796 gil_message = "Indexing Python object"
1798 def check_const_addr(self):
1799 self.base.check_const_addr()
1800 self.index.check_const()
1802 def is_lvalue(self):
1803 return 1
1805 def calculate_result_code(self):
1806 if self.is_buffer_access:
1807 return "(*%s)" % self.buffer_ptr_code
1808 else:
1809 return "(%s[%s])" % (
1810 self.base.result(), self.index.result())
1812 def extra_index_params(self):
1813 if self.index.type.is_int:
1814 if self.original_index_type.signed:
1815 size_adjustment = ""
1816 else:
1817 size_adjustment = "+1"
1818 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1819 else:
1820 return ""
1822 def generate_subexpr_evaluation_code(self, code):
1823 self.base.generate_evaluation_code(code)
1824 if not self.indices:
1825 self.index.generate_evaluation_code(code)
1826 else:
1827 for i in self.indices:
1828 i.generate_evaluation_code(code)
1830 def generate_subexpr_disposal_code(self, code):
1831 self.base.generate_disposal_code(code)
1832 if not self.indices:
1833 self.index.generate_disposal_code(code)
1834 else:
1835 for i in self.indices:
1836 i.generate_disposal_code(code)
1838 def free_subexpr_temps(self, code):
1839 self.base.free_temps(code)
1840 if not self.indices:
1841 self.index.free_temps(code)
1842 else:
1843 for i in self.indices:
1844 i.free_temps(code)
1846 def generate_result_code(self, code):
1847 if self.is_buffer_access:
1848 if code.globalstate.directives['nonecheck']:
1849 self.put_nonecheck(code)
1850 self.buffer_ptr_code = self.buffer_lookup_code(code)
1851 if self.type.is_pyobject:
1852 # is_temp is True, so must pull out value and incref it.
1853 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1854 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1855 elif self.type.is_pyobject:
1856 if self.index.type.is_int:
1857 index_code = self.index.result()
1858 if self.base.type is list_type:
1859 function = "__Pyx_GetItemInt_List"
1860 elif self.base.type is tuple_type:
1861 function = "__Pyx_GetItemInt_Tuple"
1862 else:
1863 function = "__Pyx_GetItemInt"
1864 code.globalstate.use_utility_code(getitem_int_utility_code)
1865 else:
1866 function = "PyObject_GetItem"
1867 index_code = self.index.py_result()
1868 sign_code = ""
1869 code.putln(
1870 "%s = %s(%s, %s%s); if (!%s) %s" % (
1871 self.result(),
1872 function,
1873 self.base.py_result(),
1874 index_code,
1875 self.extra_index_params(),
1876 self.result(),
1877 code.error_goto(self.pos)))
1878 code.put_gotref(self.py_result())
1880 def generate_setitem_code(self, value_code, code):
1881 if self.index.type.is_int:
1882 function = "__Pyx_SetItemInt"
1883 index_code = self.index.result()
1884 code.globalstate.use_utility_code(setitem_int_utility_code)
1885 else:
1886 index_code = self.index.py_result()
1887 if self.base.type is dict_type:
1888 function = "PyDict_SetItem"
1889 elif self.base.type is list_type:
1890 function = "PyList_SetItem"
1891 # don't use PyTuple_SetItem(), as we'd normally get a
1892 # TypeError when changing a tuple, while PyTuple_SetItem()
1893 # would allow updates
1895 #elif self.base.type is tuple_type:
1896 # function = "PyTuple_SetItem"
1897 else:
1898 function = "PyObject_SetItem"
1899 code.putln(
1900 "if (%s(%s, %s, %s%s) < 0) %s" % (
1901 function,
1902 self.base.py_result(),
1903 index_code,
1904 value_code,
1905 self.extra_index_params(),
1906 code.error_goto(self.pos)))
1908 def generate_buffer_setitem_code(self, rhs, code, op=""):
1909 # Used from generate_assignment_code and InPlaceAssignmentNode
1910 if code.globalstate.directives['nonecheck']:
1911 self.put_nonecheck(code)
1912 ptrexpr = self.buffer_lookup_code(code)
1913 if self.buffer_type.dtype.is_pyobject:
1914 # Must manage refcounts. Decref what is already there
1915 # and incref what we put in.
1916 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1917 rhs_code = rhs.result()
1918 code.putln("%s = %s;" % (ptr, ptrexpr))
1919 code.put_gotref("*%s" % ptr)
1920 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1921 ptr, rhs_code
1922 ))
1923 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1924 code.put_giveref("*%s" % ptr)
1925 code.funcstate.release_temp(ptr)
1926 else:
1927 # Simple case
1928 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1930 def generate_assignment_code(self, rhs, code):
1931 self.generate_subexpr_evaluation_code(code)
1932 if self.is_buffer_access:
1933 self.generate_buffer_setitem_code(rhs, code)
1934 elif self.type.is_pyobject:
1935 self.generate_setitem_code(rhs.py_result(), code)
1936 else:
1937 code.putln(
1938 "%s = %s;" % (
1939 self.result(), rhs.result()))
1940 self.generate_subexpr_disposal_code(code)
1941 self.free_subexpr_temps(code)
1942 rhs.generate_disposal_code(code)
1943 rhs.free_temps(code)
1945 def generate_deletion_code(self, code):
1946 self.generate_subexpr_evaluation_code(code)
1947 #if self.type.is_pyobject:
1948 if self.index.type.is_int:
1949 function = "__Pyx_DelItemInt"
1950 index_code = self.index.result()
1951 code.globalstate.use_utility_code(delitem_int_utility_code)
1952 else:
1953 index_code = self.index.py_result()
1954 if self.base.type is dict_type:
1955 function = "PyDict_DelItem"
1956 else:
1957 function = "PyObject_DelItem"
1958 code.putln(
1959 "if (%s(%s, %s%s) < 0) %s" % (
1960 function,
1961 self.base.py_result(),
1962 index_code,
1963 self.extra_index_params(),
1964 code.error_goto(self.pos)))
1965 self.generate_subexpr_disposal_code(code)
1966 self.free_subexpr_temps(code)
1968 def buffer_lookup_code(self, code):
1969 # Assign indices to temps
1970 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1971 for temp, index in zip(index_temps, self.indices):
1972 code.putln("%s = %s;" % (temp, index.result()))
1973 # Generate buffer access code using these temps
1974 import Buffer
1975 # The above could happen because child_attrs is wrong somewhere so that
1976 # options are not propagated.
1977 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1978 index_signeds=[i.type.signed for i in self.indices],
1979 index_cnames=index_temps,
1980 options=code.globalstate.directives,
1981 pos=self.pos, code=code)
1983 def put_nonecheck(self, code):
1984 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1985 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1986 code.putln("__Pyx_RaiseNoneIndexingError();")
1987 code.putln(code.error_goto(self.pos))
1988 code.putln("}")
1990 class SliceIndexNode(NewTempExprNode):
1991 # 2-element slice indexing
1993 # base ExprNode
1994 # start ExprNode or None
1995 # stop ExprNode or None
1997 subexprs = ['base', 'start', 'stop']
1999 def calculate_constant_result(self):
2000 self.constant_result = self.base.constant_result[
2001 self.start.constant_result : self.stop.constant_result]
2003 def compile_time_value(self, denv):
2004 base = self.base.compile_time_value(denv)
2005 if self.start is None:
2006 start = 0
2007 else:
2008 start = self.start.compile_time_value(denv)
2009 if self.stop is None:
2010 stop = None
2011 else:
2012 stop = self.stop.compile_time_value(denv)
2013 try:
2014 return base[start:stop]
2015 except Exception, e:
2016 self.compile_time_value_error(e)
2018 def analyse_target_declaration(self, env):
2019 pass
2021 def analyse_types(self, env):
2022 self.base.analyse_types(env)
2023 if self.start:
2024 self.start.analyse_types(env)
2025 if self.stop:
2026 self.stop.analyse_types(env)
2027 if self.base.type.is_string:
2028 self.type = py_object_type
2029 elif self.base.type.is_array or self.base.type.is_ptr:
2030 # we need a ptr type here instead of an array type, as
2031 # array types can result in invalid type casts in the C
2032 # code
2033 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
2034 else:
2035 self.base = self.base.coerce_to_pyobject(env)
2036 self.type = py_object_type
2037 c_int = PyrexTypes.c_py_ssize_t_type
2038 if self.start:
2039 self.start = self.start.coerce_to(c_int, env)
2040 if self.stop:
2041 self.stop = self.stop.coerce_to(c_int, env)
2042 self.is_temp = 1
2044 gil_check = ExprNode._gil_check
2045 gil_message = "Slicing Python object"
2047 def generate_result_code(self, code):
2048 if not self.type.is_pyobject:
2049 error(self.pos,
2050 "Slicing is not currently supported for '%s'." % self.type)
2051 return
2052 if self.base.type.is_string:
2053 if self.stop is None:
2054 code.putln(
2055 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2056 self.result(),
2057 self.base.result(),
2058 self.start_code(),
2059 code.error_goto_if_null(self.result(), self.pos)))
2060 else:
2061 code.putln(
2062 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2063 self.result(),
2064 self.base.result(),
2065 self.start_code(),
2066 self.stop_code(),
2067 self.start_code(),
2068 code.error_goto_if_null(self.result(), self.pos)))
2069 else:
2070 code.putln(
2071 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2072 self.result(),
2073 self.base.py_result(),
2074 self.start_code(),
2075 self.stop_code(),
2076 code.error_goto_if_null(self.result(), self.pos)))
2077 code.put_gotref(self.py_result())
2079 def generate_assignment_code(self, rhs, code):
2080 self.generate_subexpr_evaluation_code(code)
2081 if self.type.is_pyobject:
2082 code.put_error_if_neg(self.pos,
2083 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2084 self.base.py_result(),
2085 self.start_code(),
2086 self.stop_code(),
2087 rhs.result()))
2088 else:
2089 start_offset = ''
2090 if self.start:
2091 start_offset = self.start_code()
2092 if start_offset == '0':
2093 start_offset = ''
2094 else:
2095 start_offset += '+'
2096 if rhs.type.is_array:
2097 array_length = rhs.type.size
2098 self.generate_slice_guard_code(code, array_length)
2099 else:
2100 error("Slice assignments from pointers are not yet supported.")
2101 # FIXME: fix the array size according to start/stop
2102 array_length = self.base.type.size
2103 for i in range(array_length):
2104 code.putln("%s[%s%s] = %s[%d];" % (
2105 self.base.result(), start_offset, i,
2106 rhs.result(), i))
2107 self.generate_subexpr_disposal_code(code)
2108 self.free_subexpr_temps(code)
2109 rhs.generate_disposal_code(code)
2110 rhs.free_temps(code)
2112 def generate_deletion_code(self, code):
2113 if not self.base.type.is_pyobject:
2114 error(self.pos,
2115 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2116 return
2117 self.generate_subexpr_evaluation_code(code)
2118 code.put_error_if_neg(self.pos,
2119 "PySequence_DelSlice(%s, %s, %s)" % (
2120 self.base.py_result(),
2121 self.start_code(),
2122 self.stop_code()))
2123 self.generate_subexpr_disposal_code(code)
2125 def generate_slice_guard_code(self, code, target_size):
2126 if not self.base.type.is_array:
2127 return
2128 slice_size = self.base.type.size
2129 start = stop = None
2130 if self.stop:
2131 stop = self.stop.result()
2132 try:
2133 stop = int(stop)
2134 if stop < 0:
2135 slice_size = self.base.type.size + stop
2136 else:
2137 slice_size = stop
2138 stop = None
2139 except ValueError:
2140 pass
2141 if self.start:
2142 start = self.start.result()
2143 try:
2144 start = int(start)
2145 if start < 0:
2146 start = self.base.type.size + start
2147 slice_size -= start
2148 start = None
2149 except ValueError:
2150 pass
2151 check = None
2152 if slice_size < 0:
2153 if target_size > 0:
2154 error(self.pos, "Assignment to empty slice.")
2155 elif start is None and stop is None:
2156 # we know the exact slice length
2157 if target_size != slice_size:
2158 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2159 slice_size, target_size))
2160 elif start is not None:
2161 if stop is None:
2162 stop = slice_size
2163 check = "(%s)-(%s)" % (stop, start)
2164 else: # stop is not None:
2165 check = stop
2166 if check:
2167 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2168 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2169 target_size, check))
2170 code.putln(code.error_goto(self.pos))
2171 code.putln("}")
2173 def start_code(self):
2174 if self.start:
2175 return self.start.result()
2176 else:
2177 return "0"
2179 def stop_code(self):
2180 if self.stop:
2181 return self.stop.result()
2182 elif self.base.type.is_array:
2183 return self.base.type.size
2184 else:
2185 return "PY_SSIZE_T_MAX"
2187 def calculate_result_code(self):
2188 # self.result() is not used, but this method must exist
2189 return "<unused>"
2192 class SliceNode(NewTempExprNode):
2193 # start:stop:step in subscript list
2195 # start ExprNode
2196 # stop ExprNode
2197 # step ExprNode
2199 def calculate_constant_result(self):
2200 self.constant_result = self.base.constant_result[
2201 self.start.constant_result : \
2202 self.stop.constant_result : \
2203 self.step.constant_result]
2205 def compile_time_value(self, denv):
2206 start = self.start.compile_time_value(denv)
2207 if self.stop is None:
2208 stop = None
2209 else:
2210 stop = self.stop.compile_time_value(denv)
2211 if self.step is None:
2212 step = None
2213 else:
2214 step = self.step.compile_time_value(denv)
2215 try:
2216 return slice(start, stop, step)
2217 except Exception, e:
2218 self.compile_time_value_error(e)
2220 subexprs = ['start', 'stop', 'step']
2222 def analyse_types(self, env):
2223 self.start.analyse_types(env)
2224 self.stop.analyse_types(env)
2225 self.step.analyse_types(env)
2226 self.start = self.start.coerce_to_pyobject(env)
2227 self.stop = self.stop.coerce_to_pyobject(env)
2228 self.step = self.step.coerce_to_pyobject(env)
2229 self.type = py_object_type
2230 self.is_temp = 1
2232 gil_message = "Constructing Python slice object"
2234 def generate_result_code(self, code):
2235 code.putln(
2236 "%s = PySlice_New(%s, %s, %s); %s" % (
2237 self.result(),
2238 self.start.py_result(),
2239 self.stop.py_result(),
2240 self.step.py_result(),
2241 code.error_goto_if_null(self.result(), self.pos)))
2242 code.put_gotref(self.py_result())
2245 class CallNode(NewTempExprNode):
2246 def analyse_as_type_constructor(self, env):
2247 type = self.function.analyse_as_type(env)
2248 if type and type.is_struct_or_union:
2249 args, kwds = self.explicit_args_kwds()
2250 items = []
2251 for arg, member in zip(args, type.scope.var_entries):
2252 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2253 if kwds:
2254 items += kwds.key_value_pairs
2255 self.key_value_pairs = items
2256 self.__class__ = DictNode
2257 self.analyse_types(env)
2258 self.coerce_to(type, env)
2259 return True
2261 def gil_check(self, env):
2262 func_type = self.function_type()
2263 if func_type.is_pyobject:
2264 self._gil_check(env)
2265 elif not getattr(func_type, 'nogil', False):
2266 self._gil_check(env)
2268 gil_message = "Calling gil-requiring function"
2271 class SimpleCallNode(CallNode):
2272 # Function call without keyword, * or ** args.
2274 # function ExprNode
2275 # args [ExprNode]
2276 # arg_tuple ExprNode or None used internally
2277 # self ExprNode or None used internally
2278 # coerced_self ExprNode or None used internally
2279 # wrapper_call bool used internally
2280 # has_optional_args bool used internally
2282 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2284 self = None
2285 coerced_self = None
2286 arg_tuple = None
2287 wrapper_call = False
2288 has_optional_args = False
2290 def compile_time_value(self, denv):
2291 function = self.function.compile_time_value(denv)
2292 args = [arg.compile_time_value(denv) for arg in self.args]
2293 try:
2294 return function(*args)
2295 except Exception, e:
2296 self.compile_time_value_error(e)
2298 def analyse_as_type(self, env):
2299 attr = self.function.as_cython_attribute()
2300 if attr == 'pointer':
2301 if len(self.args) != 1:
2302 error(self.args.pos, "only one type allowed.")
2303 else:
2304 type = self.args[0].analyse_as_type(env)
2305 if not type:
2306 error(self.args[0].pos, "Unknown type")
2307 else:
2308 return PyrexTypes.CPtrType(type)
2310 def explicit_args_kwds(self):
2311 return self.args, None
2313 def analyse_types(self, env):
2314 if self.analyse_as_type_constructor(env):
2315 return
2316 function = self.function
2317 function.is_called = 1
2318 self.function.analyse_types(env)
2319 if function.is_attribute and function.entry and function.entry.is_cmethod:
2320 # Take ownership of the object from which the attribute
2321 # was obtained, because we need to pass it as 'self'.
2322 self.self = function.obj
2323 function.obj = CloneNode(self.self)
2324 func_type = self.function_type()
2325 if func_type.is_pyobject:
2326 self.arg_tuple = TupleNode(self.pos, args = self.args)
2327 self.arg_tuple.analyse_types(env)
2328 self.args = None
2329 if function.is_name and function.type_entry:
2330 # We are calling an extension type constructor. As
2331 # long as we do not support __new__(), the result type
2332 # is clear
2333 self.type = function.type_entry.type
2334 self.result_ctype = py_object_type
2335 else:
2336 self.type = py_object_type
2337 self.is_temp = 1
2338 else:
2339 for arg in self.args:
2340 arg.analyse_types(env)
2341 if self.self and func_type.args:
2342 # Coerce 'self' to the type expected by the method.
2343 expected_type = func_type.args[0].type
2344 self.coerced_self = CloneNode(self.self).coerce_to(
2345 expected_type, env)
2346 # Insert coerced 'self' argument into argument list.
2347 self.args.insert(0, self.coerced_self)
2348 self.analyse_c_function_call(env)
2350 def function_type(self):
2351 # Return the type of the function being called, coercing a function
2352 # pointer to a function if necessary.
2353 func_type = self.function.type
2354 if func_type.is_ptr:
2355 func_type = func_type.base_type
2356 return func_type
2358 def analyse_c_function_call(self, env):
2359 func_type = self.function_type()
2360 # Check function type
2361 if not func_type.is_cfunction:
2362 if not func_type.is_error:
2363 error(self.pos, "Calling non-function type '%s'" %
2364 func_type)
2365 self.type = PyrexTypes.error_type
2366 self.result_code = "<error>"
2367 return
2368 # Check no. of args
2369 max_nargs = len(func_type.args)
2370 expected_nargs = max_nargs - func_type.optional_arg_count
2371 actual_nargs = len(self.args)
2372 if actual_nargs < expected_nargs \
2373 or (not func_type.has_varargs and actual_nargs > max_nargs):
2374 expected_str = str(expected_nargs)
2375 if func_type.has_varargs:
2376 expected_str = "at least " + expected_str
2377 elif func_type.optional_arg_count:
2378 if actual_nargs < max_nargs:
2379 expected_str = "at least " + expected_str
2380 else:
2381 expected_str = "at most " + str(max_nargs)
2382 error(self.pos,
2383 "Call with wrong number of arguments (expected %s, got %s)"
2384 % (expected_str, actual_nargs))
2385 self.args = None
2386 self.type = PyrexTypes.error_type
2387 self.result_code = "<error>"
2388 return
2389 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2390 self.has_optional_args = 1
2391 self.is_temp = 1
2392 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2393 env.release_temp(self.opt_arg_struct)
2394 # Coerce arguments
2395 for i in range(min(max_nargs, actual_nargs)):
2396 formal_type = func_type.args[i].type
2397 self.args[i] = self.args[i].coerce_to(formal_type, env)
2398 for i in range(max_nargs, actual_nargs):
2399 if self.args[i].type.is_pyobject:
2400 error(self.args[i].pos,
2401 "Python object cannot be passed as a varargs parameter")
2402 # Calc result type and code fragment
2403 self.type = func_type.return_type
2404 if self.type.is_pyobject:
2405 self.result_ctype = py_object_type
2406 self.is_temp = 1
2407 elif func_type.exception_value is not None \
2408 or func_type.exception_check:
2409 self.is_temp = 1
2410 # C++ exception handler
2411 if func_type.exception_check == '+':
2412 if func_type.exception_value is None:
2413 env.use_utility_code(cpp_exception_utility_code)
2415 def calculate_result_code(self):
2416 return self.c_call_code()
2418 def c_call_code(self):
2419 func_type = self.function_type()
2420 if self.args is None or not func_type.is_cfunction:
2421 return "<error>"
2422 formal_args = func_type.args
2423 arg_list_code = []
2424 args = zip(formal_args, self.args)
2425 max_nargs = len(func_type.args)
2426 expected_nargs = max_nargs - func_type.optional_arg_count
2427 actual_nargs = len(self.args)
2428 for formal_arg, actual_arg in args[:expected_nargs]:
2429 arg_code = actual_arg.result_as(formal_arg.type)
2430 arg_list_code.append(arg_code)
2432 if func_type.is_overridable:
2433 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2435 if func_type.optional_arg_count:
2436 if expected_nargs == actual_nargs:
2437 optional_args = 'NULL'
2438 else:
2439 optional_args = "&%s" % self.opt_arg_struct
2440 arg_list_code.append(optional_args)
2442 for actual_arg in self.args[len(formal_args):]:
2443 arg_list_code.append(actual_arg.result())
2444 result = "%s(%s)" % (self.function.result(),
2445 ', '.join(arg_list_code))
2446 # if self.wrapper_call or \
2447 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2448 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2449 return result
2451 def generate_result_code(self, code):
2452 func_type = self.function_type()
2453 if func_type.is_pyobject:
2454 arg_code = self.arg_tuple.py_result()
2455 code.putln(
2456 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2457 self.result(),
2458 self.function.py_result(),
2459 arg_code,
2460 code.error_goto_if_null(self.result(), self.pos)))
2461 code.put_gotref(self.py_result())
2462 elif func_type.is_cfunction:
2463 if self.has_optional_args:
2464 actual_nargs = len(self.args)
2465 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2466 code.putln("%s.%s = %s;" % (
2467 self.opt_arg_struct,
2468 Naming.pyrex_prefix + "n",
2469 len(self.args) - expected_nargs))
2470 args = zip(func_type.args, self.args)
2471 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2472 code.putln("%s.%s = %s;" % (
2473 self.opt_arg_struct,
2474 formal_arg.name,
2475 actual_arg.result_as(formal_arg.type)))
2476 exc_checks = []
2477 if self.type.is_pyobject:
2478 exc_checks.append("!%s" % self.result())
2479 else:
2480 exc_val = func_type.exception_value
2481 exc_check = func_type.exception_check
2482 if exc_val is not None:
2483 exc_checks.append("%s == %s" % (self.result(), exc_val))
2484 if exc_check:
2485 exc_checks.append("PyErr_Occurred()")
2486 if self.is_temp or exc_checks:
2487 rhs = self.c_call_code()
2488 if self.result():
2489 lhs = "%s = " % self.result()
2490 if self.is_temp and self.type.is_pyobject:
2491 #return_type = self.type # func_type.return_type
2492 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2493 # "from", return_type, "to pyobject" ###
2494 rhs = typecast(py_object_type, self.type, rhs)
2495 else:
2496 lhs = ""
2497 if func_type.exception_check == '+':
2498 if func_type.exception_value is None:
2499 raise_py_exception = "__Pyx_CppExn2PyErr()"
2500 elif func_type.exception_value.type.is_pyobject:
2501 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2502 else:
2503 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2504 code.putln(
2505 "try {%s%s;} catch(...) {%s; %s}" % (
2506 lhs,
2507 rhs,
2508 raise_py_exception,
2509 code.error_goto(self.pos)))
2510 else:
2511 if exc_checks:
2512 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2513 else:
2514 goto_error = ""
2515 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2516 if self.type.is_pyobject and self.result():
2517 code.put_gotref(self.py_result())
2520 class PythonCapiFunctionNode(ExprNode):
2521 subexprs = []
2522 def __init__(self, pos, name, func_type, utility_code = None):
2523 self.pos = pos
2524 self.name = name
2525 self.type = func_type
2526 self.utility_code = utility_code
2528 def generate_result_code(self, code):
2529 if self.utility_code:
2530 code.globalstate.use_utility_code(self.utility_code)
2532 def calculate_result_code(self):
2533 return self.name
2535 class PythonCapiCallNode(SimpleCallNode):
2536 # Python C-API Function call (only created in transforms)
2538 def __init__(self, pos, function_name, func_type,
2539 utility_code = None, **kwargs):
2540 self.type = func_type.return_type
2541 self.result_ctype = self.type
2542 self.function = PythonCapiFunctionNode(
2543 pos, function_name, func_type,
2544 utility_code = utility_code)
2545 # call this last so that we can override the constructed
2546 # attributes above with explicit keyword arguments if required
2547 SimpleCallNode.__init__(self, pos, **kwargs)
2550 class GeneralCallNode(CallNode):
2551 # General Python function call, including keyword,
2552 # * and ** arguments.
2554 # function ExprNode
2555 # positional_args ExprNode Tuple of positional arguments
2556 # keyword_args ExprNode or None Dict of keyword arguments
2557 # starstar_arg ExprNode or None Dict of extra keyword args
2559 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2561 gil_check = CallNode._gil_check
2563 def compile_time_value(self, denv):
2564 function = self.function.compile_time_value(denv)
2565 positional_args = self.positional_args.compile_time_value(denv)
2566 keyword_args = self.keyword_args.compile_time_value(denv)
2567 starstar_arg = self.starstar_arg.compile_time_value(denv)
2568 try:
2569 keyword_args.update(starstar_arg)
2570 return function(*positional_args, **keyword_args)
2571 except Exception, e:
2572 self.compile_time_value_error(e)
2574 def explicit_args_kwds(self):
2575 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2576 raise PostParseError(self.pos,
2577 'Compile-time keyword arguments must be explicit.')
2578 return self.positional_args.args, self.keyword_args
2580 def analyse_types(self, env):
2581 if self.analyse_as_type_constructor(env):
2582 return
2583 self.function.analyse_types(env)
2584 self.positional_args.analyse_types(env)
2585 if self.keyword_args:
2586 self.keyword_args.analyse_types(env)
2587 if self.starstar_arg:
2588 self.starstar_arg.analyse_types(env)
2589 if not self.function.type.is_pyobject:
2590 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2591 error(self.pos, "Keyword arguments not allowed in cdef functions.")
2592 else:
2593 self.function = self.function.coerce_to_pyobject(env)
2594 self.positional_args = \
2595 self.positional_args.coerce_to_pyobject(env)
2596 if self.starstar_arg:
2597 self.starstar_arg = \
2598 self.starstar_arg.coerce_to_pyobject(env)
2599 function = self.function
2600 if function.is_name and function.type_entry:
2601 # We are calling an extension type constructor. As long
2602 # as we do not support __new__(), the result type is clear
2603 self.type = function.type_entry.type
2604 self.result_ctype = py_object_type
2605 else:
2606 self.type = py_object_type
2607 self.is_temp = 1
2609 def generate_result_code(self, code):
2610 if self.keyword_args and self.starstar_arg:
2611 code.put_error_if_neg(self.pos,
2612 "PyDict_Update(%s, %s)" % (
2613 self.keyword_args.py_result(),
2614 self.starstar_arg.py_result()))
2615 keyword_code = self.keyword_args.py_result()
2616 elif self.keyword_args:
2617 keyword_code = self.keyword_args.py_result()
2618 elif self.starstar_arg:
2619 keyword_code = self.starstar_arg.py_result()
2620 else:
2621 keyword_code = None
2622 if not keyword_code:
2623 call_code = "PyObject_Call(%s, %s, NULL)" % (
2624 self.function.py_result(),
2625 self.positional_args.py_result())
2626 else:
2627 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2628 self.function.py_result(),
2629 self.positional_args.py_result(),
2630 keyword_code)
2631 code.putln(
2632 "%s = %s; %s" % (
2633 self.result(),
2634 call_code,
2635 code.error_goto_if_null(self.result(), self.pos)))
2636 code.put_gotref(self.py_result())
2639 class AsTupleNode(NewTempExprNode):
2640 # Convert argument to tuple. Used for normalising
2641 # the * argument of a function call.
2643 # arg ExprNode
2645 subexprs = ['arg']
2647 def calculate_constant_result(self):
2648 self.constant_result = tuple(self.base.constant_result)
2650 def compile_time_value(self, denv):
2651 arg = self.arg.compile_time_value(denv)
2652 try:
2653 return tuple(arg)
2654 except Exception, e:
2655 self.compile_time_value_error(e)
2657 def analyse_types(self, env):
2658 self.arg.analyse_types(env)
2659 self.arg = self.arg.coerce_to_pyobject(env)
2660 self.type = tuple_type
2661 self.is_temp = 1
2663 gil_check = ExprNode._gil_check
2664 gil_message = "Constructing Python tuple"
2666 def generate_result_code(self, code):
2667 code.putln(
2668 "%s = PySequence_Tuple(%s); %s" % (
2669 self.result(),
2670 self.arg.py_result(),
2671 code.error_goto_if_null(self.result(), self.pos)))
2672 code.put_gotref(self.py_result())
2675 class AttributeNode(NewTempExprNode):
2676 # obj.attribute
2678 # obj ExprNode
2679 # attribute string
2680 # needs_none_check boolean Used if obj is an extension type.
2681 # If set to True, it is known that the type is not None.
2683 # Used internally:
2685 # is_py_attr boolean Is a Python getattr operation
2686 # member string C name of struct member
2687 # is_called boolean Function call is being done on result
2688 # entry Entry Symbol table entry of attribute
2690 is_attribute = 1
2691 subexprs = ['obj']
2693 type = PyrexTypes.error_type
2694 entry = None
2695 is_called = 0
2696 needs_none_check = True
2698 def as_cython_attribute(self):
2699 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2700 return self.attribute
2702 def coerce_to(self, dst_type, env):
2703 # If coercing to a generic pyobject and this is a cpdef function
2704 # we can create the corresponding attribute
2705 if dst_type is py_object_type:
2706 entry = self.entry
2707 if entry and entry.is_cfunction and entry.as_variable:
2708 # must be a cpdef function
2709 self.is_temp = 1
2710 self.entry = entry.as_variable
2711 self.analyse_as_python_attribute(env)
2712 return self
2713 return ExprNode.coerce_to(self, dst_type, env)
2715 def calculate_constant_result(self):
2716 attr = self.attribute
2717 if attr.startswith("__") and attr.endswith("__"):
2718 return
2719 self.constant_result = getattr(self.obj.constant_result, attr)
2721 def compile_time_value(self, denv):
2722 attr = self.attribute
2723 if attr.startswith("__") and attr.endswith("__"):
2724 self.error("Invalid attribute name '%s' in compile-time expression"
2725 % attr)
2726 return None
2727 obj = self.obj.compile_time_value(denv)
2728 try:
2729 return getattr(obj, attr)
2730 except Exception, e:
2731 self.compile_time_value_error(e)
2733 def analyse_target_declaration(self, env):
2734 pass
2736 def analyse_target_types(self, env):
2737 self.analyse_types(env, target = 1)
2739 def analyse_types(self, env, target = 0):
2740 if self.analyse_as_cimported_attribute(env, target):
2741 return
2742 if not target and self.analyse_as_unbound_cmethod(env):
2743 return
2744 self.analyse_as_ordinary_attribute(env, target)
2746 def analyse_as_cimported_attribute(self, env, target):
2747 # Try to interpret this as a reference to an imported
2748 # C const, type, var or function. If successful, mutates
2749 # this node into a NameNode and returns 1, otherwise
2750 # returns 0.
2751 module_scope = self.obj.analyse_as_module(env)
2752 if module_scope:
2753 entry = module_scope.lookup_here(self.attribute)
2754 if entry and (
2755 entry.is_cglobal or entry.is_cfunction
2756 or entry.is_type or entry.is_const):
2757 self.mutate_into_name_node(env, entry, target)
2758 return 1
2759 return 0
2761 def analyse_as_unbound_cmethod(self, env):
2762 # Try to interpret this as a reference to an unbound
2763 # C method of an extension type. If successful, mutates
2764 # this node into a NameNode and returns 1, otherwise
2765 # returns 0.
2766 type = self.obj.analyse_as_extension_type(env)
2767 if type:
2768 entry = type.scope.lookup_here(self.attribute)
2769 if entry and entry.is_cmethod:
2770 # Create a temporary entry describing the C method
2771 # as an ordinary function.
2772 ubcm_entry = Symtab.Entry(entry.name,
2773 "%s->%s" % (type.vtabptr_cname, entry.cname),
2774 entry.type)
2775 ubcm_entry.is_cfunction = 1
2776 ubcm_entry.func_cname = entry.func_cname
2777 ubcm_entry.is_unbound_cmethod = 1
2778 self.mutate_into_name_node(env, ubcm_entry, None)
2779 return 1
2780 return 0
2782 def analyse_as_type(self, env):
2783 module_scope = self.obj.analyse_as_module(env)
2784 if module_scope:
2785 return module_scope.lookup_type(self.attribute)
2786 return None
2788 def analyse_as_extension_type(self, env):
2789 # Try to interpret this as a reference to an extension type
2790 # in a cimported module. Returns the extension type, or None.
2791 module_scope = self.obj.analyse_as_module(env)
2792 if module_scope:
2793 entry = module_scope.lookup_here(self.attribute)
2794 if entry and entry.is_type and entry.type.is_extension_type:
2795 return entry.type
2796 return None
2798 def analyse_as_module(self, env):
2799 # Try to interpret this as a reference to a cimported module
2800 # in another cimported module. Returns the module scope, or None.
2801 module_scope = self.obj.analyse_as_module(env)
2802 if module_scope:
2803 entry = module_scope.lookup_here(self.attribute)
2804 if entry and entry.as_module:
2805 return entry.as_module
2806 return None
2808 def mutate_into_name_node(self, env, entry, target):
2809 # Mutate this node into a NameNode and complete the
2810 # analyse_types phase.
2811 self.__class__ = NameNode
2812 self.name = self.attribute
2813 self.entry = entry
2814 del self.obj
2815 del self.attribute
2816 if target:
2817 NameNode.analyse_target_types(self, env)
2818 else:
2819 NameNode.analyse_rvalue_entry(self, env)
2821 def analyse_as_ordinary_attribute(self, env, target):
2822 self.obj.analyse_types(env)
2823 self.analyse_attribute(env)
2824 if self.entry and self.entry.is_cmethod and not self.is_called:
2825 # error(self.pos, "C method can only be called")
2826 pass
2827 ## Reference to C array turns into pointer to first element.
2828 #while self.type.is_array:
2829 # self.type = self.type.element_ptr_type()
2830 if self.is_py_attr:
2831 if not target:
2832 self.is_temp = 1
2833 self.result_ctype = py_object_type
2835 def analyse_attribute(self, env):
2836 # Look up attribute and set self.type and self.member.
2837 self.is_py_attr = 0
2838 self.member = self.attribute
2839 if self.obj.type.is_string:
2840 self.obj = self.obj.coerce_to_pyobject(env)
2841 obj_type = self.obj.type
2842 if obj_type.is_ptr or obj_type.is_array:
2843 obj_type = obj_type.base_type
2844 self.op = "->"
2845 elif obj_type.is_extension_type:
2846 self.op = "->"
2847 else:
2848 self.op = "."
2849 if obj_type.has_attributes:
2850 entry = None
2851 if obj_type.attributes_known():
2852 entry = obj_type.scope.lookup_here(self.attribute)
2853 if entry and entry.is_member:
2854 entry = None
2855 else:
2856 error(self.pos,
2857 "Cannot select attribute of incomplete type '%s'"
2858 % obj_type)
2859 self.type = PyrexTypes.error_type
2860 return
2861 self.entry = entry
2862 if entry:
2863 if obj_type.is_extension_type and entry.name == "__weakref__":
2864 error(self.pos, "Illegal use of special attribute __weakref__")
2865 # methods need the normal attribute lookup
2866 # because they do not have struct entries
2867 if entry.is_variable or entry.is_cmethod:
2868 self.type = entry.type
2869 self.member = entry.cname
2870 return
2871 else:
2872 # If it's not a variable or C method, it must be a Python
2873 # method of an extension type, so we treat it like a Python
2874 # attribute.
2875 pass
2876 # If we get here, the base object is not a struct/union/extension
2877 # type, or it is an extension type and the attribute is either not
2878 # declared or is declared as a Python method. Treat it as a Python
2879 # attribute reference.
2880 self.analyse_as_python_attribute(env)
2882 def analyse_as_python_attribute(self, env):
2883 obj_type = self.obj.type
2884 self.member = self.attribute
2885 if obj_type.is_pyobject:
2886 self.type = py_object_type
2887 self.is_py_attr = 1
2888 else:
2889 if not obj_type.is_error:
2890 error(self.pos,
2891 "Object of type '%s' has no attribute '%s'" %
2892 (obj_type, self.attribute))
2894 def gil_check(self, env):
2895 if self.is_py_attr:
2896 self._gil_check(env)
2898 gil_message = "Accessing Python attribute"
2900 def is_simple(self):
2901 if self.obj:
2902 return self.result_in_temp() or self.obj.is_simple()
2903 else:
2904 return NameNode.is_simple(self)
2906 def is_lvalue(self):
2907 if self.obj:
2908 return 1
2909 else:
2910 return NameNode.is_lvalue(self)
2912 def is_ephemeral(self):
2913 if self.obj:
2914 return self.obj.is_ephemeral()
2915 else:
2916 return NameNode.is_ephemeral(self)
2918 def calculate_result_code(self):
2919 #print "AttributeNode.calculate_result_code:", self.member ###
2920 #print "...obj node =", self.obj, "code", self.obj.result() ###
2921 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2922 obj = self.obj
2923 obj_code = obj.result_as(obj.type)
2924 #print "...obj_code =", obj_code ###
2925 if self.entry and self.entry.is_cmethod:
2926 if obj.type.is_extension_type:
2927 return "((struct %s *)%s%s%s)->%s" % (
2928 obj.type.vtabstruct_cname, obj_code, self.op,
2929 obj.type.vtabslot_cname, self.member)
2930 else:
2931 return self.member
2932 else:
2933 return "%s%s%s" % (obj_code, self.op, self.member)
2935 def generate_result_code(self, code):
2936 interned_attr_cname = code.intern_identifier(self.attribute)
2937 if self.is_py_attr:
2938 code.putln(
2939 '%s = PyObject_GetAttr(%s, %s); %s' % (
2940 self.result(),
2941 self.obj.py_result(),
2942 interned_attr_cname,
2943 code.error_goto_if_null(self.result(), self.pos)))
2944 code.put_gotref(self.py_result())
2945 else:
2946 # result_code contains what is needed, but we may need to insert
2947 # a check and raise an exception
2948 if (self.obj.type.is_extension_type
2949 and self.needs_none_check
2950 and code.globalstate.directives['nonecheck']):
2951 self.put_nonecheck(code)
2953 def generate_assignment_code(self, rhs, code):
2954 interned_attr_cname = code.intern_identifier(self.attribute)
2955 self.obj.generate_evaluation_code(code)
2956 if self.is_py_attr:
2957 code.put_error_if_neg(self.pos,
2958 'PyObject_SetAttr(%s, %s, %s)' % (
2959 self.obj.py_result(),
2960 interned_attr_cname,
2961 rhs.py_result()))
2962 rhs.generate_disposal_code(code)
2963 rhs.free_temps(code)
2964 else:
2965 if (self.obj.type.is_extension_type
2966 and self.needs_none_check
2967 and code.globalstate.directives['nonecheck']):
2968 self.put_nonecheck(code)
2970 select_code = self.result()
2971 if self.type.is_pyobject:
2972 rhs.make_owned_reference(code)
2973 code.put_giveref(rhs.py_result())
2974 code.put_gotref(select_code)
2975 code.put_decref(select_code, self.ctype())
2976 code.putln(
2977 "%s = %s;" % (
2978 select_code,
2979 rhs.result_as(self.ctype())))
2980 #rhs.result()))
2981 rhs.generate_post_assignment_code(code)
2982 rhs.free_temps(code)
2983 self.obj.generate_disposal_code(code)
2984 self.obj.free_temps(code)
2986 def generate_deletion_code(self, code):
2987 interned_attr_cname = code.intern_identifier(self.attribute)
2988 self.obj.generate_evaluation_code(code)
2989 if self.is_py_attr:
2990 code.put_error_if_neg(self.pos,
2991 'PyObject_DelAttr(%s, %s)' % (
2992 self.obj.py_result(),
2993 interned_attr_cname))
2994 else:
2995 error(self.pos, "Cannot delete C attribute of extension type")
2996 self.obj.generate_disposal_code(code)
2997 self.obj.free_temps(code)
2999 def annotate(self, code):
3000 if self.is_py_attr:
3001 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3002 else:
3003 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3005 def put_nonecheck(self, code):
3006 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3007 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3008 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
3009 code.putln(code.error_goto(self.pos))
3010 code.putln("}")
3013 #-------------------------------------------------------------------
3015 # Constructor nodes
3017 #-------------------------------------------------------------------
3019 class SequenceNode(NewTempExprNode):
3020 # Base class for list and tuple constructor nodes.
3021 # Contains common code for performing sequence unpacking.
3023 # args [ExprNode]
3024 # iterator ExprNode
3025 # unpacked_items [ExprNode] or None
3026 # coerced_unpacked_items [ExprNode] or None
3028 subexprs = ['args']
3030 is_sequence_constructor = 1
3031 unpacked_items = None
3033 def compile_time_value_list(self, denv):
3034 return [arg.compile_time_value(denv) for arg in self.args]
3036 def analyse_target_declaration(self, env):
3037 for arg in self.args:
3038 arg.analyse_target_declaration(env)
3040 def analyse_types(self, env, skip_children=False):
3041 for i in range(len(self.args)):
3042 arg = self.args[i]
3043 if not skip_children: arg.analyse_types(env)
3044 self.args[i] = arg.coerce_to_pyobject(env)
3045 self.type = py_object_type
3046 self.is_temp = 1
3048 def analyse_target_types(self, env):
3049 self.iterator = PyTempNode(self.pos, env)
3050 self.unpacked_items = []
3051 self.coerced_unpacked_items = []
3052 for arg in self.args:
3053 arg.analyse_target_types(env)
3054 unpacked_item = PyTempNode(self.pos, env)
3055 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3056 self.unpacked_items.append(unpacked_item)
3057 self.coerced_unpacked_items.append(coerced_unpacked_item)
3058 self.type = py_object_type
3059 env.use_utility_code(unpacking_utility_code)
3061 def allocate_target_temps(self, env, rhs):
3062 self.iterator.allocate_temps(env)
3063 for arg, node in zip(self.args, self.coerced_unpacked_items):
3064 node.allocate_temps(env)
3065 arg.allocate_target_temps(env, None)
3066 #arg.release_target_temp(env)
3067 #node.release_temp(env)
3068 if rhs:
3069 rhs.release_temp(env)
3070 self.iterator.release_temp(env)
3071 for node in self.coerced_unpacked_items:
3072 node.release_temp(env)
3074 # def release_target_temp(self, env):
3075 # #for arg in self.args:
3076 # # arg.release_target_temp(env)
3077 # #for node in self.coerced_unpacked_items:
3078 # # node.release_temp(env)
3079 # self.iterator.release_temp(env)
3081 def generate_result_code(self, code):
3082 self.generate_operation_code(code)
3084 def generate_assignment_code(self, rhs, code):
3085 # Need to work around the fact that generate_evaluation_code
3086 # allocates the temps in a rather hacky way -- the assignment
3087 # is evaluated twice, within each if-block.
3089 if rhs.type is tuple_type:
3090 tuple_check = "likely(%s != Py_None)"
3091 else:
3092 tuple_check = "PyTuple_CheckExact(%s)"
3093 code.putln(
3094 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3095 tuple_check % rhs.py_result(),
3096 rhs.py_result(),
3097 len(self.args)))
3098 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3099 for i in range(len(self.args)):
3100 item = self.unpacked_items[i]
3101 code.put(
3102 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3103 item.result(),
3104 i))
3105 code.put_incref(item.result(), item.ctype())
3106 value_node = self.coerced_unpacked_items[i]
3107 value_node.generate_evaluation_code(code)
3108 rhs.generate_disposal_code(code)
3110 for i in range(len(self.args)):
3111 self.args[i].generate_assignment_code(
3112 self.coerced_unpacked_items[i], code)
3114 code.putln("} else {")
3116 if rhs.type is tuple_type:
3117 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3118 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3119 rhs.py_result(), len(self.args)))
3120 code.putln(code.error_goto(self.pos))
3121 else:
3122 code.putln(
3123 "%s = PyObject_GetIter(%s); %s" % (
3124 self.iterator.result(),
3125 rhs.py_result(),
3126 code.error_goto_if_null(self.iterator.result(), self.pos)))
3127 code.put_gotref(self.iterator.py_result())
3128 rhs.generate_disposal_code(code)
3129 for i in range(len(self.args)):
3130 item = self.unpacked_items[i]
3131 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3132 self.iterator.py_result(), i)
3133 code.putln(
3134 "%s = %s; %s" % (
3135 item.result(),
3136 typecast(item.ctype(), py_object_type, unpack_code),
3137 code.error_goto_if_null(item.result(), self.pos)))
3138 code.put_gotref(item.py_result())
3139 value_node = self.coerced_unpacked_items[i]
3140 value_node.generate_evaluation_code(code)
3141 code.put_error_if_neg(self.pos,
3142 "__Pyx_EndUnpack(%s)" % (
3143 self.iterator.py_result()))
3144 if debug_disposal_code:
3145 print("UnpackNode.generate_assignment_code:")
3146 print("...generating disposal code for %s" % self.iterator)
3147 self.iterator.generate_disposal_code(code)
3148 self.iterator.free_temps(code)
3150 for i in range(len(self.args)):
3151 self.args[i].generate_assignment_code(
3152 self.coerced_unpacked_items[i], code)
3154 code.putln("}")
3155 rhs.free_temps(code)
3157 def annotate(self, code):
3158 for arg in self.args:
3159 arg.annotate(code)
3160 if self.unpacked_items:
3161 for arg in self.unpacked_items:
3162 arg.annotate(code)
3163 for arg in self.coerced_unpacked_items:
3164 arg.annotate(code)
3167 class TupleNode(SequenceNode):
3168 # Tuple constructor.
3170 gil_message = "Constructing Python tuple"
3172 def analyse_types(self, env, skip_children=False):
3173 if len(self.args) == 0:
3174 self.is_temp = 0
3175 self.is_literal = 1
3176 else:
3177 SequenceNode.analyse_types(self, env, skip_children)
3178 self.type = tuple_type
3180 def calculate_result_code(self):
3181 if len(self.args) > 0:
3182 error(self.pos, "Positive length tuples must be constructed.")
3183 else:
3184 return Naming.empty_tuple
3186 def calculate_constant_result(self):
3187 self.constant_result = tuple([
3188 arg.constant_result for arg in self.args])
3190 def compile_time_value(self, denv):
3191 values = self.compile_time_value_list(denv)
3192 try:
3193 return tuple(values)
3194 except Exception, e:
3195 self.compile_time_value_error(e)
3197 def generate_operation_code(self, code):
3198 if len(self.args) == 0:
3199 # result_code is Naming.empty_tuple
3200 return
3201 code.putln(
3202 "%s = PyTuple_New(%s); %s" % (
3203 self.result(),
3204 len(self.args),
3205 code.error_goto_if_null(self.result(), self.pos)))
3206 code.put_gotref(self.py_result())
3207 for i in range(len(self.args)):
3208 arg = self.args[i]
3209 if not arg.result_in_temp():
3210 code.put_incref(arg.result(), arg.ctype())
3211 code.putln(
3212 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3213 self.result(),
3214 i,
3215 arg.py_result()))
3216 code.put_giveref(arg.py_result())
3218 def generate_subexpr_disposal_code(self, code):
3219 # We call generate_post_assignment_code here instead
3220 # of generate_disposal_code, because values were stored
3221 # in the tuple using a reference-stealing operation.
3222 for arg in self.args:
3223 arg.generate_post_assignment_code(code)
3224 # Should NOT call free_temps -- this is invoked by the default
3225 # generate_evaluation_code which will do that.
3228 class ListNode(SequenceNode):
3229 # List constructor.
3231 # obj_conversion_errors [PyrexError] used internally
3232 # orignial_args [ExprNode] used internally
3234 gil_message = "Constructing Python list"
3236 def analyse_expressions(self, env):
3237 SequenceNode.analyse_expressions(self, env)
3238 self.coerce_to_pyobject(env)
3240 def analyse_types(self, env):
3241 hold_errors()
3242 self.original_args = list(self.args)
3243 SequenceNode.analyse_types(self, env)
3244 self.type = list_type
3245 self.obj_conversion_errors = held_errors()
3246 release_errors(ignore=True)
3248 def coerce_to(self, dst_type, env):
3249 if dst_type.is_pyobject:
3250 for err in self.obj_conversion_errors:
3251 report_error(err)
3252 self.obj_conversion_errors = []
3253 if not self.type.subtype_of(dst_type):
3254 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3255 elif dst_type.is_ptr:
3256 base_type = dst_type.base_type
3257 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3258 for i in range(len(self.original_args)):
3259 arg = self.args[i]
3260 if isinstance(arg, CoerceToPyTypeNode):
3261 arg = arg.arg
3262 self.args[i] = arg.coerce_to(base_type, env)
3263 elif dst_type.is_struct:
3264 if len(self.args) > len(dst_type.scope.var_entries):
3265 error(self.pos, "Too may members for '%s'" % dst_type)
3266 else:
3267 if len(self.args) < len(dst_type.scope.var_entries):
3268 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3269 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3270 if isinstance(arg, CoerceToPyTypeNode):
3271 arg = arg.arg
3272 self.args[i] = arg.coerce_to(member.type, env)
3273 self.type = dst_type
3274 else:
3275 self.type = error_type
3276 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3277 return self
3279 def release_temp(self, env):
3280 if self.type.is_array:
3281 # To be valid C++, we must allocate the memory on the stack
3282 # manually and be sure not to reuse it for something else.
3283 pass
3284 else:
3285 SequenceNode.release_temp(self, env)
3287 def calculate_constant_result(self):
3288 self.constant_result = [
3289 arg.constant_result for arg in self.args]
3291 def compile_time_value(self, denv):
3292 return self.compile_time_value_list(denv)
3294 def generate_operation_code(self, code):
3295 if self.type.is_pyobject:
3296 for err in self.obj_conversion_errors:
3297 report_error(err)
3298 code.putln("%s = PyList_New(%s); %s" %
3299 (self.result(),
3300 len(self.args),
3301 code.error_goto_if_null(self.result(), self.pos)))
3302 code.put_gotref(self.py_result())
3303 for i in range(len(self.args)):
3304 arg = self.args[i]
3305 #if not arg.is_temp:
3306 if not arg.result_in_temp():
3307 code.put_incref(arg.result(), arg.ctype())
3308 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3309 (self.result(),
3310 i,
3311 arg.py_result()))
3312 code.put_giveref(arg.py_result())
3313 elif self.type.is_array:
3314 for i, arg in enumerate(self.args):
3315 code.putln("%s[%s] = %s;" % (
3316 self.result(),
3317 i,
3318 arg.result()))
3319 elif self.type.is_struct:
3320 for arg, member in zip(self.args, self.type.scope.var_entries):
3321 code.putln("%s.%s = %s;" % (
3322 self.result(),
3323 member.cname,
3324 arg.result()))
3325 else:
3326 raise InternalError("List type never specified")
3328 def generate_subexpr_disposal_code(self, code):
3329 # We call generate_post_assignment_code here instead
3330 # of generate_disposal_code, because values were stored
3331 # in the list using a reference-stealing operation.
3332 for arg in self.args:
3333 arg.generate_post_assignment_code(code)
3334 # Should NOT call free_temps -- this is invoked by the default
3335 # generate_evaluation_code which will do that.
3338 class ComprehensionNode(NewTempExprNode):
3339 subexprs = ["target"]
3340 child_attrs = ["loop", "append"]
3342 def analyse_types(self, env):
3343 self.target.analyse_expressions(env)
3344 self.type = self.target.type
3345 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3346 self.loop.analyse_declarations(env)
3348 def allocate_temps(self, env, result = None):
3349 if debug_temp_alloc:
3350 print("%s Allocating temps" % self)
3351 self.allocate_temp(env, result)
3352 # call loop.analyse_expressions() now to make sure temps get
3353 # allocated at the right time
3354 self.loop.analyse_expressions(env)
3356 def calculate_result_code(self):
3357 return self.target.result()
3359 def generate_result_code(self, code):
3360 self.generate_operation_code(code)
3362 def generate_operation_code(self, code):
3363 self.loop.generate_execution_code(code)
3365 def annotate(self, code):
3366 self.loop.annotate(code)
3369 class ComprehensionAppendNode(NewTempExprNode):
3370 # Need to be careful to avoid infinite recursion:
3371 # target must not be in child_attrs/subexprs
3372 subexprs = ['expr']
3374 def analyse_types(self, env):
3375 self.expr.analyse_types(env)
3376 if not self.expr.type.is_pyobject:
3377 self.expr = self.expr.coerce_to_pyobject(env)
3378 self.type = PyrexTypes.c_int_type
3379 self.is_temp = 1
3381 def generate_result_code(self, code):
3382 if self.target.type is list_type:
3383 function = "PyList_Append"
3384 elif self.target.type is set_type:
3385 function = "PySet_Add"
3386 else:
3387 raise InternalError(
3388 "Invalid type for comprehension node: %s" % self.target.type)
3390 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3391 (self.result(),
3392 function,
3393 self.target.result(),
3394 self.expr.result(),
3395 code.error_goto_if(self.result(), self.pos)))
3397 class DictComprehensionAppendNode(ComprehensionAppendNode):
3398 subexprs = ['key_expr', 'value_expr']
3400 def analyse_types(self, env):
3401 self.key_expr.analyse_types(env)
3402 if not self.key_expr.type.is_pyobject:
3403 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3404 self.value_expr.analyse_types(env)
3405 if not self.value_expr.type.is_pyobject:
3406 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3407 self.type = PyrexTypes.c_int_type
3408 self.is_temp = 1
3410 def generate_result_code(self, code):
3411 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3412 (self.result(),
3413 self.target.result(),
3414 self.key_expr.result(),
3415 self.value_expr.result(),
3416 code.error_goto_if(self.result(), self.pos)))
3419 class SetNode(NewTempExprNode):
3420 # Set constructor.
3422 subexprs = ['args']
3424 gil_message = "Constructing Python set"
3426 def analyse_types(self, env):
3427 for i in range(len(self.args)):
3428 arg = self.args[i]
3429 arg.analyse_types(env)
3430 self.args[i] = arg.coerce_to_pyobject(env)
3431 self.type = set_type
3432 self.is_temp = 1
3434 def calculate_constant_result(self):
3435 self.constant_result = set([
3436 arg.constant_result for arg in self.args])
3438 def compile_time_value(self, denv):
3439 values = [arg.compile_time_value(denv) for arg in self.args]
3440 try:
3441 return set(values)
3442 except Exception, e:
3443 self.compile_time_value_error(e)
3445 def generate_evaluation_code(self, code):
3446 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3447 self.allocate_temp_result(code)
3448 code.putln(
3449 "%s = PySet_New(0); %s" % (
3450 self.result(),
3451 code.error_goto_if_null(self.result(), self.pos)))
3452 code.put_gotref(self.py_result())
3453 for arg in self.args:
3454 arg.generate_evaluation_code(code)
3455 code.putln(
3456 code.error_goto_if_neg(
3457 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3458 self.pos))
3459 arg.generate_disposal_code(code)
3460 arg.free_temps(code)
3463 class DictNode(NewTempExprNode):
3464 # Dictionary constructor.
3466 # key_value_pairs [DictItemNode]
3468 # obj_conversion_errors [PyrexError] used internally
3470 subexprs = ['key_value_pairs']
3472 def calculate_constant_result(self):
3473 self.constant_result = dict([
3474 item.constant_result for item in self.key_value_pairs])
3476 def compile_time_value(self, denv):
3477 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3478 for item in self.key_value_pairs]
3479 try:
3480 return dict(pairs)
3481 except Exception, e:
3482 self.compile_time_value_error(e)
3484 def analyse_types(self, env):
3485 hold_errors()
3486 self.type = dict_type
3487 for item in self.key_value_pairs:
3488 item.analyse_types(env)
3489 self.obj_conversion_errors = held_errors()
3490 release_errors(ignore=True)
3491 self.is_temp = 1
3493 def coerce_to(self, dst_type, env):
3494 if dst_type.is_pyobject:
3495 self.release_errors()
3496 if not self.type.subtype_of(dst_type):
3497 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3498 elif dst_type.is_struct_or_union:
3499 self.type = dst_type
3500 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3501 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3502 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3503 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3504 for item in self.key_value_pairs:
3505 if isinstance(item.key, CoerceToPyTypeNode):
3506 item.key = item.key.arg
3507 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3508 error(item.key.pos, "Invalid struct field identifier")
3509 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3510 else:
3511 member = dst_type.scope.lookup_here(item.key.value)
3512 if not member:
3513 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3514 else:
3515 value = item.value
3516 if isinstance(value, CoerceToPyTypeNode):
3517 value = value.arg
3518 item.value = value.coerce_to(member.type, env)
3519 else:
3520 self.type = error_type
3521 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3522 return self
3524 def release_errors(self):
3525 for err in self.obj_conversion_errors:
3526 report_error(err)
3527 self.obj_conversion_errors = []
3529 gil_message = "Constructing Python dict"
3531 def generate_evaluation_code(self, code):
3532 # Custom method used here because key-value
3533 # pairs are evaluated and used one at a time.
3534 code.mark_pos(self.pos)
3535 self.allocate_temp_result(code)
3536 if self.type.is_pyobject:
3537 self.release_errors()
3538 code.putln(
3539 "%s = PyDict_New(); %s" % (
3540 self.result(),
3541 code.error_goto_if_null(self.result(), self.pos)))
3542 code.put_gotref(self.py_result())
3543 for item in self.key_value_pairs:
3544 item.generate_evaluation_code(code)
3545 if self.type.is_pyobject:
3546 code.put_error_if_neg(self.pos,
3547 "PyDict_SetItem(%s, %s, %s)" % (
3548 self.result(),
3549 item.key.py_result(),
3550 item.value.py_result()))
3551 else:
3552 code.putln("%s.%s = %s;" % (
3553 self.result(),
3554 item.key.value,
3555 item.value.result()))
3556 item.generate_disposal_code(code)
3557 item.free_temps(code)
3559 def annotate(self, code):
3560 for item in self.key_value_pairs:
3561 item.annotate(code)
3563 class DictItemNode(NewTempExprNode):
3564 # Represents a single item in a DictNode
3566 # key ExprNode
3567 # value ExprNode
3568 subexprs = ['key', 'value']
3570 gil_check = None # handled by DictNode
3572 def calculate_constant_result(self):
3573 self.constant_result = (
3574 self.key.constant_result, self.value.constant_result)
3576 def analyse_types(self, env):
3577 self.key.analyse_types(env)
3578 self.value.analyse_types(env)
3579 self.key = self.key.coerce_to_pyobject(env)
3580 self.value = self.value.coerce_to_pyobject(env)
3582 def generate_evaluation_code(self, code):
3583 self.key.generate_evaluation_code(code)
3584 self.value.generate_evaluation_code(code)
3586 def generate_disposal_code(self, code):
3587 self.key.generate_disposal_code(code)
3588 self.value.generate_disposal_code(code)
3590 def free_temps(self, code):
3591 self.key.free_temps(code)
3592 self.value.free_temps(code)
3594 def __iter__(self):
3595 return iter([self.key, self.value])
3598 class ClassNode(NewTempExprNode):
3599 # Helper class used in the implementation of Python
3600 # class definitions. Constructs a class object given
3601 # a name, tuple of bases and class dictionary.
3603 # name EncodedString Name of the class
3604 # bases ExprNode Base class tuple
3605 # dict ExprNode Class dict (not owned by this node)
3606 # doc ExprNode or None Doc string
3607 # module_name string Name of defining module
3609 subexprs = ['bases', 'doc']
3611 def analyse_types(self, env):
3612 self.bases.analyse_types(env)
3613 if self.doc:
3614 self.doc.analyse_types(env)
3615 self.doc = self.doc.coerce_to_pyobject(env)
3616 self.module_name = env.global_scope().qualified_name
3617 self.type = py_object_type
3618 self.is_temp = 1
3619 env.use_utility_code(create_class_utility_code);
3621 gil_message = "Constructing Python class"
3623 def generate_result_code(self, code):
3624 cname = code.intern_identifier(self.name)
3625 if self.doc:
3626 code.put_error_if_neg(self.pos,
3627 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3628 self.dict.py_result(),
3629 self.doc.py_result()))
3630 code.putln(
3631 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3632 self.result(),
3633 self.bases.py_result(),
3634 self.dict.py_result(),
3635 cname,
3636 self.module_name,
3637 code.error_goto_if_null(self.result(), self.pos)))
3638 code.put_gotref(self.py_result())
3641 class UnboundMethodNode(NewTempExprNode):
3642 # Helper class used in the implementation of Python
3643 # class definitions. Constructs an unbound method
3644 # object from a class and a function.
3646 # function ExprNode Function object
3648 subexprs = ['function']
3650 def analyse_types(self, env):
3651 self.function.analyse_types(env)
3652 self.type = py_object_type
3653 self.is_temp = 1
3655 gil_message = "Constructing an unbound method"
3657 def generate_result_code(self, code):
3658 class_cname = code.pyclass_stack[-1].classobj.result()
3659 code.putln(
3660 "%s = PyMethod_New(%s, 0, %s); %s" % (
3661 self.result(),
3662 self.function.py_result(),
3663 class_cname,
3664 code.error_goto_if_null(self.result(), self.pos)))
3665 code.put_gotref(self.py_result())
3667 class PyCFunctionNode(AtomicNewTempExprNode):
3668 # Helper class used in the implementation of Python
3669 # class definitions. Constructs a PyCFunction object
3670 # from a PyMethodDef struct.
3672 # pymethdef_cname string PyMethodDef structure
3674 def analyse_types(self, env):
3675 self.type = py_object_type
3676 self.is_temp = 1
3678 gil_message = "Constructing Python function"
3680 def generate_result_code(self, code):
3681 code.putln(
3682 "%s = PyCFunction_New(&%s, 0); %s" % (
3683 self.result(),
3684 self.pymethdef_cname,
3685 code.error_goto_if_null(self.result(), self.pos)))
3686 code.put_gotref(self.py_result())
3688 #-------------------------------------------------------------------
3690 # Unary operator nodes
3692 #-------------------------------------------------------------------
3694 compile_time_unary_operators = {
3695 'not': operator.not_,
3696 '~': operator.inv,
3697 '-': operator.neg,
3698 '+': operator.pos,
3701 class UnopNode(NewTempExprNode):
3702 # operator string
3703 # operand ExprNode
3705 # Processing during analyse_expressions phase:
3707 # analyse_c_operation
3708 # Called when the operand is not a pyobject.
3709 # - Check operand type and coerce if needed.
3710 # - Determine result type and result code fragment.
3711 # - Allocate temporary for result if needed.
3713 subexprs = ['operand']
3715 def calculate_constant_result(self):
3716 func = compile_time_unary_operators[self.operator]
3717 self.constant_result = func(self.operand.constant_result)
3719 def compile_time_value(self, denv):
3720 func = compile_time_unary_operators.get(self.operator)
3721 if not func:
3722 error(self.pos,
3723 "Unary '%s' not supported in compile-time expression"
3724 % self.operator)
3725 operand = self.operand.compile_time_value(denv)
3726 try:
3727 return func(operand)
3728 except Exception, e:
3729 self.compile_time_value_error(e)
3731 def analyse_types(self, env):
3732 self.operand.analyse_types(env)
3733 if self.is_py_operation():
3734 self.coerce_operand_to_pyobject(env)
3735 self.type = py_object_type
3736 self.is_temp = 1
3737 else:
3738 self.analyse_c_operation(env)
3740 def check_const(self):
3741 self.operand.check_const()
3743 def is_py_operation(self):
3744 return self.operand.type.is_pyobject
3746 def gil_check(self, env):
3747 if self.is_py_operation():
3748 self._gil_check(env)
3750 def coerce_operand_to_pyobject(self, env):
3751 self.operand = self.operand.coerce_to_pyobject(env)
3753 def generate_result_code(self, code):
3754 if self.operand.type.is_pyobject:
3755 self.generate_py_operation_code(code)
3756 else:
3757 if self.is_temp:
3758 self.generate_c_operation_code(code)
3760 def generate_py_operation_code(self, code):
3761 function = self.py_operation_function()
3762 code.putln(
3763 "%s = %s(%s); %s" % (
3764 self.result(),
3765 function,
3766 self.operand.py_result(),
3767 code.error_goto_if_null(self.result(), self.pos)))
3768 code.put_gotref(self.py_result())
3770 def type_error(self):
3771 if not self.operand.type.is_error:
3772 error(self.pos, "Invalid operand type for '%s' (%s)" %
3773 (self.operator, self.operand.type))
3774 self.type = PyrexTypes.error_type
3777 class NotNode(NewTempExprNode):
3778 # 'not' operator
3780 # operand ExprNode
3782 def calculate_constant_result(self):
3783 self.constant_result = not self.operand.constant_result
3785 def compile_time_value(self, denv):
3786 operand = self.operand.compile_time_value(denv)
3787 try:
3788 return not operand
3789 except Exception, e:
3790 self.compile_time_value_error(e)
3792 subexprs = ['operand']
3794 def analyse_types(self, env):
3795 self.operand.analyse_types(env)
3796 self.operand = self.operand.coerce_to_boolean(env)
3797 self.type = PyrexTypes.c_bint_type
3799 def calculate_result_code(self):
3800 return "(!%s)" % self.operand.result()
3802 def generate_result_code(self, code):
3803 pass
3806 class UnaryPlusNode(UnopNode):
3807 # unary '+' operator
3809 operator = '+'
3811 def analyse_c_operation(self, env):
3812 self.type = self.operand.type
3814 def py_operation_function(self):
3815 return "PyNumber_Positive"
3817 def calculate_result_code(self):
3818 return self.operand.result()
3821 class UnaryMinusNode(UnopNode):
3822 # unary '-' operator
3824 operator = '-'
3826 def analyse_c_operation(self, env):
3827 if self.operand.type.is_numeric:
3828 self.type = self.operand.type
3829 else:
3830 self.type_error()
3832 def py_operation_function(self):
3833 return "PyNumber_Negative"
3835 def calculate_result_code(self):
3836 return "(-%s)" % self.operand.result()
3839 class TildeNode(UnopNode):
3840 # unary '~' operator
3842 def analyse_c_operation(self, env):
3843 if self.operand.type.is_int:
3844 self.type = self.operand.type
3845 else:
3846 self.type_error()
3848 def py_operation_function(self):
3849 return "PyNumber_Invert"
3851 def calculate_result_code(self):
3852 return "(~%s)" % self.operand.result()
3855 class AmpersandNode(NewTempExprNode):
3856 # The C address-of operator.
3858 # operand ExprNode
3860 subexprs = ['operand']
3862 def analyse_types(self, env):
3863 self.operand.analyse_types(env)
3864 argtype = self.operand.type
3865 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3866 self.error("Taking address of non-lvalue")
3867 return
3868 if argtype.is_pyobject:
3869 self.error("Cannot take address of Python variable")
3870 return
3871 self.type = PyrexTypes.c_ptr_type(argtype)
3873 def check_const(self):
3874 self.operand.check_const_addr()
3876 def error(self, mess):
3877 error(self.pos, mess)
3878 self.type = PyrexTypes.error_type
3879 self.result_code = "<error>"
3881 def calculate_result_code(self):
3882 return "(&%s)" % self.operand.result()
3884 def generate_result_code(self, code):
3885 pass
3888 unop_node_classes = {
3889 "+": UnaryPlusNode,
3890 "-": UnaryMinusNode,
3891 "~": TildeNode,
3894 def unop_node(pos, operator, operand):
3895 # Construct unnop node of appropriate class for
3896 # given operator.
3897 if isinstance(operand, IntNode) and operator == '-':
3898 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3899 elif isinstance(operand, UnopNode) and operand.operator == operator:
3900 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3901 return unop_node_classes[operator](pos,
3902 operator = operator,
3903 operand = operand)
3906 class TypecastNode(NewTempExprNode):
3907 # C type cast
3909 # operand ExprNode
3910 # base_type CBaseTypeNode
3911 # declarator CDeclaratorNode
3913 # If used from a transform, one can if wanted specify the attribute
3914 # "type" directly and leave base_type and declarator to None
3916 subexprs = ['operand']
3917 base_type = declarator = type = None
3919 def analyse_types(self, env):
3920 if self.type is None:
3921 base_type = self.base_type.analyse(env)
3922 _, self.type = self.declarator.analyse(base_type, env)
3923 if self.type.is_cfunction:
3924 error(self.pos,
3925 "Cannot cast to a function type")
3926 self.type = PyrexTypes.error_type
3927 self.operand.analyse_types(env)
3928 to_py = self.type.is_pyobject
3929 from_py = self.operand.type.is_pyobject
3930 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3931 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3932 if to_py and not from_py:
3933 if (self.operand.type.to_py_function and
3934 self.operand.type.create_convert_utility_code(env)):
3935 self.result_ctype = py_object_type
3936 self.operand = self.operand.coerce_to_pyobject(env)
3937 else:
3938 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3939 self.operand = self.operand.coerce_to_simple(env)
3940 elif from_py and not to_py:
3941 if self.type.from_py_function:
3942 self.operand = self.operand.coerce_to(self.type, env)
3943 else:
3944 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3945 elif from_py and to_py:
3946 if self.typecheck and self.type.is_extension_type:
3947 self.operand = PyTypeTestNode(self.operand, self.type, env)
3949 def gil_check(self, env):
3950 if self.type.is_pyobject and self.is_temp:
3951 self._gil_check(env)
3953 def check_const(self):
3954 self.operand.check_const()
3956 def calculate_constant_result(self):
3957 # we usually do not know the result of a type cast at code
3958 # generation time
3959 pass
3961 def calculate_result_code(self):
3962 opnd = self.operand
3963 return self.type.cast_code(opnd.result())
3965 def result_as(self, type):
3966 if self.type.is_pyobject and not self.is_temp:
3967 # Optimise away some unnecessary casting
3968 return self.operand.result_as(type)
3969 else:
3970 return ExprNode.result_as(self, type)
3972 def generate_result_code(self, code):
3973 if self.is_temp:
3974 code.putln(
3975 "%s = (PyObject *)%s;" % (
3976 self.result(),
3977 self.operand.result()))
3978 code.put_incref(self.result(), self.ctype())
3981 class SizeofNode(NewTempExprNode):
3982 # Abstract base class for sizeof(x) expression nodes.
3984 type = PyrexTypes.c_size_t_type
3986 def check_const(self):
3987 pass
3989 def generate_result_code(self, code):
3990 pass
3993 class SizeofTypeNode(SizeofNode):
3994 # C sizeof function applied to a type
3996 # base_type CBaseTypeNode
3997 # declarator CDeclaratorNode
3999 subexprs = []
4000 arg_type = None
4002 def analyse_types(self, env):
4003 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4004 # this could be better handled by more uniformly treating types as runtime-available objects
4005 if 0 and self.base_type.module_path:
4006 path = self.base_type.module_path
4007 obj = env.lookup(path[0])
4008 if obj.as_module is None:
4009 operand = NameNode(pos=self.pos, name=path[0])
4010 for attr in path[1:]:
4011 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4012 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4013 self.operand = operand
4014 self.__class__ = SizeofVarNode
4015 self.analyse_types(env)
4016 return
4017 if self.arg_type is None:
4018 base_type = self.base_type.analyse(env)
4019 _, arg_type = self.declarator.analyse(base_type, env)
4020 self.arg_type = arg_type
4021 self.check_type()
4023 def check_type(self):
4024 arg_type = self.arg_type
4025 if arg_type.is_pyobject and not arg_type.is_extension_type:
4026 error(self.pos, "Cannot take sizeof Python object")
4027 elif arg_type.is_void:
4028 error(self.pos, "Cannot take sizeof void")
4029 elif not arg_type.is_complete():
4030 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4032 def calculate_result_code(self):
4033 if self.arg_type.is_extension_type:
4034 # the size of the pointer is boring
4035 # we want the size of the actual struct
4036 arg_code = self.arg_type.declaration_code("", deref=1)
4037 else:
4038 arg_code = self.arg_type.declaration_code("")
4039 return "(sizeof(%s))" % arg_code
4042 class SizeofVarNode(SizeofNode):
4043 # C sizeof function applied to a variable
4045 # operand ExprNode
4047 subexprs = ['operand']
4049 def analyse_types(self, env):
4050 # We may actually be looking at a type rather than a variable...
4051 # If we are, traditional analysis would fail...
4052 operand_as_type = self.operand.analyse_as_type(env)
4053 if operand_as_type:
4054 self.arg_type = operand_as_type
4055 self.__class__ = SizeofTypeNode
4056 self.check_type()
4057 else:
4058 self.operand.analyse_types(env)
4060 def calculate_result_code(self):
4061 return "(sizeof(%s))" % self.operand.result()
4063 def generate_result_code(self, code):
4064 pass
4067 #-------------------------------------------------------------------
4069 # Binary operator nodes
4071 #-------------------------------------------------------------------
4073 def _not_in(x, seq):
4074 return x not in seq
4076 compile_time_binary_operators = {
4077 '<': operator.lt,
4078 '<=': operator.le,
4079 '==': operator.eq,
4080 '!=': operator.ne,
4081 '>=': operator.ge,
4082 '>': operator.gt,
4083 'is': operator.is_,
4084 'is_not': operator.is_not,
4085 '+': operator.add,
4086 '&': operator.and_,
4087 '/': operator.div,
4088 '//': operator.floordiv,
4089 '<<': operator.lshift,
4090 '%': operator.mod,
4091 '*': operator.mul,
4092 '|': operator.or_,
4093 '**': operator.pow,
4094 '>>': operator.rshift,
4095 '-': operator.sub,
4096 #'/': operator.truediv,
4097 '^': operator.xor,
4098 'in': operator.contains,
4099 'not_in': _not_in,
4102 def get_compile_time_binop(node):
4103 func = compile_time_binary_operators.get(node.operator)
4104 if not func:
4105 error(node.pos,
4106 "Binary '%s' not supported in compile-time expression"
4107 % node.operator)
4108 return func
4110 class BinopNode(NewTempExprNode):
4111 # operator string
4112 # operand1 ExprNode
4113 # operand2 ExprNode
4115 # Processing during analyse_expressions phase:
4117 # analyse_c_operation
4118 # Called when neither operand is a pyobject.
4119 # - Check operand types and coerce if needed.
4120 # - Determine result type and result code fragment.
4121 # - Allocate temporary for result if needed.
4123 subexprs = ['operand1', 'operand2']
4125 def calculate_constant_result(self):
4126 func = compile_time_binary_operators[self.operator]
4127 self.constant_result = func(
4128 self.operand1.constant_result,
4129 self.operand2.constant_result)
4131 def compile_time_value(self, denv):
4132 func = get_compile_time_binop(self)
4133 operand1 = self.operand1.compile_time_value(denv)
4134 operand2 = self.operand2.compile_time_value(denv)
4135 try:
4136 return func(operand1, operand2)
4137 except Exception, e:
4138 self.compile_time_value_error(e)
4140 def analyse_types(self, env):
4141 self.operand1.analyse_types(env)
4142 self.operand2.analyse_types(env)
4143 if self.is_py_operation():
4144 self.coerce_operands_to_pyobjects(env)
4145 self.type = py_object_type
4146 self.is_temp = 1
4147 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4148 self.operand1 = self.operand1.coerce_to_temp(env)
4149 else:
4150 self.analyse_c_operation(env)
4152 def is_py_operation(self):
4153 return (self.operand1.type.is_pyobject
4154 or self.operand2.type.is_pyobject)
4156 def gil_check(self, env):
4157 if self.is_py_operation():
4158 self._gil_check(env)
4160 def coerce_operands_to_pyobjects(self, env):
4161 self.operand1 = self.operand1.coerce_to_pyobject(env)
4162 self.operand2 = self.operand2.coerce_to_pyobject(env)
4164 def check_const(self):
4165 self.operand1.check_const()
4166 self.operand2.check_const()
4168 def generate_result_code(self, code):
4169 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4170 if self.operand1.type.is_pyobject:
4171 function = self.py_operation_function()
4172 if function == "PyNumber_Power":
4173 extra_args = ", Py_None"
4174 else:
4175 extra_args = ""
4176 code.putln(
4177 "%s = %s(%s, %s%s); %s" % (
4178 self.result(),
4179 function,
4180 self.operand1.py_result(),
4181 self.operand2.py_result(),
4182 extra_args,
4183 code.error_goto_if_null(self.result(), self.pos)))
4184 code.put_gotref(self.py_result())
4185 else:
4186 if self.is_temp:
4187 self.generate_c_operation_code(code)
4189 def type_error(self):
4190 if not (self.operand1.type.is_error
4191 or self.operand2.type.is_error):
4192 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4193 (self.operator, self.operand1.type,
4194 self.operand2.type))
4195 self.type = PyrexTypes.error_type
4198 class NumBinopNode(BinopNode):
4199 # Binary operation taking numeric arguments.
4201 def analyse_c_operation(self, env):
4202 type1 = self.operand1.type
4203 type2 = self.operand2.type
4204 self.type = self.compute_c_result_type(type1, type2)
4205 if not self.type:
4206 self.type_error()
4208 def compute_c_result_type(self, type1, type2):
4209 if self.c_types_okay(type1, type2):
4210 return PyrexTypes.widest_numeric_type(type1, type2)
4211 else:
4212 return None
4214 def c_types_okay(self, type1, type2):
4215 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4216 return (type1.is_numeric or type1.is_enum) \
4217 and (type2.is_numeric or type2.is_enum)
4219 def calculate_result_code(self):
4220 return "(%s %s %s)" % (
4221 self.operand1.result(),
4222 self.operator,
4223 self.operand2.result())
4225 def py_operation_function(self):
4226 return self.py_functions[self.operator]
4228 py_functions = {
4229 "|": "PyNumber_Or",
4230 "^": "PyNumber_Xor",
4231 "&": "PyNumber_And",
4232 "<<": "PyNumber_Lshift",
4233 ">>": "PyNumber_Rshift",
4234 "+": "PyNumber_Add",
4235 "-": "PyNumber_Subtract",
4236 "*": "PyNumber_Multiply",
4237 "/": "__Pyx_PyNumber_Divide",
4238 "//": "PyNumber_FloorDivide",
4239 "%": "PyNumber_Remainder",
4240 "**": "PyNumber_Power"
4244 class IntBinopNode(NumBinopNode):
4245 # Binary operation taking integer arguments.
4247 def c_types_okay(self, type1, type2):
4248 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4249 return (type1.is_int or type1.is_enum) \
4250 and (type2.is_int or type2.is_enum)
4253 class AddNode(NumBinopNode):
4254 # '+' operator.
4256 def is_py_operation(self):
4257 if self.operand1.type.is_string \
4258 and self.operand2.type.is_string:
4259 return 1
4260 else:
4261 return NumBinopNode.is_py_operation(self)
4263 def compute_c_result_type(self, type1, type2):
4264 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4265 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4266 return type1
4267 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4268 return type2
4269 else:
4270 return NumBinopNode.compute_c_result_type(
4271 self, type1, type2)
4274 class SubNode(NumBinopNode):
4275 # '-' operator.
4277 def compute_c_result_type(self, type1, type2):
4278 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4279 return type1
4280 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4281 return PyrexTypes.c_int_type
4282 else:
4283 return NumBinopNode.compute_c_result_type(
4284 self, type1, type2)
4287 class MulNode(NumBinopNode):
4288 # '*' operator.
4290 def is_py_operation(self):
4291 type1 = self.operand1.type
4292 type2 = self.operand2.type
4293 if (type1.is_string and type2.is_int) \
4294 or (type2.is_string and type1.is_int):
4295 return 1
4296 else:
4297 return NumBinopNode.is_py_operation(self)
4300 class DivNode(NumBinopNode):
4301 # '/' or '//' operator.
4303 cdivision = None
4304 cdivision_warnings = False
4306 def analyse_types(self, env):
4307 NumBinopNode.analyse_types(self, env)
4308 if not self.type.is_pyobject and env.directives['cdivision_warnings']:
4309 self.operand1 = self.operand1.coerce_to_simple(env)
4310 self.operand2 = self.operand2.coerce_to_simple(env)
4312 def generate_evaluation_code(self, code):
4313 if not self.type.is_pyobject:
4314 if self.cdivision is None:
4315 self.cdivision = (code.globalstate.directives['cdivision']
4316 or not self.type.signed
4317 or self.type.is_float)
4318 if not self.cdivision:
4319 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4320 NumBinopNode.generate_evaluation_code(self, code)
4321 if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
4322 self.generate_div_warning_code(code)
4324 def generate_div_warning_code(self, code):
4325 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4326 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4327 self.operand1.result(),
4328 self.operand2.result()))
4329 code.putln(code.set_error_info(self.pos));
4330 code.put("if (__Pyx_cdivision_warning()) ")
4331 code.put_goto(code.error_label)
4332 code.putln("}")
4334 def calculate_result_code(self):
4335 if self.type.is_float and self.operator == '//':
4336 return "floor(%s / %s)" % (
4337 self.operand1.result(),
4338 self.operand2.result())
4339 elif self.cdivision:
4340 return "(%s / %s)" % (
4341 self.operand1.result(),
4342 self.operand2.result())
4343 else:
4344 return "__Pyx_div_%s(%s, %s)" % (
4345 self.type.specalization_name(),
4346 self.operand1.result(),
4347 self.operand2.result())
4350 class ModNode(DivNode):
4351 # '%' operator.
4353 def is_py_operation(self):
4354 return (self.operand1.type.is_string
4355 or self.operand2.type.is_string
4356 or NumBinopNode.is_py_operation(self))
4358 def generate_evaluation_code(self, code):
4359 if not self.type.is_pyobject:
4360 if self.cdivision is None:
4361 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4362 if not self.cdivision:
4363 if self.type.is_int:
4364 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4365 else:
4366 code.globalstate.use_utility_code(
4367 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4368 NumBinopNode.generate_evaluation_code(self, code)
4369 if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
4370 self.generate_div_warning_code(code)
4372 def calculate_result_code(self):
4373 if self.cdivision:
4374 if self.type.is_float:
4375 return "fmod%s(%s, %s)" % (
4376 self.type.math_h_modifier,
4377 self.operand1.result(),
4378 self.operand2.result())
4379 else:
4380 return "(%s %% %s)" % (
4381 self.operand1.result(),
4382 self.operand2.result())
4383 else:
4384 return "__Pyx_mod_%s(%s, %s)" % (
4385 self.type.specalization_name(),
4386 self.operand1.result(),
4387 self.operand2.result())
4389 class PowNode(NumBinopNode):
4390 # '**' operator.
4392 def analyse_c_operation(self, env):
4393 NumBinopNode.analyse_c_operation(self, env)
4394 if self.operand1.type.is_float or self.operand2.type.is_float:
4395 self.pow_func = "pow"
4396 else:
4397 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4398 env.use_utility_code(
4399 int_pow_utility_code.specialize(func_name=self.pow_func,
4400 type=self.type.declaration_code('')))
4402 def calculate_result_code(self):
4403 return "%s(%s, %s)" % (
4404 self.pow_func,
4405 self.operand1.result(),
4406 self.operand2.result())
4409 # Note: This class is temporary "shut down" into an ineffective mode temp
4410 # allocation mode.
4412 # More sophisticated temp reuse was going on before,
4413 # one could have a look at adding this again after /all/ classes
4414 # are converted to the new temp scheme. (The temp juggling cannot work
4415 # otherwise).
4416 class BoolBinopNode(NewTempExprNode):
4417 # Short-circuiting boolean operation.
4419 # operator string
4420 # operand1 ExprNode
4421 # operand2 ExprNode
4423 subexprs = ['operand1', 'operand2']
4425 def calculate_constant_result(self):
4426 if self.operator == 'and':
4427 self.constant_result = \
4428 self.operand1.constant_result and \
4429 self.operand2.constant_result
4430 else:
4431 self.constant_result = \
4432 self.operand1.constant_result or \
4433 self.operand2.constant_result
4435 def compile_time_value(self, denv):
4436 if self.operator == 'and':
4437 return self.operand1.compile_time_value(denv) \
4438 and self.operand2.compile_time_value(denv)
4439 else:
4440 return self.operand1.compile_time_value(denv) \
4441 or self.operand2.compile_time_value(denv)
4443 def coerce_to_boolean(self, env):
4444 self.operand1 = self.operand1.coerce_to_boolean(env)
4445 self.operand2 = self.operand2.coerce_to_boolean(env)
4446 self.type = PyrexTypes.c_bint_type
4447 return self
4449 def analyse_types(self, env):
4450 self.operand1.analyse_types(env)
4451 self.operand2.analyse_types(env)
4452 if self.operand1.type.is_pyobject or \
4453 self.operand2.type.is_pyobject:
4454 self.operand1 = self.operand1.coerce_to_pyobject(env)
4455 self.operand2 = self.operand2.coerce_to_pyobject(env)
4456 self.type = py_object_type
4457 else:
4458 self.operand1 = self.operand1.coerce_to_boolean(env)
4459 self.operand2 = self.operand2.coerce_to_boolean(env)
4460 self.type = PyrexTypes.c_bint_type
4462 # Below disabled for
4464 # For what we're about to do, it's vital that
4465 # both operands be temp nodes.
4466 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4467 # self.operand2 = self.operand2.coerce_to_temp(env)
4468 self.is_temp = 1
4470 gil_message = "Truth-testing Python object"
4472 ## def allocate_temps(self, env, result_code = None):
4473 ## # We don't need both operands at the same time, and
4474 ## # one of the operands will also be our result. So we
4475 ## # use an allocation strategy here which results in
4476 ## # this node and both its operands sharing the same
4477 ## # result variable. This allows us to avoid some
4478 ## # assignments and increfs/decrefs that would otherwise
4479 ## # be necessary.
4480 ## self.allocate_temp(env, result_code)
4481 ## self.operand1.allocate_temps(env, self.result())
4482 ## self.operand2.allocate_temps(env, self.result())
4483 ## # We haven't called release_temp on either operand,
4484 ## # because although they are temp nodes, they don't own
4485 ## # their result variable. And because they are temp
4486 ## # nodes, any temps in their subnodes will have been
4487 ## # released before their allocate_temps returned.
4488 ## # Therefore, they contain no temp vars that need to
4489 ## # be released.
4491 def check_const(self):
4492 self.operand1.check_const()
4493 self.operand2.check_const()
4495 def calculate_result_code(self):
4496 return "(%s %s %s)" % (
4497 self.operand1.result(),
4498 self.py_to_c_op[self.operator],
4499 self.operand2.result())
4501 py_to_c_op = {'and': "&&", 'or': "||"}
4503 def generate_evaluation_code(self, code):
4504 code.mark_pos(self.pos)
4505 self.operand1.generate_evaluation_code(code)
4506 test_result, uses_temp = self.generate_operand1_test(code)
4507 if self.operator == 'and':
4508 sense = ""
4509 else:
4510 sense = "!"
4511 code.putln(
4512 "if (%s%s) {" % (
4513 sense,
4514 test_result))
4515 if uses_temp:
4516 code.funcstate.release_temp(test_result)
4517 self.operand1.generate_disposal_code(code)
4518 self.operand2.generate_evaluation_code(code)
4519 self.allocate_temp_result(code)
4520 self.operand2.make_owned_reference(code)
4521 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4522 self.operand2.generate_post_assignment_code(code)
4523 self.operand2.free_temps(code)
4524 code.putln("} else {")
4525 self.operand1.make_owned_reference(code)
4526 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4527 self.operand1.generate_post_assignment_code(code)
4528 self.operand1.free_temps(code)
4529 code.putln("}")
4531 def generate_operand1_test(self, code):
4532 # Generate code to test the truth of the first operand.
4533 if self.type.is_pyobject:
4534 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4535 manage_ref=False)
4536 code.putln(
4537 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4538 test_result,
4539 self.operand1.py_result(),
4540 code.error_goto_if_neg(test_result, self.pos)))
4541 else:
4542 test_result = self.operand1.result()
4543 return (test_result, self.type.is_pyobject)
4546 class CondExprNode(NewTempExprNode):
4547 # Short-circuiting conditional expression.
4549 # test ExprNode
4550 # true_val ExprNode
4551 # false_val ExprNode
4553 true_val = None
4554 false_val = None
4556 subexprs = ['test', 'true_val', 'false_val']
4558 def calculate_constant_result(self):
4559 if self.test.constant_result:
4560 self.constant_result = self.true_val.constant_result
4561 else:
4562 self.constant_result = self.false_val.constant_result
4564 def analyse_types(self, env):
4565 self.test.analyse_types(env)
4566 self.test = self.test.coerce_to_boolean(env)
4567 self.true_val.analyse_types(env)
4568 self.false_val.analyse_types(env)
4569 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4570 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4571 self.true_val = self.true_val.coerce_to(self.type, env)
4572 self.false_val = self.false_val.coerce_to(self.type, env)
4573 self.is_temp = 1
4574 if self.type == PyrexTypes.error_type:
4575 self.type_error()
4577 def compute_result_type(self, type1, type2):
4578 if type1 == type2:
4579 return type1
4580 elif type1.is_numeric and type2.is_numeric:
4581 return PyrexTypes.widest_numeric_type(type1, type2)
4582 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4583 return type2
4584 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4585 return type1
4586 elif type1.is_pyobject or type2.is_pyobject:
4587 return py_object_type
4588 elif type1.assignable_from(type2):
4589 return type1
4590 elif type2.assignable_from(type1):
4591 return type2
4592 else:
4593 return PyrexTypes.error_type
4595 def type_error(self):
4596 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4597 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4598 (self.true_val.type, self.false_val.type))
4599 self.type = PyrexTypes.error_type
4601 def check_const(self):
4602 self.test.check_const()
4603 self.true_val.check_const()
4604 self.false_val.check_const()
4606 def generate_evaluation_code(self, code):
4607 # Because subexprs may not be evaluated we can use a more optimal
4608 # subexpr allocation strategy than the default, so override evaluation_code.
4610 code.mark_pos(self.pos)
4611 self.allocate_temp_result(code)
4612 self.test.generate_evaluation_code(code)
4613 code.putln("if (%s) {" % self.test.result() )
4614 self.eval_and_get(code, self.true_val)
4615 code.putln("} else {")
4616 self.eval_and_get(code, self.false_val)
4617 code.putln("}")
4618 self.test.generate_disposal_code(code)
4619 self.test.free_temps(code)
4621 def eval_and_get(self, code, expr):
4622 expr.generate_evaluation_code(code)
4623 expr.make_owned_reference(code)
4624 code.putln("%s = %s;" % (self.result(), expr.result()))
4625 expr.generate_post_assignment_code(code)
4626 expr.free_temps(code)
4628 richcmp_constants = {
4629 "<" : "Py_LT",
4630 "<=": "Py_LE",
4631 "==": "Py_EQ",
4632 "!=": "Py_NE",
4633 "<>": "Py_NE",
4634 ">" : "Py_GT",
4635 ">=": "Py_GE",
4638 class CmpNode(object):
4639 # Mixin class containing code common to PrimaryCmpNodes
4640 # and CascadedCmpNodes.
4642 def calculate_cascaded_constant_result(self, operand1_result):
4643 func = compile_time_binary_operators[self.operator]
4644 operand2_result = self.operand2.constant_result
4645 result = func(operand1_result, operand2_result)
4646 if result and self.cascade:
4647 result = result and \
4648 self.cascade.cascaded_compile_time_value(operand2_result)
4649 self.constant_result = result
4651 def cascaded_compile_time_value(self, operand1, denv):
4652 func = get_compile_time_binop(self)
4653 operand2 = self.operand2.compile_time_value(denv)
4654 try:
4655 result = func(operand1, operand2)
4656 except Exception, e:
4657 self.compile_time_value_error(e)
4658 result = None
4659 if result:
4660 cascade = self.cascade
4661 if cascade:
4662 # FIXME: I bet this must call cascaded_compile_time_value()
4663 result = result and cascade.compile_time_value(operand2, denv)
4664 return result
4666 def is_python_comparison(self):
4667 return (self.has_python_operands()
4668 or (self.cascade and self.cascade.is_python_comparison())
4669 or self.operator in ('in', 'not_in'))
4671 def is_python_result(self):
4672 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4673 or (self.cascade and self.cascade.is_python_result()))
4675 def check_types(self, env, operand1, op, operand2):
4676 if not self.types_okay(operand1, op, operand2):
4677 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4678 (self.operator, operand1.type, operand2.type))
4680 def types_okay(self, operand1, op, operand2):
4681 type1 = operand1.type
4682 type2 = operand2.type
4683 if type1.is_error or type2.is_error:
4684 return 1
4685 if type1.is_pyobject: # type2 will be, too
4686 return 1
4687 elif type1.is_ptr or type1.is_array:
4688 return type1.is_null_ptr or type2.is_null_ptr \
4689 or ((type2.is_ptr or type2.is_array)
4690 and type1.base_type.same_as(type2.base_type))
4691 elif ((type1.is_numeric and type2.is_numeric
4692 or type1.is_enum and (type1 is type2 or type2.is_int)
4693 or type1.is_int and type2.is_enum)
4694 and op not in ('is', 'is_not')):
4695 return 1
4696 else:
4697 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4699 def generate_operation_code(self, code, result_code,
4700 operand1, op , operand2):
4701 if self.type is PyrexTypes.py_object_type:
4702 coerce_result = "__Pyx_PyBool_FromLong"
4703 else:
4704 coerce_result = ""
4705 if 'not' in op: negation = "!"
4706 else: negation = ""
4707 if op == 'in' or op == 'not_in':
4708 code.putln(
4709 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4710 result_code,
4711 coerce_result,
4712 negation,
4713 operand2.py_result(),
4714 operand1.py_result(),
4715 code.error_goto_if_neg(result_code, self.pos)))
4716 elif (operand1.type.is_pyobject
4717 and op not in ('is', 'is_not')):
4718 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4719 result_code,
4720 operand1.py_result(),
4721 operand2.py_result(),
4722 richcmp_constants[op],
4723 code.error_goto_if_null(result_code, self.pos)))
4724 code.put_gotref(result_code)
4725 else:
4726 type1 = operand1.type
4727 type2 = operand2.type
4728 if (type1.is_extension_type or type2.is_extension_type) \
4729 and not type1.same_as(type2):
4730 common_type = py_object_type
4731 elif type1.is_numeric:
4732 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4733 else:
4734 common_type = type1
4735 code1 = operand1.result_as(common_type)
4736 code2 = operand2.result_as(common_type)
4737 code.putln("%s = %s(%s %s %s);" % (
4738 result_code,
4739 coerce_result,
4740 code1,
4741 self.c_operator(op),
4742 code2))
4744 def c_operator(self, op):
4745 if op == 'is':
4746 return "=="
4747 elif op == 'is_not':
4748 return "!="
4749 else:
4750 return op
4753 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4754 # Non-cascaded comparison or first comparison of
4755 # a cascaded sequence.
4757 # operator string
4758 # operand1 ExprNode
4759 # operand2 ExprNode
4760 # cascade CascadedCmpNode
4762 # We don't use the subexprs mechanism, because
4763 # things here are too complicated for it to handle.
4764 # Instead, we override all the framework methods
4765 # which use it.
4767 child_attrs = ['operand1', 'operand2', 'cascade']
4769 cascade = None
4771 def calculate_constant_result(self):
4772 self.constant_result = self.calculate_cascaded_constant_result(
4773 self.operand1.constant_result)
4775 def compile_time_value(self, denv):
4776 operand1 = self.operand1.compile_time_value(denv)
4777 return self.cascaded_compile_time_value(operand1, denv)
4779 def analyse_types(self, env):
4780 self.operand1.analyse_types(env)
4781 self.operand2.analyse_types(env)
4782 if self.cascade:
4783 self.cascade.analyse_types(env, self.operand2)
4784 self.is_pycmp = self.is_python_comparison()
4785 if self.is_pycmp:
4786 self.coerce_operands_to_pyobjects(env)
4787 if self.has_int_operands():
4788 self.coerce_chars_to_ints(env)
4789 if self.cascade:
4790 self.operand2 = self.operand2.coerce_to_simple(env)
4791 self.cascade.coerce_cascaded_operands_to_temp(env)
4792 self.check_operand_types(env)
4793 if self.is_python_result():
4794 self.type = PyrexTypes.py_object_type
4795 else:
4796 self.type = PyrexTypes.c_bint_type
4797 cdr = self.cascade
4798 while cdr:
4799 cdr.type = self.type
4800 cdr = cdr.cascade
4801 if self.is_pycmp or self.cascade:
4802 self.is_temp = 1
4804 def check_operand_types(self, env):
4805 self.check_types(env,
4806 self.operand1, self.operator, self.operand2)
4807 if self.cascade:
4808 self.cascade.check_operand_types(env, self.operand2)
4810 def has_python_operands(self):
4811 return (self.operand1.type.is_pyobject
4812 or self.operand2.type.is_pyobject)
4814 def coerce_operands_to_pyobjects(self, env):
4815 self.operand1 = self.operand1.coerce_to_pyobject(env)
4816 self.operand2 = self.operand2.coerce_to_pyobject(env)
4817 if self.cascade:
4818 self.cascade.coerce_operands_to_pyobjects(env)
4820 def has_int_operands(self):
4821 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4822 or (self.cascade and self.cascade.has_int_operands())
4824 def coerce_chars_to_ints(self, env):
4825 # coerce literal single-char strings to c chars
4826 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4827 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4828 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4829 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4830 if self.cascade:
4831 self.cascade.coerce_chars_to_ints(env)
4833 def allocate_subexpr_temps(self, env):
4834 self.operand1.allocate_temps(env)
4835 self.operand2.allocate_temps(env)
4836 if self.cascade:
4837 self.cascade.allocate_subexpr_temps(env)
4839 def release_subexpr_temps(self, env):
4840 self.operand1.release_temp(env)
4841 self.operand2.release_temp(env)
4842 if self.cascade:
4843 self.cascade.release_subexpr_temps(env)
4845 def check_const(self):
4846 self.operand1.check_const()
4847 self.operand2.check_const()
4848 if self.cascade:
4849 self.not_const()
4851 def calculate_result_code(self):
4852 return "(%s %s %s)" % (
4853 self.operand1.result(),
4854 self.c_operator(self.operator),
4855 self.operand2.result())
4857 def generate_evaluation_code(self, code):
4858 self.operand1.generate_evaluation_code(code)
4859 self.operand2.generate_evaluation_code(code)
4860 if self.is_temp:
4861 self.allocate_temp_result(code)
4862 self.generate_operation_code(code, self.result(),
4863 self.operand1, self.operator, self.operand2)
4864 if self.cascade:
4865 self.cascade.generate_evaluation_code(code,
4866 self.result(), self.operand2)
4867 self.operand1.generate_disposal_code(code)
4868 self.operand1.free_temps(code)
4869 self.operand2.generate_disposal_code(code)
4870 self.operand2.free_temps(code)
4872 def generate_subexpr_disposal_code(self, code):
4873 # If this is called, it is a non-cascaded cmp,
4874 # so only need to dispose of the two main operands.
4875 self.operand1.generate_disposal_code(code)
4876 self.operand2.generate_disposal_code(code)
4878 def free_subexpr_temps(self, code):
4879 # If this is called, it is a non-cascaded cmp,
4880 # so only need to dispose of the two main operands.
4881 self.operand1.free_temps(code)
4882 self.operand2.free_temps(code)
4884 def annotate(self, code):
4885 self.operand1.annotate(code)
4886 self.operand2.annotate(code)
4887 if self.cascade:
4888 self.cascade.annotate(code)
4891 class CascadedCmpNode(Node, CmpNode):
4892 # A CascadedCmpNode is not a complete expression node. It
4893 # hangs off the side of another comparison node, shares
4894 # its left operand with that node, and shares its result
4895 # with the PrimaryCmpNode at the head of the chain.
4897 # operator string
4898 # operand2 ExprNode
4899 # cascade CascadedCmpNode
4901 child_attrs = ['operand2', 'cascade']
4903 cascade = None
4904 constant_result = constant_value_not_set # FIXME: where to calculate this?
4906 def analyse_types(self, env, operand1):
4907 self.operand2.analyse_types(env)
4908 if self.cascade:
4909 self.cascade.analyse_types(env, self.operand2)
4911 def check_operand_types(self, env, operand1):
4912 self.check_types(env,
4913 operand1, self.operator, self.operand2)
4914 if self.cascade:
4915 self.cascade.check_operand_types(env, self.operand2)
4917 def has_python_operands(self):
4918 return self.operand2.type.is_pyobject
4920 def coerce_operands_to_pyobjects(self, env):
4921 self.operand2 = self.operand2.coerce_to_pyobject(env)
4922 if self.cascade:
4923 self.cascade.coerce_operands_to_pyobjects(env)
4925 def has_int_operands(self):
4926 return self.operand2.type.is_int
4928 def coerce_chars_to_ints(self, env):
4929 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4930 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4932 def coerce_cascaded_operands_to_temp(self, env):
4933 if self.cascade:
4934 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4935 self.operand2 = self.operand2.coerce_to_simple(env)
4936 self.cascade.coerce_cascaded_operands_to_temp(env)
4938 def allocate_subexpr_temps(self, env):
4939 self.operand2.allocate_temps(env)
4940 if self.cascade:
4941 self.cascade.allocate_subexpr_temps(env)
4943 def release_subexpr_temps(self, env):
4944 self.operand2.release_temp(env)
4945 if self.cascade:
4946 self.cascade.release_subexpr_temps(env)
4948 def generate_evaluation_code(self, code, result, operand1):
4949 if self.type.is_pyobject:
4950 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4951 code.put_decref(result, self.type)
4952 else:
4953 code.putln("if (%s) {" % result)
4954 self.operand2.generate_evaluation_code(code)
4955 self.generate_operation_code(code, result,
4956 operand1, self.operator, self.operand2)
4957 if self.cascade:
4958 self.cascade.generate_evaluation_code(
4959 code, result, self.operand2)
4960 # Cascaded cmp result is always temp
4961 self.operand2.generate_disposal_code(code)
4962 self.operand2.free_temps(code)
4963 code.putln("}")
4965 def annotate(self, code):
4966 self.operand2.annotate(code)
4967 if self.cascade:
4968 self.cascade.annotate(code)
4971 binop_node_classes = {
4972 "or": BoolBinopNode,
4973 "and": BoolBinopNode,
4974 "|": IntBinopNode,
4975 "^": IntBinopNode,
4976 "&": IntBinopNode,
4977 "<<": IntBinopNode,
4978 ">>": IntBinopNode,
4979 "+": AddNode,
4980 "-": SubNode,
4981 "*": MulNode,
4982 "/": DivNode,
4983 "//": DivNode,
4984 "%": ModNode,
4985 "**": PowNode
4988 def binop_node(pos, operator, operand1, operand2):
4989 # Construct binop node of appropriate class for
4990 # given operator.
4991 return binop_node_classes[operator](pos,
4992 operator = operator,
4993 operand1 = operand1,
4994 operand2 = operand2)
4996 #-------------------------------------------------------------------
4998 # Coercion nodes
5000 # Coercion nodes are special in that they are created during
5001 # the analyse_types phase of parse tree processing.
5002 # Their __init__ methods consequently incorporate some aspects
5003 # of that phase.
5005 #-------------------------------------------------------------------
5007 class CoercionNode(NewTempExprNode):
5008 # Abstract base class for coercion nodes.
5010 # arg ExprNode node being coerced
5012 subexprs = ['arg']
5014 def __init__(self, arg):
5015 self.pos = arg.pos
5016 self.arg = arg
5017 if debug_coercion:
5018 print("%s Coercing %s" % (self, self.arg))
5020 def calculate_constant_result(self):
5021 # constant folding can break type coercion, so this is disabled
5022 pass
5024 def annotate(self, code):
5025 self.arg.annotate(code)
5026 if self.arg.type != self.type:
5027 file, line, col = self.pos
5028 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5031 class CastNode(CoercionNode):
5032 # Wrap a node in a C type cast.
5034 def __init__(self, arg, new_type):
5035 CoercionNode.__init__(self, arg)
5036 self.type = new_type
5038 def calculate_result_code(self):
5039 return self.arg.result_as(self.type)
5041 def generate_result_code(self, code):
5042 self.arg.generate_result_code(code)
5045 class PyTypeTestNode(CoercionNode):
5046 # This node is used to check that a generic Python
5047 # object is an instance of a particular extension type.
5048 # This node borrows the result of its argument node.
5050 def __init__(self, arg, dst_type, env):
5051 # The arg is know to be a Python object, and
5052 # the dst_type is known to be an extension type.
5053 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5054 CoercionNode.__init__(self, arg)
5055 self.type = dst_type
5056 self.result_ctype = arg.ctype()
5058 gil_check = CoercionNode._gil_check
5059 gil_message = "Python type test"
5061 def analyse_types(self, env):
5062 pass
5064 def result_in_temp(self):
5065 return self.arg.result_in_temp()
5067 def is_ephemeral(self):
5068 return self.arg.is_ephemeral()
5070 def calculate_constant_result(self):
5071 # FIXME
5072 pass
5074 def calculate_result_code(self):
5075 return self.arg.result()
5077 def generate_result_code(self, code):
5078 if self.type.typeobj_is_available():
5079 if not self.type.is_builtin_type:
5080 code.globalstate.use_utility_code(type_test_utility_code)
5081 code.putln(
5082 "if (!(%s)) %s" % (
5083 self.type.type_test_code(self.arg.py_result()),
5084 code.error_goto(self.pos)))
5085 else:
5086 error(self.pos, "Cannot test type of extern C class "
5087 "without type object name specification")
5089 def generate_post_assignment_code(self, code):
5090 self.arg.generate_post_assignment_code(code)
5092 def free_temps(self, code):
5093 self.arg.free_temps(code)
5096 class NoneCheckNode(CoercionNode):
5097 # This node is used to check that a Python object is not None and
5098 # raises an appropriate exception (as specified by the creating
5099 # transform).
5101 def __init__(self, arg, exception_type_cname, exception_message):
5102 CoercionNode.__init__(self, arg)
5103 self.type = arg.type
5104 self.result_ctype = arg.ctype()
5105 self.exception_type_cname = exception_type_cname
5106 self.exception_message = exception_message
5108 def analyse_types(self, env):
5109 pass
5111 def result_in_temp(self):
5112 return self.arg.result_in_temp()
5114 def calculate_result_code(self):
5115 return self.arg.result()
5117 def generate_result_code(self, code):
5118 code.putln(
5119 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5120 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5121 self.exception_type_cname,
5122 StringEncoding.escape_byte_string(self.exception_message),
5123 code.error_goto(self.pos)))
5124 code.putln("}")
5126 def generate_post_assignment_code(self, code):
5127 self.arg.generate_post_assignment_code(code)
5129 def free_temps(self, code):
5130 self.arg.free_temps(code)
5133 class CoerceToPyTypeNode(CoercionNode):
5134 # This node is used to convert a C data type
5135 # to a Python object.
5137 def __init__(self, arg, env):
5138 CoercionNode.__init__(self, arg)
5139 self.type = py_object_type
5140 self.is_temp = 1
5141 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
5142 error(arg.pos,
5143 "Cannot convert '%s' to Python object" % arg.type)
5145 gil_message = "Converting to Python object"
5147 def coerce_to_boolean(self, env):
5148 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5150 def coerce_to_integer(self, env):
5151 # If not already some C integer type, coerce to longint.
5152 if self.arg.type.is_int:
5153 return self.arg
5154 else:
5155 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5157 def analyse_types(self, env):
5158 # The arg is always already analysed
5159 pass
5161 def generate_result_code(self, code):
5162 function = self.arg.type.to_py_function
5163 code.putln('%s = %s(%s); %s' % (
5164 self.result(),
5165 function,
5166 self.arg.result(),
5167 code.error_goto_if_null(self.result(), self.pos)))
5168 code.put_gotref(self.py_result())
5171 class CoerceFromPyTypeNode(CoercionNode):
5172 # This node is used to convert a Python object
5173 # to a C data type.
5175 def __init__(self, result_type, arg, env):
5176 CoercionNode.__init__(self, arg)
5177 self.type = result_type
5178 self.is_temp = 1
5179 if not result_type.from_py_function:
5180 error(arg.pos,
5181 "Cannot convert Python object to '%s'" % result_type)
5182 if self.type.is_string and self.arg.is_ephemeral():
5183 error(arg.pos,
5184 "Obtaining char * from temporary Python value")
5186 def analyse_types(self, env):
5187 # The arg is always already analysed
5188 pass
5190 def generate_result_code(self, code):
5191 function = self.type.from_py_function
5192 operand = self.arg.py_result()
5193 rhs = "%s(%s)" % (function, operand)
5194 if self.type.is_enum:
5195 rhs = typecast(self.type, c_long_type, rhs)
5196 code.putln('%s = %s; %s' % (
5197 self.result(),
5198 rhs,
5199 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5200 if self.type.is_pyobject:
5201 code.put_gotref(self.py_result())
5204 class CoerceToBooleanNode(CoercionNode):
5205 # This node is used when a result needs to be used
5206 # in a boolean context.
5208 def __init__(self, arg, env):
5209 CoercionNode.__init__(self, arg)
5210 self.type = PyrexTypes.c_bint_type
5211 if arg.type.is_pyobject:
5212 self.is_temp = 1
5214 def gil_check(self, env):
5215 if self.arg.type.is_pyobject:
5216 self._gil_check(env)
5218 gil_message = "Truth-testing Python object"
5220 def check_const(self):
5221 if self.is_temp:
5222 self.not_const()
5223 self.arg.check_const()
5225 def calculate_result_code(self):
5226 return "(%s != 0)" % self.arg.result()
5228 def generate_result_code(self, code):
5229 if self.arg.type.is_pyobject:
5230 code.putln(
5231 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5232 self.result(),
5233 self.arg.py_result(),
5234 code.error_goto_if_neg(self.result(), self.pos)))
5237 class CoerceToTempNode(CoercionNode):
5238 # This node is used to force the result of another node
5239 # to be stored in a temporary. It is only used if the
5240 # argument node's result is not already in a temporary.
5242 def __init__(self, arg, env):
5243 CoercionNode.__init__(self, arg)
5244 self.type = self.arg.type
5245 self.is_temp = 1
5246 if self.type.is_pyobject:
5247 self.result_ctype = py_object_type
5249 gil_message = "Creating temporary Python reference"
5251 def analyse_types(self, env):
5252 # The arg is always already analysed
5253 pass
5255 def coerce_to_boolean(self, env):
5256 self.arg = self.arg.coerce_to_boolean(env)
5257 self.type = self.arg.type
5258 self.result_ctype = self.type
5259 return self
5261 def generate_result_code(self, code):
5262 #self.arg.generate_evaluation_code(code) # Already done
5263 # by generic generate_subexpr_evaluation_code!
5264 code.putln("%s = %s;" % (
5265 self.result(), self.arg.result_as(self.ctype())))
5266 if self.type.is_pyobject:
5267 code.put_incref(self.result(), self.ctype())
5270 class CloneNode(CoercionNode):
5271 # This node is employed when the result of another node needs
5272 # to be used multiple times. The argument node's result must
5273 # be in a temporary. This node "borrows" the result from the
5274 # argument node, and does not generate any evaluation or
5275 # disposal code for it. The original owner of the argument
5276 # node is responsible for doing those things.
5278 subexprs = [] # Arg is not considered a subexpr
5279 gil_check = None
5281 def __init__(self, arg):
5282 CoercionNode.__init__(self, arg)
5283 if hasattr(arg, 'type'):
5284 self.type = arg.type
5285 self.result_ctype = arg.result_ctype
5286 if hasattr(arg, 'entry'):
5287 self.entry = arg.entry
5289 def result(self):
5290 return self.arg.result()
5292 def analyse_types(self, env):
5293 self.type = self.arg.type
5294 self.result_ctype = self.arg.result_ctype
5295 self.is_temp = 1
5296 if hasattr(self.arg, 'entry'):
5297 self.entry = self.arg.entry
5299 def generate_evaluation_code(self, code):
5300 pass
5302 def generate_result_code(self, code):
5303 pass
5305 def generate_disposal_code(self, code):
5306 pass
5308 def allocate_temps(self, env):
5309 pass
5311 def release_temp(self, env):
5312 pass
5314 def free_temps(self, code):
5315 pass
5318 #------------------------------------------------------------------------------------
5320 # Runtime support code
5322 #------------------------------------------------------------------------------------
5324 get_name_interned_utility_code = UtilityCode(
5325 proto = """
5326 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5327 """,
5328 impl = """
5329 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5330 PyObject *result;
5331 result = PyObject_GetAttr(dict, name);
5332 if (!result)
5333 PyErr_SetObject(PyExc_NameError, name);
5334 return result;
5336 """)
5338 #------------------------------------------------------------------------------------
5340 import_utility_code = UtilityCode(
5341 proto = """
5342 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5343 """,
5344 impl = """
5345 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5346 PyObject *__import__ = 0;
5347 PyObject *empty_list = 0;
5348 PyObject *module = 0;
5349 PyObject *global_dict = 0;
5350 PyObject *empty_dict = 0;
5351 PyObject *list;
5352 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5353 if (!__import__)
5354 goto bad;
5355 if (from_list)
5356 list = from_list;
5357 else {
5358 empty_list = PyList_New(0);
5359 if (!empty_list)
5360 goto bad;
5361 list = empty_list;
5363 global_dict = PyModule_GetDict(%(GLOBALS)s);
5364 if (!global_dict)
5365 goto bad;
5366 empty_dict = PyDict_New();
5367 if (!empty_dict)
5368 goto bad;
5369 module = PyObject_CallFunctionObjArgs(__import__,
5370 name, global_dict, empty_dict, list, NULL);
5371 bad:
5372 Py_XDECREF(empty_list);
5373 Py_XDECREF(__import__);
5374 Py_XDECREF(empty_dict);
5375 return module;
5377 """ % {
5378 "BUILTINS": Naming.builtins_cname,
5379 "GLOBALS": Naming.module_cname,
5380 })
5382 #------------------------------------------------------------------------------------
5384 get_exception_utility_code = UtilityCode(
5385 proto = """
5386 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5387 """,
5388 impl = """
5389 static PyObject *__Pyx_GetExcValue(void) {
5390 PyObject *type = 0, *value = 0, *tb = 0;
5391 PyObject *tmp_type, *tmp_value, *tmp_tb;
5392 PyObject *result = 0;
5393 PyThreadState *tstate = PyThreadState_Get();
5394 PyErr_Fetch(&type, &value, &tb);
5395 PyErr_NormalizeException(&type, &value, &tb);
5396 if (PyErr_Occurred())
5397 goto bad;
5398 if (!value) {
5399 value = Py_None;
5400 Py_INCREF(value);
5402 tmp_type = tstate->exc_type;
5403 tmp_value = tstate->exc_value;
5404 tmp_tb = tstate->exc_traceback;
5405 tstate->exc_type = type;
5406 tstate->exc_value = value;
5407 tstate->exc_traceback = tb;
5408 /* Make sure tstate is in a consistent state when we XDECREF
5409 these objects (XDECREF may run arbitrary code). */
5410 Py_XDECREF(tmp_type);
5411 Py_XDECREF(tmp_value);
5412 Py_XDECREF(tmp_tb);
5413 result = value;
5414 Py_XINCREF(result);
5415 type = 0;
5416 value = 0;
5417 tb = 0;
5418 bad:
5419 Py_XDECREF(type);
5420 Py_XDECREF(value);
5421 Py_XDECREF(tb);
5422 return result;
5424 """)
5426 #------------------------------------------------------------------------------------
5428 type_test_utility_code = UtilityCode(
5429 proto = """
5430 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5431 """,
5432 impl = """
5433 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5434 if (!type) {
5435 PyErr_Format(PyExc_SystemError, "Missing type object");
5436 return 0;
5438 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5439 return 1;
5440 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5441 Py_TYPE(obj)->tp_name, type->tp_name);
5442 return 0;
5444 """)
5446 #------------------------------------------------------------------------------------
5448 create_class_utility_code = UtilityCode(
5449 proto = """
5450 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5451 """,
5452 impl = """
5453 static PyObject *__Pyx_CreateClass(
5454 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5456 PyObject *py_modname;
5457 PyObject *result = 0;
5459 #if PY_MAJOR_VERSION < 3
5460 py_modname = PyString_FromString(modname);
5461 #else
5462 py_modname = PyUnicode_FromString(modname);
5463 #endif
5464 if (!py_modname)
5465 goto bad;
5466 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5467 goto bad;
5468 #if PY_MAJOR_VERSION < 3
5469 result = PyClass_New(bases, dict, name);
5470 #else
5471 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5472 #endif
5473 bad:
5474 Py_XDECREF(py_modname);
5475 return result;
5477 """)
5479 #------------------------------------------------------------------------------------
5481 cpp_exception_utility_code = UtilityCode(
5482 proto = """
5483 #ifndef __Pyx_CppExn2PyErr
5484 static void __Pyx_CppExn2PyErr() {
5485 try {
5486 if (PyErr_Occurred())
5487 ; // let the latest Python exn pass through and ignore the current one
5488 else
5489 throw;
5490 } catch (const std::out_of_range& exn) {
5491 // catch out_of_range explicitly so the proper Python exn may be raised
5492 PyErr_SetString(PyExc_IndexError, exn.what());
5493 } catch (const std::exception& exn) {
5494 PyErr_SetString(PyExc_RuntimeError, exn.what());
5496 catch (...)
5498 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5501 #endif
5502 """,
5503 impl = ""
5506 #------------------------------------------------------------------------------------
5508 # If the is_unsigned flag is set, we need to do some extra work to make
5509 # sure the index doesn't become negative.
5511 getitem_int_utility_code = UtilityCode(
5512 proto = """
5514 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5515 PyObject *r;
5516 if (!j) return NULL;
5517 r = PyObject_GetItem(o, j);
5518 Py_DECREF(j);
5519 return r;
5522 """ + ''.join([
5523 """
5524 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5525 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5526 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5528 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5529 if (likely(o != Py_None)) {
5530 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5531 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5532 Py_INCREF(r);
5533 return r;
5535 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5536 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5537 Py_INCREF(r);
5538 return r;
5541 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5543 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5544 ]) + """
5546 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5547 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5548 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5550 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5551 PyObject *r;
5552 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5553 r = PyList_GET_ITEM(o, i);
5554 Py_INCREF(r);
5556 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5557 r = PyTuple_GET_ITEM(o, i);
5558 Py_INCREF(r);
5560 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5561 r = PySequence_GetItem(o, i);
5563 else {
5564 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5566 return r;
5568 """,
5569 impl = """
5570 """)
5574 #------------------------------------------------------------------------------------
5576 setitem_int_utility_code = UtilityCode(
5577 proto = """
5578 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5579 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5580 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5582 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5583 int r;
5584 if (!j) return -1;
5585 r = PyObject_SetItem(o, j, v);
5586 Py_DECREF(j);
5587 return r;
5590 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5591 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5592 Py_DECREF(PyList_GET_ITEM(o, i));
5593 Py_INCREF(v);
5594 PyList_SET_ITEM(o, i, v);
5595 return 1;
5597 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5598 return PySequence_SetItem(o, i, v);
5599 else {
5600 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5601 return __Pyx_SetItemInt_Generic(o, j, v);
5604 """,
5605 impl = """
5606 """)
5608 #------------------------------------------------------------------------------------
5610 delitem_int_utility_code = UtilityCode(
5611 proto = """
5612 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5613 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5614 __Pyx_DelItem_Generic(o, to_py_func(i)))
5616 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5617 int r;
5618 if (!j) return -1;
5619 r = PyObject_DelItem(o, j);
5620 Py_DECREF(j);
5621 return r;
5624 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5625 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5626 return PySequence_DelItem(o, i);
5627 else {
5628 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5629 return __Pyx_DelItem_Generic(o, j);
5632 """,
5633 impl = """
5634 """)
5636 #------------------------------------------------------------------------------------
5638 raise_noneattr_error_utility_code = UtilityCode(
5639 proto = """
5640 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5641 """,
5642 impl = '''
5643 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5644 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5646 ''')
5648 raise_noneindex_error_utility_code = UtilityCode(
5649 proto = """
5650 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5651 """,
5652 impl = '''
5653 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5654 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5656 ''')
5658 raise_none_iter_error_utility_code = UtilityCode(
5659 proto = """
5660 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5661 """,
5662 impl = '''
5663 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5664 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5666 ''')
5668 raise_too_many_values_to_unpack = UtilityCode(
5669 proto = """
5670 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5671 """,
5672 impl = '''
5673 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5674 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5676 ''')
5678 raise_need_more_values_to_unpack = UtilityCode(
5679 proto = """
5680 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5681 """,
5682 impl = '''
5683 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5684 PyErr_Format(PyExc_ValueError,
5685 #if PY_VERSION_HEX < 0x02050000
5686 "need more than %d value%s to unpack", (int)index,
5687 #else
5688 "need more than %zd value%s to unpack", index,
5689 #endif
5690 (index == 1) ? "" : "s");
5692 ''')
5694 #------------------------------------------------------------------------------------
5696 tuple_unpacking_error_code = UtilityCode(
5697 proto = """
5698 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
5699 """,
5700 impl = """
5701 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
5702 if (t == Py_None) {
5703 __Pyx_RaiseNoneNotIterableError();
5704 } else if (PyTuple_GET_SIZE(t) < index) {
5705 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
5706 } else {
5707 __Pyx_RaiseTooManyValuesError();
5710 """,
5711 requires = [raise_none_iter_error_utility_code,
5712 raise_need_more_values_to_unpack,
5713 raise_too_many_values_to_unpack]
5716 unpacking_utility_code = UtilityCode(
5717 proto = """
5718 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5719 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5720 """,
5721 impl = """
5722 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5723 PyObject *item;
5724 if (!(item = PyIter_Next(iter))) {
5725 if (!PyErr_Occurred()) {
5726 __Pyx_RaiseNeedMoreValuesError(index);
5729 return item;
5732 static int __Pyx_EndUnpack(PyObject *iter) {
5733 PyObject *item;
5734 if ((item = PyIter_Next(iter))) {
5735 Py_DECREF(item);
5736 __Pyx_RaiseTooManyValuesError();
5737 return -1;
5739 else if (!PyErr_Occurred())
5740 return 0;
5741 else
5742 return -1;
5744 """,
5745 requires = [raise_need_more_values_to_unpack,
5746 raise_too_many_values_to_unpack]
5750 #------------------------------------------------------------------------------------
5752 int_pow_utility_code = UtilityCode(
5753 proto="""
5754 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
5755 """,
5756 impl="""
5757 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
5758 %(type)s t = b;
5759 switch (e) {
5760 case 3:
5761 t *= b;
5762 case 2:
5763 t *= b;
5764 case 1:
5765 return t;
5766 case 0:
5767 return 1;
5769 if (unlikely(e<0)) return 0;
5770 t = 1;
5771 while (likely(e)) {
5772 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
5773 b *= b;
5774 e >>= 1;
5776 return t;
5778 """)
5780 # ------------------------------ Division ------------------------------------
5782 div_int_utility_code = UtilityCode(
5783 proto="""
5784 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
5785 """,
5786 impl="""
5787 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
5788 %(type)s q = a / b;
5789 %(type)s r = a - q*b;
5790 q -= ((r != 0) & ((r ^ b) < 0));
5791 return q;
5793 """)
5795 mod_int_utility_code = UtilityCode(
5796 proto="""
5797 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5798 """,
5799 impl="""
5800 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5801 %(type)s r = a %% b;
5802 r += ((r != 0) & ((r ^ b) < 0)) * b;
5803 return r;
5805 """)
5807 mod_float_utility_code = UtilityCode(
5808 proto="""
5809 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5810 """,
5811 impl="""
5812 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5813 %(type)s r = fmod%(math_h_modifier)s(a, b);
5814 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
5815 return r;
5817 """)
5819 cdivision_warning_utility_code = UtilityCode(
5820 proto="""
5821 static int __Pyx_cdivision_warning(void); /* proto */
5822 """,
5823 impl="""
5824 static int __Pyx_cdivision_warning(void) {
5825 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
5826 "division with oppositely signed operands, C and Python semantics differ",
5827 %(FILENAME)s,
5828 %(LINENO)s,
5829 %(MODULENAME)s,
5830 NULL);
5832 """ % {
5833 'FILENAME': Naming.filename_cname,
5834 'MODULENAME': Naming.modulename_cname,
5835 'LINENO': Naming.lineno_cname,
5836 })