Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 1478:b638811d14d0

implement set/dict comprehensions and set literals
author Stefan Behnel <scoder@users.berlios.de>
date Fri Dec 12 09:21:10 2008 +0100 (3 years ago)
parents 67cfcfc0e4c5
children ae2b5e4187b9
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 from Nodes import Node
13 import PyrexTypes
14 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
15 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type
16 import Symtab
17 import Options
18 from Annotate import AnnotationItem
20 from Cython.Debugging import print_call_chain
21 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
22 debug_coercion
25 class ExprNode(Node):
26 # subexprs [string] Class var holding names of subexpr node attrs
27 # type PyrexType Type of the result
28 # result_code string Code fragment
29 # result_ctype string C type of result_code if different from type
30 # is_temp boolean Result is in a temporary variable
31 # is_sequence_constructor
32 # boolean Is a list or tuple constructor expression
33 # saved_subexpr_nodes
34 # [ExprNode or [ExprNode or None] or None]
35 # Cached result of subexpr_nodes()
37 result_ctype = None
38 type = None
40 # The Analyse Expressions phase for expressions is split
41 # into two sub-phases:
42 #
43 # Analyse Types
44 # Determines the result type of the expression based
45 # on the types of its sub-expressions, and inserts
46 # coercion nodes into the expression tree where needed.
47 # Marks nodes which will need to have temporary variables
48 # allocated.
49 #
50 # Allocate Temps
51 # Allocates temporary variables where needed, and fills
52 # in the result_code field of each node.
53 #
54 # ExprNode provides some convenience routines which
55 # perform both of the above phases. These should only
56 # be called from statement nodes, and only when no
57 # coercion nodes need to be added around the expression
58 # being analysed. In that case, the above two phases
59 # should be invoked separately.
60 #
61 # Framework code in ExprNode provides much of the common
62 # processing for the various phases. It makes use of the
63 # 'subexprs' class attribute of ExprNodes, which should
64 # contain a list of the names of attributes which can
65 # hold sub-nodes or sequences of sub-nodes.
66 #
67 # The framework makes use of a number of abstract methods.
68 # Their responsibilities are as follows.
69 #
70 # Declaration Analysis phase
71 #
72 # analyse_target_declaration
73 # Called during the Analyse Declarations phase to analyse
74 # the LHS of an assignment or argument of a del statement.
75 # Nodes which cannot be the LHS of an assignment need not
76 # implement it.
77 #
78 # Expression Analysis phase
79 #
80 # analyse_types
81 # - Call analyse_types on all sub-expressions.
82 # - Check operand types, and wrap coercion nodes around
83 # sub-expressions where needed.
84 # - Set the type of this node.
85 # - If a temporary variable will be required for the
86 # result, set the is_temp flag of this node.
87 #
88 # analyse_target_types
89 # Called during the Analyse Types phase to analyse
90 # the LHS of an assignment or argument of a del
91 # statement. Similar responsibilities to analyse_types.
92 #
93 # allocate_temps
94 # - Call allocate_temps for all sub-nodes.
95 # - Call allocate_temp for this node.
96 # - If a temporary was allocated, call release_temp on
97 # all sub-expressions.
98 #
99 # allocate_target_temps
100 # - Call allocate_temps on sub-nodes and allocate any other
101 # temps used during assignment.
102 # - Fill in result_code with a C lvalue if needed.
103 # - If a rhs node is supplied, call release_temp on it.
104 # - Call release_temp on sub-nodes and release any other
105 # temps used during assignment.
106 #
107 # target_code
108 # Called by the default implementation of allocate_target_temps.
109 # Should return a C lvalue for assigning to the node. The default
110 # implementation calls calculate_result_code.
111 #
112 # check_const
113 # - Check that this node and its subnodes form a
114 # legal constant expression. If so, do nothing,
115 # otherwise call not_const.
116 #
117 # The default implementation of check_const
118 # assumes that the expression is not constant.
119 #
120 # check_const_addr
121 # - Same as check_const, except check that the
122 # expression is a C lvalue whose address is
123 # constant. Otherwise, call addr_not_const.
124 #
125 # The default implementation of calc_const_addr
126 # assumes that the expression is not a constant
127 # lvalue.
128 #
129 # Code Generation phase
130 #
131 # generate_evaluation_code
132 # - Call generate_evaluation_code for sub-expressions.
133 # - Perform the functions of generate_result_code
134 # (see below).
135 # - If result is temporary, call generate_disposal_code
136 # on all sub-expressions.
137 #
138 # A default implementation of generate_evaluation_code
139 # is provided which uses the following abstract methods:
140 #
141 # generate_result_code
142 # - Generate any C statements necessary to calculate
143 # the result of this node from the results of its
144 # sub-expressions.
145 #
146 # calculate_result_code
147 # - Should return a C code fragment evaluating to the
148 # result. This is only called when the result is not
149 # a temporary.
150 #
151 # generate_assignment_code
152 # Called on the LHS of an assignment.
153 # - Call generate_evaluation_code for sub-expressions.
154 # - Generate code to perform the assignment.
155 # - If the assignment absorbed a reference, call
156 # generate_post_assignment_code on the RHS,
157 # otherwise call generate_disposal_code on it.
158 #
159 # generate_deletion_code
160 # Called on an argument of a del statement.
161 # - Call generate_evaluation_code for sub-expressions.
162 # - Generate code to perform the deletion.
163 # - Call generate_disposal_code on all sub-expressions.
164 #
165 #
167 is_sequence_constructor = 0
168 is_attribute = 0
170 saved_subexpr_nodes = None
171 is_temp = 0
172 is_target = 0
174 def get_child_attrs(self):
175 return self.subexprs
176 child_attrs = property(fget=get_child_attrs)
178 def not_implemented(self, method_name):
179 print_call_chain(method_name, "not implemented") ###
180 raise InternalError(
181 "%s.%s not implemented" %
182 (self.__class__.__name__, method_name))
184 def is_lvalue(self):
185 return 0
187 def is_ephemeral(self):
188 # An ephemeral node is one whose result is in
189 # a Python temporary and we suspect there are no
190 # other references to it. Certain operations are
191 # disallowed on such values, since they are
192 # likely to result in a dangling pointer.
193 return self.type.is_pyobject and self.is_temp
195 def subexpr_nodes(self):
196 # Extract a list of subexpression nodes based
197 # on the contents of the subexprs class attribute.
198 nodes = []
199 for name in self.subexprs:
200 item = getattr(self, name)
201 if item:
202 if isinstance(item, ExprNode):
203 nodes.append(item)
204 else:
205 nodes.extend(item)
206 return nodes
208 def result(self):
209 if not self.is_temp or self.is_target:
210 return self.calculate_result_code()
211 else: # i.e. self.is_temp:
212 return self.result_code
214 def result_as(self, type = None):
215 # Return the result code cast to the specified C type.
216 return typecast(type, self.ctype(), self.result())
218 def py_result(self):
219 # Return the result code cast to PyObject *.
220 return self.result_as(py_object_type)
222 def ctype(self):
223 # Return the native C type of the result (i.e. the
224 # C type of the result_code expression).
225 return self.result_ctype or self.type
227 def compile_time_value(self, denv):
228 # Return value of compile-time expression, or report error.
229 error(self.pos, "Invalid compile-time expression")
231 def compile_time_value_error(self, e):
232 error(self.pos, "Error in compile-time expression: %s: %s" % (
233 e.__class__.__name__, e))
235 # ------------- Declaration Analysis ----------------
237 def analyse_target_declaration(self, env):
238 error(self.pos, "Cannot assign to or delete this")
240 # ------------- Expression Analysis ----------------
242 def analyse_const_expression(self, env):
243 # Called during the analyse_declarations phase of a
244 # constant expression. Analyses the expression's type,
245 # checks whether it is a legal const expression,
246 # and determines its value.
247 self.analyse_types(env)
248 self.allocate_temps(env)
249 self.check_const()
251 def analyse_expressions(self, env):
252 # Convenience routine performing both the Type
253 # Analysis and Temp Allocation phases for a whole
254 # expression.
255 self.analyse_types(env)
256 self.allocate_temps(env)
258 def analyse_target_expression(self, env, rhs):
259 # Convenience routine performing both the Type
260 # Analysis and Temp Allocation phases for the LHS of
261 # an assignment.
262 self.analyse_target_types(env)
263 self.allocate_target_temps(env, rhs)
265 def analyse_boolean_expression(self, env):
266 # Analyse expression and coerce to a boolean.
267 self.analyse_types(env)
268 bool = self.coerce_to_boolean(env)
269 bool.allocate_temps(env)
270 return bool
272 def analyse_temp_boolean_expression(self, env):
273 # Analyse boolean expression and coerce result into
274 # a temporary. This is used when a branch is to be
275 # performed on the result and we won't have an
276 # opportunity to ensure disposal code is executed
277 # afterwards. By forcing the result into a temporary,
278 # we ensure that all disposal has been done by the
279 # time we get the result.
280 self.analyse_types(env)
281 bool = self.coerce_to_boolean(env)
282 temp_bool = bool.coerce_to_temp(env)
283 temp_bool.allocate_temps(env)
284 return temp_bool
286 # --------------- Type Analysis ------------------
288 def analyse_as_module(self, env):
289 # If this node can be interpreted as a reference to a
290 # cimported module, return its scope, else None.
291 return None
293 def analyse_as_type(self, env):
294 # If this node can be interpreted as a reference to a
295 # type, return that type, else None.
296 return None
298 def analyse_as_extension_type(self, env):
299 # If this node can be interpreted as a reference to an
300 # extension type, return its type, else None.
301 return None
303 def analyse_types(self, env):
304 self.not_implemented("analyse_types")
306 def analyse_target_types(self, env):
307 self.analyse_types(env)
309 def gil_assignment_check(self, env):
310 if env.nogil and self.type.is_pyobject:
311 error(self.pos, "Assignment of Python object not allowed without gil")
313 def check_const(self):
314 self.not_const()
316 def not_const(self):
317 error(self.pos, "Not allowed in a constant expression")
319 def check_const_addr(self):
320 self.addr_not_const()
322 def addr_not_const(self):
323 error(self.pos, "Address is not constant")
325 def gil_check(self, env):
326 if env.nogil and self.type.is_pyobject:
327 self.gil_error()
329 # ----------------- Result Allocation -----------------
331 def result_in_temp(self):
332 # Return true if result is in a temporary owned by
333 # this node or one of its subexpressions. Overridden
334 # by certain nodes which can share the result of
335 # a subnode.
336 return self.is_temp
338 def allocate_target_temps(self, env, rhs):
339 # Perform temp allocation for the LHS of an assignment.
340 if debug_temp_alloc:
341 print("%s Allocating target temps" % self)
342 self.allocate_subexpr_temps(env)
343 self.is_target = True
344 if rhs:
345 rhs.release_temp(env)
346 self.release_subexpr_temps(env)
348 def allocate_temps(self, env, result = None):
349 # Allocate temporary variables for this node and
350 # all its sub-expressions. If a result is specified,
351 # this must be a temp node and the specified variable
352 # is used as the result instead of allocating a new
353 # one.
354 if debug_temp_alloc:
355 print("%s Allocating temps" % self)
356 self.allocate_subexpr_temps(env)
357 self.allocate_temp(env, result)
358 if self.is_temp:
359 self.release_subexpr_temps(env)
361 def allocate_subexpr_temps(self, env):
362 # Allocate temporary variables for all sub-expressions
363 # of this node.
364 if debug_temp_alloc:
365 print("%s Allocating temps for: %s" % (self, self.subexprs))
366 for node in self.subexpr_nodes():
367 if node:
368 if debug_temp_alloc:
369 print("%s Allocating temps for %s" % (self, node))
370 node.allocate_temps(env)
372 def allocate_temp(self, env, result = None):
373 # If this node requires a temporary variable for its
374 # result, allocate one, otherwise set the result to
375 # a C code fragment. If a result is specified,
376 # this must be a temp node and the specified variable
377 # is used as the result instead of allocating a new
378 # one.
379 if debug_temp_alloc:
380 print("%s Allocating temp" % self)
381 if result:
382 if not self.is_temp:
383 raise InternalError("Result forced on non-temp node")
384 self.result_code = result
385 elif self.is_temp:
386 type = self.type
387 if not type.is_void:
388 if type.is_pyobject:
389 type = PyrexTypes.py_object_type
390 self.result_code = env.allocate_temp(type)
391 else:
392 self.result_code = None
393 if debug_temp_alloc:
394 print("%s Allocated result %s" % (self, self.result_code))
396 def target_code(self):
397 # Return code fragment for use as LHS of a C assignment.
398 return self.calculate_result_code()
400 def calculate_result_code(self):
401 self.not_implemented("calculate_result_code")
403 # def release_target_temp(self, env):
404 # # Release temporaries used by LHS of an assignment.
405 # self.release_subexpr_temps(env)
407 def release_temp(self, env):
408 # If this node owns a temporary result, release it,
409 # otherwise release results of its sub-expressions.
410 if self.is_temp:
411 if debug_temp_alloc:
412 print("%s Releasing result %s" % (self, self.result_code))
413 env.release_temp(self.result_code)
414 else:
415 self.release_subexpr_temps(env)
417 def release_subexpr_temps(self, env):
418 # Release the results of all sub-expressions of
419 # this node.
420 for node in self.subexpr_nodes():
421 if node:
422 node.release_temp(env)
424 # ---------------- Code Generation -----------------
426 def make_owned_reference(self, code):
427 # If result is a pyobject, make sure we own
428 # a reference to it.
429 if self.type.is_pyobject and not self.result_in_temp():
430 code.put_incref(self.result(), self.ctype())
432 def generate_evaluation_code(self, code):
433 code.mark_pos(self.pos)
434 # Generate code to evaluate this node and
435 # its sub-expressions, and dispose of any
436 # temporary results of its sub-expressions.
437 self.generate_subexpr_evaluation_code(code)
438 self.generate_result_code(code)
439 if self.is_temp:
440 self.generate_subexpr_disposal_code(code)
441 self.free_subexpr_temps(code)
443 def generate_subexpr_evaluation_code(self, code):
444 for node in self.subexpr_nodes():
445 node.generate_evaluation_code(code)
447 def generate_result_code(self, code):
448 self.not_implemented("generate_result_code")
450 def generate_disposal_code(self, code):
451 # If necessary, generate code to dispose of
452 # temporary Python reference.
453 if self.is_temp:
454 if self.type.is_pyobject:
455 code.put_decref_clear(self.result(), self.ctype())
456 else:
457 self.generate_subexpr_disposal_code(code)
459 def generate_subexpr_disposal_code(self, code):
460 # Generate code to dispose of temporary results
461 # of all sub-expressions.
462 for node in self.subexpr_nodes():
463 node.generate_disposal_code(code)
465 def generate_post_assignment_code(self, code):
466 # Same as generate_disposal_code except that
467 # assignment will have absorbed a reference to
468 # the result if it is a Python object.
469 if self.is_temp:
470 if self.type.is_pyobject:
471 code.putln("%s = 0;" % self.result())
472 else:
473 self.generate_subexpr_disposal_code(code)
475 def generate_assignment_code(self, rhs, code):
476 # Stub method for nodes which are not legal as
477 # the LHS of an assignment. An error will have
478 # been reported earlier.
479 pass
481 def generate_deletion_code(self, code):
482 # Stub method for nodes that are not legal as
483 # the argument of a del statement. An error
484 # will have been reported earlier.
485 pass
487 def free_temps(self, code):
488 pass
490 def free_subexpr_temps(self, code):
491 for sub in self.subexpr_nodes():
492 sub.free_temps(code)
494 # ---------------- Annotation ---------------------
496 def annotate(self, code):
497 for node in self.subexpr_nodes():
498 node.annotate(code)
500 # ----------------- Coercion ----------------------
502 def coerce_to(self, dst_type, env):
503 # Coerce the result so that it can be assigned to
504 # something of type dst_type. If processing is necessary,
505 # wraps this node in a coercion node and returns that.
506 # Otherwise, returns this node unchanged.
507 #
508 # This method is called during the analyse_expressions
509 # phase of the src_node's processing.
510 src = self
511 src_type = self.type
512 src_is_py_type = src_type.is_pyobject
513 dst_is_py_type = dst_type.is_pyobject
515 if dst_type.is_pyobject:
516 if not src.type.is_pyobject:
517 src = CoerceToPyTypeNode(src, env)
518 if not src.type.subtype_of(dst_type):
519 if not isinstance(src, NoneNode):
520 src = PyTypeTestNode(src, dst_type, env)
521 elif src.type.is_pyobject:
522 src = CoerceFromPyTypeNode(dst_type, src, env)
523 else: # neither src nor dst are py types
524 # Added the string comparison, since for c types that
525 # is enough, but Cython gets confused when the types are
526 # in different files.
527 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
528 error(self.pos, "Cannot assign type '%s' to '%s'" %
529 (src.type, dst_type))
530 return src
532 def coerce_to_pyobject(self, env):
533 return self.coerce_to(PyrexTypes.py_object_type, env)
535 def coerce_to_boolean(self, env):
536 # Coerce result to something acceptable as
537 # a boolean value.
538 type = self.type
539 if type.is_pyobject or type.is_ptr or type.is_float:
540 return CoerceToBooleanNode(self, env)
541 else:
542 if not type.is_int and not type.is_error:
543 error(self.pos,
544 "Type '%s' not acceptable as a boolean" % type)
545 return self
547 def coerce_to_integer(self, env):
548 # If not already some C integer type, coerce to longint.
549 if self.type.is_int:
550 return self
551 else:
552 return self.coerce_to(PyrexTypes.c_long_type, env)
554 def coerce_to_temp(self, env):
555 # Ensure that the result is in a temporary.
556 if self.result_in_temp():
557 return self
558 else:
559 return CoerceToTempNode(self, env)
561 def coerce_to_simple(self, env):
562 # Ensure that the result is simple (see is_simple).
563 if self.is_simple():
564 return self
565 else:
566 return self.coerce_to_temp(env)
568 def is_simple(self):
569 # A node is simple if its result is something that can
570 # be referred to without performing any operations, e.g.
571 # a constant, local var, C global var, struct member
572 # reference, or temporary.
573 return self.result_in_temp()
575 def as_cython_attribute(self):
576 return None
579 class RemoveAllocateTemps(type):
580 def __init__(cls, name, bases, dct):
581 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
582 def noop(self, env): pass
583 setattr(cls, 'allocate_temps', noop)
584 setattr(cls, 'allocate_temp', noop)
585 setattr(cls, 'release_temp', noop)
587 class NewTempExprNode(ExprNode):
588 backwards_compatible_result = None
589 temp_code = None
591 # Do not enable this unless you are trying to make all ExprNodes
592 # NewTempExprNodes (child nodes reached via recursion may not have
593 # transferred).
594 # __metaclass__ = RemoveAllocateTemps
596 def result(self):
597 if self.is_temp:
598 return self.temp_code
599 else:
600 return self.calculate_result_code()
602 def allocate_target_temps(self, env, rhs):
603 self.allocate_subexpr_temps(env)
604 self.is_target = True
605 if rhs:
606 rhs.release_temp(env)
607 self.release_subexpr_temps(env)
609 def allocate_temps(self, env, result = None):
610 self.allocate_subexpr_temps(env)
611 self.backwards_compatible_result = result
612 if self.is_temp:
613 self.release_subexpr_temps(env)
615 def allocate_temp(self, env, result = None):
616 assert result is None
618 def release_temp(self, env):
619 if self.is_temp:
620 pass
621 else:
622 self.release_subexpr_temps(env)
624 def allocate_temp_result(self, code):
625 if self.temp_code:
626 raise RuntimeError("Temp allocated multiple times")
627 type = self.type
628 if not type.is_void:
629 if type.is_pyobject:
630 type = PyrexTypes.py_object_type
631 if self.backwards_compatible_result:
632 self.temp_code = self.backwards_compatible_result
633 else:
634 self.temp_code = code.funcstate.allocate_temp(
635 type, manage_ref=True)
636 else:
637 self.temp_code = None
639 def release_temp_result(self, code):
640 if not self.temp_code:
641 if self.old_temp:
642 raise RuntimeError("temp %s released multiple times in %s" % (
643 self.old_temp, self.__class__.__name__))
644 else:
645 raise RuntimeError("no temp, but release requested in %s" % (
646 self.__class__.__name__))
647 code.funcstate.release_temp(self.temp_code)
648 self.old_temp = self.temp_code
649 self.temp_code = None
651 def generate_evaluation_code(self, code):
652 code.mark_pos(self.pos)
654 # Generate code to evaluate this node and
655 # its sub-expressions, and dispose of any
656 # temporary results of its sub-expressions.
657 self.generate_subexpr_evaluation_code(code)
659 if self.is_temp:
660 self.allocate_temp_result(code)
662 self.generate_result_code(code)
663 if self.is_temp:
664 # If we are temp we do not need to wait until this node is disposed
665 # before disposing children.
666 self.generate_subexpr_disposal_code(code)
667 self.free_subexpr_temps(code)
669 def generate_disposal_code(self, code):
670 if self.is_temp:
671 if self.type.is_pyobject:
672 code.put_decref_clear(self.result(), self.ctype())
673 else:
674 # Already done if self.is_temp
675 self.generate_subexpr_disposal_code(code)
677 def generate_post_assignment_code(self, code):
678 if self.is_temp:
679 if self.type.is_pyobject:
680 code.putln("%s = 0;" % self.result())
681 else:
682 self.generate_subexpr_disposal_code(code)
684 def free_temps(self, code):
685 if self.is_temp:
686 if not self.type.is_void:
687 self.release_temp_result(code)
688 else:
689 self.free_subexpr_temps(code)
691 # ExprNode = NewTempExprNode
693 class AtomicExprNode(ExprNode):
694 # Abstract base class for expression nodes which have
695 # no sub-expressions.
697 subexprs = []
699 class AtomicNewTempExprNode(NewTempExprNode):
700 # I do not dare to convert NameNode yet. This is now
701 # ancestor of all former AtomicExprNode except
702 # NameNode. Should be renamed to AtomicExprNode
703 # when done.
705 # Abstract base class for expression nodes which have
706 # no sub-expressions.
708 subexprs = []
710 # Override to optimize -- we know we have no children
711 def generate_subexpr_evaluation_code(self, code):
712 pass
713 def generate_subexpr_disposal_code(self, code):
714 pass
716 class PyConstNode(AtomicNewTempExprNode):
717 # Abstract base class for constant Python values.
719 is_literal = 1
721 def is_simple(self):
722 return 1
724 def analyse_types(self, env):
725 self.type = py_object_type
727 def calculate_result_code(self):
728 return self.value
730 def generate_result_code(self, code):
731 pass
734 class NoneNode(PyConstNode):
735 # The constant value None
737 value = "Py_None"
739 def compile_time_value(self, denv):
740 return None
742 class EllipsisNode(PyConstNode):
743 # '...' in a subscript list.
745 value = "Py_Ellipsis"
747 def compile_time_value(self, denv):
748 return Ellipsis
751 class ConstNode(AtomicNewTempExprNode):
752 # Abstract base type for literal constant nodes.
753 #
754 # value string C code fragment
756 is_literal = 1
758 def is_simple(self):
759 return 1
761 def analyse_types(self, env):
762 pass # Types are held in class variables
764 def check_const(self):
765 pass
767 def calculate_result_code(self):
768 return str(self.value)
770 def generate_result_code(self, code):
771 pass
774 class BoolNode(ConstNode):
775 type = PyrexTypes.c_bint_type
776 # The constant value True or False
778 def compile_time_value(self, denv):
779 return self.value
781 def calculate_result_code(self):
782 return str(int(self.value))
784 class NullNode(ConstNode):
785 type = PyrexTypes.c_null_ptr_type
786 value = "NULL"
789 class CharNode(ConstNode):
790 type = PyrexTypes.c_char_type
792 def compile_time_value(self, denv):
793 return ord(self.value)
795 def calculate_result_code(self):
796 return "'%s'" % StringEncoding.escape_character(self.value)
799 class IntNode(ConstNode):
801 # unsigned "" or "U"
802 # longness "" or "L" or "LL"
804 unsigned = ""
805 longness = ""
806 type = PyrexTypes.c_long_type
808 def coerce_to(self, dst_type, env):
809 if dst_type.is_numeric:
810 self.type = PyrexTypes.c_long_type
811 return self
812 # Arrange for a Python version of the number to be pre-allocated
813 # when coercing to a Python type.
814 if dst_type.is_pyobject:
815 self.entry = env.get_py_num(self.value, self.longness)
816 self.type = PyrexTypes.py_object_type
817 # We still need to perform normal coerce_to processing on the
818 # result, because we might be coercing to an extension type,
819 # in which case a type test node will be needed.
820 return ConstNode.coerce_to(self, dst_type, env)
822 def coerce_to_boolean(self, env):
823 self.type = PyrexTypes.c_bint_type
824 return self
826 def calculate_result_code(self):
827 if self.type.is_pyobject:
828 return self.entry.cname
829 else:
830 return str(self.value) + self.unsigned + self.longness
832 def compile_time_value(self, denv):
833 return int(self.value, 0)
836 class FloatNode(ConstNode):
837 type = PyrexTypes.c_double_type
839 def compile_time_value(self, denv):
840 return float(self.value)
842 def calculate_result_code(self):
843 strval = str(self.value)
844 if strval == 'nan':
845 return "(Py_HUGE_VAL * 0)"
846 elif strval == 'inf':
847 return "Py_HUGE_VAL"
848 elif strval == '-inf':
849 return "(-Py_HUGE_VAL)"
850 else:
851 return strval
854 class StringNode(ConstNode):
855 # entry Symtab.Entry
857 type = PyrexTypes.c_char_ptr_type
859 def compile_time_value(self, denv):
860 return self.value
862 def analyse_types(self, env):
863 self.entry = env.add_string_const(self.value)
865 def analyse_as_type(self, env):
866 type = PyrexTypes.parse_basic_type(self.value)
867 if type is not None:
868 return type
869 from TreeFragment import TreeFragment
870 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
871 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
872 sizeof_node = declaration.root.stats[0].expr
873 sizeof_node.analyse_types(env)
874 if isinstance(sizeof_node, SizeofTypeNode):
875 return sizeof_node.arg_type
877 def coerce_to(self, dst_type, env):
878 if dst_type == PyrexTypes.c_char_ptr_type:
879 self.type = PyrexTypes.c_char_ptr_type
880 return self
882 if dst_type.is_int:
883 if not self.type.is_pyobject and len(self.entry.init) == 1:
884 return CharNode(self.pos, value=self.value)
885 else:
886 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
887 return self
888 # Arrange for a Python version of the string to be pre-allocated
889 # when coercing to a Python type.
890 if dst_type.is_pyobject and not self.type.is_pyobject:
891 node = self.as_py_string_node(env)
892 else:
893 node = self
894 # We still need to perform normal coerce_to processing on the
895 # result, because we might be coercing to an extension type,
896 # in which case a type test node will be needed.
897 return ConstNode.coerce_to(node, dst_type, env)
899 def as_py_string_node(self, env):
900 # Return a new StringNode with the same entry as this node
901 # but whose type is a Python type instead of a C type.
902 entry = self.entry
903 env.add_py_string(entry)
904 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
906 def calculate_result_code(self):
907 if self.type.is_pyobject:
908 return self.entry.pystring_cname
909 else:
910 return self.entry.cname
913 class UnicodeNode(PyConstNode):
914 # entry Symtab.Entry
916 type = unicode_type
918 def analyse_types(self, env):
919 self.entry = env.add_string_const(self.value)
920 env.add_py_string(self.entry)
922 def calculate_result_code(self):
923 return self.entry.pystring_cname
925 def _coerce_to(self, dst_type, env):
926 if not dst_type.is_pyobject:
927 node = StringNode(self.pos, entry = entry, type = py_object_type)
928 return ConstNode.coerce_to(node, dst_type, env)
929 else:
930 return self
931 # We still need to perform normal coerce_to processing on the
932 # result, because we might be coercing to an extension type,
933 # in which case a type test node will be needed.
935 def compile_time_value(self, env):
936 return self.value
939 class IdentifierStringNode(ConstNode):
940 # A Python string that behaves like an identifier, e.g. for
941 # keyword arguments in a call, or for imported names
942 type = PyrexTypes.py_object_type
944 def analyse_types(self, env):
945 self.cname = env.intern_identifier(self.value)
947 def calculate_result_code(self):
948 return self.cname
951 class LongNode(AtomicNewTempExprNode):
952 # Python long integer literal
953 #
954 # value string
956 def compile_time_value(self, denv):
957 return long(self.value)
959 gil_message = "Constructing Python long int"
961 def analyse_types(self, env):
962 self.type = py_object_type
963 self.gil_check(env)
964 self.is_temp = 1
966 gil_message = "Constructing Python long int"
968 def generate_result_code(self, code):
969 code.putln(
970 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
971 self.result(),
972 self.value,
973 code.error_goto_if_null(self.result(), self.pos)))
976 class ImagNode(AtomicNewTempExprNode):
977 # Imaginary number literal
978 #
979 # value float imaginary part
981 def compile_time_value(self, denv):
982 return complex(0.0, self.value)
984 def analyse_types(self, env):
985 self.type = py_object_type
986 self.gil_check(env)
987 self.is_temp = 1
989 gil_message = "Constructing complex number"
991 def generate_result_code(self, code):
992 code.putln(
993 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
994 self.result(),
995 self.value,
996 code.error_goto_if_null(self.result(), self.pos)))
999 class NameNode(AtomicExprNode):
1000 # Reference to a local or global variable name.
1002 # name string Python name of the variable
1004 # entry Entry Symbol table entry
1005 # interned_cname string
1007 is_name = True
1008 is_cython_module = False
1009 cython_attribute = None
1010 lhs_of_first_assignment = False
1011 entry = None
1013 def create_analysed_rvalue(pos, env, entry):
1014 node = NameNode(pos)
1015 node.analyse_types(env, entry=entry)
1016 return node
1018 def as_cython_attribute(self):
1019 return self.cython_attribute
1021 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1023 def compile_time_value(self, denv):
1024 try:
1025 return denv.lookup(self.name)
1026 except KeyError:
1027 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1029 def coerce_to(self, dst_type, env):
1030 # If coercing to a generic pyobject and this is a builtin
1031 # C function with a Python equivalent, manufacture a NameNode
1032 # referring to the Python builtin.
1033 #print "NameNode.coerce_to:", self.name, dst_type ###
1034 if dst_type is py_object_type:
1035 entry = self.entry
1036 if entry and entry.is_cfunction:
1037 var_entry = entry.as_variable
1038 if var_entry:
1039 if var_entry.is_builtin and Options.cache_builtins:
1040 var_entry = env.declare_builtin(var_entry.name, self.pos)
1041 node = NameNode(self.pos, name = self.name)
1042 node.entry = var_entry
1043 node.analyse_rvalue_entry(env)
1044 return node
1045 return AtomicExprNode.coerce_to(self, dst_type, env)
1047 def analyse_as_module(self, env):
1048 # Try to interpret this as a reference to a cimported module.
1049 # Returns the module scope, or None.
1050 entry = self.entry
1051 if not entry:
1052 entry = env.lookup(self.name)
1053 if entry and entry.as_module:
1054 return entry.as_module
1055 return None
1057 def analyse_as_type(self, env):
1058 if self.cython_attribute:
1059 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1060 else:
1061 type = PyrexTypes.parse_basic_type(self.name)
1062 if type:
1063 return type
1064 entry = self.entry
1065 if not entry:
1066 entry = env.lookup(self.name)
1067 if entry and entry.is_type:
1068 return entry.type
1069 else:
1070 return None
1072 def analyse_as_extension_type(self, env):
1073 # Try to interpret this as a reference to an extension type.
1074 # Returns the extension type, or None.
1075 entry = self.entry
1076 if not entry:
1077 entry = env.lookup(self.name)
1078 if entry and entry.is_type and entry.type.is_extension_type:
1079 return entry.type
1080 else:
1081 return None
1083 def analyse_target_declaration(self, env):
1084 if not self.entry:
1085 self.entry = env.lookup_here(self.name)
1086 if not self.entry:
1087 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1088 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1089 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1090 if self.entry.is_declared_generic:
1091 self.result_ctype = py_object_type
1093 def analyse_types(self, env):
1094 if self.entry is None:
1095 self.entry = env.lookup(self.name)
1096 if not self.entry:
1097 self.entry = env.declare_builtin(self.name, self.pos)
1098 if not self.entry:
1099 self.type = PyrexTypes.error_type
1100 return
1101 self.analyse_rvalue_entry(env)
1103 def analyse_target_types(self, env):
1104 self.analyse_entry(env)
1105 if not self.is_lvalue():
1106 error(self.pos, "Assignment to non-lvalue '%s'"
1107 % self.name)
1108 self.type = PyrexTypes.error_type
1109 self.entry.used = 1
1110 if self.entry.type.is_buffer:
1111 import Buffer
1112 Buffer.used_buffer_aux_vars(self.entry)
1114 def analyse_rvalue_entry(self, env):
1115 #print "NameNode.analyse_rvalue_entry:", self.name ###
1116 #print "Entry:", self.entry.__dict__ ###
1117 self.analyse_entry(env)
1118 entry = self.entry
1119 if entry.is_declared_generic:
1120 self.result_ctype = py_object_type
1121 if entry.is_pyglobal or entry.is_builtin:
1122 if Options.cache_builtins and entry.is_builtin:
1123 self.is_temp = 0
1124 else:
1125 self.is_temp = 1
1126 env.use_utility_code(get_name_interned_utility_code)
1127 self.gil_check(env)
1129 gil_message = "Accessing Python global or builtin"
1131 def analyse_entry(self, env):
1132 #print "NameNode.analyse_entry:", self.name ###
1133 self.check_identifier_kind()
1134 entry = self.entry
1135 type = entry.type
1136 self.type = type
1137 if entry.is_pyglobal or entry.is_builtin:
1138 assert type.is_pyobject, "Python global or builtin not a Python object"
1139 self.interned_cname = self.entry.interned_cname = \
1140 env.intern_identifier(self.entry.name)
1142 def check_identifier_kind(self):
1143 #print "NameNode.check_identifier_kind:", self.entry.name ###
1144 #print self.entry.__dict__ ###
1145 entry = self.entry
1146 #entry.used = 1
1147 if not (entry.is_const or entry.is_variable
1148 or entry.is_builtin or entry.is_cfunction):
1149 if self.entry.as_variable:
1150 self.entry = self.entry.as_variable
1151 else:
1152 error(self.pos,
1153 "'%s' is not a constant, variable or function identifier" % self.name)
1155 def is_simple(self):
1156 # If it's not a C variable, it'll be in a temp.
1157 return 1
1159 def calculate_target_results(self, env):
1160 pass
1162 def check_const(self):
1163 entry = self.entry
1164 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1165 self.not_const()
1167 def check_const_addr(self):
1168 entry = self.entry
1169 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1170 self.addr_not_const()
1172 def is_lvalue(self):
1173 return self.entry.is_variable and \
1174 not self.entry.type.is_array and \
1175 not self.entry.is_readonly
1177 def is_ephemeral(self):
1178 # Name nodes are never ephemeral, even if the
1179 # result is in a temporary.
1180 return 0
1182 def allocate_temp(self, env, result = None):
1183 AtomicExprNode.allocate_temp(self, env, result)
1184 entry = self.entry
1185 if entry:
1186 entry.used = 1
1187 if entry.type.is_buffer:
1188 import Buffer
1189 Buffer.used_buffer_aux_vars(entry)
1190 if entry.utility_code:
1191 env.use_utility_code(entry.utility_code)
1193 def calculate_result_code(self):
1194 entry = self.entry
1195 if not entry:
1196 return "<error>" # There was an error earlier
1197 return entry.cname
1199 def generate_result_code(self, code):
1200 assert hasattr(self, 'entry')
1201 entry = self.entry
1202 if entry is None:
1203 return # There was an error earlier
1204 if entry.is_builtin and Options.cache_builtins:
1205 return # Lookup already cached
1206 elif entry.is_pyglobal or entry.is_builtin:
1207 if entry.is_builtin:
1208 namespace = Naming.builtins_cname
1209 else: # entry.is_pyglobal
1210 namespace = entry.scope.namespace_cname
1211 code.putln(
1212 '%s = __Pyx_GetName(%s, %s); %s' % (
1213 self.result(),
1214 namespace,
1215 self.interned_cname,
1216 code.error_goto_if_null(self.result(), self.pos)))
1217 elif entry.is_local and False:
1218 # control flow not good enough yet
1219 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1220 if assigned is False:
1221 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1222 elif not Options.init_local_none and assigned is None:
1223 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1224 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1226 def generate_assignment_code(self, rhs, code):
1227 #print "NameNode.generate_assignment_code:", self.name ###
1228 entry = self.entry
1229 if entry is None:
1230 return # There was an error earlier
1232 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1233 and not self.lhs_of_first_assignment):
1234 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1236 # is_pyglobal seems to be True for module level-globals only.
1237 # We use this to access class->tp_dict if necessary.
1238 if entry.is_pyglobal:
1239 namespace = self.entry.scope.namespace_cname
1240 if entry.is_member:
1241 # if the entry is a member we have to cheat: SetAttr does not work
1242 # on types, so we create a descriptor which is then added to tp_dict
1243 code.put_error_if_neg(self.pos,
1244 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1245 namespace,
1246 self.interned_cname,
1247 rhs.py_result()))
1248 # in Py2.6+, we need to invalidate the method cache
1249 code.putln("PyType_Modified(%s);" %
1250 entry.scope.parent_type.typeptr_cname)
1251 else:
1252 code.put_error_if_neg(self.pos,
1253 'PyObject_SetAttr(%s, %s, %s)' % (
1254 namespace,
1255 self.interned_cname,
1256 rhs.py_result()))
1257 if debug_disposal_code:
1258 print("NameNode.generate_assignment_code:")
1259 print("...generating disposal code for %s" % rhs)
1260 rhs.generate_disposal_code(code)
1261 rhs.free_temps(code)
1262 else:
1263 if self.type.is_buffer:
1264 # Generate code for doing the buffer release/acquisition.
1265 # This might raise an exception in which case the assignment (done
1266 # below) will not happen.
1268 # The reason this is not in a typetest-like node is because the
1269 # variables that the acquired buffer info is stored to is allocated
1270 # per entry and coupled with it.
1271 self.generate_acquire_buffer(rhs, code)
1273 if self.type.is_pyobject:
1274 rhs.make_owned_reference(code)
1275 #print "NameNode.generate_assignment_code: to", self.name ###
1276 #print "...from", rhs ###
1277 #print "...LHS type", self.type, "ctype", self.ctype() ###
1278 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1279 if not self.lhs_of_first_assignment:
1280 if entry.is_local and not Options.init_local_none:
1281 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1282 if initalized is True:
1283 code.put_decref(self.result(), self.ctype())
1284 elif initalized is None:
1285 code.put_xdecref(self.result(), self.ctype())
1286 else:
1287 code.put_decref(self.result(), self.ctype())
1288 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1289 if debug_disposal_code:
1290 print("NameNode.generate_assignment_code:")
1291 print("...generating post-assignment code for %s" % rhs)
1292 rhs.generate_post_assignment_code(code)
1293 rhs.free_temps(code)
1295 def generate_acquire_buffer(self, rhs, code):
1296 # rhstmp is only used in case the rhs is a complicated expression leading to
1297 # the object, to avoid repeating the same C expression for every reference
1298 # to the rhs. It does NOT hold a reference.
1299 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1300 if pretty_rhs:
1301 rhstmp = rhs.result_as(self.ctype())
1302 else:
1303 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1304 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1306 buffer_aux = self.entry.buffer_aux
1307 bufstruct = buffer_aux.buffer_info_var.cname
1308 import Buffer
1309 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1310 is_initialized=not self.lhs_of_first_assignment,
1311 pos=self.pos, code=code)
1313 if not pretty_rhs:
1314 code.putln("%s = 0;" % rhstmp)
1315 code.funcstate.release_temp(rhstmp)
1317 def generate_deletion_code(self, code):
1318 if self.entry is None:
1319 return # There was an error earlier
1320 if not self.entry.is_pyglobal:
1321 error(self.pos, "Deletion of local or C global name not supported")
1322 return
1323 code.put_error_if_neg(self.pos,
1324 'PyObject_DelAttrString(%s, "%s")' % (
1325 Naming.module_cname,
1326 self.entry.name))
1328 def annotate(self, code):
1329 if hasattr(self, 'is_called') and self.is_called:
1330 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1331 if self.type.is_pyobject:
1332 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1333 else:
1334 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1336 class BackquoteNode(ExprNode):
1337 # `expr`
1339 # arg ExprNode
1341 subexprs = ['arg']
1343 def analyse_types(self, env):
1344 self.arg.analyse_types(env)
1345 self.arg = self.arg.coerce_to_pyobject(env)
1346 self.type = py_object_type
1347 self.gil_check(env)
1348 self.is_temp = 1
1350 gil_message = "Backquote expression"
1352 def generate_result_code(self, code):
1353 code.putln(
1354 "%s = PyObject_Repr(%s); %s" % (
1355 self.result(),
1356 self.arg.py_result(),
1357 code.error_goto_if_null(self.result(), self.pos)))
1360 class ImportNode(ExprNode):
1361 # Used as part of import statement implementation.
1362 # Implements result =
1363 # __import__(module_name, globals(), None, name_list)
1365 # module_name IdentifierStringNode dotted name of module
1366 # name_list ListNode or None list of names to be imported
1368 subexprs = ['module_name', 'name_list']
1370 def analyse_types(self, env):
1371 self.module_name.analyse_types(env)
1372 self.module_name = self.module_name.coerce_to_pyobject(env)
1373 if self.name_list:
1374 self.name_list.analyse_types(env)
1375 self.name_list.coerce_to_pyobject(env)
1376 self.type = py_object_type
1377 self.gil_check(env)
1378 self.is_temp = 1
1379 env.use_utility_code(import_utility_code)
1381 gil_message = "Python import"
1383 def generate_result_code(self, code):
1384 if self.name_list:
1385 name_list_code = self.name_list.py_result()
1386 else:
1387 name_list_code = "0"
1388 code.putln(
1389 "%s = __Pyx_Import(%s, %s); %s" % (
1390 self.result(),
1391 self.module_name.py_result(),
1392 name_list_code,
1393 code.error_goto_if_null(self.result(), self.pos)))
1396 class IteratorNode(NewTempExprNode):
1397 # Used as part of for statement implementation.
1399 # allocate_counter_temp/release_counter_temp needs to be called
1400 # by parent (ForInStatNode)
1402 # Implements result = iter(sequence)
1404 # sequence ExprNode
1406 subexprs = ['sequence']
1408 def analyse_types(self, env):
1409 self.sequence.analyse_types(env)
1410 self.sequence = self.sequence.coerce_to_pyobject(env)
1411 self.type = py_object_type
1412 self.gil_check(env)
1413 self.is_temp = 1
1415 gil_message = "Iterating over Python object"
1417 def allocate_counter_temp(self, code):
1418 self.counter_cname = code.funcstate.allocate_temp(
1419 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1421 def release_counter_temp(self, code):
1422 code.funcstate.release_temp(self.counter_cname)
1424 def generate_result_code(self, code):
1425 is_builtin_sequence = self.sequence.type is list_type or \
1426 self.sequence.type is tuple_type
1427 if is_builtin_sequence:
1428 code.putln(
1429 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1430 else:
1431 code.putln(
1432 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1433 self.sequence.py_result(),
1434 self.sequence.py_result()))
1435 code.putln(
1436 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1437 self.counter_cname,
1438 self.result(),
1439 self.sequence.py_result(),
1440 self.result()))
1441 code.putln("} else {")
1442 if is_builtin_sequence:
1443 code.putln(
1444 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1445 code.error_goto(self.pos))
1446 else:
1447 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1448 self.counter_cname,
1449 self.result(),
1450 self.sequence.py_result(),
1451 code.error_goto_if_null(self.result(), self.pos)))
1452 code.putln("}")
1455 class NextNode(AtomicNewTempExprNode):
1456 # Used as part of for statement implementation.
1457 # Implements result = iterator.next()
1458 # Created during analyse_types phase.
1459 # The iterator is not owned by this node.
1461 # iterator ExprNode
1463 def __init__(self, iterator, env):
1464 self.pos = iterator.pos
1465 self.iterator = iterator
1466 self.type = py_object_type
1467 self.is_temp = 1
1469 def generate_result_code(self, code):
1470 if self.iterator.sequence.type is list_type:
1471 type_checks = [(list_type, "List")]
1472 elif self.iterator.sequence.type is tuple_type:
1473 type_checks = [(tuple_type, "Tuple")]
1474 else:
1475 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1477 for py_type, prefix in type_checks:
1478 if len(type_checks) > 1:
1479 code.putln(
1480 "if (likely(Py%s_CheckExact(%s))) {" % (
1481 prefix, self.iterator.py_result()))
1482 code.putln(
1483 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1484 self.iterator.counter_cname,
1485 prefix,
1486 self.iterator.py_result()))
1487 code.putln(
1488 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1489 self.result(),
1490 prefix,
1491 self.iterator.py_result(),
1492 self.iterator.counter_cname,
1493 self.result(),
1494 self.iterator.counter_cname))
1495 if len(type_checks) > 1:
1496 code.put("} else ")
1497 if len(type_checks) == 1:
1498 return
1499 code.putln("{")
1500 code.putln(
1501 "%s = PyIter_Next(%s);" % (
1502 self.result(),
1503 self.iterator.py_result()))
1504 code.putln(
1505 "if (!%s) {" %
1506 self.result())
1507 code.putln(code.error_goto_if_PyErr(self.pos))
1508 code.putln("break;")
1509 code.putln("}")
1510 code.putln("}")
1513 class ExcValueNode(AtomicNewTempExprNode):
1514 # Node created during analyse_types phase
1515 # of an ExceptClauseNode to fetch the current
1516 # exception value.
1518 def __init__(self, pos, env, var):
1519 ExprNode.__init__(self, pos)
1520 self.type = py_object_type
1521 self.var = var
1523 def calculate_result_code(self):
1524 return self.var
1526 def generate_result_code(self, code):
1527 pass
1529 def analyse_types(self, env):
1530 pass
1533 class TempNode(ExprNode):
1534 # Node created during analyse_types phase
1535 # of some nodes to hold a temporary value.
1537 subexprs = []
1539 def __init__(self, pos, type, env):
1540 ExprNode.__init__(self, pos)
1541 self.type = type
1542 if type.is_pyobject:
1543 self.result_ctype = py_object_type
1544 self.is_temp = 1
1546 def analyse_types(self, env):
1547 return self.type
1549 def generate_result_code(self, code):
1550 pass
1553 class PyTempNode(TempNode):
1554 # TempNode holding a Python value.
1556 def __init__(self, pos, env):
1557 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1560 #-------------------------------------------------------------------
1562 # Trailer nodes
1564 #-------------------------------------------------------------------
1566 class IndexNode(ExprNode):
1567 # Sequence indexing.
1569 # base ExprNode
1570 # index ExprNode
1571 # indices [ExprNode]
1572 # is_buffer_access boolean Whether this is a buffer access.
1574 # indices is used on buffer access, index on non-buffer access.
1575 # The former contains a clean list of index parameters, the
1576 # latter whatever Python object is needed for index access.
1578 subexprs = ['base', 'index', 'indices']
1579 indices = None
1581 def __init__(self, pos, index, *args, **kw):
1582 ExprNode.__init__(self, pos, index=index, *args, **kw)
1583 self._index = index
1585 def compile_time_value(self, denv):
1586 base = self.base.compile_time_value(denv)
1587 index = self.index.compile_time_value(denv)
1588 try:
1589 return base[index]
1590 except Exception, e:
1591 self.compile_time_value_error(e)
1593 def is_ephemeral(self):
1594 return self.base.is_ephemeral()
1596 def analyse_target_declaration(self, env):
1597 pass
1599 def analyse_as_type(self, env):
1600 base_type = self.base.analyse_as_type(env)
1601 if base_type and not base_type.is_pyobject:
1602 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1603 return None
1605 def analyse_types(self, env):
1606 self.analyse_base_and_index_types(env, getting = 1)
1608 def analyse_target_types(self, env):
1609 self.analyse_base_and_index_types(env, setting = 1)
1611 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1612 # Note: This might be cleaned up by having IndexNode
1613 # parsed in a saner way and only construct the tuple if
1614 # needed.
1616 # Note that this function must leave IndexNode in a cloneable state.
1617 # For buffers, self.index is packed out on the initial analysis, and
1618 # when cloning self.indices is copied.
1619 self.is_buffer_access = False
1621 self.base.analyse_types(env)
1622 # Handle the case where base is a literal char* (and we expect a string, not an int)
1623 if isinstance(self.base, StringNode):
1624 self.base = self.base.coerce_to_pyobject(env)
1626 skip_child_analysis = False
1627 buffer_access = False
1628 if self.base.type.is_buffer:
1629 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1630 if self.indices:
1631 indices = self.indices
1632 else:
1633 # On cloning, indices is cloned. Otherwise, unpack index into indices
1634 assert not isinstance(self.index, CloneNode)
1635 if isinstance(self.index, TupleNode):
1636 indices = self.index.args
1637 else:
1638 indices = [self.index]
1639 if len(indices) == self.base.type.ndim:
1640 buffer_access = True
1641 skip_child_analysis = True
1642 for x in indices:
1643 x.analyse_types(env)
1644 if not x.type.is_int:
1645 buffer_access = False
1647 if buffer_access:
1648 self.indices = indices
1649 self.index = None
1650 self.type = self.base.type.dtype
1651 self.is_buffer_access = True
1652 self.buffer_type = self.base.entry.type
1654 if getting and self.type.is_pyobject:
1655 self.is_temp = True
1656 if setting:
1657 if not self.base.entry.type.writable:
1658 error(self.pos, "Writing to readonly buffer")
1659 else:
1660 self.base.entry.buffer_aux.writable_needed = True
1661 else:
1662 if isinstance(self.index, TupleNode):
1663 self.index.analyse_types(env, skip_children=skip_child_analysis)
1664 elif not skip_child_analysis:
1665 self.index.analyse_types(env)
1666 self.original_index_type = self.index.type
1667 if self.base.type.is_pyobject:
1668 if self.index.type.is_int and not self.index.type.is_longlong:
1669 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1670 else:
1671 self.index = self.index.coerce_to_pyobject(env)
1672 self.type = py_object_type
1673 self.gil_check(env)
1674 self.is_temp = 1
1675 else:
1676 if self.base.type.is_ptr or self.base.type.is_array:
1677 self.type = self.base.type.base_type
1678 else:
1679 error(self.pos,
1680 "Attempting to index non-array type '%s'" %
1681 self.base.type)
1682 self.type = PyrexTypes.error_type
1683 if self.index.type.is_pyobject:
1684 self.index = self.index.coerce_to(
1685 PyrexTypes.c_py_ssize_t_type, env)
1686 if not self.index.type.is_int:
1687 error(self.pos,
1688 "Invalid index type '%s'" %
1689 self.index.type)
1691 gil_message = "Indexing Python object"
1693 def check_const_addr(self):
1694 self.base.check_const_addr()
1695 self.index.check_const()
1697 def is_lvalue(self):
1698 return 1
1700 def calculate_result_code(self):
1701 if self.is_buffer_access:
1702 return "(*%s)" % self.buffer_ptr_code
1703 else:
1704 return "(%s[%s])" % (
1705 self.base.result(), self.index.result())
1707 def index_unsigned_parameter(self):
1708 if self.index.type.is_int:
1709 if self.original_index_type.signed:
1710 return ", 0"
1711 else:
1712 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1713 else:
1714 return ""
1716 def generate_subexpr_evaluation_code(self, code):
1717 self.base.generate_evaluation_code(code)
1718 if not self.indices:
1719 self.index.generate_evaluation_code(code)
1720 else:
1721 for i in self.indices:
1722 i.generate_evaluation_code(code)
1724 def generate_subexpr_disposal_code(self, code):
1725 self.base.generate_disposal_code(code)
1726 if not self.indices:
1727 self.index.generate_disposal_code(code)
1728 else:
1729 for i in self.indices:
1730 i.generate_disposal_code(code)
1732 def free_subexpr_temps(self, code):
1733 self.base.free_temps(code)
1734 if not self.indices:
1735 self.index.free_temps(code)
1736 else:
1737 for i in self.indices:
1738 i.free_temps(code)
1740 def generate_result_code(self, code):
1741 if self.is_buffer_access:
1742 if code.globalstate.directives['nonecheck']:
1743 self.put_nonecheck(code)
1744 self.buffer_ptr_code = self.buffer_lookup_code(code)
1745 if self.type.is_pyobject:
1746 # is_temp is True, so must pull out value and incref it.
1747 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1748 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1749 elif self.type.is_pyobject:
1750 if self.index.type.is_int:
1751 function = "__Pyx_GetItemInt"
1752 index_code = self.index.result()
1753 code.globalstate.use_utility_code(getitem_int_utility_code)
1754 else:
1755 function = "PyObject_GetItem"
1756 index_code = self.index.py_result()
1757 sign_code = ""
1758 code.putln(
1759 "%s = %s(%s, %s%s); if (!%s) %s" % (
1760 self.result(),
1761 function,
1762 self.base.py_result(),
1763 index_code,
1764 self.index_unsigned_parameter(),
1765 self.result(),
1766 code.error_goto(self.pos)))
1768 def generate_setitem_code(self, value_code, code):
1769 if self.index.type.is_int:
1770 function = "__Pyx_SetItemInt"
1771 index_code = self.index.result()
1772 code.globalstate.use_utility_code(setitem_int_utility_code)
1773 else:
1774 index_code = self.index.py_result()
1775 if self.base.type is dict_type:
1776 function = "PyDict_SetItem"
1777 elif self.base.type is list_type:
1778 function = "PyList_SetItem"
1779 # don't use PyTuple_SetItem(), as we'd normally get a
1780 # TypeError when changing a tuple, while PyTuple_SetItem()
1781 # would allow updates
1783 #elif self.base.type is tuple_type:
1784 # function = "PyTuple_SetItem"
1785 else:
1786 function = "PyObject_SetItem"
1787 code.putln(
1788 "if (%s(%s, %s, %s%s) < 0) %s" % (
1789 function,
1790 self.base.py_result(),
1791 index_code,
1792 value_code,
1793 self.index_unsigned_parameter(),
1794 code.error_goto(self.pos)))
1796 def generate_buffer_setitem_code(self, rhs, code, op=""):
1797 # Used from generate_assignment_code and InPlaceAssignmentNode
1798 if code.globalstate.directives['nonecheck']:
1799 self.put_nonecheck(code)
1800 ptrexpr = self.buffer_lookup_code(code)
1801 if self.buffer_type.dtype.is_pyobject:
1802 # Must manage refcounts. Decref what is already there
1803 # and incref what we put in.
1804 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1805 rhs_code = rhs.result()
1806 code.putln("%s = %s;" % (ptr, ptrexpr))
1807 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1808 ptr, rhs_code
1809 ))
1810 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1811 code.funcstate.release_temp(ptr)
1812 else:
1813 # Simple case
1814 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1816 def generate_assignment_code(self, rhs, code):
1817 self.generate_subexpr_evaluation_code(code)
1818 if self.is_buffer_access:
1819 self.generate_buffer_setitem_code(rhs, code)
1820 elif self.type.is_pyobject:
1821 self.generate_setitem_code(rhs.py_result(), code)
1822 else:
1823 code.putln(
1824 "%s = %s;" % (
1825 self.result(), rhs.result()))
1826 self.generate_subexpr_disposal_code(code)
1827 self.free_subexpr_temps(code)
1828 rhs.generate_disposal_code(code)
1829 rhs.free_temps(code)
1831 def generate_deletion_code(self, code):
1832 self.generate_subexpr_evaluation_code(code)
1833 #if self.type.is_pyobject:
1834 if self.index.type.is_int:
1835 function = "__Pyx_DelItemInt"
1836 index_code = self.index.result()
1837 code.globalstate.use_utility_code(delitem_int_utility_code)
1838 else:
1839 index_code = self.index.py_result()
1840 if self.base.type is dict_type:
1841 function = "PyDict_DelItem"
1842 else:
1843 function = "PyObject_DelItem"
1844 code.putln(
1845 "if (%s(%s, %s%s) < 0) %s" % (
1846 function,
1847 self.base.py_result(),
1848 index_code,
1849 self.index_unsigned_parameter(),
1850 code.error_goto(self.pos)))
1851 self.generate_subexpr_disposal_code(code)
1853 def buffer_lookup_code(self, code):
1854 # Assign indices to temps
1855 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1856 for temp, index in zip(index_temps, self.indices):
1857 code.putln("%s = %s;" % (temp, index.result()))
1858 # Generate buffer access code using these temps
1859 import Buffer
1860 # The above could happen because child_attrs is wrong somewhere so that
1861 # options are not propagated.
1862 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1863 index_signeds=[i.type.signed for i in self.indices],
1864 index_cnames=index_temps,
1865 options=code.globalstate.directives,
1866 pos=self.pos, code=code)
1868 def put_nonecheck(self, code):
1869 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1870 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1871 code.putln("__Pyx_RaiseNoneIndexingError();")
1872 code.putln(code.error_goto(self.pos))
1873 code.putln("}")
1875 class SliceIndexNode(ExprNode):
1876 # 2-element slice indexing
1878 # base ExprNode
1879 # start ExprNode or None
1880 # stop ExprNode or None
1882 subexprs = ['base', 'start', 'stop']
1884 def compile_time_value(self, denv):
1885 base = self.base.compile_time_value(denv)
1886 if self.start is None:
1887 start = 0
1888 else:
1889 start = self.start.compile_time_value(denv)
1890 if self.stop is None:
1891 stop = None
1892 else:
1893 stop = self.stop.compile_time_value(denv)
1894 try:
1895 return base[start:stop]
1896 except Exception, e:
1897 self.compile_time_value_error(e)
1899 def analyse_target_declaration(self, env):
1900 pass
1902 def analyse_types(self, env):
1903 self.base.analyse_types(env)
1904 if self.start:
1905 self.start.analyse_types(env)
1906 if self.stop:
1907 self.stop.analyse_types(env)
1908 if self.base.type.is_array or self.base.type.is_ptr:
1909 # we need a ptr type here instead of an array type, as
1910 # array types can result in invalid type casts in the C
1911 # code
1912 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
1913 else:
1914 self.base = self.base.coerce_to_pyobject(env)
1915 self.type = py_object_type
1916 c_int = PyrexTypes.c_py_ssize_t_type
1917 if self.start:
1918 self.start = self.start.coerce_to(c_int, env)
1919 if self.stop:
1920 self.stop = self.stop.coerce_to(c_int, env)
1921 self.gil_check(env)
1922 self.is_temp = 1
1924 gil_message = "Slicing Python object"
1926 def generate_result_code(self, code):
1927 if not self.type.is_pyobject:
1928 error(self.pos,
1929 "Slicing is not currently supported for '%s'." % self.type)
1930 return
1931 code.putln(
1932 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1933 self.result(),
1934 self.base.py_result(),
1935 self.start_code(),
1936 self.stop_code(),
1937 code.error_goto_if_null(self.result(), self.pos)))
1939 def generate_assignment_code(self, rhs, code):
1940 self.generate_subexpr_evaluation_code(code)
1941 if self.type.is_pyobject:
1942 code.put_error_if_neg(self.pos,
1943 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1944 self.base.py_result(),
1945 self.start_code(),
1946 self.stop_code(),
1947 rhs.result()))
1948 else:
1949 start_offset = ''
1950 if self.start:
1951 start_offset = self.start_code()
1952 if start_offset == '0':
1953 start_offset = ''
1954 else:
1955 start_offset += '+'
1956 if rhs.type.is_array:
1957 array_length = rhs.type.size
1958 self.generate_slice_guard_code(code, array_length)
1959 else:
1960 error("Slice assignments from pointers are not yet supported.")
1961 # FIXME: fix the array size according to start/stop
1962 array_length = self.base.type.size
1963 for i in range(array_length):
1964 code.putln("%s[%s%s] = %s[%d];" % (
1965 self.base.result(), start_offset, i,
1966 rhs.result(), i))
1967 self.generate_subexpr_disposal_code(code)
1968 rhs.generate_disposal_code(code)
1969 rhs.free_temps(code)
1971 def generate_deletion_code(self, code):
1972 if not self.type.is_pyobject:
1973 error(self.pos,
1974 "Deleting slices is only supported for Python types, not '%s'." % self.type)
1975 return
1976 self.generate_subexpr_evaluation_code(code)
1977 code.put_error_if_neg(self.pos,
1978 "PySequence_DelSlice(%s, %s, %s)" % (
1979 self.base.py_result(),
1980 self.start_code(),
1981 self.stop_code()))
1982 self.generate_subexpr_disposal_code(code)
1984 def generate_slice_guard_code(self, code, target_size):
1985 if not self.base.type.is_array:
1986 return
1987 slice_size = self.base.type.size
1988 start = stop = None
1989 if self.stop:
1990 stop = self.stop.result()
1991 try:
1992 stop = int(stop)
1993 if stop < 0:
1994 slice_size = self.base.type.size + stop
1995 else:
1996 slice_size = stop
1997 stop = None
1998 except ValueError:
1999 pass
2000 if self.start:
2001 start = self.start.result()
2002 try:
2003 start = int(start)
2004 if start < 0:
2005 start = self.base.type.size + start
2006 slice_size -= start
2007 start = None
2008 except ValueError:
2009 pass
2010 check = None
2011 if slice_size < 0:
2012 if target_size > 0:
2013 error(self.pos, "Assignment to empty slice.")
2014 elif start is None and stop is None:
2015 # we know the exact slice length
2016 if target_size != slice_size:
2017 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2018 slice_size, target_size))
2019 elif start is not None:
2020 if stop is None:
2021 stop = slice_size
2022 check = "(%s)-(%s)" % (stop, start)
2023 else: # stop is not None:
2024 check = stop
2025 if check:
2026 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2027 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2028 target_size, check))
2029 code.putln(code.error_goto(self.pos))
2030 code.putln("}")
2032 def start_code(self):
2033 if self.start:
2034 return self.start.result()
2035 else:
2036 return "0"
2038 def stop_code(self):
2039 if self.stop:
2040 return self.stop.result()
2041 elif self.base.type.is_array:
2042 return self.base.type.size
2043 else:
2044 return "PY_SSIZE_T_MAX"
2046 def calculate_result_code(self):
2047 # self.result() is not used, but this method must exist
2048 return "<unused>"
2051 class SliceNode(ExprNode):
2052 # start:stop:step in subscript list
2054 # start ExprNode
2055 # stop ExprNode
2056 # step ExprNode
2058 def compile_time_value(self, denv):
2059 start = self.start.compile_time_value(denv)
2060 if self.stop is None:
2061 stop = None
2062 else:
2063 stop = self.stop.compile_time_value(denv)
2064 if self.step is None:
2065 step = None
2066 else:
2067 step = self.step.compile_time_value(denv)
2068 try:
2069 return slice(start, stop, step)
2070 except Exception, e:
2071 self.compile_time_value_error(e)
2073 subexprs = ['start', 'stop', 'step']
2075 def analyse_types(self, env):
2076 self.start.analyse_types(env)
2077 self.stop.analyse_types(env)
2078 self.step.analyse_types(env)
2079 self.start = self.start.coerce_to_pyobject(env)
2080 self.stop = self.stop.coerce_to_pyobject(env)
2081 self.step = self.step.coerce_to_pyobject(env)
2082 self.type = py_object_type
2083 self.gil_check(env)
2084 self.is_temp = 1
2086 gil_message = "Constructing Python slice object"
2088 def generate_result_code(self, code):
2089 code.putln(
2090 "%s = PySlice_New(%s, %s, %s); %s" % (
2091 self.result(),
2092 self.start.py_result(),
2093 self.stop.py_result(),
2094 self.step.py_result(),
2095 code.error_goto_if_null(self.result(), self.pos)))
2098 class CallNode(NewTempExprNode):
2099 def gil_check(self, env):
2100 # Make sure we're not in a nogil environment
2101 if env.nogil:
2102 error(self.pos, "Calling gil-requiring function without gil")
2104 def analyse_as_type_constructor(self, env):
2105 type = self.function.analyse_as_type(env)
2106 if type and type.is_struct_or_union:
2107 args, kwds = self.explicit_args_kwds()
2108 items = []
2109 for arg, member in zip(args, type.scope.var_entries):
2110 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2111 if kwds:
2112 items += kwds.key_value_pairs
2113 self.key_value_pairs = items
2114 self.__class__ = DictNode
2115 self.analyse_types(env)
2116 self.coerce_to(type, env)
2117 return True
2120 class SimpleCallNode(CallNode):
2121 # Function call without keyword, * or ** args.
2123 # function ExprNode
2124 # args [ExprNode]
2125 # arg_tuple ExprNode or None used internally
2126 # self ExprNode or None used internally
2127 # coerced_self ExprNode or None used internally
2128 # wrapper_call bool used internally
2129 # has_optional_args bool used internally
2131 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2133 self = None
2134 coerced_self = None
2135 arg_tuple = None
2136 wrapper_call = False
2137 has_optional_args = False
2139 def compile_time_value(self, denv):
2140 function = self.function.compile_time_value(denv)
2141 args = [arg.compile_time_value(denv) for arg in self.args]
2142 try:
2143 return function(*args)
2144 except Exception, e:
2145 self.compile_time_value_error(e)
2147 def analyse_as_type(self, env):
2148 attr = self.function.as_cython_attribute()
2149 if attr == 'pointer':
2150 if len(self.args) != 1:
2151 error(self.args.pos, "only one type allowed.")
2152 else:
2153 type = self.args[0].analyse_as_type(env)
2154 if not type:
2155 error(self.args[0].pos, "Unknown type")
2156 else:
2157 return PyrexTypes.CPtrType(type)
2159 def explicit_args_kwds(self):
2160 return self.args, None
2162 def analyse_types(self, env):
2163 if self.analyse_as_type_constructor(env):
2164 return
2165 function = self.function
2166 function.is_called = 1
2167 self.function.analyse_types(env)
2168 if function.is_attribute and function.is_py_attr and \
2169 function.attribute == "append" and len(self.args) == 1:
2170 # L.append(x) is almost always applied to a list
2171 self.py_func = self.function
2172 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2173 self.function.analyse_types(env)
2174 self.self = self.py_func.obj
2175 function.obj = CloneNode(self.self)
2176 env.use_utility_code(append_utility_code)
2177 if function.is_attribute and function.entry and function.entry.is_cmethod:
2178 # Take ownership of the object from which the attribute
2179 # was obtained, because we need to pass it as 'self'.
2180 self.self = function.obj
2181 function.obj = CloneNode(self.self)
2182 func_type = self.function_type()
2183 if func_type.is_pyobject:
2184 self.arg_tuple = TupleNode(self.pos, args = self.args)
2185 self.arg_tuple.analyse_types(env)
2186 self.args = None
2187 self.type = py_object_type
2188 self.gil_check(env)
2189 self.is_temp = 1
2190 else:
2191 for arg in self.args:
2192 arg.analyse_types(env)
2193 if self.self and func_type.args:
2194 # Coerce 'self' to the type expected by the method.
2195 expected_type = func_type.args[0].type
2196 self.coerced_self = CloneNode(self.self).coerce_to(
2197 expected_type, env)
2198 # Insert coerced 'self' argument into argument list.
2199 self.args.insert(0, self.coerced_self)
2200 self.analyse_c_function_call(env)
2202 def function_type(self):
2203 # Return the type of the function being called, coercing a function
2204 # pointer to a function if necessary.
2205 func_type = self.function.type
2206 if func_type.is_ptr:
2207 func_type = func_type.base_type
2208 return func_type
2210 def analyse_c_function_call(self, env):
2211 func_type = self.function_type()
2212 # Check function type
2213 if not func_type.is_cfunction:
2214 if not func_type.is_error:
2215 error(self.pos, "Calling non-function type '%s'" %
2216 func_type)
2217 self.type = PyrexTypes.error_type
2218 self.result_code = "<error>"
2219 return
2220 # Check no. of args
2221 max_nargs = len(func_type.args)
2222 expected_nargs = max_nargs - func_type.optional_arg_count
2223 actual_nargs = len(self.args)
2224 if actual_nargs < expected_nargs \
2225 or (not func_type.has_varargs and actual_nargs > max_nargs):
2226 expected_str = str(expected_nargs)
2227 if func_type.has_varargs:
2228 expected_str = "at least " + expected_str
2229 elif func_type.optional_arg_count:
2230 if actual_nargs < max_nargs:
2231 expected_str = "at least " + expected_str
2232 else:
2233 expected_str = "at most " + str(max_nargs)
2234 error(self.pos,
2235 "Call with wrong number of arguments (expected %s, got %s)"
2236 % (expected_str, actual_nargs))
2237 self.args = None
2238 self.type = PyrexTypes.error_type
2239 self.result_code = "<error>"
2240 return
2241 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2242 self.has_optional_args = 1
2243 self.is_temp = 1
2244 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2245 env.release_temp(self.opt_arg_struct)
2246 # Coerce arguments
2247 for i in range(min(max_nargs, actual_nargs)):
2248 formal_type = func_type.args[i].type
2249 self.args[i] = self.args[i].coerce_to(formal_type, env)
2250 for i in range(max_nargs, actual_nargs):
2251 if self.args[i].type.is_pyobject:
2252 error(self.args[i].pos,
2253 "Python object cannot be passed as a varargs parameter")
2254 # Calc result type and code fragment
2255 self.type = func_type.return_type
2256 if self.type.is_pyobject \
2257 or func_type.exception_value is not None \
2258 or func_type.exception_check:
2259 self.is_temp = 1
2260 if self.type.is_pyobject:
2261 self.result_ctype = py_object_type
2262 # C++ exception handler
2263 if func_type.exception_check == '+':
2264 if func_type.exception_value is None:
2265 env.use_utility_code(cpp_exception_utility_code)
2266 # Check gil
2267 if not func_type.nogil:
2268 self.gil_check(env)
2270 def calculate_result_code(self):
2271 return self.c_call_code()
2273 def c_call_code(self):
2274 func_type = self.function_type()
2275 if self.args is None or not func_type.is_cfunction:
2276 return "<error>"
2277 formal_args = func_type.args
2278 arg_list_code = []
2279 args = zip(formal_args, self.args)
2280 max_nargs = len(func_type.args)
2281 expected_nargs = max_nargs - func_type.optional_arg_count
2282 actual_nargs = len(self.args)
2283 for formal_arg, actual_arg in args[:expected_nargs]:
2284 arg_code = actual_arg.result_as(formal_arg.type)
2285 arg_list_code.append(arg_code)
2287 if func_type.is_overridable:
2288 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2290 if func_type.optional_arg_count:
2291 if expected_nargs == actual_nargs:
2292 optional_args = 'NULL'
2293 else:
2294 optional_args = "&%s" % self.opt_arg_struct
2295 arg_list_code.append(optional_args)
2297 for actual_arg in self.args[len(formal_args):]:
2298 arg_list_code.append(actual_arg.result())
2299 result = "%s(%s)" % (self.function.result(),
2300 ', '.join(arg_list_code))
2301 # if self.wrapper_call or \
2302 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2303 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2304 return result
2306 def generate_result_code(self, code):
2307 func_type = self.function_type()
2308 if func_type.is_pyobject:
2309 arg_code = self.arg_tuple.py_result()
2310 code.putln(
2311 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2312 self.result(),
2313 self.function.py_result(),
2314 arg_code,
2315 code.error_goto_if_null(self.result(), self.pos)))
2316 elif func_type.is_cfunction:
2317 if self.has_optional_args:
2318 actual_nargs = len(self.args)
2319 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2320 code.putln("%s.%s = %s;" % (
2321 self.opt_arg_struct,
2322 Naming.pyrex_prefix + "n",
2323 len(self.args) - expected_nargs))
2324 args = zip(func_type.args, self.args)
2325 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2326 code.putln("%s.%s = %s;" % (
2327 self.opt_arg_struct,
2328 formal_arg.name,
2329 actual_arg.result_as(formal_arg.type)))
2330 exc_checks = []
2331 if self.type.is_pyobject:
2332 exc_checks.append("!%s" % self.result())
2333 else:
2334 exc_val = func_type.exception_value
2335 exc_check = func_type.exception_check
2336 if exc_val is not None:
2337 exc_checks.append("%s == %s" % (self.result(), exc_val))
2338 if exc_check:
2339 exc_checks.append("PyErr_Occurred()")
2340 if self.is_temp or exc_checks:
2341 rhs = self.c_call_code()
2342 if self.result():
2343 lhs = "%s = " % self.result()
2344 if self.is_temp and self.type.is_pyobject:
2345 #return_type = self.type # func_type.return_type
2346 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2347 # "from", return_type, "to pyobject" ###
2348 rhs = typecast(py_object_type, self.type, rhs)
2349 else:
2350 lhs = ""
2351 if func_type.exception_check == '+':
2352 if func_type.exception_value is None:
2353 raise_py_exception = "__Pyx_CppExn2PyErr()"
2354 elif func_type.exception_value.type.is_pyobject:
2355 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2356 else:
2357 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2358 code.putln(
2359 "try {%s%s;} catch(...) {%s; %s}" % (
2360 lhs,
2361 rhs,
2362 raise_py_exception,
2363 code.error_goto(self.pos)))
2364 else:
2365 if exc_checks:
2366 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2367 else:
2368 goto_error = ""
2369 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2371 class GeneralCallNode(CallNode):
2372 # General Python function call, including keyword,
2373 # * and ** arguments.
2375 # function ExprNode
2376 # positional_args ExprNode Tuple of positional arguments
2377 # keyword_args ExprNode or None Dict of keyword arguments
2378 # starstar_arg ExprNode or None Dict of extra keyword args
2380 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2382 def compile_time_value(self, denv):
2383 function = self.function.compile_time_value(denv)
2384 positional_args = self.positional_args.compile_time_value(denv)
2385 keyword_args = self.keyword_args.compile_time_value(denv)
2386 starstar_arg = self.starstar_arg.compile_time_value(denv)
2387 try:
2388 keyword_args.update(starstar_arg)
2389 return function(*positional_args, **keyword_args)
2390 except Exception, e:
2391 self.compile_time_value_error(e)
2393 def explicit_args_kwds(self):
2394 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2395 raise PostParseError(self.pos,
2396 'Compile-time keyword arguments must be explicit.')
2397 return self.positional_args.args, self.keyword_args
2399 def analyse_types(self, env):
2400 if self.analyse_as_type_constructor(env):
2401 return
2402 self.function.analyse_types(env)
2403 self.positional_args.analyse_types(env)
2404 if self.keyword_args:
2405 self.keyword_args.analyse_types(env)
2406 if self.starstar_arg:
2407 self.starstar_arg.analyse_types(env)
2408 self.function = self.function.coerce_to_pyobject(env)
2409 self.positional_args = \
2410 self.positional_args.coerce_to_pyobject(env)
2411 if self.starstar_arg:
2412 self.starstar_arg = \
2413 self.starstar_arg.coerce_to_pyobject(env)
2414 self.type = py_object_type
2415 self.gil_check(env)
2416 self.is_temp = 1
2418 def generate_result_code(self, code):
2419 if self.keyword_args and self.starstar_arg:
2420 code.put_error_if_neg(self.pos,
2421 "PyDict_Update(%s, %s)" % (
2422 self.keyword_args.py_result(),
2423 self.starstar_arg.py_result()))
2424 keyword_code = self.keyword_args.py_result()
2425 elif self.keyword_args:
2426 keyword_code = self.keyword_args.py_result()
2427 elif self.starstar_arg:
2428 keyword_code = self.starstar_arg.py_result()
2429 else:
2430 keyword_code = None
2431 if not keyword_code:
2432 call_code = "PyObject_Call(%s, %s, NULL)" % (
2433 self.function.py_result(),
2434 self.positional_args.py_result())
2435 else:
2436 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2437 self.function.py_result(),
2438 self.positional_args.py_result(),
2439 keyword_code)
2440 code.putln(
2441 "%s = %s; %s" % (
2442 self.result(),
2443 call_code,
2444 code.error_goto_if_null(self.result(), self.pos)))
2447 class AsTupleNode(ExprNode):
2448 # Convert argument to tuple. Used for normalising
2449 # the * argument of a function call.
2451 # arg ExprNode
2453 subexprs = ['arg']
2455 def compile_time_value(self, denv):
2456 arg = self.arg.compile_time_value(denv)
2457 try:
2458 return tuple(arg)
2459 except Exception, e:
2460 self.compile_time_value_error(e)
2462 def analyse_types(self, env):
2463 self.arg.analyse_types(env)
2464 self.arg = self.arg.coerce_to_pyobject(env)
2465 self.type = tuple_type
2466 self.gil_check(env)
2467 self.is_temp = 1
2469 gil_message = "Constructing Python tuple"
2471 def generate_result_code(self, code):
2472 code.putln(
2473 "%s = PySequence_Tuple(%s); %s" % (
2474 self.result(),
2475 self.arg.py_result(),
2476 code.error_goto_if_null(self.result(), self.pos)))
2479 class AttributeNode(ExprNode):
2480 # obj.attribute
2482 # obj ExprNode
2483 # attribute string
2484 # needs_none_check boolean Used if obj is an extension type.
2485 # If set to True, it is known that the type is not None.
2487 # Used internally:
2489 # is_py_attr boolean Is a Python getattr operation
2490 # member string C name of struct member
2491 # is_called boolean Function call is being done on result
2492 # entry Entry Symbol table entry of attribute
2493 # interned_attr_cname string C name of interned attribute name
2495 is_attribute = 1
2496 subexprs = ['obj']
2498 type = PyrexTypes.error_type
2499 entry = None
2500 is_called = 0
2501 needs_none_check = True
2503 def as_cython_attribute(self):
2504 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2505 return self.attribute
2507 def coerce_to(self, dst_type, env):
2508 # If coercing to a generic pyobject and this is a cpdef function
2509 # we can create the corresponding attribute
2510 if dst_type is py_object_type:
2511 entry = self.entry
2512 if entry and entry.is_cfunction and entry.as_variable:
2513 # must be a cpdef function
2514 self.is_temp = 1
2515 self.entry = entry.as_variable
2516 self.analyse_as_python_attribute(env)
2517 return self
2518 return ExprNode.coerce_to(self, dst_type, env)
2520 def compile_time_value(self, denv):
2521 attr = self.attribute
2522 if attr.beginswith("__") and attr.endswith("__"):
2523 self.error("Invalid attribute name '%s' in compile-time expression"
2524 % attr)
2525 return None
2526 obj = self.arg.compile_time_value(denv)
2527 try:
2528 return getattr(obj, attr)
2529 except Exception, e:
2530 self.compile_time_value_error(e)
2532 def analyse_target_declaration(self, env):
2533 pass
2535 def analyse_target_types(self, env):
2536 self.analyse_types(env, target = 1)
2538 def analyse_types(self, env, target = 0):
2539 if self.analyse_as_cimported_attribute(env, target):
2540 return
2541 if not target and self.analyse_as_unbound_cmethod(env):
2542 return
2543 self.analyse_as_ordinary_attribute(env, target)
2545 def analyse_as_cimported_attribute(self, env, target):
2546 # Try to interpret this as a reference to an imported
2547 # C const, type, var or function. If successful, mutates
2548 # this node into a NameNode and returns 1, otherwise
2549 # returns 0.
2550 module_scope = self.obj.analyse_as_module(env)
2551 if module_scope:
2552 entry = module_scope.lookup_here(self.attribute)
2553 if entry and (
2554 entry.is_cglobal or entry.is_cfunction
2555 or entry.is_type or entry.is_const):
2556 self.mutate_into_name_node(env, entry, target)
2557 return 1
2558 return 0
2560 def analyse_as_unbound_cmethod(self, env):
2561 # Try to interpret this as a reference to an unbound
2562 # C method of an extension type. If successful, mutates
2563 # this node into a NameNode and returns 1, otherwise
2564 # returns 0.
2565 type = self.obj.analyse_as_extension_type(env)
2566 if type:
2567 entry = type.scope.lookup_here(self.attribute)
2568 if entry and entry.is_cmethod:
2569 # Create a temporary entry describing the C method
2570 # as an ordinary function.
2571 ubcm_entry = Symtab.Entry(entry.name,
2572 "%s->%s" % (type.vtabptr_cname, entry.cname),
2573 entry.type)
2574 ubcm_entry.is_cfunction = 1
2575 ubcm_entry.func_cname = entry.func_cname
2576 ubcm_entry.is_unbound_cmethod = 1
2577 self.mutate_into_name_node(env, ubcm_entry, None)
2578 return 1
2579 return 0
2581 def analyse_as_type(self, env):
2582 module_scope = self.obj.analyse_as_module(env)
2583 if module_scope:
2584 return module_scope.lookup_type(self.attribute)
2585 return None
2587 def analyse_as_extension_type(self, env):
2588 # Try to interpret this as a reference to an extension type
2589 # in a cimported module. Returns the extension type, or None.
2590 module_scope = self.obj.analyse_as_module(env)
2591 if module_scope:
2592 entry = module_scope.lookup_here(self.attribute)
2593 if entry and entry.is_type and entry.type.is_extension_type:
2594 return entry.type
2595 return None
2597 def analyse_as_module(self, env):
2598 # Try to interpret this as a reference to a cimported module
2599 # in another cimported module. Returns the module scope, or None.
2600 module_scope = self.obj.analyse_as_module(env)
2601 if module_scope:
2602 entry = module_scope.lookup_here(self.attribute)
2603 if entry and entry.as_module:
2604 return entry.as_module
2605 return None
2607 def mutate_into_name_node(self, env, entry, target):
2608 # Mutate this node into a NameNode and complete the
2609 # analyse_types phase.
2610 self.__class__ = NameNode
2611 self.name = self.attribute
2612 self.entry = entry
2613 del self.obj
2614 del self.attribute
2615 if target:
2616 NameNode.analyse_target_types(self, env)
2617 else:
2618 NameNode.analyse_rvalue_entry(self, env)
2620 def analyse_as_ordinary_attribute(self, env, target):
2621 self.obj.analyse_types(env)
2622 self.analyse_attribute(env)
2623 if self.entry and self.entry.is_cmethod and not self.is_called:
2624 # error(self.pos, "C method can only be called")
2625 pass
2626 ## Reference to C array turns into pointer to first element.
2627 #while self.type.is_array:
2628 # self.type = self.type.element_ptr_type()
2629 if self.is_py_attr:
2630 if not target:
2631 self.is_temp = 1
2632 self.result_ctype = py_object_type
2634 def analyse_attribute(self, env):
2635 # Look up attribute and set self.type and self.member.
2636 self.is_py_attr = 0
2637 self.member = self.attribute
2638 if self.obj.type.is_string:
2639 self.obj = self.obj.coerce_to_pyobject(env)
2640 obj_type = self.obj.type
2641 if obj_type.is_ptr or obj_type.is_array:
2642 obj_type = obj_type.base_type
2643 self.op = "->"
2644 elif obj_type.is_extension_type:
2645 self.op = "->"
2646 else:
2647 self.op = "."
2648 if obj_type.has_attributes:
2649 entry = None
2650 if obj_type.attributes_known():
2651 entry = obj_type.scope.lookup_here(self.attribute)
2652 if entry and entry.is_member:
2653 entry = None
2654 else:
2655 error(self.pos,
2656 "Cannot select attribute of incomplete type '%s'"
2657 % obj_type)
2658 self.type = PyrexTypes.error_type
2659 return
2660 self.entry = entry
2661 if entry:
2662 if obj_type.is_extension_type and entry.name == "__weakref__":
2663 error(self.pos, "Illegal use of special attribute __weakref__")
2664 # methods need the normal attribute lookup
2665 # because they do not have struct entries
2666 if entry.is_variable or entry.is_cmethod:
2667 self.type = entry.type
2668 self.member = entry.cname
2669 return
2670 else:
2671 # If it's not a variable or C method, it must be a Python
2672 # method of an extension type, so we treat it like a Python
2673 # attribute.
2674 pass
2675 # If we get here, the base object is not a struct/union/extension
2676 # type, or it is an extension type and the attribute is either not
2677 # declared or is declared as a Python method. Treat it as a Python
2678 # attribute reference.
2679 self.analyse_as_python_attribute(env)
2681 def analyse_as_python_attribute(self, env):
2682 obj_type = self.obj.type
2683 self.member = self.attribute
2684 if obj_type.is_pyobject:
2685 self.type = py_object_type
2686 self.is_py_attr = 1
2687 self.interned_attr_cname = env.intern_identifier(self.attribute)
2688 self.gil_check(env)
2689 else:
2690 if not obj_type.is_error:
2691 error(self.pos,
2692 "Object of type '%s' has no attribute '%s'" %
2693 (obj_type, self.attribute))
2695 gil_message = "Accessing Python attribute"
2697 def is_simple(self):
2698 if self.obj:
2699 return self.result_in_temp() or self.obj.is_simple()
2700 else:
2701 return NameNode.is_simple(self)
2703 def is_lvalue(self):
2704 if self.obj:
2705 return 1
2706 else:
2707 return NameNode.is_lvalue(self)
2709 def is_ephemeral(self):
2710 if self.obj:
2711 return self.obj.is_ephemeral()
2712 else:
2713 return NameNode.is_ephemeral(self)
2715 def calculate_result_code(self):
2716 #print "AttributeNode.calculate_result_code:", self.member ###
2717 #print "...obj node =", self.obj, "code", self.obj.result() ###
2718 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2719 obj = self.obj
2720 obj_code = obj.result_as(obj.type)
2721 #print "...obj_code =", obj_code ###
2722 if self.entry and self.entry.is_cmethod:
2723 if obj.type.is_extension_type:
2724 return "((struct %s *)%s%s%s)->%s" % (
2725 obj.type.vtabstruct_cname, obj_code, self.op,
2726 obj.type.vtabslot_cname, self.member)
2727 else:
2728 return self.member
2729 else:
2730 return "%s%s%s" % (obj_code, self.op, self.member)
2732 def generate_result_code(self, code):
2733 if self.is_py_attr:
2734 code.putln(
2735 '%s = PyObject_GetAttr(%s, %s); %s' % (
2736 self.result(),
2737 self.obj.py_result(),
2738 self.interned_attr_cname,
2739 code.error_goto_if_null(self.result(), self.pos)))
2740 else:
2741 # result_code contains what is needed, but we may need to insert
2742 # a check and raise an exception
2743 if (self.obj.type.is_extension_type
2744 and self.needs_none_check
2745 and code.globalstate.directives['nonecheck']):
2746 self.put_nonecheck(code)
2748 def generate_assignment_code(self, rhs, code):
2749 self.obj.generate_evaluation_code(code)
2750 if self.is_py_attr:
2751 code.put_error_if_neg(self.pos,
2752 'PyObject_SetAttr(%s, %s, %s)' % (
2753 self.obj.py_result(),
2754 self.interned_attr_cname,
2755 rhs.py_result()))
2756 rhs.generate_disposal_code(code)
2757 rhs.free_temps(code)
2758 else:
2759 if (self.obj.type.is_extension_type
2760 and self.needs_none_check
2761 and code.globalstate.directives['nonecheck']):
2762 self.put_nonecheck(code)
2764 select_code = self.result()
2765 if self.type.is_pyobject:
2766 rhs.make_owned_reference(code)
2767 code.put_decref(select_code, self.ctype())
2768 code.putln(
2769 "%s = %s;" % (
2770 select_code,
2771 rhs.result_as(self.ctype())))
2772 #rhs.result()))
2773 rhs.generate_post_assignment_code(code)
2774 rhs.free_temps(code)
2775 self.obj.generate_disposal_code(code)
2776 self.obj.free_temps(code)
2778 def generate_deletion_code(self, code):
2779 self.obj.generate_evaluation_code(code)
2780 if self.is_py_attr:
2781 code.put_error_if_neg(self.pos,
2782 'PyObject_DelAttr(%s, %s)' % (
2783 self.obj.py_result(),
2784 self.interned_attr_cname))
2785 else:
2786 error(self.pos, "Cannot delete C attribute of extension type")
2787 self.obj.generate_disposal_code(code)
2788 self.obj.free_temps(code)
2790 def annotate(self, code):
2791 if self.is_py_attr:
2792 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2793 else:
2794 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2796 def put_nonecheck(self, code):
2797 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2798 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2799 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2800 code.putln(code.error_goto(self.pos))
2801 code.putln("}")
2804 #-------------------------------------------------------------------
2806 # Constructor nodes
2808 #-------------------------------------------------------------------
2810 class SequenceNode(NewTempExprNode):
2811 # Base class for list and tuple constructor nodes.
2812 # Contains common code for performing sequence unpacking.
2814 # args [ExprNode]
2815 # iterator ExprNode
2816 # unpacked_items [ExprNode] or None
2817 # coerced_unpacked_items [ExprNode] or None
2819 subexprs = ['args']
2821 is_sequence_constructor = 1
2822 unpacked_items = None
2824 def compile_time_value_list(self, denv):
2825 return [arg.compile_time_value(denv) for arg in self.args]
2827 def analyse_target_declaration(self, env):
2828 for arg in self.args:
2829 arg.analyse_target_declaration(env)
2831 def analyse_types(self, env, skip_children=False):
2832 for i in range(len(self.args)):
2833 arg = self.args[i]
2834 if not skip_children: arg.analyse_types(env)
2835 self.args[i] = arg.coerce_to_pyobject(env)
2836 self.type = py_object_type
2837 self.gil_check(env)
2838 self.is_temp = 1
2840 def analyse_target_types(self, env):
2841 self.iterator = PyTempNode(self.pos, env)
2842 self.unpacked_items = []
2843 self.coerced_unpacked_items = []
2844 for arg in self.args:
2845 arg.analyse_target_types(env)
2846 unpacked_item = PyTempNode(self.pos, env)
2847 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2848 self.unpacked_items.append(unpacked_item)
2849 self.coerced_unpacked_items.append(coerced_unpacked_item)
2850 self.type = py_object_type
2851 env.use_utility_code(unpacking_utility_code)
2853 def allocate_target_temps(self, env, rhs):
2854 self.iterator.allocate_temps(env)
2855 for arg, node in zip(self.args, self.coerced_unpacked_items):
2856 node.allocate_temps(env)
2857 arg.allocate_target_temps(env, None)
2858 #arg.release_target_temp(env)
2859 #node.release_temp(env)
2860 if rhs:
2861 rhs.release_temp(env)
2862 self.iterator.release_temp(env)
2863 for node in self.coerced_unpacked_items:
2864 node.release_temp(env)
2866 # def release_target_temp(self, env):
2867 # #for arg in self.args:
2868 # # arg.release_target_temp(env)
2869 # #for node in self.coerced_unpacked_items:
2870 # # node.release_temp(env)
2871 # self.iterator.release_temp(env)
2873 def generate_result_code(self, code):
2874 self.generate_operation_code(code)
2876 def generate_assignment_code(self, rhs, code):
2877 # Need to work around the fact that generate_evaluation_code
2878 # allocates the temps in a rather hacky way -- the assignment
2879 # is evaluated twice, within each if-block.
2881 code.putln(
2882 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2883 rhs.py_result(),
2884 rhs.py_result(),
2885 len(self.args)))
2886 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2887 for i in range(len(self.args)):
2888 item = self.unpacked_items[i]
2889 code.put(
2890 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
2891 item.result(),
2892 i))
2893 code.put_incref(item.result(), item.ctype())
2894 value_node = self.coerced_unpacked_items[i]
2895 value_node.generate_evaluation_code(code)
2896 rhs.generate_disposal_code(code)
2898 for i in range(len(self.args)):
2899 self.args[i].generate_assignment_code(
2900 self.coerced_unpacked_items[i], code)
2902 code.putln("} else {")
2904 code.putln(
2905 "%s = PyObject_GetIter(%s); %s" % (
2906 self.iterator.result(),
2907 rhs.py_result(),
2908 code.error_goto_if_null(self.iterator.result(), self.pos)))
2909 rhs.generate_disposal_code(code)
2910 for i in range(len(self.args)):
2911 item = self.unpacked_items[i]
2912 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2913 self.iterator.py_result(), i)
2914 code.putln(
2915 "%s = %s; %s" % (
2916 item.result(),
2917 typecast(item.ctype(), py_object_type, unpack_code),
2918 code.error_goto_if_null(item.result(), self.pos)))
2919 value_node = self.coerced_unpacked_items[i]
2920 value_node.generate_evaluation_code(code)
2921 code.put_error_if_neg(self.pos,
2922 "__Pyx_EndUnpack(%s)" % (
2923 self.iterator.py_result()))
2924 if debug_disposal_code:
2925 print("UnpackNode.generate_assignment_code:")
2926 print("...generating disposal code for %s" % self.iterator)
2927 self.iterator.generate_disposal_code(code)
2928 self.iterator.free_temps(code)
2930 for i in range(len(self.args)):
2931 self.args[i].generate_assignment_code(
2932 self.coerced_unpacked_items[i], code)
2933 code.putln("}")
2934 rhs.free_temps(code)
2936 def annotate(self, code):
2937 for arg in self.args:
2938 arg.annotate(code)
2939 if self.unpacked_items:
2940 for arg in self.unpacked_items:
2941 arg.annotate(code)
2942 for arg in self.coerced_unpacked_items:
2943 arg.annotate(code)
2946 class TupleNode(SequenceNode):
2947 # Tuple constructor.
2949 gil_message = "Constructing Python tuple"
2951 def analyse_types(self, env, skip_children=False):
2952 if len(self.args) == 0:
2953 self.is_temp = 0
2954 self.is_literal = 1
2955 else:
2956 SequenceNode.analyse_types(self, env, skip_children)
2957 self.type = tuple_type
2959 def calculate_result_code(self):
2960 if len(self.args) > 0:
2961 error(self.pos, "Positive length tuples must be constructed.")
2962 else:
2963 return Naming.empty_tuple
2965 def compile_time_value(self, denv):
2966 values = self.compile_time_value_list(denv)
2967 try:
2968 return tuple(values)
2969 except Exception, e:
2970 self.compile_time_value_error(e)
2972 def generate_operation_code(self, code):
2973 if len(self.args) == 0:
2974 # result_code is Naming.empty_tuple
2975 return
2976 code.putln(
2977 "%s = PyTuple_New(%s); %s" % (
2978 self.result(),
2979 len(self.args),
2980 code.error_goto_if_null(self.result(), self.pos)))
2981 for i in range(len(self.args)):
2982 arg = self.args[i]
2983 if not arg.result_in_temp():
2984 code.put_incref(arg.result(), arg.ctype())
2985 code.putln(
2986 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2987 self.result(),
2988 i,
2989 arg.py_result()))
2991 def generate_subexpr_disposal_code(self, code):
2992 # We call generate_post_assignment_code here instead
2993 # of generate_disposal_code, because values were stored
2994 # in the tuple using a reference-stealing operation.
2995 for arg in self.args:
2996 arg.generate_post_assignment_code(code)
2997 # Should NOT call free_temps -- this is invoked by the default
2998 # generate_evaluation_code which will do that.
3001 class ListNode(SequenceNode):
3002 # List constructor.
3004 # obj_conversion_errors [PyrexError] used internally
3005 # orignial_args [ExprNode] used internally
3007 gil_message = "Constructing Python list"
3009 def analyse_expressions(self, env):
3010 SequenceNode.analyse_expressions(self, env)
3011 self.coerce_to_pyobject(env)
3013 def analyse_types(self, env):
3014 hold_errors()
3015 self.original_args = list(self.args)
3016 SequenceNode.analyse_types(self, env)
3017 self.type = list_type
3018 self.obj_conversion_errors = held_errors()
3019 release_errors(ignore=True)
3021 def coerce_to(self, dst_type, env):
3022 if dst_type.is_pyobject:
3023 for err in self.obj_conversion_errors:
3024 report_error(err)
3025 self.obj_conversion_errors = []
3026 if not self.type.subtype_of(dst_type):
3027 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3028 elif dst_type.is_ptr:
3029 base_type = dst_type.base_type
3030 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3031 for i in range(len(self.original_args)):
3032 arg = self.args[i]
3033 if isinstance(arg, CoerceToPyTypeNode):
3034 arg = arg.arg
3035 self.args[i] = arg.coerce_to(base_type, env)
3036 elif dst_type.is_struct:
3037 if len(self.args) > len(dst_type.scope.var_entries):
3038 error(self.pos, "Too may members for '%s'" % dst_type)
3039 else:
3040 if len(self.args) < len(dst_type.scope.var_entries):
3041 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3042 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3043 if isinstance(arg, CoerceToPyTypeNode):
3044 arg = arg.arg
3045 self.args[i] = arg.coerce_to(member.type, env)
3046 self.type = dst_type
3047 else:
3048 self.type = error_type
3049 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3050 return self
3052 def release_temp(self, env):
3053 if self.type.is_array:
3054 # To be valid C++, we must allocate the memory on the stack
3055 # manually and be sure not to reuse it for something else.
3056 pass
3057 else:
3058 SequenceNode.release_temp(self, env)
3060 def compile_time_value(self, denv):
3061 return self.compile_time_value_list(denv)
3063 def generate_operation_code(self, code):
3064 if self.type.is_pyobject:
3065 for err in self.obj_conversion_errors:
3066 report_error(err)
3067 code.putln("%s = PyList_New(%s); %s" %
3068 (self.result(),
3069 len(self.args),
3070 code.error_goto_if_null(self.result(), self.pos)))
3071 for i in range(len(self.args)):
3072 arg = self.args[i]
3073 #if not arg.is_temp:
3074 if not arg.result_in_temp():
3075 code.put_incref(arg.result(), arg.ctype())
3076 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3077 (self.result(),
3078 i,
3079 arg.py_result()))
3080 elif self.type.is_array:
3081 for i, arg in enumerate(self.args):
3082 code.putln("%s[%s] = %s;" % (
3083 self.result(),
3084 i,
3085 arg.result()))
3086 elif self.type.is_struct:
3087 for arg, member in zip(self.args, self.type.scope.var_entries):
3088 code.putln("%s.%s = %s;" % (
3089 self.result(),
3090 member.cname,
3091 arg.result()))
3092 else:
3093 raise InternalError("List type never specified")
3095 def generate_subexpr_disposal_code(self, code):
3096 # We call generate_post_assignment_code here instead
3097 # of generate_disposal_code, because values were stored
3098 # in the list using a reference-stealing operation.
3099 for arg in self.args:
3100 arg.generate_post_assignment_code(code)
3101 # Should NOT call free_temps -- this is invoked by the default
3102 # generate_evaluation_code which will do that.
3105 class ComprehensionNode(SequenceNode):
3106 subexprs = []
3107 is_sequence_constructor = 0 # not unpackable
3108 comp_result_type = py_object_type
3110 child_attrs = ["loop", "append"]
3112 def analyse_types(self, env):
3113 self.type = self.comp_result_type
3114 self.is_temp = 1
3115 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3117 def allocate_temps(self, env, result = None):
3118 if debug_temp_alloc:
3119 print("%s Allocating temps" % self)
3120 self.allocate_temp(env, result)
3121 self.loop.analyse_declarations(env)
3122 self.loop.analyse_expressions(env)
3124 def generate_operation_code(self, code):
3125 code.putln("%s = PyList_New(%s); %s" %
3126 (self.result(),
3127 0,
3128 code.error_goto_if_null(self.result(), self.pos)))
3129 self.loop.generate_execution_code(code)
3131 def annotate(self, code):
3132 self.loop.annotate(code)
3135 class ListComprehensionNode(ComprehensionNode):
3136 comp_result_type = list_type
3138 def generate_operation_code(self, code):
3139 code.putln("%s = PyList_New(%s); %s" %
3140 (self.result(),
3141 0,
3142 code.error_goto_if_null(self.result(), self.pos)))
3143 self.loop.generate_execution_code(code)
3145 class SetComprehensionNode(ComprehensionNode):
3146 comp_result_type = set_type
3148 def generate_operation_code(self, code):
3149 code.putln("%s = PySet_New(0); %s" % # arg == iterable, not size!
3150 (self.result(),
3151 code.error_goto_if_null(self.result(), self.pos)))
3152 self.loop.generate_execution_code(code)
3154 class DictComprehensionNode(ComprehensionNode):
3155 comp_result_type = dict_type
3157 def generate_operation_code(self, code):
3158 code.putln("%s = PyDict_New(); %s" %
3159 (self.result(),
3160 code.error_goto_if_null(self.result(), self.pos)))
3161 self.loop.generate_execution_code(code)
3164 class ComprehensionAppendNode(NewTempExprNode):
3165 # Need to be careful to avoid infinite recursion:
3166 # target must not be in child_attrs/subexprs
3167 subexprs = ['expr']
3169 def analyse_types(self, env):
3170 self.expr.analyse_types(env)
3171 if not self.expr.type.is_pyobject:
3172 self.expr = self.expr.coerce_to_pyobject(env)
3173 self.type = PyrexTypes.c_int_type
3174 self.is_temp = 1
3176 class ListComprehensionAppendNode(ComprehensionAppendNode):
3177 def generate_result_code(self, code):
3178 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
3179 (self.result(),
3180 self.target.result(),
3181 self.expr.result(),
3182 code.error_goto_if(self.result(), self.pos)))
3184 class SetComprehensionAppendNode(ComprehensionAppendNode):
3185 def generate_result_code(self, code):
3186 code.putln("%s = PySet_Add(%s, (PyObject*)%s); %s" %
3187 (self.result(),
3188 self.target.result(),
3189 self.expr.result(),
3190 code.error_goto_if(self.result(), self.pos)))
3192 class DictComprehensionAppendNode(ComprehensionAppendNode):
3193 subexprs = ['key_expr', 'value_expr']
3195 def analyse_types(self, env):
3196 self.key_expr.analyse_types(env)
3197 if not self.key_expr.type.is_pyobject:
3198 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3199 self.value_expr.analyse_types(env)
3200 if not self.value_expr.type.is_pyobject:
3201 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3202 self.type = PyrexTypes.c_int_type
3203 self.is_temp = 1
3205 def generate_result_code(self, code):
3206 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3207 (self.result(),
3208 self.target.result(),
3209 self.key_expr.result(),
3210 self.value_expr.result(),
3211 code.error_goto_if(self.result(), self.pos)))
3214 class SetNode(NewTempExprNode):
3215 # Set constructor.
3217 subexprs = ['args']
3219 gil_message = "Constructing Python set"
3221 def analyse_types(self, env):
3222 for i in range(len(self.args)):
3223 arg = self.args[i]
3224 arg.analyse_types(env)
3225 self.args[i] = arg.coerce_to_pyobject(env)
3226 self.type = set_type
3227 self.gil_check(env)
3228 self.is_temp = 1
3230 def compile_time_value(self, denv):
3231 values = [arg.compile_time_value(denv) for arg in self.args]
3232 try:
3233 set
3234 except NameError:
3235 from sets import Set as set
3236 try:
3237 return set(values)
3238 except Exception, e:
3239 self.compile_time_value_error(e)
3241 def generate_evaluation_code(self, code):
3242 self.allocate_temp_result(code)
3243 code.putln(
3244 "%s = PySet_New(0); %s" % (
3245 self.result(),
3246 code.error_goto_if_null(self.result(), self.pos)))
3247 for arg in self.args:
3248 arg.generate_evaluation_code(code)
3249 code.putln(
3250 code.error_goto_if_neg(
3251 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3252 self.pos))
3253 arg.generate_disposal_code(code)
3254 arg.free_temps(code)
3257 class DictNode(ExprNode):
3258 # Dictionary constructor.
3260 # key_value_pairs [DictItemNode]
3262 # obj_conversion_errors [PyrexError] used internally
3264 subexprs = ['key_value_pairs']
3266 def compile_time_value(self, denv):
3267 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3268 for item in self.key_value_pairs]
3269 try:
3270 return dict(pairs)
3271 except Exception, e:
3272 self.compile_time_value_error(e)
3274 def analyse_types(self, env):
3275 hold_errors()
3276 self.type = dict_type
3277 for item in self.key_value_pairs:
3278 item.analyse_types(env)
3279 self.gil_check(env)
3280 self.obj_conversion_errors = held_errors()
3281 release_errors(ignore=True)
3282 self.is_temp = 1
3284 def coerce_to(self, dst_type, env):
3285 if dst_type.is_pyobject:
3286 self.release_errors()
3287 if not self.type.subtype_of(dst_type):
3288 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3289 elif dst_type.is_struct_or_union:
3290 self.type = dst_type
3291 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3292 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3293 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3294 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3295 for item in self.key_value_pairs:
3296 if isinstance(item.key, CoerceToPyTypeNode):
3297 item.key = item.key.arg
3298 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3299 error(item.key.pos, "Invalid struct field identifier")
3300 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3301 else:
3302 member = dst_type.scope.lookup_here(item.key.value)
3303 if not member:
3304 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3305 else:
3306 value = item.value
3307 if isinstance(value, CoerceToPyTypeNode):
3308 value = value.arg
3309 item.value = value.coerce_to(member.type, env)
3310 else:
3311 self.type = error_type
3312 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3313 return self
3315 def release_errors(self):
3316 for err in self.obj_conversion_errors:
3317 report_error(err)
3318 self.obj_conversion_errors = []
3320 gil_message = "Constructing Python dict"
3322 def allocate_temps(self, env, result = None):
3323 # Custom method used here because key-value
3324 # pairs are evaluated and used one at a time.
3325 self.allocate_temp(env, result)
3326 for item in self.key_value_pairs:
3327 item.key.allocate_temps(env)
3328 item.value.allocate_temps(env)
3329 item.key.release_temp(env)
3330 item.value.release_temp(env)
3332 def generate_evaluation_code(self, code):
3333 # Custom method used here because key-value
3334 # pairs are evaluated and used one at a time.
3335 if self.type.is_pyobject:
3336 self.release_errors()
3337 code.putln(
3338 "%s = PyDict_New(); %s" % (
3339 self.result(),
3340 code.error_goto_if_null(self.result(), self.pos)))
3341 for item in self.key_value_pairs:
3342 item.generate_evaluation_code(code)
3343 if self.type.is_pyobject:
3344 code.put_error_if_neg(self.pos,
3345 "PyDict_SetItem(%s, %s, %s)" % (
3346 self.result(),
3347 item.key.py_result(),
3348 item.value.py_result()))
3349 else:
3350 code.putln("%s.%s = %s;" % (
3351 self.result(),
3352 item.key.value,
3353 item.value.result()))
3354 item.generate_disposal_code(code)
3355 item.free_temps(code)
3357 def annotate(self, code):
3358 for item in self.key_value_pairs:
3359 item.annotate(code)
3361 class DictItemNode(ExprNode):
3362 # Represents a single item in a DictNode
3364 # key ExprNode
3365 # value ExprNode
3366 subexprs = ['key', 'value']
3368 def analyse_types(self, env):
3369 self.key.analyse_types(env)
3370 self.value.analyse_types(env)
3371 self.key = self.key.coerce_to_pyobject(env)
3372 self.value = self.value.coerce_to_pyobject(env)
3374 def generate_evaluation_code(self, code):
3375 self.key.generate_evaluation_code(code)
3376 self.value.generate_evaluation_code(code)
3378 def generate_disposal_code(self, code):
3379 self.key.generate_disposal_code(code)
3380 self.value.generate_disposal_code(code)
3382 def free_temps(self, code):
3383 self.key.free_temps(code)
3384 self.value.free_temps(code)
3386 def __iter__(self):
3387 return iter([self.key, self.value])
3390 class ClassNode(ExprNode):
3391 # Helper class used in the implementation of Python
3392 # class definitions. Constructs a class object given
3393 # a name, tuple of bases and class dictionary.
3395 # name EncodedString Name of the class
3396 # cname string Class name as a Python string
3397 # bases ExprNode Base class tuple
3398 # dict ExprNode Class dict (not owned by this node)
3399 # doc ExprNode or None Doc string
3400 # module_name string Name of defining module
3402 subexprs = ['bases', 'doc']
3404 def analyse_types(self, env):
3405 self.cname = env.intern_identifier(self.name)
3406 self.bases.analyse_types(env)
3407 if self.doc:
3408 self.doc.analyse_types(env)
3409 self.doc = self.doc.coerce_to_pyobject(env)
3410 self.module_name = env.global_scope().qualified_name
3411 self.type = py_object_type
3412 self.gil_check(env)
3413 self.is_temp = 1
3414 env.use_utility_code(create_class_utility_code);
3416 gil_message = "Constructing Python class"
3418 def generate_result_code(self, code):
3419 if self.doc:
3420 code.put_error_if_neg(self.pos,
3421 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3422 self.dict.py_result(),
3423 self.doc.py_result()))
3424 code.putln(
3425 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3426 self.result(),
3427 self.bases.py_result(),
3428 self.dict.py_result(),
3429 self.cname,
3430 self.module_name,
3431 code.error_goto_if_null(self.result(), self.pos)))
3434 class UnboundMethodNode(ExprNode):
3435 # Helper class used in the implementation of Python
3436 # class definitions. Constructs an unbound method
3437 # object from a class and a function.
3439 # class_cname string C var holding the class object
3440 # function ExprNode Function object
3442 subexprs = ['function']
3444 def analyse_types(self, env):
3445 self.function.analyse_types(env)
3446 self.type = py_object_type
3447 self.gil_check(env)
3448 self.is_temp = 1
3450 gil_message = "Constructing an unbound method"
3452 def generate_result_code(self, code):
3453 code.putln(
3454 "%s = PyMethod_New(%s, 0, %s); %s" % (
3455 self.result(),
3456 self.function.py_result(),
3457 self.class_cname,
3458 code.error_goto_if_null(self.result(), self.pos)))
3461 class PyCFunctionNode(AtomicNewTempExprNode):
3462 # Helper class used in the implementation of Python
3463 # class definitions. Constructs a PyCFunction object
3464 # from a PyMethodDef struct.
3466 # pymethdef_cname string PyMethodDef structure
3468 def analyse_types(self, env):
3469 self.type = py_object_type
3470 self.gil_check(env)
3471 self.is_temp = 1
3473 gil_message = "Constructing Python function"
3475 def generate_result_code(self, code):
3476 code.putln(
3477 "%s = PyCFunction_New(&%s, 0); %s" % (
3478 self.result(),
3479 self.pymethdef_cname,
3480 code.error_goto_if_null(self.result(), self.pos)))
3482 #-------------------------------------------------------------------
3484 # Unary operator nodes
3486 #-------------------------------------------------------------------
3488 compile_time_unary_operators = {
3489 'not': operator.not_,
3490 '~': operator.inv,
3491 '-': operator.neg,
3492 '+': operator.pos,
3495 class UnopNode(ExprNode):
3496 # operator string
3497 # operand ExprNode
3499 # Processing during analyse_expressions phase:
3501 # analyse_c_operation
3502 # Called when the operand is not a pyobject.
3503 # - Check operand type and coerce if needed.
3504 # - Determine result type and result code fragment.
3505 # - Allocate temporary for result if needed.
3507 subexprs = ['operand']
3509 def compile_time_value(self, denv):
3510 func = compile_time_unary_operators.get(self.operator)
3511 if not func:
3512 error(self.pos,
3513 "Unary '%s' not supported in compile-time expression"
3514 % self.operator)
3515 operand = self.operand.compile_time_value(denv)
3516 try:
3517 return func(operand)
3518 except Exception, e:
3519 self.compile_time_value_error(e)
3521 def analyse_types(self, env):
3522 self.operand.analyse_types(env)
3523 if self.is_py_operation():
3524 self.coerce_operand_to_pyobject(env)
3525 self.type = py_object_type
3526 self.gil_check(env)
3527 self.is_temp = 1
3528 else:
3529 self.analyse_c_operation(env)
3531 def check_const(self):
3532 self.operand.check_const()
3534 def is_py_operation(self):
3535 return self.operand.type.is_pyobject
3537 def coerce_operand_to_pyobject(self, env):
3538 self.operand = self.operand.coerce_to_pyobject(env)
3540 def generate_result_code(self, code):
3541 if self.operand.type.is_pyobject:
3542 self.generate_py_operation_code(code)
3543 else:
3544 if self.is_temp:
3545 self.generate_c_operation_code(code)
3547 def generate_py_operation_code(self, code):
3548 function = self.py_operation_function()
3549 code.putln(
3550 "%s = %s(%s); %s" % (
3551 self.result(),
3552 function,
3553 self.operand.py_result(),
3554 code.error_goto_if_null(self.result(), self.pos)))
3556 def type_error(self):
3557 if not self.operand.type.is_error:
3558 error(self.pos, "Invalid operand type for '%s' (%s)" %
3559 (self.operator, self.operand.type))
3560 self.type = PyrexTypes.error_type
3563 class NotNode(ExprNode):
3564 # 'not' operator
3566 # operand ExprNode
3568 def compile_time_value(self, denv):
3569 operand = self.operand.compile_time_value(denv)
3570 try:
3571 return not operand
3572 except Exception, e:
3573 self.compile_time_value_error(e)
3575 subexprs = ['operand']
3577 def analyse_types(self, env):
3578 self.operand.analyse_types(env)
3579 self.operand = self.operand.coerce_to_boolean(env)
3580 self.type = PyrexTypes.c_bint_type
3582 def calculate_result_code(self):
3583 return "(!%s)" % self.operand.result()
3585 def generate_result_code(self, code):
3586 pass
3589 class UnaryPlusNode(UnopNode):
3590 # unary '+' operator
3592 operator = '+'
3594 def analyse_c_operation(self, env):
3595 self.type = self.operand.type
3597 def py_operation_function(self):
3598 return "PyNumber_Positive"
3600 def calculate_result_code(self):
3601 return self.operand.result()
3604 class UnaryMinusNode(UnopNode):
3605 # unary '-' operator
3607 operator = '-'
3609 def analyse_c_operation(self, env):
3610 if self.operand.type.is_numeric:
3611 self.type = self.operand.type
3612 else:
3613 self.type_error()
3615 def py_operation_function(self):
3616 return "PyNumber_Negative"
3618 def calculate_result_code(self):
3619 return "(-%s)" % self.operand.result()
3622 class TildeNode(UnopNode):
3623 # unary '~' operator
3625 def analyse_c_operation(self, env):
3626 if self.operand.type.is_int:
3627 self.type = self.operand.type
3628 else:
3629 self.type_error()
3631 def py_operation_function(self):
3632 return "PyNumber_Invert"
3634 def calculate_result_code(self):
3635 return "(~%s)" % self.operand.result()
3638 class AmpersandNode(ExprNode):
3639 # The C address-of operator.
3641 # operand ExprNode
3643 subexprs = ['operand']
3645 def analyse_types(self, env):
3646 self.operand.analyse_types(env)
3647 argtype = self.operand.type
3648 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3649 self.error("Taking address of non-lvalue")
3650 return
3651 if argtype.is_pyobject:
3652 self.error("Cannot take address of Python variable")
3653 return
3654 self.type = PyrexTypes.c_ptr_type(argtype)
3656 def check_const(self):
3657 self.operand.check_const_addr()
3659 def error(self, mess):
3660 error(self.pos, mess)
3661 self.type = PyrexTypes.error_type
3662 self.result_code = "<error>"
3664 def calculate_result_code(self):
3665 return "(&%s)" % self.operand.result()
3667 def generate_result_code(self, code):
3668 pass
3671 unop_node_classes = {
3672 "+": UnaryPlusNode,
3673 "-": UnaryMinusNode,
3674 "~": TildeNode,
3677 def unop_node(pos, operator, operand):
3678 # Construct unnop node of appropriate class for
3679 # given operator.
3680 if isinstance(operand, IntNode) and operator == '-':
3681 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3682 elif isinstance(operand, UnopNode) and operand.operator == operator:
3683 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3684 return unop_node_classes[operator](pos,
3685 operator = operator,
3686 operand = operand)
3689 class TypecastNode(NewTempExprNode):
3690 # C type cast
3692 # operand ExprNode
3693 # base_type CBaseTypeNode
3694 # declarator CDeclaratorNode
3696 # If used from a transform, one can if wanted specify the attribute
3697 # "type" directly and leave base_type and declarator to None
3699 subexprs = ['operand']
3700 base_type = declarator = type = None
3702 def analyse_types(self, env):
3703 if self.type is None:
3704 base_type = self.base_type.analyse(env)
3705 _, self.type = self.declarator.analyse(base_type, env)
3706 if self.type.is_cfunction:
3707 error(self.pos,
3708 "Cannot cast to a function type")
3709 self.type = PyrexTypes.error_type
3710 self.operand.analyse_types(env)
3711 to_py = self.type.is_pyobject
3712 from_py = self.operand.type.is_pyobject
3713 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3714 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3715 if to_py and not from_py:
3716 if (self.operand.type.to_py_function and
3717 self.operand.type.create_convert_utility_code(env)):
3718 self.result_ctype = py_object_type
3719 self.operand = self.operand.coerce_to_pyobject(env)
3720 else:
3721 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3722 self.operand = self.operand.coerce_to_simple(env)
3723 elif from_py and not to_py:
3724 if self.type.from_py_function:
3725 self.operand = self.operand.coerce_to(self.type, env)
3726 else:
3727 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3728 elif from_py and to_py:
3729 if self.typecheck and self.type.is_extension_type:
3730 self.operand = PyTypeTestNode(self.operand, self.type, env)
3732 def check_const(self):
3733 self.operand.check_const()
3735 def calculate_result_code(self):
3736 opnd = self.operand
3737 return self.type.cast_code(opnd.result())
3739 def result_as(self, type):
3740 if self.type.is_pyobject and not self.is_temp:
3741 # Optimise away some unnecessary casting
3742 return self.operand.result_as(type)
3743 else:
3744 return ExprNode.result_as(self, type)
3746 def generate_result_code(self, code):
3747 if self.is_temp:
3748 code.putln(
3749 "%s = (PyObject *)%s;" % (
3750 self.result(),
3751 self.operand.result()))
3752 code.put_incref(self.result(), self.ctype())
3755 class SizeofNode(ExprNode):
3756 # Abstract base class for sizeof(x) expression nodes.
3758 type = PyrexTypes.c_int_type
3760 def check_const(self):
3761 pass
3763 def generate_result_code(self, code):
3764 pass
3767 class SizeofTypeNode(SizeofNode):
3768 # C sizeof function applied to a type
3770 # base_type CBaseTypeNode
3771 # declarator CDeclaratorNode
3773 subexprs = []
3774 arg_type = None
3776 def analyse_types(self, env):
3777 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3778 # this could be better handled by more uniformly treating types as runtime-available objects
3779 if 0 and self.base_type.module_path:
3780 path = self.base_type.module_path
3781 obj = env.lookup(path[0])
3782 if obj.as_module is None:
3783 operand = NameNode(pos=self.pos, name=path[0])
3784 for attr in path[1:]:
3785 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3786 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3787 self.operand = operand
3788 self.__class__ = SizeofVarNode
3789 self.analyse_types(env)
3790 return
3791 if self.arg_type is None:
3792 base_type = self.base_type.analyse(env)
3793 _, arg_type = self.declarator.analyse(base_type, env)
3794 self.arg_type = arg_type
3795 self.check_type()
3797 def check_type(self):
3798 arg_type = self.arg_type
3799 if arg_type.is_pyobject and not arg_type.is_extension_type:
3800 error(self.pos, "Cannot take sizeof Python object")
3801 elif arg_type.is_void:
3802 error(self.pos, "Cannot take sizeof void")
3803 elif not arg_type.is_complete():
3804 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3806 def calculate_result_code(self):
3807 if self.arg_type.is_extension_type:
3808 # the size of the pointer is boring
3809 # we want the size of the actual struct
3810 arg_code = self.arg_type.declaration_code("", deref=1)
3811 else:
3812 arg_code = self.arg_type.declaration_code("")
3813 return "(sizeof(%s))" % arg_code
3816 class SizeofVarNode(SizeofNode):
3817 # C sizeof function applied to a variable
3819 # operand ExprNode
3821 subexprs = ['operand']
3823 def analyse_types(self, env):
3824 # We may actually be looking at a type rather than a variable...
3825 # If we are, traditional analysis would fail...
3826 operand_as_type = self.operand.analyse_as_type(env)
3827 if operand_as_type:
3828 self.arg_type = operand_as_type
3829 self.__class__ = SizeofTypeNode
3830 self.check_type()
3831 else:
3832 self.operand.analyse_types(env)
3834 def calculate_result_code(self):
3835 return "(sizeof(%s))" % self.operand.result()
3837 def generate_result_code(self, code):
3838 pass
3841 #-------------------------------------------------------------------
3843 # Binary operator nodes
3845 #-------------------------------------------------------------------
3847 def _not_in(x, seq):
3848 return x not in seq
3850 compile_time_binary_operators = {
3851 '<': operator.lt,
3852 '<=': operator.le,
3853 '==': operator.eq,
3854 '!=': operator.ne,
3855 '>=': operator.ge,
3856 '>': operator.gt,
3857 'is': operator.is_,
3858 'is_not': operator.is_not,
3859 '+': operator.add,
3860 '&': operator.and_,
3861 '/': operator.div,
3862 '//': operator.floordiv,
3863 '<<': operator.lshift,
3864 '%': operator.mod,
3865 '*': operator.mul,
3866 '|': operator.or_,
3867 '**': operator.pow,
3868 '>>': operator.rshift,
3869 '-': operator.sub,
3870 #'/': operator.truediv,
3871 '^': operator.xor,
3872 'in': operator.contains,
3873 'not_in': _not_in,
3876 def get_compile_time_binop(node):
3877 func = compile_time_binary_operators.get(node.operator)
3878 if not func:
3879 error(node.pos,
3880 "Binary '%s' not supported in compile-time expression"
3881 % node.operator)
3882 return func
3884 class BinopNode(NewTempExprNode):
3885 # operator string
3886 # operand1 ExprNode
3887 # operand2 ExprNode
3889 # Processing during analyse_expressions phase:
3891 # analyse_c_operation
3892 # Called when neither operand is a pyobject.
3893 # - Check operand types and coerce if needed.
3894 # - Determine result type and result code fragment.
3895 # - Allocate temporary for result if needed.
3897 subexprs = ['operand1', 'operand2']
3899 def compile_time_value(self, denv):
3900 func = get_compile_time_binop(self)
3901 operand1 = self.operand1.compile_time_value(denv)
3902 operand2 = self.operand2.compile_time_value(denv)
3903 try:
3904 return func(operand1, operand2)
3905 except Exception, e:
3906 self.compile_time_value_error(e)
3908 def analyse_types(self, env):
3909 self.operand1.analyse_types(env)
3910 self.operand2.analyse_types(env)
3911 if self.is_py_operation():
3912 self.coerce_operands_to_pyobjects(env)
3913 self.type = py_object_type
3914 self.gil_check(env)
3915 self.is_temp = 1
3916 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3917 self.operand1 = self.operand1.coerce_to_temp(env)
3918 else:
3919 self.analyse_c_operation(env)
3921 def is_py_operation(self):
3922 return (self.operand1.type.is_pyobject
3923 or self.operand2.type.is_pyobject)
3925 def coerce_operands_to_pyobjects(self, env):
3926 self.operand1 = self.operand1.coerce_to_pyobject(env)
3927 self.operand2 = self.operand2.coerce_to_pyobject(env)
3929 def check_const(self):
3930 self.operand1.check_const()
3931 self.operand2.check_const()
3933 def generate_result_code(self, code):
3934 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3935 if self.operand1.type.is_pyobject:
3936 function = self.py_operation_function()
3937 if function == "PyNumber_Power":
3938 extra_args = ", Py_None"
3939 else:
3940 extra_args = ""
3941 code.putln(
3942 "%s = %s(%s, %s%s); %s" % (
3943 self.result(),
3944 function,
3945 self.operand1.py_result(),
3946 self.operand2.py_result(),
3947 extra_args,
3948 code.error_goto_if_null(self.result(), self.pos)))
3949 else:
3950 if self.is_temp:
3951 self.generate_c_operation_code(code)
3953 def type_error(self):
3954 if not (self.operand1.type.is_error
3955 or self.operand2.type.is_error):
3956 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3957 (self.operator, self.operand1.type,
3958 self.operand2.type))
3959 self.type = PyrexTypes.error_type
3962 class NumBinopNode(BinopNode):
3963 # Binary operation taking numeric arguments.
3965 def analyse_c_operation(self, env):
3966 type1 = self.operand1.type
3967 type2 = self.operand2.type
3968 if self.operator == "**" and type1.is_int and type2.is_int:
3969 error(self.pos, "** with two C int types is ambiguous")
3970 self.type = error_type
3971 return
3972 self.type = self.compute_c_result_type(type1, type2)
3973 if not self.type:
3974 self.type_error()
3976 def compute_c_result_type(self, type1, type2):
3977 if self.c_types_okay(type1, type2):
3978 return PyrexTypes.widest_numeric_type(type1, type2)
3979 else:
3980 return None
3982 def c_types_okay(self, type1, type2):
3983 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3984 return (type1.is_numeric or type1.is_enum) \
3985 and (type2.is_numeric or type2.is_enum)
3987 def calculate_result_code(self):
3988 return "(%s %s %s)" % (
3989 self.operand1.result(),
3990 self.operator,
3991 self.operand2.result())
3993 def py_operation_function(self):
3994 return self.py_functions[self.operator]
3996 py_functions = {
3997 "|": "PyNumber_Or",
3998 "^": "PyNumber_Xor",
3999 "&": "PyNumber_And",
4000 "<<": "PyNumber_Lshift",
4001 ">>": "PyNumber_Rshift",
4002 "+": "PyNumber_Add",
4003 "-": "PyNumber_Subtract",
4004 "*": "PyNumber_Multiply",
4005 "/": "__Pyx_PyNumber_Divide",
4006 "//": "PyNumber_FloorDivide",
4007 "%": "PyNumber_Remainder",
4008 "**": "PyNumber_Power"
4012 class IntBinopNode(NumBinopNode):
4013 # Binary operation taking integer arguments.
4015 def c_types_okay(self, type1, type2):
4016 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4017 return (type1.is_int or type1.is_enum) \
4018 and (type2.is_int or type2.is_enum)
4021 class AddNode(NumBinopNode):
4022 # '+' operator.
4024 def is_py_operation(self):
4025 if self.operand1.type.is_string \
4026 and self.operand2.type.is_string:
4027 return 1
4028 else:
4029 return NumBinopNode.is_py_operation(self)
4031 def compute_c_result_type(self, type1, type2):
4032 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4033 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4034 return type1
4035 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4036 return type2
4037 else:
4038 return NumBinopNode.compute_c_result_type(
4039 self, type1, type2)
4042 class SubNode(NumBinopNode):
4043 # '-' operator.
4045 def compute_c_result_type(self, type1, type2):
4046 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4047 return type1
4048 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4049 return PyrexTypes.c_int_type
4050 else:
4051 return NumBinopNode.compute_c_result_type(
4052 self, type1, type2)
4055 class MulNode(NumBinopNode):
4056 # '*' operator.
4058 def is_py_operation(self):
4059 type1 = self.operand1.type
4060 type2 = self.operand2.type
4061 if (type1.is_string and type2.is_int) \
4062 or (type2.is_string and type1.is_int):
4063 return 1
4064 else:
4065 return NumBinopNode.is_py_operation(self)
4068 class FloorDivNode(NumBinopNode):
4069 # '//' operator.
4071 def calculate_result_code(self):
4072 return "(%s %s %s)" % (
4073 self.operand1.result(),
4074 "/", # c division is by default floor-div
4075 self.operand2.result())
4078 class ModNode(NumBinopNode):
4079 # '%' operator.
4081 def is_py_operation(self):
4082 return (self.operand1.type.is_string
4083 or self.operand2.type.is_string
4084 or NumBinopNode.is_py_operation(self))
4086 def calculate_result_code(self):
4087 if self.operand1.type.is_float or self.operand2.type.is_float:
4088 return "fmod(%s, %s)" % (
4089 self.operand1.result(),
4090 self.operand2.result())
4091 else:
4092 return "(%s %% %s)" % (
4093 self.operand1.result(),
4094 self.operand2.result())
4096 class PowNode(NumBinopNode):
4097 # '**' operator.
4099 def compute_c_result_type(self, type1, type2):
4100 if self.c_types_okay(type1, type2):
4101 return PyrexTypes.c_double_type
4102 else:
4103 return None
4105 def c_types_okay(self, type1, type2):
4106 return (type1.is_float or type2.is_float) and \
4107 NumBinopNode.c_types_okay(self, type1, type2)
4109 def type_error(self):
4110 if not (self.operand1.type.is_error or self.operand2.type.is_error):
4111 if self.operand1.type.is_int and self.operand2.type.is_int:
4112 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
4113 (self.operator, self.operand1.type, self.operand2.type))
4114 else:
4115 NumBinopNode.type_error(self)
4116 self.type = PyrexTypes.error_type
4118 def calculate_result_code(self):
4119 return "pow(%s, %s)" % (
4120 self.operand1.result(), self.operand2.result())
4123 # Note: This class is temporary "shut down" into an ineffective mode temp
4124 # allocation mode.
4126 # More sophisticated temp reuse was going on before,
4127 # one could have a look at adding this again after /all/ classes
4128 # are converted to the new temp scheme. (The temp juggling cannot work
4129 # otherwise).
4130 class BoolBinopNode(NewTempExprNode):
4131 # Short-circuiting boolean operation.
4133 # operator string
4134 # operand1 ExprNode
4135 # operand2 ExprNode
4137 subexprs = ['operand1', 'operand2']
4139 def compile_time_value(self, denv):
4140 if self.operator == 'and':
4141 return self.operand1.compile_time_value(denv) \
4142 and self.operand2.compile_time_value(denv)
4143 else:
4144 return self.operand1.compile_time_value(denv) \
4145 or self.operand2.compile_time_value(denv)
4147 def coerce_to_boolean(self, env):
4148 self.operand1 = self.operand1.coerce_to_boolean(env)
4149 self.operand2 = self.operand2.coerce_to_boolean(env)
4150 self.type = PyrexTypes.c_bint_type
4151 return self
4153 def analyse_types(self, env):
4154 self.operand1.analyse_types(env)
4155 self.operand2.analyse_types(env)
4156 if self.operand1.type.is_pyobject or \
4157 self.operand2.type.is_pyobject:
4158 self.operand1 = self.operand1.coerce_to_pyobject(env)
4159 self.operand2 = self.operand2.coerce_to_pyobject(env)
4160 self.type = py_object_type
4161 self.gil_check(env)
4162 else:
4163 self.operand1 = self.operand1.coerce_to_boolean(env)
4164 self.operand2 = self.operand2.coerce_to_boolean(env)
4165 self.type = PyrexTypes.c_bint_type
4167 # Below disabled for
4169 # For what we're about to do, it's vital that
4170 # both operands be temp nodes.
4171 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4172 # self.operand2 = self.operand2.coerce_to_temp(env)
4173 self.is_temp = 1
4175 gil_message = "Truth-testing Python object"
4177 ## def allocate_temps(self, env, result_code = None):
4178 ## # We don't need both operands at the same time, and
4179 ## # one of the operands will also be our result. So we
4180 ## # use an allocation strategy here which results in
4181 ## # this node and both its operands sharing the same
4182 ## # result variable. This allows us to avoid some
4183 ## # assignments and increfs/decrefs that would otherwise
4184 ## # be necessary.
4185 ## self.allocate_temp(env, result_code)
4186 ## self.operand1.allocate_temps(env, self.result())
4187 ## self.operand2.allocate_temps(env, self.result())
4188 ## # We haven't called release_temp on either operand,
4189 ## # because although they are temp nodes, they don't own
4190 ## # their result variable. And because they are temp
4191 ## # nodes, any temps in their subnodes will have been
4192 ## # released before their allocate_temps returned.
4193 ## # Therefore, they contain no temp vars that need to
4194 ## # be released.
4196 def check_const(self):
4197 self.operand1.check_const()
4198 self.operand2.check_const()
4200 def calculate_result_code(self):
4201 return "(%s %s %s)" % (
4202 self.operand1.result(),
4203 self.py_to_c_op[self.operator],
4204 self.operand2.result())
4206 py_to_c_op = {'and': "&&", 'or': "||"}
4208 def generate_evaluation_code(self, code):
4209 code.mark_pos(self.pos)
4210 self.operand1.generate_evaluation_code(code)
4211 test_result, uses_temp = self.generate_operand1_test(code)
4212 if self.operator == 'and':
4213 sense = ""
4214 else:
4215 sense = "!"
4216 code.putln(
4217 "if (%s%s) {" % (
4218 sense,
4219 test_result))
4220 if uses_temp:
4221 code.funcstate.release_temp(test_result)
4222 self.operand1.generate_disposal_code(code)
4223 self.operand2.generate_evaluation_code(code)
4224 self.allocate_temp_result(code)
4225 self.operand2.make_owned_reference(code)
4226 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4227 self.operand2.generate_post_assignment_code(code)
4228 self.operand2.free_temps(code)
4229 code.putln("} else {")
4230 self.operand1.make_owned_reference(code)
4231 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4232 self.operand1.generate_post_assignment_code(code)
4233 self.operand1.free_temps(code)
4234 code.putln("}")
4236 def generate_operand1_test(self, code):
4237 # Generate code to test the truth of the first operand.
4238 if self.type.is_pyobject:
4239 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4240 manage_ref=False)
4241 code.putln(
4242 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4243 test_result,
4244 self.operand1.py_result(),
4245 code.error_goto_if_neg(test_result, self.pos)))
4246 else:
4247 test_result = self.operand1.result()
4248 return (test_result, self.type.is_pyobject)
4251 class CondExprNode(ExprNode):
4252 # Short-circuiting conditional expression.
4254 # test ExprNode
4255 # true_val ExprNode
4256 # false_val ExprNode
4258 true_val = None
4259 false_val = None
4261 subexprs = ['test', 'true_val', 'false_val']
4263 def analyse_types(self, env):
4264 self.test.analyse_types(env)
4265 self.test = self.test.coerce_to_boolean(env)
4266 self.true_val.analyse_types(env)
4267 self.false_val.analyse_types(env)
4268 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4269 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4270 self.true_val = self.true_val.coerce_to(self.type, env)
4271 self.false_val = self.false_val.coerce_to(self.type, env)
4272 # must be tmp variables so they can share a result
4273 self.true_val = self.true_val.coerce_to_temp(env)
4274 self.false_val = self.false_val.coerce_to_temp(env)
4275 self.is_temp = 1
4276 if self.type == PyrexTypes.error_type:
4277 self.type_error()
4279 def allocate_temps(self, env, result_code = None):
4280 # We only ever evaluate one side, and this is
4281 # after evaluating the truth value, so we may
4282 # use an allocation strategy here which results in
4283 # this node and both its operands sharing the same
4284 # result variable. This allows us to avoid some
4285 # assignments and increfs/decrefs that would otherwise
4286 # be necessary.
4287 self.allocate_temp(env, result_code)
4288 self.test.allocate_temps(env, result_code)
4289 self.true_val.allocate_temps(env, self.result())
4290 self.false_val.allocate_temps(env, self.result())
4291 # We haven't called release_temp on either value,
4292 # because although they are temp nodes, they don't own
4293 # their result variable. And because they are temp
4294 # nodes, any temps in their subnodes will have been
4295 # released before their allocate_temps returned.
4296 # Therefore, they contain no temp vars that need to
4297 # be released.
4299 def compute_result_type(self, type1, type2):
4300 if type1 == type2:
4301 return type1
4302 elif type1.is_numeric and type2.is_numeric:
4303 return PyrexTypes.widest_numeric_type(type1, type2)
4304 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4305 return type2
4306 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4307 return type1
4308 elif type1.is_pyobject or type2.is_pyobject:
4309 return py_object_type
4310 elif type1.assignable_from(type2):
4311 return type1
4312 elif type2.assignable_from(type1):
4313 return type2
4314 else:
4315 return PyrexTypes.error_type
4317 def type_error(self):
4318 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4319 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4320 (self.true_val.type, self.false_val.type))
4321 self.type = PyrexTypes.error_type
4323 def check_const(self):
4324 self.test.check_const()
4325 self.true_val.check_const()
4326 self.false_val.check_const()
4328 def generate_evaluation_code(self, code):
4329 self.test.generate_evaluation_code(code)
4330 code.putln("if (%s) {" % self.test.result() )
4331 self.true_val.generate_evaluation_code(code)
4332 code.putln("} else {")
4333 self.false_val.generate_evaluation_code(code)
4334 code.putln("}")
4335 self.test.generate_disposal_code(code)
4336 self.test.free_temps(code)
4338 richcmp_constants = {
4339 "<" : "Py_LT",
4340 "<=": "Py_LE",
4341 "==": "Py_EQ",
4342 "!=": "Py_NE",
4343 "<>": "Py_NE",
4344 ">" : "Py_GT",
4345 ">=": "Py_GE",
4348 class CmpNode:
4349 # Mixin class containing code common to PrimaryCmpNodes
4350 # and CascadedCmpNodes.
4352 def cascaded_compile_time_value(self, operand1, denv):
4353 func = get_compile_time_binop(self)
4354 operand2 = self.operand2.compile_time_value(denv)
4355 try:
4356 result = func(operand1, operand2)
4357 except Exception, e:
4358 self.compile_time_value_error(e)
4359 result = None
4360 if result:
4361 cascade = self.cascade
4362 if cascade:
4363 result = result and cascade.compile_time_value(operand2, denv)
4364 return result
4366 def is_python_comparison(self):
4367 return (self.has_python_operands()
4368 or (self.cascade and self.cascade.is_python_comparison())
4369 or self.operator in ('in', 'not_in'))
4371 def is_python_result(self):
4372 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4373 or (self.cascade and self.cascade.is_python_result()))
4375 def check_types(self, env, operand1, op, operand2):
4376 if not self.types_okay(operand1, op, operand2):
4377 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4378 (self.operator, operand1.type, operand2.type))
4380 def types_okay(self, operand1, op, operand2):
4381 type1 = operand1.type
4382 type2 = operand2.type
4383 if type1.is_error or type2.is_error:
4384 return 1
4385 if type1.is_pyobject: # type2 will be, too
4386 return 1
4387 elif type1.is_ptr or type1.is_array:
4388 return type1.is_null_ptr or type2.is_null_ptr \
4389 or ((type2.is_ptr or type2.is_array)
4390 and type1.base_type.same_as(type2.base_type))
4391 elif ((type1.is_numeric and type2.is_numeric
4392 or type1.is_enum and (type1 is type2 or type2.is_int)
4393 or type1.is_int and type2.is_enum)
4394 and op not in ('is', 'is_not')):
4395 return 1
4396 else:
4397 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4399 def generate_operation_code(self, code, result_code,
4400 operand1, op , operand2):
4401 if self.type is PyrexTypes.py_object_type:
4402 coerce_result = "__Pyx_PyBool_FromLong"
4403 else:
4404 coerce_result = ""
4405 if 'not' in op: negation = "!"
4406 else: negation = ""
4407 if op == 'in' or op == 'not_in':
4408 code.putln(
4409 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4410 result_code,
4411 coerce_result,
4412 negation,
4413 operand2.py_result(),
4414 operand1.py_result(),
4415 code.error_goto_if_neg(result_code, self.pos)))
4416 elif (operand1.type.is_pyobject
4417 and op not in ('is', 'is_not')):
4418 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4419 result_code,
4420 operand1.py_result(),
4421 operand2.py_result(),
4422 richcmp_constants[op],
4423 code.error_goto_if_null(result_code, self.pos)))
4424 else:
4425 type1 = operand1.type
4426 type2 = operand2.type
4427 if (type1.is_extension_type or type2.is_extension_type) \
4428 and not type1.same_as(type2):
4429 common_type = py_object_type
4430 elif type1.is_numeric:
4431 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4432 else:
4433 common_type = type1
4434 code1 = operand1.result_as(common_type)
4435 code2 = operand2.result_as(common_type)
4436 code.putln("%s = %s(%s %s %s);" % (
4437 result_code,
4438 coerce_result,
4439 code1,
4440 self.c_operator(op),
4441 code2))
4443 def c_operator(self, op):
4444 if op == 'is':
4445 return "=="
4446 elif op == 'is_not':
4447 return "!="
4448 else:
4449 return op
4452 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4453 # Non-cascaded comparison or first comparison of
4454 # a cascaded sequence.
4456 # operator string
4457 # operand1 ExprNode
4458 # operand2 ExprNode
4459 # cascade CascadedCmpNode
4461 # We don't use the subexprs mechanism, because
4462 # things here are too complicated for it to handle.
4463 # Instead, we override all the framework methods
4464 # which use it.
4466 child_attrs = ['operand1', 'operand2', 'cascade']
4468 cascade = None
4470 def compile_time_value(self, denv):
4471 operand1 = self.operand1.compile_time_value(denv)
4472 return self.cascaded_compile_time_value(operand1, denv)
4474 def analyse_types(self, env):
4475 self.operand1.analyse_types(env)
4476 self.operand2.analyse_types(env)
4477 if self.cascade:
4478 self.cascade.analyse_types(env, self.operand2)
4479 self.is_pycmp = self.is_python_comparison()
4480 if self.is_pycmp:
4481 self.coerce_operands_to_pyobjects(env)
4482 if self.has_int_operands():
4483 self.coerce_chars_to_ints(env)
4484 if self.cascade:
4485 self.operand2 = self.operand2.coerce_to_simple(env)
4486 self.cascade.coerce_cascaded_operands_to_temp(env)
4487 self.check_operand_types(env)
4488 if self.is_python_result():
4489 self.type = PyrexTypes.py_object_type
4490 else:
4491 self.type = PyrexTypes.c_bint_type
4492 cdr = self.cascade
4493 while cdr:
4494 cdr.type = self.type
4495 cdr = cdr.cascade
4496 if self.is_pycmp or self.cascade:
4497 self.is_temp = 1
4499 def check_operand_types(self, env):
4500 self.check_types(env,
4501 self.operand1, self.operator, self.operand2)
4502 if self.cascade:
4503 self.cascade.check_operand_types(env, self.operand2)
4505 def has_python_operands(self):
4506 return (self.operand1.type.is_pyobject
4507 or self.operand2.type.is_pyobject)
4509 def coerce_operands_to_pyobjects(self, env):
4510 self.operand1 = self.operand1.coerce_to_pyobject(env)
4511 self.operand2 = self.operand2.coerce_to_pyobject(env)
4512 if self.cascade:
4513 self.cascade.coerce_operands_to_pyobjects(env)
4515 def has_int_operands(self):
4516 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4517 or (self.cascade and self.cascade.has_int_operands())
4519 def coerce_chars_to_ints(self, env):
4520 # coerce literal single-char strings to c chars
4521 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4522 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4523 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4524 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4525 if self.cascade:
4526 self.cascade.coerce_chars_to_ints(env)
4528 def allocate_subexpr_temps(self, env):
4529 self.operand1.allocate_temps(env)
4530 self.operand2.allocate_temps(env)
4531 if self.cascade:
4532 self.cascade.allocate_subexpr_temps(env)
4534 def release_subexpr_temps(self, env):
4535 self.operand1.release_temp(env)
4536 self.operand2.release_temp(env)
4537 if self.cascade:
4538 self.cascade.release_subexpr_temps(env)
4540 def check_const(self):
4541 self.operand1.check_const()
4542 self.operand2.check_const()
4543 if self.cascade:
4544 self.not_const()
4546 def calculate_result_code(self):
4547 return "(%s %s %s)" % (
4548 self.operand1.result(),
4549 self.c_operator(self.operator),
4550 self.operand2.result())
4552 def generate_evaluation_code(self, code):
4553 self.operand1.generate_evaluation_code(code)
4554 self.operand2.generate_evaluation_code(code)
4555 if self.is_temp:
4556 self.allocate_temp_result(code)
4557 self.generate_operation_code(code, self.result(),
4558 self.operand1, self.operator, self.operand2)
4559 if self.cascade:
4560 self.cascade.generate_evaluation_code(code,
4561 self.result(), self.operand2)
4562 self.operand1.generate_disposal_code(code)
4563 self.operand1.free_temps(code)
4564 self.operand2.generate_disposal_code(code)
4565 self.operand2.free_temps(code)
4567 def generate_subexpr_disposal_code(self, code):
4568 # If this is called, it is a non-cascaded cmp,
4569 # so only need to dispose of the two main operands.
4570 self.operand1.generate_disposal_code(code)
4571 self.operand2.generate_disposal_code(code)
4573 def free_subexpr_temps(self, code):
4574 # If this is called, it is a non-cascaded cmp,
4575 # so only need to dispose of the two main operands.
4576 self.operand1.free_temps(code)
4577 self.operand2.free_temps(code)
4579 def annotate(self, code):
4580 self.operand1.annotate(code)
4581 self.operand2.annotate(code)
4582 if self.cascade:
4583 self.cascade.annotate(code)
4586 class CascadedCmpNode(Node, CmpNode):
4587 # A CascadedCmpNode is not a complete expression node. It
4588 # hangs off the side of another comparison node, shares
4589 # its left operand with that node, and shares its result
4590 # with the PrimaryCmpNode at the head of the chain.
4592 # operator string
4593 # operand2 ExprNode
4594 # cascade CascadedCmpNode
4596 child_attrs = ['operand2', 'cascade']
4598 cascade = None
4600 def analyse_types(self, env, operand1):
4601 self.operand2.analyse_types(env)
4602 if self.cascade:
4603 self.cascade.analyse_types(env, self.operand2)
4605 def check_operand_types(self, env, operand1):
4606 self.check_types(env,
4607 operand1, self.operator, self.operand2)
4608 if self.cascade:
4609 self.cascade.check_operand_types(env, self.operand2)
4611 def has_python_operands(self):
4612 return self.operand2.type.is_pyobject
4614 def coerce_operands_to_pyobjects(self, env):
4615 self.operand2 = self.operand2.coerce_to_pyobject(env)
4616 if self.cascade:
4617 self.cascade.coerce_operands_to_pyobjects(env)
4619 def has_int_operands(self):
4620 return self.operand2.type.is_int
4622 def coerce_chars_to_ints(self, env):
4623 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4624 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4626 def coerce_cascaded_operands_to_temp(self, env):
4627 if self.cascade:
4628 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4629 self.operand2 = self.operand2.coerce_to_simple(env)
4630 self.cascade.coerce_cascaded_operands_to_temp(env)
4632 def allocate_subexpr_temps(self, env):
4633 self.operand2.allocate_temps(env)
4634 if self.cascade:
4635 self.cascade.allocate_subexpr_temps(env)
4637 def release_subexpr_temps(self, env):
4638 self.operand2.release_temp(env)
4639 if self.cascade:
4640 self.cascade.release_subexpr_temps(env)
4642 def generate_evaluation_code(self, code, result, operand1):
4643 if self.type.is_pyobject:
4644 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4645 else:
4646 code.putln("if (%s) {" % result)
4647 self.operand2.generate_evaluation_code(code)
4648 self.generate_operation_code(code, result,
4649 operand1, self.operator, self.operand2)
4650 if self.cascade:
4651 self.cascade.generate_evaluation_code(
4652 code, result, self.operand2)
4653 # Cascaded cmp result is always temp
4654 self.operand2.generate_disposal_code(code)
4655 self.operand2.free_temps(code)
4656 code.putln("}")
4658 def annotate(self, code):
4659 self.operand2.annotate(code)
4660 if self.cascade:
4661 self.cascade.annotate(code)
4664 binop_node_classes = {
4665 "or": BoolBinopNode,
4666 "and": BoolBinopNode,
4667 "|": IntBinopNode,
4668 "^": IntBinopNode,
4669 "&": IntBinopNode,
4670 "<<": IntBinopNode,
4671 ">>": IntBinopNode,
4672 "+": AddNode,
4673 "-": SubNode,
4674 "*": MulNode,
4675 "/": NumBinopNode,
4676 "//": FloorDivNode,
4677 "%": ModNode,
4678 "**": PowNode
4681 def binop_node(pos, operator, operand1, operand2):
4682 # Construct binop node of appropriate class for
4683 # given operator.
4684 return binop_node_classes[operator](pos,
4685 operator = operator,
4686 operand1 = operand1,
4687 operand2 = operand2)
4689 #-------------------------------------------------------------------
4691 # Coercion nodes
4693 # Coercion nodes are special in that they are created during
4694 # the analyse_types phase of parse tree processing.
4695 # Their __init__ methods consequently incorporate some aspects
4696 # of that phase.
4698 #-------------------------------------------------------------------
4700 class CoercionNode(NewTempExprNode):
4701 # Abstract base class for coercion nodes.
4703 # arg ExprNode node being coerced
4705 subexprs = ['arg']
4707 def __init__(self, arg):
4708 self.pos = arg.pos
4709 self.arg = arg
4710 if debug_coercion:
4711 print("%s Coercing %s" % (self, self.arg))
4713 def annotate(self, code):
4714 self.arg.annotate(code)
4715 if self.arg.type != self.type:
4716 file, line, col = self.pos
4717 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4720 class CastNode(CoercionNode):
4721 # Wrap a node in a C type cast.
4723 def __init__(self, arg, new_type):
4724 CoercionNode.__init__(self, arg)
4725 self.type = new_type
4727 def calculate_result_code(self):
4728 return self.arg.result_as(self.type)
4730 def generate_result_code(self, code):
4731 self.arg.generate_result_code(code)
4734 class PyTypeTestNode(CoercionNode):
4735 # This node is used to check that a generic Python
4736 # object is an instance of a particular extension type.
4737 # This node borrows the result of its argument node.
4739 def __init__(self, arg, dst_type, env):
4740 # The arg is know to be a Python object, and
4741 # the dst_type is known to be an extension type.
4742 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4743 CoercionNode.__init__(self, arg)
4744 self.type = dst_type
4745 self.gil_check(env)
4746 self.result_ctype = arg.ctype()
4748 gil_message = "Python type test"
4750 def analyse_types(self, env):
4751 pass
4753 def result_in_temp(self):
4754 return self.arg.result_in_temp()
4756 def is_ephemeral(self):
4757 return self.arg.is_ephemeral()
4759 def calculate_result_code(self):
4760 return self.arg.result()
4762 def generate_result_code(self, code):
4763 if self.type.typeobj_is_available():
4764 if not self.type.is_builtin_type:
4765 code.globalstate.use_utility_code(type_test_utility_code)
4766 code.putln(
4767 "if (!(%s)) %s" % (
4768 self.type.type_test_code(self.arg.py_result()),
4769 code.error_goto(self.pos)))
4770 else:
4771 error(self.pos, "Cannot test type of extern C class "
4772 "without type object name specification")
4774 def generate_post_assignment_code(self, code):
4775 self.arg.generate_post_assignment_code(code)
4777 def free_temps(self, code):
4778 self.arg.free_temps(code)
4781 class CoerceToPyTypeNode(CoercionNode):
4782 # This node is used to convert a C data type
4783 # to a Python object.
4785 def __init__(self, arg, env):
4786 CoercionNode.__init__(self, arg)
4787 self.type = py_object_type
4788 self.gil_check(env)
4789 self.is_temp = 1
4790 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4791 error(arg.pos,
4792 "Cannot convert '%s' to Python object" % arg.type)
4794 gil_message = "Converting to Python object"
4796 def coerce_to_boolean(self, env):
4797 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
4799 def analyse_types(self, env):
4800 # The arg is always already analysed
4801 pass
4803 def generate_result_code(self, code):
4804 function = self.arg.type.to_py_function
4805 code.putln('%s = %s(%s); %s' % (
4806 self.result(),
4807 function,
4808 self.arg.result(),
4809 code.error_goto_if_null(self.result(), self.pos)))
4812 class CoerceFromPyTypeNode(CoercionNode):
4813 # This node is used to convert a Python object
4814 # to a C data type.
4816 def __init__(self, result_type, arg, env):
4817 CoercionNode.__init__(self, arg)
4818 self.type = result_type
4819 self.is_temp = 1
4820 if not result_type.from_py_function:
4821 error(arg.pos,
4822 "Cannot convert Python object to '%s'" % result_type)
4823 if self.type.is_string and self.arg.is_ephemeral():
4824 error(arg.pos,
4825 "Obtaining char * from temporary Python value")
4827 def analyse_types(self, env):
4828 # The arg is always already analysed
4829 pass
4831 def generate_result_code(self, code):
4832 function = self.type.from_py_function
4833 operand = self.arg.py_result()
4834 rhs = "%s(%s)" % (function, operand)
4835 if self.type.is_enum:
4836 rhs = typecast(self.type, c_long_type, rhs)
4837 code.putln('%s = %s; %s' % (
4838 self.result(),
4839 rhs,
4840 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4843 class CoerceToBooleanNode(CoercionNode):
4844 # This node is used when a result needs to be used
4845 # in a boolean context.
4847 def __init__(self, arg, env):
4848 CoercionNode.__init__(self, arg)
4849 self.type = PyrexTypes.c_bint_type
4850 if arg.type.is_pyobject:
4851 if env.nogil:
4852 self.gil_error()
4853 self.is_temp = 1
4855 gil_message = "Truth-testing Python object"
4857 def check_const(self):
4858 if self.is_temp:
4859 self.not_const()
4860 self.arg.check_const()
4862 def calculate_result_code(self):
4863 return "(%s != 0)" % self.arg.result()
4865 def generate_result_code(self, code):
4866 if self.arg.type.is_pyobject:
4867 code.putln(
4868 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4869 self.result(),
4870 self.arg.py_result(),
4871 code.error_goto_if_neg(self.result(), self.pos)))
4874 class CoerceToTempNode(CoercionNode):
4875 # This node is used to force the result of another node
4876 # to be stored in a temporary. It is only used if the
4877 # argument node's result is not already in a temporary.
4879 def __init__(self, arg, env):
4880 CoercionNode.__init__(self, arg)
4881 self.type = self.arg.type
4882 self.is_temp = 1
4883 if self.type.is_pyobject:
4884 self.gil_check(env)
4885 self.result_ctype = py_object_type
4887 gil_message = "Creating temporary Python reference"
4889 def analyse_types(self, env):
4890 # The arg is always already analysed
4891 pass
4893 def coerce_to_boolean(self, env):
4894 self.arg = self.arg.coerce_to_boolean(env)
4895 self.type = self.arg.type
4896 self.result_ctype = self.type
4897 return self
4899 def generate_result_code(self, code):
4900 #self.arg.generate_evaluation_code(code) # Already done
4901 # by generic generate_subexpr_evaluation_code!
4902 code.putln("%s = %s;" % (
4903 self.result(), self.arg.result_as(self.ctype())))
4904 if self.type.is_pyobject:
4905 code.put_incref(self.result(), self.ctype())
4908 class CloneNode(CoercionNode):
4909 # This node is employed when the result of another node needs
4910 # to be used multiple times. The argument node's result must
4911 # be in a temporary. This node "borrows" the result from the
4912 # argument node, and does not generate any evaluation or
4913 # disposal code for it. The original owner of the argument
4914 # node is responsible for doing those things.
4916 subexprs = [] # Arg is not considered a subexpr
4918 def __init__(self, arg):
4919 CoercionNode.__init__(self, arg)
4920 if hasattr(arg, 'type'):
4921 self.type = arg.type
4922 self.result_ctype = arg.result_ctype
4923 if hasattr(arg, 'entry'):
4924 self.entry = arg.entry
4926 def result(self):
4927 return self.arg.result()
4929 def analyse_types(self, env):
4930 self.type = self.arg.type
4931 self.result_ctype = self.arg.result_ctype
4932 self.is_temp = 1
4933 if hasattr(self.arg, 'entry'):
4934 self.entry = self.arg.entry
4936 def generate_evaluation_code(self, code):
4937 pass
4939 def generate_result_code(self, code):
4940 pass
4942 def generate_disposal_code(self, code):
4943 pass
4945 def allocate_temps(self, env):
4946 pass
4948 def release_temp(self, env):
4949 pass
4951 def free_temps(self, code):
4952 pass
4955 #------------------------------------------------------------------------------------
4957 # Runtime support code
4959 #------------------------------------------------------------------------------------
4961 get_name_interned_utility_code = UtilityCode(
4962 proto = """
4963 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4964 """,
4965 impl = """
4966 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4967 PyObject *result;
4968 result = PyObject_GetAttr(dict, name);
4969 if (!result)
4970 PyErr_SetObject(PyExc_NameError, name);
4971 return result;
4973 """)
4975 #------------------------------------------------------------------------------------
4977 import_utility_code = UtilityCode(
4978 proto = """
4979 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4980 """,
4981 impl = """
4982 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4983 PyObject *__import__ = 0;
4984 PyObject *empty_list = 0;
4985 PyObject *module = 0;
4986 PyObject *global_dict = 0;
4987 PyObject *empty_dict = 0;
4988 PyObject *list;
4989 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4990 if (!__import__)
4991 goto bad;
4992 if (from_list)
4993 list = from_list;
4994 else {
4995 empty_list = PyList_New(0);
4996 if (!empty_list)
4997 goto bad;
4998 list = empty_list;
5000 global_dict = PyModule_GetDict(%(GLOBALS)s);
5001 if (!global_dict)
5002 goto bad;
5003 empty_dict = PyDict_New();
5004 if (!empty_dict)
5005 goto bad;
5006 module = PyObject_CallFunctionObjArgs(__import__,
5007 name, global_dict, empty_dict, list, NULL);
5008 bad:
5009 Py_XDECREF(empty_list);
5010 Py_XDECREF(__import__);
5011 Py_XDECREF(empty_dict);
5012 return module;
5014 """ % {
5015 "BUILTINS": Naming.builtins_cname,
5016 "GLOBALS": Naming.module_cname,
5017 })
5019 #------------------------------------------------------------------------------------
5021 get_exception_utility_code = UtilityCode(
5022 proto = """
5023 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5024 """,
5025 impl = """
5026 static PyObject *__Pyx_GetExcValue(void) {
5027 PyObject *type = 0, *value = 0, *tb = 0;
5028 PyObject *tmp_type, *tmp_value, *tmp_tb;
5029 PyObject *result = 0;
5030 PyThreadState *tstate = PyThreadState_Get();
5031 PyErr_Fetch(&type, &value, &tb);
5032 PyErr_NormalizeException(&type, &value, &tb);
5033 if (PyErr_Occurred())
5034 goto bad;
5035 if (!value) {
5036 value = Py_None;
5037 Py_INCREF(value);
5039 tmp_type = tstate->exc_type;
5040 tmp_value = tstate->exc_value;
5041 tmp_tb = tstate->exc_traceback;
5042 tstate->exc_type = type;
5043 tstate->exc_value = value;
5044 tstate->exc_traceback = tb;
5045 /* Make sure tstate is in a consistent state when we XDECREF
5046 these objects (XDECREF may run arbitrary code). */
5047 Py_XDECREF(tmp_type);
5048 Py_XDECREF(tmp_value);
5049 Py_XDECREF(tmp_tb);
5050 result = value;
5051 Py_XINCREF(result);
5052 type = 0;
5053 value = 0;
5054 tb = 0;
5055 bad:
5056 Py_XDECREF(type);
5057 Py_XDECREF(value);
5058 Py_XDECREF(tb);
5059 return result;
5061 """)
5063 #------------------------------------------------------------------------------------
5065 unpacking_utility_code = UtilityCode(
5066 proto = """
5067 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5068 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5069 """,
5070 impl = """
5071 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5072 PyObject *item;
5073 if (!(item = PyIter_Next(iter))) {
5074 if (!PyErr_Occurred()) {
5075 PyErr_Format(PyExc_ValueError,
5076 #if PY_VERSION_HEX < 0x02050000
5077 "need more than %d values to unpack", (int)index);
5078 #else
5079 "need more than %zd values to unpack", index);
5080 #endif
5083 return item;
5086 static int __Pyx_EndUnpack(PyObject *iter) {
5087 PyObject *item;
5088 if ((item = PyIter_Next(iter))) {
5089 Py_DECREF(item);
5090 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5091 return -1;
5093 else if (!PyErr_Occurred())
5094 return 0;
5095 else
5096 return -1;
5098 """)
5100 #------------------------------------------------------------------------------------
5102 type_test_utility_code = UtilityCode(
5103 proto = """
5104 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5105 """,
5106 impl = """
5107 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5108 if (!type) {
5109 PyErr_Format(PyExc_SystemError, "Missing type object");
5110 return 0;
5112 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5113 return 1;
5114 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5115 Py_TYPE(obj)->tp_name, type->tp_name);
5116 return 0;
5118 """)
5120 #------------------------------------------------------------------------------------
5122 create_class_utility_code = UtilityCode(
5123 proto = """
5124 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5125 """,
5126 impl = """
5127 static PyObject *__Pyx_CreateClass(
5128 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5130 PyObject *py_modname;
5131 PyObject *result = 0;
5133 #if PY_MAJOR_VERSION < 3
5134 py_modname = PyString_FromString(modname);
5135 #else
5136 py_modname = PyUnicode_FromString(modname);
5137 #endif
5138 if (!py_modname)
5139 goto bad;
5140 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5141 goto bad;
5142 #if PY_MAJOR_VERSION < 3
5143 result = PyClass_New(bases, dict, name);
5144 #else
5145 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5146 #endif
5147 bad:
5148 Py_XDECREF(py_modname);
5149 return result;
5151 """)
5153 #------------------------------------------------------------------------------------
5155 cpp_exception_utility_code = UtilityCode(
5156 proto = """
5157 #ifndef __Pyx_CppExn2PyErr
5158 static void __Pyx_CppExn2PyErr() {
5159 try {
5160 if (PyErr_Occurred())
5161 ; // let the latest Python exn pass through and ignore the current one
5162 else
5163 throw;
5164 } catch (const std::out_of_range& exn) {
5165 // catch out_of_range explicitly so the proper Python exn may be raised
5166 PyErr_SetString(PyExc_IndexError, exn.what());
5167 } catch (const std::exception& exn) {
5168 PyErr_SetString(PyExc_RuntimeError, exn.what());
5170 catch (...)
5172 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5175 #endif
5176 """,
5177 impl = ""
5180 #------------------------------------------------------------------------------------
5182 append_utility_code = UtilityCode(
5183 proto = """
5184 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5185 if (likely(PyList_CheckExact(L))) {
5186 if (PyList_Append(L, x) < 0) return NULL;
5187 Py_INCREF(Py_None);
5188 return Py_None; /* this is just to have an accurate signature */
5190 else {
5191 PyObject *r, *m;
5192 m = PyObject_GetAttrString(L, "append");
5193 if (!m) return NULL;
5194 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5195 Py_DECREF(m);
5196 return r;
5199 """,
5200 impl = ""
5203 #------------------------------------------------------------------------------------
5205 # If the is_unsigned flag is set, we need to do some extra work to make
5206 # sure the index doesn't become negative.
5208 getitem_int_utility_code = UtilityCode(
5209 proto = """
5210 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5211 PyObject *r;
5212 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5213 r = PyList_GET_ITEM(o, i);
5214 Py_INCREF(r);
5216 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
5217 r = PyTuple_GET_ITEM(o, i);
5218 Py_INCREF(r);
5220 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
5221 r = PySequence_GetItem(o, i);
5222 else {
5223 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5224 if (!j)
5225 return 0;
5226 r = PyObject_GetItem(o, j);
5227 Py_DECREF(j);
5229 return r;
5231 """,
5232 impl = """
5233 """)
5235 #------------------------------------------------------------------------------------
5237 setitem_int_utility_code = UtilityCode(
5238 proto = """
5239 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
5240 int r;
5241 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5242 Py_DECREF(PyList_GET_ITEM(o, i));
5243 Py_INCREF(v);
5244 PyList_SET_ITEM(o, i, v);
5245 return 1;
5247 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5248 r = PySequence_SetItem(o, i, v);
5249 else {
5250 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5251 if (!j)
5252 return -1;
5253 r = PyObject_SetItem(o, j, v);
5254 Py_DECREF(j);
5256 return r;
5258 """,
5259 impl = """
5260 """)
5262 #------------------------------------------------------------------------------------
5264 delitem_int_utility_code = UtilityCode(
5265 proto = """
5266 static INLINE int __Pyx_DelItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5267 int r;
5268 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5269 r = PySequence_DelItem(o, i);
5270 else {
5271 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5272 if (!j)
5273 return -1;
5274 r = PyObject_DelItem(o, j);
5275 Py_DECREF(j);
5277 return r;
5279 """,
5280 impl = """
5281 """)
5283 #------------------------------------------------------------------------------------
5285 raise_noneattr_error_utility_code = UtilityCode(
5286 proto = """
5287 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5288 """,
5289 impl = """
5290 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5291 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5293 """)
5295 raise_noneindex_error_utility_code = UtilityCode(
5296 proto = """
5297 static INLINE void __Pyx_RaiseNoneIndexingError();
5298 """,
5299 impl = """
5300 static INLINE void __Pyx_RaiseNoneIndexingError() {
5301 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5303 """)