Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 2158:50307880f9c1

almost complete refactoring of constant allocation to move it into the code generation phase
author Stefan Behnel <scoder@users.berlios.de>
date Wed Mar 18 21:44:34 2009 +0100 (3 years ago)
parents b968461f6584
children 8195340e572c
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 Builtin
17 import Symtab
18 import Options
19 from Annotate import AnnotationItem
21 from Cython.Debugging import print_call_chain
22 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
23 debug_coercion
25 try:
26 set
27 except NameError:
28 from sets import Set as set
30 class NotConstant(object): pass # just for the name
31 not_a_constant = NotConstant()
32 constant_value_not_set = object()
34 class ExprNode(Node):
35 # subexprs [string] Class var holding names of subexpr node attrs
36 # type PyrexType Type of the result
37 # result_code string Code fragment
38 # result_ctype string C type of result_code if different from type
39 # is_temp boolean Result is in a temporary variable
40 # is_sequence_constructor
41 # boolean Is a list or tuple constructor expression
42 # saved_subexpr_nodes
43 # [ExprNode or [ExprNode or None] or None]
44 # Cached result of subexpr_nodes()
46 result_ctype = None
47 type = None
49 # The Analyse Expressions phase for expressions is split
50 # into two sub-phases:
51 #
52 # Analyse Types
53 # Determines the result type of the expression based
54 # on the types of its sub-expressions, and inserts
55 # coercion nodes into the expression tree where needed.
56 # Marks nodes which will need to have temporary variables
57 # allocated.
58 #
59 # Allocate Temps
60 # Allocates temporary variables where needed, and fills
61 # in the result_code field of each node.
62 #
63 # ExprNode provides some convenience routines which
64 # perform both of the above phases. These should only
65 # be called from statement nodes, and only when no
66 # coercion nodes need to be added around the expression
67 # being analysed. In that case, the above two phases
68 # should be invoked separately.
69 #
70 # Framework code in ExprNode provides much of the common
71 # processing for the various phases. It makes use of the
72 # 'subexprs' class attribute of ExprNodes, which should
73 # contain a list of the names of attributes which can
74 # hold sub-nodes or sequences of sub-nodes.
75 #
76 # The framework makes use of a number of abstract methods.
77 # Their responsibilities are as follows.
78 #
79 # Declaration Analysis phase
80 #
81 # analyse_target_declaration
82 # Called during the Analyse Declarations phase to analyse
83 # the LHS of an assignment or argument of a del statement.
84 # Nodes which cannot be the LHS of an assignment need not
85 # implement it.
86 #
87 # Expression Analysis phase
88 #
89 # analyse_types
90 # - Call analyse_types on all sub-expressions.
91 # - Check operand types, and wrap coercion nodes around
92 # sub-expressions where needed.
93 # - Set the type of this node.
94 # - If a temporary variable will be required for the
95 # result, set the is_temp flag of this node.
96 #
97 # analyse_target_types
98 # Called during the Analyse Types phase to analyse
99 # the LHS of an assignment or argument of a del
100 # statement. Similar responsibilities to analyse_types.
101 #
102 # allocate_temps
103 # - Call allocate_temps for all sub-nodes.
104 # - Call allocate_temp for this node.
105 # - If a temporary was allocated, call release_temp on
106 # all sub-expressions.
107 #
108 # allocate_target_temps
109 # - Call allocate_temps on sub-nodes and allocate any other
110 # temps used during assignment.
111 # - Fill in result_code with a C lvalue if needed.
112 # - If a rhs node is supplied, call release_temp on it.
113 # - Call release_temp on sub-nodes and release any other
114 # temps used during assignment.
115 #
116 # target_code
117 # Called by the default implementation of allocate_target_temps.
118 # Should return a C lvalue for assigning to the node. The default
119 # implementation calls calculate_result_code.
120 #
121 # check_const
122 # - Check that this node and its subnodes form a
123 # legal constant expression. If so, do nothing,
124 # otherwise call not_const.
125 #
126 # The default implementation of check_const
127 # assumes that the expression is not constant.
128 #
129 # check_const_addr
130 # - Same as check_const, except check that the
131 # expression is a C lvalue whose address is
132 # constant. Otherwise, call addr_not_const.
133 #
134 # The default implementation of calc_const_addr
135 # assumes that the expression is not a constant
136 # lvalue.
137 #
138 # Code Generation phase
139 #
140 # generate_evaluation_code
141 # - Call generate_evaluation_code for sub-expressions.
142 # - Perform the functions of generate_result_code
143 # (see below).
144 # - If result is temporary, call generate_disposal_code
145 # on all sub-expressions.
146 #
147 # A default implementation of generate_evaluation_code
148 # is provided which uses the following abstract methods:
149 #
150 # generate_result_code
151 # - Generate any C statements necessary to calculate
152 # the result of this node from the results of its
153 # sub-expressions.
154 #
155 # calculate_result_code
156 # - Should return a C code fragment evaluating to the
157 # result. This is only called when the result is not
158 # a temporary.
159 #
160 # generate_assignment_code
161 # Called on the LHS of an assignment.
162 # - Call generate_evaluation_code for sub-expressions.
163 # - Generate code to perform the assignment.
164 # - If the assignment absorbed a reference, call
165 # generate_post_assignment_code on the RHS,
166 # otherwise call generate_disposal_code on it.
167 #
168 # generate_deletion_code
169 # Called on an argument of a del statement.
170 # - Call generate_evaluation_code for sub-expressions.
171 # - Generate code to perform the deletion.
172 # - Call generate_disposal_code on all sub-expressions.
173 #
174 #
176 is_sequence_constructor = 0
177 is_attribute = 0
179 saved_subexpr_nodes = None
180 is_temp = 0
181 is_target = 0
183 constant_result = constant_value_not_set
185 try:
186 _get_child_attrs = operator.attrgetter('subexprs')
187 except AttributeError:
188 # Python 2.3
189 def _get_child_attrs(self):
190 return self.subexprs
191 child_attrs = property(fget=_get_child_attrs)
193 def not_implemented(self, method_name):
194 print_call_chain(method_name, "not implemented") ###
195 raise InternalError(
196 "%s.%s not implemented" %
197 (self.__class__.__name__, method_name))
199 def is_lvalue(self):
200 return 0
202 def is_ephemeral(self):
203 # An ephemeral node is one whose result is in
204 # a Python temporary and we suspect there are no
205 # other references to it. Certain operations are
206 # disallowed on such values, since they are
207 # likely to result in a dangling pointer.
208 return self.type.is_pyobject and self.is_temp
210 def subexpr_nodes(self):
211 # Extract a list of subexpression nodes based
212 # on the contents of the subexprs class attribute.
213 nodes = []
214 for name in self.subexprs:
215 item = getattr(self, name)
216 if item is not None:
217 if type(item) is list:
218 nodes.extend(item)
219 else:
220 nodes.append(item)
221 return nodes
223 def result(self):
224 if not self.is_temp or self.is_target:
225 return self.calculate_result_code()
226 else: # i.e. self.is_temp:
227 return self.result_code
229 def result_as(self, type = None):
230 # Return the result code cast to the specified C type.
231 return typecast(type, self.ctype(), self.result())
233 def py_result(self):
234 # Return the result code cast to PyObject *.
235 return self.result_as(py_object_type)
237 def ctype(self):
238 # Return the native C type of the result (i.e. the
239 # C type of the result_code expression).
240 return self.result_ctype or self.type
242 def calculate_constant_result(self):
243 # Calculate the constant result of this expression and store
244 # it in ``self.constant_result``. Does nothing by default,
245 # thus leaving ``self.constant_result`` unknown.
246 #
247 # This must only be called when it is assured that all
248 # sub-expressions have a valid constant_result value. The
249 # ConstantFolding transform will do this.
250 pass
252 def compile_time_value(self, denv):
253 # Return value of compile-time expression, or report error.
254 error(self.pos, "Invalid compile-time expression")
256 def compile_time_value_error(self, e):
257 error(self.pos, "Error in compile-time expression: %s: %s" % (
258 e.__class__.__name__, e))
260 # ------------- Declaration Analysis ----------------
262 def analyse_target_declaration(self, env):
263 error(self.pos, "Cannot assign to or delete this")
265 # ------------- Expression Analysis ----------------
267 def analyse_const_expression(self, env):
268 # Called during the analyse_declarations phase of a
269 # constant expression. Analyses the expression's type,
270 # checks whether it is a legal const expression,
271 # and determines its value.
272 self.analyse_types(env)
273 self.allocate_temps(env)
274 self.check_const()
276 def analyse_expressions(self, env):
277 # Convenience routine performing both the Type
278 # Analysis and Temp Allocation phases for a whole
279 # expression.
280 self.analyse_types(env)
281 self.allocate_temps(env)
283 def analyse_target_expression(self, env, rhs):
284 # Convenience routine performing both the Type
285 # Analysis and Temp Allocation phases for the LHS of
286 # an assignment.
287 self.analyse_target_types(env)
288 self.allocate_target_temps(env, rhs)
290 def analyse_boolean_expression(self, env):
291 # Analyse expression and coerce to a boolean.
292 self.analyse_types(env)
293 bool = self.coerce_to_boolean(env)
294 bool.allocate_temps(env)
295 return bool
297 def analyse_temp_boolean_expression(self, env):
298 # Analyse boolean expression and coerce result into
299 # a temporary. This is used when a branch is to be
300 # performed on the result and we won't have an
301 # opportunity to ensure disposal code is executed
302 # afterwards. By forcing the result into a temporary,
303 # we ensure that all disposal has been done by the
304 # time we get the result.
305 self.analyse_types(env)
306 bool = self.coerce_to_boolean(env)
307 temp_bool = bool.coerce_to_temp(env)
308 temp_bool.allocate_temps(env)
309 return temp_bool
311 # --------------- Type Analysis ------------------
313 def analyse_as_module(self, env):
314 # If this node can be interpreted as a reference to a
315 # cimported module, return its scope, else None.
316 return None
318 def analyse_as_type(self, env):
319 # If this node can be interpreted as a reference to a
320 # type, return that type, else None.
321 return None
323 def analyse_as_extension_type(self, env):
324 # If this node can be interpreted as a reference to an
325 # extension type, return its type, else None.
326 return None
328 def analyse_types(self, env):
329 self.not_implemented("analyse_types")
331 def analyse_target_types(self, env):
332 self.analyse_types(env)
334 def gil_check(self, env):
335 # By default, any expression based on Python objects is
336 # prevented in nogil environments. Subtypes must override
337 # this if they can work without the GIL.
338 if self.type.is_pyobject:
339 self._gil_check(env)
341 def gil_assignment_check(self, env):
342 if env.nogil and self.type.is_pyobject:
343 error(self.pos, "Assignment of Python object not allowed without gil")
345 def check_const(self):
346 self.not_const()
348 def not_const(self):
349 error(self.pos, "Not allowed in a constant expression")
351 def check_const_addr(self):
352 self.addr_not_const()
354 def addr_not_const(self):
355 error(self.pos, "Address is not constant")
357 # ----------------- Result Allocation -----------------
359 def result_in_temp(self):
360 # Return true if result is in a temporary owned by
361 # this node or one of its subexpressions. Overridden
362 # by certain nodes which can share the result of
363 # a subnode.
364 return self.is_temp
366 def allocate_target_temps(self, env, rhs):
367 # Perform temp allocation for the LHS of an assignment.
368 if debug_temp_alloc:
369 print("%s Allocating target temps" % self)
370 self.allocate_subexpr_temps(env)
371 self.is_target = True
372 if rhs:
373 rhs.release_temp(env)
374 self.release_subexpr_temps(env)
376 def allocate_temps(self, env, result = None):
377 # Allocate temporary variables for this node and
378 # all its sub-expressions. If a result is specified,
379 # this must be a temp node and the specified variable
380 # is used as the result instead of allocating a new
381 # one.
382 if debug_temp_alloc:
383 print("%s Allocating temps" % self)
384 self.allocate_subexpr_temps(env)
385 self.allocate_temp(env, result)
386 if self.is_temp:
387 self.release_subexpr_temps(env)
389 def allocate_subexpr_temps(self, env):
390 # Allocate temporary variables for all sub-expressions
391 # of this node.
392 if debug_temp_alloc:
393 print("%s Allocating temps for: %s" % (self, self.subexprs))
394 for node in self.subexpr_nodes():
395 if node:
396 if debug_temp_alloc:
397 print("%s Allocating temps for %s" % (self, node))
398 node.allocate_temps(env)
400 def allocate_temp(self, env, result = None):
401 # If this node requires a temporary variable for its
402 # result, allocate one, otherwise set the result to
403 # a C code fragment. If a result is specified,
404 # this must be a temp node and the specified variable
405 # is used as the result instead of allocating a new
406 # one.
407 if debug_temp_alloc:
408 print("%s Allocating temp" % self)
409 if result:
410 if not self.is_temp:
411 raise InternalError("Result forced on non-temp node")
412 self.result_code = result
413 elif self.is_temp:
414 type = self.type
415 if not type.is_void:
416 if type.is_pyobject:
417 type = PyrexTypes.py_object_type
418 self.result_code = env.allocate_temp(type)
419 else:
420 self.result_code = None
421 if debug_temp_alloc:
422 print("%s Allocated result %s" % (self, self.result_code))
424 def target_code(self):
425 # Return code fragment for use as LHS of a C assignment.
426 return self.calculate_result_code()
428 def calculate_result_code(self):
429 self.not_implemented("calculate_result_code")
431 # def release_target_temp(self, env):
432 # # Release temporaries used by LHS of an assignment.
433 # self.release_subexpr_temps(env)
435 def release_temp(self, env):
436 # If this node owns a temporary result, release it,
437 # otherwise release results of its sub-expressions.
438 if self.is_temp:
439 if debug_temp_alloc:
440 print("%s Releasing result %s" % (self, self.result_code))
441 env.release_temp(self.result_code)
442 else:
443 self.release_subexpr_temps(env)
445 def release_subexpr_temps(self, env):
446 # Release the results of all sub-expressions of
447 # this node.
448 for node in self.subexpr_nodes():
449 if node:
450 node.release_temp(env)
452 # ---------------- Code Generation -----------------
454 def make_owned_reference(self, code):
455 # If result is a pyobject, make sure we own
456 # a reference to it.
457 if self.type.is_pyobject and not self.result_in_temp():
458 code.put_incref(self.result(), self.ctype())
460 def generate_evaluation_code(self, code):
461 code.mark_pos(self.pos)
462 # Generate code to evaluate this node and
463 # its sub-expressions, and dispose of any
464 # temporary results of its sub-expressions.
465 self.generate_subexpr_evaluation_code(code)
466 self.generate_result_code(code)
467 if self.is_temp:
468 self.generate_subexpr_disposal_code(code)
469 self.free_subexpr_temps(code)
471 def generate_subexpr_evaluation_code(self, code):
472 for node in self.subexpr_nodes():
473 node.generate_evaluation_code(code)
475 def generate_result_code(self, code):
476 self.not_implemented("generate_result_code")
478 def generate_disposal_code(self, code):
479 # If necessary, generate code to dispose of
480 # temporary Python reference.
481 if self.is_temp:
482 if self.type.is_pyobject:
483 code.put_decref_clear(self.result(), self.ctype())
484 else:
485 self.generate_subexpr_disposal_code(code)
487 def generate_subexpr_disposal_code(self, code):
488 # Generate code to dispose of temporary results
489 # of all sub-expressions.
490 for node in self.subexpr_nodes():
491 node.generate_disposal_code(code)
493 def generate_post_assignment_code(self, code):
494 # Same as generate_disposal_code except that
495 # assignment will have absorbed a reference to
496 # the result if it is a Python object.
497 if self.is_temp:
498 if self.type.is_pyobject:
499 code.putln("%s = 0;" % self.result())
500 else:
501 self.generate_subexpr_disposal_code(code)
503 def generate_assignment_code(self, rhs, code):
504 # Stub method for nodes which are not legal as
505 # the LHS of an assignment. An error will have
506 # been reported earlier.
507 pass
509 def generate_deletion_code(self, code):
510 # Stub method for nodes that are not legal as
511 # the argument of a del statement. An error
512 # will have been reported earlier.
513 pass
515 def free_temps(self, code):
516 if not self.is_temp:
517 self.free_subexpr_temps(code)
518 # otherwise, already freed in generate_evaluation_code
520 def free_subexpr_temps(self, code):
521 for sub in self.subexpr_nodes():
522 sub.free_temps(code)
524 # ---------------- Annotation ---------------------
526 def annotate(self, code):
527 for node in self.subexpr_nodes():
528 node.annotate(code)
530 # ----------------- Coercion ----------------------
532 def coerce_to(self, dst_type, env):
533 # Coerce the result so that it can be assigned to
534 # something of type dst_type. If processing is necessary,
535 # wraps this node in a coercion node and returns that.
536 # Otherwise, returns this node unchanged.
537 #
538 # This method is called during the analyse_expressions
539 # phase of the src_node's processing.
540 src = self
541 src_type = self.type
542 src_is_py_type = src_type.is_pyobject
543 dst_is_py_type = dst_type.is_pyobject
545 if dst_type.is_pyobject:
546 if not src.type.is_pyobject:
547 src = CoerceToPyTypeNode(src, env)
548 if not src.type.subtype_of(dst_type):
549 if not isinstance(src, NoneNode):
550 src = PyTypeTestNode(src, dst_type, env)
551 elif src.type.is_pyobject:
552 src = CoerceFromPyTypeNode(dst_type, src, env)
553 else: # neither src nor dst are py types
554 # Added the string comparison, since for c types that
555 # is enough, but Cython gets confused when the types are
556 # in different files.
557 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
558 error(self.pos, "Cannot assign type '%s' to '%s'" %
559 (src.type, dst_type))
560 return src
562 def coerce_to_pyobject(self, env):
563 return self.coerce_to(PyrexTypes.py_object_type, env)
565 def coerce_to_boolean(self, env):
566 # Coerce result to something acceptable as
567 # a boolean value.
568 type = self.type
569 if type.is_pyobject or type.is_ptr or type.is_float:
570 return CoerceToBooleanNode(self, env)
571 else:
572 if not type.is_int and not type.is_error:
573 error(self.pos,
574 "Type '%s' not acceptable as a boolean" % type)
575 return self
577 def coerce_to_integer(self, env):
578 # If not already some C integer type, coerce to longint.
579 if self.type.is_int:
580 return self
581 else:
582 return self.coerce_to(PyrexTypes.c_long_type, env)
584 def coerce_to_temp(self, env):
585 # Ensure that the result is in a temporary.
586 if self.result_in_temp():
587 return self
588 else:
589 return CoerceToTempNode(self, env)
591 def coerce_to_simple(self, env):
592 # Ensure that the result is simple (see is_simple).
593 if self.is_simple():
594 return self
595 else:
596 return self.coerce_to_temp(env)
598 def is_simple(self):
599 # A node is simple if its result is something that can
600 # be referred to without performing any operations, e.g.
601 # a constant, local var, C global var, struct member
602 # reference, or temporary.
603 return self.result_in_temp()
605 def as_cython_attribute(self):
606 return None
609 class RemoveAllocateTemps(type):
610 def __init__(cls, name, bases, dct):
611 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
612 def noop(self, env): pass
613 setattr(cls, 'allocate_temps', noop)
614 setattr(cls, 'allocate_temp', noop)
615 setattr(cls, 'release_temp', noop)
617 class NewTempExprNode(ExprNode):
618 backwards_compatible_result = None
619 temp_code = None
620 old_temp = None # error checker for multiple frees etc.
622 # Do not enable this unless you are trying to make all ExprNodes
623 # NewTempExprNodes (child nodes reached via recursion may not have
624 # transferred).
625 # __metaclass__ = RemoveAllocateTemps
627 def result(self):
628 if self.is_temp:
629 return self.temp_code
630 else:
631 return self.calculate_result_code()
633 def allocate_target_temps(self, env, rhs):
634 self.allocate_subexpr_temps(env)
635 self.is_target = True
636 if rhs:
637 rhs.release_temp(env)
638 self.release_subexpr_temps(env)
640 def allocate_temps(self, env, result = None):
641 self.allocate_subexpr_temps(env)
642 self.backwards_compatible_result = result
643 if self.is_temp:
644 self.release_subexpr_temps(env)
646 def allocate_temp(self, env, result = None):
647 assert result is None
649 def release_temp(self, env):
650 if self.is_temp:
651 pass
652 else:
653 self.release_subexpr_temps(env)
655 def allocate_temp_result(self, code):
656 if self.temp_code:
657 raise RuntimeError("Temp allocated multiple times")
658 type = self.type
659 if not type.is_void:
660 if type.is_pyobject:
661 type = PyrexTypes.py_object_type
662 if self.backwards_compatible_result:
663 self.temp_code = self.backwards_compatible_result
664 else:
665 self.temp_code = code.funcstate.allocate_temp(
666 type, manage_ref=True)
667 else:
668 self.temp_code = None
670 def release_temp_result(self, code):
671 if not self.temp_code:
672 if self.old_temp:
673 raise RuntimeError("temp %s released multiple times in %s" % (
674 self.old_temp, self.__class__.__name__))
675 else:
676 raise RuntimeError("no temp, but release requested in %s" % (
677 self.__class__.__name__))
678 code.funcstate.release_temp(self.temp_code)
679 self.old_temp = self.temp_code
680 self.temp_code = None
682 def generate_evaluation_code(self, code):
683 code.mark_pos(self.pos)
685 # Generate code to evaluate this node and
686 # its sub-expressions, and dispose of any
687 # temporary results of its sub-expressions.
688 self.generate_subexpr_evaluation_code(code)
690 if self.is_temp:
691 self.allocate_temp_result(code)
693 self.generate_result_code(code)
694 if self.is_temp:
695 # If we are temp we do not need to wait until this node is disposed
696 # before disposing children.
697 self.generate_subexpr_disposal_code(code)
698 self.free_subexpr_temps(code)
700 def generate_disposal_code(self, code):
701 if self.is_temp:
702 if self.type.is_pyobject:
703 code.put_decref_clear(self.result(), self.ctype())
704 else:
705 # Already done if self.is_temp
706 self.generate_subexpr_disposal_code(code)
708 def generate_post_assignment_code(self, code):
709 if self.is_temp:
710 if self.type.is_pyobject:
711 code.putln("%s = 0;" % self.result())
712 else:
713 self.generate_subexpr_disposal_code(code)
715 def free_temps(self, code):
716 if self.is_temp:
717 if not self.type.is_void:
718 self.release_temp_result(code)
719 else:
720 self.free_subexpr_temps(code)
722 # ExprNode = NewTempExprNode
724 class AtomicExprNode(ExprNode):
725 # Abstract base class for expression nodes which have
726 # no sub-expressions.
728 subexprs = []
730 class AtomicNewTempExprNode(NewTempExprNode):
731 # I do not dare to convert NameNode yet. This is now
732 # ancestor of all former AtomicExprNode except
733 # NameNode. Should be renamed to AtomicExprNode
734 # when done.
736 # Abstract base class for expression nodes which have
737 # no sub-expressions.
739 subexprs = []
741 # Override to optimize -- we know we have no children
742 def generate_subexpr_evaluation_code(self, code):
743 pass
744 def generate_subexpr_disposal_code(self, code):
745 pass
747 class PyConstNode(AtomicNewTempExprNode):
748 # Abstract base class for constant Python values.
750 is_literal = 1
752 def is_simple(self):
753 return 1
755 def analyse_types(self, env):
756 self.type = py_object_type
758 def calculate_result_code(self):
759 return self.value
761 def generate_result_code(self, code):
762 pass
765 class NoneNode(PyConstNode):
766 # The constant value None
768 value = "Py_None"
770 constant_result = None
771 gil_check = None
773 def compile_time_value(self, denv):
774 return None
776 class EllipsisNode(PyConstNode):
777 # '...' in a subscript list.
779 value = "Py_Ellipsis"
781 constant_result = Ellipsis
783 def compile_time_value(self, denv):
784 return Ellipsis
787 class ConstNode(AtomicNewTempExprNode):
788 # Abstract base type for literal constant nodes.
789 #
790 # value string C code fragment
792 is_literal = 1
793 gil_check = None
795 def is_simple(self):
796 return 1
798 def analyse_types(self, env):
799 pass # Types are held in class variables
801 def check_const(self):
802 pass
804 def calculate_result_code(self):
805 return str(self.value)
807 def generate_result_code(self, code):
808 pass
811 class BoolNode(ConstNode):
812 type = PyrexTypes.c_bint_type
813 # The constant value True or False
815 def calculate_constant_result(self):
816 self.constant_result = self.value
818 def compile_time_value(self, denv):
819 return self.value
821 def calculate_result_code(self):
822 return str(int(self.value))
825 class NullNode(ConstNode):
826 type = PyrexTypes.c_null_ptr_type
827 value = "NULL"
828 constant_result = 0
831 class CharNode(ConstNode):
832 type = PyrexTypes.c_char_type
834 def calculate_constant_result(self):
835 self.constant_result = ord(self.value)
837 def compile_time_value(self, denv):
838 return ord(self.value)
840 def calculate_result_code(self):
841 return "'%s'" % StringEncoding.escape_character(self.value)
844 class IntNode(ConstNode):
846 # unsigned "" or "U"
847 # longness "" or "L" or "LL"
849 unsigned = ""
850 longness = ""
851 type = PyrexTypes.c_long_type
853 def coerce_to(self, dst_type, env):
854 if dst_type.is_numeric:
855 self.type = PyrexTypes.c_long_type
856 return self
857 # Arrange for a Python version of the number to be pre-allocated
858 # when coercing to a Python type.
859 if dst_type.is_pyobject:
860 self.type = PyrexTypes.py_object_type
861 # We still need to perform normal coerce_to processing on the
862 # result, because we might be coercing to an extension type,
863 # in which case a type test node will be needed.
864 return ConstNode.coerce_to(self, dst_type, env)
866 def coerce_to_boolean(self, env):
867 self.type = PyrexTypes.c_bint_type
868 return self
870 def generate_evaluation_code(self, code):
871 if self.type.is_pyobject:
872 self.result_code = code.get_py_num(self.value, self.longness)
873 else:
874 self.result_code = str(self.value) + self.unsigned + self.longness
876 def calculate_result_code(self):
877 return self.result_code
879 def calculate_constant_result(self):
880 self.constant_result = int(self.value, 0)
882 def compile_time_value(self, denv):
883 return int(self.value, 0)
886 class FloatNode(ConstNode):
887 type = PyrexTypes.c_double_type
889 def calculate_constant_result(self):
890 self.constant_result = float(self.value)
892 def compile_time_value(self, denv):
893 return float(self.value)
895 def calculate_result_code(self):
896 strval = repr(float(self.value))
897 if strval == 'nan':
898 return "(Py_HUGE_VAL * 0)"
899 elif strval == 'inf':
900 return "Py_HUGE_VAL"
901 elif strval == '-inf':
902 return "(-Py_HUGE_VAL)"
903 else:
904 return strval
907 class StringNode(ConstNode):
908 type = PyrexTypes.c_char_ptr_type
910 def compile_time_value(self, denv):
911 return self.value
913 def analyse_as_type(self, env):
914 type = PyrexTypes.parse_basic_type(self.value)
915 if type is not None:
916 return type
917 from TreeFragment import TreeFragment
918 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
919 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
920 sizeof_node = declaration.root.stats[0].expr
921 sizeof_node.analyse_types(env)
922 if isinstance(sizeof_node, SizeofTypeNode):
923 return sizeof_node.arg_type
925 def coerce_to(self, dst_type, env):
926 if dst_type == PyrexTypes.c_char_ptr_type:
927 self.type = PyrexTypes.c_char_ptr_type
928 return self
930 if dst_type.is_int:
931 if not self.type.is_pyobject and len(self.value) == 1:
932 return CharNode(self.pos, value=self.value)
933 else:
934 error(self.pos, "Only single-character byte strings can be coerced into ints.")
935 return self
936 # Arrange for a Python version of the string to be pre-allocated
937 # when coercing to a Python type.
938 if dst_type.is_pyobject and not self.type.is_pyobject:
939 node = self.as_py_string_node(env)
940 else:
941 node = self
942 # We still need to perform normal coerce_to processing on the
943 # result, because we might be coercing to an extension type,
944 # in which case a type test node will be needed.
945 return ConstNode.coerce_to(node, dst_type, env)
947 def as_py_string_node(self, env):
948 # Return a new StringNode with the same value as this node
949 # but whose type is a Python type instead of a C type.
950 return StringNode(self.pos, value = self.value, type = py_object_type)
952 def generate_evaluation_code(self, code):
953 if self.type.is_pyobject:
954 self.result_code = code.get_py_string_const(self.value)
955 else:
956 self.result_code = code.get_string_const(self.value)
958 def calculate_result_code(self):
959 return self.result_code
962 class UnicodeNode(PyConstNode):
963 type = unicode_type
965 def coerce_to(self, dst_type, env):
966 if dst_type.is_pyobject:
967 return self
968 else:
969 error(self.pos, "Unicode objects do not support coercion to C types.")
970 return self
972 def generate_evaluation_code(self, code):
973 if self.type.is_pyobject:
974 self.result_code = code.get_py_string_const(self.value)
975 else:
976 self.result_code = code.get_string_const(self.value)
978 def calculate_result_code(self):
979 return self.result_code
981 def compile_time_value(self, env):
982 return self.value
985 class IdentifierStringNode(ConstNode):
986 # A Python string that behaves like an identifier, e.g. for
987 # keyword arguments in a call, or for imported names
988 type = PyrexTypes.py_object_type
990 def generate_evaluation_code(self, code):
991 if self.type.is_pyobject:
992 self.result_code = code.get_py_string_const(self.value, True)
993 else:
994 self.result_code = code.get_string_const(self.value)
996 def calculate_result_code(self):
997 return self.result_code
1000 class LongNode(AtomicNewTempExprNode):
1001 # Python long integer literal
1003 # value string
1005 def calculate_constant_result(self):
1006 self.constant_result = long(self.value)
1008 def compile_time_value(self, denv):
1009 return long(self.value)
1011 def analyse_types(self, env):
1012 self.type = py_object_type
1013 self.is_temp = 1
1015 gil_message = "Constructing Python long int"
1017 def generate_result_code(self, code):
1018 code.putln(
1019 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1020 self.result(),
1021 self.value,
1022 code.error_goto_if_null(self.result(), self.pos)))
1023 code.put_gotref(self.py_result())
1026 class ImagNode(AtomicNewTempExprNode):
1027 # Imaginary number literal
1029 # value float imaginary part
1031 def calculate_constant_result(self):
1032 self.constant_result = complex(0.0, self.value)
1034 def compile_time_value(self, denv):
1035 return complex(0.0, self.value)
1037 def analyse_types(self, env):
1038 self.type = py_object_type
1039 self.is_temp = 1
1041 gil_message = "Constructing complex number"
1043 def generate_result_code(self, code):
1044 code.putln(
1045 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1046 self.result(),
1047 float(self.value),
1048 code.error_goto_if_null(self.result(), self.pos)))
1049 code.put_gotref(self.py_result())
1053 class NameNode(AtomicExprNode):
1054 # Reference to a local or global variable name.
1056 # name string Python name of the variable
1058 # entry Entry Symbol table entry
1060 is_name = True
1061 is_cython_module = False
1062 cython_attribute = None
1063 lhs_of_first_assignment = False
1064 is_used_as_rvalue = 0
1065 entry = None
1067 def create_analysed_rvalue(pos, env, entry):
1068 node = NameNode(pos)
1069 node.analyse_types(env, entry=entry)
1070 return node
1072 def as_cython_attribute(self):
1073 return self.cython_attribute
1075 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1077 def compile_time_value(self, denv):
1078 try:
1079 return denv.lookup(self.name)
1080 except KeyError:
1081 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1083 def coerce_to(self, dst_type, env):
1084 # If coercing to a generic pyobject and this is a builtin
1085 # C function with a Python equivalent, manufacture a NameNode
1086 # referring to the Python builtin.
1087 #print "NameNode.coerce_to:", self.name, dst_type ###
1088 if dst_type is py_object_type:
1089 entry = self.entry
1090 if entry and entry.is_cfunction:
1091 var_entry = entry.as_variable
1092 if var_entry:
1093 if var_entry.is_builtin and Options.cache_builtins:
1094 var_entry = env.declare_builtin(var_entry.name, self.pos)
1095 node = NameNode(self.pos, name = self.name)
1096 node.entry = var_entry
1097 node.analyse_rvalue_entry(env)
1098 return node
1099 return AtomicExprNode.coerce_to(self, dst_type, env)
1101 def analyse_as_module(self, env):
1102 # Try to interpret this as a reference to a cimported module.
1103 # Returns the module scope, or None.
1104 entry = self.entry
1105 if not entry:
1106 entry = env.lookup(self.name)
1107 if entry and entry.as_module:
1108 return entry.as_module
1109 return None
1111 def analyse_as_type(self, env):
1112 if self.cython_attribute:
1113 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1114 else:
1115 type = PyrexTypes.parse_basic_type(self.name)
1116 if type:
1117 return type
1118 entry = self.entry
1119 if not entry:
1120 entry = env.lookup(self.name)
1121 if entry and entry.is_type:
1122 return entry.type
1123 else:
1124 return None
1126 def analyse_as_extension_type(self, env):
1127 # Try to interpret this as a reference to an extension type.
1128 # Returns the extension type, or None.
1129 entry = self.entry
1130 if not entry:
1131 entry = env.lookup(self.name)
1132 if entry and entry.is_type and entry.type.is_extension_type:
1133 return entry.type
1134 else:
1135 return None
1137 def analyse_target_declaration(self, env):
1138 if not self.entry:
1139 self.entry = env.lookup_here(self.name)
1140 if not self.entry:
1141 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1142 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1143 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1144 if self.entry.is_declared_generic:
1145 self.result_ctype = py_object_type
1147 def analyse_types(self, env):
1148 if self.entry is None:
1149 self.entry = env.lookup(self.name)
1150 if not self.entry:
1151 self.entry = env.declare_builtin(self.name, self.pos)
1152 if not self.entry:
1153 self.type = PyrexTypes.error_type
1154 return
1155 self.analyse_rvalue_entry(env)
1157 def analyse_target_types(self, env):
1158 self.analyse_entry(env)
1159 if not self.is_lvalue():
1160 error(self.pos, "Assignment to non-lvalue '%s'"
1161 % self.name)
1162 self.type = PyrexTypes.error_type
1163 self.entry.used = 1
1164 if self.entry.type.is_buffer:
1165 import Buffer
1166 Buffer.used_buffer_aux_vars(self.entry)
1168 def analyse_rvalue_entry(self, env):
1169 #print "NameNode.analyse_rvalue_entry:", self.name ###
1170 #print "Entry:", self.entry.__dict__ ###
1171 self.analyse_entry(env)
1172 entry = self.entry
1173 if entry.is_declared_generic:
1174 self.result_ctype = py_object_type
1175 if entry.is_pyglobal or entry.is_builtin:
1176 if Options.cache_builtins and entry.is_builtin:
1177 self.is_temp = 0
1178 else:
1179 self.is_temp = 1
1180 self.is_used_as_rvalue = 1
1181 env.use_utility_code(get_name_interned_utility_code)
1183 def gil_check(self, env):
1184 if self.is_used_as_rvalue:
1185 entry = self.entry
1186 if entry.is_builtin:
1187 # if not Options.cache_builtins: # cached builtins are ok
1188 self._gil_check(env)
1189 elif entry.is_pyglobal:
1190 self._gil_check(env)
1192 gil_message = "Accessing Python global or builtin"
1194 def analyse_entry(self, env):
1195 #print "NameNode.analyse_entry:", self.name ###
1196 self.check_identifier_kind()
1197 entry = self.entry
1198 type = entry.type
1199 self.type = type
1201 def check_identifier_kind(self):
1202 #print "NameNode.check_identifier_kind:", self.entry.name ###
1203 #print self.entry.__dict__ ###
1204 entry = self.entry
1205 #entry.used = 1
1206 if not (entry.is_const or entry.is_variable
1207 or entry.is_builtin or entry.is_cfunction):
1208 if self.entry.as_variable:
1209 self.entry = self.entry.as_variable
1210 else:
1211 error(self.pos,
1212 "'%s' is not a constant, variable or function identifier" % self.name)
1214 def is_simple(self):
1215 # If it's not a C variable, it'll be in a temp.
1216 return 1
1218 def calculate_target_results(self, env):
1219 pass
1221 def check_const(self):
1222 entry = self.entry
1223 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1224 self.not_const()
1226 def check_const_addr(self):
1227 entry = self.entry
1228 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1229 self.addr_not_const()
1231 def is_lvalue(self):
1232 return self.entry.is_variable and \
1233 not self.entry.type.is_array and \
1234 not self.entry.is_readonly
1236 def is_ephemeral(self):
1237 # Name nodes are never ephemeral, even if the
1238 # result is in a temporary.
1239 return 0
1241 def allocate_temp(self, env, result = None):
1242 AtomicExprNode.allocate_temp(self, env, result)
1243 entry = self.entry
1244 if entry:
1245 entry.used = 1
1246 if entry.type.is_buffer:
1247 import Buffer
1248 Buffer.used_buffer_aux_vars(entry)
1249 if entry.utility_code:
1250 env.use_utility_code(entry.utility_code)
1252 def calculate_result_code(self):
1253 entry = self.entry
1254 if not entry:
1255 return "<error>" # There was an error earlier
1256 return entry.cname
1258 def generate_result_code(self, code):
1259 assert hasattr(self, 'entry')
1260 entry = self.entry
1261 if entry is None:
1262 return # There was an error earlier
1263 if entry.is_builtin and Options.cache_builtins:
1264 return # Lookup already cached
1265 elif entry.is_pyglobal or entry.is_builtin:
1266 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1267 interned_cname = code.intern_identifier(self.entry.name)
1268 if entry.is_builtin:
1269 namespace = Naming.builtins_cname
1270 else: # entry.is_pyglobal
1271 namespace = entry.scope.namespace_cname
1272 code.putln(
1273 '%s = __Pyx_GetName(%s, %s); %s' % (
1274 self.result(),
1275 namespace,
1276 interned_cname,
1277 code.error_goto_if_null(self.result(), self.pos)))
1278 code.put_gotref(self.py_result())
1280 elif entry.is_local and False:
1281 # control flow not good enough yet
1282 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1283 if assigned is False:
1284 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1285 elif not Options.init_local_none and assigned is None:
1286 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1287 (entry.cname, entry.name, code.error_goto(self.pos)))
1288 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1290 def generate_assignment_code(self, rhs, code):
1291 #print "NameNode.generate_assignment_code:", self.name ###
1292 entry = self.entry
1293 if entry is None:
1294 return # There was an error earlier
1296 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1297 and not self.lhs_of_first_assignment):
1298 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1300 # is_pyglobal seems to be True for module level-globals only.
1301 # We use this to access class->tp_dict if necessary.
1302 if entry.is_pyglobal:
1303 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1304 interned_cname = code.intern_identifier(self.entry.name)
1305 namespace = self.entry.scope.namespace_cname
1306 if entry.is_member:
1307 # if the entry is a member we have to cheat: SetAttr does not work
1308 # on types, so we create a descriptor which is then added to tp_dict
1309 code.put_error_if_neg(self.pos,
1310 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1311 namespace,
1312 interned_cname,
1313 rhs.py_result()))
1314 rhs.generate_disposal_code(code)
1315 rhs.free_temps(code)
1316 # in Py2.6+, we need to invalidate the method cache
1317 code.putln("PyType_Modified(%s);" %
1318 entry.scope.parent_type.typeptr_cname)
1319 else:
1320 code.put_error_if_neg(self.pos,
1321 'PyObject_SetAttr(%s, %s, %s)' % (
1322 namespace,
1323 interned_cname,
1324 rhs.py_result()))
1325 if debug_disposal_code:
1326 print("NameNode.generate_assignment_code:")
1327 print("...generating disposal code for %s" % rhs)
1328 rhs.generate_disposal_code(code)
1329 rhs.free_temps(code)
1330 else:
1331 if self.type.is_buffer:
1332 # Generate code for doing the buffer release/acquisition.
1333 # This might raise an exception in which case the assignment (done
1334 # below) will not happen.
1336 # The reason this is not in a typetest-like node is because the
1337 # variables that the acquired buffer info is stored to is allocated
1338 # per entry and coupled with it.
1339 self.generate_acquire_buffer(rhs, code)
1341 if self.type.is_pyobject:
1342 rhs.make_owned_reference(code)
1343 #print "NameNode.generate_assignment_code: to", self.name ###
1344 #print "...from", rhs ###
1345 #print "...LHS type", self.type, "ctype", self.ctype() ###
1346 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1347 if entry.is_cglobal:
1348 code.put_gotref(self.py_result())
1349 if not self.lhs_of_first_assignment:
1350 if entry.is_local and not Options.init_local_none:
1351 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1352 if initalized is True:
1353 code.put_decref(self.result(), self.ctype())
1354 elif initalized is None:
1355 code.put_xdecref(self.result(), self.ctype())
1356 else:
1357 code.put_decref(self.result(), self.ctype())
1358 if entry.is_cglobal:
1359 code.put_giveref(rhs.py_result())
1360 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1361 if debug_disposal_code:
1362 print("NameNode.generate_assignment_code:")
1363 print("...generating post-assignment code for %s" % rhs)
1364 rhs.generate_post_assignment_code(code)
1365 rhs.free_temps(code)
1367 def generate_acquire_buffer(self, rhs, code):
1368 # rhstmp is only used in case the rhs is a complicated expression leading to
1369 # the object, to avoid repeating the same C expression for every reference
1370 # to the rhs. It does NOT hold a reference.
1371 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1372 if pretty_rhs:
1373 rhstmp = rhs.result_as(self.ctype())
1374 else:
1375 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1376 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1378 buffer_aux = self.entry.buffer_aux
1379 bufstruct = buffer_aux.buffer_info_var.cname
1380 import Buffer
1381 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1382 is_initialized=not self.lhs_of_first_assignment,
1383 pos=self.pos, code=code)
1385 if not pretty_rhs:
1386 code.putln("%s = 0;" % rhstmp)
1387 code.funcstate.release_temp(rhstmp)
1389 def generate_deletion_code(self, code):
1390 if self.entry is None:
1391 return # There was an error earlier
1392 if not self.entry.is_pyglobal:
1393 error(self.pos, "Deletion of local or C global name not supported")
1394 return
1395 code.put_error_if_neg(self.pos,
1396 '__Pyx_DelAttrString(%s, "%s")' % (
1397 Naming.module_cname,
1398 self.entry.name))
1400 def annotate(self, code):
1401 if hasattr(self, 'is_called') and self.is_called:
1402 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1403 if self.type.is_pyobject:
1404 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1405 else:
1406 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1408 class BackquoteNode(ExprNode):
1409 # `expr`
1411 # arg ExprNode
1413 subexprs = ['arg']
1415 def analyse_types(self, env):
1416 self.arg.analyse_types(env)
1417 self.arg = self.arg.coerce_to_pyobject(env)
1418 self.type = py_object_type
1419 self.is_temp = 1
1421 gil_message = "Backquote expression"
1423 def calculate_constant_result(self):
1424 self.constant_result = repr(self.arg.constant_result)
1426 def generate_result_code(self, code):
1427 code.putln(
1428 "%s = PyObject_Repr(%s); %s" % (
1429 self.result(),
1430 self.arg.py_result(),
1431 code.error_goto_if_null(self.result(), self.pos)))
1432 code.put_gotref(self.py_result())
1436 class ImportNode(ExprNode):
1437 # Used as part of import statement implementation.
1438 # Implements result =
1439 # __import__(module_name, globals(), None, name_list)
1441 # module_name IdentifierStringNode dotted name of module
1442 # name_list ListNode or None list of names to be imported
1444 subexprs = ['module_name', 'name_list']
1446 def analyse_types(self, env):
1447 self.module_name.analyse_types(env)
1448 self.module_name = self.module_name.coerce_to_pyobject(env)
1449 if self.name_list:
1450 self.name_list.analyse_types(env)
1451 self.name_list.coerce_to_pyobject(env)
1452 self.type = py_object_type
1453 self.is_temp = 1
1454 env.use_utility_code(import_utility_code)
1456 gil_message = "Python import"
1458 def generate_result_code(self, code):
1459 if self.name_list:
1460 name_list_code = self.name_list.py_result()
1461 else:
1462 name_list_code = "0"
1463 code.putln(
1464 "%s = __Pyx_Import(%s, %s); %s" % (
1465 self.result(),
1466 self.module_name.py_result(),
1467 name_list_code,
1468 code.error_goto_if_null(self.result(), self.pos)))
1469 code.put_gotref(self.py_result())
1472 class IteratorNode(NewTempExprNode):
1473 # Used as part of for statement implementation.
1475 # allocate_counter_temp/release_counter_temp needs to be called
1476 # by parent (ForInStatNode)
1478 # Implements result = iter(sequence)
1480 # sequence ExprNode
1482 subexprs = ['sequence']
1484 def analyse_types(self, env):
1485 self.sequence.analyse_types(env)
1486 self.sequence = self.sequence.coerce_to_pyobject(env)
1487 self.type = py_object_type
1488 self.is_temp = 1
1490 gil_message = "Iterating over Python object"
1492 def allocate_counter_temp(self, code):
1493 self.counter_cname = code.funcstate.allocate_temp(
1494 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1496 def release_counter_temp(self, code):
1497 code.funcstate.release_temp(self.counter_cname)
1499 def generate_result_code(self, code):
1500 is_builtin_sequence = self.sequence.type is list_type or \
1501 self.sequence.type is tuple_type
1502 if is_builtin_sequence:
1503 code.putln(
1504 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1505 else:
1506 code.putln(
1507 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1508 self.sequence.py_result(),
1509 self.sequence.py_result()))
1510 code.putln(
1511 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1512 self.counter_cname,
1513 self.result(),
1514 self.sequence.py_result(),
1515 self.result()))
1516 code.putln("} else {")
1517 if is_builtin_sequence:
1518 code.putln(
1519 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1520 code.error_goto(self.pos))
1521 else:
1522 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1523 self.counter_cname,
1524 self.result(),
1525 self.sequence.py_result(),
1526 code.error_goto_if_null(self.result(), self.pos)))
1527 code.put_gotref(self.py_result())
1528 code.putln("}")
1531 class NextNode(AtomicNewTempExprNode):
1532 # Used as part of for statement implementation.
1533 # Implements result = iterator.next()
1534 # Created during analyse_types phase.
1535 # The iterator is not owned by this node.
1537 # iterator ExprNode
1539 def __init__(self, iterator, env):
1540 self.pos = iterator.pos
1541 self.iterator = iterator
1542 self.type = py_object_type
1543 self.is_temp = 1
1545 def generate_result_code(self, code):
1546 if self.iterator.sequence.type is list_type:
1547 type_checks = [(list_type, "List")]
1548 elif self.iterator.sequence.type is tuple_type:
1549 type_checks = [(tuple_type, "Tuple")]
1550 else:
1551 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1553 for py_type, prefix in type_checks:
1554 if len(type_checks) > 1:
1555 code.putln(
1556 "if (likely(Py%s_CheckExact(%s))) {" % (
1557 prefix, self.iterator.py_result()))
1558 code.putln(
1559 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1560 self.iterator.counter_cname,
1561 prefix,
1562 self.iterator.py_result()))
1563 code.putln(
1564 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1565 self.result(),
1566 prefix,
1567 self.iterator.py_result(),
1568 self.iterator.counter_cname,
1569 self.result(),
1570 self.iterator.counter_cname))
1571 if len(type_checks) > 1:
1572 code.put("} else ")
1573 if len(type_checks) == 1:
1574 return
1575 code.putln("{")
1576 code.putln(
1577 "%s = PyIter_Next(%s);" % (
1578 self.result(),
1579 self.iterator.py_result()))
1580 code.putln(
1581 "if (!%s) {" %
1582 self.result())
1583 code.putln(code.error_goto_if_PyErr(self.pos))
1584 code.putln("break;")
1585 code.putln("}")
1586 code.put_gotref(self.py_result())
1587 code.putln("}")
1590 class ExcValueNode(AtomicNewTempExprNode):
1591 # Node created during analyse_types phase
1592 # of an ExceptClauseNode to fetch the current
1593 # exception value.
1595 def __init__(self, pos, env, var):
1596 ExprNode.__init__(self, pos)
1597 self.type = py_object_type
1598 self.var = var
1600 def calculate_result_code(self):
1601 return self.var
1603 def generate_result_code(self, code):
1604 pass
1606 def analyse_types(self, env):
1607 pass
1610 class TempNode(ExprNode):
1611 # Node created during analyse_types phase
1612 # of some nodes to hold a temporary value.
1614 subexprs = []
1616 def __init__(self, pos, type, env):
1617 ExprNode.__init__(self, pos)
1618 self.type = type
1619 if type.is_pyobject:
1620 self.result_ctype = py_object_type
1621 self.is_temp = 1
1623 def analyse_types(self, env):
1624 return self.type
1626 def generate_result_code(self, code):
1627 pass
1630 class PyTempNode(TempNode):
1631 # TempNode holding a Python value.
1633 def __init__(self, pos, env):
1634 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1637 #-------------------------------------------------------------------
1639 # Trailer nodes
1641 #-------------------------------------------------------------------
1643 class IndexNode(ExprNode):
1644 # Sequence indexing.
1646 # base ExprNode
1647 # index ExprNode
1648 # indices [ExprNode]
1649 # is_buffer_access boolean Whether this is a buffer access.
1651 # indices is used on buffer access, index on non-buffer access.
1652 # The former contains a clean list of index parameters, the
1653 # latter whatever Python object is needed for index access.
1655 subexprs = ['base', 'index', 'indices']
1656 indices = None
1658 def __init__(self, pos, index, *args, **kw):
1659 ExprNode.__init__(self, pos, index=index, *args, **kw)
1660 self._index = index
1662 def calculate_constant_result(self):
1663 self.constant_result = \
1664 self.base.constant_result[self.index.constant_result]
1666 def compile_time_value(self, denv):
1667 base = self.base.compile_time_value(denv)
1668 index = self.index.compile_time_value(denv)
1669 try:
1670 return base[index]
1671 except Exception, e:
1672 self.compile_time_value_error(e)
1674 def is_ephemeral(self):
1675 return self.base.is_ephemeral()
1677 def analyse_target_declaration(self, env):
1678 pass
1680 def analyse_as_type(self, env):
1681 base_type = self.base.analyse_as_type(env)
1682 if base_type and not base_type.is_pyobject:
1683 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1684 return None
1686 def analyse_types(self, env):
1687 self.analyse_base_and_index_types(env, getting = 1)
1689 def analyse_target_types(self, env):
1690 self.analyse_base_and_index_types(env, setting = 1)
1692 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1693 # Note: This might be cleaned up by having IndexNode
1694 # parsed in a saner way and only construct the tuple if
1695 # needed.
1697 # Note that this function must leave IndexNode in a cloneable state.
1698 # For buffers, self.index is packed out on the initial analysis, and
1699 # when cloning self.indices is copied.
1700 self.is_buffer_access = False
1702 self.base.analyse_types(env)
1703 # Handle the case where base is a literal char* (and we expect a string, not an int)
1704 if isinstance(self.base, StringNode):
1705 self.base = self.base.coerce_to_pyobject(env)
1707 skip_child_analysis = False
1708 buffer_access = False
1709 if self.base.type.is_buffer:
1710 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1711 if self.indices:
1712 indices = self.indices
1713 else:
1714 # On cloning, indices is cloned. Otherwise, unpack index into indices
1715 assert not isinstance(self.index, CloneNode)
1716 if isinstance(self.index, TupleNode):
1717 indices = self.index.args
1718 else:
1719 indices = [self.index]
1720 if len(indices) == self.base.type.ndim:
1721 buffer_access = True
1722 skip_child_analysis = True
1723 for x in indices:
1724 x.analyse_types(env)
1725 if not x.type.is_int:
1726 buffer_access = False
1728 if buffer_access:
1729 self.indices = indices
1730 self.index = None
1731 self.type = self.base.type.dtype
1732 self.is_buffer_access = True
1733 self.buffer_type = self.base.entry.type
1735 if getting and self.type.is_pyobject:
1736 self.is_temp = True
1737 if setting:
1738 if not self.base.entry.type.writable:
1739 error(self.pos, "Writing to readonly buffer")
1740 else:
1741 self.base.entry.buffer_aux.writable_needed = True
1742 else:
1743 if isinstance(self.index, TupleNode):
1744 self.index.analyse_types(env, skip_children=skip_child_analysis)
1745 elif not skip_child_analysis:
1746 self.index.analyse_types(env)
1747 self.original_index_type = self.index.type
1748 if self.base.type.is_pyobject:
1749 if self.index.type.is_int:
1750 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1751 else:
1752 self.index = self.index.coerce_to_pyobject(env)
1753 self.type = py_object_type
1754 self.is_temp = 1
1755 else:
1756 if self.base.type.is_ptr or self.base.type.is_array:
1757 self.type = self.base.type.base_type
1758 else:
1759 error(self.pos,
1760 "Attempting to index non-array type '%s'" %
1761 self.base.type)
1762 self.type = PyrexTypes.error_type
1763 if self.index.type.is_pyobject:
1764 self.index = self.index.coerce_to(
1765 PyrexTypes.c_py_ssize_t_type, env)
1766 if not self.index.type.is_int:
1767 error(self.pos,
1768 "Invalid index type '%s'" %
1769 self.index.type)
1771 def gil_check(self, env):
1772 if not self.is_buffer_access:
1773 if self.base.type.is_pyobject:
1774 self._gil_check(env)
1776 gil_message = "Indexing Python object"
1778 def check_const_addr(self):
1779 self.base.check_const_addr()
1780 self.index.check_const()
1782 def is_lvalue(self):
1783 return 1
1785 def calculate_result_code(self):
1786 if self.is_buffer_access:
1787 return "(*%s)" % self.buffer_ptr_code
1788 else:
1789 return "(%s[%s])" % (
1790 self.base.result(), self.index.result())
1792 def extra_index_params(self):
1793 if self.index.type.is_int:
1794 if self.original_index_type.signed:
1795 size_adjustment = ""
1796 else:
1797 size_adjustment = "+1"
1798 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1799 else:
1800 return ""
1802 def generate_subexpr_evaluation_code(self, code):
1803 self.base.generate_evaluation_code(code)
1804 if not self.indices:
1805 self.index.generate_evaluation_code(code)
1806 else:
1807 for i in self.indices:
1808 i.generate_evaluation_code(code)
1810 def generate_subexpr_disposal_code(self, code):
1811 self.base.generate_disposal_code(code)
1812 if not self.indices:
1813 self.index.generate_disposal_code(code)
1814 else:
1815 for i in self.indices:
1816 i.generate_disposal_code(code)
1818 def free_subexpr_temps(self, code):
1819 self.base.free_temps(code)
1820 if not self.indices:
1821 self.index.free_temps(code)
1822 else:
1823 for i in self.indices:
1824 i.free_temps(code)
1826 def generate_result_code(self, code):
1827 if self.is_buffer_access:
1828 if code.globalstate.directives['nonecheck']:
1829 self.put_nonecheck(code)
1830 self.buffer_ptr_code = self.buffer_lookup_code(code)
1831 if self.type.is_pyobject:
1832 # is_temp is True, so must pull out value and incref it.
1833 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1834 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1835 elif self.type.is_pyobject:
1836 if self.index.type.is_int:
1837 index_code = self.index.result()
1838 if self.base.type is list_type:
1839 function = "__Pyx_GetItemInt_List"
1840 elif self.base.type is tuple_type:
1841 function = "__Pyx_GetItemInt_Tuple"
1842 else:
1843 function = "__Pyx_GetItemInt"
1844 code.globalstate.use_utility_code(getitem_int_utility_code)
1845 else:
1846 function = "PyObject_GetItem"
1847 index_code = self.index.py_result()
1848 sign_code = ""
1849 code.putln(
1850 "%s = %s(%s, %s%s); if (!%s) %s" % (
1851 self.result(),
1852 function,
1853 self.base.py_result(),
1854 index_code,
1855 self.extra_index_params(),
1856 self.result(),
1857 code.error_goto(self.pos)))
1858 code.put_gotref(self.py_result())
1860 def generate_setitem_code(self, value_code, code):
1861 if self.index.type.is_int:
1862 function = "__Pyx_SetItemInt"
1863 index_code = self.index.result()
1864 code.globalstate.use_utility_code(setitem_int_utility_code)
1865 else:
1866 index_code = self.index.py_result()
1867 if self.base.type is dict_type:
1868 function = "PyDict_SetItem"
1869 elif self.base.type is list_type:
1870 function = "PyList_SetItem"
1871 # don't use PyTuple_SetItem(), as we'd normally get a
1872 # TypeError when changing a tuple, while PyTuple_SetItem()
1873 # would allow updates
1875 #elif self.base.type is tuple_type:
1876 # function = "PyTuple_SetItem"
1877 else:
1878 function = "PyObject_SetItem"
1879 code.putln(
1880 "if (%s(%s, %s, %s%s) < 0) %s" % (
1881 function,
1882 self.base.py_result(),
1883 index_code,
1884 value_code,
1885 self.extra_index_params(),
1886 code.error_goto(self.pos)))
1888 def generate_buffer_setitem_code(self, rhs, code, op=""):
1889 # Used from generate_assignment_code and InPlaceAssignmentNode
1890 if code.globalstate.directives['nonecheck']:
1891 self.put_nonecheck(code)
1892 ptrexpr = self.buffer_lookup_code(code)
1893 if self.buffer_type.dtype.is_pyobject:
1894 # Must manage refcounts. Decref what is already there
1895 # and incref what we put in.
1896 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1897 rhs_code = rhs.result()
1898 code.putln("%s = %s;" % (ptr, ptrexpr))
1899 code.put_gotref("*%s" % ptr)
1900 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1901 ptr, rhs_code
1902 ))
1903 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1904 code.put_giveref("*%s" % ptr)
1905 code.funcstate.release_temp(ptr)
1906 else:
1907 # Simple case
1908 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1910 def generate_assignment_code(self, rhs, code):
1911 self.generate_subexpr_evaluation_code(code)
1912 if self.is_buffer_access:
1913 self.generate_buffer_setitem_code(rhs, code)
1914 elif self.type.is_pyobject:
1915 self.generate_setitem_code(rhs.py_result(), code)
1916 else:
1917 code.putln(
1918 "%s = %s;" % (
1919 self.result(), rhs.result()))
1920 self.generate_subexpr_disposal_code(code)
1921 self.free_subexpr_temps(code)
1922 rhs.generate_disposal_code(code)
1923 rhs.free_temps(code)
1925 def generate_deletion_code(self, code):
1926 self.generate_subexpr_evaluation_code(code)
1927 #if self.type.is_pyobject:
1928 if self.index.type.is_int:
1929 function = "__Pyx_DelItemInt"
1930 index_code = self.index.result()
1931 code.globalstate.use_utility_code(delitem_int_utility_code)
1932 else:
1933 index_code = self.index.py_result()
1934 if self.base.type is dict_type:
1935 function = "PyDict_DelItem"
1936 else:
1937 function = "PyObject_DelItem"
1938 code.putln(
1939 "if (%s(%s, %s%s) < 0) %s" % (
1940 function,
1941 self.base.py_result(),
1942 index_code,
1943 self.extra_index_params(),
1944 code.error_goto(self.pos)))
1945 self.generate_subexpr_disposal_code(code)
1946 self.free_subexpr_temps(code)
1948 def buffer_lookup_code(self, code):
1949 # Assign indices to temps
1950 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1951 for temp, index in zip(index_temps, self.indices):
1952 code.putln("%s = %s;" % (temp, index.result()))
1953 # Generate buffer access code using these temps
1954 import Buffer
1955 # The above could happen because child_attrs is wrong somewhere so that
1956 # options are not propagated.
1957 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1958 index_signeds=[i.type.signed for i in self.indices],
1959 index_cnames=index_temps,
1960 options=code.globalstate.directives,
1961 pos=self.pos, code=code)
1963 def put_nonecheck(self, code):
1964 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1965 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1966 code.putln("__Pyx_RaiseNoneIndexingError();")
1967 code.putln(code.error_goto(self.pos))
1968 code.putln("}")
1970 class SliceIndexNode(ExprNode):
1971 # 2-element slice indexing
1973 # base ExprNode
1974 # start ExprNode or None
1975 # stop ExprNode or None
1977 subexprs = ['base', 'start', 'stop']
1979 def calculate_constant_result(self):
1980 self.constant_result = self.base.constant_result[
1981 self.start.constant_result : self.stop.constant_result]
1983 def compile_time_value(self, denv):
1984 base = self.base.compile_time_value(denv)
1985 if self.start is None:
1986 start = 0
1987 else:
1988 start = self.start.compile_time_value(denv)
1989 if self.stop is None:
1990 stop = None
1991 else:
1992 stop = self.stop.compile_time_value(denv)
1993 try:
1994 return base[start:stop]
1995 except Exception, e:
1996 self.compile_time_value_error(e)
1998 def analyse_target_declaration(self, env):
1999 pass
2001 def analyse_types(self, env):
2002 self.base.analyse_types(env)
2003 if self.start:
2004 self.start.analyse_types(env)
2005 if self.stop:
2006 self.stop.analyse_types(env)
2007 if self.base.type.is_string:
2008 self.type = py_object_type
2009 elif self.base.type.is_array or self.base.type.is_ptr:
2010 # we need a ptr type here instead of an array type, as
2011 # array types can result in invalid type casts in the C
2012 # code
2013 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
2014 else:
2015 self.base = self.base.coerce_to_pyobject(env)
2016 self.type = py_object_type
2017 c_int = PyrexTypes.c_py_ssize_t_type
2018 if self.start:
2019 self.start = self.start.coerce_to(c_int, env)
2020 if self.stop:
2021 self.stop = self.stop.coerce_to(c_int, env)
2022 self.is_temp = 1
2024 gil_check = ExprNode._gil_check
2025 gil_message = "Slicing Python object"
2027 def generate_result_code(self, code):
2028 if not self.type.is_pyobject:
2029 error(self.pos,
2030 "Slicing is not currently supported for '%s'." % self.type)
2031 return
2032 if self.base.type.is_string:
2033 if self.stop is None:
2034 code.putln(
2035 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2036 self.result(),
2037 self.base.result(),
2038 self.start_code(),
2039 code.error_goto_if_null(self.result(), self.pos)))
2040 else:
2041 code.putln(
2042 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2043 self.result(),
2044 self.base.result(),
2045 self.start_code(),
2046 self.stop_code(),
2047 self.start_code(),
2048 code.error_goto_if_null(self.result(), self.pos)))
2049 else:
2050 code.putln(
2051 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2052 self.result(),
2053 self.base.py_result(),
2054 self.start_code(),
2055 self.stop_code(),
2056 code.error_goto_if_null(self.result(), self.pos)))
2057 code.put_gotref(self.py_result())
2059 def generate_assignment_code(self, rhs, code):
2060 self.generate_subexpr_evaluation_code(code)
2061 if self.type.is_pyobject:
2062 code.put_error_if_neg(self.pos,
2063 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2064 self.base.py_result(),
2065 self.start_code(),
2066 self.stop_code(),
2067 rhs.result()))
2068 else:
2069 start_offset = ''
2070 if self.start:
2071 start_offset = self.start_code()
2072 if start_offset == '0':
2073 start_offset = ''
2074 else:
2075 start_offset += '+'
2076 if rhs.type.is_array:
2077 array_length = rhs.type.size
2078 self.generate_slice_guard_code(code, array_length)
2079 else:
2080 error("Slice assignments from pointers are not yet supported.")
2081 # FIXME: fix the array size according to start/stop
2082 array_length = self.base.type.size
2083 for i in range(array_length):
2084 code.putln("%s[%s%s] = %s[%d];" % (
2085 self.base.result(), start_offset, i,
2086 rhs.result(), i))
2087 self.generate_subexpr_disposal_code(code)
2088 self.free_subexpr_temps(code)
2089 rhs.generate_disposal_code(code)
2090 rhs.free_temps(code)
2092 def generate_deletion_code(self, code):
2093 if not self.base.type.is_pyobject:
2094 error(self.pos,
2095 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2096 return
2097 self.generate_subexpr_evaluation_code(code)
2098 code.put_error_if_neg(self.pos,
2099 "PySequence_DelSlice(%s, %s, %s)" % (
2100 self.base.py_result(),
2101 self.start_code(),
2102 self.stop_code()))
2103 self.generate_subexpr_disposal_code(code)
2105 def generate_slice_guard_code(self, code, target_size):
2106 if not self.base.type.is_array:
2107 return
2108 slice_size = self.base.type.size
2109 start = stop = None
2110 if self.stop:
2111 stop = self.stop.result()
2112 try:
2113 stop = int(stop)
2114 if stop < 0:
2115 slice_size = self.base.type.size + stop
2116 else:
2117 slice_size = stop
2118 stop = None
2119 except ValueError:
2120 pass
2121 if self.start:
2122 start = self.start.result()
2123 try:
2124 start = int(start)
2125 if start < 0:
2126 start = self.base.type.size + start
2127 slice_size -= start
2128 start = None
2129 except ValueError:
2130 pass
2131 check = None
2132 if slice_size < 0:
2133 if target_size > 0:
2134 error(self.pos, "Assignment to empty slice.")
2135 elif start is None and stop is None:
2136 # we know the exact slice length
2137 if target_size != slice_size:
2138 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2139 slice_size, target_size))
2140 elif start is not None:
2141 if stop is None:
2142 stop = slice_size
2143 check = "(%s)-(%s)" % (stop, start)
2144 else: # stop is not None:
2145 check = stop
2146 if check:
2147 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2148 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2149 target_size, check))
2150 code.putln(code.error_goto(self.pos))
2151 code.putln("}")
2153 def start_code(self):
2154 if self.start:
2155 return self.start.result()
2156 else:
2157 return "0"
2159 def stop_code(self):
2160 if self.stop:
2161 return self.stop.result()
2162 elif self.base.type.is_array:
2163 return self.base.type.size
2164 else:
2165 return "PY_SSIZE_T_MAX"
2167 def calculate_result_code(self):
2168 # self.result() is not used, but this method must exist
2169 return "<unused>"
2172 class SliceNode(ExprNode):
2173 # start:stop:step in subscript list
2175 # start ExprNode
2176 # stop ExprNode
2177 # step ExprNode
2179 def calculate_constant_result(self):
2180 self.constant_result = self.base.constant_result[
2181 self.start.constant_result : \
2182 self.stop.constant_result : \
2183 self.step.constant_result]
2185 def compile_time_value(self, denv):
2186 start = self.start.compile_time_value(denv)
2187 if self.stop is None:
2188 stop = None
2189 else:
2190 stop = self.stop.compile_time_value(denv)
2191 if self.step is None:
2192 step = None
2193 else:
2194 step = self.step.compile_time_value(denv)
2195 try:
2196 return slice(start, stop, step)
2197 except Exception, e:
2198 self.compile_time_value_error(e)
2200 subexprs = ['start', 'stop', 'step']
2202 def analyse_types(self, env):
2203 self.start.analyse_types(env)
2204 self.stop.analyse_types(env)
2205 self.step.analyse_types(env)
2206 self.start = self.start.coerce_to_pyobject(env)
2207 self.stop = self.stop.coerce_to_pyobject(env)
2208 self.step = self.step.coerce_to_pyobject(env)
2209 self.type = py_object_type
2210 self.is_temp = 1
2212 gil_message = "Constructing Python slice object"
2214 def generate_result_code(self, code):
2215 code.putln(
2216 "%s = PySlice_New(%s, %s, %s); %s" % (
2217 self.result(),
2218 self.start.py_result(),
2219 self.stop.py_result(),
2220 self.step.py_result(),
2221 code.error_goto_if_null(self.result(), self.pos)))
2222 code.put_gotref(self.py_result())
2225 class CallNode(NewTempExprNode):
2226 def analyse_as_type_constructor(self, env):
2227 type = self.function.analyse_as_type(env)
2228 if type and type.is_struct_or_union:
2229 args, kwds = self.explicit_args_kwds()
2230 items = []
2231 for arg, member in zip(args, type.scope.var_entries):
2232 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2233 if kwds:
2234 items += kwds.key_value_pairs
2235 self.key_value_pairs = items
2236 self.__class__ = DictNode
2237 self.analyse_types(env)
2238 self.coerce_to(type, env)
2239 return True
2241 def gil_check(self, env):
2242 func_type = self.function_type()
2243 if func_type.is_pyobject:
2244 self._gil_check(env)
2245 elif not getattr(func_type, 'nogil', False):
2246 self._gil_check(env)
2248 gil_message = "Calling gil-requiring function"
2251 class SimpleCallNode(CallNode):
2252 # Function call without keyword, * or ** args.
2254 # function ExprNode
2255 # args [ExprNode]
2256 # arg_tuple ExprNode or None used internally
2257 # self ExprNode or None used internally
2258 # coerced_self ExprNode or None used internally
2259 # wrapper_call bool used internally
2260 # has_optional_args bool used internally
2262 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2264 self = None
2265 coerced_self = None
2266 arg_tuple = None
2267 wrapper_call = False
2268 has_optional_args = False
2270 def compile_time_value(self, denv):
2271 function = self.function.compile_time_value(denv)
2272 args = [arg.compile_time_value(denv) for arg in self.args]
2273 try:
2274 return function(*args)
2275 except Exception, e:
2276 self.compile_time_value_error(e)
2278 def analyse_as_type(self, env):
2279 attr = self.function.as_cython_attribute()
2280 if attr == 'pointer':
2281 if len(self.args) != 1:
2282 error(self.args.pos, "only one type allowed.")
2283 else:
2284 type = self.args[0].analyse_as_type(env)
2285 if not type:
2286 error(self.args[0].pos, "Unknown type")
2287 else:
2288 return PyrexTypes.CPtrType(type)
2290 def explicit_args_kwds(self):
2291 return self.args, None
2293 def analyse_types(self, env):
2294 if self.analyse_as_type_constructor(env):
2295 return
2296 function = self.function
2297 function.is_called = 1
2298 self.function.analyse_types(env)
2299 if function.is_attribute and function.is_py_attr and \
2300 function.attribute == "append" and len(self.args) == 1:
2301 # L.append(x) is almost always applied to a list
2302 self.py_func = self.function
2303 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2304 self.function.analyse_types(env)
2305 self.self = self.py_func.obj
2306 function.obj = CloneNode(self.self)
2307 env.use_utility_code(append_utility_code)
2308 if function.is_attribute and function.entry and function.entry.is_cmethod:
2309 # Take ownership of the object from which the attribute
2310 # was obtained, because we need to pass it as 'self'.
2311 self.self = function.obj
2312 function.obj = CloneNode(self.self)
2313 func_type = self.function_type()
2314 if func_type.is_pyobject:
2315 self.arg_tuple = TupleNode(self.pos, args = self.args)
2316 self.arg_tuple.analyse_types(env)
2317 self.args = None
2318 self.type = py_object_type
2319 self.is_temp = 1
2320 else:
2321 for arg in self.args:
2322 arg.analyse_types(env)
2323 if self.self and func_type.args:
2324 # Coerce 'self' to the type expected by the method.
2325 expected_type = func_type.args[0].type
2326 self.coerced_self = CloneNode(self.self).coerce_to(
2327 expected_type, env)
2328 # Insert coerced 'self' argument into argument list.
2329 self.args.insert(0, self.coerced_self)
2330 self.analyse_c_function_call(env)
2332 def function_type(self):
2333 # Return the type of the function being called, coercing a function
2334 # pointer to a function if necessary.
2335 func_type = self.function.type
2336 if func_type.is_ptr:
2337 func_type = func_type.base_type
2338 return func_type
2340 def analyse_c_function_call(self, env):
2341 func_type = self.function_type()
2342 # Check function type
2343 if not func_type.is_cfunction:
2344 if not func_type.is_error:
2345 error(self.pos, "Calling non-function type '%s'" %
2346 func_type)
2347 self.type = PyrexTypes.error_type
2348 self.result_code = "<error>"
2349 return
2350 # Check no. of args
2351 max_nargs = len(func_type.args)
2352 expected_nargs = max_nargs - func_type.optional_arg_count
2353 actual_nargs = len(self.args)
2354 if actual_nargs < expected_nargs \
2355 or (not func_type.has_varargs and actual_nargs > max_nargs):
2356 expected_str = str(expected_nargs)
2357 if func_type.has_varargs:
2358 expected_str = "at least " + expected_str
2359 elif func_type.optional_arg_count:
2360 if actual_nargs < max_nargs:
2361 expected_str = "at least " + expected_str
2362 else:
2363 expected_str = "at most " + str(max_nargs)
2364 error(self.pos,
2365 "Call with wrong number of arguments (expected %s, got %s)"
2366 % (expected_str, actual_nargs))
2367 self.args = None
2368 self.type = PyrexTypes.error_type
2369 self.result_code = "<error>"
2370 return
2371 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2372 self.has_optional_args = 1
2373 self.is_temp = 1
2374 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2375 env.release_temp(self.opt_arg_struct)
2376 # Coerce arguments
2377 for i in range(min(max_nargs, actual_nargs)):
2378 formal_type = func_type.args[i].type
2379 self.args[i] = self.args[i].coerce_to(formal_type, env)
2380 for i in range(max_nargs, actual_nargs):
2381 if self.args[i].type.is_pyobject:
2382 error(self.args[i].pos,
2383 "Python object cannot be passed as a varargs parameter")
2384 # Calc result type and code fragment
2385 self.type = func_type.return_type
2386 if self.type.is_pyobject:
2387 self.result_ctype = py_object_type
2388 self.is_temp = 1
2389 elif func_type.exception_value is not None \
2390 or func_type.exception_check:
2391 self.is_temp = 1
2392 # C++ exception handler
2393 if func_type.exception_check == '+':
2394 if func_type.exception_value is None:
2395 env.use_utility_code(cpp_exception_utility_code)
2397 def calculate_result_code(self):
2398 return self.c_call_code()
2400 def c_call_code(self):
2401 func_type = self.function_type()
2402 if self.args is None or not func_type.is_cfunction:
2403 return "<error>"
2404 formal_args = func_type.args
2405 arg_list_code = []
2406 args = zip(formal_args, self.args)
2407 max_nargs = len(func_type.args)
2408 expected_nargs = max_nargs - func_type.optional_arg_count
2409 actual_nargs = len(self.args)
2410 for formal_arg, actual_arg in args[:expected_nargs]:
2411 arg_code = actual_arg.result_as(formal_arg.type)
2412 arg_list_code.append(arg_code)
2414 if func_type.is_overridable:
2415 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2417 if func_type.optional_arg_count:
2418 if expected_nargs == actual_nargs:
2419 optional_args = 'NULL'
2420 else:
2421 optional_args = "&%s" % self.opt_arg_struct
2422 arg_list_code.append(optional_args)
2424 for actual_arg in self.args[len(formal_args):]:
2425 arg_list_code.append(actual_arg.result())
2426 result = "%s(%s)" % (self.function.result(),
2427 ', '.join(arg_list_code))
2428 # if self.wrapper_call or \
2429 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2430 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2431 return result
2433 def generate_result_code(self, code):
2434 func_type = self.function_type()
2435 if func_type.is_pyobject:
2436 arg_code = self.arg_tuple.py_result()
2437 code.putln(
2438 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2439 self.result(),
2440 self.function.py_result(),
2441 arg_code,
2442 code.error_goto_if_null(self.result(), self.pos)))
2443 code.put_gotref(self.py_result())
2444 elif func_type.is_cfunction:
2445 if self.has_optional_args:
2446 actual_nargs = len(self.args)
2447 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2448 code.putln("%s.%s = %s;" % (
2449 self.opt_arg_struct,
2450 Naming.pyrex_prefix + "n",
2451 len(self.args) - expected_nargs))
2452 args = zip(func_type.args, self.args)
2453 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2454 code.putln("%s.%s = %s;" % (
2455 self.opt_arg_struct,
2456 formal_arg.name,
2457 actual_arg.result_as(formal_arg.type)))
2458 exc_checks = []
2459 if self.type.is_pyobject:
2460 exc_checks.append("!%s" % self.result())
2461 else:
2462 exc_val = func_type.exception_value
2463 exc_check = func_type.exception_check
2464 if exc_val is not None:
2465 exc_checks.append("%s == %s" % (self.result(), exc_val))
2466 if exc_check:
2467 exc_checks.append("PyErr_Occurred()")
2468 if self.is_temp or exc_checks:
2469 rhs = self.c_call_code()
2470 if self.result():
2471 lhs = "%s = " % self.result()
2472 if self.is_temp and self.type.is_pyobject:
2473 #return_type = self.type # func_type.return_type
2474 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2475 # "from", return_type, "to pyobject" ###
2476 rhs = typecast(py_object_type, self.type, rhs)
2477 else:
2478 lhs = ""
2479 if func_type.exception_check == '+':
2480 if func_type.exception_value is None:
2481 raise_py_exception = "__Pyx_CppExn2PyErr()"
2482 elif func_type.exception_value.type.is_pyobject:
2483 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2484 else:
2485 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2486 code.putln(
2487 "try {%s%s;} catch(...) {%s; %s}" % (
2488 lhs,
2489 rhs,
2490 raise_py_exception,
2491 code.error_goto(self.pos)))
2492 else:
2493 if exc_checks:
2494 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2495 else:
2496 goto_error = ""
2497 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2498 if self.type.is_pyobject and self.result():
2499 code.put_gotref(self.py_result())
2502 class GeneralCallNode(CallNode):
2503 # General Python function call, including keyword,
2504 # * and ** arguments.
2506 # function ExprNode
2507 # positional_args ExprNode Tuple of positional arguments
2508 # keyword_args ExprNode or None Dict of keyword arguments
2509 # starstar_arg ExprNode or None Dict of extra keyword args
2511 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2513 gil_check = CallNode._gil_check
2515 def compile_time_value(self, denv):
2516 function = self.function.compile_time_value(denv)
2517 positional_args = self.positional_args.compile_time_value(denv)
2518 keyword_args = self.keyword_args.compile_time_value(denv)
2519 starstar_arg = self.starstar_arg.compile_time_value(denv)
2520 try:
2521 keyword_args.update(starstar_arg)
2522 return function(*positional_args, **keyword_args)
2523 except Exception, e:
2524 self.compile_time_value_error(e)
2526 def explicit_args_kwds(self):
2527 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2528 raise PostParseError(self.pos,
2529 'Compile-time keyword arguments must be explicit.')
2530 return self.positional_args.args, self.keyword_args
2532 def analyse_types(self, env):
2533 if self.analyse_as_type_constructor(env):
2534 return
2535 self.function.analyse_types(env)
2536 self.positional_args.analyse_types(env)
2537 if self.keyword_args:
2538 self.keyword_args.analyse_types(env)
2539 if self.starstar_arg:
2540 self.starstar_arg.analyse_types(env)
2541 self.function = self.function.coerce_to_pyobject(env)
2542 self.positional_args = \
2543 self.positional_args.coerce_to_pyobject(env)
2544 if self.starstar_arg:
2545 self.starstar_arg = \
2546 self.starstar_arg.coerce_to_pyobject(env)
2547 self.type = py_object_type
2548 self.is_temp = 1
2550 def generate_result_code(self, code):
2551 if self.keyword_args and self.starstar_arg:
2552 code.put_error_if_neg(self.pos,
2553 "PyDict_Update(%s, %s)" % (
2554 self.keyword_args.py_result(),
2555 self.starstar_arg.py_result()))
2556 keyword_code = self.keyword_args.py_result()
2557 elif self.keyword_args:
2558 keyword_code = self.keyword_args.py_result()
2559 elif self.starstar_arg:
2560 keyword_code = self.starstar_arg.py_result()
2561 else:
2562 keyword_code = None
2563 if not keyword_code:
2564 call_code = "PyObject_Call(%s, %s, NULL)" % (
2565 self.function.py_result(),
2566 self.positional_args.py_result())
2567 else:
2568 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2569 self.function.py_result(),
2570 self.positional_args.py_result(),
2571 keyword_code)
2572 code.putln(
2573 "%s = %s; %s" % (
2574 self.result(),
2575 call_code,
2576 code.error_goto_if_null(self.result(), self.pos)))
2577 code.put_gotref(self.py_result())
2580 class AsTupleNode(ExprNode):
2581 # Convert argument to tuple. Used for normalising
2582 # the * argument of a function call.
2584 # arg ExprNode
2586 subexprs = ['arg']
2588 def calculate_constant_result(self):
2589 self.constant_result = tuple(self.base.constant_result)
2591 def compile_time_value(self, denv):
2592 arg = self.arg.compile_time_value(denv)
2593 try:
2594 return tuple(arg)
2595 except Exception, e:
2596 self.compile_time_value_error(e)
2598 def analyse_types(self, env):
2599 self.arg.analyse_types(env)
2600 self.arg = self.arg.coerce_to_pyobject(env)
2601 self.type = tuple_type
2602 self.is_temp = 1
2604 gil_check = ExprNode._gil_check
2605 gil_message = "Constructing Python tuple"
2607 def generate_result_code(self, code):
2608 code.putln(
2609 "%s = PySequence_Tuple(%s); %s" % (
2610 self.result(),
2611 self.arg.py_result(),
2612 code.error_goto_if_null(self.result(), self.pos)))
2613 code.put_gotref(self.py_result())
2616 class AttributeNode(NewTempExprNode):
2617 # obj.attribute
2619 # obj ExprNode
2620 # attribute string
2621 # needs_none_check boolean Used if obj is an extension type.
2622 # If set to True, it is known that the type is not None.
2624 # Used internally:
2626 # is_py_attr boolean Is a Python getattr operation
2627 # member string C name of struct member
2628 # is_called boolean Function call is being done on result
2629 # entry Entry Symbol table entry of attribute
2631 is_attribute = 1
2632 subexprs = ['obj']
2634 type = PyrexTypes.error_type
2635 entry = None
2636 is_called = 0
2637 needs_none_check = True
2639 def as_cython_attribute(self):
2640 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2641 return self.attribute
2643 def coerce_to(self, dst_type, env):
2644 # If coercing to a generic pyobject and this is a cpdef function
2645 # we can create the corresponding attribute
2646 if dst_type is py_object_type:
2647 entry = self.entry
2648 if entry and entry.is_cfunction and entry.as_variable:
2649 # must be a cpdef function
2650 self.is_temp = 1
2651 self.entry = entry.as_variable
2652 self.analyse_as_python_attribute(env)
2653 return self
2654 return ExprNode.coerce_to(self, dst_type, env)
2656 def calculate_constant_result(self):
2657 attr = self.attribute
2658 if attr.startswith("__") and attr.endswith("__"):
2659 return
2660 self.constant_result = getattr(self.obj.constant_result, attr)
2662 def compile_time_value(self, denv):
2663 attr = self.attribute
2664 if attr.startswith("__") and attr.endswith("__"):
2665 self.error("Invalid attribute name '%s' in compile-time expression"
2666 % attr)
2667 return None
2668 obj = self.obj.compile_time_value(denv)
2669 try:
2670 return getattr(obj, attr)
2671 except Exception, e:
2672 self.compile_time_value_error(e)
2674 def analyse_target_declaration(self, env):
2675 pass
2677 def analyse_target_types(self, env):
2678 self.analyse_types(env, target = 1)
2680 def analyse_types(self, env, target = 0):
2681 if self.analyse_as_cimported_attribute(env, target):
2682 return
2683 if not target and self.analyse_as_unbound_cmethod(env):
2684 return
2685 self.analyse_as_ordinary_attribute(env, target)
2687 def analyse_as_cimported_attribute(self, env, target):
2688 # Try to interpret this as a reference to an imported
2689 # C const, type, var or function. If successful, mutates
2690 # this node into a NameNode and returns 1, otherwise
2691 # returns 0.
2692 module_scope = self.obj.analyse_as_module(env)
2693 if module_scope:
2694 entry = module_scope.lookup_here(self.attribute)
2695 if entry and (
2696 entry.is_cglobal or entry.is_cfunction
2697 or entry.is_type or entry.is_const):
2698 self.mutate_into_name_node(env, entry, target)
2699 return 1
2700 return 0
2702 def analyse_as_unbound_cmethod(self, env):
2703 # Try to interpret this as a reference to an unbound
2704 # C method of an extension type. If successful, mutates
2705 # this node into a NameNode and returns 1, otherwise
2706 # returns 0.
2707 type = self.obj.analyse_as_extension_type(env)
2708 if type:
2709 entry = type.scope.lookup_here(self.attribute)
2710 if entry and entry.is_cmethod:
2711 # Create a temporary entry describing the C method
2712 # as an ordinary function.
2713 ubcm_entry = Symtab.Entry(entry.name,
2714 "%s->%s" % (type.vtabptr_cname, entry.cname),
2715 entry.type)
2716 ubcm_entry.is_cfunction = 1
2717 ubcm_entry.func_cname = entry.func_cname
2718 ubcm_entry.is_unbound_cmethod = 1
2719 self.mutate_into_name_node(env, ubcm_entry, None)
2720 return 1
2721 return 0
2723 def analyse_as_type(self, env):
2724 module_scope = self.obj.analyse_as_module(env)
2725 if module_scope:
2726 return module_scope.lookup_type(self.attribute)
2727 return None
2729 def analyse_as_extension_type(self, env):
2730 # Try to interpret this as a reference to an extension type
2731 # in a cimported module. Returns the extension type, or None.
2732 module_scope = self.obj.analyse_as_module(env)
2733 if module_scope:
2734 entry = module_scope.lookup_here(self.attribute)
2735 if entry and entry.is_type and entry.type.is_extension_type:
2736 return entry.type
2737 return None
2739 def analyse_as_module(self, env):
2740 # Try to interpret this as a reference to a cimported module
2741 # in another cimported module. Returns the module scope, or None.
2742 module_scope = self.obj.analyse_as_module(env)
2743 if module_scope:
2744 entry = module_scope.lookup_here(self.attribute)
2745 if entry and entry.as_module:
2746 return entry.as_module
2747 return None
2749 def mutate_into_name_node(self, env, entry, target):
2750 # Mutate this node into a NameNode and complete the
2751 # analyse_types phase.
2752 self.__class__ = NameNode
2753 self.name = self.attribute
2754 self.entry = entry
2755 del self.obj
2756 del self.attribute
2757 if target:
2758 NameNode.analyse_target_types(self, env)
2759 else:
2760 NameNode.analyse_rvalue_entry(self, env)
2762 def analyse_as_ordinary_attribute(self, env, target):
2763 self.obj.analyse_types(env)
2764 self.analyse_attribute(env)
2765 if self.entry and self.entry.is_cmethod and not self.is_called:
2766 # error(self.pos, "C method can only be called")
2767 pass
2768 ## Reference to C array turns into pointer to first element.
2769 #while self.type.is_array:
2770 # self.type = self.type.element_ptr_type()
2771 if self.is_py_attr:
2772 if not target:
2773 self.is_temp = 1
2774 self.result_ctype = py_object_type
2776 def analyse_attribute(self, env):
2777 # Look up attribute and set self.type and self.member.
2778 self.is_py_attr = 0
2779 self.member = self.attribute
2780 if self.obj.type.is_string:
2781 self.obj = self.obj.coerce_to_pyobject(env)
2782 obj_type = self.obj.type
2783 if obj_type.is_ptr or obj_type.is_array:
2784 obj_type = obj_type.base_type
2785 self.op = "->"
2786 elif obj_type.is_extension_type:
2787 self.op = "->"
2788 else:
2789 self.op = "."
2790 if obj_type.has_attributes:
2791 entry = None
2792 if obj_type.attributes_known():
2793 entry = obj_type.scope.lookup_here(self.attribute)
2794 if entry and entry.is_member:
2795 entry = None
2796 else:
2797 error(self.pos,
2798 "Cannot select attribute of incomplete type '%s'"
2799 % obj_type)
2800 self.type = PyrexTypes.error_type
2801 return
2802 self.entry = entry
2803 if entry:
2804 if obj_type.is_extension_type and entry.name == "__weakref__":
2805 error(self.pos, "Illegal use of special attribute __weakref__")
2806 # methods need the normal attribute lookup
2807 # because they do not have struct entries
2808 if entry.is_variable or entry.is_cmethod:
2809 self.type = entry.type
2810 self.member = entry.cname
2811 return
2812 else:
2813 # If it's not a variable or C method, it must be a Python
2814 # method of an extension type, so we treat it like a Python
2815 # attribute.
2816 pass
2817 # If we get here, the base object is not a struct/union/extension
2818 # type, or it is an extension type and the attribute is either not
2819 # declared or is declared as a Python method. Treat it as a Python
2820 # attribute reference.
2821 self.analyse_as_python_attribute(env)
2823 def analyse_as_python_attribute(self, env):
2824 obj_type = self.obj.type
2825 self.member = self.attribute
2826 if obj_type.is_pyobject:
2827 self.type = py_object_type
2828 self.is_py_attr = 1
2829 else:
2830 if not obj_type.is_error:
2831 error(self.pos,
2832 "Object of type '%s' has no attribute '%s'" %
2833 (obj_type, self.attribute))
2835 def gil_check(self, env):
2836 if self.is_py_attr:
2837 self._gil_check(env)
2839 gil_message = "Accessing Python attribute"
2841 def is_simple(self):
2842 if self.obj:
2843 return self.result_in_temp() or self.obj.is_simple()
2844 else:
2845 return NameNode.is_simple(self)
2847 def is_lvalue(self):
2848 if self.obj:
2849 return 1
2850 else:
2851 return NameNode.is_lvalue(self)
2853 def is_ephemeral(self):
2854 if self.obj:
2855 return self.obj.is_ephemeral()
2856 else:
2857 return NameNode.is_ephemeral(self)
2859 def calculate_result_code(self):
2860 #print "AttributeNode.calculate_result_code:", self.member ###
2861 #print "...obj node =", self.obj, "code", self.obj.result() ###
2862 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2863 obj = self.obj
2864 obj_code = obj.result_as(obj.type)
2865 #print "...obj_code =", obj_code ###
2866 if self.entry and self.entry.is_cmethod:
2867 if obj.type.is_extension_type:
2868 return "((struct %s *)%s%s%s)->%s" % (
2869 obj.type.vtabstruct_cname, obj_code, self.op,
2870 obj.type.vtabslot_cname, self.member)
2871 else:
2872 return self.member
2873 else:
2874 return "%s%s%s" % (obj_code, self.op, self.member)
2876 def generate_result_code(self, code):
2877 interned_attr_cname = code.intern_identifier(self.attribute)
2878 if self.is_py_attr:
2879 code.putln(
2880 '%s = PyObject_GetAttr(%s, %s); %s' % (
2881 self.result(),
2882 self.obj.py_result(),
2883 interned_attr_cname,
2884 code.error_goto_if_null(self.result(), self.pos)))
2885 code.put_gotref(self.py_result())
2886 else:
2887 # result_code contains what is needed, but we may need to insert
2888 # a check and raise an exception
2889 if (self.obj.type.is_extension_type
2890 and self.needs_none_check
2891 and code.globalstate.directives['nonecheck']):
2892 self.put_nonecheck(code)
2894 def generate_assignment_code(self, rhs, code):
2895 interned_attr_cname = code.intern_identifier(self.attribute)
2896 self.obj.generate_evaluation_code(code)
2897 if self.is_py_attr:
2898 code.put_error_if_neg(self.pos,
2899 'PyObject_SetAttr(%s, %s, %s)' % (
2900 self.obj.py_result(),
2901 interned_attr_cname,
2902 rhs.py_result()))
2903 rhs.generate_disposal_code(code)
2904 rhs.free_temps(code)
2905 else:
2906 if (self.obj.type.is_extension_type
2907 and self.needs_none_check
2908 and code.globalstate.directives['nonecheck']):
2909 self.put_nonecheck(code)
2911 select_code = self.result()
2912 if self.type.is_pyobject:
2913 rhs.make_owned_reference(code)
2914 code.put_giveref(rhs.py_result())
2915 code.put_gotref(select_code)
2916 code.put_decref(select_code, self.ctype())
2917 code.putln(
2918 "%s = %s;" % (
2919 select_code,
2920 rhs.result_as(self.ctype())))
2921 #rhs.result()))
2922 rhs.generate_post_assignment_code(code)
2923 rhs.free_temps(code)
2924 self.obj.generate_disposal_code(code)
2925 self.obj.free_temps(code)
2927 def generate_deletion_code(self, code):
2928 interned_attr_cname = code.intern_identifier(self.attribute)
2929 self.obj.generate_evaluation_code(code)
2930 if self.is_py_attr:
2931 code.put_error_if_neg(self.pos,
2932 'PyObject_DelAttr(%s, %s)' % (
2933 self.obj.py_result(),
2934 interned_attr_cname))
2935 else:
2936 error(self.pos, "Cannot delete C attribute of extension type")
2937 self.obj.generate_disposal_code(code)
2938 self.obj.free_temps(code)
2940 def annotate(self, code):
2941 if self.is_py_attr:
2942 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2943 else:
2944 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2946 def put_nonecheck(self, code):
2947 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2948 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2949 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2950 code.putln(code.error_goto(self.pos))
2951 code.putln("}")
2954 #-------------------------------------------------------------------
2956 # Constructor nodes
2958 #-------------------------------------------------------------------
2960 class SequenceNode(NewTempExprNode):
2961 # Base class for list and tuple constructor nodes.
2962 # Contains common code for performing sequence unpacking.
2964 # args [ExprNode]
2965 # iterator ExprNode
2966 # unpacked_items [ExprNode] or None
2967 # coerced_unpacked_items [ExprNode] or None
2969 subexprs = ['args']
2971 is_sequence_constructor = 1
2972 unpacked_items = None
2974 def compile_time_value_list(self, denv):
2975 return [arg.compile_time_value(denv) for arg in self.args]
2977 def analyse_target_declaration(self, env):
2978 for arg in self.args:
2979 arg.analyse_target_declaration(env)
2981 def analyse_types(self, env, skip_children=False):
2982 for i in range(len(self.args)):
2983 arg = self.args[i]
2984 if not skip_children: arg.analyse_types(env)
2985 self.args[i] = arg.coerce_to_pyobject(env)
2986 self.type = py_object_type
2987 self.is_temp = 1
2989 def analyse_target_types(self, env):
2990 self.iterator = PyTempNode(self.pos, env)
2991 self.unpacked_items = []
2992 self.coerced_unpacked_items = []
2993 for arg in self.args:
2994 arg.analyse_target_types(env)
2995 unpacked_item = PyTempNode(self.pos, env)
2996 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2997 self.unpacked_items.append(unpacked_item)
2998 self.coerced_unpacked_items.append(coerced_unpacked_item)
2999 self.type = py_object_type
3000 env.use_utility_code(unpacking_utility_code)
3002 def allocate_target_temps(self, env, rhs):
3003 self.iterator.allocate_temps(env)
3004 for arg, node in zip(self.args, self.coerced_unpacked_items):
3005 node.allocate_temps(env)
3006 arg.allocate_target_temps(env, None)
3007 #arg.release_target_temp(env)
3008 #node.release_temp(env)
3009 if rhs:
3010 rhs.release_temp(env)
3011 self.iterator.release_temp(env)
3012 for node in self.coerced_unpacked_items:
3013 node.release_temp(env)
3015 # def release_target_temp(self, env):
3016 # #for arg in self.args:
3017 # # arg.release_target_temp(env)
3018 # #for node in self.coerced_unpacked_items:
3019 # # node.release_temp(env)
3020 # self.iterator.release_temp(env)
3022 def generate_result_code(self, code):
3023 self.generate_operation_code(code)
3025 def generate_assignment_code(self, rhs, code):
3026 # Need to work around the fact that generate_evaluation_code
3027 # allocates the temps in a rather hacky way -- the assignment
3028 # is evaluated twice, within each if-block.
3030 if rhs.type is tuple_type:
3031 tuple_check = "likely(%s != Py_None)"
3032 else:
3033 tuple_check = "PyTuple_CheckExact(%s)"
3034 code.putln(
3035 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3036 tuple_check % rhs.py_result(),
3037 rhs.py_result(),
3038 len(self.args)))
3039 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3040 for i in range(len(self.args)):
3041 item = self.unpacked_items[i]
3042 code.put(
3043 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3044 item.result(),
3045 i))
3046 code.put_incref(item.result(), item.ctype())
3047 value_node = self.coerced_unpacked_items[i]
3048 value_node.generate_evaluation_code(code)
3049 rhs.generate_disposal_code(code)
3051 for i in range(len(self.args)):
3052 self.args[i].generate_assignment_code(
3053 self.coerced_unpacked_items[i], code)
3055 code.putln("} else {")
3057 if rhs.type is tuple_type:
3058 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3059 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3060 rhs.py_result(), len(self.args)))
3061 code.putln(code.error_goto(self.pos))
3062 else:
3063 code.putln(
3064 "%s = PyObject_GetIter(%s); %s" % (
3065 self.iterator.result(),
3066 rhs.py_result(),
3067 code.error_goto_if_null(self.iterator.result(), self.pos)))
3068 code.put_gotref(self.iterator.py_result())
3069 rhs.generate_disposal_code(code)
3070 for i in range(len(self.args)):
3071 item = self.unpacked_items[i]
3072 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3073 self.iterator.py_result(), i)
3074 code.putln(
3075 "%s = %s; %s" % (
3076 item.result(),
3077 typecast(item.ctype(), py_object_type, unpack_code),
3078 code.error_goto_if_null(item.result(), self.pos)))
3079 code.put_gotref(item.py_result())
3080 value_node = self.coerced_unpacked_items[i]
3081 value_node.generate_evaluation_code(code)
3082 code.put_error_if_neg(self.pos,
3083 "__Pyx_EndUnpack(%s)" % (
3084 self.iterator.py_result()))
3085 if debug_disposal_code:
3086 print("UnpackNode.generate_assignment_code:")
3087 print("...generating disposal code for %s" % self.iterator)
3088 self.iterator.generate_disposal_code(code)
3089 self.iterator.free_temps(code)
3091 for i in range(len(self.args)):
3092 self.args[i].generate_assignment_code(
3093 self.coerced_unpacked_items[i], code)
3095 code.putln("}")
3096 rhs.free_temps(code)
3098 def annotate(self, code):
3099 for arg in self.args:
3100 arg.annotate(code)
3101 if self.unpacked_items:
3102 for arg in self.unpacked_items:
3103 arg.annotate(code)
3104 for arg in self.coerced_unpacked_items:
3105 arg.annotate(code)
3108 class TupleNode(SequenceNode):
3109 # Tuple constructor.
3111 gil_message = "Constructing Python tuple"
3113 def analyse_types(self, env, skip_children=False):
3114 if len(self.args) == 0:
3115 self.is_temp = 0
3116 self.is_literal = 1
3117 else:
3118 SequenceNode.analyse_types(self, env, skip_children)
3119 self.type = tuple_type
3121 def calculate_result_code(self):
3122 if len(self.args) > 0:
3123 error(self.pos, "Positive length tuples must be constructed.")
3124 else:
3125 return Naming.empty_tuple
3127 def calculate_constant_result(self):
3128 self.constant_result = tuple([
3129 arg.constant_result for arg in self.args])
3131 def compile_time_value(self, denv):
3132 values = self.compile_time_value_list(denv)
3133 try:
3134 return tuple(values)
3135 except Exception, e:
3136 self.compile_time_value_error(e)
3138 def generate_operation_code(self, code):
3139 if len(self.args) == 0:
3140 # result_code is Naming.empty_tuple
3141 return
3142 code.putln(
3143 "%s = PyTuple_New(%s); %s" % (
3144 self.result(),
3145 len(self.args),
3146 code.error_goto_if_null(self.result(), self.pos)))
3147 code.put_gotref(self.py_result())
3148 for i in range(len(self.args)):
3149 arg = self.args[i]
3150 if not arg.result_in_temp():
3151 code.put_incref(arg.result(), arg.ctype())
3152 code.putln(
3153 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3154 self.result(),
3155 i,
3156 arg.py_result()))
3157 code.put_giveref(arg.py_result())
3159 def generate_subexpr_disposal_code(self, code):
3160 # We call generate_post_assignment_code here instead
3161 # of generate_disposal_code, because values were stored
3162 # in the tuple using a reference-stealing operation.
3163 for arg in self.args:
3164 arg.generate_post_assignment_code(code)
3165 # Should NOT call free_temps -- this is invoked by the default
3166 # generate_evaluation_code which will do that.
3169 class ListNode(SequenceNode):
3170 # List constructor.
3172 # obj_conversion_errors [PyrexError] used internally
3173 # orignial_args [ExprNode] used internally
3175 gil_message = "Constructing Python list"
3177 def analyse_expressions(self, env):
3178 SequenceNode.analyse_expressions(self, env)
3179 self.coerce_to_pyobject(env)
3181 def analyse_types(self, env):
3182 hold_errors()
3183 self.original_args = list(self.args)
3184 SequenceNode.analyse_types(self, env)
3185 self.type = list_type
3186 self.obj_conversion_errors = held_errors()
3187 release_errors(ignore=True)
3189 def coerce_to(self, dst_type, env):
3190 if dst_type.is_pyobject:
3191 for err in self.obj_conversion_errors:
3192 report_error(err)
3193 self.obj_conversion_errors = []
3194 if not self.type.subtype_of(dst_type):
3195 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3196 elif dst_type.is_ptr:
3197 base_type = dst_type.base_type
3198 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3199 for i in range(len(self.original_args)):
3200 arg = self.args[i]
3201 if isinstance(arg, CoerceToPyTypeNode):
3202 arg = arg.arg
3203 self.args[i] = arg.coerce_to(base_type, env)
3204 elif dst_type.is_struct:
3205 if len(self.args) > len(dst_type.scope.var_entries):
3206 error(self.pos, "Too may members for '%s'" % dst_type)
3207 else:
3208 if len(self.args) < len(dst_type.scope.var_entries):
3209 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3210 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3211 if isinstance(arg, CoerceToPyTypeNode):
3212 arg = arg.arg
3213 self.args[i] = arg.coerce_to(member.type, env)
3214 self.type = dst_type
3215 else:
3216 self.type = error_type
3217 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3218 return self
3220 def release_temp(self, env):
3221 if self.type.is_array:
3222 # To be valid C++, we must allocate the memory on the stack
3223 # manually and be sure not to reuse it for something else.
3224 pass
3225 else:
3226 SequenceNode.release_temp(self, env)
3228 def calculate_constant_result(self):
3229 self.constant_result = [
3230 arg.constant_result for arg in self.args]
3232 def compile_time_value(self, denv):
3233 return self.compile_time_value_list(denv)
3235 def generate_operation_code(self, code):
3236 if self.type.is_pyobject:
3237 for err in self.obj_conversion_errors:
3238 report_error(err)
3239 code.putln("%s = PyList_New(%s); %s" %
3240 (self.result(),
3241 len(self.args),
3242 code.error_goto_if_null(self.result(), self.pos)))
3243 code.put_gotref(self.py_result())
3244 for i in range(len(self.args)):
3245 arg = self.args[i]
3246 #if not arg.is_temp:
3247 if not arg.result_in_temp():
3248 code.put_incref(arg.result(), arg.ctype())
3249 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3250 (self.result(),
3251 i,
3252 arg.py_result()))
3253 code.put_giveref(arg.py_result())
3254 elif self.type.is_array:
3255 for i, arg in enumerate(self.args):
3256 code.putln("%s[%s] = %s;" % (
3257 self.result(),
3258 i,
3259 arg.result()))
3260 elif self.type.is_struct:
3261 for arg, member in zip(self.args, self.type.scope.var_entries):
3262 code.putln("%s.%s = %s;" % (
3263 self.result(),
3264 member.cname,
3265 arg.result()))
3266 else:
3267 raise InternalError("List type never specified")
3269 def generate_subexpr_disposal_code(self, code):
3270 # We call generate_post_assignment_code here instead
3271 # of generate_disposal_code, because values were stored
3272 # in the list using a reference-stealing operation.
3273 for arg in self.args:
3274 arg.generate_post_assignment_code(code)
3275 # Should NOT call free_temps -- this is invoked by the default
3276 # generate_evaluation_code which will do that.
3279 class ComprehensionNode(NewTempExprNode):
3280 subexprs = ["target"]
3281 child_attrs = ["loop", "append"]
3283 def analyse_types(self, env):
3284 self.target.analyse_expressions(env)
3285 self.type = self.target.type
3286 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3287 self.loop.analyse_declarations(env)
3289 def allocate_temps(self, env, result = None):
3290 if debug_temp_alloc:
3291 print("%s Allocating temps" % self)
3292 self.allocate_temp(env, result)
3293 # call loop.analyse_expressions() now to make sure temps get
3294 # allocated at the right time
3295 self.loop.analyse_expressions(env)
3297 def calculate_result_code(self):
3298 return self.target.result()
3300 def generate_result_code(self, code):
3301 self.generate_operation_code(code)
3303 def generate_operation_code(self, code):
3304 self.loop.generate_execution_code(code)
3306 def annotate(self, code):
3307 self.loop.annotate(code)
3310 class ComprehensionAppendNode(NewTempExprNode):
3311 # Need to be careful to avoid infinite recursion:
3312 # target must not be in child_attrs/subexprs
3313 subexprs = ['expr']
3315 def analyse_types(self, env):
3316 self.expr.analyse_types(env)
3317 if not self.expr.type.is_pyobject:
3318 self.expr = self.expr.coerce_to_pyobject(env)
3319 self.type = PyrexTypes.c_int_type
3320 self.is_temp = 1
3322 def generate_result_code(self, code):
3323 if self.target.type is list_type:
3324 function = "PyList_Append"
3325 elif self.target.type is set_type:
3326 function = "PySet_Add"
3327 else:
3328 raise InternalError(
3329 "Invalid type for comprehension node: %s" % self.target.type)
3331 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3332 (self.result(),
3333 function,
3334 self.target.result(),
3335 self.expr.result(),
3336 code.error_goto_if(self.result(), self.pos)))
3338 class DictComprehensionAppendNode(ComprehensionAppendNode):
3339 subexprs = ['key_expr', 'value_expr']
3341 def analyse_types(self, env):
3342 self.key_expr.analyse_types(env)
3343 if not self.key_expr.type.is_pyobject:
3344 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3345 self.value_expr.analyse_types(env)
3346 if not self.value_expr.type.is_pyobject:
3347 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3348 self.type = PyrexTypes.c_int_type
3349 self.is_temp = 1
3351 def generate_result_code(self, code):
3352 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3353 (self.result(),
3354 self.target.result(),
3355 self.key_expr.result(),
3356 self.value_expr.result(),
3357 code.error_goto_if(self.result(), self.pos)))
3360 class SetNode(NewTempExprNode):
3361 # Set constructor.
3363 subexprs = ['args']
3365 gil_message = "Constructing Python set"
3367 def analyse_types(self, env):
3368 for i in range(len(self.args)):
3369 arg = self.args[i]
3370 arg.analyse_types(env)
3371 self.args[i] = arg.coerce_to_pyobject(env)
3372 self.type = set_type
3373 self.is_temp = 1
3375 def calculate_constant_result(self):
3376 self.constant_result = set([
3377 arg.constant_result for arg in self.args])
3379 def compile_time_value(self, denv):
3380 values = [arg.compile_time_value(denv) for arg in self.args]
3381 try:
3382 return set(values)
3383 except Exception, e:
3384 self.compile_time_value_error(e)
3386 def generate_evaluation_code(self, code):
3387 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3388 self.allocate_temp_result(code)
3389 code.putln(
3390 "%s = PySet_New(0); %s" % (
3391 self.result(),
3392 code.error_goto_if_null(self.result(), self.pos)))
3393 code.put_gotref(self.py_result())
3394 for arg in self.args:
3395 arg.generate_evaluation_code(code)
3396 code.putln(
3397 code.error_goto_if_neg(
3398 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3399 self.pos))
3400 arg.generate_disposal_code(code)
3401 arg.free_temps(code)
3404 class DictNode(ExprNode):
3405 # Dictionary constructor.
3407 # key_value_pairs [DictItemNode]
3409 # obj_conversion_errors [PyrexError] used internally
3411 subexprs = ['key_value_pairs']
3413 def calculate_constant_result(self):
3414 self.constant_result = dict([
3415 item.constant_result for item in self.key_value_pairs])
3417 def compile_time_value(self, denv):
3418 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3419 for item in self.key_value_pairs]
3420 try:
3421 return dict(pairs)
3422 except Exception, e:
3423 self.compile_time_value_error(e)
3425 def analyse_types(self, env):
3426 hold_errors()
3427 self.type = dict_type
3428 for item in self.key_value_pairs:
3429 item.analyse_types(env)
3430 self.obj_conversion_errors = held_errors()
3431 release_errors(ignore=True)
3432 self.is_temp = 1
3434 def coerce_to(self, dst_type, env):
3435 if dst_type.is_pyobject:
3436 self.release_errors()
3437 if not self.type.subtype_of(dst_type):
3438 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3439 elif dst_type.is_struct_or_union:
3440 self.type = dst_type
3441 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3442 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3443 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3444 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3445 for item in self.key_value_pairs:
3446 if isinstance(item.key, CoerceToPyTypeNode):
3447 item.key = item.key.arg
3448 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3449 error(item.key.pos, "Invalid struct field identifier")
3450 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3451 else:
3452 member = dst_type.scope.lookup_here(item.key.value)
3453 if not member:
3454 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3455 else:
3456 value = item.value
3457 if isinstance(value, CoerceToPyTypeNode):
3458 value = value.arg
3459 item.value = value.coerce_to(member.type, env)
3460 else:
3461 self.type = error_type
3462 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3463 return self
3465 def release_errors(self):
3466 for err in self.obj_conversion_errors:
3467 report_error(err)
3468 self.obj_conversion_errors = []
3470 gil_message = "Constructing Python dict"
3472 def allocate_temps(self, env, result = None):
3473 # Custom method used here because key-value
3474 # pairs are evaluated and used one at a time.
3475 self.allocate_temp(env, result)
3476 for item in self.key_value_pairs:
3477 item.key.allocate_temps(env)
3478 item.value.allocate_temps(env)
3479 item.key.release_temp(env)
3480 item.value.release_temp(env)
3482 def generate_evaluation_code(self, code):
3483 # Custom method used here because key-value
3484 # pairs are evaluated and used one at a time.
3485 if self.type.is_pyobject:
3486 self.release_errors()
3487 code.putln(
3488 "%s = PyDict_New(); %s" % (
3489 self.result(),
3490 code.error_goto_if_null(self.result(), self.pos)))
3491 code.put_gotref(self.py_result())
3492 for item in self.key_value_pairs:
3493 item.generate_evaluation_code(code)
3494 if self.type.is_pyobject:
3495 code.put_error_if_neg(self.pos,
3496 "PyDict_SetItem(%s, %s, %s)" % (
3497 self.result(),
3498 item.key.py_result(),
3499 item.value.py_result()))
3500 else:
3501 code.putln("%s.%s = %s;" % (
3502 self.result(),
3503 item.key.value,
3504 item.value.result()))
3505 item.generate_disposal_code(code)
3506 item.free_temps(code)
3508 def annotate(self, code):
3509 for item in self.key_value_pairs:
3510 item.annotate(code)
3512 class DictItemNode(ExprNode):
3513 # Represents a single item in a DictNode
3515 # key ExprNode
3516 # value ExprNode
3517 subexprs = ['key', 'value']
3519 gil_check = None # handled by DictNode
3521 def calculate_constant_result(self):
3522 self.constant_result = (
3523 self.key.constant_result, self.value.constant_result)
3525 def analyse_types(self, env):
3526 self.key.analyse_types(env)
3527 self.value.analyse_types(env)
3528 self.key = self.key.coerce_to_pyobject(env)
3529 self.value = self.value.coerce_to_pyobject(env)
3531 def generate_evaluation_code(self, code):
3532 self.key.generate_evaluation_code(code)
3533 self.value.generate_evaluation_code(code)
3535 def generate_disposal_code(self, code):
3536 self.key.generate_disposal_code(code)
3537 self.value.generate_disposal_code(code)
3539 def free_temps(self, code):
3540 self.key.free_temps(code)
3541 self.value.free_temps(code)
3543 def __iter__(self):
3544 return iter([self.key, self.value])
3547 class ClassNode(ExprNode):
3548 # Helper class used in the implementation of Python
3549 # class definitions. Constructs a class object given
3550 # a name, tuple of bases and class dictionary.
3552 # name EncodedString Name of the class
3553 # bases ExprNode Base class tuple
3554 # dict ExprNode Class dict (not owned by this node)
3555 # doc ExprNode or None Doc string
3556 # module_name string Name of defining module
3558 subexprs = ['bases', 'doc']
3560 def analyse_types(self, env):
3561 self.bases.analyse_types(env)
3562 if self.doc:
3563 self.doc.analyse_types(env)
3564 self.doc = self.doc.coerce_to_pyobject(env)
3565 self.module_name = env.global_scope().qualified_name
3566 self.type = py_object_type
3567 self.is_temp = 1
3568 env.use_utility_code(create_class_utility_code);
3570 gil_message = "Constructing Python class"
3572 def generate_result_code(self, code):
3573 cname = code.intern_identifier(self.name)
3574 if self.doc:
3575 code.put_error_if_neg(self.pos,
3576 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3577 self.dict.py_result(),
3578 self.doc.py_result()))
3579 code.putln(
3580 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3581 self.result(),
3582 self.bases.py_result(),
3583 self.dict.py_result(),
3584 cname,
3585 self.module_name,
3586 code.error_goto_if_null(self.result(), self.pos)))
3587 code.put_gotref(self.py_result())
3590 class UnboundMethodNode(ExprNode):
3591 # Helper class used in the implementation of Python
3592 # class definitions. Constructs an unbound method
3593 # object from a class and a function.
3595 # class_cname string C var holding the class object
3596 # function ExprNode Function object
3598 subexprs = ['function']
3600 def analyse_types(self, env):
3601 self.function.analyse_types(env)
3602 self.type = py_object_type
3603 self.is_temp = 1
3605 gil_message = "Constructing an unbound method"
3607 def generate_result_code(self, code):
3608 code.putln(
3609 "%s = PyMethod_New(%s, 0, %s); %s" % (
3610 self.result(),
3611 self.function.py_result(),
3612 self.class_cname,
3613 code.error_goto_if_null(self.result(), self.pos)))
3614 code.put_gotref(self.py_result())
3616 class PyCFunctionNode(AtomicNewTempExprNode):
3617 # Helper class used in the implementation of Python
3618 # class definitions. Constructs a PyCFunction object
3619 # from a PyMethodDef struct.
3621 # pymethdef_cname string PyMethodDef structure
3623 def analyse_types(self, env):
3624 self.type = py_object_type
3625 self.is_temp = 1
3627 gil_message = "Constructing Python function"
3629 def generate_result_code(self, code):
3630 code.putln(
3631 "%s = PyCFunction_New(&%s, 0); %s" % (
3632 self.result(),
3633 self.pymethdef_cname,
3634 code.error_goto_if_null(self.result(), self.pos)))
3635 code.put_gotref(self.py_result())
3637 #-------------------------------------------------------------------
3639 # Unary operator nodes
3641 #-------------------------------------------------------------------
3643 compile_time_unary_operators = {
3644 'not': operator.not_,
3645 '~': operator.inv,
3646 '-': operator.neg,
3647 '+': operator.pos,
3650 class UnopNode(ExprNode):
3651 # operator string
3652 # operand ExprNode
3654 # Processing during analyse_expressions phase:
3656 # analyse_c_operation
3657 # Called when the operand is not a pyobject.
3658 # - Check operand type and coerce if needed.
3659 # - Determine result type and result code fragment.
3660 # - Allocate temporary for result if needed.
3662 subexprs = ['operand']
3664 def calculate_constant_result(self):
3665 func = compile_time_unary_operators[self.operator]
3666 self.constant_result = func(self.operand.constant_result)
3668 def compile_time_value(self, denv):
3669 func = compile_time_unary_operators.get(self.operator)
3670 if not func:
3671 error(self.pos,
3672 "Unary '%s' not supported in compile-time expression"
3673 % self.operator)
3674 operand = self.operand.compile_time_value(denv)
3675 try:
3676 return func(operand)
3677 except Exception, e:
3678 self.compile_time_value_error(e)
3680 def analyse_types(self, env):
3681 self.operand.analyse_types(env)
3682 if self.is_py_operation():
3683 self.coerce_operand_to_pyobject(env)
3684 self.type = py_object_type
3685 self.is_temp = 1
3686 else:
3687 self.analyse_c_operation(env)
3689 def check_const(self):
3690 self.operand.check_const()
3692 def is_py_operation(self):
3693 return self.operand.type.is_pyobject
3695 def gil_check(self, env):
3696 if self.is_py_operation():
3697 self._gil_check(env)
3699 def coerce_operand_to_pyobject(self, env):
3700 self.operand = self.operand.coerce_to_pyobject(env)
3702 def generate_result_code(self, code):
3703 if self.operand.type.is_pyobject:
3704 self.generate_py_operation_code(code)
3705 else:
3706 if self.is_temp:
3707 self.generate_c_operation_code(code)
3709 def generate_py_operation_code(self, code):
3710 function = self.py_operation_function()
3711 code.putln(
3712 "%s = %s(%s); %s" % (
3713 self.result(),
3714 function,
3715 self.operand.py_result(),
3716 code.error_goto_if_null(self.result(), self.pos)))
3717 code.put_gotref(self.py_result())
3719 def type_error(self):
3720 if not self.operand.type.is_error:
3721 error(self.pos, "Invalid operand type for '%s' (%s)" %
3722 (self.operator, self.operand.type))
3723 self.type = PyrexTypes.error_type
3726 class NotNode(ExprNode):
3727 # 'not' operator
3729 # operand ExprNode
3731 def calculate_constant_result(self):
3732 self.constant_result = not self.operand.constant_result
3734 def compile_time_value(self, denv):
3735 operand = self.operand.compile_time_value(denv)
3736 try:
3737 return not operand
3738 except Exception, e:
3739 self.compile_time_value_error(e)
3741 subexprs = ['operand']
3743 def analyse_types(self, env):
3744 self.operand.analyse_types(env)
3745 self.operand = self.operand.coerce_to_boolean(env)
3746 self.type = PyrexTypes.c_bint_type
3748 def calculate_result_code(self):
3749 return "(!%s)" % self.operand.result()
3751 def generate_result_code(self, code):
3752 pass
3755 class UnaryPlusNode(UnopNode):
3756 # unary '+' operator
3758 operator = '+'
3760 def analyse_c_operation(self, env):
3761 self.type = self.operand.type
3763 def py_operation_function(self):
3764 return "PyNumber_Positive"
3766 def calculate_result_code(self):
3767 return self.operand.result()
3770 class UnaryMinusNode(UnopNode):
3771 # unary '-' operator
3773 operator = '-'
3775 def analyse_c_operation(self, env):
3776 if self.operand.type.is_numeric:
3777 self.type = self.operand.type
3778 else:
3779 self.type_error()
3781 def py_operation_function(self):
3782 return "PyNumber_Negative"
3784 def calculate_result_code(self):
3785 return "(-%s)" % self.operand.result()
3788 class TildeNode(UnopNode):
3789 # unary '~' operator
3791 def analyse_c_operation(self, env):
3792 if self.operand.type.is_int:
3793 self.type = self.operand.type
3794 else:
3795 self.type_error()
3797 def py_operation_function(self):
3798 return "PyNumber_Invert"
3800 def calculate_result_code(self):
3801 return "(~%s)" % self.operand.result()
3804 class AmpersandNode(ExprNode):
3805 # The C address-of operator.
3807 # operand ExprNode
3809 subexprs = ['operand']
3811 def analyse_types(self, env):
3812 self.operand.analyse_types(env)
3813 argtype = self.operand.type
3814 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3815 self.error("Taking address of non-lvalue")
3816 return
3817 if argtype.is_pyobject:
3818 self.error("Cannot take address of Python variable")
3819 return
3820 self.type = PyrexTypes.c_ptr_type(argtype)
3822 def check_const(self):
3823 self.operand.check_const_addr()
3825 def error(self, mess):
3826 error(self.pos, mess)
3827 self.type = PyrexTypes.error_type
3828 self.result_code = "<error>"
3830 def calculate_result_code(self):
3831 return "(&%s)" % self.operand.result()
3833 def generate_result_code(self, code):
3834 pass
3837 unop_node_classes = {
3838 "+": UnaryPlusNode,
3839 "-": UnaryMinusNode,
3840 "~": TildeNode,
3843 def unop_node(pos, operator, operand):
3844 # Construct unnop node of appropriate class for
3845 # given operator.
3846 if isinstance(operand, IntNode) and operator == '-':
3847 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3848 elif isinstance(operand, UnopNode) and operand.operator == operator:
3849 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3850 return unop_node_classes[operator](pos,
3851 operator = operator,
3852 operand = operand)
3855 class TypecastNode(NewTempExprNode):
3856 # C type cast
3858 # operand ExprNode
3859 # base_type CBaseTypeNode
3860 # declarator CDeclaratorNode
3862 # If used from a transform, one can if wanted specify the attribute
3863 # "type" directly and leave base_type and declarator to None
3865 subexprs = ['operand']
3866 base_type = declarator = type = None
3868 def analyse_types(self, env):
3869 if self.type is None:
3870 base_type = self.base_type.analyse(env)
3871 _, self.type = self.declarator.analyse(base_type, env)
3872 if self.type.is_cfunction:
3873 error(self.pos,
3874 "Cannot cast to a function type")
3875 self.type = PyrexTypes.error_type
3876 self.operand.analyse_types(env)
3877 to_py = self.type.is_pyobject
3878 from_py = self.operand.type.is_pyobject
3879 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3880 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3881 if to_py and not from_py:
3882 if (self.operand.type.to_py_function and
3883 self.operand.type.create_convert_utility_code(env)):
3884 self.result_ctype = py_object_type
3885 self.operand = self.operand.coerce_to_pyobject(env)
3886 else:
3887 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3888 self.operand = self.operand.coerce_to_simple(env)
3889 elif from_py and not to_py:
3890 if self.type.from_py_function:
3891 self.operand = self.operand.coerce_to(self.type, env)
3892 else:
3893 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3894 elif from_py and to_py:
3895 if self.typecheck and self.type.is_extension_type:
3896 self.operand = PyTypeTestNode(self.operand, self.type, env)
3898 def gil_check(self, env):
3899 if self.type.is_pyobject and self.is_temp:
3900 self._gil_check(env)
3902 def check_const(self):
3903 self.operand.check_const()
3905 def calculate_constant_result(self):
3906 self.constant_result = self.operand.constant_result
3908 def calculate_result_code(self):
3909 opnd = self.operand
3910 return self.type.cast_code(opnd.result())
3912 def result_as(self, type):
3913 if self.type.is_pyobject and not self.is_temp:
3914 # Optimise away some unnecessary casting
3915 return self.operand.result_as(type)
3916 else:
3917 return ExprNode.result_as(self, type)
3919 def generate_result_code(self, code):
3920 if self.is_temp:
3921 code.putln(
3922 "%s = (PyObject *)%s;" % (
3923 self.result(),
3924 self.operand.result()))
3925 code.put_incref(self.result(), self.ctype())
3928 class SizeofNode(ExprNode):
3929 # Abstract base class for sizeof(x) expression nodes.
3931 type = PyrexTypes.c_size_t_type
3933 def check_const(self):
3934 pass
3936 def generate_result_code(self, code):
3937 pass
3940 class SizeofTypeNode(SizeofNode):
3941 # C sizeof function applied to a type
3943 # base_type CBaseTypeNode
3944 # declarator CDeclaratorNode
3946 subexprs = []
3947 arg_type = None
3949 def analyse_types(self, env):
3950 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3951 # this could be better handled by more uniformly treating types as runtime-available objects
3952 if 0 and self.base_type.module_path:
3953 path = self.base_type.module_path
3954 obj = env.lookup(path[0])
3955 if obj.as_module is None:
3956 operand = NameNode(pos=self.pos, name=path[0])
3957 for attr in path[1:]:
3958 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3959 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3960 self.operand = operand
3961 self.__class__ = SizeofVarNode
3962 self.analyse_types(env)
3963 return
3964 if self.arg_type is None:
3965 base_type = self.base_type.analyse(env)
3966 _, arg_type = self.declarator.analyse(base_type, env)
3967 self.arg_type = arg_type
3968 self.check_type()
3970 def check_type(self):
3971 arg_type = self.arg_type
3972 if arg_type.is_pyobject and not arg_type.is_extension_type:
3973 error(self.pos, "Cannot take sizeof Python object")
3974 elif arg_type.is_void:
3975 error(self.pos, "Cannot take sizeof void")
3976 elif not arg_type.is_complete():
3977 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3979 def calculate_result_code(self):
3980 if self.arg_type.is_extension_type:
3981 # the size of the pointer is boring
3982 # we want the size of the actual struct
3983 arg_code = self.arg_type.declaration_code("", deref=1)
3984 else:
3985 arg_code = self.arg_type.declaration_code("")
3986 return "(sizeof(%s))" % arg_code
3989 class SizeofVarNode(SizeofNode):
3990 # C sizeof function applied to a variable
3992 # operand ExprNode
3994 subexprs = ['operand']
3996 def analyse_types(self, env):
3997 # We may actually be looking at a type rather than a variable...
3998 # If we are, traditional analysis would fail...
3999 operand_as_type = self.operand.analyse_as_type(env)
4000 if operand_as_type:
4001 self.arg_type = operand_as_type
4002 self.__class__ = SizeofTypeNode
4003 self.check_type()
4004 else:
4005 self.operand.analyse_types(env)
4007 def calculate_result_code(self):
4008 return "(sizeof(%s))" % self.operand.result()
4010 def generate_result_code(self, code):
4011 pass
4014 #-------------------------------------------------------------------
4016 # Binary operator nodes
4018 #-------------------------------------------------------------------
4020 def _not_in(x, seq):
4021 return x not in seq
4023 compile_time_binary_operators = {
4024 '<': operator.lt,
4025 '<=': operator.le,
4026 '==': operator.eq,
4027 '!=': operator.ne,
4028 '>=': operator.ge,
4029 '>': operator.gt,
4030 'is': operator.is_,
4031 'is_not': operator.is_not,
4032 '+': operator.add,
4033 '&': operator.and_,
4034 '/': operator.div,
4035 '//': operator.floordiv,
4036 '<<': operator.lshift,
4037 '%': operator.mod,
4038 '*': operator.mul,
4039 '|': operator.or_,
4040 '**': operator.pow,
4041 '>>': operator.rshift,
4042 '-': operator.sub,
4043 #'/': operator.truediv,
4044 '^': operator.xor,
4045 'in': operator.contains,
4046 'not_in': _not_in,
4049 def get_compile_time_binop(node):
4050 func = compile_time_binary_operators.get(node.operator)
4051 if not func:
4052 error(node.pos,
4053 "Binary '%s' not supported in compile-time expression"
4054 % node.operator)
4055 return func
4057 class BinopNode(NewTempExprNode):
4058 # operator string
4059 # operand1 ExprNode
4060 # operand2 ExprNode
4062 # Processing during analyse_expressions phase:
4064 # analyse_c_operation
4065 # Called when neither operand is a pyobject.
4066 # - Check operand types and coerce if needed.
4067 # - Determine result type and result code fragment.
4068 # - Allocate temporary for result if needed.
4070 subexprs = ['operand1', 'operand2']
4072 def calculate_constant_result(self):
4073 func = compile_time_binary_operators[self.operator]
4074 self.constant_result = func(
4075 self.operand1.constant_result,
4076 self.operand2.constant_result)
4078 def compile_time_value(self, denv):
4079 func = get_compile_time_binop(self)
4080 operand1 = self.operand1.compile_time_value(denv)
4081 operand2 = self.operand2.compile_time_value(denv)
4082 try:
4083 return func(operand1, operand2)
4084 except Exception, e:
4085 self.compile_time_value_error(e)
4087 def analyse_types(self, env):
4088 self.operand1.analyse_types(env)
4089 self.operand2.analyse_types(env)
4090 if self.is_py_operation():
4091 self.coerce_operands_to_pyobjects(env)
4092 self.type = py_object_type
4093 self.is_temp = 1
4094 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4095 self.operand1 = self.operand1.coerce_to_temp(env)
4096 else:
4097 self.analyse_c_operation(env)
4099 def is_py_operation(self):
4100 return (self.operand1.type.is_pyobject
4101 or self.operand2.type.is_pyobject)
4103 def gil_check(self, env):
4104 if self.is_py_operation():
4105 self._gil_check(env)
4107 def coerce_operands_to_pyobjects(self, env):
4108 self.operand1 = self.operand1.coerce_to_pyobject(env)
4109 self.operand2 = self.operand2.coerce_to_pyobject(env)
4111 def check_const(self):
4112 self.operand1.check_const()
4113 self.operand2.check_const()
4115 def generate_result_code(self, code):
4116 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4117 if self.operand1.type.is_pyobject:
4118 function = self.py_operation_function()
4119 if function == "PyNumber_Power":
4120 extra_args = ", Py_None"
4121 else:
4122 extra_args = ""
4123 code.putln(
4124 "%s = %s(%s, %s%s); %s" % (
4125 self.result(),
4126 function,
4127 self.operand1.py_result(),
4128 self.operand2.py_result(),
4129 extra_args,
4130 code.error_goto_if_null(self.result(), self.pos)))
4131 code.put_gotref(self.py_result())
4132 else:
4133 if self.is_temp:
4134 self.generate_c_operation_code(code)
4136 def type_error(self):
4137 if not (self.operand1.type.is_error
4138 or self.operand2.type.is_error):
4139 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4140 (self.operator, self.operand1.type,
4141 self.operand2.type))
4142 self.type = PyrexTypes.error_type
4145 class NumBinopNode(BinopNode):
4146 # Binary operation taking numeric arguments.
4148 def analyse_c_operation(self, env):
4149 type1 = self.operand1.type
4150 type2 = self.operand2.type
4151 self.type = self.compute_c_result_type(type1, type2)
4152 if not self.type:
4153 self.type_error()
4155 def compute_c_result_type(self, type1, type2):
4156 if self.c_types_okay(type1, type2):
4157 return PyrexTypes.widest_numeric_type(type1, type2)
4158 else:
4159 return None
4161 def c_types_okay(self, type1, type2):
4162 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4163 return (type1.is_numeric or type1.is_enum) \
4164 and (type2.is_numeric or type2.is_enum)
4166 def calculate_result_code(self):
4167 return "(%s %s %s)" % (
4168 self.operand1.result(),
4169 self.operator,
4170 self.operand2.result())
4172 def py_operation_function(self):
4173 return self.py_functions[self.operator]
4175 py_functions = {
4176 "|": "PyNumber_Or",
4177 "^": "PyNumber_Xor",
4178 "&": "PyNumber_And",
4179 "<<": "PyNumber_Lshift",
4180 ">>": "PyNumber_Rshift",
4181 "+": "PyNumber_Add",
4182 "-": "PyNumber_Subtract",
4183 "*": "PyNumber_Multiply",
4184 "/": "__Pyx_PyNumber_Divide",
4185 "//": "PyNumber_FloorDivide",
4186 "%": "PyNumber_Remainder",
4187 "**": "PyNumber_Power"
4191 class IntBinopNode(NumBinopNode):
4192 # Binary operation taking integer arguments.
4194 def c_types_okay(self, type1, type2):
4195 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4196 return (type1.is_int or type1.is_enum) \
4197 and (type2.is_int or type2.is_enum)
4200 class AddNode(NumBinopNode):
4201 # '+' operator.
4203 def is_py_operation(self):
4204 if self.operand1.type.is_string \
4205 and self.operand2.type.is_string:
4206 return 1
4207 else:
4208 return NumBinopNode.is_py_operation(self)
4210 def compute_c_result_type(self, type1, type2):
4211 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4212 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4213 return type1
4214 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4215 return type2
4216 else:
4217 return NumBinopNode.compute_c_result_type(
4218 self, type1, type2)
4221 class SubNode(NumBinopNode):
4222 # '-' operator.
4224 def compute_c_result_type(self, type1, type2):
4225 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4226 return type1
4227 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4228 return PyrexTypes.c_int_type
4229 else:
4230 return NumBinopNode.compute_c_result_type(
4231 self, type1, type2)
4234 class MulNode(NumBinopNode):
4235 # '*' operator.
4237 def is_py_operation(self):
4238 type1 = self.operand1.type
4239 type2 = self.operand2.type
4240 if (type1.is_string and type2.is_int) \
4241 or (type2.is_string and type1.is_int):
4242 return 1
4243 else:
4244 return NumBinopNode.is_py_operation(self)
4247 class FloorDivNode(NumBinopNode):
4248 # '//' operator.
4250 def calculate_result_code(self):
4251 return "(%s %s %s)" % (
4252 self.operand1.result(),
4253 "/", # c division is by default floor-div
4254 self.operand2.result())
4257 class ModNode(NumBinopNode):
4258 # '%' operator.
4260 def is_py_operation(self):
4261 return (self.operand1.type.is_string
4262 or self.operand2.type.is_string
4263 or NumBinopNode.is_py_operation(self))
4265 def calculate_result_code(self):
4266 if self.operand1.type.is_float or self.operand2.type.is_float:
4267 return "fmod(%s, %s)" % (
4268 self.operand1.result(),
4269 self.operand2.result())
4270 else:
4271 return "(%s %% %s)" % (
4272 self.operand1.result(),
4273 self.operand2.result())
4275 class PowNode(NumBinopNode):
4276 # '**' operator.
4278 def analyse_c_operation(self, env):
4279 NumBinopNode.analyse_c_operation(self, env)
4280 if self.operand1.type.is_float or self.operand2.type.is_float:
4281 self.pow_func = "pow"
4282 else:
4283 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4284 env.use_utility_code(
4285 int_pow_utility_code.specialize(func_name=self.pow_func,
4286 type=self.type.declaration_code('')))
4288 def calculate_result_code(self):
4289 return "%s(%s, %s)" % (
4290 self.pow_func,
4291 self.operand1.result(),
4292 self.operand2.result())
4295 # Note: This class is temporary "shut down" into an ineffective mode temp
4296 # allocation mode.
4298 # More sophisticated temp reuse was going on before,
4299 # one could have a look at adding this again after /all/ classes
4300 # are converted to the new temp scheme. (The temp juggling cannot work
4301 # otherwise).
4302 class BoolBinopNode(NewTempExprNode):
4303 # Short-circuiting boolean operation.
4305 # operator string
4306 # operand1 ExprNode
4307 # operand2 ExprNode
4309 subexprs = ['operand1', 'operand2']
4311 def calculate_constant_result(self):
4312 if self.operator == 'and':
4313 self.constant_result = \
4314 self.operand1.constant_result and \
4315 self.operand2.constant_result
4316 else:
4317 self.constant_result = \
4318 self.operand1.constant_result or \
4319 self.operand2.constant_result
4321 def compile_time_value(self, denv):
4322 if self.operator == 'and':
4323 return self.operand1.compile_time_value(denv) \
4324 and self.operand2.compile_time_value(denv)
4325 else:
4326 return self.operand1.compile_time_value(denv) \
4327 or self.operand2.compile_time_value(denv)
4329 def coerce_to_boolean(self, env):
4330 self.operand1 = self.operand1.coerce_to_boolean(env)
4331 self.operand2 = self.operand2.coerce_to_boolean(env)
4332 self.type = PyrexTypes.c_bint_type
4333 return self
4335 def analyse_types(self, env):
4336 self.operand1.analyse_types(env)
4337 self.operand2.analyse_types(env)
4338 if self.operand1.type.is_pyobject or \
4339 self.operand2.type.is_pyobject:
4340 self.operand1 = self.operand1.coerce_to_pyobject(env)
4341 self.operand2 = self.operand2.coerce_to_pyobject(env)
4342 self.type = py_object_type
4343 else:
4344 self.operand1 = self.operand1.coerce_to_boolean(env)
4345 self.operand2 = self.operand2.coerce_to_boolean(env)
4346 self.type = PyrexTypes.c_bint_type
4348 # Below disabled for
4350 # For what we're about to do, it's vital that
4351 # both operands be temp nodes.
4352 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4353 # self.operand2 = self.operand2.coerce_to_temp(env)
4354 self.is_temp = 1
4356 gil_message = "Truth-testing Python object"
4358 ## def allocate_temps(self, env, result_code = None):
4359 ## # We don't need both operands at the same time, and
4360 ## # one of the operands will also be our result. So we
4361 ## # use an allocation strategy here which results in
4362 ## # this node and both its operands sharing the same
4363 ## # result variable. This allows us to avoid some
4364 ## # assignments and increfs/decrefs that would otherwise
4365 ## # be necessary.
4366 ## self.allocate_temp(env, result_code)
4367 ## self.operand1.allocate_temps(env, self.result())
4368 ## self.operand2.allocate_temps(env, self.result())
4369 ## # We haven't called release_temp on either operand,
4370 ## # because although they are temp nodes, they don't own
4371 ## # their result variable. And because they are temp
4372 ## # nodes, any temps in their subnodes will have been
4373 ## # released before their allocate_temps returned.
4374 ## # Therefore, they contain no temp vars that need to
4375 ## # be released.
4377 def check_const(self):
4378 self.operand1.check_const()
4379 self.operand2.check_const()
4381 def calculate_result_code(self):
4382 return "(%s %s %s)" % (
4383 self.operand1.result(),
4384 self.py_to_c_op[self.operator],
4385 self.operand2.result())
4387 py_to_c_op = {'and': "&&", 'or': "||"}
4389 def generate_evaluation_code(self, code):
4390 code.mark_pos(self.pos)
4391 self.operand1.generate_evaluation_code(code)
4392 test_result, uses_temp = self.generate_operand1_test(code)
4393 if self.operator == 'and':
4394 sense = ""
4395 else:
4396 sense = "!"
4397 code.putln(
4398 "if (%s%s) {" % (
4399 sense,
4400 test_result))
4401 if uses_temp:
4402 code.funcstate.release_temp(test_result)
4403 self.operand1.generate_disposal_code(code)
4404 self.operand2.generate_evaluation_code(code)
4405 self.allocate_temp_result(code)
4406 self.operand2.make_owned_reference(code)
4407 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4408 self.operand2.generate_post_assignment_code(code)
4409 self.operand2.free_temps(code)
4410 code.putln("} else {")
4411 self.operand1.make_owned_reference(code)
4412 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4413 self.operand1.generate_post_assignment_code(code)
4414 self.operand1.free_temps(code)
4415 code.putln("}")
4417 def generate_operand1_test(self, code):
4418 # Generate code to test the truth of the first operand.
4419 if self.type.is_pyobject:
4420 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4421 manage_ref=False)
4422 code.putln(
4423 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4424 test_result,
4425 self.operand1.py_result(),
4426 code.error_goto_if_neg(test_result, self.pos)))
4427 else:
4428 test_result = self.operand1.result()
4429 return (test_result, self.type.is_pyobject)
4432 class CondExprNode(ExprNode):
4433 # Short-circuiting conditional expression.
4435 # test ExprNode
4436 # true_val ExprNode
4437 # false_val ExprNode
4439 true_val = None
4440 false_val = None
4442 subexprs = ['test', 'true_val', 'false_val']
4444 def calculate_constant_result(self):
4445 if self.test.constant_result:
4446 self.constant_result = self.true_val.constant_result
4447 else:
4448 self.constant_result = self.false_val.constant_result
4450 def analyse_types(self, env):
4451 self.test.analyse_types(env)
4452 self.test = self.test.coerce_to_boolean(env)
4453 self.true_val.analyse_types(env)
4454 self.false_val.analyse_types(env)
4455 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4456 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4457 self.true_val = self.true_val.coerce_to(self.type, env)
4458 self.false_val = self.false_val.coerce_to(self.type, env)
4459 # must be tmp variables so they can share a result
4460 self.true_val = self.true_val.coerce_to_temp(env)
4461 self.false_val = self.false_val.coerce_to_temp(env)
4462 self.is_temp = 1
4463 if self.type == PyrexTypes.error_type:
4464 self.type_error()
4466 def allocate_temps(self, env, result_code = None):
4467 # We only ever evaluate one side, and this is
4468 # after evaluating the truth value, so we may
4469 # use an allocation strategy here which results in
4470 # this node and both its operands sharing the same
4471 # result variable. This allows us to avoid some
4472 # assignments and increfs/decrefs that would otherwise
4473 # be necessary.
4474 self.allocate_temp(env, result_code)
4475 self.test.allocate_temps(env, result_code)
4476 self.true_val.allocate_temps(env, self.result())
4477 self.false_val.allocate_temps(env, self.result())
4478 # We haven't called release_temp on either value,
4479 # because although they are temp nodes, they don't own
4480 # their result variable. And because they are temp
4481 # nodes, any temps in their subnodes will have been
4482 # released before their allocate_temps returned.
4483 # Therefore, they contain no temp vars that need to
4484 # be released.
4486 def compute_result_type(self, type1, type2):
4487 if type1 == type2:
4488 return type1
4489 elif type1.is_numeric and type2.is_numeric:
4490 return PyrexTypes.widest_numeric_type(type1, type2)
4491 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4492 return type2
4493 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4494 return type1
4495 elif type1.is_pyobject or type2.is_pyobject:
4496 return py_object_type
4497 elif type1.assignable_from(type2):
4498 return type1
4499 elif type2.assignable_from(type1):
4500 return type2
4501 else:
4502 return PyrexTypes.error_type
4504 def type_error(self):
4505 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4506 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4507 (self.true_val.type, self.false_val.type))
4508 self.type = PyrexTypes.error_type
4510 def check_const(self):
4511 self.test.check_const()
4512 self.true_val.check_const()
4513 self.false_val.check_const()
4515 def generate_evaluation_code(self, code):
4516 self.test.generate_evaluation_code(code)
4517 code.putln("if (%s) {" % self.test.result() )
4518 self.true_val.generate_evaluation_code(code)
4519 code.putln("} else {")
4520 self.false_val.generate_evaluation_code(code)
4521 code.putln("}")
4522 self.test.generate_disposal_code(code)
4523 self.test.free_temps(code)
4525 richcmp_constants = {
4526 "<" : "Py_LT",
4527 "<=": "Py_LE",
4528 "==": "Py_EQ",
4529 "!=": "Py_NE",
4530 "<>": "Py_NE",
4531 ">" : "Py_GT",
4532 ">=": "Py_GE",
4535 class CmpNode(object):
4536 # Mixin class containing code common to PrimaryCmpNodes
4537 # and CascadedCmpNodes.
4539 def calculate_cascaded_constant_result(self, operand1_result):
4540 func = compile_time_binary_operators[self.operator]
4541 operand2_result = self.operand2.constant_result
4542 result = func(operand1_result, operand2_result)
4543 if result and self.cascade:
4544 result = result and \
4545 self.cascade.cascaded_compile_time_value(operand2_result)
4546 self.constant_result = result
4548 def cascaded_compile_time_value(self, operand1, denv):
4549 func = get_compile_time_binop(self)
4550 operand2 = self.operand2.compile_time_value(denv)
4551 try:
4552 result = func(operand1, operand2)
4553 except Exception, e:
4554 self.compile_time_value_error(e)
4555 result = None
4556 if result:
4557 cascade = self.cascade
4558 if cascade:
4559 # FIXME: I bet this must call cascaded_compile_time_value()
4560 result = result and cascade.compile_time_value(operand2, denv)
4561 return result
4563 def is_python_comparison(self):
4564 return (self.has_python_operands()
4565 or (self.cascade and self.cascade.is_python_comparison())
4566 or self.operator in ('in', 'not_in'))
4568 def is_python_result(self):
4569 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4570 or (self.cascade and self.cascade.is_python_result()))
4572 def check_types(self, env, operand1, op, operand2):
4573 if not self.types_okay(operand1, op, operand2):
4574 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4575 (self.operator, operand1.type, operand2.type))
4577 def types_okay(self, operand1, op, operand2):
4578 type1 = operand1.type
4579 type2 = operand2.type
4580 if type1.is_error or type2.is_error:
4581 return 1
4582 if type1.is_pyobject: # type2 will be, too
4583 return 1
4584 elif type1.is_ptr or type1.is_array:
4585 return type1.is_null_ptr or type2.is_null_ptr \
4586 or ((type2.is_ptr or type2.is_array)
4587 and type1.base_type.same_as(type2.base_type))
4588 elif ((type1.is_numeric and type2.is_numeric
4589 or type1.is_enum and (type1 is type2 or type2.is_int)
4590 or type1.is_int and type2.is_enum)
4591 and op not in ('is', 'is_not')):
4592 return 1
4593 else:
4594 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4596 def generate_operation_code(self, code, result_code,
4597 operand1, op , operand2):
4598 if self.type is PyrexTypes.py_object_type:
4599 coerce_result = "__Pyx_PyBool_FromLong"
4600 else:
4601 coerce_result = ""
4602 if 'not' in op: negation = "!"
4603 else: negation = ""
4604 if op == 'in' or op == 'not_in':
4605 code.putln(
4606 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4607 result_code,
4608 coerce_result,
4609 negation,
4610 operand2.py_result(),
4611 operand1.py_result(),
4612 code.error_goto_if_neg(result_code, self.pos)))
4613 elif (operand1.type.is_pyobject
4614 and op not in ('is', 'is_not')):
4615 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4616 result_code,
4617 operand1.py_result(),
4618 operand2.py_result(),
4619 richcmp_constants[op],
4620 code.error_goto_if_null(result_code, self.pos)))
4621 code.put_gotref(result_code)
4622 else:
4623 type1 = operand1.type
4624 type2 = operand2.type
4625 if (type1.is_extension_type or type2.is_extension_type) \
4626 and not type1.same_as(type2):
4627 common_type = py_object_type
4628 elif type1.is_numeric:
4629 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4630 else:
4631 common_type = type1
4632 code1 = operand1.result_as(common_type)
4633 code2 = operand2.result_as(common_type)
4634 code.putln("%s = %s(%s %s %s);" % (
4635 result_code,
4636 coerce_result,
4637 code1,
4638 self.c_operator(op),
4639 code2))
4641 def c_operator(self, op):
4642 if op == 'is':
4643 return "=="
4644 elif op == 'is_not':
4645 return "!="
4646 else:
4647 return op
4650 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4651 # Non-cascaded comparison or first comparison of
4652 # a cascaded sequence.
4654 # operator string
4655 # operand1 ExprNode
4656 # operand2 ExprNode
4657 # cascade CascadedCmpNode
4659 # We don't use the subexprs mechanism, because
4660 # things here are too complicated for it to handle.
4661 # Instead, we override all the framework methods
4662 # which use it.
4664 child_attrs = ['operand1', 'operand2', 'cascade']
4666 cascade = None
4668 def calculate_constant_result(self):
4669 self.constant_result = self.calculate_cascaded_constant_result(
4670 self.operand1.constant_result)
4672 def compile_time_value(self, denv):
4673 operand1 = self.operand1.compile_time_value(denv)
4674 return self.cascaded_compile_time_value(operand1, denv)
4676 def analyse_types(self, env):
4677 self.operand1.analyse_types(env)
4678 self.operand2.analyse_types(env)
4679 if self.cascade:
4680 self.cascade.analyse_types(env, self.operand2)
4681 self.is_pycmp = self.is_python_comparison()
4682 if self.is_pycmp:
4683 self.coerce_operands_to_pyobjects(env)
4684 if self.has_int_operands():
4685 self.coerce_chars_to_ints(env)
4686 if self.cascade:
4687 self.operand2 = self.operand2.coerce_to_simple(env)
4688 self.cascade.coerce_cascaded_operands_to_temp(env)
4689 self.check_operand_types(env)
4690 if self.is_python_result():
4691 self.type = PyrexTypes.py_object_type
4692 else:
4693 self.type = PyrexTypes.c_bint_type
4694 cdr = self.cascade
4695 while cdr:
4696 cdr.type = self.type
4697 cdr = cdr.cascade
4698 if self.is_pycmp or self.cascade:
4699 self.is_temp = 1
4701 def check_operand_types(self, env):
4702 self.check_types(env,
4703 self.operand1, self.operator, self.operand2)
4704 if self.cascade:
4705 self.cascade.check_operand_types(env, self.operand2)
4707 def has_python_operands(self):
4708 return (self.operand1.type.is_pyobject
4709 or self.operand2.type.is_pyobject)
4711 def coerce_operands_to_pyobjects(self, env):
4712 self.operand1 = self.operand1.coerce_to_pyobject(env)
4713 self.operand2 = self.operand2.coerce_to_pyobject(env)
4714 if self.cascade:
4715 self.cascade.coerce_operands_to_pyobjects(env)
4717 def has_int_operands(self):
4718 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4719 or (self.cascade and self.cascade.has_int_operands())
4721 def coerce_chars_to_ints(self, env):
4722 # coerce literal single-char strings to c chars
4723 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4724 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4725 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4726 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4727 if self.cascade:
4728 self.cascade.coerce_chars_to_ints(env)
4730 def allocate_subexpr_temps(self, env):
4731 self.operand1.allocate_temps(env)
4732 self.operand2.allocate_temps(env)
4733 if self.cascade:
4734 self.cascade.allocate_subexpr_temps(env)
4736 def release_subexpr_temps(self, env):
4737 self.operand1.release_temp(env)
4738 self.operand2.release_temp(env)
4739 if self.cascade:
4740 self.cascade.release_subexpr_temps(env)
4742 def check_const(self):
4743 self.operand1.check_const()
4744 self.operand2.check_const()
4745 if self.cascade:
4746 self.not_const()
4748 def calculate_result_code(self):
4749 return "(%s %s %s)" % (
4750 self.operand1.result(),
4751 self.c_operator(self.operator),
4752 self.operand2.result())
4754 def generate_evaluation_code(self, code):
4755 self.operand1.generate_evaluation_code(code)
4756 self.operand2.generate_evaluation_code(code)
4757 if self.is_temp:
4758 self.allocate_temp_result(code)
4759 self.generate_operation_code(code, self.result(),
4760 self.operand1, self.operator, self.operand2)
4761 if self.cascade:
4762 self.cascade.generate_evaluation_code(code,
4763 self.result(), self.operand2)
4764 self.operand1.generate_disposal_code(code)
4765 self.operand1.free_temps(code)
4766 self.operand2.generate_disposal_code(code)
4767 self.operand2.free_temps(code)
4769 def generate_subexpr_disposal_code(self, code):
4770 # If this is called, it is a non-cascaded cmp,
4771 # so only need to dispose of the two main operands.
4772 self.operand1.generate_disposal_code(code)
4773 self.operand2.generate_disposal_code(code)
4775 def free_subexpr_temps(self, code):
4776 # If this is called, it is a non-cascaded cmp,
4777 # so only need to dispose of the two main operands.
4778 self.operand1.free_temps(code)
4779 self.operand2.free_temps(code)
4781 def annotate(self, code):
4782 self.operand1.annotate(code)
4783 self.operand2.annotate(code)
4784 if self.cascade:
4785 self.cascade.annotate(code)
4788 class CascadedCmpNode(Node, CmpNode):
4789 # A CascadedCmpNode is not a complete expression node. It
4790 # hangs off the side of another comparison node, shares
4791 # its left operand with that node, and shares its result
4792 # with the PrimaryCmpNode at the head of the chain.
4794 # operator string
4795 # operand2 ExprNode
4796 # cascade CascadedCmpNode
4798 child_attrs = ['operand2', 'cascade']
4800 cascade = None
4801 constant_result = constant_value_not_set # FIXME: where to calculate this?
4803 def analyse_types(self, env, operand1):
4804 self.operand2.analyse_types(env)
4805 if self.cascade:
4806 self.cascade.analyse_types(env, self.operand2)
4808 def check_operand_types(self, env, operand1):
4809 self.check_types(env,
4810 operand1, self.operator, self.operand2)
4811 if self.cascade:
4812 self.cascade.check_operand_types(env, self.operand2)
4814 def has_python_operands(self):
4815 return self.operand2.type.is_pyobject
4817 def coerce_operands_to_pyobjects(self, env):
4818 self.operand2 = self.operand2.coerce_to_pyobject(env)
4819 if self.cascade:
4820 self.cascade.coerce_operands_to_pyobjects(env)
4822 def has_int_operands(self):
4823 return self.operand2.type.is_int
4825 def coerce_chars_to_ints(self, env):
4826 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4827 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4829 def coerce_cascaded_operands_to_temp(self, env):
4830 if self.cascade:
4831 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4832 self.operand2 = self.operand2.coerce_to_simple(env)
4833 self.cascade.coerce_cascaded_operands_to_temp(env)
4835 def allocate_subexpr_temps(self, env):
4836 self.operand2.allocate_temps(env)
4837 if self.cascade:
4838 self.cascade.allocate_subexpr_temps(env)
4840 def release_subexpr_temps(self, env):
4841 self.operand2.release_temp(env)
4842 if self.cascade:
4843 self.cascade.release_subexpr_temps(env)
4845 def generate_evaluation_code(self, code, result, operand1):
4846 if self.type.is_pyobject:
4847 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4848 code.put_decref(result, self.type)
4849 else:
4850 code.putln("if (%s) {" % result)
4851 self.operand2.generate_evaluation_code(code)
4852 self.generate_operation_code(code, result,
4853 operand1, self.operator, self.operand2)
4854 if self.cascade:
4855 self.cascade.generate_evaluation_code(
4856 code, result, self.operand2)
4857 # Cascaded cmp result is always temp
4858 self.operand2.generate_disposal_code(code)
4859 self.operand2.free_temps(code)
4860 code.putln("}")
4862 def annotate(self, code):
4863 self.operand2.annotate(code)
4864 if self.cascade:
4865 self.cascade.annotate(code)
4868 binop_node_classes = {
4869 "or": BoolBinopNode,
4870 "and": BoolBinopNode,
4871 "|": IntBinopNode,
4872 "^": IntBinopNode,
4873 "&": IntBinopNode,
4874 "<<": IntBinopNode,
4875 ">>": IntBinopNode,
4876 "+": AddNode,
4877 "-": SubNode,
4878 "*": MulNode,
4879 "/": NumBinopNode,
4880 "//": FloorDivNode,
4881 "%": ModNode,
4882 "**": PowNode
4885 def binop_node(pos, operator, operand1, operand2):
4886 # Construct binop node of appropriate class for
4887 # given operator.
4888 return binop_node_classes[operator](pos,
4889 operator = operator,
4890 operand1 = operand1,
4891 operand2 = operand2)
4893 #-------------------------------------------------------------------
4895 # Coercion nodes
4897 # Coercion nodes are special in that they are created during
4898 # the analyse_types phase of parse tree processing.
4899 # Their __init__ methods consequently incorporate some aspects
4900 # of that phase.
4902 #-------------------------------------------------------------------
4904 class CoercionNode(NewTempExprNode):
4905 # Abstract base class for coercion nodes.
4907 # arg ExprNode node being coerced
4909 subexprs = ['arg']
4911 def __init__(self, arg):
4912 self.pos = arg.pos
4913 self.arg = arg
4914 if debug_coercion:
4915 print("%s Coercing %s" % (self, self.arg))
4917 def calculate_constant_result(self):
4918 self.constant_result = self.arg.constant_result
4920 def annotate(self, code):
4921 self.arg.annotate(code)
4922 if self.arg.type != self.type:
4923 file, line, col = self.pos
4924 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4927 class CastNode(CoercionNode):
4928 # Wrap a node in a C type cast.
4930 def __init__(self, arg, new_type):
4931 CoercionNode.__init__(self, arg)
4932 self.type = new_type
4934 def calculate_result_code(self):
4935 return self.arg.result_as(self.type)
4937 def generate_result_code(self, code):
4938 self.arg.generate_result_code(code)
4941 class PyTypeTestNode(CoercionNode):
4942 # This node is used to check that a generic Python
4943 # object is an instance of a particular extension type.
4944 # This node borrows the result of its argument node.
4946 def __init__(self, arg, dst_type, env):
4947 # The arg is know to be a Python object, and
4948 # the dst_type is known to be an extension type.
4949 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4950 CoercionNode.__init__(self, arg)
4951 self.type = dst_type
4952 self.result_ctype = arg.ctype()
4954 gil_check = CoercionNode._gil_check
4955 gil_message = "Python type test"
4957 def analyse_types(self, env):
4958 pass
4960 def result_in_temp(self):
4961 return self.arg.result_in_temp()
4963 def is_ephemeral(self):
4964 return self.arg.is_ephemeral()
4966 def calculate_result_code(self):
4967 return self.arg.result()
4969 def generate_result_code(self, code):
4970 if self.type.typeobj_is_available():
4971 if not self.type.is_builtin_type:
4972 code.globalstate.use_utility_code(type_test_utility_code)
4973 code.putln(
4974 "if (!(%s)) %s" % (
4975 self.type.type_test_code(self.arg.py_result()),
4976 code.error_goto(self.pos)))
4977 else:
4978 error(self.pos, "Cannot test type of extern C class "
4979 "without type object name specification")
4981 def generate_post_assignment_code(self, code):
4982 self.arg.generate_post_assignment_code(code)
4984 def free_temps(self, code):
4985 self.arg.free_temps(code)
4988 class CoerceToPyTypeNode(CoercionNode):
4989 # This node is used to convert a C data type
4990 # to a Python object.
4992 def __init__(self, arg, env):
4993 CoercionNode.__init__(self, arg)
4994 self.type = py_object_type
4995 self.is_temp = 1
4996 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4997 error(arg.pos,
4998 "Cannot convert '%s' to Python object" % arg.type)
5000 gil_message = "Converting to Python object"
5002 def coerce_to_boolean(self, env):
5003 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5005 def coerce_to_integer(self, env):
5006 # If not already some C integer type, coerce to longint.
5007 if self.arg.type.is_int:
5008 return self.arg
5009 else:
5010 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5012 def analyse_types(self, env):
5013 # The arg is always already analysed
5014 pass
5016 def generate_result_code(self, code):
5017 function = self.arg.type.to_py_function
5018 code.putln('%s = %s(%s); %s' % (
5019 self.result(),
5020 function,
5021 self.arg.result(),
5022 code.error_goto_if_null(self.result(), self.pos)))
5023 code.put_gotref(self.py_result())
5026 class CoerceFromPyTypeNode(CoercionNode):
5027 # This node is used to convert a Python object
5028 # to a C data type.
5030 def __init__(self, result_type, arg, env):
5031 CoercionNode.__init__(self, arg)
5032 self.type = result_type
5033 self.is_temp = 1
5034 if not result_type.from_py_function:
5035 error(arg.pos,
5036 "Cannot convert Python object to '%s'" % result_type)
5037 if self.type.is_string and self.arg.is_ephemeral():
5038 error(arg.pos,
5039 "Obtaining char * from temporary Python value")
5041 def analyse_types(self, env):
5042 # The arg is always already analysed
5043 pass
5045 def generate_result_code(self, code):
5046 function = self.type.from_py_function
5047 operand = self.arg.py_result()
5048 rhs = "%s(%s)" % (function, operand)
5049 if self.type.is_enum:
5050 rhs = typecast(self.type, c_long_type, rhs)
5051 code.putln('%s = %s; %s' % (
5052 self.result(),
5053 rhs,
5054 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5055 if self.type.is_pyobject:
5056 code.put_gotref(self.py_result())
5059 class CoerceToBooleanNode(CoercionNode):
5060 # This node is used when a result needs to be used
5061 # in a boolean context.
5063 def __init__(self, arg, env):
5064 CoercionNode.__init__(self, arg)
5065 self.type = PyrexTypes.c_bint_type
5066 if arg.type.is_pyobject:
5067 self.is_temp = 1
5069 def gil_check(self, env):
5070 if self.arg.type.is_pyobject:
5071 self._gil_check(env)
5073 gil_message = "Truth-testing Python object"
5075 def check_const(self):
5076 if self.is_temp:
5077 self.not_const()
5078 self.arg.check_const()
5080 def calculate_result_code(self):
5081 return "(%s != 0)" % self.arg.result()
5083 def generate_result_code(self, code):
5084 if self.arg.type.is_pyobject:
5085 code.putln(
5086 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5087 self.result(),
5088 self.arg.py_result(),
5089 code.error_goto_if_neg(self.result(), self.pos)))
5092 class CoerceToTempNode(CoercionNode):
5093 # This node is used to force the result of another node
5094 # to be stored in a temporary. It is only used if the
5095 # argument node's result is not already in a temporary.
5097 def __init__(self, arg, env):
5098 CoercionNode.__init__(self, arg)
5099 self.type = self.arg.type
5100 self.is_temp = 1
5101 if self.type.is_pyobject:
5102 self.result_ctype = py_object_type
5104 gil_message = "Creating temporary Python reference"
5106 def analyse_types(self, env):
5107 # The arg is always already analysed
5108 pass
5110 def coerce_to_boolean(self, env):
5111 self.arg = self.arg.coerce_to_boolean(env)
5112 self.type = self.arg.type
5113 self.result_ctype = self.type
5114 return self
5116 def generate_result_code(self, code):
5117 #self.arg.generate_evaluation_code(code) # Already done
5118 # by generic generate_subexpr_evaluation_code!
5119 code.putln("%s = %s;" % (
5120 self.result(), self.arg.result_as(self.ctype())))
5121 if self.type.is_pyobject:
5122 code.put_incref(self.result(), self.ctype())
5125 class CloneNode(CoercionNode):
5126 # This node is employed when the result of another node needs
5127 # to be used multiple times. The argument node's result must
5128 # be in a temporary. This node "borrows" the result from the
5129 # argument node, and does not generate any evaluation or
5130 # disposal code for it. The original owner of the argument
5131 # node is responsible for doing those things.
5133 subexprs = [] # Arg is not considered a subexpr
5134 gil_check = None
5136 def __init__(self, arg):
5137 CoercionNode.__init__(self, arg)
5138 if hasattr(arg, 'type'):
5139 self.type = arg.type
5140 self.result_ctype = arg.result_ctype
5141 if hasattr(arg, 'entry'):
5142 self.entry = arg.entry
5144 def result(self):
5145 return self.arg.result()
5147 def analyse_types(self, env):
5148 self.type = self.arg.type
5149 self.result_ctype = self.arg.result_ctype
5150 self.is_temp = 1
5151 if hasattr(self.arg, 'entry'):
5152 self.entry = self.arg.entry
5154 def generate_evaluation_code(self, code):
5155 pass
5157 def generate_result_code(self, code):
5158 pass
5160 def generate_disposal_code(self, code):
5161 pass
5163 def allocate_temps(self, env):
5164 pass
5166 def release_temp(self, env):
5167 pass
5169 def free_temps(self, code):
5170 pass
5173 #------------------------------------------------------------------------------------
5175 # Runtime support code
5177 #------------------------------------------------------------------------------------
5179 get_name_interned_utility_code = UtilityCode(
5180 proto = """
5181 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5182 """,
5183 impl = """
5184 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5185 PyObject *result;
5186 result = PyObject_GetAttr(dict, name);
5187 if (!result)
5188 PyErr_SetObject(PyExc_NameError, name);
5189 return result;
5191 """)
5193 #------------------------------------------------------------------------------------
5195 import_utility_code = UtilityCode(
5196 proto = """
5197 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5198 """,
5199 impl = """
5200 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5201 PyObject *__import__ = 0;
5202 PyObject *empty_list = 0;
5203 PyObject *module = 0;
5204 PyObject *global_dict = 0;
5205 PyObject *empty_dict = 0;
5206 PyObject *list;
5207 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5208 if (!__import__)
5209 goto bad;
5210 if (from_list)
5211 list = from_list;
5212 else {
5213 empty_list = PyList_New(0);
5214 if (!empty_list)
5215 goto bad;
5216 list = empty_list;
5218 global_dict = PyModule_GetDict(%(GLOBALS)s);
5219 if (!global_dict)
5220 goto bad;
5221 empty_dict = PyDict_New();
5222 if (!empty_dict)
5223 goto bad;
5224 module = PyObject_CallFunctionObjArgs(__import__,
5225 name, global_dict, empty_dict, list, NULL);
5226 bad:
5227 Py_XDECREF(empty_list);
5228 Py_XDECREF(__import__);
5229 Py_XDECREF(empty_dict);
5230 return module;
5232 """ % {
5233 "BUILTINS": Naming.builtins_cname,
5234 "GLOBALS": Naming.module_cname,
5235 })
5237 #------------------------------------------------------------------------------------
5239 get_exception_utility_code = UtilityCode(
5240 proto = """
5241 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5242 """,
5243 impl = """
5244 static PyObject *__Pyx_GetExcValue(void) {
5245 PyObject *type = 0, *value = 0, *tb = 0;
5246 PyObject *tmp_type, *tmp_value, *tmp_tb;
5247 PyObject *result = 0;
5248 PyThreadState *tstate = PyThreadState_Get();
5249 PyErr_Fetch(&type, &value, &tb);
5250 PyErr_NormalizeException(&type, &value, &tb);
5251 if (PyErr_Occurred())
5252 goto bad;
5253 if (!value) {
5254 value = Py_None;
5255 Py_INCREF(value);
5257 tmp_type = tstate->exc_type;
5258 tmp_value = tstate->exc_value;
5259 tmp_tb = tstate->exc_traceback;
5260 tstate->exc_type = type;
5261 tstate->exc_value = value;
5262 tstate->exc_traceback = tb;
5263 /* Make sure tstate is in a consistent state when we XDECREF
5264 these objects (XDECREF may run arbitrary code). */
5265 Py_XDECREF(tmp_type);
5266 Py_XDECREF(tmp_value);
5267 Py_XDECREF(tmp_tb);
5268 result = value;
5269 Py_XINCREF(result);
5270 type = 0;
5271 value = 0;
5272 tb = 0;
5273 bad:
5274 Py_XDECREF(type);
5275 Py_XDECREF(value);
5276 Py_XDECREF(tb);
5277 return result;
5279 """)
5281 #------------------------------------------------------------------------------------
5283 type_test_utility_code = UtilityCode(
5284 proto = """
5285 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5286 """,
5287 impl = """
5288 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5289 if (!type) {
5290 PyErr_Format(PyExc_SystemError, "Missing type object");
5291 return 0;
5293 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5294 return 1;
5295 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5296 Py_TYPE(obj)->tp_name, type->tp_name);
5297 return 0;
5299 """)
5301 #------------------------------------------------------------------------------------
5303 create_class_utility_code = UtilityCode(
5304 proto = """
5305 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5306 """,
5307 impl = """
5308 static PyObject *__Pyx_CreateClass(
5309 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5311 PyObject *py_modname;
5312 PyObject *result = 0;
5314 #if PY_MAJOR_VERSION < 3
5315 py_modname = PyString_FromString(modname);
5316 #else
5317 py_modname = PyUnicode_FromString(modname);
5318 #endif
5319 if (!py_modname)
5320 goto bad;
5321 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5322 goto bad;
5323 #if PY_MAJOR_VERSION < 3
5324 result = PyClass_New(bases, dict, name);
5325 #else
5326 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5327 #endif
5328 bad:
5329 Py_XDECREF(py_modname);
5330 return result;
5332 """)
5334 #------------------------------------------------------------------------------------
5336 cpp_exception_utility_code = UtilityCode(
5337 proto = """
5338 #ifndef __Pyx_CppExn2PyErr
5339 static void __Pyx_CppExn2PyErr() {
5340 try {
5341 if (PyErr_Occurred())
5342 ; // let the latest Python exn pass through and ignore the current one
5343 else
5344 throw;
5345 } catch (const std::out_of_range& exn) {
5346 // catch out_of_range explicitly so the proper Python exn may be raised
5347 PyErr_SetString(PyExc_IndexError, exn.what());
5348 } catch (const std::exception& exn) {
5349 PyErr_SetString(PyExc_RuntimeError, exn.what());
5351 catch (...)
5353 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5356 #endif
5357 """,
5358 impl = ""
5361 #------------------------------------------------------------------------------------
5363 append_utility_code = UtilityCode(
5364 proto = """
5365 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5366 if (likely(PyList_CheckExact(L))) {
5367 if (PyList_Append(L, x) < 0) return NULL;
5368 Py_INCREF(Py_None);
5369 return Py_None; /* this is just to have an accurate signature */
5371 else {
5372 PyObject *r, *m;
5373 m = __Pyx_GetAttrString(L, "append");
5374 if (!m) return NULL;
5375 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5376 Py_DECREF(m);
5377 return r;
5380 """,
5381 impl = ""
5384 #------------------------------------------------------------------------------------
5386 # If the is_unsigned flag is set, we need to do some extra work to make
5387 # sure the index doesn't become negative.
5389 getitem_int_utility_code = UtilityCode(
5390 proto = """
5392 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5393 PyObject *r;
5394 if (!j) return NULL;
5395 r = PyObject_GetItem(o, j);
5396 Py_DECREF(j);
5397 return r;
5400 """ + ''.join([
5401 """
5402 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5403 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5404 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5406 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5407 if (likely(o != Py_None)) {
5408 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5409 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5410 Py_INCREF(r);
5411 return r;
5413 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5414 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5415 Py_INCREF(r);
5416 return r;
5419 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5421 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5422 ]) + """
5424 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5425 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5426 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5428 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5429 PyObject *r;
5430 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5431 r = PyList_GET_ITEM(o, i);
5432 Py_INCREF(r);
5434 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5435 r = PyTuple_GET_ITEM(o, i);
5436 Py_INCREF(r);
5438 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5439 r = PySequence_GetItem(o, i);
5441 else {
5442 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5444 return r;
5446 """,
5447 impl = """
5448 """)
5452 #------------------------------------------------------------------------------------
5454 setitem_int_utility_code = UtilityCode(
5455 proto = """
5456 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5457 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5458 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5460 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5461 int r;
5462 if (!j) return -1;
5463 r = PyObject_SetItem(o, j, v);
5464 Py_DECREF(j);
5465 return r;
5468 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5469 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5470 Py_DECREF(PyList_GET_ITEM(o, i));
5471 Py_INCREF(v);
5472 PyList_SET_ITEM(o, i, v);
5473 return 1;
5475 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5476 return PySequence_SetItem(o, i, v);
5477 else {
5478 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5479 return __Pyx_SetItemInt_Generic(o, j, v);
5482 """,
5483 impl = """
5484 """)
5486 #------------------------------------------------------------------------------------
5488 delitem_int_utility_code = UtilityCode(
5489 proto = """
5490 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5491 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5492 __Pyx_DelItem_Generic(o, to_py_func(i)))
5494 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5495 int r;
5496 if (!j) return -1;
5497 r = PyObject_DelItem(o, j);
5498 Py_DECREF(j);
5499 return r;
5502 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5503 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5504 return PySequence_DelItem(o, i);
5505 else {
5506 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5507 return __Pyx_DelItem_Generic(o, j);
5510 """,
5511 impl = """
5512 """)
5514 #------------------------------------------------------------------------------------
5516 raise_noneattr_error_utility_code = UtilityCode(
5517 proto = """
5518 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5519 """,
5520 impl = '''
5521 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5522 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5524 ''')
5526 raise_noneindex_error_utility_code = UtilityCode(
5527 proto = """
5528 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5529 """,
5530 impl = '''
5531 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5532 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5534 ''')
5536 raise_none_iter_error_utility_code = UtilityCode(
5537 proto = """
5538 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5539 """,
5540 impl = '''
5541 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5542 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5544 ''')
5546 raise_too_many_values_to_unpack = UtilityCode(
5547 proto = """
5548 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5549 """,
5550 impl = '''
5551 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5552 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5554 ''')
5556 raise_need_more_values_to_unpack = UtilityCode(
5557 proto = """
5558 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5559 """,
5560 impl = '''
5561 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5562 PyErr_Format(PyExc_ValueError,
5563 #if PY_VERSION_HEX < 0x02050000
5564 "need more than %d value%s to unpack", (int)index,
5565 #else
5566 "need more than %zd value%s to unpack", index,
5567 #endif
5568 (index == 1) ? "" : "s");
5570 ''')
5572 #------------------------------------------------------------------------------------
5574 tuple_unpacking_error_code = UtilityCode(
5575 proto = """
5576 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
5577 """,
5578 impl = """
5579 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
5580 if (t == Py_None) {
5581 __Pyx_RaiseNoneNotIterableError();
5582 } else if (PyTuple_GET_SIZE(t) < index) {
5583 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
5584 } else {
5585 __Pyx_RaiseTooManyValuesError();
5588 """,
5589 requires = [raise_none_iter_error_utility_code,
5590 raise_need_more_values_to_unpack,
5591 raise_too_many_values_to_unpack]
5594 unpacking_utility_code = UtilityCode(
5595 proto = """
5596 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5597 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5598 """,
5599 impl = """
5600 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5601 PyObject *item;
5602 if (!(item = PyIter_Next(iter))) {
5603 if (!PyErr_Occurred()) {
5604 __Pyx_RaiseNeedMoreValuesError(index);
5607 return item;
5610 static int __Pyx_EndUnpack(PyObject *iter) {
5611 PyObject *item;
5612 if ((item = PyIter_Next(iter))) {
5613 Py_DECREF(item);
5614 __Pyx_RaiseTooManyValuesError();
5615 return -1;
5617 else if (!PyErr_Occurred())
5618 return 0;
5619 else
5620 return -1;
5622 """,
5623 requires = [raise_need_more_values_to_unpack,
5624 raise_too_many_values_to_unpack]
5628 #------------------------------------------------------------------------------------
5630 int_pow_utility_code = UtilityCode(
5631 proto="""
5632 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
5633 """,
5634 impl="""
5635 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
5636 %(type)s t = b;
5637 switch (e) {
5638 case 3:
5639 t *= b;
5640 case 2:
5641 t *= b;
5642 case 1:
5643 return t;
5644 case 0:
5645 return 1;
5647 if (unlikely(e<0)) return 0;
5648 t = 1;
5649 while (likely(e)) {
5650 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
5651 b *= b;
5652 e >>= 1;
5654 return t;
5656 """)