Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 1925:9a445f71940f
Fix #267
| author | Dag Sverre Seljebotn <dagss@student.matnat.uio.no> |
|---|---|
| date | Sun Mar 29 12:19:11 2009 +0200 (3 years ago) |
| parents | 413a75b92fc0 |
| children | 6b5e32a276ac |
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 calculate_constant_result(self):
244 # Calculate the constant result of this expression and store
245 # it in ``self.constant_result``. Does nothing by default,
246 # thus leaving ``self.constant_result`` unknown.
247 #
248 # This must only be called when it is assured that all
249 # sub-expressions have a valid constant_result value. The
250 # ConstantFolding transform will do this.
251 pass
253 def compile_time_value(self, denv):
254 # Return value of compile-time expression, or report error.
255 error(self.pos, "Invalid compile-time expression")
257 def compile_time_value_error(self, e):
258 error(self.pos, "Error in compile-time expression: %s: %s" % (
259 e.__class__.__name__, e))
261 # ------------- Declaration Analysis ----------------
263 def analyse_target_declaration(self, env):
264 error(self.pos, "Cannot assign to or delete this")
266 # ------------- Expression Analysis ----------------
268 def analyse_const_expression(self, env):
269 # Called during the analyse_declarations phase of a
270 # constant expression. Analyses the expression's type,
271 # checks whether it is a legal const expression,
272 # and determines its value.
273 self.analyse_types(env)
274 self.allocate_temps(env)
275 self.check_const()
277 def analyse_expressions(self, env):
278 # Convenience routine performing both the Type
279 # Analysis and Temp Allocation phases for a whole
280 # expression.
281 self.analyse_types(env)
282 self.allocate_temps(env)
284 def analyse_target_expression(self, env, rhs):
285 # Convenience routine performing both the Type
286 # Analysis and Temp Allocation phases for the LHS of
287 # an assignment.
288 self.analyse_target_types(env)
289 self.allocate_target_temps(env, rhs)
291 def analyse_boolean_expression(self, env):
292 # Analyse expression and coerce to a boolean.
293 self.analyse_types(env)
294 bool = self.coerce_to_boolean(env)
295 bool.allocate_temps(env)
296 return bool
298 def analyse_temp_boolean_expression(self, env):
299 # Analyse boolean expression and coerce result into
300 # a temporary. This is used when a branch is to be
301 # performed on the result and we won't have an
302 # opportunity to ensure disposal code is executed
303 # afterwards. By forcing the result into a temporary,
304 # we ensure that all disposal has been done by the
305 # time we get the result.
306 self.analyse_types(env)
307 bool = self.coerce_to_boolean(env)
308 temp_bool = bool.coerce_to_temp(env)
309 temp_bool.allocate_temps(env)
310 return temp_bool
312 # --------------- Type Analysis ------------------
314 def analyse_as_module(self, env):
315 # If this node can be interpreted as a reference to a
316 # cimported module, return its scope, else None.
317 return None
319 def analyse_as_type(self, env):
320 # If this node can be interpreted as a reference to a
321 # type, return that type, else None.
322 return None
324 def analyse_as_extension_type(self, env):
325 # If this node can be interpreted as a reference to an
326 # extension type, return its type, else None.
327 return None
329 def analyse_types(self, env):
330 self.not_implemented("analyse_types")
332 def analyse_target_types(self, env):
333 self.analyse_types(env)
335 def gil_assignment_check(self, env):
336 if env.nogil and self.type.is_pyobject:
337 error(self.pos, "Assignment of Python object not allowed without gil")
339 def check_const(self):
340 self.not_const()
342 def not_const(self):
343 error(self.pos, "Not allowed in a constant expression")
345 def check_const_addr(self):
346 self.addr_not_const()
348 def addr_not_const(self):
349 error(self.pos, "Address is not constant")
351 def gil_check(self, env):
352 if env is not None and env.nogil and self.type.is_pyobject:
353 self.gil_error()
355 # ----------------- Result Allocation -----------------
357 def result_in_temp(self):
358 # Return true if result is in a temporary owned by
359 # this node or one of its subexpressions. Overridden
360 # by certain nodes which can share the result of
361 # a subnode.
362 return self.is_temp
364 def allocate_target_temps(self, env, rhs):
365 # Perform temp allocation for the LHS of an assignment.
366 if debug_temp_alloc:
367 print("%s Allocating target temps" % self)
368 self.allocate_subexpr_temps(env)
369 self.is_target = True
370 if rhs:
371 rhs.release_temp(env)
372 self.release_subexpr_temps(env)
374 def allocate_temps(self, env, result = None):
375 # Allocate temporary variables for this node and
376 # all its sub-expressions. If a result is specified,
377 # this must be a temp node and the specified variable
378 # is used as the result instead of allocating a new
379 # one.
380 if debug_temp_alloc:
381 print("%s Allocating temps" % self)
382 self.allocate_subexpr_temps(env)
383 self.allocate_temp(env, result)
384 if self.is_temp:
385 self.release_subexpr_temps(env)
387 def allocate_subexpr_temps(self, env):
388 # Allocate temporary variables for all sub-expressions
389 # of this node.
390 if debug_temp_alloc:
391 print("%s Allocating temps for: %s" % (self, self.subexprs))
392 for node in self.subexpr_nodes():
393 if node:
394 if debug_temp_alloc:
395 print("%s Allocating temps for %s" % (self, node))
396 node.allocate_temps(env)
398 def allocate_temp(self, env, result = None):
399 # If this node requires a temporary variable for its
400 # result, allocate one, otherwise set the result to
401 # a C code fragment. If a result is specified,
402 # this must be a temp node and the specified variable
403 # is used as the result instead of allocating a new
404 # one.
405 if debug_temp_alloc:
406 print("%s Allocating temp" % self)
407 if result:
408 if not self.is_temp:
409 raise InternalError("Result forced on non-temp node")
410 self.result_code = result
411 elif self.is_temp:
412 type = self.type
413 if not type.is_void:
414 if type.is_pyobject:
415 type = PyrexTypes.py_object_type
416 self.result_code = env.allocate_temp(type)
417 else:
418 self.result_code = None
419 if debug_temp_alloc:
420 print("%s Allocated result %s" % (self, self.result_code))
422 def target_code(self):
423 # Return code fragment for use as LHS of a C assignment.
424 return self.calculate_result_code()
426 def calculate_result_code(self):
427 self.not_implemented("calculate_result_code")
429 # def release_target_temp(self, env):
430 # # Release temporaries used by LHS of an assignment.
431 # self.release_subexpr_temps(env)
433 def release_temp(self, env):
434 # If this node owns a temporary result, release it,
435 # otherwise release results of its sub-expressions.
436 if self.is_temp:
437 if debug_temp_alloc:
438 print("%s Releasing result %s" % (self, self.result_code))
439 env.release_temp(self.result_code)
440 else:
441 self.release_subexpr_temps(env)
443 def release_subexpr_temps(self, env):
444 # Release the results of all sub-expressions of
445 # this node.
446 for node in self.subexpr_nodes():
447 if node:
448 node.release_temp(env)
450 # ---------------- Code Generation -----------------
452 def make_owned_reference(self, code):
453 # If result is a pyobject, make sure we own
454 # a reference to it.
455 if self.type.is_pyobject and not self.result_in_temp():
456 code.put_incref(self.result(), self.ctype())
458 def generate_evaluation_code(self, code):
459 code.mark_pos(self.pos)
460 # Generate code to evaluate this node and
461 # its sub-expressions, and dispose of any
462 # temporary results of its sub-expressions.
463 self.generate_subexpr_evaluation_code(code)
464 self.generate_result_code(code)
465 if self.is_temp:
466 self.generate_subexpr_disposal_code(code)
467 self.free_subexpr_temps(code)
469 def generate_subexpr_evaluation_code(self, code):
470 for node in self.subexpr_nodes():
471 node.generate_evaluation_code(code)
473 def generate_result_code(self, code):
474 self.not_implemented("generate_result_code")
476 def generate_disposal_code(self, code):
477 # If necessary, generate code to dispose of
478 # temporary Python reference.
479 if self.is_temp:
480 if self.type.is_pyobject:
481 code.put_decref_clear(self.result(), self.ctype())
482 else:
483 self.generate_subexpr_disposal_code(code)
485 def generate_subexpr_disposal_code(self, code):
486 # Generate code to dispose of temporary results
487 # of all sub-expressions.
488 for node in self.subexpr_nodes():
489 node.generate_disposal_code(code)
491 def generate_post_assignment_code(self, code):
492 # Same as generate_disposal_code except that
493 # assignment will have absorbed a reference to
494 # the result if it is a Python object.
495 if self.is_temp:
496 if self.type.is_pyobject:
497 code.putln("%s = 0;" % self.result())
498 else:
499 self.generate_subexpr_disposal_code(code)
501 def generate_assignment_code(self, rhs, code):
502 # Stub method for nodes which are not legal as
503 # the LHS of an assignment. An error will have
504 # been reported earlier.
505 pass
507 def generate_deletion_code(self, code):
508 # Stub method for nodes that are not legal as
509 # the argument of a del statement. An error
510 # will have been reported earlier.
511 pass
513 def free_temps(self, code):
514 if not self.is_temp:
515 self.free_subexpr_temps(code)
516 # otherwise, already freed in generate_evaluation_code
518 def free_subexpr_temps(self, code):
519 for sub in self.subexpr_nodes():
520 sub.free_temps(code)
522 # ---------------- Annotation ---------------------
524 def annotate(self, code):
525 for node in self.subexpr_nodes():
526 node.annotate(code)
528 # ----------------- Coercion ----------------------
530 def coerce_to(self, dst_type, env):
531 # Coerce the result so that it can be assigned to
532 # something of type dst_type. If processing is necessary,
533 # wraps this node in a coercion node and returns that.
534 # Otherwise, returns this node unchanged.
535 #
536 # This method is called during the analyse_expressions
537 # phase of the src_node's processing.
538 src = self
539 src_type = self.type
540 src_is_py_type = src_type.is_pyobject
541 dst_is_py_type = dst_type.is_pyobject
543 if dst_type.is_pyobject:
544 if not src.type.is_pyobject:
545 src = CoerceToPyTypeNode(src, env)
546 if not src.type.subtype_of(dst_type):
547 if not isinstance(src, NoneNode):
548 src = PyTypeTestNode(src, dst_type, env)
549 elif src.type.is_pyobject:
550 src = CoerceFromPyTypeNode(dst_type, src, env)
551 else: # neither src nor dst are py types
552 # Added the string comparison, since for c types that
553 # is enough, but Cython gets confused when the types are
554 # in different files.
555 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
556 error(self.pos, "Cannot assign type '%s' to '%s'" %
557 (src.type, dst_type))
558 return src
560 def coerce_to_pyobject(self, env):
561 return self.coerce_to(PyrexTypes.py_object_type, env)
563 def coerce_to_boolean(self, env):
564 # Coerce result to something acceptable as
565 # a boolean value.
566 type = self.type
567 if type.is_pyobject or type.is_ptr or type.is_float:
568 return CoerceToBooleanNode(self, env)
569 else:
570 if not type.is_int and not type.is_error:
571 error(self.pos,
572 "Type '%s' not acceptable as a boolean" % type)
573 return self
575 def coerce_to_integer(self, env):
576 # If not already some C integer type, coerce to longint.
577 if self.type.is_int:
578 return self
579 else:
580 return self.coerce_to(PyrexTypes.c_long_type, env)
582 def coerce_to_temp(self, env):
583 # Ensure that the result is in a temporary.
584 if self.result_in_temp():
585 return self
586 else:
587 return CoerceToTempNode(self, env)
589 def coerce_to_simple(self, env):
590 # Ensure that the result is simple (see is_simple).
591 if self.is_simple():
592 return self
593 else:
594 return self.coerce_to_temp(env)
596 def is_simple(self):
597 # A node is simple if its result is something that can
598 # be referred to without performing any operations, e.g.
599 # a constant, local var, C global var, struct member
600 # reference, or temporary.
601 return self.result_in_temp()
603 def as_cython_attribute(self):
604 return None
607 class RemoveAllocateTemps(type):
608 def __init__(cls, name, bases, dct):
609 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
610 def noop(self, env): pass
611 setattr(cls, 'allocate_temps', noop)
612 setattr(cls, 'allocate_temp', noop)
613 setattr(cls, 'release_temp', noop)
615 class NewTempExprNode(ExprNode):
616 backwards_compatible_result = None
617 temp_code = None
618 old_temp = None # error checker for multiple frees etc.
620 # Do not enable this unless you are trying to make all ExprNodes
621 # NewTempExprNodes (child nodes reached via recursion may not have
622 # transferred).
623 # __metaclass__ = RemoveAllocateTemps
625 def result(self):
626 if self.is_temp:
627 return self.temp_code
628 else:
629 return self.calculate_result_code()
631 def allocate_target_temps(self, env, rhs):
632 self.allocate_subexpr_temps(env)
633 self.is_target = True
634 if rhs:
635 rhs.release_temp(env)
636 self.release_subexpr_temps(env)
638 def allocate_temps(self, env, result = None):
639 self.allocate_subexpr_temps(env)
640 self.backwards_compatible_result = result
641 if self.is_temp:
642 self.release_subexpr_temps(env)
644 def allocate_temp(self, env, result = None):
645 assert result is None
647 def release_temp(self, env):
648 if self.is_temp:
649 pass
650 else:
651 self.release_subexpr_temps(env)
653 def allocate_temp_result(self, code):
654 if self.temp_code:
655 raise RuntimeError("Temp allocated multiple times")
656 type = self.type
657 if not type.is_void:
658 if type.is_pyobject:
659 type = PyrexTypes.py_object_type
660 if self.backwards_compatible_result:
661 self.temp_code = self.backwards_compatible_result
662 else:
663 self.temp_code = code.funcstate.allocate_temp(
664 type, manage_ref=True)
665 else:
666 self.temp_code = None
668 def release_temp_result(self, code):
669 if not self.temp_code:
670 if self.old_temp:
671 raise RuntimeError("temp %s released multiple times in %s" % (
672 self.old_temp, self.__class__.__name__))
673 else:
674 raise RuntimeError("no temp, but release requested in %s" % (
675 self.__class__.__name__))
676 code.funcstate.release_temp(self.temp_code)
677 self.old_temp = self.temp_code
678 self.temp_code = None
680 def generate_evaluation_code(self, code):
681 code.mark_pos(self.pos)
683 # Generate code to evaluate this node and
684 # its sub-expressions, and dispose of any
685 # temporary results of its sub-expressions.
686 self.generate_subexpr_evaluation_code(code)
688 if self.is_temp:
689 self.allocate_temp_result(code)
691 self.generate_result_code(code)
692 if self.is_temp:
693 # If we are temp we do not need to wait until this node is disposed
694 # before disposing children.
695 self.generate_subexpr_disposal_code(code)
696 self.free_subexpr_temps(code)
698 def generate_disposal_code(self, code):
699 if self.is_temp:
700 if self.type.is_pyobject:
701 code.put_decref_clear(self.result(), self.ctype())
702 else:
703 # Already done if self.is_temp
704 self.generate_subexpr_disposal_code(code)
706 def generate_post_assignment_code(self, code):
707 if self.is_temp:
708 if self.type.is_pyobject:
709 code.putln("%s = 0;" % self.result())
710 else:
711 self.generate_subexpr_disposal_code(code)
713 def free_temps(self, code):
714 if self.is_temp:
715 if not self.type.is_void:
716 self.release_temp_result(code)
717 else:
718 self.free_subexpr_temps(code)
720 # ExprNode = NewTempExprNode
722 class AtomicExprNode(ExprNode):
723 # Abstract base class for expression nodes which have
724 # no sub-expressions.
726 subexprs = []
728 class AtomicNewTempExprNode(NewTempExprNode):
729 # I do not dare to convert NameNode yet. This is now
730 # ancestor of all former AtomicExprNode except
731 # NameNode. Should be renamed to AtomicExprNode
732 # when done.
734 # Abstract base class for expression nodes which have
735 # no sub-expressions.
737 subexprs = []
739 # Override to optimize -- we know we have no children
740 def generate_subexpr_evaluation_code(self, code):
741 pass
742 def generate_subexpr_disposal_code(self, code):
743 pass
745 class PyConstNode(AtomicNewTempExprNode):
746 # Abstract base class for constant Python values.
748 is_literal = 1
750 def is_simple(self):
751 return 1
753 def analyse_types(self, env):
754 self.type = py_object_type
756 def calculate_result_code(self):
757 return self.value
759 def generate_result_code(self, code):
760 pass
763 class NoneNode(PyConstNode):
764 # The constant value None
766 value = "Py_None"
768 constant_result = None
770 def compile_time_value(self, denv):
771 return None
773 class EllipsisNode(PyConstNode):
774 # '...' in a subscript list.
776 value = "Py_Ellipsis"
778 constant_result = Ellipsis
780 def compile_time_value(self, denv):
781 return Ellipsis
784 class ConstNode(AtomicNewTempExprNode):
785 # Abstract base type for literal constant nodes.
786 #
787 # value string C code fragment
789 is_literal = 1
791 def is_simple(self):
792 return 1
794 def analyse_types(self, env):
795 pass # Types are held in class variables
797 def check_const(self):
798 pass
800 def calculate_result_code(self):
801 return str(self.value)
803 def generate_result_code(self, code):
804 pass
807 class BoolNode(ConstNode):
808 type = PyrexTypes.c_bint_type
809 # The constant value True or False
811 def calculate_constant_result(self):
812 self.constant_result = self.value
814 def compile_time_value(self, denv):
815 return self.value
817 def calculate_result_code(self):
818 return str(int(self.value))
820 class NullNode(ConstNode):
821 type = PyrexTypes.c_null_ptr_type
822 value = "NULL"
823 constant_result = 0
826 class CharNode(ConstNode):
827 type = PyrexTypes.c_char_type
829 def calculate_constant_result(self):
830 self.constant_result = ord(self.value)
832 def compile_time_value(self, denv):
833 return ord(self.value)
835 def calculate_result_code(self):
836 return "'%s'" % StringEncoding.escape_character(self.value)
839 class IntNode(ConstNode):
841 # unsigned "" or "U"
842 # longness "" or "L" or "LL"
844 unsigned = ""
845 longness = ""
846 type = PyrexTypes.c_long_type
848 def coerce_to(self, dst_type, env):
849 if dst_type.is_numeric:
850 self.type = PyrexTypes.c_long_type
851 return self
852 # Arrange for a Python version of the number to be pre-allocated
853 # when coercing to a Python type.
854 if dst_type.is_pyobject:
855 self.entry = env.get_py_num(self.value, self.longness)
856 self.type = PyrexTypes.py_object_type
857 # We still need to perform normal coerce_to processing on the
858 # result, because we might be coercing to an extension type,
859 # in which case a type test node will be needed.
860 return ConstNode.coerce_to(self, dst_type, env)
862 def coerce_to_boolean(self, env):
863 self.type = PyrexTypes.c_bint_type
864 return self
866 def calculate_result_code(self):
867 if self.type.is_pyobject:
868 return self.entry.cname
869 else:
870 return str(self.value) + self.unsigned + self.longness
872 def calculate_constant_result(self):
873 self.constant_result = int(self.value, 0)
875 def compile_time_value(self, denv):
876 return int(self.value, 0)
879 class FloatNode(ConstNode):
880 type = PyrexTypes.c_double_type
882 def calculate_constant_result(self):
883 self.constant_result = float(self.value)
885 def compile_time_value(self, denv):
886 return float(self.value)
888 def calculate_result_code(self):
889 strval = repr(float(self.value))
890 if strval == 'nan':
891 return "(Py_HUGE_VAL * 0)"
892 elif strval == 'inf':
893 return "Py_HUGE_VAL"
894 elif strval == '-inf':
895 return "(-Py_HUGE_VAL)"
896 else:
897 return strval
900 class StringNode(ConstNode):
901 # entry Symtab.Entry
903 type = PyrexTypes.c_char_ptr_type
905 def compile_time_value(self, denv):
906 return self.value
908 def analyse_types(self, env):
909 self.entry = env.add_string_const(self.value)
911 def analyse_as_type(self, env):
912 type = PyrexTypes.parse_basic_type(self.value)
913 if type is not None:
914 return type
915 from TreeFragment import TreeFragment
916 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
917 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
918 sizeof_node = declaration.root.stats[0].expr
919 sizeof_node.analyse_types(env)
920 if isinstance(sizeof_node, SizeofTypeNode):
921 return sizeof_node.arg_type
923 def coerce_to(self, dst_type, env):
924 if dst_type == PyrexTypes.c_char_ptr_type:
925 self.type = PyrexTypes.c_char_ptr_type
926 return self
928 if dst_type.is_int:
929 if not self.type.is_pyobject and len(self.entry.init) == 1:
930 return CharNode(self.pos, value=self.value)
931 else:
932 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
933 return self
934 # Arrange for a Python version of the string to be pre-allocated
935 # when coercing to a Python type.
936 if dst_type.is_pyobject and not self.type.is_pyobject:
937 node = self.as_py_string_node(env)
938 else:
939 node = self
940 # We still need to perform normal coerce_to processing on the
941 # result, because we might be coercing to an extension type,
942 # in which case a type test node will be needed.
943 return ConstNode.coerce_to(node, dst_type, env)
945 def as_py_string_node(self, env):
946 # Return a new StringNode with the same entry as this node
947 # but whose type is a Python type instead of a C type.
948 entry = self.entry
949 env.add_py_string(entry)
950 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
952 def calculate_result_code(self):
953 if self.type.is_pyobject:
954 return self.entry.pystring_cname
955 else:
956 return self.entry.cname
959 class UnicodeNode(PyConstNode):
960 # entry Symtab.Entry
962 type = unicode_type
964 def analyse_types(self, env):
965 self.entry = env.add_string_const(self.value)
966 env.add_py_string(self.entry)
968 def calculate_result_code(self):
969 return self.entry.pystring_cname
971 def _coerce_to(self, dst_type, env):
972 if not dst_type.is_pyobject:
973 node = StringNode(self.pos, entry = entry, type = py_object_type)
974 return ConstNode.coerce_to(node, dst_type, env)
975 else:
976 return self
977 # We still need to perform normal coerce_to processing on the
978 # result, because we might be coercing to an extension type,
979 # in which case a type test node will be needed.
981 def compile_time_value(self, env):
982 return self.value
985 class IdentifierStringNode(ConstNode):
986 # A Python string that behaves like an identifier, e.g. for
987 # keyword arguments in a call, or for imported names
988 type = PyrexTypes.py_object_type
990 def analyse_types(self, env):
991 self.cname = env.intern_identifier(self.value)
993 def calculate_result_code(self):
994 return self.cname
997 class LongNode(AtomicNewTempExprNode):
998 # Python long integer literal
999 #
1000 # value string
1002 def calculate_constant_result(self):
1003 self.constant_result = long(self.value)
1005 def compile_time_value(self, denv):
1006 return long(self.value)
1008 gil_message = "Constructing Python long int"
1010 def analyse_types(self, env):
1011 self.type = py_object_type
1012 self.gil_check(env)
1013 self.is_temp = 1
1015 gil_message = "Constructing Python long int"
1017 def generate_result_code(self, code):
1018 code.putln(
1019 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1020 self.result(),
1021 self.value,
1022 code.error_goto_if_null(self.result(), self.pos)))
1023 code.put_gotref(self.py_result())
1026 class ImagNode(AtomicNewTempExprNode):
1027 # Imaginary number literal
1028 #
1029 # value float imaginary part
1031 def calculate_constant_result(self):
1032 self.constant_result = complex(0.0, self.value)
1034 def compile_time_value(self, denv):
1035 return complex(0.0, self.value)
1037 def analyse_types(self, env):
1038 self.type = py_object_type
1039 self.gil_check(env)
1040 self.is_temp = 1
1042 gil_message = "Constructing complex number"
1044 def generate_result_code(self, code):
1045 code.putln(
1046 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1047 self.result(),
1048 float(self.value),
1049 code.error_goto_if_null(self.result(), self.pos)))
1050 code.put_gotref(self.py_result())
1054 class NameNode(AtomicExprNode):
1055 # Reference to a local or global variable name.
1056 #
1057 # name string Python name of the variable
1058 #
1059 # entry Entry Symbol table entry
1060 # interned_cname string
1062 is_name = True
1063 is_cython_module = False
1064 cython_attribute = None
1065 lhs_of_first_assignment = False
1066 entry = None
1068 def create_analysed_rvalue(pos, env, entry):
1069 node = NameNode(pos)
1070 node.analyse_types(env, entry=entry)
1071 return node
1073 def as_cython_attribute(self):
1074 return self.cython_attribute
1076 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1078 def compile_time_value(self, denv):
1079 try:
1080 return denv.lookup(self.name)
1081 except KeyError:
1082 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1084 def coerce_to(self, dst_type, env):
1085 # If coercing to a generic pyobject and this is a builtin
1086 # C function with a Python equivalent, manufacture a NameNode
1087 # referring to the Python builtin.
1088 #print "NameNode.coerce_to:", self.name, dst_type ###
1089 if dst_type is py_object_type:
1090 entry = self.entry
1091 if entry and entry.is_cfunction:
1092 var_entry = entry.as_variable
1093 if var_entry:
1094 if var_entry.is_builtin and Options.cache_builtins:
1095 var_entry = env.declare_builtin(var_entry.name, self.pos)
1096 node = NameNode(self.pos, name = self.name)
1097 node.entry = var_entry
1098 node.analyse_rvalue_entry(env)
1099 return node
1100 return AtomicExprNode.coerce_to(self, dst_type, env)
1102 def analyse_as_module(self, env):
1103 # Try to interpret this as a reference to a cimported module.
1104 # Returns the module scope, or None.
1105 entry = self.entry
1106 if not entry:
1107 entry = env.lookup(self.name)
1108 if entry and entry.as_module:
1109 return entry.as_module
1110 return None
1112 def analyse_as_type(self, env):
1113 if self.cython_attribute:
1114 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1115 else:
1116 type = PyrexTypes.parse_basic_type(self.name)
1117 if type:
1118 return type
1119 entry = self.entry
1120 if not entry:
1121 entry = env.lookup(self.name)
1122 if entry and entry.is_type:
1123 return entry.type
1124 else:
1125 return None
1127 def analyse_as_extension_type(self, env):
1128 # Try to interpret this as a reference to an extension type.
1129 # Returns the extension type, or None.
1130 entry = self.entry
1131 if not entry:
1132 entry = env.lookup(self.name)
1133 if entry and entry.is_type and entry.type.is_extension_type:
1134 return entry.type
1135 else:
1136 return None
1138 def analyse_target_declaration(self, env):
1139 if not self.entry:
1140 self.entry = env.lookup_here(self.name)
1141 if not self.entry:
1142 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1143 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1144 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1145 if self.entry.is_declared_generic:
1146 self.result_ctype = py_object_type
1148 def analyse_types(self, env):
1149 if self.entry is None:
1150 self.entry = env.lookup(self.name)
1151 if not self.entry:
1152 self.entry = env.declare_builtin(self.name, self.pos)
1153 if not self.entry:
1154 self.type = PyrexTypes.error_type
1155 return
1156 self.analyse_rvalue_entry(env)
1158 def analyse_target_types(self, env):
1159 self.analyse_entry(env)
1160 if not self.is_lvalue():
1161 error(self.pos, "Assignment to non-lvalue '%s'"
1162 % self.name)
1163 self.type = PyrexTypes.error_type
1164 self.entry.used = 1
1165 if self.entry.type.is_buffer:
1166 import Buffer
1167 Buffer.used_buffer_aux_vars(self.entry)
1169 def analyse_rvalue_entry(self, env):
1170 #print "NameNode.analyse_rvalue_entry:", self.name ###
1171 #print "Entry:", self.entry.__dict__ ###
1172 self.analyse_entry(env)
1173 entry = self.entry
1174 if entry.is_declared_generic:
1175 self.result_ctype = py_object_type
1176 if entry.is_pyglobal or entry.is_builtin:
1177 if Options.cache_builtins and entry.is_builtin:
1178 self.is_temp = 0
1179 else:
1180 self.is_temp = 1
1181 env.use_utility_code(get_name_interned_utility_code)
1182 self.gil_check(env)
1184 gil_message = "Accessing Python global or builtin"
1186 def analyse_entry(self, env):
1187 #print "NameNode.analyse_entry:", self.name ###
1188 self.check_identifier_kind()
1189 entry = self.entry
1190 type = entry.type
1191 self.type = type
1192 if entry.is_pyglobal or entry.is_builtin:
1193 assert type.is_pyobject, "Python global or builtin not a Python object"
1194 self.interned_cname = self.entry.interned_cname = \
1195 env.intern_identifier(self.entry.name)
1197 def check_identifier_kind(self):
1198 #print "NameNode.check_identifier_kind:", self.entry.name ###
1199 #print self.entry.__dict__ ###
1200 entry = self.entry
1201 #entry.used = 1
1202 if not (entry.is_const or entry.is_variable
1203 or entry.is_builtin or entry.is_cfunction):
1204 if self.entry.as_variable:
1205 self.entry = self.entry.as_variable
1206 else:
1207 error(self.pos,
1208 "'%s' is not a constant, variable or function identifier" % self.name)
1210 def is_simple(self):
1211 # If it's not a C variable, it'll be in a temp.
1212 return 1
1214 def calculate_target_results(self, env):
1215 pass
1217 def check_const(self):
1218 entry = self.entry
1219 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1220 self.not_const()
1222 def check_const_addr(self):
1223 entry = self.entry
1224 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1225 self.addr_not_const()
1227 def is_lvalue(self):
1228 return self.entry.is_variable and \
1229 not self.entry.type.is_array and \
1230 not self.entry.is_readonly
1232 def is_ephemeral(self):
1233 # Name nodes are never ephemeral, even if the
1234 # result is in a temporary.
1235 return 0
1237 def allocate_temp(self, env, result = None):
1238 AtomicExprNode.allocate_temp(self, env, result)
1239 entry = self.entry
1240 if entry:
1241 entry.used = 1
1242 if entry.type.is_buffer:
1243 import Buffer
1244 Buffer.used_buffer_aux_vars(entry)
1245 if entry.utility_code:
1246 env.use_utility_code(entry.utility_code)
1248 def calculate_result_code(self):
1249 entry = self.entry
1250 if not entry:
1251 return "<error>" # There was an error earlier
1252 return entry.cname
1254 def generate_result_code(self, code):
1255 assert hasattr(self, 'entry')
1256 entry = self.entry
1257 if entry is None:
1258 return # There was an error earlier
1259 if entry.is_builtin and Options.cache_builtins:
1260 return # Lookup already cached
1261 elif entry.is_pyglobal or entry.is_builtin:
1262 if entry.is_builtin:
1263 namespace = Naming.builtins_cname
1264 else: # entry.is_pyglobal
1265 namespace = entry.scope.namespace_cname
1266 code.putln(
1267 '%s = __Pyx_GetName(%s, %s); %s' % (
1268 self.result(),
1269 namespace,
1270 self.interned_cname,
1271 code.error_goto_if_null(self.result(), self.pos)))
1272 code.put_gotref(self.py_result())
1274 elif entry.is_local and False:
1275 # control flow not good enough yet
1276 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1277 if assigned is False:
1278 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1279 elif not Options.init_local_none and assigned is None:
1280 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1281 (entry.cname, entry.name, code.error_goto(self.pos)))
1282 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1284 def generate_assignment_code(self, rhs, code):
1285 #print "NameNode.generate_assignment_code:", self.name ###
1286 entry = self.entry
1287 if entry is None:
1288 return # There was an error earlier
1290 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1291 and not self.lhs_of_first_assignment):
1292 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1294 # is_pyglobal seems to be True for module level-globals only.
1295 # We use this to access class->tp_dict if necessary.
1296 if entry.is_pyglobal:
1297 namespace = self.entry.scope.namespace_cname
1298 if entry.is_member:
1299 # if the entry is a member we have to cheat: SetAttr does not work
1300 # on types, so we create a descriptor which is then added to tp_dict
1301 code.put_error_if_neg(self.pos,
1302 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1303 namespace,
1304 self.interned_cname,
1305 rhs.py_result()))
1306 rhs.generate_disposal_code(code)
1307 rhs.free_temps(code)
1308 # in Py2.6+, we need to invalidate the method cache
1309 code.putln("PyType_Modified(%s);" %
1310 entry.scope.parent_type.typeptr_cname)
1311 else:
1312 code.put_error_if_neg(self.pos,
1313 'PyObject_SetAttr(%s, %s, %s)' % (
1314 namespace,
1315 self.interned_cname,
1316 rhs.py_result()))
1317 if debug_disposal_code:
1318 print("NameNode.generate_assignment_code:")
1319 print("...generating disposal code for %s" % rhs)
1320 rhs.generate_disposal_code(code)
1321 rhs.free_temps(code)
1322 else:
1323 if self.type.is_buffer:
1324 # Generate code for doing the buffer release/acquisition.
1325 # This might raise an exception in which case the assignment (done
1326 # below) will not happen.
1327 #
1328 # The reason this is not in a typetest-like node is because the
1329 # variables that the acquired buffer info is stored to is allocated
1330 # per entry and coupled with it.
1331 self.generate_acquire_buffer(rhs, code)
1333 if self.type.is_pyobject:
1334 rhs.make_owned_reference(code)
1335 #print "NameNode.generate_assignment_code: to", self.name ###
1336 #print "...from", rhs ###
1337 #print "...LHS type", self.type, "ctype", self.ctype() ###
1338 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1339 if entry.is_cglobal:
1340 code.put_gotref(self.py_result())
1341 if not self.lhs_of_first_assignment:
1342 if entry.is_local and not Options.init_local_none:
1343 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1344 if initalized is True:
1345 code.put_decref(self.result(), self.ctype())
1346 elif initalized is None:
1347 code.put_xdecref(self.result(), self.ctype())
1348 else:
1349 code.put_decref(self.result(), self.ctype())
1350 if entry.is_cglobal:
1351 code.put_giveref(rhs.py_result())
1352 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1353 if debug_disposal_code:
1354 print("NameNode.generate_assignment_code:")
1355 print("...generating post-assignment code for %s" % rhs)
1356 rhs.generate_post_assignment_code(code)
1357 rhs.free_temps(code)
1359 def generate_acquire_buffer(self, rhs, code):
1360 # rhstmp is only used in case the rhs is a complicated expression leading to
1361 # the object, to avoid repeating the same C expression for every reference
1362 # to the rhs. It does NOT hold a reference.
1363 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1364 if pretty_rhs:
1365 rhstmp = rhs.result_as(self.ctype())
1366 else:
1367 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1368 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1370 buffer_aux = self.entry.buffer_aux
1371 bufstruct = buffer_aux.buffer_info_var.cname
1372 import Buffer
1373 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1374 is_initialized=not self.lhs_of_first_assignment,
1375 pos=self.pos, code=code)
1377 if not pretty_rhs:
1378 code.putln("%s = 0;" % rhstmp)
1379 code.funcstate.release_temp(rhstmp)
1381 def generate_deletion_code(self, code):
1382 if self.entry is None:
1383 return # There was an error earlier
1384 if not self.entry.is_pyglobal:
1385 error(self.pos, "Deletion of local or C global name not supported")
1386 return
1387 code.put_error_if_neg(self.pos,
1388 '__Pyx_DelAttrString(%s, "%s")' % (
1389 Naming.module_cname,
1390 self.entry.name))
1392 def annotate(self, code):
1393 if hasattr(self, 'is_called') and self.is_called:
1394 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1395 if self.type.is_pyobject:
1396 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1397 else:
1398 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1400 class BackquoteNode(ExprNode):
1401 # `expr`
1402 #
1403 # arg ExprNode
1405 subexprs = ['arg']
1407 def analyse_types(self, env):
1408 self.arg.analyse_types(env)
1409 self.arg = self.arg.coerce_to_pyobject(env)
1410 self.type = py_object_type
1411 self.gil_check(env)
1412 self.is_temp = 1
1414 gil_message = "Backquote expression"
1416 def calculate_constant_result(self):
1417 self.constant_result = repr(self.arg.constant_result)
1419 def generate_result_code(self, code):
1420 code.putln(
1421 "%s = PyObject_Repr(%s); %s" % (
1422 self.result(),
1423 self.arg.py_result(),
1424 code.error_goto_if_null(self.result(), self.pos)))
1425 code.put_gotref(self.py_result())
1429 class ImportNode(ExprNode):
1430 # Used as part of import statement implementation.
1431 # Implements result =
1432 # __import__(module_name, globals(), None, name_list)
1433 #
1434 # module_name IdentifierStringNode dotted name of module
1435 # name_list ListNode or None list of names to be imported
1437 subexprs = ['module_name', 'name_list']
1439 def analyse_types(self, env):
1440 self.module_name.analyse_types(env)
1441 self.module_name = self.module_name.coerce_to_pyobject(env)
1442 if self.name_list:
1443 self.name_list.analyse_types(env)
1444 self.name_list.coerce_to_pyobject(env)
1445 self.type = py_object_type
1446 self.gil_check(env)
1447 self.is_temp = 1
1448 env.use_utility_code(import_utility_code)
1450 gil_message = "Python import"
1452 def generate_result_code(self, code):
1453 if self.name_list:
1454 name_list_code = self.name_list.py_result()
1455 else:
1456 name_list_code = "0"
1457 code.putln(
1458 "%s = __Pyx_Import(%s, %s); %s" % (
1459 self.result(),
1460 self.module_name.py_result(),
1461 name_list_code,
1462 code.error_goto_if_null(self.result(), self.pos)))
1463 code.put_gotref(self.py_result())
1466 class IteratorNode(NewTempExprNode):
1467 # Used as part of for statement implementation.
1468 #
1469 # allocate_counter_temp/release_counter_temp needs to be called
1470 # by parent (ForInStatNode)
1471 #
1472 # Implements result = iter(sequence)
1473 #
1474 # sequence ExprNode
1476 subexprs = ['sequence']
1478 def analyse_types(self, env):
1479 self.sequence.analyse_types(env)
1480 self.sequence = self.sequence.coerce_to_pyobject(env)
1481 self.type = py_object_type
1482 self.gil_check(env)
1483 self.is_temp = 1
1485 gil_message = "Iterating over Python object"
1487 def allocate_counter_temp(self, code):
1488 self.counter_cname = code.funcstate.allocate_temp(
1489 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1491 def release_counter_temp(self, code):
1492 code.funcstate.release_temp(self.counter_cname)
1494 def generate_result_code(self, code):
1495 is_builtin_sequence = self.sequence.type is list_type or \
1496 self.sequence.type is tuple_type
1497 if is_builtin_sequence:
1498 code.putln(
1499 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1500 else:
1501 code.putln(
1502 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1503 self.sequence.py_result(),
1504 self.sequence.py_result()))
1505 code.putln(
1506 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1507 self.counter_cname,
1508 self.result(),
1509 self.sequence.py_result(),
1510 self.result()))
1511 code.putln("} else {")
1512 if is_builtin_sequence:
1513 code.putln(
1514 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1515 code.error_goto(self.pos))
1516 else:
1517 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1518 self.counter_cname,
1519 self.result(),
1520 self.sequence.py_result(),
1521 code.error_goto_if_null(self.result(), self.pos)))
1522 code.put_gotref(self.py_result())
1523 code.putln("}")
1526 class NextNode(AtomicNewTempExprNode):
1527 # Used as part of for statement implementation.
1528 # Implements result = iterator.next()
1529 # Created during analyse_types phase.
1530 # The iterator is not owned by this node.
1531 #
1532 # iterator ExprNode
1534 def __init__(self, iterator, env):
1535 self.pos = iterator.pos
1536 self.iterator = iterator
1537 self.type = py_object_type
1538 self.is_temp = 1
1540 def generate_result_code(self, code):
1541 if self.iterator.sequence.type is list_type:
1542 type_checks = [(list_type, "List")]
1543 elif self.iterator.sequence.type is tuple_type:
1544 type_checks = [(tuple_type, "Tuple")]
1545 else:
1546 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1548 for py_type, prefix in type_checks:
1549 if len(type_checks) > 1:
1550 code.putln(
1551 "if (likely(Py%s_CheckExact(%s))) {" % (
1552 prefix, self.iterator.py_result()))
1553 code.putln(
1554 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1555 self.iterator.counter_cname,
1556 prefix,
1557 self.iterator.py_result()))
1558 code.putln(
1559 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1560 self.result(),
1561 prefix,
1562 self.iterator.py_result(),
1563 self.iterator.counter_cname,
1564 self.result(),
1565 self.iterator.counter_cname))
1566 if len(type_checks) > 1:
1567 code.put("} else ")
1568 if len(type_checks) == 1:
1569 return
1570 code.putln("{")
1571 code.putln(
1572 "%s = PyIter_Next(%s);" % (
1573 self.result(),
1574 self.iterator.py_result()))
1575 code.putln(
1576 "if (!%s) {" %
1577 self.result())
1578 code.putln(code.error_goto_if_PyErr(self.pos))
1579 code.putln("break;")
1580 code.putln("}")
1581 code.put_gotref(self.py_result())
1582 code.putln("}")
1585 class ExcValueNode(AtomicNewTempExprNode):
1586 # Node created during analyse_types phase
1587 # of an ExceptClauseNode to fetch the current
1588 # exception value.
1590 def __init__(self, pos, env, var):
1591 ExprNode.__init__(self, pos)
1592 self.type = py_object_type
1593 self.var = var
1595 def calculate_result_code(self):
1596 return self.var
1598 def generate_result_code(self, code):
1599 pass
1601 def analyse_types(self, env):
1602 pass
1605 class TempNode(ExprNode):
1606 # Node created during analyse_types phase
1607 # of some nodes to hold a temporary value.
1609 subexprs = []
1611 def __init__(self, pos, type, env):
1612 ExprNode.__init__(self, pos)
1613 self.type = type
1614 if type.is_pyobject:
1615 self.result_ctype = py_object_type
1616 self.is_temp = 1
1618 def analyse_types(self, env):
1619 return self.type
1621 def generate_result_code(self, code):
1622 pass
1625 class PyTempNode(TempNode):
1626 # TempNode holding a Python value.
1628 def __init__(self, pos, env):
1629 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1632 #-------------------------------------------------------------------
1633 #
1634 # Trailer nodes
1635 #
1636 #-------------------------------------------------------------------
1638 class IndexNode(ExprNode):
1639 # Sequence indexing.
1640 #
1641 # base ExprNode
1642 # index ExprNode
1643 # indices [ExprNode]
1644 # is_buffer_access boolean Whether this is a buffer access.
1645 #
1646 # indices is used on buffer access, index on non-buffer access.
1647 # The former contains a clean list of index parameters, the
1648 # latter whatever Python object is needed for index access.
1650 subexprs = ['base', 'index', 'indices']
1651 indices = None
1653 def __init__(self, pos, index, *args, **kw):
1654 ExprNode.__init__(self, pos, index=index, *args, **kw)
1655 self._index = index
1657 def calculate_constant_result(self):
1658 self.constant_result = \
1659 self.base.constant_result[self.index.constant_result]
1661 def compile_time_value(self, denv):
1662 base = self.base.compile_time_value(denv)
1663 index = self.index.compile_time_value(denv)
1664 try:
1665 return base[index]
1666 except Exception, e:
1667 self.compile_time_value_error(e)
1669 def is_ephemeral(self):
1670 return self.base.is_ephemeral()
1672 def analyse_target_declaration(self, env):
1673 pass
1675 def analyse_as_type(self, env):
1676 base_type = self.base.analyse_as_type(env)
1677 if base_type and not base_type.is_pyobject:
1678 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1679 return None
1681 def analyse_types(self, env):
1682 self.analyse_base_and_index_types(env, getting = 1)
1684 def analyse_target_types(self, env):
1685 self.analyse_base_and_index_types(env, setting = 1)
1687 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1688 # Note: This might be cleaned up by having IndexNode
1689 # parsed in a saner way and only construct the tuple if
1690 # needed.
1692 # Note that this function must leave IndexNode in a cloneable state.
1693 # For buffers, self.index is packed out on the initial analysis, and
1694 # when cloning self.indices is copied.
1695 self.is_buffer_access = False
1697 self.base.analyse_types(env)
1698 # Handle the case where base is a literal char* (and we expect a string, not an int)
1699 if isinstance(self.base, StringNode):
1700 self.base = self.base.coerce_to_pyobject(env)
1702 skip_child_analysis = False
1703 buffer_access = False
1704 if self.base.type.is_buffer:
1705 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1706 if self.indices:
1707 indices = self.indices
1708 else:
1709 # On cloning, indices is cloned. Otherwise, unpack index into indices
1710 assert not isinstance(self.index, CloneNode)
1711 if isinstance(self.index, TupleNode):
1712 indices = self.index.args
1713 else:
1714 indices = [self.index]
1715 if len(indices) == self.base.type.ndim:
1716 buffer_access = True
1717 skip_child_analysis = True
1718 for x in indices:
1719 x.analyse_types(env)
1720 if not x.type.is_int:
1721 buffer_access = False
1723 if buffer_access:
1724 self.indices = indices
1725 self.index = None
1726 self.type = self.base.type.dtype
1727 self.is_buffer_access = True
1728 self.buffer_type = self.base.entry.type
1730 if getting and self.type.is_pyobject:
1731 self.is_temp = True
1732 if setting:
1733 if not self.base.entry.type.writable:
1734 error(self.pos, "Writing to readonly buffer")
1735 else:
1736 self.base.entry.buffer_aux.writable_needed = True
1737 else:
1738 if isinstance(self.index, TupleNode):
1739 self.index.analyse_types(env, skip_children=skip_child_analysis)
1740 elif not skip_child_analysis:
1741 self.index.analyse_types(env)
1742 self.original_index_type = self.index.type
1743 if self.base.type.is_pyobject:
1744 if self.index.type.is_int:
1745 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1746 else:
1747 self.index = self.index.coerce_to_pyobject(env)
1748 self.type = py_object_type
1749 self.gil_check(env)
1750 self.is_temp = 1
1751 else:
1752 if self.base.type.is_ptr or self.base.type.is_array:
1753 self.type = self.base.type.base_type
1754 else:
1755 error(self.pos,
1756 "Attempting to index non-array type '%s'" %
1757 self.base.type)
1758 self.type = PyrexTypes.error_type
1759 if self.index.type.is_pyobject:
1760 self.index = self.index.coerce_to(
1761 PyrexTypes.c_py_ssize_t_type, env)
1762 if not self.index.type.is_int:
1763 error(self.pos,
1764 "Invalid index type '%s'" %
1765 self.index.type)
1767 gil_message = "Indexing Python object"
1769 def check_const_addr(self):
1770 self.base.check_const_addr()
1771 self.index.check_const()
1773 def is_lvalue(self):
1774 return 1
1776 def calculate_result_code(self):
1777 if self.is_buffer_access:
1778 return "(*%s)" % self.buffer_ptr_code
1779 else:
1780 return "(%s[%s])" % (
1781 self.base.result(), self.index.result())
1783 def extra_index_params(self):
1784 if self.index.type.is_int:
1785 if self.original_index_type.signed:
1786 size_adjustment = ""
1787 else:
1788 size_adjustment = "+1"
1789 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1790 else:
1791 return ""
1793 def generate_subexpr_evaluation_code(self, code):
1794 self.base.generate_evaluation_code(code)
1795 if not self.indices:
1796 self.index.generate_evaluation_code(code)
1797 else:
1798 for i in self.indices:
1799 i.generate_evaluation_code(code)
1801 def generate_subexpr_disposal_code(self, code):
1802 self.base.generate_disposal_code(code)
1803 if not self.indices:
1804 self.index.generate_disposal_code(code)
1805 else:
1806 for i in self.indices:
1807 i.generate_disposal_code(code)
1809 def free_subexpr_temps(self, code):
1810 self.base.free_temps(code)
1811 if not self.indices:
1812 self.index.free_temps(code)
1813 else:
1814 for i in self.indices:
1815 i.free_temps(code)
1817 def generate_result_code(self, code):
1818 if self.is_buffer_access:
1819 if code.globalstate.directives['nonecheck']:
1820 self.put_nonecheck(code)
1821 self.buffer_ptr_code = self.buffer_lookup_code(code)
1822 if self.type.is_pyobject:
1823 # is_temp is True, so must pull out value and incref it.
1824 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1825 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1826 elif self.type.is_pyobject:
1827 if self.index.type.is_int:
1828 index_code = self.index.result()
1829 if self.base.type is list_type:
1830 function = "__Pyx_GetItemInt_List"
1831 elif self.base.type is tuple_type:
1832 function = "__Pyx_GetItemInt_Tuple"
1833 else:
1834 function = "__Pyx_GetItemInt"
1835 code.globalstate.use_utility_code(getitem_int_utility_code)
1836 else:
1837 function = "PyObject_GetItem"
1838 index_code = self.index.py_result()
1839 sign_code = ""
1840 code.putln(
1841 "%s = %s(%s, %s%s); if (!%s) %s" % (
1842 self.result(),
1843 function,
1844 self.base.py_result(),
1845 index_code,
1846 self.extra_index_params(),
1847 self.result(),
1848 code.error_goto(self.pos)))
1849 code.put_gotref(self.py_result())
1851 def generate_setitem_code(self, value_code, code):
1852 if self.index.type.is_int:
1853 function = "__Pyx_SetItemInt"
1854 index_code = self.index.result()
1855 code.globalstate.use_utility_code(setitem_int_utility_code)
1856 else:
1857 index_code = self.index.py_result()
1858 if self.base.type is dict_type:
1859 function = "PyDict_SetItem"
1860 elif self.base.type is list_type:
1861 function = "PyList_SetItem"
1862 # don't use PyTuple_SetItem(), as we'd normally get a
1863 # TypeError when changing a tuple, while PyTuple_SetItem()
1864 # would allow updates
1865 #
1866 #elif self.base.type is tuple_type:
1867 # function = "PyTuple_SetItem"
1868 else:
1869 function = "PyObject_SetItem"
1870 code.putln(
1871 "if (%s(%s, %s, %s%s) < 0) %s" % (
1872 function,
1873 self.base.py_result(),
1874 index_code,
1875 value_code,
1876 self.extra_index_params(),
1877 code.error_goto(self.pos)))
1879 def generate_buffer_setitem_code(self, rhs, code, op=""):
1880 # Used from generate_assignment_code and InPlaceAssignmentNode
1881 if code.globalstate.directives['nonecheck']:
1882 self.put_nonecheck(code)
1883 ptrexpr = self.buffer_lookup_code(code)
1884 if self.buffer_type.dtype.is_pyobject:
1885 # Must manage refcounts. Decref what is already there
1886 # and incref what we put in.
1887 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1888 rhs_code = rhs.result()
1889 code.putln("%s = %s;" % (ptr, ptrexpr))
1890 code.put_gotref("*%s" % ptr)
1891 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1892 ptr, rhs_code
1893 ))
1894 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1895 code.put_giveref("*%s" % ptr)
1896 code.funcstate.release_temp(ptr)
1897 else:
1898 # Simple case
1899 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1901 def generate_assignment_code(self, rhs, code):
1902 self.generate_subexpr_evaluation_code(code)
1903 if self.is_buffer_access:
1904 self.generate_buffer_setitem_code(rhs, code)
1905 elif self.type.is_pyobject:
1906 self.generate_setitem_code(rhs.py_result(), code)
1907 else:
1908 code.putln(
1909 "%s = %s;" % (
1910 self.result(), rhs.result()))
1911 self.generate_subexpr_disposal_code(code)
1912 self.free_subexpr_temps(code)
1913 rhs.generate_disposal_code(code)
1914 rhs.free_temps(code)
1916 def generate_deletion_code(self, code):
1917 self.generate_subexpr_evaluation_code(code)
1918 #if self.type.is_pyobject:
1919 if self.index.type.is_int:
1920 function = "__Pyx_DelItemInt"
1921 index_code = self.index.result()
1922 code.globalstate.use_utility_code(delitem_int_utility_code)
1923 else:
1924 index_code = self.index.py_result()
1925 if self.base.type is dict_type:
1926 function = "PyDict_DelItem"
1927 else:
1928 function = "PyObject_DelItem"
1929 code.putln(
1930 "if (%s(%s, %s%s) < 0) %s" % (
1931 function,
1932 self.base.py_result(),
1933 index_code,
1934 self.extra_index_params(),
1935 code.error_goto(self.pos)))
1936 self.generate_subexpr_disposal_code(code)
1937 self.free_subexpr_temps(code)
1939 def buffer_lookup_code(self, code):
1940 # Assign indices to temps
1941 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1942 for temp, index in zip(index_temps, self.indices):
1943 code.putln("%s = %s;" % (temp, index.result()))
1944 # Generate buffer access code using these temps
1945 import Buffer
1946 # The above could happen because child_attrs is wrong somewhere so that
1947 # options are not propagated.
1948 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1949 index_signeds=[i.type.signed for i in self.indices],
1950 index_cnames=index_temps,
1951 options=code.globalstate.directives,
1952 pos=self.pos, code=code)
1954 def put_nonecheck(self, code):
1955 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1956 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1957 code.putln("__Pyx_RaiseNoneIndexingError();")
1958 code.putln(code.error_goto(self.pos))
1959 code.putln("}")
1961 class SliceIndexNode(ExprNode):
1962 # 2-element slice indexing
1963 #
1964 # base ExprNode
1965 # start ExprNode or None
1966 # stop ExprNode or None
1968 subexprs = ['base', 'start', 'stop']
1970 def calculate_constant_result(self):
1971 self.constant_result = self.base.constant_result[
1972 self.start.constant_result : self.stop.constant_result]
1974 def compile_time_value(self, denv):
1975 base = self.base.compile_time_value(denv)
1976 if self.start is None:
1977 start = 0
1978 else:
1979 start = self.start.compile_time_value(denv)
1980 if self.stop is None:
1981 stop = None
1982 else:
1983 stop = self.stop.compile_time_value(denv)
1984 try:
1985 return base[start:stop]
1986 except Exception, e:
1987 self.compile_time_value_error(e)
1989 def analyse_target_declaration(self, env):
1990 pass
1992 def analyse_types(self, env):
1993 self.base.analyse_types(env)
1994 if self.start:
1995 self.start.analyse_types(env)
1996 if self.stop:
1997 self.stop.analyse_types(env)
1998 if self.base.type.is_string:
1999 self.type = py_object_type
2000 elif self.base.type.is_array or self.base.type.is_ptr:
2001 # we need a ptr type here instead of an array type, as
2002 # array types can result in invalid type casts in the C
2003 # code
2004 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
2005 else:
2006 self.base = self.base.coerce_to_pyobject(env)
2007 self.type = py_object_type
2008 c_int = PyrexTypes.c_py_ssize_t_type
2009 if self.start:
2010 self.start = self.start.coerce_to(c_int, env)
2011 if self.stop:
2012 self.stop = self.stop.coerce_to(c_int, env)
2013 self.gil_check(env)
2014 self.is_temp = 1
2016 gil_message = "Slicing Python object"
2018 def generate_result_code(self, code):
2019 if not self.type.is_pyobject:
2020 error(self.pos,
2021 "Slicing is not currently supported for '%s'." % self.type)
2022 return
2023 if self.base.type.is_string:
2024 if self.stop is None:
2025 code.putln(
2026 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2027 self.result(),
2028 self.base.result(),
2029 self.start_code(),
2030 code.error_goto_if_null(self.result(), self.pos)))
2031 else:
2032 code.putln(
2033 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2034 self.result(),
2035 self.base.result(),
2036 self.start_code(),
2037 self.stop_code(),
2038 self.start_code(),
2039 code.error_goto_if_null(self.result(), self.pos)))
2040 else:
2041 code.putln(
2042 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2043 self.result(),
2044 self.base.py_result(),
2045 self.start_code(),
2046 self.stop_code(),
2047 code.error_goto_if_null(self.result(), self.pos)))
2048 code.put_gotref(self.py_result())
2050 def generate_assignment_code(self, rhs, code):
2051 self.generate_subexpr_evaluation_code(code)
2052 if self.type.is_pyobject:
2053 code.put_error_if_neg(self.pos,
2054 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2055 self.base.py_result(),
2056 self.start_code(),
2057 self.stop_code(),
2058 rhs.result()))
2059 else:
2060 start_offset = ''
2061 if self.start:
2062 start_offset = self.start_code()
2063 if start_offset == '0':
2064 start_offset = ''
2065 else:
2066 start_offset += '+'
2067 if rhs.type.is_array:
2068 array_length = rhs.type.size
2069 self.generate_slice_guard_code(code, array_length)
2070 else:
2071 error("Slice assignments from pointers are not yet supported.")
2072 # FIXME: fix the array size according to start/stop
2073 array_length = self.base.type.size
2074 for i in range(array_length):
2075 code.putln("%s[%s%s] = %s[%d];" % (
2076 self.base.result(), start_offset, i,
2077 rhs.result(), i))
2078 self.generate_subexpr_disposal_code(code)
2079 self.free_subexpr_temps(code)
2080 rhs.generate_disposal_code(code)
2081 rhs.free_temps(code)
2083 def generate_deletion_code(self, code):
2084 if not self.base.type.is_pyobject:
2085 error(self.pos,
2086 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2087 return
2088 self.generate_subexpr_evaluation_code(code)
2089 code.put_error_if_neg(self.pos,
2090 "PySequence_DelSlice(%s, %s, %s)" % (
2091 self.base.py_result(),
2092 self.start_code(),
2093 self.stop_code()))
2094 self.generate_subexpr_disposal_code(code)
2096 def generate_slice_guard_code(self, code, target_size):
2097 if not self.base.type.is_array:
2098 return
2099 slice_size = self.base.type.size
2100 start = stop = None
2101 if self.stop:
2102 stop = self.stop.result()
2103 try:
2104 stop = int(stop)
2105 if stop < 0:
2106 slice_size = self.base.type.size + stop
2107 else:
2108 slice_size = stop
2109 stop = None
2110 except ValueError:
2111 pass
2112 if self.start:
2113 start = self.start.result()
2114 try:
2115 start = int(start)
2116 if start < 0:
2117 start = self.base.type.size + start
2118 slice_size -= start
2119 start = None
2120 except ValueError:
2121 pass
2122 check = None
2123 if slice_size < 0:
2124 if target_size > 0:
2125 error(self.pos, "Assignment to empty slice.")
2126 elif start is None and stop is None:
2127 # we know the exact slice length
2128 if target_size != slice_size:
2129 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2130 slice_size, target_size))
2131 elif start is not None:
2132 if stop is None:
2133 stop = slice_size
2134 check = "(%s)-(%s)" % (stop, start)
2135 else: # stop is not None:
2136 check = stop
2137 if check:
2138 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2139 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2140 target_size, check))
2141 code.putln(code.error_goto(self.pos))
2142 code.putln("}")
2144 def start_code(self):
2145 if self.start:
2146 return self.start.result()
2147 else:
2148 return "0"
2150 def stop_code(self):
2151 if self.stop:
2152 return self.stop.result()
2153 elif self.base.type.is_array:
2154 return self.base.type.size
2155 else:
2156 return "PY_SSIZE_T_MAX"
2158 def calculate_result_code(self):
2159 # self.result() is not used, but this method must exist
2160 return "<unused>"
2163 class SliceNode(ExprNode):
2164 # start:stop:step in subscript list
2165 #
2166 # start ExprNode
2167 # stop ExprNode
2168 # step ExprNode
2170 def calculate_constant_result(self):
2171 self.constant_result = self.base.constant_result[
2172 self.start.constant_result : \
2173 self.stop.constant_result : \
2174 self.step.constant_result]
2176 def compile_time_value(self, denv):
2177 start = self.start.compile_time_value(denv)
2178 if self.stop is None:
2179 stop = None
2180 else:
2181 stop = self.stop.compile_time_value(denv)
2182 if self.step is None:
2183 step = None
2184 else:
2185 step = self.step.compile_time_value(denv)
2186 try:
2187 return slice(start, stop, step)
2188 except Exception, e:
2189 self.compile_time_value_error(e)
2191 subexprs = ['start', 'stop', 'step']
2193 def analyse_types(self, env):
2194 self.start.analyse_types(env)
2195 self.stop.analyse_types(env)
2196 self.step.analyse_types(env)
2197 self.start = self.start.coerce_to_pyobject(env)
2198 self.stop = self.stop.coerce_to_pyobject(env)
2199 self.step = self.step.coerce_to_pyobject(env)
2200 self.type = py_object_type
2201 self.gil_check(env)
2202 self.is_temp = 1
2204 gil_message = "Constructing Python slice object"
2206 def generate_result_code(self, code):
2207 code.putln(
2208 "%s = PySlice_New(%s, %s, %s); %s" % (
2209 self.result(),
2210 self.start.py_result(),
2211 self.stop.py_result(),
2212 self.step.py_result(),
2213 code.error_goto_if_null(self.result(), self.pos)))
2214 code.put_gotref(self.py_result())
2217 class CallNode(NewTempExprNode):
2218 def gil_check(self, env):
2219 # Make sure we're not in a nogil environment
2220 if env.nogil:
2221 error(self.pos, "Calling gil-requiring function without gil")
2223 def analyse_as_type_constructor(self, env):
2224 type = self.function.analyse_as_type(env)
2225 if type and type.is_struct_or_union:
2226 args, kwds = self.explicit_args_kwds()
2227 items = []
2228 for arg, member in zip(args, type.scope.var_entries):
2229 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2230 if kwds:
2231 items += kwds.key_value_pairs
2232 self.key_value_pairs = items
2233 self.__class__ = DictNode
2234 self.analyse_types(env)
2235 self.coerce_to(type, env)
2236 return True
2239 class SimpleCallNode(CallNode):
2240 # Function call without keyword, * or ** args.
2241 #
2242 # function ExprNode
2243 # args [ExprNode]
2244 # arg_tuple ExprNode or None used internally
2245 # self ExprNode or None used internally
2246 # coerced_self ExprNode or None used internally
2247 # wrapper_call bool used internally
2248 # has_optional_args bool used internally
2250 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2252 self = None
2253 coerced_self = None
2254 arg_tuple = None
2255 wrapper_call = False
2256 has_optional_args = False
2258 def compile_time_value(self, denv):
2259 function = self.function.compile_time_value(denv)
2260 args = [arg.compile_time_value(denv) for arg in self.args]
2261 try:
2262 return function(*args)
2263 except Exception, e:
2264 self.compile_time_value_error(e)
2266 def analyse_as_type(self, env):
2267 attr = self.function.as_cython_attribute()
2268 if attr == 'pointer':
2269 if len(self.args) != 1:
2270 error(self.args.pos, "only one type allowed.")
2271 else:
2272 type = self.args[0].analyse_as_type(env)
2273 if not type:
2274 error(self.args[0].pos, "Unknown type")
2275 else:
2276 return PyrexTypes.CPtrType(type)
2278 def explicit_args_kwds(self):
2279 return self.args, None
2281 def analyse_types(self, env):
2282 if self.analyse_as_type_constructor(env):
2283 return
2284 function = self.function
2285 function.is_called = 1
2286 self.function.analyse_types(env)
2287 if function.is_attribute and function.is_py_attr and \
2288 function.attribute == "append" and len(self.args) == 1:
2289 # L.append(x) is almost always applied to a list
2290 self.py_func = self.function
2291 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2292 self.function.analyse_types(env)
2293 self.self = self.py_func.obj
2294 function.obj = CloneNode(self.self)
2295 env.use_utility_code(append_utility_code)
2296 if function.is_attribute and function.entry and function.entry.is_cmethod:
2297 # Take ownership of the object from which the attribute
2298 # was obtained, because we need to pass it as 'self'.
2299 self.self = function.obj
2300 function.obj = CloneNode(self.self)
2301 func_type = self.function_type()
2302 if func_type.is_pyobject:
2303 self.arg_tuple = TupleNode(self.pos, args = self.args)
2304 self.arg_tuple.analyse_types(env)
2305 self.args = None
2306 self.type = py_object_type
2307 self.gil_check(env)
2308 self.is_temp = 1
2309 else:
2310 for arg in self.args:
2311 arg.analyse_types(env)
2312 if self.self and func_type.args:
2313 # Coerce 'self' to the type expected by the method.
2314 expected_type = func_type.args[0].type
2315 self.coerced_self = CloneNode(self.self).coerce_to(
2316 expected_type, env)
2317 # Insert coerced 'self' argument into argument list.
2318 self.args.insert(0, self.coerced_self)
2319 self.analyse_c_function_call(env)
2321 def function_type(self):
2322 # Return the type of the function being called, coercing a function
2323 # pointer to a function if necessary.
2324 func_type = self.function.type
2325 if func_type.is_ptr:
2326 func_type = func_type.base_type
2327 return func_type
2329 def analyse_c_function_call(self, env):
2330 func_type = self.function_type()
2331 # Check function type
2332 if not func_type.is_cfunction:
2333 if not func_type.is_error:
2334 error(self.pos, "Calling non-function type '%s'" %
2335 func_type)
2336 self.type = PyrexTypes.error_type
2337 self.result_code = "<error>"
2338 return
2339 # Check no. of args
2340 max_nargs = len(func_type.args)
2341 expected_nargs = max_nargs - func_type.optional_arg_count
2342 actual_nargs = len(self.args)
2343 if actual_nargs < expected_nargs \
2344 or (not func_type.has_varargs and actual_nargs > max_nargs):
2345 expected_str = str(expected_nargs)
2346 if func_type.has_varargs:
2347 expected_str = "at least " + expected_str
2348 elif func_type.optional_arg_count:
2349 if actual_nargs < max_nargs:
2350 expected_str = "at least " + expected_str
2351 else:
2352 expected_str = "at most " + str(max_nargs)
2353 error(self.pos,
2354 "Call with wrong number of arguments (expected %s, got %s)"
2355 % (expected_str, actual_nargs))
2356 self.args = None
2357 self.type = PyrexTypes.error_type
2358 self.result_code = "<error>"
2359 return
2360 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2361 self.has_optional_args = 1
2362 self.is_temp = 1
2363 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2364 env.release_temp(self.opt_arg_struct)
2365 # Coerce arguments
2366 for i in range(min(max_nargs, actual_nargs)):
2367 formal_type = func_type.args[i].type
2368 self.args[i] = self.args[i].coerce_to(formal_type, env)
2369 for i in range(max_nargs, actual_nargs):
2370 if self.args[i].type.is_pyobject:
2371 error(self.args[i].pos,
2372 "Python object cannot be passed as a varargs parameter")
2373 # Calc result type and code fragment
2374 self.type = func_type.return_type
2375 if self.type.is_pyobject:
2376 self.result_ctype = py_object_type
2377 self.is_temp = 1
2378 elif func_type.exception_value is not None \
2379 or func_type.exception_check:
2380 self.is_temp = 1
2381 # C++ exception handler
2382 if func_type.exception_check == '+':
2383 if func_type.exception_value is None:
2384 env.use_utility_code(cpp_exception_utility_code)
2385 # Check gil
2386 if not func_type.nogil:
2387 self.gil_check(env)
2389 def calculate_result_code(self):
2390 return self.c_call_code()
2392 def c_call_code(self):
2393 func_type = self.function_type()
2394 if self.args is None or not func_type.is_cfunction:
2395 return "<error>"
2396 formal_args = func_type.args
2397 arg_list_code = []
2398 args = zip(formal_args, self.args)
2399 max_nargs = len(func_type.args)
2400 expected_nargs = max_nargs - func_type.optional_arg_count
2401 actual_nargs = len(self.args)
2402 for formal_arg, actual_arg in args[:expected_nargs]:
2403 arg_code = actual_arg.result_as(formal_arg.type)
2404 arg_list_code.append(arg_code)
2406 if func_type.is_overridable:
2407 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2409 if func_type.optional_arg_count:
2410 if expected_nargs == actual_nargs:
2411 optional_args = 'NULL'
2412 else:
2413 optional_args = "&%s" % self.opt_arg_struct
2414 arg_list_code.append(optional_args)
2416 for actual_arg in self.args[len(formal_args):]:
2417 arg_list_code.append(actual_arg.result())
2418 result = "%s(%s)" % (self.function.result(),
2419 ', '.join(arg_list_code))
2420 # if self.wrapper_call or \
2421 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2422 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2423 return result
2425 def generate_result_code(self, code):
2426 func_type = self.function_type()
2427 if func_type.is_pyobject:
2428 arg_code = self.arg_tuple.py_result()
2429 code.putln(
2430 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2431 self.result(),
2432 self.function.py_result(),
2433 arg_code,
2434 code.error_goto_if_null(self.result(), self.pos)))
2435 code.put_gotref(self.py_result())
2436 elif func_type.is_cfunction:
2437 if self.has_optional_args:
2438 actual_nargs = len(self.args)
2439 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2440 code.putln("%s.%s = %s;" % (
2441 self.opt_arg_struct,
2442 Naming.pyrex_prefix + "n",
2443 len(self.args) - expected_nargs))
2444 args = zip(func_type.args, self.args)
2445 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2446 code.putln("%s.%s = %s;" % (
2447 self.opt_arg_struct,
2448 formal_arg.name,
2449 actual_arg.result_as(formal_arg.type)))
2450 exc_checks = []
2451 if self.type.is_pyobject:
2452 exc_checks.append("!%s" % self.result())
2453 else:
2454 exc_val = func_type.exception_value
2455 exc_check = func_type.exception_check
2456 if exc_val is not None:
2457 exc_checks.append("%s == %s" % (self.result(), exc_val))
2458 if exc_check:
2459 exc_checks.append("PyErr_Occurred()")
2460 if self.is_temp or exc_checks:
2461 rhs = self.c_call_code()
2462 if self.result():
2463 lhs = "%s = " % self.result()
2464 if self.is_temp and self.type.is_pyobject:
2465 #return_type = self.type # func_type.return_type
2466 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2467 # "from", return_type, "to pyobject" ###
2468 rhs = typecast(py_object_type, self.type, rhs)
2469 else:
2470 lhs = ""
2471 if func_type.exception_check == '+':
2472 if func_type.exception_value is None:
2473 raise_py_exception = "__Pyx_CppExn2PyErr()"
2474 elif func_type.exception_value.type.is_pyobject:
2475 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2476 else:
2477 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2478 code.putln(
2479 "try {%s%s;} catch(...) {%s; %s}" % (
2480 lhs,
2481 rhs,
2482 raise_py_exception,
2483 code.error_goto(self.pos)))
2484 else:
2485 if exc_checks:
2486 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2487 else:
2488 goto_error = ""
2489 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2490 if self.type.is_pyobject and self.result():
2491 code.put_gotref(self.py_result())
2494 class GeneralCallNode(CallNode):
2495 # General Python function call, including keyword,
2496 # * and ** arguments.
2497 #
2498 # function ExprNode
2499 # positional_args ExprNode Tuple of positional arguments
2500 # keyword_args ExprNode or None Dict of keyword arguments
2501 # starstar_arg ExprNode or None Dict of extra keyword args
2503 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2505 def compile_time_value(self, denv):
2506 function = self.function.compile_time_value(denv)
2507 positional_args = self.positional_args.compile_time_value(denv)
2508 keyword_args = self.keyword_args.compile_time_value(denv)
2509 starstar_arg = self.starstar_arg.compile_time_value(denv)
2510 try:
2511 keyword_args.update(starstar_arg)
2512 return function(*positional_args, **keyword_args)
2513 except Exception, e:
2514 self.compile_time_value_error(e)
2516 def explicit_args_kwds(self):
2517 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2518 raise PostParseError(self.pos,
2519 'Compile-time keyword arguments must be explicit.')
2520 return self.positional_args.args, self.keyword_args
2522 def analyse_types(self, env):
2523 if self.analyse_as_type_constructor(env):
2524 return
2525 self.function.analyse_types(env)
2526 self.positional_args.analyse_types(env)
2527 if self.keyword_args:
2528 self.keyword_args.analyse_types(env)
2529 if self.starstar_arg:
2530 self.starstar_arg.analyse_types(env)
2531 if not self.function.type.is_pyobject:
2532 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2533 error(self.pos, "Keyword arguments not allowed in cdef functions.")
2534 else:
2535 self.function = self.function.coerce_to_pyobject(env)
2536 self.positional_args = \
2537 self.positional_args.coerce_to_pyobject(env)
2538 if self.starstar_arg:
2539 self.starstar_arg = \
2540 self.starstar_arg.coerce_to_pyobject(env)
2541 self.type = py_object_type
2542 self.gil_check(env)
2543 self.is_temp = 1
2545 def generate_result_code(self, code):
2546 if self.keyword_args and self.starstar_arg:
2547 code.put_error_if_neg(self.pos,
2548 "PyDict_Update(%s, %s)" % (
2549 self.keyword_args.py_result(),
2550 self.starstar_arg.py_result()))
2551 keyword_code = self.keyword_args.py_result()
2552 elif self.keyword_args:
2553 keyword_code = self.keyword_args.py_result()
2554 elif self.starstar_arg:
2555 keyword_code = self.starstar_arg.py_result()
2556 else:
2557 keyword_code = None
2558 if not keyword_code:
2559 call_code = "PyObject_Call(%s, %s, NULL)" % (
2560 self.function.py_result(),
2561 self.positional_args.py_result())
2562 else:
2563 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2564 self.function.py_result(),
2565 self.positional_args.py_result(),
2566 keyword_code)
2567 code.putln(
2568 "%s = %s; %s" % (
2569 self.result(),
2570 call_code,
2571 code.error_goto_if_null(self.result(), self.pos)))
2572 code.put_gotref(self.py_result())
2575 class AsTupleNode(ExprNode):
2576 # Convert argument to tuple. Used for normalising
2577 # the * argument of a function call.
2578 #
2579 # arg ExprNode
2581 subexprs = ['arg']
2583 def calculate_constant_result(self):
2584 self.constant_result = tuple(self.base.constant_result)
2586 def compile_time_value(self, denv):
2587 arg = self.arg.compile_time_value(denv)
2588 try:
2589 return tuple(arg)
2590 except Exception, e:
2591 self.compile_time_value_error(e)
2593 def analyse_types(self, env):
2594 self.arg.analyse_types(env)
2595 self.arg = self.arg.coerce_to_pyobject(env)
2596 self.type = tuple_type
2597 self.gil_check(env)
2598 self.is_temp = 1
2600 gil_message = "Constructing Python tuple"
2602 def generate_result_code(self, code):
2603 code.putln(
2604 "%s = PySequence_Tuple(%s); %s" % (
2605 self.result(),
2606 self.arg.py_result(),
2607 code.error_goto_if_null(self.result(), self.pos)))
2608 code.put_gotref(self.py_result())
2611 class AttributeNode(NewTempExprNode):
2612 # obj.attribute
2613 #
2614 # obj ExprNode
2615 # attribute string
2616 # needs_none_check boolean Used if obj is an extension type.
2617 # If set to True, it is known that the type is not None.
2618 #
2619 # Used internally:
2620 #
2621 # is_py_attr boolean Is a Python getattr operation
2622 # member string C name of struct member
2623 # is_called boolean Function call is being done on result
2624 # entry Entry Symbol table entry of attribute
2625 # interned_attr_cname string C name of interned attribute name
2627 is_attribute = 1
2628 subexprs = ['obj']
2630 type = PyrexTypes.error_type
2631 entry = None
2632 is_called = 0
2633 needs_none_check = True
2635 def as_cython_attribute(self):
2636 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2637 return self.attribute
2639 def coerce_to(self, dst_type, env):
2640 # If coercing to a generic pyobject and this is a cpdef function
2641 # we can create the corresponding attribute
2642 if dst_type is py_object_type:
2643 entry = self.entry
2644 if entry and entry.is_cfunction and entry.as_variable:
2645 # must be a cpdef function
2646 self.is_temp = 1
2647 self.entry = entry.as_variable
2648 self.analyse_as_python_attribute(env)
2649 return self
2650 return ExprNode.coerce_to(self, dst_type, env)
2652 def calculate_constant_result(self):
2653 attr = self.attribute
2654 if attr.startswith("__") and attr.endswith("__"):
2655 return
2656 self.constant_result = getattr(self.obj.constant_result, attr)
2658 def compile_time_value(self, denv):
2659 attr = self.attribute
2660 if attr.startswith("__") and attr.endswith("__"):
2661 self.error("Invalid attribute name '%s' in compile-time expression"
2662 % attr)
2663 return None
2664 obj = self.obj.compile_time_value(denv)
2665 try:
2666 return getattr(obj, attr)
2667 except Exception, e:
2668 self.compile_time_value_error(e)
2670 def analyse_target_declaration(self, env):
2671 pass
2673 def analyse_target_types(self, env):
2674 self.analyse_types(env, target = 1)
2676 def analyse_types(self, env, target = 0):
2677 if self.analyse_as_cimported_attribute(env, target):
2678 return
2679 if not target and self.analyse_as_unbound_cmethod(env):
2680 return
2681 self.analyse_as_ordinary_attribute(env, target)
2683 def analyse_as_cimported_attribute(self, env, target):
2684 # Try to interpret this as a reference to an imported
2685 # C const, type, var or function. If successful, mutates
2686 # this node into a NameNode and returns 1, otherwise
2687 # returns 0.
2688 module_scope = self.obj.analyse_as_module(env)
2689 if module_scope:
2690 entry = module_scope.lookup_here(self.attribute)
2691 if entry and (
2692 entry.is_cglobal or entry.is_cfunction
2693 or entry.is_type or entry.is_const):
2694 self.mutate_into_name_node(env, entry, target)
2695 return 1
2696 return 0
2698 def analyse_as_unbound_cmethod(self, env):
2699 # Try to interpret this as a reference to an unbound
2700 # C method of an extension type. If successful, mutates
2701 # this node into a NameNode and returns 1, otherwise
2702 # returns 0.
2703 type = self.obj.analyse_as_extension_type(env)
2704 if type:
2705 entry = type.scope.lookup_here(self.attribute)
2706 if entry and entry.is_cmethod:
2707 # Create a temporary entry describing the C method
2708 # as an ordinary function.
2709 ubcm_entry = Symtab.Entry(entry.name,
2710 "%s->%s" % (type.vtabptr_cname, entry.cname),
2711 entry.type)
2712 ubcm_entry.is_cfunction = 1
2713 ubcm_entry.func_cname = entry.func_cname
2714 ubcm_entry.is_unbound_cmethod = 1
2715 self.mutate_into_name_node(env, ubcm_entry, None)
2716 return 1
2717 return 0
2719 def analyse_as_type(self, env):
2720 module_scope = self.obj.analyse_as_module(env)
2721 if module_scope:
2722 return module_scope.lookup_type(self.attribute)
2723 return None
2725 def analyse_as_extension_type(self, env):
2726 # Try to interpret this as a reference to an extension type
2727 # in a cimported module. Returns the extension type, or None.
2728 module_scope = self.obj.analyse_as_module(env)
2729 if module_scope:
2730 entry = module_scope.lookup_here(self.attribute)
2731 if entry and entry.is_type and entry.type.is_extension_type:
2732 return entry.type
2733 return None
2735 def analyse_as_module(self, env):
2736 # Try to interpret this as a reference to a cimported module
2737 # in another cimported module. Returns the module scope, or None.
2738 module_scope = self.obj.analyse_as_module(env)
2739 if module_scope:
2740 entry = module_scope.lookup_here(self.attribute)
2741 if entry and entry.as_module:
2742 return entry.as_module
2743 return None
2745 def mutate_into_name_node(self, env, entry, target):
2746 # Mutate this node into a NameNode and complete the
2747 # analyse_types phase.
2748 self.__class__ = NameNode
2749 self.name = self.attribute
2750 self.entry = entry
2751 del self.obj
2752 del self.attribute
2753 if target:
2754 NameNode.analyse_target_types(self, env)
2755 else:
2756 NameNode.analyse_rvalue_entry(self, env)
2758 def analyse_as_ordinary_attribute(self, env, target):
2759 self.obj.analyse_types(env)
2760 self.analyse_attribute(env)
2761 if self.entry and self.entry.is_cmethod and not self.is_called:
2762 # error(self.pos, "C method can only be called")
2763 pass
2764 ## Reference to C array turns into pointer to first element.
2765 #while self.type.is_array:
2766 # self.type = self.type.element_ptr_type()
2767 if self.is_py_attr:
2768 if not target:
2769 self.is_temp = 1
2770 self.result_ctype = py_object_type
2772 def analyse_attribute(self, env):
2773 # Look up attribute and set self.type and self.member.
2774 self.is_py_attr = 0
2775 self.member = self.attribute
2776 if self.obj.type.is_string:
2777 self.obj = self.obj.coerce_to_pyobject(env)
2778 obj_type = self.obj.type
2779 if obj_type.is_ptr or obj_type.is_array:
2780 obj_type = obj_type.base_type
2781 self.op = "->"
2782 elif obj_type.is_extension_type:
2783 self.op = "->"
2784 else:
2785 self.op = "."
2786 if obj_type.has_attributes:
2787 entry = None
2788 if obj_type.attributes_known():
2789 entry = obj_type.scope.lookup_here(self.attribute)
2790 if entry and entry.is_member:
2791 entry = None
2792 else:
2793 error(self.pos,
2794 "Cannot select attribute of incomplete type '%s'"
2795 % obj_type)
2796 self.type = PyrexTypes.error_type
2797 return
2798 self.entry = entry
2799 if entry:
2800 if obj_type.is_extension_type and entry.name == "__weakref__":
2801 error(self.pos, "Illegal use of special attribute __weakref__")
2802 # methods need the normal attribute lookup
2803 # because they do not have struct entries
2804 if entry.is_variable or entry.is_cmethod:
2805 self.type = entry.type
2806 self.member = entry.cname
2807 return
2808 else:
2809 # If it's not a variable or C method, it must be a Python
2810 # method of an extension type, so we treat it like a Python
2811 # attribute.
2812 pass
2813 # If we get here, the base object is not a struct/union/extension
2814 # type, or it is an extension type and the attribute is either not
2815 # declared or is declared as a Python method. Treat it as a Python
2816 # attribute reference.
2817 self.analyse_as_python_attribute(env)
2819 def analyse_as_python_attribute(self, env):
2820 obj_type = self.obj.type
2821 self.member = self.attribute
2822 if obj_type.is_pyobject:
2823 self.type = py_object_type
2824 self.is_py_attr = 1
2825 self.interned_attr_cname = env.intern_identifier(self.attribute)
2826 self.gil_check(env)
2827 else:
2828 if not obj_type.is_error:
2829 error(self.pos,
2830 "Object of type '%s' has no attribute '%s'" %
2831 (obj_type, self.attribute))
2833 gil_message = "Accessing Python attribute"
2835 def is_simple(self):
2836 if self.obj:
2837 return self.result_in_temp() or self.obj.is_simple()
2838 else:
2839 return NameNode.is_simple(self)
2841 def is_lvalue(self):
2842 if self.obj:
2843 return 1
2844 else:
2845 return NameNode.is_lvalue(self)
2847 def is_ephemeral(self):
2848 if self.obj:
2849 return self.obj.is_ephemeral()
2850 else:
2851 return NameNode.is_ephemeral(self)
2853 def calculate_result_code(self):
2854 #print "AttributeNode.calculate_result_code:", self.member ###
2855 #print "...obj node =", self.obj, "code", self.obj.result() ###
2856 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2857 obj = self.obj
2858 obj_code = obj.result_as(obj.type)
2859 #print "...obj_code =", obj_code ###
2860 if self.entry and self.entry.is_cmethod:
2861 if obj.type.is_extension_type:
2862 return "((struct %s *)%s%s%s)->%s" % (
2863 obj.type.vtabstruct_cname, obj_code, self.op,
2864 obj.type.vtabslot_cname, self.member)
2865 else:
2866 return self.member
2867 else:
2868 return "%s%s%s" % (obj_code, self.op, self.member)
2870 def generate_result_code(self, code):
2871 if self.is_py_attr:
2872 code.putln(
2873 '%s = PyObject_GetAttr(%s, %s); %s' % (
2874 self.result(),
2875 self.obj.py_result(),
2876 self.interned_attr_cname,
2877 code.error_goto_if_null(self.result(), self.pos)))
2878 code.put_gotref(self.py_result())
2879 else:
2880 # result_code contains what is needed, but we may need to insert
2881 # a check and raise an exception
2882 if (self.obj.type.is_extension_type
2883 and self.needs_none_check
2884 and code.globalstate.directives['nonecheck']):
2885 self.put_nonecheck(code)
2887 def generate_assignment_code(self, rhs, code):
2888 self.obj.generate_evaluation_code(code)
2889 if self.is_py_attr:
2890 code.put_error_if_neg(self.pos,
2891 'PyObject_SetAttr(%s, %s, %s)' % (
2892 self.obj.py_result(),
2893 self.interned_attr_cname,
2894 rhs.py_result()))
2895 rhs.generate_disposal_code(code)
2896 rhs.free_temps(code)
2897 else:
2898 if (self.obj.type.is_extension_type
2899 and self.needs_none_check
2900 and code.globalstate.directives['nonecheck']):
2901 self.put_nonecheck(code)
2903 select_code = self.result()
2904 if self.type.is_pyobject:
2905 rhs.make_owned_reference(code)
2906 code.put_giveref(rhs.py_result())
2907 code.put_gotref(select_code)
2908 code.put_decref(select_code, self.ctype())
2909 code.putln(
2910 "%s = %s;" % (
2911 select_code,
2912 rhs.result_as(self.ctype())))
2913 #rhs.result()))
2914 rhs.generate_post_assignment_code(code)
2915 rhs.free_temps(code)
2916 self.obj.generate_disposal_code(code)
2917 self.obj.free_temps(code)
2919 def generate_deletion_code(self, code):
2920 self.obj.generate_evaluation_code(code)
2921 if self.is_py_attr:
2922 code.put_error_if_neg(self.pos,
2923 'PyObject_DelAttr(%s, %s)' % (
2924 self.obj.py_result(),
2925 self.interned_attr_cname))
2926 else:
2927 error(self.pos, "Cannot delete C attribute of extension type")
2928 self.obj.generate_disposal_code(code)
2929 self.obj.free_temps(code)
2931 def annotate(self, code):
2932 if self.is_py_attr:
2933 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2934 else:
2935 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2937 def put_nonecheck(self, code):
2938 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2939 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2940 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2941 code.putln(code.error_goto(self.pos))
2942 code.putln("}")
2945 #-------------------------------------------------------------------
2946 #
2947 # Constructor nodes
2948 #
2949 #-------------------------------------------------------------------
2951 class SequenceNode(NewTempExprNode):
2952 # Base class for list and tuple constructor nodes.
2953 # Contains common code for performing sequence unpacking.
2954 #
2955 # args [ExprNode]
2956 # iterator ExprNode
2957 # unpacked_items [ExprNode] or None
2958 # coerced_unpacked_items [ExprNode] or None
2960 subexprs = ['args']
2962 is_sequence_constructor = 1
2963 unpacked_items = None
2965 def compile_time_value_list(self, denv):
2966 return [arg.compile_time_value(denv) for arg in self.args]
2968 def analyse_target_declaration(self, env):
2969 for arg in self.args:
2970 arg.analyse_target_declaration(env)
2972 def analyse_types(self, env, skip_children=False):
2973 for i in range(len(self.args)):
2974 arg = self.args[i]
2975 if not skip_children: arg.analyse_types(env)
2976 self.args[i] = arg.coerce_to_pyobject(env)
2977 self.type = py_object_type
2978 self.gil_check(env)
2979 self.is_temp = 1
2981 def analyse_target_types(self, env):
2982 self.iterator = PyTempNode(self.pos, env)
2983 self.unpacked_items = []
2984 self.coerced_unpacked_items = []
2985 for arg in self.args:
2986 arg.analyse_target_types(env)
2987 unpacked_item = PyTempNode(self.pos, env)
2988 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2989 self.unpacked_items.append(unpacked_item)
2990 self.coerced_unpacked_items.append(coerced_unpacked_item)
2991 self.type = py_object_type
2992 env.use_utility_code(unpacking_utility_code)
2994 def allocate_target_temps(self, env, rhs):
2995 self.iterator.allocate_temps(env)
2996 for arg, node in zip(self.args, self.coerced_unpacked_items):
2997 node.allocate_temps(env)
2998 arg.allocate_target_temps(env, None)
2999 #arg.release_target_temp(env)
3000 #node.release_temp(env)
3001 if rhs:
3002 rhs.release_temp(env)
3003 self.iterator.release_temp(env)
3004 for node in self.coerced_unpacked_items:
3005 node.release_temp(env)
3007 # def release_target_temp(self, env):
3008 # #for arg in self.args:
3009 # # arg.release_target_temp(env)
3010 # #for node in self.coerced_unpacked_items:
3011 # # node.release_temp(env)
3012 # self.iterator.release_temp(env)
3014 def generate_result_code(self, code):
3015 self.generate_operation_code(code)
3017 def generate_assignment_code(self, rhs, code):
3018 # Need to work around the fact that generate_evaluation_code
3019 # allocates the temps in a rather hacky way -- the assignment
3020 # is evaluated twice, within each if-block.
3022 if rhs.type is tuple_type:
3023 tuple_check = "likely(%s != Py_None)"
3024 else:
3025 tuple_check = "PyTuple_CheckExact(%s)"
3026 code.putln(
3027 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3028 tuple_check % rhs.py_result(),
3029 rhs.py_result(),
3030 len(self.args)))
3031 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3032 for i in range(len(self.args)):
3033 item = self.unpacked_items[i]
3034 code.put(
3035 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3036 item.result(),
3037 i))
3038 code.put_incref(item.result(), item.ctype())
3039 value_node = self.coerced_unpacked_items[i]
3040 value_node.generate_evaluation_code(code)
3041 rhs.generate_disposal_code(code)
3043 for i in range(len(self.args)):
3044 self.args[i].generate_assignment_code(
3045 self.coerced_unpacked_items[i], code)
3047 code.putln("} else {")
3049 if rhs.type is tuple_type:
3050 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3051 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3052 rhs.py_result(), len(self.args)))
3053 code.putln(code.error_goto(self.pos))
3054 else:
3055 code.putln(
3056 "%s = PyObject_GetIter(%s); %s" % (
3057 self.iterator.result(),
3058 rhs.py_result(),
3059 code.error_goto_if_null(self.iterator.result(), self.pos)))
3060 code.put_gotref(self.iterator.py_result())
3061 rhs.generate_disposal_code(code)
3062 for i in range(len(self.args)):
3063 item = self.unpacked_items[i]
3064 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3065 self.iterator.py_result(), i)
3066 code.putln(
3067 "%s = %s; %s" % (
3068 item.result(),
3069 typecast(item.ctype(), py_object_type, unpack_code),
3070 code.error_goto_if_null(item.result(), self.pos)))
3071 code.put_gotref(item.py_result())
3072 value_node = self.coerced_unpacked_items[i]
3073 value_node.generate_evaluation_code(code)
3074 code.put_error_if_neg(self.pos,
3075 "__Pyx_EndUnpack(%s)" % (
3076 self.iterator.py_result()))
3077 if debug_disposal_code:
3078 print("UnpackNode.generate_assignment_code:")
3079 print("...generating disposal code for %s" % self.iterator)
3080 self.iterator.generate_disposal_code(code)
3081 self.iterator.free_temps(code)
3083 for i in range(len(self.args)):
3084 self.args[i].generate_assignment_code(
3085 self.coerced_unpacked_items[i], code)
3087 code.putln("}")
3088 rhs.free_temps(code)
3090 def annotate(self, code):
3091 for arg in self.args:
3092 arg.annotate(code)
3093 if self.unpacked_items:
3094 for arg in self.unpacked_items:
3095 arg.annotate(code)
3096 for arg in self.coerced_unpacked_items:
3097 arg.annotate(code)
3100 class TupleNode(SequenceNode):
3101 # Tuple constructor.
3103 gil_message = "Constructing Python tuple"
3105 def analyse_types(self, env, skip_children=False):
3106 if len(self.args) == 0:
3107 self.is_temp = 0
3108 self.is_literal = 1
3109 else:
3110 SequenceNode.analyse_types(self, env, skip_children)
3111 self.type = tuple_type
3113 def calculate_result_code(self):
3114 if len(self.args) > 0:
3115 error(self.pos, "Positive length tuples must be constructed.")
3116 else:
3117 return Naming.empty_tuple
3119 def calculate_constant_result(self):
3120 self.constant_result = tuple([
3121 arg.constant_result for arg in self.args])
3123 def compile_time_value(self, denv):
3124 values = self.compile_time_value_list(denv)
3125 try:
3126 return tuple(values)
3127 except Exception, e:
3128 self.compile_time_value_error(e)
3130 def generate_operation_code(self, code):
3131 if len(self.args) == 0:
3132 # result_code is Naming.empty_tuple
3133 return
3134 code.putln(
3135 "%s = PyTuple_New(%s); %s" % (
3136 self.result(),
3137 len(self.args),
3138 code.error_goto_if_null(self.result(), self.pos)))
3139 code.put_gotref(self.py_result())
3140 for i in range(len(self.args)):
3141 arg = self.args[i]
3142 if not arg.result_in_temp():
3143 code.put_incref(arg.result(), arg.ctype())
3144 code.putln(
3145 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3146 self.result(),
3147 i,
3148 arg.py_result()))
3149 code.put_giveref(arg.py_result())
3151 def generate_subexpr_disposal_code(self, code):
3152 # We call generate_post_assignment_code here instead
3153 # of generate_disposal_code, because values were stored
3154 # in the tuple using a reference-stealing operation.
3155 for arg in self.args:
3156 arg.generate_post_assignment_code(code)
3157 # Should NOT call free_temps -- this is invoked by the default
3158 # generate_evaluation_code which will do that.
3161 class ListNode(SequenceNode):
3162 # List constructor.
3164 # obj_conversion_errors [PyrexError] used internally
3165 # orignial_args [ExprNode] used internally
3167 gil_message = "Constructing Python list"
3169 def analyse_expressions(self, env):
3170 SequenceNode.analyse_expressions(self, env)
3171 self.coerce_to_pyobject(env)
3173 def analyse_types(self, env):
3174 hold_errors()
3175 self.original_args = list(self.args)
3176 SequenceNode.analyse_types(self, env)
3177 self.type = list_type
3178 self.obj_conversion_errors = held_errors()
3179 release_errors(ignore=True)
3181 def coerce_to(self, dst_type, env):
3182 if dst_type.is_pyobject:
3183 for err in self.obj_conversion_errors:
3184 report_error(err)
3185 self.obj_conversion_errors = []
3186 if not self.type.subtype_of(dst_type):
3187 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3188 elif dst_type.is_ptr:
3189 base_type = dst_type.base_type
3190 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3191 for i in range(len(self.original_args)):
3192 arg = self.args[i]
3193 if isinstance(arg, CoerceToPyTypeNode):
3194 arg = arg.arg
3195 self.args[i] = arg.coerce_to(base_type, env)
3196 elif dst_type.is_struct:
3197 if len(self.args) > len(dst_type.scope.var_entries):
3198 error(self.pos, "Too may members for '%s'" % dst_type)
3199 else:
3200 if len(self.args) < len(dst_type.scope.var_entries):
3201 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3202 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3203 if isinstance(arg, CoerceToPyTypeNode):
3204 arg = arg.arg
3205 self.args[i] = arg.coerce_to(member.type, env)
3206 self.type = dst_type
3207 else:
3208 self.type = error_type
3209 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3210 return self
3212 def release_temp(self, env):
3213 if self.type.is_array:
3214 # To be valid C++, we must allocate the memory on the stack
3215 # manually and be sure not to reuse it for something else.
3216 pass
3217 else:
3218 SequenceNode.release_temp(self, env)
3220 def calculate_constant_result(self):
3221 self.constant_result = [
3222 arg.constant_result for arg in self.args]
3224 def compile_time_value(self, denv):
3225 return self.compile_time_value_list(denv)
3227 def generate_operation_code(self, code):
3228 if self.type.is_pyobject:
3229 for err in self.obj_conversion_errors:
3230 report_error(err)
3231 code.putln("%s = PyList_New(%s); %s" %
3232 (self.result(),
3233 len(self.args),
3234 code.error_goto_if_null(self.result(), self.pos)))
3235 code.put_gotref(self.py_result())
3236 for i in range(len(self.args)):
3237 arg = self.args[i]
3238 #if not arg.is_temp:
3239 if not arg.result_in_temp():
3240 code.put_incref(arg.result(), arg.ctype())
3241 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3242 (self.result(),
3243 i,
3244 arg.py_result()))
3245 code.put_giveref(arg.py_result())
3246 elif self.type.is_array:
3247 for i, arg in enumerate(self.args):
3248 code.putln("%s[%s] = %s;" % (
3249 self.result(),
3250 i,
3251 arg.result()))
3252 elif self.type.is_struct:
3253 for arg, member in zip(self.args, self.type.scope.var_entries):
3254 code.putln("%s.%s = %s;" % (
3255 self.result(),
3256 member.cname,
3257 arg.result()))
3258 else:
3259 raise InternalError("List type never specified")
3261 def generate_subexpr_disposal_code(self, code):
3262 # We call generate_post_assignment_code here instead
3263 # of generate_disposal_code, because values were stored
3264 # in the list using a reference-stealing operation.
3265 for arg in self.args:
3266 arg.generate_post_assignment_code(code)
3267 # Should NOT call free_temps -- this is invoked by the default
3268 # generate_evaluation_code which will do that.
3271 class ComprehensionNode(NewTempExprNode):
3272 subexprs = ["target"]
3273 child_attrs = ["loop", "append"]
3275 def analyse_types(self, env):
3276 self.target.analyse_expressions(env)
3277 self.type = self.target.type
3278 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3279 self.loop.analyse_declarations(env)
3281 def allocate_temps(self, env, result = None):
3282 if debug_temp_alloc:
3283 print("%s Allocating temps" % self)
3284 self.allocate_temp(env, result)
3285 # call loop.analyse_expressions() now to make sure temps get
3286 # allocated at the right time
3287 self.loop.analyse_expressions(env)
3289 def calculate_result_code(self):
3290 return self.target.result()
3292 def generate_result_code(self, code):
3293 self.generate_operation_code(code)
3295 def generate_operation_code(self, code):
3296 self.loop.generate_execution_code(code)
3298 def annotate(self, code):
3299 self.loop.annotate(code)
3302 class ComprehensionAppendNode(NewTempExprNode):
3303 # Need to be careful to avoid infinite recursion:
3304 # target must not be in child_attrs/subexprs
3305 subexprs = ['expr']
3307 def analyse_types(self, env):
3308 self.expr.analyse_types(env)
3309 if not self.expr.type.is_pyobject:
3310 self.expr = self.expr.coerce_to_pyobject(env)
3311 self.type = PyrexTypes.c_int_type
3312 self.is_temp = 1
3314 def generate_result_code(self, code):
3315 if self.target.type is list_type:
3316 function = "PyList_Append"
3317 elif self.target.type is set_type:
3318 function = "PySet_Add"
3319 else:
3320 raise InternalError(
3321 "Invalid type for comprehension node: %s" % self.target.type)
3323 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3324 (self.result(),
3325 function,
3326 self.target.result(),
3327 self.expr.result(),
3328 code.error_goto_if(self.result(), self.pos)))
3330 class DictComprehensionAppendNode(ComprehensionAppendNode):
3331 subexprs = ['key_expr', 'value_expr']
3333 def analyse_types(self, env):
3334 self.key_expr.analyse_types(env)
3335 if not self.key_expr.type.is_pyobject:
3336 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3337 self.value_expr.analyse_types(env)
3338 if not self.value_expr.type.is_pyobject:
3339 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3340 self.type = PyrexTypes.c_int_type
3341 self.is_temp = 1
3343 def generate_result_code(self, code):
3344 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3345 (self.result(),
3346 self.target.result(),
3347 self.key_expr.result(),
3348 self.value_expr.result(),
3349 code.error_goto_if(self.result(), self.pos)))
3352 class SetNode(NewTempExprNode):
3353 # Set constructor.
3355 subexprs = ['args']
3357 gil_message = "Constructing Python set"
3359 def analyse_types(self, env):
3360 for i in range(len(self.args)):
3361 arg = self.args[i]
3362 arg.analyse_types(env)
3363 self.args[i] = arg.coerce_to_pyobject(env)
3364 self.type = set_type
3365 self.gil_check(env)
3366 self.is_temp = 1
3368 def calculate_constant_result(self):
3369 self.constant_result = set([
3370 arg.constant_result for arg in self.args])
3372 def compile_time_value(self, denv):
3373 values = [arg.compile_time_value(denv) for arg in self.args]
3374 try:
3375 return set(values)
3376 except Exception, e:
3377 self.compile_time_value_error(e)
3379 def generate_evaluation_code(self, code):
3380 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3381 self.allocate_temp_result(code)
3382 code.putln(
3383 "%s = PySet_New(0); %s" % (
3384 self.result(),
3385 code.error_goto_if_null(self.result(), self.pos)))
3386 code.put_gotref(self.py_result())
3387 for arg in self.args:
3388 arg.generate_evaluation_code(code)
3389 code.putln(
3390 code.error_goto_if_neg(
3391 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3392 self.pos))
3393 arg.generate_disposal_code(code)
3394 arg.free_temps(code)
3397 class DictNode(ExprNode):
3398 # Dictionary constructor.
3399 #
3400 # key_value_pairs [DictItemNode]
3401 #
3402 # obj_conversion_errors [PyrexError] used internally
3404 subexprs = ['key_value_pairs']
3406 def calculate_constant_result(self):
3407 self.constant_result = dict([
3408 item.constant_result for item in self.key_value_pairs])
3410 def compile_time_value(self, denv):
3411 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3412 for item in self.key_value_pairs]
3413 try:
3414 return dict(pairs)
3415 except Exception, e:
3416 self.compile_time_value_error(e)
3418 def analyse_types(self, env):
3419 hold_errors()
3420 self.type = dict_type
3421 for item in self.key_value_pairs:
3422 item.analyse_types(env)
3423 self.gil_check(env)
3424 self.obj_conversion_errors = held_errors()
3425 release_errors(ignore=True)
3426 self.is_temp = 1
3428 def coerce_to(self, dst_type, env):
3429 if dst_type.is_pyobject:
3430 self.release_errors()
3431 if not self.type.subtype_of(dst_type):
3432 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3433 elif dst_type.is_struct_or_union:
3434 self.type = dst_type
3435 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3436 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3437 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3438 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3439 for item in self.key_value_pairs:
3440 if isinstance(item.key, CoerceToPyTypeNode):
3441 item.key = item.key.arg
3442 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3443 error(item.key.pos, "Invalid struct field identifier")
3444 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3445 else:
3446 member = dst_type.scope.lookup_here(item.key.value)
3447 if not member:
3448 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3449 else:
3450 value = item.value
3451 if isinstance(value, CoerceToPyTypeNode):
3452 value = value.arg
3453 item.value = value.coerce_to(member.type, env)
3454 else:
3455 self.type = error_type
3456 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3457 return self
3459 def release_errors(self):
3460 for err in self.obj_conversion_errors:
3461 report_error(err)
3462 self.obj_conversion_errors = []
3464 gil_message = "Constructing Python dict"
3466 def allocate_temps(self, env, result = None):
3467 # Custom method used here because key-value
3468 # pairs are evaluated and used one at a time.
3469 self.allocate_temp(env, result)
3470 for item in self.key_value_pairs:
3471 item.key.allocate_temps(env)
3472 item.value.allocate_temps(env)
3473 item.key.release_temp(env)
3474 item.value.release_temp(env)
3476 def generate_evaluation_code(self, code):
3477 # Custom method used here because key-value
3478 # pairs are evaluated and used one at a time.
3479 if self.type.is_pyobject:
3480 self.release_errors()
3481 code.putln(
3482 "%s = PyDict_New(); %s" % (
3483 self.result(),
3484 code.error_goto_if_null(self.result(), self.pos)))
3485 code.put_gotref(self.py_result())
3486 for item in self.key_value_pairs:
3487 item.generate_evaluation_code(code)
3488 if self.type.is_pyobject:
3489 code.put_error_if_neg(self.pos,
3490 "PyDict_SetItem(%s, %s, %s)" % (
3491 self.result(),
3492 item.key.py_result(),
3493 item.value.py_result()))
3494 else:
3495 code.putln("%s.%s = %s;" % (
3496 self.result(),
3497 item.key.value,
3498 item.value.result()))
3499 item.generate_disposal_code(code)
3500 item.free_temps(code)
3502 def annotate(self, code):
3503 for item in self.key_value_pairs:
3504 item.annotate(code)
3506 class DictItemNode(ExprNode):
3507 # Represents a single item in a DictNode
3508 #
3509 # key ExprNode
3510 # value ExprNode
3511 subexprs = ['key', 'value']
3513 def calculate_constant_result(self):
3514 self.constant_result = (
3515 self.key.constant_result, self.value.constant_result)
3517 def analyse_types(self, env):
3518 self.key.analyse_types(env)
3519 self.value.analyse_types(env)
3520 self.key = self.key.coerce_to_pyobject(env)
3521 self.value = self.value.coerce_to_pyobject(env)
3523 def generate_evaluation_code(self, code):
3524 self.key.generate_evaluation_code(code)
3525 self.value.generate_evaluation_code(code)
3527 def generate_disposal_code(self, code):
3528 self.key.generate_disposal_code(code)
3529 self.value.generate_disposal_code(code)
3531 def free_temps(self, code):
3532 self.key.free_temps(code)
3533 self.value.free_temps(code)
3535 def __iter__(self):
3536 return iter([self.key, self.value])
3539 class ClassNode(ExprNode):
3540 # Helper class used in the implementation of Python
3541 # class definitions. Constructs a class object given
3542 # a name, tuple of bases and class dictionary.
3543 #
3544 # name EncodedString Name of the class
3545 # cname string Class name as a Python string
3546 # bases ExprNode Base class tuple
3547 # dict ExprNode Class dict (not owned by this node)
3548 # doc ExprNode or None Doc string
3549 # module_name string Name of defining module
3551 subexprs = ['bases', 'doc']
3553 def analyse_types(self, env):
3554 self.cname = env.intern_identifier(self.name)
3555 self.bases.analyse_types(env)
3556 if self.doc:
3557 self.doc.analyse_types(env)
3558 self.doc = self.doc.coerce_to_pyobject(env)
3559 self.module_name = env.global_scope().qualified_name
3560 self.type = py_object_type
3561 self.gil_check(env)
3562 self.is_temp = 1
3563 env.use_utility_code(create_class_utility_code);
3565 gil_message = "Constructing Python class"
3567 def generate_result_code(self, code):
3568 if self.doc:
3569 code.put_error_if_neg(self.pos,
3570 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3571 self.dict.py_result(),
3572 self.doc.py_result()))
3573 code.putln(
3574 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3575 self.result(),
3576 self.bases.py_result(),
3577 self.dict.py_result(),
3578 self.cname,
3579 self.module_name,
3580 code.error_goto_if_null(self.result(), self.pos)))
3581 code.put_gotref(self.py_result())
3584 class UnboundMethodNode(ExprNode):
3585 # Helper class used in the implementation of Python
3586 # class definitions. Constructs an unbound method
3587 # object from a class and a function.
3588 #
3589 # class_cname string C var holding the class object
3590 # function ExprNode Function object
3592 subexprs = ['function']
3594 def analyse_types(self, env):
3595 self.function.analyse_types(env)
3596 self.type = py_object_type
3597 self.gil_check(env)
3598 self.is_temp = 1
3600 gil_message = "Constructing an unbound method"
3602 def generate_result_code(self, code):
3603 code.putln(
3604 "%s = PyMethod_New(%s, 0, %s); %s" % (
3605 self.result(),
3606 self.function.py_result(),
3607 self.class_cname,
3608 code.error_goto_if_null(self.result(), self.pos)))
3609 code.put_gotref(self.py_result())
3611 class PyCFunctionNode(AtomicNewTempExprNode):
3612 # Helper class used in the implementation of Python
3613 # class definitions. Constructs a PyCFunction object
3614 # from a PyMethodDef struct.
3615 #
3616 # pymethdef_cname string PyMethodDef structure
3618 def analyse_types(self, env):
3619 self.type = py_object_type
3620 self.gil_check(env)
3621 self.is_temp = 1
3623 gil_message = "Constructing Python function"
3625 def generate_result_code(self, code):
3626 code.putln(
3627 "%s = PyCFunction_New(&%s, 0); %s" % (
3628 self.result(),
3629 self.pymethdef_cname,
3630 code.error_goto_if_null(self.result(), self.pos)))
3631 code.put_gotref(self.py_result())
3633 #-------------------------------------------------------------------
3634 #
3635 # Unary operator nodes
3636 #
3637 #-------------------------------------------------------------------
3639 compile_time_unary_operators = {
3640 'not': operator.not_,
3641 '~': operator.inv,
3642 '-': operator.neg,
3643 '+': operator.pos,
3644 }
3646 class UnopNode(ExprNode):
3647 # operator string
3648 # operand ExprNode
3649 #
3650 # Processing during analyse_expressions phase:
3651 #
3652 # analyse_c_operation
3653 # Called when the operand is not a pyobject.
3654 # - Check operand type and coerce if needed.
3655 # - Determine result type and result code fragment.
3656 # - Allocate temporary for result if needed.
3658 subexprs = ['operand']
3660 def calculate_constant_result(self):
3661 func = compile_time_unary_operators[self.operator]
3662 self.constant_result = func(self.operand.constant_result)
3664 def compile_time_value(self, denv):
3665 func = compile_time_unary_operators.get(self.operator)
3666 if not func:
3667 error(self.pos,
3668 "Unary '%s' not supported in compile-time expression"
3669 % self.operator)
3670 operand = self.operand.compile_time_value(denv)
3671 try:
3672 return func(operand)
3673 except Exception, e:
3674 self.compile_time_value_error(e)
3676 def analyse_types(self, env):
3677 self.operand.analyse_types(env)
3678 if self.is_py_operation():
3679 self.coerce_operand_to_pyobject(env)
3680 self.type = py_object_type
3681 self.gil_check(env)
3682 self.is_temp = 1
3683 else:
3684 self.analyse_c_operation(env)
3686 def check_const(self):
3687 self.operand.check_const()
3689 def is_py_operation(self):
3690 return self.operand.type.is_pyobject
3692 def coerce_operand_to_pyobject(self, env):
3693 self.operand = self.operand.coerce_to_pyobject(env)
3695 def generate_result_code(self, code):
3696 if self.operand.type.is_pyobject:
3697 self.generate_py_operation_code(code)
3698 else:
3699 if self.is_temp:
3700 self.generate_c_operation_code(code)
3702 def generate_py_operation_code(self, code):
3703 function = self.py_operation_function()
3704 code.putln(
3705 "%s = %s(%s); %s" % (
3706 self.result(),
3707 function,
3708 self.operand.py_result(),
3709 code.error_goto_if_null(self.result(), self.pos)))
3710 code.put_gotref(self.py_result())
3712 def type_error(self):
3713 if not self.operand.type.is_error:
3714 error(self.pos, "Invalid operand type for '%s' (%s)" %
3715 (self.operator, self.operand.type))
3716 self.type = PyrexTypes.error_type
3719 class NotNode(ExprNode):
3720 # 'not' operator
3721 #
3722 # operand ExprNode
3724 def calculate_constant_result(self):
3725 self.constant_result = not self.operand.constant_result
3727 def compile_time_value(self, denv):
3728 operand = self.operand.compile_time_value(denv)
3729 try:
3730 return not operand
3731 except Exception, e:
3732 self.compile_time_value_error(e)
3734 subexprs = ['operand']
3736 def analyse_types(self, env):
3737 self.operand.analyse_types(env)
3738 self.operand = self.operand.coerce_to_boolean(env)
3739 self.type = PyrexTypes.c_bint_type
3741 def calculate_result_code(self):
3742 return "(!%s)" % self.operand.result()
3744 def generate_result_code(self, code):
3745 pass
3748 class UnaryPlusNode(UnopNode):
3749 # unary '+' operator
3751 operator = '+'
3753 def analyse_c_operation(self, env):
3754 self.type = self.operand.type
3756 def py_operation_function(self):
3757 return "PyNumber_Positive"
3759 def calculate_result_code(self):
3760 return self.operand.result()
3763 class UnaryMinusNode(UnopNode):
3764 # unary '-' operator
3766 operator = '-'
3768 def analyse_c_operation(self, env):
3769 if self.operand.type.is_numeric:
3770 self.type = self.operand.type
3771 else:
3772 self.type_error()
3774 def py_operation_function(self):
3775 return "PyNumber_Negative"
3777 def calculate_result_code(self):
3778 return "(-%s)" % self.operand.result()
3781 class TildeNode(UnopNode):
3782 # unary '~' operator
3784 def analyse_c_operation(self, env):
3785 if self.operand.type.is_int:
3786 self.type = self.operand.type
3787 else:
3788 self.type_error()
3790 def py_operation_function(self):
3791 return "PyNumber_Invert"
3793 def calculate_result_code(self):
3794 return "(~%s)" % self.operand.result()
3797 class AmpersandNode(ExprNode):
3798 # The C address-of operator.
3799 #
3800 # operand ExprNode
3802 subexprs = ['operand']
3804 def analyse_types(self, env):
3805 self.operand.analyse_types(env)
3806 argtype = self.operand.type
3807 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3808 self.error("Taking address of non-lvalue")
3809 return
3810 if argtype.is_pyobject:
3811 self.error("Cannot take address of Python variable")
3812 return
3813 self.type = PyrexTypes.c_ptr_type(argtype)
3815 def check_const(self):
3816 self.operand.check_const_addr()
3818 def error(self, mess):
3819 error(self.pos, mess)
3820 self.type = PyrexTypes.error_type
3821 self.result_code = "<error>"
3823 def calculate_result_code(self):
3824 return "(&%s)" % self.operand.result()
3826 def generate_result_code(self, code):
3827 pass
3830 unop_node_classes = {
3831 "+": UnaryPlusNode,
3832 "-": UnaryMinusNode,
3833 "~": TildeNode,
3834 }
3836 def unop_node(pos, operator, operand):
3837 # Construct unnop node of appropriate class for
3838 # given operator.
3839 if isinstance(operand, IntNode) and operator == '-':
3840 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3841 elif isinstance(operand, UnopNode) and operand.operator == operator:
3842 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3843 return unop_node_classes[operator](pos,
3844 operator = operator,
3845 operand = operand)
3848 class TypecastNode(NewTempExprNode):
3849 # C type cast
3850 #
3851 # operand ExprNode
3852 # base_type CBaseTypeNode
3853 # declarator CDeclaratorNode
3854 #
3855 # If used from a transform, one can if wanted specify the attribute
3856 # "type" directly and leave base_type and declarator to None
3858 subexprs = ['operand']
3859 base_type = declarator = type = None
3861 def analyse_types(self, env):
3862 if self.type is None:
3863 base_type = self.base_type.analyse(env)
3864 _, self.type = self.declarator.analyse(base_type, env)
3865 if self.type.is_cfunction:
3866 error(self.pos,
3867 "Cannot cast to a function type")
3868 self.type = PyrexTypes.error_type
3869 self.operand.analyse_types(env)
3870 to_py = self.type.is_pyobject
3871 from_py = self.operand.type.is_pyobject
3872 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3873 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3874 if to_py and not from_py:
3875 if (self.operand.type.to_py_function and
3876 self.operand.type.create_convert_utility_code(env)):
3877 self.result_ctype = py_object_type
3878 self.operand = self.operand.coerce_to_pyobject(env)
3879 else:
3880 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3881 self.operand = self.operand.coerce_to_simple(env)
3882 elif from_py and not to_py:
3883 if self.type.from_py_function:
3884 self.operand = self.operand.coerce_to(self.type, env)
3885 else:
3886 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3887 elif from_py and to_py:
3888 if self.typecheck and self.type.is_extension_type:
3889 self.operand = PyTypeTestNode(self.operand, self.type, env)
3891 def check_const(self):
3892 self.operand.check_const()
3894 def calculate_constant_result(self):
3895 self.constant_result = self.operand.constant_result
3897 def calculate_result_code(self):
3898 opnd = self.operand
3899 return self.type.cast_code(opnd.result())
3901 def result_as(self, type):
3902 if self.type.is_pyobject and not self.is_temp:
3903 # Optimise away some unnecessary casting
3904 return self.operand.result_as(type)
3905 else:
3906 return ExprNode.result_as(self, type)
3908 def generate_result_code(self, code):
3909 if self.is_temp:
3910 code.putln(
3911 "%s = (PyObject *)%s;" % (
3912 self.result(),
3913 self.operand.result()))
3914 code.put_incref(self.result(), self.ctype())
3917 class SizeofNode(ExprNode):
3918 # Abstract base class for sizeof(x) expression nodes.
3920 type = PyrexTypes.c_size_t_type
3922 def check_const(self):
3923 pass
3925 def generate_result_code(self, code):
3926 pass
3929 class SizeofTypeNode(SizeofNode):
3930 # C sizeof function applied to a type
3931 #
3932 # base_type CBaseTypeNode
3933 # declarator CDeclaratorNode
3935 subexprs = []
3936 arg_type = None
3938 def analyse_types(self, env):
3939 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3940 # this could be better handled by more uniformly treating types as runtime-available objects
3941 if 0 and self.base_type.module_path:
3942 path = self.base_type.module_path
3943 obj = env.lookup(path[0])
3944 if obj.as_module is None:
3945 operand = NameNode(pos=self.pos, name=path[0])
3946 for attr in path[1:]:
3947 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3948 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3949 self.operand = operand
3950 self.__class__ = SizeofVarNode
3951 self.analyse_types(env)
3952 return
3953 if self.arg_type is None:
3954 base_type = self.base_type.analyse(env)
3955 _, arg_type = self.declarator.analyse(base_type, env)
3956 self.arg_type = arg_type
3957 self.check_type()
3959 def check_type(self):
3960 arg_type = self.arg_type
3961 if arg_type.is_pyobject and not arg_type.is_extension_type:
3962 error(self.pos, "Cannot take sizeof Python object")
3963 elif arg_type.is_void:
3964 error(self.pos, "Cannot take sizeof void")
3965 elif not arg_type.is_complete():
3966 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3968 def calculate_result_code(self):
3969 if self.arg_type.is_extension_type:
3970 # the size of the pointer is boring
3971 # we want the size of the actual struct
3972 arg_code = self.arg_type.declaration_code("", deref=1)
3973 else:
3974 arg_code = self.arg_type.declaration_code("")
3975 return "(sizeof(%s))" % arg_code
3978 class SizeofVarNode(SizeofNode):
3979 # C sizeof function applied to a variable
3980 #
3981 # operand ExprNode
3983 subexprs = ['operand']
3985 def analyse_types(self, env):
3986 # We may actually be looking at a type rather than a variable...
3987 # If we are, traditional analysis would fail...
3988 operand_as_type = self.operand.analyse_as_type(env)
3989 if operand_as_type:
3990 self.arg_type = operand_as_type
3991 self.__class__ = SizeofTypeNode
3992 self.check_type()
3993 else:
3994 self.operand.analyse_types(env)
3996 def calculate_result_code(self):
3997 return "(sizeof(%s))" % self.operand.result()
3999 def generate_result_code(self, code):
4000 pass
4003 #-------------------------------------------------------------------
4004 #
4005 # Binary operator nodes
4006 #
4007 #-------------------------------------------------------------------
4009 def _not_in(x, seq):
4010 return x not in seq
4012 compile_time_binary_operators = {
4013 '<': operator.lt,
4014 '<=': operator.le,
4015 '==': operator.eq,
4016 '!=': operator.ne,
4017 '>=': operator.ge,
4018 '>': operator.gt,
4019 'is': operator.is_,
4020 'is_not': operator.is_not,
4021 '+': operator.add,
4022 '&': operator.and_,
4023 '/': operator.div,
4024 '//': operator.floordiv,
4025 '<<': operator.lshift,
4026 '%': operator.mod,
4027 '*': operator.mul,
4028 '|': operator.or_,
4029 '**': operator.pow,
4030 '>>': operator.rshift,
4031 '-': operator.sub,
4032 #'/': operator.truediv,
4033 '^': operator.xor,
4034 'in': operator.contains,
4035 'not_in': _not_in,
4036 }
4038 def get_compile_time_binop(node):
4039 func = compile_time_binary_operators.get(node.operator)
4040 if not func:
4041 error(node.pos,
4042 "Binary '%s' not supported in compile-time expression"
4043 % node.operator)
4044 return func
4046 class BinopNode(NewTempExprNode):
4047 # operator string
4048 # operand1 ExprNode
4049 # operand2 ExprNode
4050 #
4051 # Processing during analyse_expressions phase:
4052 #
4053 # analyse_c_operation
4054 # Called when neither operand is a pyobject.
4055 # - Check operand types and coerce if needed.
4056 # - Determine result type and result code fragment.
4057 # - Allocate temporary for result if needed.
4059 subexprs = ['operand1', 'operand2']
4061 def calculate_constant_result(self):
4062 func = compile_time_binary_operators[self.operator]
4063 self.constant_result = func(
4064 self.operand1.constant_result,
4065 self.operand2.constant_result)
4067 def compile_time_value(self, denv):
4068 func = get_compile_time_binop(self)
4069 operand1 = self.operand1.compile_time_value(denv)
4070 operand2 = self.operand2.compile_time_value(denv)
4071 try:
4072 return func(operand1, operand2)
4073 except Exception, e:
4074 self.compile_time_value_error(e)
4076 def analyse_types(self, env):
4077 self.operand1.analyse_types(env)
4078 self.operand2.analyse_types(env)
4079 if self.is_py_operation():
4080 self.coerce_operands_to_pyobjects(env)
4081 self.type = py_object_type
4082 self.gil_check(env)
4083 self.is_temp = 1
4084 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4085 self.operand1 = self.operand1.coerce_to_temp(env)
4086 else:
4087 self.analyse_c_operation(env)
4089 def is_py_operation(self):
4090 return (self.operand1.type.is_pyobject
4091 or self.operand2.type.is_pyobject)
4093 def coerce_operands_to_pyobjects(self, env):
4094 self.operand1 = self.operand1.coerce_to_pyobject(env)
4095 self.operand2 = self.operand2.coerce_to_pyobject(env)
4097 def check_const(self):
4098 self.operand1.check_const()
4099 self.operand2.check_const()
4101 def generate_result_code(self, code):
4102 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4103 if self.operand1.type.is_pyobject:
4104 function = self.py_operation_function()
4105 if function == "PyNumber_Power":
4106 extra_args = ", Py_None"
4107 else:
4108 extra_args = ""
4109 code.putln(
4110 "%s = %s(%s, %s%s); %s" % (
4111 self.result(),
4112 function,
4113 self.operand1.py_result(),
4114 self.operand2.py_result(),
4115 extra_args,
4116 code.error_goto_if_null(self.result(), self.pos)))
4117 code.put_gotref(self.py_result())
4118 else:
4119 if self.is_temp:
4120 self.generate_c_operation_code(code)
4122 def type_error(self):
4123 if not (self.operand1.type.is_error
4124 or self.operand2.type.is_error):
4125 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4126 (self.operator, self.operand1.type,
4127 self.operand2.type))
4128 self.type = PyrexTypes.error_type
4131 class NumBinopNode(BinopNode):
4132 # Binary operation taking numeric arguments.
4134 def analyse_c_operation(self, env):
4135 type1 = self.operand1.type
4136 type2 = self.operand2.type
4137 self.type = self.compute_c_result_type(type1, type2)
4138 if not self.type:
4139 self.type_error()
4141 def compute_c_result_type(self, type1, type2):
4142 if self.c_types_okay(type1, type2):
4143 return PyrexTypes.widest_numeric_type(type1, type2)
4144 else:
4145 return None
4147 def c_types_okay(self, type1, type2):
4148 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4149 return (type1.is_numeric or type1.is_enum) \
4150 and (type2.is_numeric or type2.is_enum)
4152 def calculate_result_code(self):
4153 return "(%s %s %s)" % (
4154 self.operand1.result(),
4155 self.operator,
4156 self.operand2.result())
4158 def py_operation_function(self):
4159 return self.py_functions[self.operator]
4161 py_functions = {
4162 "|": "PyNumber_Or",
4163 "^": "PyNumber_Xor",
4164 "&": "PyNumber_And",
4165 "<<": "PyNumber_Lshift",
4166 ">>": "PyNumber_Rshift",
4167 "+": "PyNumber_Add",
4168 "-": "PyNumber_Subtract",
4169 "*": "PyNumber_Multiply",
4170 "/": "__Pyx_PyNumber_Divide",
4171 "//": "PyNumber_FloorDivide",
4172 "%": "PyNumber_Remainder",
4173 "**": "PyNumber_Power"
4174 }
4177 class IntBinopNode(NumBinopNode):
4178 # Binary operation taking integer arguments.
4180 def c_types_okay(self, type1, type2):
4181 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4182 return (type1.is_int or type1.is_enum) \
4183 and (type2.is_int or type2.is_enum)
4186 class AddNode(NumBinopNode):
4187 # '+' operator.
4189 def is_py_operation(self):
4190 if self.operand1.type.is_string \
4191 and self.operand2.type.is_string:
4192 return 1
4193 else:
4194 return NumBinopNode.is_py_operation(self)
4196 def compute_c_result_type(self, type1, type2):
4197 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4198 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4199 return type1
4200 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4201 return type2
4202 else:
4203 return NumBinopNode.compute_c_result_type(
4204 self, type1, type2)
4207 class SubNode(NumBinopNode):
4208 # '-' operator.
4210 def compute_c_result_type(self, type1, type2):
4211 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4212 return type1
4213 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4214 return PyrexTypes.c_int_type
4215 else:
4216 return NumBinopNode.compute_c_result_type(
4217 self, type1, type2)
4220 class MulNode(NumBinopNode):
4221 # '*' operator.
4223 def is_py_operation(self):
4224 type1 = self.operand1.type
4225 type2 = self.operand2.type
4226 if (type1.is_string and type2.is_int) \
4227 or (type2.is_string and type1.is_int):
4228 return 1
4229 else:
4230 return NumBinopNode.is_py_operation(self)
4233 class DivNode(NumBinopNode):
4234 # '/' or '//' operator.
4236 cdivision = None
4237 cdivision_warnings = False
4239 def analyse_types(self, env):
4240 NumBinopNode.analyse_types(self, env)
4241 if not self.type.is_pyobject and env.directives['cdivision_warnings']:
4242 self.operand1 = self.operand1.coerce_to_simple(env)
4243 self.operand2 = self.operand2.coerce_to_simple(env)
4245 def generate_evaluation_code(self, code):
4246 if not self.type.is_pyobject:
4247 if self.cdivision is None:
4248 self.cdivision = (code.globalstate.directives['cdivision']
4249 or not self.type.signed
4250 or self.type.is_float)
4251 if not self.cdivision:
4252 code.globalstate.use_utility_code(div_utility_code.specialize(self.type))
4253 NumBinopNode.generate_evaluation_code(self, code)
4254 if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
4255 self.generate_div_warning_code(code)
4257 def generate_div_warning_code(self, code):
4258 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4259 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4260 self.operand1.result(),
4261 self.operand2.result()))
4262 code.putln(code.set_error_info(self.pos));
4263 code.put("if (__Pyx_cdivision_warning()) ")
4264 code.put_goto(code.error_label)
4265 code.putln("}")
4267 def calculate_result_code(self):
4268 if self.cdivision:
4269 return "(%s / %s)" % (
4270 self.operand1.result(),
4271 self.operand2.result())
4272 else:
4273 return "__Pyx_div_%s(%s, %s)" % (
4274 self.type.specalization_name(),
4275 self.operand1.result(),
4276 self.operand2.result())
4279 class ModNode(DivNode):
4280 # '%' operator.
4282 def is_py_operation(self):
4283 return (self.operand1.type.is_string
4284 or self.operand2.type.is_string
4285 or NumBinopNode.is_py_operation(self))
4287 def generate_evaluation_code(self, code):
4288 if not self.type.is_pyobject:
4289 if self.cdivision is None:
4290 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4291 if not self.cdivision:
4292 if self.type.is_int:
4293 code.globalstate.use_utility_code(mod_int_helper_macro)
4294 math_h_modifier = '__Pyx_INT'
4295 else:
4296 math_h_modifier = self.type.math_h_modifier
4297 code.globalstate.use_utility_code(mod_utility_code.specialize(self.type, math_h_modifier=math_h_modifier))
4298 NumBinopNode.generate_evaluation_code(self, code)
4299 if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
4300 self.generate_div_warning_code(code)
4302 def calculate_result_code(self):
4303 if self.cdivision:
4304 if self.type.is_float:
4305 return "fmod%s(%s, %s)" % (
4306 self.type.math_h_modifier,
4307 self.operand1.result(),
4308 self.operand2.result())
4309 else:
4310 return "(%s %% %s)" % (
4311 self.operand1.result(),
4312 self.operand2.result())
4313 else:
4314 return "__Pyx_mod_%s(%s, %s)" % (
4315 self.type.specalization_name(),
4316 self.operand1.result(),
4317 self.operand2.result())
4319 class PowNode(NumBinopNode):
4320 # '**' operator.
4322 def analyse_c_operation(self, env):
4323 NumBinopNode.analyse_c_operation(self, env)
4324 if self.operand1.type.is_float or self.operand2.type.is_float:
4325 self.pow_func = "pow"
4326 else:
4327 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4328 env.use_utility_code(
4329 int_pow_utility_code.specialize(func_name=self.pow_func,
4330 type=self.type.declaration_code('')))
4332 def calculate_result_code(self):
4333 return "%s(%s, %s)" % (
4334 self.pow_func,
4335 self.operand1.result(),
4336 self.operand2.result())
4339 # Note: This class is temporary "shut down" into an ineffective mode temp
4340 # allocation mode.
4341 #
4342 # More sophisticated temp reuse was going on before,
4343 # one could have a look at adding this again after /all/ classes
4344 # are converted to the new temp scheme. (The temp juggling cannot work
4345 # otherwise).
4346 class BoolBinopNode(NewTempExprNode):
4347 # Short-circuiting boolean operation.
4348 #
4349 # operator string
4350 # operand1 ExprNode
4351 # operand2 ExprNode
4353 subexprs = ['operand1', 'operand2']
4355 def calculate_constant_result(self):
4356 if self.operator == 'and':
4357 self.constant_result = \
4358 self.operand1.constant_result and \
4359 self.operand2.constant_result
4360 else:
4361 self.constant_result = \
4362 self.operand1.constant_result or \
4363 self.operand2.constant_result
4365 def compile_time_value(self, denv):
4366 if self.operator == 'and':
4367 return self.operand1.compile_time_value(denv) \
4368 and self.operand2.compile_time_value(denv)
4369 else:
4370 return self.operand1.compile_time_value(denv) \
4371 or self.operand2.compile_time_value(denv)
4373 def coerce_to_boolean(self, env):
4374 self.operand1 = self.operand1.coerce_to_boolean(env)
4375 self.operand2 = self.operand2.coerce_to_boolean(env)
4376 self.type = PyrexTypes.c_bint_type
4377 return self
4379 def analyse_types(self, env):
4380 self.operand1.analyse_types(env)
4381 self.operand2.analyse_types(env)
4382 if self.operand1.type.is_pyobject or \
4383 self.operand2.type.is_pyobject:
4384 self.operand1 = self.operand1.coerce_to_pyobject(env)
4385 self.operand2 = self.operand2.coerce_to_pyobject(env)
4386 self.type = py_object_type
4387 self.gil_check(env)
4388 else:
4389 self.operand1 = self.operand1.coerce_to_boolean(env)
4390 self.operand2 = self.operand2.coerce_to_boolean(env)
4391 self.type = PyrexTypes.c_bint_type
4393 # Below disabled for
4395 # For what we're about to do, it's vital that
4396 # both operands be temp nodes.
4397 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4398 # self.operand2 = self.operand2.coerce_to_temp(env)
4399 self.is_temp = 1
4401 gil_message = "Truth-testing Python object"
4403 ## def allocate_temps(self, env, result_code = None):
4404 ## # We don't need both operands at the same time, and
4405 ## # one of the operands will also be our result. So we
4406 ## # use an allocation strategy here which results in
4407 ## # this node and both its operands sharing the same
4408 ## # result variable. This allows us to avoid some
4409 ## # assignments and increfs/decrefs that would otherwise
4410 ## # be necessary.
4411 ## self.allocate_temp(env, result_code)
4412 ## self.operand1.allocate_temps(env, self.result())
4413 ## self.operand2.allocate_temps(env, self.result())
4414 ## # We haven't called release_temp on either operand,
4415 ## # because although they are temp nodes, they don't own
4416 ## # their result variable. And because they are temp
4417 ## # nodes, any temps in their subnodes will have been
4418 ## # released before their allocate_temps returned.
4419 ## # Therefore, they contain no temp vars that need to
4420 ## # be released.
4422 def check_const(self):
4423 self.operand1.check_const()
4424 self.operand2.check_const()
4426 def calculate_result_code(self):
4427 return "(%s %s %s)" % (
4428 self.operand1.result(),
4429 self.py_to_c_op[self.operator],
4430 self.operand2.result())
4432 py_to_c_op = {'and': "&&", 'or': "||"}
4434 def generate_evaluation_code(self, code):
4435 code.mark_pos(self.pos)
4436 self.operand1.generate_evaluation_code(code)
4437 test_result, uses_temp = self.generate_operand1_test(code)
4438 if self.operator == 'and':
4439 sense = ""
4440 else:
4441 sense = "!"
4442 code.putln(
4443 "if (%s%s) {" % (
4444 sense,
4445 test_result))
4446 if uses_temp:
4447 code.funcstate.release_temp(test_result)
4448 self.operand1.generate_disposal_code(code)
4449 self.operand2.generate_evaluation_code(code)
4450 self.allocate_temp_result(code)
4451 self.operand2.make_owned_reference(code)
4452 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4453 self.operand2.generate_post_assignment_code(code)
4454 self.operand2.free_temps(code)
4455 code.putln("} else {")
4456 self.operand1.make_owned_reference(code)
4457 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4458 self.operand1.generate_post_assignment_code(code)
4459 self.operand1.free_temps(code)
4460 code.putln("}")
4462 def generate_operand1_test(self, code):
4463 # Generate code to test the truth of the first operand.
4464 if self.type.is_pyobject:
4465 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4466 manage_ref=False)
4467 code.putln(
4468 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4469 test_result,
4470 self.operand1.py_result(),
4471 code.error_goto_if_neg(test_result, self.pos)))
4472 else:
4473 test_result = self.operand1.result()
4474 return (test_result, self.type.is_pyobject)
4477 class CondExprNode(ExprNode):
4478 # Short-circuiting conditional expression.
4479 #
4480 # test ExprNode
4481 # true_val ExprNode
4482 # false_val ExprNode
4484 true_val = None
4485 false_val = None
4487 subexprs = ['test', 'true_val', 'false_val']
4489 def calculate_constant_result(self):
4490 if self.test.constant_result:
4491 self.constant_result = self.true_val.constant_result
4492 else:
4493 self.constant_result = self.false_val.constant_result
4495 def analyse_types(self, env):
4496 self.test.analyse_types(env)
4497 self.test = self.test.coerce_to_boolean(env)
4498 self.true_val.analyse_types(env)
4499 self.false_val.analyse_types(env)
4500 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4501 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4502 self.true_val = self.true_val.coerce_to(self.type, env)
4503 self.false_val = self.false_val.coerce_to(self.type, env)
4504 self.is_temp = 1
4505 if self.type == PyrexTypes.error_type:
4506 self.type_error()
4508 def compute_result_type(self, type1, type2):
4509 if type1 == type2:
4510 return type1
4511 elif type1.is_numeric and type2.is_numeric:
4512 return PyrexTypes.widest_numeric_type(type1, type2)
4513 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4514 return type2
4515 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4516 return type1
4517 elif type1.is_pyobject or type2.is_pyobject:
4518 return py_object_type
4519 elif type1.assignable_from(type2):
4520 return type1
4521 elif type2.assignable_from(type1):
4522 return type2
4523 else:
4524 return PyrexTypes.error_type
4526 def type_error(self):
4527 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4528 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4529 (self.true_val.type, self.false_val.type))
4530 self.type = PyrexTypes.error_type
4532 def check_const(self):
4533 self.test.check_const()
4534 self.true_val.check_const()
4535 self.false_val.check_const()
4537 def generate_evaluation_code(self, code):
4538 # Because subexprs may not be evaluated we can use a more optimal
4539 # subexpr allocation strategy than the default, so override evaluation_code.
4541 code.mark_pos(self.pos)
4542 #self.allocate_temp_result(code) # uncomment this when we switch to new temps
4543 self.test.generate_evaluation_code(code)
4544 code.putln("if (%s) {" % self.test.result() )
4545 self.eval_and_get(code, self.true_val)
4546 code.putln("} else {")
4547 self.eval_and_get(code, self.false_val)
4548 code.putln("}")
4549 self.test.generate_disposal_code(code)
4550 self.test.free_temps(code)
4552 def eval_and_get(self, code, expr):
4553 expr.generate_evaluation_code(code)
4554 expr.make_owned_reference(code)
4555 code.putln("%s = %s;" % (self.result(), expr.result()))
4556 expr.generate_post_assignment_code(code)
4557 expr.free_temps(code)
4559 richcmp_constants = {
4560 "<" : "Py_LT",
4561 "<=": "Py_LE",
4562 "==": "Py_EQ",
4563 "!=": "Py_NE",
4564 "<>": "Py_NE",
4565 ">" : "Py_GT",
4566 ">=": "Py_GE",
4567 }
4569 class CmpNode(object):
4570 # Mixin class containing code common to PrimaryCmpNodes
4571 # and CascadedCmpNodes.
4573 def calculate_cascaded_constant_result(self, operand1_result):
4574 func = compile_time_binary_operators[self.operator]
4575 operand2_result = self.operand2.constant_result
4576 result = func(operand1_result, operand2_result)
4577 if result and self.cascade:
4578 result = result and \
4579 self.cascade.cascaded_compile_time_value(operand2_result)
4580 self.constant_result = result
4582 def cascaded_compile_time_value(self, operand1, denv):
4583 func = get_compile_time_binop(self)
4584 operand2 = self.operand2.compile_time_value(denv)
4585 try:
4586 result = func(operand1, operand2)
4587 except Exception, e:
4588 self.compile_time_value_error(e)
4589 result = None
4590 if result:
4591 cascade = self.cascade
4592 if cascade:
4593 # FIXME: I bet this must call cascaded_compile_time_value()
4594 result = result and cascade.compile_time_value(operand2, denv)
4595 return result
4597 def is_python_comparison(self):
4598 return (self.has_python_operands()
4599 or (self.cascade and self.cascade.is_python_comparison())
4600 or self.operator in ('in', 'not_in'))
4602 def is_python_result(self):
4603 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4604 or (self.cascade and self.cascade.is_python_result()))
4606 def check_types(self, env, operand1, op, operand2):
4607 if not self.types_okay(operand1, op, operand2):
4608 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4609 (self.operator, operand1.type, operand2.type))
4611 def types_okay(self, operand1, op, operand2):
4612 type1 = operand1.type
4613 type2 = operand2.type
4614 if type1.is_error or type2.is_error:
4615 return 1
4616 if type1.is_pyobject: # type2 will be, too
4617 return 1
4618 elif type1.is_ptr or type1.is_array:
4619 return type1.is_null_ptr or type2.is_null_ptr \
4620 or ((type2.is_ptr or type2.is_array)
4621 and type1.base_type.same_as(type2.base_type))
4622 elif ((type1.is_numeric and type2.is_numeric
4623 or type1.is_enum and (type1 is type2 or type2.is_int)
4624 or type1.is_int and type2.is_enum)
4625 and op not in ('is', 'is_not')):
4626 return 1
4627 else:
4628 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4630 def generate_operation_code(self, code, result_code,
4631 operand1, op , operand2):
4632 if self.type is PyrexTypes.py_object_type:
4633 coerce_result = "__Pyx_PyBool_FromLong"
4634 else:
4635 coerce_result = ""
4636 if 'not' in op: negation = "!"
4637 else: negation = ""
4638 if op == 'in' or op == 'not_in':
4639 code.putln(
4640 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4641 result_code,
4642 coerce_result,
4643 negation,
4644 operand2.py_result(),
4645 operand1.py_result(),
4646 code.error_goto_if_neg(result_code, self.pos)))
4647 elif (operand1.type.is_pyobject
4648 and op not in ('is', 'is_not')):
4649 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4650 result_code,
4651 operand1.py_result(),
4652 operand2.py_result(),
4653 richcmp_constants[op],
4654 code.error_goto_if_null(result_code, self.pos)))
4655 code.put_gotref(result_code)
4656 else:
4657 type1 = operand1.type
4658 type2 = operand2.type
4659 if (type1.is_extension_type or type2.is_extension_type) \
4660 and not type1.same_as(type2):
4661 common_type = py_object_type
4662 elif type1.is_numeric:
4663 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4664 else:
4665 common_type = type1
4666 code1 = operand1.result_as(common_type)
4667 code2 = operand2.result_as(common_type)
4668 code.putln("%s = %s(%s %s %s);" % (
4669 result_code,
4670 coerce_result,
4671 code1,
4672 self.c_operator(op),
4673 code2))
4675 def c_operator(self, op):
4676 if op == 'is':
4677 return "=="
4678 elif op == 'is_not':
4679 return "!="
4680 else:
4681 return op
4684 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4685 # Non-cascaded comparison or first comparison of
4686 # a cascaded sequence.
4687 #
4688 # operator string
4689 # operand1 ExprNode
4690 # operand2 ExprNode
4691 # cascade CascadedCmpNode
4693 # We don't use the subexprs mechanism, because
4694 # things here are too complicated for it to handle.
4695 # Instead, we override all the framework methods
4696 # which use it.
4698 child_attrs = ['operand1', 'operand2', 'cascade']
4700 cascade = None
4702 def calculate_constant_result(self):
4703 self.constant_result = self.calculate_cascaded_constant_result(
4704 self.operand1.constant_result)
4706 def compile_time_value(self, denv):
4707 operand1 = self.operand1.compile_time_value(denv)
4708 return self.cascaded_compile_time_value(operand1, denv)
4710 def analyse_types(self, env):
4711 self.operand1.analyse_types(env)
4712 self.operand2.analyse_types(env)
4713 if self.cascade:
4714 self.cascade.analyse_types(env, self.operand2)
4715 self.is_pycmp = self.is_python_comparison()
4716 if self.is_pycmp:
4717 self.coerce_operands_to_pyobjects(env)
4718 if self.has_int_operands():
4719 self.coerce_chars_to_ints(env)
4720 if self.cascade:
4721 self.operand2 = self.operand2.coerce_to_simple(env)
4722 self.cascade.coerce_cascaded_operands_to_temp(env)
4723 self.check_operand_types(env)
4724 if self.is_python_result():
4725 self.type = PyrexTypes.py_object_type
4726 else:
4727 self.type = PyrexTypes.c_bint_type
4728 cdr = self.cascade
4729 while cdr:
4730 cdr.type = self.type
4731 cdr = cdr.cascade
4732 if self.is_pycmp or self.cascade:
4733 self.is_temp = 1
4735 def check_operand_types(self, env):
4736 self.check_types(env,
4737 self.operand1, self.operator, self.operand2)
4738 if self.cascade:
4739 self.cascade.check_operand_types(env, self.operand2)
4741 def has_python_operands(self):
4742 return (self.operand1.type.is_pyobject
4743 or self.operand2.type.is_pyobject)
4745 def coerce_operands_to_pyobjects(self, env):
4746 self.operand1 = self.operand1.coerce_to_pyobject(env)
4747 self.operand2 = self.operand2.coerce_to_pyobject(env)
4748 if self.cascade:
4749 self.cascade.coerce_operands_to_pyobjects(env)
4751 def has_int_operands(self):
4752 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4753 or (self.cascade and self.cascade.has_int_operands())
4755 def coerce_chars_to_ints(self, env):
4756 # coerce literal single-char strings to c chars
4757 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4758 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4759 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4760 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4761 if self.cascade:
4762 self.cascade.coerce_chars_to_ints(env)
4764 def allocate_subexpr_temps(self, env):
4765 self.operand1.allocate_temps(env)
4766 self.operand2.allocate_temps(env)
4767 if self.cascade:
4768 self.cascade.allocate_subexpr_temps(env)
4770 def release_subexpr_temps(self, env):
4771 self.operand1.release_temp(env)
4772 self.operand2.release_temp(env)
4773 if self.cascade:
4774 self.cascade.release_subexpr_temps(env)
4776 def check_const(self):
4777 self.operand1.check_const()
4778 self.operand2.check_const()
4779 if self.cascade:
4780 self.not_const()
4782 def calculate_result_code(self):
4783 return "(%s %s %s)" % (
4784 self.operand1.result(),
4785 self.c_operator(self.operator),
4786 self.operand2.result())
4788 def generate_evaluation_code(self, code):
4789 self.operand1.generate_evaluation_code(code)
4790 self.operand2.generate_evaluation_code(code)
4791 if self.is_temp:
4792 self.allocate_temp_result(code)
4793 self.generate_operation_code(code, self.result(),
4794 self.operand1, self.operator, self.operand2)
4795 if self.cascade:
4796 self.cascade.generate_evaluation_code(code,
4797 self.result(), self.operand2)
4798 self.operand1.generate_disposal_code(code)
4799 self.operand1.free_temps(code)
4800 self.operand2.generate_disposal_code(code)
4801 self.operand2.free_temps(code)
4803 def generate_subexpr_disposal_code(self, code):
4804 # If this is called, it is a non-cascaded cmp,
4805 # so only need to dispose of the two main operands.
4806 self.operand1.generate_disposal_code(code)
4807 self.operand2.generate_disposal_code(code)
4809 def free_subexpr_temps(self, code):
4810 # If this is called, it is a non-cascaded cmp,
4811 # so only need to dispose of the two main operands.
4812 self.operand1.free_temps(code)
4813 self.operand2.free_temps(code)
4815 def annotate(self, code):
4816 self.operand1.annotate(code)
4817 self.operand2.annotate(code)
4818 if self.cascade:
4819 self.cascade.annotate(code)
4822 class CascadedCmpNode(Node, CmpNode):
4823 # A CascadedCmpNode is not a complete expression node. It
4824 # hangs off the side of another comparison node, shares
4825 # its left operand with that node, and shares its result
4826 # with the PrimaryCmpNode at the head of the chain.
4827 #
4828 # operator string
4829 # operand2 ExprNode
4830 # cascade CascadedCmpNode
4832 child_attrs = ['operand2', 'cascade']
4834 cascade = None
4835 constant_result = constant_value_not_set # FIXME: where to calculate this?
4837 def analyse_types(self, env, operand1):
4838 self.operand2.analyse_types(env)
4839 if self.cascade:
4840 self.cascade.analyse_types(env, self.operand2)
4842 def check_operand_types(self, env, operand1):
4843 self.check_types(env,
4844 operand1, self.operator, self.operand2)
4845 if self.cascade:
4846 self.cascade.check_operand_types(env, self.operand2)
4848 def has_python_operands(self):
4849 return self.operand2.type.is_pyobject
4851 def coerce_operands_to_pyobjects(self, env):
4852 self.operand2 = self.operand2.coerce_to_pyobject(env)
4853 if self.cascade:
4854 self.cascade.coerce_operands_to_pyobjects(env)
4856 def has_int_operands(self):
4857 return self.operand2.type.is_int
4859 def coerce_chars_to_ints(self, env):
4860 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4861 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4863 def coerce_cascaded_operands_to_temp(self, env):
4864 if self.cascade:
4865 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4866 self.operand2 = self.operand2.coerce_to_simple(env)
4867 self.cascade.coerce_cascaded_operands_to_temp(env)
4869 def allocate_subexpr_temps(self, env):
4870 self.operand2.allocate_temps(env)
4871 if self.cascade:
4872 self.cascade.allocate_subexpr_temps(env)
4874 def release_subexpr_temps(self, env):
4875 self.operand2.release_temp(env)
4876 if self.cascade:
4877 self.cascade.release_subexpr_temps(env)
4879 def generate_evaluation_code(self, code, result, operand1):
4880 if self.type.is_pyobject:
4881 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4882 code.put_decref(result, self.type)
4883 else:
4884 code.putln("if (%s) {" % result)
4885 self.operand2.generate_evaluation_code(code)
4886 self.generate_operation_code(code, result,
4887 operand1, self.operator, self.operand2)
4888 if self.cascade:
4889 self.cascade.generate_evaluation_code(
4890 code, result, self.operand2)
4891 # Cascaded cmp result is always temp
4892 self.operand2.generate_disposal_code(code)
4893 self.operand2.free_temps(code)
4894 code.putln("}")
4896 def annotate(self, code):
4897 self.operand2.annotate(code)
4898 if self.cascade:
4899 self.cascade.annotate(code)
4902 binop_node_classes = {
4903 "or": BoolBinopNode,
4904 "and": BoolBinopNode,
4905 "|": IntBinopNode,
4906 "^": IntBinopNode,
4907 "&": IntBinopNode,
4908 "<<": IntBinopNode,
4909 ">>": IntBinopNode,
4910 "+": AddNode,
4911 "-": SubNode,
4912 "*": MulNode,
4913 "/": DivNode,
4914 "//": DivNode,
4915 "%": ModNode,
4916 "**": PowNode
4917 }
4919 def binop_node(pos, operator, operand1, operand2):
4920 # Construct binop node of appropriate class for
4921 # given operator.
4922 return binop_node_classes[operator](pos,
4923 operator = operator,
4924 operand1 = operand1,
4925 operand2 = operand2)
4927 #-------------------------------------------------------------------
4928 #
4929 # Coercion nodes
4930 #
4931 # Coercion nodes are special in that they are created during
4932 # the analyse_types phase of parse tree processing.
4933 # Their __init__ methods consequently incorporate some aspects
4934 # of that phase.
4935 #
4936 #-------------------------------------------------------------------
4938 class CoercionNode(NewTempExprNode):
4939 # Abstract base class for coercion nodes.
4940 #
4941 # arg ExprNode node being coerced
4943 subexprs = ['arg']
4945 def __init__(self, arg):
4946 self.pos = arg.pos
4947 self.arg = arg
4948 if debug_coercion:
4949 print("%s Coercing %s" % (self, self.arg))
4951 def calculate_constant_result(self):
4952 self.constant_result = self.arg.constant_result
4954 def annotate(self, code):
4955 self.arg.annotate(code)
4956 if self.arg.type != self.type:
4957 file, line, col = self.pos
4958 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4961 class CastNode(CoercionNode):
4962 # Wrap a node in a C type cast.
4964 def __init__(self, arg, new_type):
4965 CoercionNode.__init__(self, arg)
4966 self.type = new_type
4968 def calculate_result_code(self):
4969 return self.arg.result_as(self.type)
4971 def generate_result_code(self, code):
4972 self.arg.generate_result_code(code)
4975 class PyTypeTestNode(CoercionNode):
4976 # This node is used to check that a generic Python
4977 # object is an instance of a particular extension type.
4978 # This node borrows the result of its argument node.
4980 def __init__(self, arg, dst_type, env):
4981 # The arg is know to be a Python object, and
4982 # the dst_type is known to be an extension type.
4983 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4984 CoercionNode.__init__(self, arg)
4985 self.type = dst_type
4986 self.gil_check(env)
4987 self.result_ctype = arg.ctype()
4989 gil_message = "Python type test"
4991 def analyse_types(self, env):
4992 pass
4994 def result_in_temp(self):
4995 return self.arg.result_in_temp()
4997 def is_ephemeral(self):
4998 return self.arg.is_ephemeral()
5000 def calculate_result_code(self):
5001 return self.arg.result()
5003 def generate_result_code(self, code):
5004 if self.type.typeobj_is_available():
5005 if not self.type.is_builtin_type:
5006 code.globalstate.use_utility_code(type_test_utility_code)
5007 code.putln(
5008 "if (!(%s)) %s" % (
5009 self.type.type_test_code(self.arg.py_result()),
5010 code.error_goto(self.pos)))
5011 else:
5012 error(self.pos, "Cannot test type of extern C class "
5013 "without type object name specification")
5015 def generate_post_assignment_code(self, code):
5016 self.arg.generate_post_assignment_code(code)
5018 def free_temps(self, code):
5019 self.arg.free_temps(code)
5022 class CoerceToPyTypeNode(CoercionNode):
5023 # This node is used to convert a C data type
5024 # to a Python object.
5026 def __init__(self, arg, env):
5027 CoercionNode.__init__(self, arg)
5028 self.type = py_object_type
5029 self.gil_check(env)
5030 self.is_temp = 1
5031 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
5032 error(arg.pos,
5033 "Cannot convert '%s' to Python object" % arg.type)
5035 gil_message = "Converting to Python object"
5037 def coerce_to_boolean(self, env):
5038 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5040 def coerce_to_integer(self, env):
5041 # If not already some C integer type, coerce to longint.
5042 if self.arg.type.is_int:
5043 return self.arg
5044 else:
5045 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5047 def analyse_types(self, env):
5048 # The arg is always already analysed
5049 pass
5051 def generate_result_code(self, code):
5052 function = self.arg.type.to_py_function
5053 code.putln('%s = %s(%s); %s' % (
5054 self.result(),
5055 function,
5056 self.arg.result(),
5057 code.error_goto_if_null(self.result(), self.pos)))
5058 code.put_gotref(self.py_result())
5061 class CoerceFromPyTypeNode(CoercionNode):
5062 # This node is used to convert a Python object
5063 # to a C data type.
5065 def __init__(self, result_type, arg, env):
5066 CoercionNode.__init__(self, arg)
5067 self.type = result_type
5068 self.is_temp = 1
5069 if not result_type.from_py_function:
5070 error(arg.pos,
5071 "Cannot convert Python object to '%s'" % result_type)
5072 if self.type.is_string and self.arg.is_ephemeral():
5073 error(arg.pos,
5074 "Obtaining char * from temporary Python value")
5076 def analyse_types(self, env):
5077 # The arg is always already analysed
5078 pass
5080 def generate_result_code(self, code):
5081 function = self.type.from_py_function
5082 operand = self.arg.py_result()
5083 rhs = "%s(%s)" % (function, operand)
5084 if self.type.is_enum:
5085 rhs = typecast(self.type, c_long_type, rhs)
5086 code.putln('%s = %s; %s' % (
5087 self.result(),
5088 rhs,
5089 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5090 if self.type.is_pyobject:
5091 code.put_gotref(self.py_result())
5094 class CoerceToBooleanNode(CoercionNode):
5095 # This node is used when a result needs to be used
5096 # in a boolean context.
5098 def __init__(self, arg, env):
5099 CoercionNode.__init__(self, arg)
5100 self.type = PyrexTypes.c_bint_type
5101 if arg.type.is_pyobject:
5102 if env.nogil:
5103 self.gil_error()
5104 self.is_temp = 1
5106 gil_message = "Truth-testing Python object"
5108 def check_const(self):
5109 if self.is_temp:
5110 self.not_const()
5111 self.arg.check_const()
5113 def calculate_result_code(self):
5114 return "(%s != 0)" % self.arg.result()
5116 def generate_result_code(self, code):
5117 if self.arg.type.is_pyobject:
5118 code.putln(
5119 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5120 self.result(),
5121 self.arg.py_result(),
5122 code.error_goto_if_neg(self.result(), self.pos)))
5125 class CoerceToTempNode(CoercionNode):
5126 # This node is used to force the result of another node
5127 # to be stored in a temporary. It is only used if the
5128 # argument node's result is not already in a temporary.
5130 def __init__(self, arg, env):
5131 CoercionNode.__init__(self, arg)
5132 self.type = self.arg.type
5133 self.is_temp = 1
5134 if self.type.is_pyobject:
5135 self.gil_check(env)
5136 self.result_ctype = py_object_type
5138 gil_message = "Creating temporary Python reference"
5140 def analyse_types(self, env):
5141 # The arg is always already analysed
5142 pass
5144 def coerce_to_boolean(self, env):
5145 self.arg = self.arg.coerce_to_boolean(env)
5146 self.type = self.arg.type
5147 self.result_ctype = self.type
5148 return self
5150 def generate_result_code(self, code):
5151 #self.arg.generate_evaluation_code(code) # Already done
5152 # by generic generate_subexpr_evaluation_code!
5153 code.putln("%s = %s;" % (
5154 self.result(), self.arg.result_as(self.ctype())))
5155 if self.type.is_pyobject:
5156 code.put_incref(self.result(), self.ctype())
5159 class CloneNode(CoercionNode):
5160 # This node is employed when the result of another node needs
5161 # to be used multiple times. The argument node's result must
5162 # be in a temporary. This node "borrows" the result from the
5163 # argument node, and does not generate any evaluation or
5164 # disposal code for it. The original owner of the argument
5165 # node is responsible for doing those things.
5167 subexprs = [] # Arg is not considered a subexpr
5169 def __init__(self, arg):
5170 CoercionNode.__init__(self, arg)
5171 if hasattr(arg, 'type'):
5172 self.type = arg.type
5173 self.result_ctype = arg.result_ctype
5174 if hasattr(arg, 'entry'):
5175 self.entry = arg.entry
5177 def result(self):
5178 return self.arg.result()
5180 def analyse_types(self, env):
5181 self.type = self.arg.type
5182 self.result_ctype = self.arg.result_ctype
5183 self.is_temp = 1
5184 if hasattr(self.arg, 'entry'):
5185 self.entry = self.arg.entry
5187 def generate_evaluation_code(self, code):
5188 pass
5190 def generate_result_code(self, code):
5191 pass
5193 def generate_disposal_code(self, code):
5194 pass
5196 def allocate_temps(self, env):
5197 pass
5199 def release_temp(self, env):
5200 pass
5202 def free_temps(self, code):
5203 pass
5206 #------------------------------------------------------------------------------------
5207 #
5208 # Runtime support code
5209 #
5210 #------------------------------------------------------------------------------------
5212 get_name_interned_utility_code = UtilityCode(
5213 proto = """
5214 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5215 """,
5216 impl = """
5217 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5218 PyObject *result;
5219 result = PyObject_GetAttr(dict, name);
5220 if (!result)
5221 PyErr_SetObject(PyExc_NameError, name);
5222 return result;
5223 }
5224 """)
5226 #------------------------------------------------------------------------------------
5228 import_utility_code = UtilityCode(
5229 proto = """
5230 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5231 """,
5232 impl = """
5233 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5234 PyObject *__import__ = 0;
5235 PyObject *empty_list = 0;
5236 PyObject *module = 0;
5237 PyObject *global_dict = 0;
5238 PyObject *empty_dict = 0;
5239 PyObject *list;
5240 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5241 if (!__import__)
5242 goto bad;
5243 if (from_list)
5244 list = from_list;
5245 else {
5246 empty_list = PyList_New(0);
5247 if (!empty_list)
5248 goto bad;
5249 list = empty_list;
5250 }
5251 global_dict = PyModule_GetDict(%(GLOBALS)s);
5252 if (!global_dict)
5253 goto bad;
5254 empty_dict = PyDict_New();
5255 if (!empty_dict)
5256 goto bad;
5257 module = PyObject_CallFunctionObjArgs(__import__,
5258 name, global_dict, empty_dict, list, NULL);
5259 bad:
5260 Py_XDECREF(empty_list);
5261 Py_XDECREF(__import__);
5262 Py_XDECREF(empty_dict);
5263 return module;
5264 }
5265 """ % {
5266 "BUILTINS": Naming.builtins_cname,
5267 "GLOBALS": Naming.module_cname,
5268 })
5270 #------------------------------------------------------------------------------------
5272 get_exception_utility_code = UtilityCode(
5273 proto = """
5274 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5275 """,
5276 impl = """
5277 static PyObject *__Pyx_GetExcValue(void) {
5278 PyObject *type = 0, *value = 0, *tb = 0;
5279 PyObject *tmp_type, *tmp_value, *tmp_tb;
5280 PyObject *result = 0;
5281 PyThreadState *tstate = PyThreadState_Get();
5282 PyErr_Fetch(&type, &value, &tb);
5283 PyErr_NormalizeException(&type, &value, &tb);
5284 if (PyErr_Occurred())
5285 goto bad;
5286 if (!value) {
5287 value = Py_None;
5288 Py_INCREF(value);
5289 }
5290 tmp_type = tstate->exc_type;
5291 tmp_value = tstate->exc_value;
5292 tmp_tb = tstate->exc_traceback;
5293 tstate->exc_type = type;
5294 tstate->exc_value = value;
5295 tstate->exc_traceback = tb;
5296 /* Make sure tstate is in a consistent state when we XDECREF
5297 these objects (XDECREF may run arbitrary code). */
5298 Py_XDECREF(tmp_type);
5299 Py_XDECREF(tmp_value);
5300 Py_XDECREF(tmp_tb);
5301 result = value;
5302 Py_XINCREF(result);
5303 type = 0;
5304 value = 0;
5305 tb = 0;
5306 bad:
5307 Py_XDECREF(type);
5308 Py_XDECREF(value);
5309 Py_XDECREF(tb);
5310 return result;
5311 }
5312 """)
5314 #------------------------------------------------------------------------------------
5316 type_test_utility_code = UtilityCode(
5317 proto = """
5318 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5319 """,
5320 impl = """
5321 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5322 if (!type) {
5323 PyErr_Format(PyExc_SystemError, "Missing type object");
5324 return 0;
5325 }
5326 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5327 return 1;
5328 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5329 Py_TYPE(obj)->tp_name, type->tp_name);
5330 return 0;
5331 }
5332 """)
5334 #------------------------------------------------------------------------------------
5336 create_class_utility_code = UtilityCode(
5337 proto = """
5338 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5339 """,
5340 impl = """
5341 static PyObject *__Pyx_CreateClass(
5342 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5343 {
5344 PyObject *py_modname;
5345 PyObject *result = 0;
5347 #if PY_MAJOR_VERSION < 3
5348 py_modname = PyString_FromString(modname);
5349 #else
5350 py_modname = PyUnicode_FromString(modname);
5351 #endif
5352 if (!py_modname)
5353 goto bad;
5354 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5355 goto bad;
5356 #if PY_MAJOR_VERSION < 3
5357 result = PyClass_New(bases, dict, name);
5358 #else
5359 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5360 #endif
5361 bad:
5362 Py_XDECREF(py_modname);
5363 return result;
5364 }
5365 """)
5367 #------------------------------------------------------------------------------------
5369 cpp_exception_utility_code = UtilityCode(
5370 proto = """
5371 #ifndef __Pyx_CppExn2PyErr
5372 static void __Pyx_CppExn2PyErr() {
5373 try {
5374 if (PyErr_Occurred())
5375 ; // let the latest Python exn pass through and ignore the current one
5376 else
5377 throw;
5378 } catch (const std::out_of_range& exn) {
5379 // catch out_of_range explicitly so the proper Python exn may be raised
5380 PyErr_SetString(PyExc_IndexError, exn.what());
5381 } catch (const std::exception& exn) {
5382 PyErr_SetString(PyExc_RuntimeError, exn.what());
5383 }
5384 catch (...)
5385 {
5386 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5387 }
5388 }
5389 #endif
5390 """,
5391 impl = ""
5392 )
5394 #------------------------------------------------------------------------------------
5396 append_utility_code = UtilityCode(
5397 proto = """
5398 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5399 if (likely(PyList_CheckExact(L))) {
5400 if (PyList_Append(L, x) < 0) return NULL;
5401 Py_INCREF(Py_None);
5402 return Py_None; /* this is just to have an accurate signature */
5403 }
5404 else {
5405 PyObject *r, *m;
5406 m = __Pyx_GetAttrString(L, "append");
5407 if (!m) return NULL;
5408 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5409 Py_DECREF(m);
5410 return r;
5411 }
5412 }
5413 """,
5414 impl = ""
5415 )
5417 #------------------------------------------------------------------------------------
5419 # If the is_unsigned flag is set, we need to do some extra work to make
5420 # sure the index doesn't become negative.
5422 getitem_int_utility_code = UtilityCode(
5423 proto = """
5425 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5426 PyObject *r;
5427 if (!j) return NULL;
5428 r = PyObject_GetItem(o, j);
5429 Py_DECREF(j);
5430 return r;
5431 }
5433 """ + ''.join([
5434 """
5435 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5436 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5437 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5439 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5440 if (likely(o != Py_None)) {
5441 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5442 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5443 Py_INCREF(r);
5444 return r;
5445 }
5446 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5447 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5448 Py_INCREF(r);
5449 return r;
5450 }
5451 }
5452 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5453 }
5454 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5455 ]) + """
5457 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5458 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5459 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5461 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5462 PyObject *r;
5463 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5464 r = PyList_GET_ITEM(o, i);
5465 Py_INCREF(r);
5466 }
5467 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5468 r = PyTuple_GET_ITEM(o, i);
5469 Py_INCREF(r);
5470 }
5471 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5472 r = PySequence_GetItem(o, i);
5473 }
5474 else {
5475 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5476 }
5477 return r;
5478 }
5479 """,
5480 impl = """
5481 """)
5485 #------------------------------------------------------------------------------------
5487 setitem_int_utility_code = UtilityCode(
5488 proto = """
5489 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5490 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5491 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5493 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5494 int r;
5495 if (!j) return -1;
5496 r = PyObject_SetItem(o, j, v);
5497 Py_DECREF(j);
5498 return r;
5499 }
5501 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5502 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5503 Py_DECREF(PyList_GET_ITEM(o, i));
5504 Py_INCREF(v);
5505 PyList_SET_ITEM(o, i, v);
5506 return 1;
5507 }
5508 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5509 return PySequence_SetItem(o, i, v);
5510 else {
5511 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5512 return __Pyx_SetItemInt_Generic(o, j, v);
5513 }
5514 }
5515 """,
5516 impl = """
5517 """)
5519 #------------------------------------------------------------------------------------
5521 delitem_int_utility_code = UtilityCode(
5522 proto = """
5523 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5524 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5525 __Pyx_DelItem_Generic(o, to_py_func(i)))
5527 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5528 int r;
5529 if (!j) return -1;
5530 r = PyObject_DelItem(o, j);
5531 Py_DECREF(j);
5532 return r;
5533 }
5535 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5536 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5537 return PySequence_DelItem(o, i);
5538 else {
5539 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5540 return __Pyx_DelItem_Generic(o, j);
5541 }
5542 }
5543 """,
5544 impl = """
5545 """)
5547 #------------------------------------------------------------------------------------
5549 raise_noneattr_error_utility_code = UtilityCode(
5550 proto = """
5551 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5552 """,
5553 impl = '''
5554 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5555 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5556 }
5557 ''')
5559 raise_noneindex_error_utility_code = UtilityCode(
5560 proto = """
5561 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5562 """,
5563 impl = '''
5564 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5565 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5566 }
5567 ''')
5569 raise_none_iter_error_utility_code = UtilityCode(
5570 proto = """
5571 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5572 """,
5573 impl = '''
5574 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5575 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5576 }
5577 ''')
5579 raise_too_many_values_to_unpack = UtilityCode(
5580 proto = """
5581 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5582 """,
5583 impl = '''
5584 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5585 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5586 }
5587 ''')
5589 raise_need_more_values_to_unpack = UtilityCode(
5590 proto = """
5591 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5592 """,
5593 impl = '''
5594 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5595 PyErr_Format(PyExc_ValueError,
5596 #if PY_VERSION_HEX < 0x02050000
5597 "need more than %d value%s to unpack", (int)index,
5598 #else
5599 "need more than %zd value%s to unpack", index,
5600 #endif
5601 (index == 1) ? "" : "s");
5602 }
5603 ''')
5605 #------------------------------------------------------------------------------------
5607 tuple_unpacking_error_code = UtilityCode(
5608 proto = """
5609 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
5610 """,
5611 impl = """
5612 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
5613 if (t == Py_None) {
5614 __Pyx_RaiseNoneNotIterableError();
5615 } else if (PyTuple_GET_SIZE(t) < index) {
5616 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
5617 } else {
5618 __Pyx_RaiseTooManyValuesError();
5619 }
5620 }
5621 """,
5622 requires = [raise_none_iter_error_utility_code,
5623 raise_need_more_values_to_unpack,
5624 raise_too_many_values_to_unpack]
5625 )
5627 unpacking_utility_code = UtilityCode(
5628 proto = """
5629 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5630 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5631 """,
5632 impl = """
5633 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5634 PyObject *item;
5635 if (!(item = PyIter_Next(iter))) {
5636 if (!PyErr_Occurred()) {
5637 __Pyx_RaiseNeedMoreValuesError(index);
5638 }
5639 }
5640 return item;
5641 }
5643 static int __Pyx_EndUnpack(PyObject *iter) {
5644 PyObject *item;
5645 if ((item = PyIter_Next(iter))) {
5646 Py_DECREF(item);
5647 __Pyx_RaiseTooManyValuesError();
5648 return -1;
5649 }
5650 else if (!PyErr_Occurred())
5651 return 0;
5652 else
5653 return -1;
5654 }
5655 """,
5656 requires = [raise_need_more_values_to_unpack,
5657 raise_too_many_values_to_unpack]
5658 )
5661 #------------------------------------------------------------------------------------
5663 int_pow_utility_code = UtilityCode(
5664 proto="""
5665 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
5666 """,
5667 impl="""
5668 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
5669 %(type)s t = b;
5670 switch (e) {
5671 case 3:
5672 t *= b;
5673 case 2:
5674 t *= b;
5675 case 1:
5676 return t;
5677 case 0:
5678 return 1;
5679 }
5680 if (unlikely(e<0)) return 0;
5681 t = 1;
5682 while (likely(e)) {
5683 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
5684 b *= b;
5685 e >>= 1;
5686 }
5687 return t;
5688 }
5689 """)
5691 # ------------------------------ Division ------------------------------------
5693 # This is so we can treat floating point and integer mod simultaneously.
5694 mod_int_helper_macro = UtilityCode(proto="""
5695 #define fmod__Pyx_INT(a, b) ((a) % (b))
5696 """)
5698 mod_utility_code = UtilityCode(
5699 proto="""
5700 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
5701 """,
5702 impl="""
5703 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
5704 %(type)s res = fmod%(math_h_modifier)s(a, b);
5705 res += ((res < 0) ^ (b < 0)) * b;
5706 return res;
5707 }
5708 """)
5710 div_utility_code = UtilityCode(
5711 proto="""
5712 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
5713 """,
5714 impl="""
5715 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
5716 %(type)s res = a / b;
5717 res -= (res < 0);
5718 return res;
5719 }
5720 """)
5722 cdivision_warning_utility_code = UtilityCode(
5723 proto="""
5724 static int __Pyx_cdivision_warning(void); /* proto */
5725 """,
5726 impl="""
5727 static int __Pyx_cdivision_warning(void) {
5728 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
5729 "division with oppositely signed operands, C and Python semantics differ",
5730 %(FILENAME)s,
5731 %(LINENO)s,
5732 %(MODULENAME)s,
5733 NULL);
5734 }
5735 """ % {
5736 'FILENAME': Naming.filename_cname,
5737 'MODULENAME': Naming.modulename_cname,
5738 'LINENO': Naming.lineno_cname,
5739 })
