Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 1851:7c9b5a80ccfe

ticket #186: generate more efficient code when tuple-unpacking a typed tuple
author Stefan Behnel <scoder@users.berlios.de>
date Fri Mar 13 23:42:09 2009 +0100 (3 years ago)
parents 3bdf0e8cf1dc
children db46e82515c7
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_assignment_check(self, env):
335 if env.nogil and self.type.is_pyobject:
336 error(self.pos, "Assignment of Python object not allowed without gil")
338 def check_const(self):
339 self.not_const()
341 def not_const(self):
342 error(self.pos, "Not allowed in a constant expression")
344 def check_const_addr(self):
345 self.addr_not_const()
347 def addr_not_const(self):
348 error(self.pos, "Address is not constant")
350 def gil_check(self, env):
351 if env is not None and env.nogil and self.type.is_pyobject:
352 self.gil_error()
354 # ----------------- Result Allocation -----------------
356 def result_in_temp(self):
357 # Return true if result is in a temporary owned by
358 # this node or one of its subexpressions. Overridden
359 # by certain nodes which can share the result of
360 # a subnode.
361 return self.is_temp
363 def allocate_target_temps(self, env, rhs):
364 # Perform temp allocation for the LHS of an assignment.
365 if debug_temp_alloc:
366 print("%s Allocating target temps" % self)
367 self.allocate_subexpr_temps(env)
368 self.is_target = True
369 if rhs:
370 rhs.release_temp(env)
371 self.release_subexpr_temps(env)
373 def allocate_temps(self, env, result = None):
374 # Allocate temporary variables for this node and
375 # all its sub-expressions. If a result is specified,
376 # this must be a temp node and the specified variable
377 # is used as the result instead of allocating a new
378 # one.
379 if debug_temp_alloc:
380 print("%s Allocating temps" % self)
381 self.allocate_subexpr_temps(env)
382 self.allocate_temp(env, result)
383 if self.is_temp:
384 self.release_subexpr_temps(env)
386 def allocate_subexpr_temps(self, env):
387 # Allocate temporary variables for all sub-expressions
388 # of this node.
389 if debug_temp_alloc:
390 print("%s Allocating temps for: %s" % (self, self.subexprs))
391 for node in self.subexpr_nodes():
392 if node:
393 if debug_temp_alloc:
394 print("%s Allocating temps for %s" % (self, node))
395 node.allocate_temps(env)
397 def allocate_temp(self, env, result = None):
398 # If this node requires a temporary variable for its
399 # result, allocate one, otherwise set the result to
400 # a C code fragment. If a result is specified,
401 # this must be a temp node and the specified variable
402 # is used as the result instead of allocating a new
403 # one.
404 if debug_temp_alloc:
405 print("%s Allocating temp" % self)
406 if result:
407 if not self.is_temp:
408 raise InternalError("Result forced on non-temp node")
409 self.result_code = result
410 elif self.is_temp:
411 type = self.type
412 if not type.is_void:
413 if type.is_pyobject:
414 type = PyrexTypes.py_object_type
415 self.result_code = env.allocate_temp(type)
416 else:
417 self.result_code = None
418 if debug_temp_alloc:
419 print("%s Allocated result %s" % (self, self.result_code))
421 def target_code(self):
422 # Return code fragment for use as LHS of a C assignment.
423 return self.calculate_result_code()
425 def calculate_result_code(self):
426 self.not_implemented("calculate_result_code")
428 # def release_target_temp(self, env):
429 # # Release temporaries used by LHS of an assignment.
430 # self.release_subexpr_temps(env)
432 def release_temp(self, env):
433 # If this node owns a temporary result, release it,
434 # otherwise release results of its sub-expressions.
435 if self.is_temp:
436 if debug_temp_alloc:
437 print("%s Releasing result %s" % (self, self.result_code))
438 env.release_temp(self.result_code)
439 else:
440 self.release_subexpr_temps(env)
442 def release_subexpr_temps(self, env):
443 # Release the results of all sub-expressions of
444 # this node.
445 for node in self.subexpr_nodes():
446 if node:
447 node.release_temp(env)
449 # ---------------- Code Generation -----------------
451 def make_owned_reference(self, code):
452 # If result is a pyobject, make sure we own
453 # a reference to it.
454 if self.type.is_pyobject and not self.result_in_temp():
455 code.put_incref(self.result(), self.ctype())
457 def generate_evaluation_code(self, code):
458 code.mark_pos(self.pos)
459 # Generate code to evaluate this node and
460 # its sub-expressions, and dispose of any
461 # temporary results of its sub-expressions.
462 self.generate_subexpr_evaluation_code(code)
463 self.generate_result_code(code)
464 if self.is_temp:
465 self.generate_subexpr_disposal_code(code)
466 self.free_subexpr_temps(code)
468 def generate_subexpr_evaluation_code(self, code):
469 for node in self.subexpr_nodes():
470 node.generate_evaluation_code(code)
472 def generate_result_code(self, code):
473 self.not_implemented("generate_result_code")
475 def generate_disposal_code(self, code):
476 # If necessary, generate code to dispose of
477 # temporary Python reference.
478 if self.is_temp:
479 if self.type.is_pyobject:
480 code.put_decref_clear(self.result(), self.ctype())
481 else:
482 self.generate_subexpr_disposal_code(code)
484 def generate_subexpr_disposal_code(self, code):
485 # Generate code to dispose of temporary results
486 # of all sub-expressions.
487 for node in self.subexpr_nodes():
488 node.generate_disposal_code(code)
490 def generate_post_assignment_code(self, code):
491 # Same as generate_disposal_code except that
492 # assignment will have absorbed a reference to
493 # the result if it is a Python object.
494 if self.is_temp:
495 if self.type.is_pyobject:
496 code.putln("%s = 0;" % self.result())
497 else:
498 self.generate_subexpr_disposal_code(code)
500 def generate_assignment_code(self, rhs, code):
501 # Stub method for nodes which are not legal as
502 # the LHS of an assignment. An error will have
503 # been reported earlier.
504 pass
506 def generate_deletion_code(self, code):
507 # Stub method for nodes that are not legal as
508 # the argument of a del statement. An error
509 # will have been reported earlier.
510 pass
512 def free_temps(self, code):
513 if not self.is_temp:
514 self.free_subexpr_temps(code)
515 # otherwise, already freed in generate_evaluation_code
517 def free_subexpr_temps(self, code):
518 for sub in self.subexpr_nodes():
519 sub.free_temps(code)
521 # ---------------- Annotation ---------------------
523 def annotate(self, code):
524 for node in self.subexpr_nodes():
525 node.annotate(code)
527 # ----------------- Coercion ----------------------
529 def coerce_to(self, dst_type, env):
530 # Coerce the result so that it can be assigned to
531 # something of type dst_type. If processing is necessary,
532 # wraps this node in a coercion node and returns that.
533 # Otherwise, returns this node unchanged.
534 #
535 # This method is called during the analyse_expressions
536 # phase of the src_node's processing.
537 src = self
538 src_type = self.type
539 src_is_py_type = src_type.is_pyobject
540 dst_is_py_type = dst_type.is_pyobject
542 if dst_type.is_pyobject:
543 if not src.type.is_pyobject:
544 src = CoerceToPyTypeNode(src, env)
545 if not src.type.subtype_of(dst_type):
546 if not isinstance(src, NoneNode):
547 src = PyTypeTestNode(src, dst_type, env)
548 elif src.type.is_pyobject:
549 src = CoerceFromPyTypeNode(dst_type, src, env)
550 else: # neither src nor dst are py types
551 # Added the string comparison, since for c types that
552 # is enough, but Cython gets confused when the types are
553 # in different files.
554 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
555 error(self.pos, "Cannot assign type '%s' to '%s'" %
556 (src.type, dst_type))
557 return src
559 def coerce_to_pyobject(self, env):
560 return self.coerce_to(PyrexTypes.py_object_type, env)
562 def coerce_to_boolean(self, env):
563 # Coerce result to something acceptable as
564 # a boolean value.
565 type = self.type
566 if type.is_pyobject or type.is_ptr or type.is_float:
567 return CoerceToBooleanNode(self, env)
568 else:
569 if not type.is_int and not type.is_error:
570 error(self.pos,
571 "Type '%s' not acceptable as a boolean" % type)
572 return self
574 def coerce_to_integer(self, env):
575 # If not already some C integer type, coerce to longint.
576 if self.type.is_int:
577 return self
578 else:
579 return self.coerce_to(PyrexTypes.c_long_type, env)
581 def coerce_to_temp(self, env):
582 # Ensure that the result is in a temporary.
583 if self.result_in_temp():
584 return self
585 else:
586 return CoerceToTempNode(self, env)
588 def coerce_to_simple(self, env):
589 # Ensure that the result is simple (see is_simple).
590 if self.is_simple():
591 return self
592 else:
593 return self.coerce_to_temp(env)
595 def is_simple(self):
596 # A node is simple if its result is something that can
597 # be referred to without performing any operations, e.g.
598 # a constant, local var, C global var, struct member
599 # reference, or temporary.
600 return self.result_in_temp()
602 def as_cython_attribute(self):
603 return None
606 class RemoveAllocateTemps(type):
607 def __init__(cls, name, bases, dct):
608 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
609 def noop(self, env): pass
610 setattr(cls, 'allocate_temps', noop)
611 setattr(cls, 'allocate_temp', noop)
612 setattr(cls, 'release_temp', noop)
614 class NewTempExprNode(ExprNode):
615 backwards_compatible_result = None
616 temp_code = None
617 old_temp = None # error checker for multiple frees etc.
619 # Do not enable this unless you are trying to make all ExprNodes
620 # NewTempExprNodes (child nodes reached via recursion may not have
621 # transferred).
622 # __metaclass__ = RemoveAllocateTemps
624 def result(self):
625 if self.is_temp:
626 return self.temp_code
627 else:
628 return self.calculate_result_code()
630 def allocate_target_temps(self, env, rhs):
631 self.allocate_subexpr_temps(env)
632 self.is_target = True
633 if rhs:
634 rhs.release_temp(env)
635 self.release_subexpr_temps(env)
637 def allocate_temps(self, env, result = None):
638 self.allocate_subexpr_temps(env)
639 self.backwards_compatible_result = result
640 if self.is_temp:
641 self.release_subexpr_temps(env)
643 def allocate_temp(self, env, result = None):
644 assert result is None
646 def release_temp(self, env):
647 if self.is_temp:
648 pass
649 else:
650 self.release_subexpr_temps(env)
652 def allocate_temp_result(self, code):
653 if self.temp_code:
654 raise RuntimeError("Temp allocated multiple times")
655 type = self.type
656 if not type.is_void:
657 if type.is_pyobject:
658 type = PyrexTypes.py_object_type
659 if self.backwards_compatible_result:
660 self.temp_code = self.backwards_compatible_result
661 else:
662 self.temp_code = code.funcstate.allocate_temp(
663 type, manage_ref=True)
664 else:
665 self.temp_code = None
667 def release_temp_result(self, code):
668 if not self.temp_code:
669 if self.old_temp:
670 raise RuntimeError("temp %s released multiple times in %s" % (
671 self.old_temp, self.__class__.__name__))
672 else:
673 raise RuntimeError("no temp, but release requested in %s" % (
674 self.__class__.__name__))
675 code.funcstate.release_temp(self.temp_code)
676 self.old_temp = self.temp_code
677 self.temp_code = None
679 def generate_evaluation_code(self, code):
680 code.mark_pos(self.pos)
682 # Generate code to evaluate this node and
683 # its sub-expressions, and dispose of any
684 # temporary results of its sub-expressions.
685 self.generate_subexpr_evaluation_code(code)
687 if self.is_temp:
688 self.allocate_temp_result(code)
690 self.generate_result_code(code)
691 if self.is_temp:
692 # If we are temp we do not need to wait until this node is disposed
693 # before disposing children.
694 self.generate_subexpr_disposal_code(code)
695 self.free_subexpr_temps(code)
697 def generate_disposal_code(self, code):
698 if self.is_temp:
699 if self.type.is_pyobject:
700 code.put_decref_clear(self.result(), self.ctype())
701 else:
702 # Already done if self.is_temp
703 self.generate_subexpr_disposal_code(code)
705 def generate_post_assignment_code(self, code):
706 if self.is_temp:
707 if self.type.is_pyobject:
708 code.putln("%s = 0;" % self.result())
709 else:
710 self.generate_subexpr_disposal_code(code)
712 def free_temps(self, code):
713 if self.is_temp:
714 if not self.type.is_void:
715 self.release_temp_result(code)
716 else:
717 self.free_subexpr_temps(code)
719 # ExprNode = NewTempExprNode
721 class AtomicExprNode(ExprNode):
722 # Abstract base class for expression nodes which have
723 # no sub-expressions.
725 subexprs = []
727 class AtomicNewTempExprNode(NewTempExprNode):
728 # I do not dare to convert NameNode yet. This is now
729 # ancestor of all former AtomicExprNode except
730 # NameNode. Should be renamed to AtomicExprNode
731 # when done.
733 # Abstract base class for expression nodes which have
734 # no sub-expressions.
736 subexprs = []
738 # Override to optimize -- we know we have no children
739 def generate_subexpr_evaluation_code(self, code):
740 pass
741 def generate_subexpr_disposal_code(self, code):
742 pass
744 class PyConstNode(AtomicNewTempExprNode):
745 # Abstract base class for constant Python values.
747 is_literal = 1
749 def is_simple(self):
750 return 1
752 def analyse_types(self, env):
753 self.type = py_object_type
755 def calculate_result_code(self):
756 return self.value
758 def generate_result_code(self, code):
759 pass
762 class NoneNode(PyConstNode):
763 # The constant value None
765 value = "Py_None"
767 constant_result = None
769 def compile_time_value(self, denv):
770 return None
772 class EllipsisNode(PyConstNode):
773 # '...' in a subscript list.
775 value = "Py_Ellipsis"
777 constant_result = Ellipsis
779 def compile_time_value(self, denv):
780 return Ellipsis
783 class ConstNode(AtomicNewTempExprNode):
784 # Abstract base type for literal constant nodes.
785 #
786 # value string C code fragment
788 is_literal = 1
790 def is_simple(self):
791 return 1
793 def analyse_types(self, env):
794 pass # Types are held in class variables
796 def check_const(self):
797 pass
799 def calculate_result_code(self):
800 return str(self.value)
802 def generate_result_code(self, code):
803 pass
806 class BoolNode(ConstNode):
807 type = PyrexTypes.c_bint_type
808 # The constant value True or False
810 def calculate_constant_result(self):
811 self.constant_result = self.value
813 def compile_time_value(self, denv):
814 return self.value
816 def calculate_result_code(self):
817 return str(int(self.value))
819 class NullNode(ConstNode):
820 type = PyrexTypes.c_null_ptr_type
821 value = "NULL"
822 constant_result = 0
825 class CharNode(ConstNode):
826 type = PyrexTypes.c_char_type
828 def calculate_constant_result(self):
829 self.constant_result = ord(self.value)
831 def compile_time_value(self, denv):
832 return ord(self.value)
834 def calculate_result_code(self):
835 return "'%s'" % StringEncoding.escape_character(self.value)
838 class IntNode(ConstNode):
840 # unsigned "" or "U"
841 # longness "" or "L" or "LL"
843 unsigned = ""
844 longness = ""
845 type = PyrexTypes.c_long_type
847 def coerce_to(self, dst_type, env):
848 if dst_type.is_numeric:
849 self.type = PyrexTypes.c_long_type
850 return self
851 # Arrange for a Python version of the number to be pre-allocated
852 # when coercing to a Python type.
853 if dst_type.is_pyobject:
854 self.entry = env.get_py_num(self.value, self.longness)
855 self.type = PyrexTypes.py_object_type
856 # We still need to perform normal coerce_to processing on the
857 # result, because we might be coercing to an extension type,
858 # in which case a type test node will be needed.
859 return ConstNode.coerce_to(self, dst_type, env)
861 def coerce_to_boolean(self, env):
862 self.type = PyrexTypes.c_bint_type
863 return self
865 def calculate_result_code(self):
866 if self.type.is_pyobject:
867 return self.entry.cname
868 else:
869 return str(self.value) + self.unsigned + self.longness
871 def calculate_constant_result(self):
872 self.constant_result = int(self.value, 0)
874 def compile_time_value(self, denv):
875 return int(self.value, 0)
878 class FloatNode(ConstNode):
879 type = PyrexTypes.c_double_type
881 def calculate_constant_result(self):
882 self.constant_result = float(self.value)
884 def compile_time_value(self, denv):
885 return float(self.value)
887 def calculate_result_code(self):
888 strval = repr(float(self.value))
889 if strval == 'nan':
890 return "(Py_HUGE_VAL * 0)"
891 elif strval == 'inf':
892 return "Py_HUGE_VAL"
893 elif strval == '-inf':
894 return "(-Py_HUGE_VAL)"
895 else:
896 return strval
899 class StringNode(ConstNode):
900 # entry Symtab.Entry
902 type = PyrexTypes.c_char_ptr_type
904 def compile_time_value(self, denv):
905 return self.value
907 def analyse_types(self, env):
908 self.entry = env.add_string_const(self.value)
910 def analyse_as_type(self, env):
911 type = PyrexTypes.parse_basic_type(self.value)
912 if type is not None:
913 return type
914 from TreeFragment import TreeFragment
915 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
916 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
917 sizeof_node = declaration.root.stats[0].expr
918 sizeof_node.analyse_types(env)
919 if isinstance(sizeof_node, SizeofTypeNode):
920 return sizeof_node.arg_type
922 def coerce_to(self, dst_type, env):
923 if dst_type == PyrexTypes.c_char_ptr_type:
924 self.type = PyrexTypes.c_char_ptr_type
925 return self
927 if dst_type.is_int:
928 if not self.type.is_pyobject and len(self.entry.init) == 1:
929 return CharNode(self.pos, value=self.value)
930 else:
931 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
932 return self
933 # Arrange for a Python version of the string to be pre-allocated
934 # when coercing to a Python type.
935 if dst_type.is_pyobject and not self.type.is_pyobject:
936 node = self.as_py_string_node(env)
937 else:
938 node = self
939 # We still need to perform normal coerce_to processing on the
940 # result, because we might be coercing to an extension type,
941 # in which case a type test node will be needed.
942 return ConstNode.coerce_to(node, dst_type, env)
944 def as_py_string_node(self, env):
945 # Return a new StringNode with the same entry as this node
946 # but whose type is a Python type instead of a C type.
947 entry = self.entry
948 env.add_py_string(entry)
949 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
951 def calculate_result_code(self):
952 if self.type.is_pyobject:
953 return self.entry.pystring_cname
954 else:
955 return self.entry.cname
958 class UnicodeNode(PyConstNode):
959 # entry Symtab.Entry
961 type = unicode_type
963 def analyse_types(self, env):
964 self.entry = env.add_string_const(self.value)
965 env.add_py_string(self.entry)
967 def calculate_result_code(self):
968 return self.entry.pystring_cname
970 def _coerce_to(self, dst_type, env):
971 if not dst_type.is_pyobject:
972 node = StringNode(self.pos, entry = entry, type = py_object_type)
973 return ConstNode.coerce_to(node, dst_type, env)
974 else:
975 return self
976 # We still need to perform normal coerce_to processing on the
977 # result, because we might be coercing to an extension type,
978 # in which case a type test node will be needed.
980 def compile_time_value(self, env):
981 return self.value
984 class IdentifierStringNode(ConstNode):
985 # A Python string that behaves like an identifier, e.g. for
986 # keyword arguments in a call, or for imported names
987 type = PyrexTypes.py_object_type
989 def analyse_types(self, env):
990 self.cname = env.intern_identifier(self.value)
992 def calculate_result_code(self):
993 return self.cname
996 class LongNode(AtomicNewTempExprNode):
997 # Python long integer literal
998 #
999 # value string
1001 def calculate_constant_result(self):
1002 self.constant_result = long(self.value)
1004 def compile_time_value(self, denv):
1005 return long(self.value)
1007 gil_message = "Constructing Python long int"
1009 def analyse_types(self, env):
1010 self.type = py_object_type
1011 self.gil_check(env)
1012 self.is_temp = 1
1014 gil_message = "Constructing Python long int"
1016 def generate_result_code(self, code):
1017 code.putln(
1018 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1019 self.result(),
1020 self.value,
1021 code.error_goto_if_null(self.result(), self.pos)))
1022 code.put_gotref(self.py_result())
1025 class ImagNode(AtomicNewTempExprNode):
1026 # Imaginary number literal
1028 # value float imaginary part
1030 def calculate_constant_result(self):
1031 self.constant_result = complex(0.0, self.value)
1033 def compile_time_value(self, denv):
1034 return complex(0.0, self.value)
1036 def analyse_types(self, env):
1037 self.type = py_object_type
1038 self.gil_check(env)
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
1059 # interned_cname string
1061 is_name = True
1062 is_cython_module = False
1063 cython_attribute = None
1064 lhs_of_first_assignment = False
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 env.use_utility_code(get_name_interned_utility_code)
1181 self.gil_check(env)
1183 gil_message = "Accessing Python global or builtin"
1185 def analyse_entry(self, env):
1186 #print "NameNode.analyse_entry:", self.name ###
1187 self.check_identifier_kind()
1188 entry = self.entry
1189 type = entry.type
1190 self.type = type
1191 if entry.is_pyglobal or entry.is_builtin:
1192 assert type.is_pyobject, "Python global or builtin not a Python object"
1193 self.interned_cname = self.entry.interned_cname = \
1194 env.intern_identifier(self.entry.name)
1196 def check_identifier_kind(self):
1197 #print "NameNode.check_identifier_kind:", self.entry.name ###
1198 #print self.entry.__dict__ ###
1199 entry = self.entry
1200 #entry.used = 1
1201 if not (entry.is_const or entry.is_variable
1202 or entry.is_builtin or entry.is_cfunction):
1203 if self.entry.as_variable:
1204 self.entry = self.entry.as_variable
1205 else:
1206 error(self.pos,
1207 "'%s' is not a constant, variable or function identifier" % self.name)
1209 def is_simple(self):
1210 # If it's not a C variable, it'll be in a temp.
1211 return 1
1213 def calculate_target_results(self, env):
1214 pass
1216 def check_const(self):
1217 entry = self.entry
1218 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1219 self.not_const()
1221 def check_const_addr(self):
1222 entry = self.entry
1223 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1224 self.addr_not_const()
1226 def is_lvalue(self):
1227 return self.entry.is_variable and \
1228 not self.entry.type.is_array and \
1229 not self.entry.is_readonly
1231 def is_ephemeral(self):
1232 # Name nodes are never ephemeral, even if the
1233 # result is in a temporary.
1234 return 0
1236 def allocate_temp(self, env, result = None):
1237 AtomicExprNode.allocate_temp(self, env, result)
1238 entry = self.entry
1239 if entry:
1240 entry.used = 1
1241 if entry.type.is_buffer:
1242 import Buffer
1243 Buffer.used_buffer_aux_vars(entry)
1244 if entry.utility_code:
1245 env.use_utility_code(entry.utility_code)
1247 def calculate_result_code(self):
1248 entry = self.entry
1249 if not entry:
1250 return "<error>" # There was an error earlier
1251 return entry.cname
1253 def generate_result_code(self, code):
1254 assert hasattr(self, 'entry')
1255 entry = self.entry
1256 if entry is None:
1257 return # There was an error earlier
1258 if entry.is_builtin and Options.cache_builtins:
1259 return # Lookup already cached
1260 elif entry.is_pyglobal or entry.is_builtin:
1261 if entry.is_builtin:
1262 namespace = Naming.builtins_cname
1263 else: # entry.is_pyglobal
1264 namespace = entry.scope.namespace_cname
1265 code.putln(
1266 '%s = __Pyx_GetName(%s, %s); %s' % (
1267 self.result(),
1268 namespace,
1269 self.interned_cname,
1270 code.error_goto_if_null(self.result(), self.pos)))
1271 code.put_gotref(self.py_result())
1273 elif entry.is_local and False:
1274 # control flow not good enough yet
1275 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1276 if assigned is False:
1277 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1278 elif not Options.init_local_none and assigned is None:
1279 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1280 (entry.cname, entry.name, code.error_goto(self.pos)))
1281 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1283 def generate_assignment_code(self, rhs, code):
1284 #print "NameNode.generate_assignment_code:", self.name ###
1285 entry = self.entry
1286 if entry is None:
1287 return # There was an error earlier
1289 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1290 and not self.lhs_of_first_assignment):
1291 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1293 # is_pyglobal seems to be True for module level-globals only.
1294 # We use this to access class->tp_dict if necessary.
1295 if entry.is_pyglobal:
1296 namespace = self.entry.scope.namespace_cname
1297 if entry.is_member:
1298 # if the entry is a member we have to cheat: SetAttr does not work
1299 # on types, so we create a descriptor which is then added to tp_dict
1300 code.put_error_if_neg(self.pos,
1301 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1302 namespace,
1303 self.interned_cname,
1304 rhs.py_result()))
1305 rhs.generate_disposal_code(code)
1306 rhs.free_temps(code)
1307 # in Py2.6+, we need to invalidate the method cache
1308 code.putln("PyType_Modified(%s);" %
1309 entry.scope.parent_type.typeptr_cname)
1310 else:
1311 code.put_error_if_neg(self.pos,
1312 'PyObject_SetAttr(%s, %s, %s)' % (
1313 namespace,
1314 self.interned_cname,
1315 rhs.py_result()))
1316 if debug_disposal_code:
1317 print("NameNode.generate_assignment_code:")
1318 print("...generating disposal code for %s" % rhs)
1319 rhs.generate_disposal_code(code)
1320 rhs.free_temps(code)
1321 else:
1322 if self.type.is_buffer:
1323 # Generate code for doing the buffer release/acquisition.
1324 # This might raise an exception in which case the assignment (done
1325 # below) will not happen.
1327 # The reason this is not in a typetest-like node is because the
1328 # variables that the acquired buffer info is stored to is allocated
1329 # per entry and coupled with it.
1330 self.generate_acquire_buffer(rhs, code)
1332 if self.type.is_pyobject:
1333 rhs.make_owned_reference(code)
1334 #print "NameNode.generate_assignment_code: to", self.name ###
1335 #print "...from", rhs ###
1336 #print "...LHS type", self.type, "ctype", self.ctype() ###
1337 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1338 if entry.is_cglobal:
1339 code.put_gotref(self.py_result())
1340 if not self.lhs_of_first_assignment:
1341 if entry.is_local and not Options.init_local_none:
1342 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1343 if initalized is True:
1344 code.put_decref(self.result(), self.ctype())
1345 elif initalized is None:
1346 code.put_xdecref(self.result(), self.ctype())
1347 else:
1348 code.put_decref(self.result(), self.ctype())
1349 if entry.is_cglobal:
1350 code.put_giveref(rhs.py_result())
1351 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1352 if debug_disposal_code:
1353 print("NameNode.generate_assignment_code:")
1354 print("...generating post-assignment code for %s" % rhs)
1355 rhs.generate_post_assignment_code(code)
1356 rhs.free_temps(code)
1358 def generate_acquire_buffer(self, rhs, code):
1359 # rhstmp is only used in case the rhs is a complicated expression leading to
1360 # the object, to avoid repeating the same C expression for every reference
1361 # to the rhs. It does NOT hold a reference.
1362 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1363 if pretty_rhs:
1364 rhstmp = rhs.result_as(self.ctype())
1365 else:
1366 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1367 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1369 buffer_aux = self.entry.buffer_aux
1370 bufstruct = buffer_aux.buffer_info_var.cname
1371 import Buffer
1372 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1373 is_initialized=not self.lhs_of_first_assignment,
1374 pos=self.pos, code=code)
1376 if not pretty_rhs:
1377 code.putln("%s = 0;" % rhstmp)
1378 code.funcstate.release_temp(rhstmp)
1380 def generate_deletion_code(self, code):
1381 if self.entry is None:
1382 return # There was an error earlier
1383 if not self.entry.is_pyglobal:
1384 error(self.pos, "Deletion of local or C global name not supported")
1385 return
1386 code.put_error_if_neg(self.pos,
1387 '__Pyx_DelAttrString(%s, "%s")' % (
1388 Naming.module_cname,
1389 self.entry.name))
1391 def annotate(self, code):
1392 if hasattr(self, 'is_called') and self.is_called:
1393 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1394 if self.type.is_pyobject:
1395 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1396 else:
1397 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1399 class BackquoteNode(ExprNode):
1400 # `expr`
1402 # arg ExprNode
1404 subexprs = ['arg']
1406 def analyse_types(self, env):
1407 self.arg.analyse_types(env)
1408 self.arg = self.arg.coerce_to_pyobject(env)
1409 self.type = py_object_type
1410 self.gil_check(env)
1411 self.is_temp = 1
1413 gil_message = "Backquote expression"
1415 def calculate_constant_result(self):
1416 self.constant_result = repr(self.arg.constant_result)
1418 def generate_result_code(self, code):
1419 code.putln(
1420 "%s = PyObject_Repr(%s); %s" % (
1421 self.result(),
1422 self.arg.py_result(),
1423 code.error_goto_if_null(self.result(), self.pos)))
1424 code.put_gotref(self.py_result())
1428 class ImportNode(ExprNode):
1429 # Used as part of import statement implementation.
1430 # Implements result =
1431 # __import__(module_name, globals(), None, name_list)
1433 # module_name IdentifierStringNode dotted name of module
1434 # name_list ListNode or None list of names to be imported
1436 subexprs = ['module_name', 'name_list']
1438 def analyse_types(self, env):
1439 self.module_name.analyse_types(env)
1440 self.module_name = self.module_name.coerce_to_pyobject(env)
1441 if self.name_list:
1442 self.name_list.analyse_types(env)
1443 self.name_list.coerce_to_pyobject(env)
1444 self.type = py_object_type
1445 self.gil_check(env)
1446 self.is_temp = 1
1447 env.use_utility_code(import_utility_code)
1449 gil_message = "Python import"
1451 def generate_result_code(self, code):
1452 if self.name_list:
1453 name_list_code = self.name_list.py_result()
1454 else:
1455 name_list_code = "0"
1456 code.putln(
1457 "%s = __Pyx_Import(%s, %s); %s" % (
1458 self.result(),
1459 self.module_name.py_result(),
1460 name_list_code,
1461 code.error_goto_if_null(self.result(), self.pos)))
1462 code.put_gotref(self.py_result())
1465 class IteratorNode(NewTempExprNode):
1466 # Used as part of for statement implementation.
1468 # allocate_counter_temp/release_counter_temp needs to be called
1469 # by parent (ForInStatNode)
1471 # Implements result = iter(sequence)
1473 # sequence ExprNode
1475 subexprs = ['sequence']
1477 def analyse_types(self, env):
1478 self.sequence.analyse_types(env)
1479 self.sequence = self.sequence.coerce_to_pyobject(env)
1480 self.type = py_object_type
1481 self.gil_check(env)
1482 self.is_temp = 1
1484 gil_message = "Iterating over Python object"
1486 def allocate_counter_temp(self, code):
1487 self.counter_cname = code.funcstate.allocate_temp(
1488 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1490 def release_counter_temp(self, code):
1491 code.funcstate.release_temp(self.counter_cname)
1493 def generate_result_code(self, code):
1494 is_builtin_sequence = self.sequence.type is list_type or \
1495 self.sequence.type is tuple_type
1496 if is_builtin_sequence:
1497 code.putln(
1498 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1499 else:
1500 code.putln(
1501 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1502 self.sequence.py_result(),
1503 self.sequence.py_result()))
1504 code.putln(
1505 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1506 self.counter_cname,
1507 self.result(),
1508 self.sequence.py_result(),
1509 self.result()))
1510 code.putln("} else {")
1511 if is_builtin_sequence:
1512 code.putln(
1513 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1514 code.error_goto(self.pos))
1515 else:
1516 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1517 self.counter_cname,
1518 self.result(),
1519 self.sequence.py_result(),
1520 code.error_goto_if_null(self.result(), self.pos)))
1521 code.put_gotref(self.py_result())
1522 code.putln("}")
1525 class NextNode(AtomicNewTempExprNode):
1526 # Used as part of for statement implementation.
1527 # Implements result = iterator.next()
1528 # Created during analyse_types phase.
1529 # The iterator is not owned by this node.
1531 # iterator ExprNode
1533 def __init__(self, iterator, env):
1534 self.pos = iterator.pos
1535 self.iterator = iterator
1536 self.type = py_object_type
1537 self.is_temp = 1
1539 def generate_result_code(self, code):
1540 if self.iterator.sequence.type is list_type:
1541 type_checks = [(list_type, "List")]
1542 elif self.iterator.sequence.type is tuple_type:
1543 type_checks = [(tuple_type, "Tuple")]
1544 else:
1545 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1547 for py_type, prefix in type_checks:
1548 if len(type_checks) > 1:
1549 code.putln(
1550 "if (likely(Py%s_CheckExact(%s))) {" % (
1551 prefix, self.iterator.py_result()))
1552 code.putln(
1553 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1554 self.iterator.counter_cname,
1555 prefix,
1556 self.iterator.py_result()))
1557 code.putln(
1558 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1559 self.result(),
1560 prefix,
1561 self.iterator.py_result(),
1562 self.iterator.counter_cname,
1563 self.result(),
1564 self.iterator.counter_cname))
1565 if len(type_checks) > 1:
1566 code.put("} else ")
1567 if len(type_checks) == 1:
1568 return
1569 code.putln("{")
1570 code.putln(
1571 "%s = PyIter_Next(%s);" % (
1572 self.result(),
1573 self.iterator.py_result()))
1574 code.putln(
1575 "if (!%s) {" %
1576 self.result())
1577 code.putln(code.error_goto_if_PyErr(self.pos))
1578 code.putln("break;")
1579 code.putln("}")
1580 code.put_gotref(self.py_result())
1581 code.putln("}")
1584 class ExcValueNode(AtomicNewTempExprNode):
1585 # Node created during analyse_types phase
1586 # of an ExceptClauseNode to fetch the current
1587 # exception value.
1589 def __init__(self, pos, env, var):
1590 ExprNode.__init__(self, pos)
1591 self.type = py_object_type
1592 self.var = var
1594 def calculate_result_code(self):
1595 return self.var
1597 def generate_result_code(self, code):
1598 pass
1600 def analyse_types(self, env):
1601 pass
1604 class TempNode(ExprNode):
1605 # Node created during analyse_types phase
1606 # of some nodes to hold a temporary value.
1608 subexprs = []
1610 def __init__(self, pos, type, env):
1611 ExprNode.__init__(self, pos)
1612 self.type = type
1613 if type.is_pyobject:
1614 self.result_ctype = py_object_type
1615 self.is_temp = 1
1617 def analyse_types(self, env):
1618 return self.type
1620 def generate_result_code(self, code):
1621 pass
1624 class PyTempNode(TempNode):
1625 # TempNode holding a Python value.
1627 def __init__(self, pos, env):
1628 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1631 #-------------------------------------------------------------------
1633 # Trailer nodes
1635 #-------------------------------------------------------------------
1637 class IndexNode(ExprNode):
1638 # Sequence indexing.
1640 # base ExprNode
1641 # index ExprNode
1642 # indices [ExprNode]
1643 # is_buffer_access boolean Whether this is a buffer access.
1645 # indices is used on buffer access, index on non-buffer access.
1646 # The former contains a clean list of index parameters, the
1647 # latter whatever Python object is needed for index access.
1649 subexprs = ['base', 'index', 'indices']
1650 indices = None
1652 def __init__(self, pos, index, *args, **kw):
1653 ExprNode.__init__(self, pos, index=index, *args, **kw)
1654 self._index = index
1656 def calculate_constant_result(self):
1657 self.constant_result = \
1658 self.base.constant_result[self.index.constant_result]
1660 def compile_time_value(self, denv):
1661 base = self.base.compile_time_value(denv)
1662 index = self.index.compile_time_value(denv)
1663 try:
1664 return base[index]
1665 except Exception, e:
1666 self.compile_time_value_error(e)
1668 def is_ephemeral(self):
1669 return self.base.is_ephemeral()
1671 def analyse_target_declaration(self, env):
1672 pass
1674 def analyse_as_type(self, env):
1675 base_type = self.base.analyse_as_type(env)
1676 if base_type and not base_type.is_pyobject:
1677 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1678 return None
1680 def analyse_types(self, env):
1681 self.analyse_base_and_index_types(env, getting = 1)
1683 def analyse_target_types(self, env):
1684 self.analyse_base_and_index_types(env, setting = 1)
1686 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1687 # Note: This might be cleaned up by having IndexNode
1688 # parsed in a saner way and only construct the tuple if
1689 # needed.
1691 # Note that this function must leave IndexNode in a cloneable state.
1692 # For buffers, self.index is packed out on the initial analysis, and
1693 # when cloning self.indices is copied.
1694 self.is_buffer_access = False
1696 self.base.analyse_types(env)
1697 # Handle the case where base is a literal char* (and we expect a string, not an int)
1698 if isinstance(self.base, StringNode):
1699 self.base = self.base.coerce_to_pyobject(env)
1701 skip_child_analysis = False
1702 buffer_access = False
1703 if self.base.type.is_buffer:
1704 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1705 if self.indices:
1706 indices = self.indices
1707 else:
1708 # On cloning, indices is cloned. Otherwise, unpack index into indices
1709 assert not isinstance(self.index, CloneNode)
1710 if isinstance(self.index, TupleNode):
1711 indices = self.index.args
1712 else:
1713 indices = [self.index]
1714 if len(indices) == self.base.type.ndim:
1715 buffer_access = True
1716 skip_child_analysis = True
1717 for x in indices:
1718 x.analyse_types(env)
1719 if not x.type.is_int:
1720 buffer_access = False
1722 if buffer_access:
1723 self.indices = indices
1724 self.index = None
1725 self.type = self.base.type.dtype
1726 self.is_buffer_access = True
1727 self.buffer_type = self.base.entry.type
1729 if getting and self.type.is_pyobject:
1730 self.is_temp = True
1731 if setting:
1732 if not self.base.entry.type.writable:
1733 error(self.pos, "Writing to readonly buffer")
1734 else:
1735 self.base.entry.buffer_aux.writable_needed = True
1736 else:
1737 if isinstance(self.index, TupleNode):
1738 self.index.analyse_types(env, skip_children=skip_child_analysis)
1739 elif not skip_child_analysis:
1740 self.index.analyse_types(env)
1741 self.original_index_type = self.index.type
1742 if self.base.type.is_pyobject:
1743 if self.index.type.is_int:
1744 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1745 else:
1746 self.index = self.index.coerce_to_pyobject(env)
1747 self.type = py_object_type
1748 self.gil_check(env)
1749 self.is_temp = 1
1750 else:
1751 if self.base.type.is_ptr or self.base.type.is_array:
1752 self.type = self.base.type.base_type
1753 else:
1754 error(self.pos,
1755 "Attempting to index non-array type '%s'" %
1756 self.base.type)
1757 self.type = PyrexTypes.error_type
1758 if self.index.type.is_pyobject:
1759 self.index = self.index.coerce_to(
1760 PyrexTypes.c_py_ssize_t_type, env)
1761 if not self.index.type.is_int:
1762 error(self.pos,
1763 "Invalid index type '%s'" %
1764 self.index.type)
1766 gil_message = "Indexing Python object"
1768 def check_const_addr(self):
1769 self.base.check_const_addr()
1770 self.index.check_const()
1772 def is_lvalue(self):
1773 return 1
1775 def calculate_result_code(self):
1776 if self.is_buffer_access:
1777 return "(*%s)" % self.buffer_ptr_code
1778 else:
1779 return "(%s[%s])" % (
1780 self.base.result(), self.index.result())
1782 def extra_index_params(self):
1783 if self.index.type.is_int:
1784 if self.original_index_type.signed:
1785 size_adjustment = ""
1786 else:
1787 size_adjustment = "+1"
1788 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1789 else:
1790 return ""
1792 def generate_subexpr_evaluation_code(self, code):
1793 self.base.generate_evaluation_code(code)
1794 if not self.indices:
1795 self.index.generate_evaluation_code(code)
1796 else:
1797 for i in self.indices:
1798 i.generate_evaluation_code(code)
1800 def generate_subexpr_disposal_code(self, code):
1801 self.base.generate_disposal_code(code)
1802 if not self.indices:
1803 self.index.generate_disposal_code(code)
1804 else:
1805 for i in self.indices:
1806 i.generate_disposal_code(code)
1808 def free_subexpr_temps(self, code):
1809 self.base.free_temps(code)
1810 if not self.indices:
1811 self.index.free_temps(code)
1812 else:
1813 for i in self.indices:
1814 i.free_temps(code)
1816 def generate_result_code(self, code):
1817 if self.is_buffer_access:
1818 if code.globalstate.directives['nonecheck']:
1819 self.put_nonecheck(code)
1820 self.buffer_ptr_code = self.buffer_lookup_code(code)
1821 if self.type.is_pyobject:
1822 # is_temp is True, so must pull out value and incref it.
1823 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1824 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1825 elif self.type.is_pyobject:
1826 if self.index.type.is_int:
1827 index_code = self.index.result()
1828 if self.base.type is list_type:
1829 function = "__Pyx_GetItemInt_List"
1830 elif self.base.type is tuple_type:
1831 function = "__Pyx_GetItemInt_Tuple"
1832 else:
1833 function = "__Pyx_GetItemInt"
1834 code.globalstate.use_utility_code(getitem_int_utility_code)
1835 else:
1836 function = "PyObject_GetItem"
1837 index_code = self.index.py_result()
1838 sign_code = ""
1839 code.putln(
1840 "%s = %s(%s, %s%s); if (!%s) %s" % (
1841 self.result(),
1842 function,
1843 self.base.py_result(),
1844 index_code,
1845 self.extra_index_params(),
1846 self.result(),
1847 code.error_goto(self.pos)))
1848 code.put_gotref(self.py_result())
1850 def generate_setitem_code(self, value_code, code):
1851 if self.index.type.is_int:
1852 function = "__Pyx_SetItemInt"
1853 index_code = self.index.result()
1854 code.globalstate.use_utility_code(setitem_int_utility_code)
1855 else:
1856 index_code = self.index.py_result()
1857 if self.base.type is dict_type:
1858 function = "PyDict_SetItem"
1859 elif self.base.type is list_type:
1860 function = "PyList_SetItem"
1861 # don't use PyTuple_SetItem(), as we'd normally get a
1862 # TypeError when changing a tuple, while PyTuple_SetItem()
1863 # would allow updates
1865 #elif self.base.type is tuple_type:
1866 # function = "PyTuple_SetItem"
1867 else:
1868 function = "PyObject_SetItem"
1869 code.putln(
1870 "if (%s(%s, %s, %s%s) < 0) %s" % (
1871 function,
1872 self.base.py_result(),
1873 index_code,
1874 value_code,
1875 self.extra_index_params(),
1876 code.error_goto(self.pos)))
1878 def generate_buffer_setitem_code(self, rhs, code, op=""):
1879 # Used from generate_assignment_code and InPlaceAssignmentNode
1880 if code.globalstate.directives['nonecheck']:
1881 self.put_nonecheck(code)
1882 ptrexpr = self.buffer_lookup_code(code)
1883 if self.buffer_type.dtype.is_pyobject:
1884 # Must manage refcounts. Decref what is already there
1885 # and incref what we put in.
1886 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1887 rhs_code = rhs.result()
1888 code.putln("%s = %s;" % (ptr, ptrexpr))
1889 code.put_gotref("*%s" % ptr)
1890 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1891 ptr, rhs_code
1892 ))
1893 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1894 code.put_giveref("*%s" % ptr)
1895 code.funcstate.release_temp(ptr)
1896 else:
1897 # Simple case
1898 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1900 def generate_assignment_code(self, rhs, code):
1901 self.generate_subexpr_evaluation_code(code)
1902 if self.is_buffer_access:
1903 self.generate_buffer_setitem_code(rhs, code)
1904 elif self.type.is_pyobject:
1905 self.generate_setitem_code(rhs.py_result(), code)
1906 else:
1907 code.putln(
1908 "%s = %s;" % (
1909 self.result(), rhs.result()))
1910 self.generate_subexpr_disposal_code(code)
1911 self.free_subexpr_temps(code)
1912 rhs.generate_disposal_code(code)
1913 rhs.free_temps(code)
1915 def generate_deletion_code(self, code):
1916 self.generate_subexpr_evaluation_code(code)
1917 #if self.type.is_pyobject:
1918 if self.index.type.is_int:
1919 function = "__Pyx_DelItemInt"
1920 index_code = self.index.result()
1921 code.globalstate.use_utility_code(delitem_int_utility_code)
1922 else:
1923 index_code = self.index.py_result()
1924 if self.base.type is dict_type:
1925 function = "PyDict_DelItem"
1926 else:
1927 function = "PyObject_DelItem"
1928 code.putln(
1929 "if (%s(%s, %s%s) < 0) %s" % (
1930 function,
1931 self.base.py_result(),
1932 index_code,
1933 self.extra_index_params(),
1934 code.error_goto(self.pos)))
1935 self.generate_subexpr_disposal_code(code)
1936 self.free_subexpr_temps(code)
1938 def buffer_lookup_code(self, code):
1939 # Assign indices to temps
1940 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1941 for temp, index in zip(index_temps, self.indices):
1942 code.putln("%s = %s;" % (temp, index.result()))
1943 # Generate buffer access code using these temps
1944 import Buffer
1945 # The above could happen because child_attrs is wrong somewhere so that
1946 # options are not propagated.
1947 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1948 index_signeds=[i.type.signed for i in self.indices],
1949 index_cnames=index_temps,
1950 options=code.globalstate.directives,
1951 pos=self.pos, code=code)
1953 def put_nonecheck(self, code):
1954 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1955 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1956 code.putln("__Pyx_RaiseNoneIndexingError();")
1957 code.putln(code.error_goto(self.pos))
1958 code.putln("}")
1960 class SliceIndexNode(ExprNode):
1961 # 2-element slice indexing
1963 # base ExprNode
1964 # start ExprNode or None
1965 # stop ExprNode or None
1967 subexprs = ['base', 'start', 'stop']
1969 def calculate_constant_result(self):
1970 self.constant_result = self.base.constant_result[
1971 self.start.constant_result : self.stop.constant_result]
1973 def compile_time_value(self, denv):
1974 base = self.base.compile_time_value(denv)
1975 if self.start is None:
1976 start = 0
1977 else:
1978 start = self.start.compile_time_value(denv)
1979 if self.stop is None:
1980 stop = None
1981 else:
1982 stop = self.stop.compile_time_value(denv)
1983 try:
1984 return base[start:stop]
1985 except Exception, e:
1986 self.compile_time_value_error(e)
1988 def analyse_target_declaration(self, env):
1989 pass
1991 def analyse_types(self, env):
1992 self.base.analyse_types(env)
1993 if self.start:
1994 self.start.analyse_types(env)
1995 if self.stop:
1996 self.stop.analyse_types(env)
1997 if self.base.type.is_string:
1998 self.type = py_object_type
1999 elif self.base.type.is_array or self.base.type.is_ptr:
2000 # we need a ptr type here instead of an array type, as
2001 # array types can result in invalid type casts in the C
2002 # code
2003 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
2004 else:
2005 self.base = self.base.coerce_to_pyobject(env)
2006 self.type = py_object_type
2007 c_int = PyrexTypes.c_py_ssize_t_type
2008 if self.start:
2009 self.start = self.start.coerce_to(c_int, env)
2010 if self.stop:
2011 self.stop = self.stop.coerce_to(c_int, env)
2012 self.gil_check(env)
2013 self.is_temp = 1
2015 gil_message = "Slicing Python object"
2017 def generate_result_code(self, code):
2018 if not self.type.is_pyobject:
2019 error(self.pos,
2020 "Slicing is not currently supported for '%s'." % self.type)
2021 return
2022 if self.base.type.is_string:
2023 if self.stop is None:
2024 code.putln(
2025 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2026 self.result(),
2027 self.base.result(),
2028 self.start_code(),
2029 code.error_goto_if_null(self.result(), self.pos)))
2030 else:
2031 code.putln(
2032 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2033 self.result(),
2034 self.base.result(),
2035 self.start_code(),
2036 self.stop_code(),
2037 self.start_code(),
2038 code.error_goto_if_null(self.result(), self.pos)))
2039 else:
2040 code.putln(
2041 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2042 self.result(),
2043 self.base.py_result(),
2044 self.start_code(),
2045 self.stop_code(),
2046 code.error_goto_if_null(self.result(), self.pos)))
2047 code.put_gotref(self.py_result())
2049 def generate_assignment_code(self, rhs, code):
2050 self.generate_subexpr_evaluation_code(code)
2051 if self.type.is_pyobject:
2052 code.put_error_if_neg(self.pos,
2053 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2054 self.base.py_result(),
2055 self.start_code(),
2056 self.stop_code(),
2057 rhs.result()))
2058 else:
2059 start_offset = ''
2060 if self.start:
2061 start_offset = self.start_code()
2062 if start_offset == '0':
2063 start_offset = ''
2064 else:
2065 start_offset += '+'
2066 if rhs.type.is_array:
2067 array_length = rhs.type.size
2068 self.generate_slice_guard_code(code, array_length)
2069 else:
2070 error("Slice assignments from pointers are not yet supported.")
2071 # FIXME: fix the array size according to start/stop
2072 array_length = self.base.type.size
2073 for i in range(array_length):
2074 code.putln("%s[%s%s] = %s[%d];" % (
2075 self.base.result(), start_offset, i,
2076 rhs.result(), i))
2077 self.generate_subexpr_disposal_code(code)
2078 self.free_subexpr_temps(code)
2079 rhs.generate_disposal_code(code)
2080 rhs.free_temps(code)
2082 def generate_deletion_code(self, code):
2083 if not self.base.type.is_pyobject:
2084 error(self.pos,
2085 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2086 return
2087 self.generate_subexpr_evaluation_code(code)
2088 code.put_error_if_neg(self.pos,
2089 "PySequence_DelSlice(%s, %s, %s)" % (
2090 self.base.py_result(),
2091 self.start_code(),
2092 self.stop_code()))
2093 self.generate_subexpr_disposal_code(code)
2095 def generate_slice_guard_code(self, code, target_size):
2096 if not self.base.type.is_array:
2097 return
2098 slice_size = self.base.type.size
2099 start = stop = None
2100 if self.stop:
2101 stop = self.stop.result()
2102 try:
2103 stop = int(stop)
2104 if stop < 0:
2105 slice_size = self.base.type.size + stop
2106 else:
2107 slice_size = stop
2108 stop = None
2109 except ValueError:
2110 pass
2111 if self.start:
2112 start = self.start.result()
2113 try:
2114 start = int(start)
2115 if start < 0:
2116 start = self.base.type.size + start
2117 slice_size -= start
2118 start = None
2119 except ValueError:
2120 pass
2121 check = None
2122 if slice_size < 0:
2123 if target_size > 0:
2124 error(self.pos, "Assignment to empty slice.")
2125 elif start is None and stop is None:
2126 # we know the exact slice length
2127 if target_size != slice_size:
2128 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2129 slice_size, target_size))
2130 elif start is not None:
2131 if stop is None:
2132 stop = slice_size
2133 check = "(%s)-(%s)" % (stop, start)
2134 else: # stop is not None:
2135 check = stop
2136 if check:
2137 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2138 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2139 target_size, check))
2140 code.putln(code.error_goto(self.pos))
2141 code.putln("}")
2143 def start_code(self):
2144 if self.start:
2145 return self.start.result()
2146 else:
2147 return "0"
2149 def stop_code(self):
2150 if self.stop:
2151 return self.stop.result()
2152 elif self.base.type.is_array:
2153 return self.base.type.size
2154 else:
2155 return "PY_SSIZE_T_MAX"
2157 def calculate_result_code(self):
2158 # self.result() is not used, but this method must exist
2159 return "<unused>"
2162 class SliceNode(ExprNode):
2163 # start:stop:step in subscript list
2165 # start ExprNode
2166 # stop ExprNode
2167 # step ExprNode
2169 def calculate_constant_result(self):
2170 self.constant_result = self.base.constant_result[
2171 self.start.constant_result : \
2172 self.stop.constant_result : \
2173 self.step.constant_result]
2175 def compile_time_value(self, denv):
2176 start = self.start.compile_time_value(denv)
2177 if self.stop is None:
2178 stop = None
2179 else:
2180 stop = self.stop.compile_time_value(denv)
2181 if self.step is None:
2182 step = None
2183 else:
2184 step = self.step.compile_time_value(denv)
2185 try:
2186 return slice(start, stop, step)
2187 except Exception, e:
2188 self.compile_time_value_error(e)
2190 subexprs = ['start', 'stop', 'step']
2192 def analyse_types(self, env):
2193 self.start.analyse_types(env)
2194 self.stop.analyse_types(env)
2195 self.step.analyse_types(env)
2196 self.start = self.start.coerce_to_pyobject(env)
2197 self.stop = self.stop.coerce_to_pyobject(env)
2198 self.step = self.step.coerce_to_pyobject(env)
2199 self.type = py_object_type
2200 self.gil_check(env)
2201 self.is_temp = 1
2203 gil_message = "Constructing Python slice object"
2205 def generate_result_code(self, code):
2206 code.putln(
2207 "%s = PySlice_New(%s, %s, %s); %s" % (
2208 self.result(),
2209 self.start.py_result(),
2210 self.stop.py_result(),
2211 self.step.py_result(),
2212 code.error_goto_if_null(self.result(), self.pos)))
2213 code.put_gotref(self.py_result())
2216 class CallNode(NewTempExprNode):
2217 def gil_check(self, env):
2218 # Make sure we're not in a nogil environment
2219 if env.nogil:
2220 error(self.pos, "Calling gil-requiring function without gil")
2222 def analyse_as_type_constructor(self, env):
2223 type = self.function.analyse_as_type(env)
2224 if type and type.is_struct_or_union:
2225 args, kwds = self.explicit_args_kwds()
2226 items = []
2227 for arg, member in zip(args, type.scope.var_entries):
2228 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2229 if kwds:
2230 items += kwds.key_value_pairs
2231 self.key_value_pairs = items
2232 self.__class__ = DictNode
2233 self.analyse_types(env)
2234 self.coerce_to(type, env)
2235 return True
2238 class SimpleCallNode(CallNode):
2239 # Function call without keyword, * or ** args.
2241 # function ExprNode
2242 # args [ExprNode]
2243 # arg_tuple ExprNode or None used internally
2244 # self ExprNode or None used internally
2245 # coerced_self ExprNode or None used internally
2246 # wrapper_call bool used internally
2247 # has_optional_args bool used internally
2249 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2251 self = None
2252 coerced_self = None
2253 arg_tuple = None
2254 wrapper_call = False
2255 has_optional_args = False
2257 def compile_time_value(self, denv):
2258 function = self.function.compile_time_value(denv)
2259 args = [arg.compile_time_value(denv) for arg in self.args]
2260 try:
2261 return function(*args)
2262 except Exception, e:
2263 self.compile_time_value_error(e)
2265 def analyse_as_type(self, env):
2266 attr = self.function.as_cython_attribute()
2267 if attr == 'pointer':
2268 if len(self.args) != 1:
2269 error(self.args.pos, "only one type allowed.")
2270 else:
2271 type = self.args[0].analyse_as_type(env)
2272 if not type:
2273 error(self.args[0].pos, "Unknown type")
2274 else:
2275 return PyrexTypes.CPtrType(type)
2277 def explicit_args_kwds(self):
2278 return self.args, None
2280 def analyse_types(self, env):
2281 if self.analyse_as_type_constructor(env):
2282 return
2283 function = self.function
2284 function.is_called = 1
2285 self.function.analyse_types(env)
2286 if function.is_attribute and function.is_py_attr and \
2287 function.attribute == "append" and len(self.args) == 1:
2288 # L.append(x) is almost always applied to a list
2289 self.py_func = self.function
2290 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2291 self.function.analyse_types(env)
2292 self.self = self.py_func.obj
2293 function.obj = CloneNode(self.self)
2294 env.use_utility_code(append_utility_code)
2295 if function.is_attribute and function.entry and function.entry.is_cmethod:
2296 # Take ownership of the object from which the attribute
2297 # was obtained, because we need to pass it as 'self'.
2298 self.self = function.obj
2299 function.obj = CloneNode(self.self)
2300 func_type = self.function_type()
2301 if func_type.is_pyobject:
2302 self.arg_tuple = TupleNode(self.pos, args = self.args)
2303 self.arg_tuple.analyse_types(env)
2304 self.args = None
2305 self.type = py_object_type
2306 self.gil_check(env)
2307 self.is_temp = 1
2308 else:
2309 for arg in self.args:
2310 arg.analyse_types(env)
2311 if self.self and func_type.args:
2312 # Coerce 'self' to the type expected by the method.
2313 expected_type = func_type.args[0].type
2314 self.coerced_self = CloneNode(self.self).coerce_to(
2315 expected_type, env)
2316 # Insert coerced 'self' argument into argument list.
2317 self.args.insert(0, self.coerced_self)
2318 self.analyse_c_function_call(env)
2320 def function_type(self):
2321 # Return the type of the function being called, coercing a function
2322 # pointer to a function if necessary.
2323 func_type = self.function.type
2324 if func_type.is_ptr:
2325 func_type = func_type.base_type
2326 return func_type
2328 def analyse_c_function_call(self, env):
2329 func_type = self.function_type()
2330 # Check function type
2331 if not func_type.is_cfunction:
2332 if not func_type.is_error:
2333 error(self.pos, "Calling non-function type '%s'" %
2334 func_type)
2335 self.type = PyrexTypes.error_type
2336 self.result_code = "<error>"
2337 return
2338 # Check no. of args
2339 max_nargs = len(func_type.args)
2340 expected_nargs = max_nargs - func_type.optional_arg_count
2341 actual_nargs = len(self.args)
2342 if actual_nargs < expected_nargs \
2343 or (not func_type.has_varargs and actual_nargs > max_nargs):
2344 expected_str = str(expected_nargs)
2345 if func_type.has_varargs:
2346 expected_str = "at least " + expected_str
2347 elif func_type.optional_arg_count:
2348 if actual_nargs < max_nargs:
2349 expected_str = "at least " + expected_str
2350 else:
2351 expected_str = "at most " + str(max_nargs)
2352 error(self.pos,
2353 "Call with wrong number of arguments (expected %s, got %s)"
2354 % (expected_str, actual_nargs))
2355 self.args = None
2356 self.type = PyrexTypes.error_type
2357 self.result_code = "<error>"
2358 return
2359 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2360 self.has_optional_args = 1
2361 self.is_temp = 1
2362 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2363 env.release_temp(self.opt_arg_struct)
2364 # Coerce arguments
2365 for i in range(min(max_nargs, actual_nargs)):
2366 formal_type = func_type.args[i].type
2367 self.args[i] = self.args[i].coerce_to(formal_type, env)
2368 for i in range(max_nargs, actual_nargs):
2369 if self.args[i].type.is_pyobject:
2370 error(self.args[i].pos,
2371 "Python object cannot be passed as a varargs parameter")
2372 # Calc result type and code fragment
2373 self.type = func_type.return_type
2374 if self.type.is_pyobject:
2375 self.result_ctype = py_object_type
2376 self.is_temp = 1
2377 elif func_type.exception_value is not None \
2378 or func_type.exception_check:
2379 self.is_temp = 1
2380 # C++ exception handler
2381 if func_type.exception_check == '+':
2382 if func_type.exception_value is None:
2383 env.use_utility_code(cpp_exception_utility_code)
2384 # Check gil
2385 if not func_type.nogil:
2386 self.gil_check(env)
2388 def calculate_result_code(self):
2389 return self.c_call_code()
2391 def c_call_code(self):
2392 func_type = self.function_type()
2393 if self.args is None or not func_type.is_cfunction:
2394 return "<error>"
2395 formal_args = func_type.args
2396 arg_list_code = []
2397 args = zip(formal_args, self.args)
2398 max_nargs = len(func_type.args)
2399 expected_nargs = max_nargs - func_type.optional_arg_count
2400 actual_nargs = len(self.args)
2401 for formal_arg, actual_arg in args[:expected_nargs]:
2402 arg_code = actual_arg.result_as(formal_arg.type)
2403 arg_list_code.append(arg_code)
2405 if func_type.is_overridable:
2406 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2408 if func_type.optional_arg_count:
2409 if expected_nargs == actual_nargs:
2410 optional_args = 'NULL'
2411 else:
2412 optional_args = "&%s" % self.opt_arg_struct
2413 arg_list_code.append(optional_args)
2415 for actual_arg in self.args[len(formal_args):]:
2416 arg_list_code.append(actual_arg.result())
2417 result = "%s(%s)" % (self.function.result(),
2418 ', '.join(arg_list_code))
2419 # if self.wrapper_call or \
2420 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2421 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2422 return result
2424 def generate_result_code(self, code):
2425 func_type = self.function_type()
2426 if func_type.is_pyobject:
2427 arg_code = self.arg_tuple.py_result()
2428 code.putln(
2429 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2430 self.result(),
2431 self.function.py_result(),
2432 arg_code,
2433 code.error_goto_if_null(self.result(), self.pos)))
2434 code.put_gotref(self.py_result())
2435 elif func_type.is_cfunction:
2436 if self.has_optional_args:
2437 actual_nargs = len(self.args)
2438 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2439 code.putln("%s.%s = %s;" % (
2440 self.opt_arg_struct,
2441 Naming.pyrex_prefix + "n",
2442 len(self.args) - expected_nargs))
2443 args = zip(func_type.args, self.args)
2444 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2445 code.putln("%s.%s = %s;" % (
2446 self.opt_arg_struct,
2447 formal_arg.name,
2448 actual_arg.result_as(formal_arg.type)))
2449 exc_checks = []
2450 if self.type.is_pyobject:
2451 exc_checks.append("!%s" % self.result())
2452 else:
2453 exc_val = func_type.exception_value
2454 exc_check = func_type.exception_check
2455 if exc_val is not None:
2456 exc_checks.append("%s == %s" % (self.result(), exc_val))
2457 if exc_check:
2458 exc_checks.append("PyErr_Occurred()")
2459 if self.is_temp or exc_checks:
2460 rhs = self.c_call_code()
2461 if self.result():
2462 lhs = "%s = " % self.result()
2463 if self.is_temp and self.type.is_pyobject:
2464 #return_type = self.type # func_type.return_type
2465 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2466 # "from", return_type, "to pyobject" ###
2467 rhs = typecast(py_object_type, self.type, rhs)
2468 else:
2469 lhs = ""
2470 if func_type.exception_check == '+':
2471 if func_type.exception_value is None:
2472 raise_py_exception = "__Pyx_CppExn2PyErr()"
2473 elif func_type.exception_value.type.is_pyobject:
2474 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2475 else:
2476 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2477 code.putln(
2478 "try {%s%s;} catch(...) {%s; %s}" % (
2479 lhs,
2480 rhs,
2481 raise_py_exception,
2482 code.error_goto(self.pos)))
2483 else:
2484 if exc_checks:
2485 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2486 else:
2487 goto_error = ""
2488 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2489 if self.type.is_pyobject and self.result():
2490 code.put_gotref(self.py_result())
2493 class GeneralCallNode(CallNode):
2494 # General Python function call, including keyword,
2495 # * and ** arguments.
2497 # function ExprNode
2498 # positional_args ExprNode Tuple of positional arguments
2499 # keyword_args ExprNode or None Dict of keyword arguments
2500 # starstar_arg ExprNode or None Dict of extra keyword args
2502 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2504 def compile_time_value(self, denv):
2505 function = self.function.compile_time_value(denv)
2506 positional_args = self.positional_args.compile_time_value(denv)
2507 keyword_args = self.keyword_args.compile_time_value(denv)
2508 starstar_arg = self.starstar_arg.compile_time_value(denv)
2509 try:
2510 keyword_args.update(starstar_arg)
2511 return function(*positional_args, **keyword_args)
2512 except Exception, e:
2513 self.compile_time_value_error(e)
2515 def explicit_args_kwds(self):
2516 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2517 raise PostParseError(self.pos,
2518 'Compile-time keyword arguments must be explicit.')
2519 return self.positional_args.args, self.keyword_args
2521 def analyse_types(self, env):
2522 if self.analyse_as_type_constructor(env):
2523 return
2524 self.function.analyse_types(env)
2525 self.positional_args.analyse_types(env)
2526 if self.keyword_args:
2527 self.keyword_args.analyse_types(env)
2528 if self.starstar_arg:
2529 self.starstar_arg.analyse_types(env)
2530 self.function = self.function.coerce_to_pyobject(env)
2531 self.positional_args = \
2532 self.positional_args.coerce_to_pyobject(env)
2533 if self.starstar_arg:
2534 self.starstar_arg = \
2535 self.starstar_arg.coerce_to_pyobject(env)
2536 self.type = py_object_type
2537 self.gil_check(env)
2538 self.is_temp = 1
2540 def generate_result_code(self, code):
2541 if self.keyword_args and self.starstar_arg:
2542 code.put_error_if_neg(self.pos,
2543 "PyDict_Update(%s, %s)" % (
2544 self.keyword_args.py_result(),
2545 self.starstar_arg.py_result()))
2546 keyword_code = self.keyword_args.py_result()
2547 elif self.keyword_args:
2548 keyword_code = self.keyword_args.py_result()
2549 elif self.starstar_arg:
2550 keyword_code = self.starstar_arg.py_result()
2551 else:
2552 keyword_code = None
2553 if not keyword_code:
2554 call_code = "PyObject_Call(%s, %s, NULL)" % (
2555 self.function.py_result(),
2556 self.positional_args.py_result())
2557 else:
2558 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2559 self.function.py_result(),
2560 self.positional_args.py_result(),
2561 keyword_code)
2562 code.putln(
2563 "%s = %s; %s" % (
2564 self.result(),
2565 call_code,
2566 code.error_goto_if_null(self.result(), self.pos)))
2567 code.put_gotref(self.py_result())
2570 class AsTupleNode(ExprNode):
2571 # Convert argument to tuple. Used for normalising
2572 # the * argument of a function call.
2574 # arg ExprNode
2576 subexprs = ['arg']
2578 def calculate_constant_result(self):
2579 self.constant_result = tuple(self.base.constant_result)
2581 def compile_time_value(self, denv):
2582 arg = self.arg.compile_time_value(denv)
2583 try:
2584 return tuple(arg)
2585 except Exception, e:
2586 self.compile_time_value_error(e)
2588 def analyse_types(self, env):
2589 self.arg.analyse_types(env)
2590 self.arg = self.arg.coerce_to_pyobject(env)
2591 self.type = tuple_type
2592 self.gil_check(env)
2593 self.is_temp = 1
2595 gil_message = "Constructing Python tuple"
2597 def generate_result_code(self, code):
2598 code.putln(
2599 "%s = PySequence_Tuple(%s); %s" % (
2600 self.result(),
2601 self.arg.py_result(),
2602 code.error_goto_if_null(self.result(), self.pos)))
2603 code.put_gotref(self.py_result())
2606 class AttributeNode(NewTempExprNode):
2607 # obj.attribute
2609 # obj ExprNode
2610 # attribute string
2611 # needs_none_check boolean Used if obj is an extension type.
2612 # If set to True, it is known that the type is not None.
2614 # Used internally:
2616 # is_py_attr boolean Is a Python getattr operation
2617 # member string C name of struct member
2618 # is_called boolean Function call is being done on result
2619 # entry Entry Symbol table entry of attribute
2620 # interned_attr_cname string C name of interned attribute name
2622 is_attribute = 1
2623 subexprs = ['obj']
2625 type = PyrexTypes.error_type
2626 entry = None
2627 is_called = 0
2628 needs_none_check = True
2630 def as_cython_attribute(self):
2631 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2632 return self.attribute
2634 def coerce_to(self, dst_type, env):
2635 # If coercing to a generic pyobject and this is a cpdef function
2636 # we can create the corresponding attribute
2637 if dst_type is py_object_type:
2638 entry = self.entry
2639 if entry and entry.is_cfunction and entry.as_variable:
2640 # must be a cpdef function
2641 self.is_temp = 1
2642 self.entry = entry.as_variable
2643 self.analyse_as_python_attribute(env)
2644 return self
2645 return ExprNode.coerce_to(self, dst_type, env)
2647 def calculate_constant_result(self):
2648 attr = self.attribute
2649 if attr.startswith("__") and attr.endswith("__"):
2650 return
2651 self.constant_result = getattr(self.obj.constant_result, attr)
2653 def compile_time_value(self, denv):
2654 attr = self.attribute
2655 if attr.startswith("__") and attr.endswith("__"):
2656 self.error("Invalid attribute name '%s' in compile-time expression"
2657 % attr)
2658 return None
2659 obj = self.obj.compile_time_value(denv)
2660 try:
2661 return getattr(obj, attr)
2662 except Exception, e:
2663 self.compile_time_value_error(e)
2665 def analyse_target_declaration(self, env):
2666 pass
2668 def analyse_target_types(self, env):
2669 self.analyse_types(env, target = 1)
2671 def analyse_types(self, env, target = 0):
2672 if self.analyse_as_cimported_attribute(env, target):
2673 return
2674 if not target and self.analyse_as_unbound_cmethod(env):
2675 return
2676 self.analyse_as_ordinary_attribute(env, target)
2678 def analyse_as_cimported_attribute(self, env, target):
2679 # Try to interpret this as a reference to an imported
2680 # C const, type, var or function. If successful, mutates
2681 # this node into a NameNode and returns 1, otherwise
2682 # returns 0.
2683 module_scope = self.obj.analyse_as_module(env)
2684 if module_scope:
2685 entry = module_scope.lookup_here(self.attribute)
2686 if entry and (
2687 entry.is_cglobal or entry.is_cfunction
2688 or entry.is_type or entry.is_const):
2689 self.mutate_into_name_node(env, entry, target)
2690 return 1
2691 return 0
2693 def analyse_as_unbound_cmethod(self, env):
2694 # Try to interpret this as a reference to an unbound
2695 # C method of an extension type. If successful, mutates
2696 # this node into a NameNode and returns 1, otherwise
2697 # returns 0.
2698 type = self.obj.analyse_as_extension_type(env)
2699 if type:
2700 entry = type.scope.lookup_here(self.attribute)
2701 if entry and entry.is_cmethod:
2702 # Create a temporary entry describing the C method
2703 # as an ordinary function.
2704 ubcm_entry = Symtab.Entry(entry.name,
2705 "%s->%s" % (type.vtabptr_cname, entry.cname),
2706 entry.type)
2707 ubcm_entry.is_cfunction = 1
2708 ubcm_entry.func_cname = entry.func_cname
2709 ubcm_entry.is_unbound_cmethod = 1
2710 self.mutate_into_name_node(env, ubcm_entry, None)
2711 return 1
2712 return 0
2714 def analyse_as_type(self, env):
2715 module_scope = self.obj.analyse_as_module(env)
2716 if module_scope:
2717 return module_scope.lookup_type(self.attribute)
2718 return None
2720 def analyse_as_extension_type(self, env):
2721 # Try to interpret this as a reference to an extension type
2722 # in a cimported module. Returns the extension type, or None.
2723 module_scope = self.obj.analyse_as_module(env)
2724 if module_scope:
2725 entry = module_scope.lookup_here(self.attribute)
2726 if entry and entry.is_type and entry.type.is_extension_type:
2727 return entry.type
2728 return None
2730 def analyse_as_module(self, env):
2731 # Try to interpret this as a reference to a cimported module
2732 # in another cimported module. Returns the module scope, or None.
2733 module_scope = self.obj.analyse_as_module(env)
2734 if module_scope:
2735 entry = module_scope.lookup_here(self.attribute)
2736 if entry and entry.as_module:
2737 return entry.as_module
2738 return None
2740 def mutate_into_name_node(self, env, entry, target):
2741 # Mutate this node into a NameNode and complete the
2742 # analyse_types phase.
2743 self.__class__ = NameNode
2744 self.name = self.attribute
2745 self.entry = entry
2746 del self.obj
2747 del self.attribute
2748 if target:
2749 NameNode.analyse_target_types(self, env)
2750 else:
2751 NameNode.analyse_rvalue_entry(self, env)
2753 def analyse_as_ordinary_attribute(self, env, target):
2754 self.obj.analyse_types(env)
2755 self.analyse_attribute(env)
2756 if self.entry and self.entry.is_cmethod and not self.is_called:
2757 # error(self.pos, "C method can only be called")
2758 pass
2759 ## Reference to C array turns into pointer to first element.
2760 #while self.type.is_array:
2761 # self.type = self.type.element_ptr_type()
2762 if self.is_py_attr:
2763 if not target:
2764 self.is_temp = 1
2765 self.result_ctype = py_object_type
2767 def analyse_attribute(self, env):
2768 # Look up attribute and set self.type and self.member.
2769 self.is_py_attr = 0
2770 self.member = self.attribute
2771 if self.obj.type.is_string:
2772 self.obj = self.obj.coerce_to_pyobject(env)
2773 obj_type = self.obj.type
2774 if obj_type.is_ptr or obj_type.is_array:
2775 obj_type = obj_type.base_type
2776 self.op = "->"
2777 elif obj_type.is_extension_type:
2778 self.op = "->"
2779 else:
2780 self.op = "."
2781 if obj_type.has_attributes:
2782 entry = None
2783 if obj_type.attributes_known():
2784 entry = obj_type.scope.lookup_here(self.attribute)
2785 if entry and entry.is_member:
2786 entry = None
2787 else:
2788 error(self.pos,
2789 "Cannot select attribute of incomplete type '%s'"
2790 % obj_type)
2791 self.type = PyrexTypes.error_type
2792 return
2793 self.entry = entry
2794 if entry:
2795 if obj_type.is_extension_type and entry.name == "__weakref__":
2796 error(self.pos, "Illegal use of special attribute __weakref__")
2797 # methods need the normal attribute lookup
2798 # because they do not have struct entries
2799 if entry.is_variable or entry.is_cmethod:
2800 self.type = entry.type
2801 self.member = entry.cname
2802 return
2803 else:
2804 # If it's not a variable or C method, it must be a Python
2805 # method of an extension type, so we treat it like a Python
2806 # attribute.
2807 pass
2808 # If we get here, the base object is not a struct/union/extension
2809 # type, or it is an extension type and the attribute is either not
2810 # declared or is declared as a Python method. Treat it as a Python
2811 # attribute reference.
2812 self.analyse_as_python_attribute(env)
2814 def analyse_as_python_attribute(self, env):
2815 obj_type = self.obj.type
2816 self.member = self.attribute
2817 if obj_type.is_pyobject:
2818 self.type = py_object_type
2819 self.is_py_attr = 1
2820 self.interned_attr_cname = env.intern_identifier(self.attribute)
2821 self.gil_check(env)
2822 else:
2823 if not obj_type.is_error:
2824 error(self.pos,
2825 "Object of type '%s' has no attribute '%s'" %
2826 (obj_type, self.attribute))
2828 gil_message = "Accessing Python attribute"
2830 def is_simple(self):
2831 if self.obj:
2832 return self.result_in_temp() or self.obj.is_simple()
2833 else:
2834 return NameNode.is_simple(self)
2836 def is_lvalue(self):
2837 if self.obj:
2838 return 1
2839 else:
2840 return NameNode.is_lvalue(self)
2842 def is_ephemeral(self):
2843 if self.obj:
2844 return self.obj.is_ephemeral()
2845 else:
2846 return NameNode.is_ephemeral(self)
2848 def calculate_result_code(self):
2849 #print "AttributeNode.calculate_result_code:", self.member ###
2850 #print "...obj node =", self.obj, "code", self.obj.result() ###
2851 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2852 obj = self.obj
2853 obj_code = obj.result_as(obj.type)
2854 #print "...obj_code =", obj_code ###
2855 if self.entry and self.entry.is_cmethod:
2856 if obj.type.is_extension_type:
2857 return "((struct %s *)%s%s%s)->%s" % (
2858 obj.type.vtabstruct_cname, obj_code, self.op,
2859 obj.type.vtabslot_cname, self.member)
2860 else:
2861 return self.member
2862 else:
2863 return "%s%s%s" % (obj_code, self.op, self.member)
2865 def generate_result_code(self, code):
2866 if self.is_py_attr:
2867 code.putln(
2868 '%s = PyObject_GetAttr(%s, %s); %s' % (
2869 self.result(),
2870 self.obj.py_result(),
2871 self.interned_attr_cname,
2872 code.error_goto_if_null(self.result(), self.pos)))
2873 code.put_gotref(self.py_result())
2874 else:
2875 # result_code contains what is needed, but we may need to insert
2876 # a check and raise an exception
2877 if (self.obj.type.is_extension_type
2878 and self.needs_none_check
2879 and code.globalstate.directives['nonecheck']):
2880 self.put_nonecheck(code)
2882 def generate_assignment_code(self, rhs, code):
2883 self.obj.generate_evaluation_code(code)
2884 if self.is_py_attr:
2885 code.put_error_if_neg(self.pos,
2886 'PyObject_SetAttr(%s, %s, %s)' % (
2887 self.obj.py_result(),
2888 self.interned_attr_cname,
2889 rhs.py_result()))
2890 rhs.generate_disposal_code(code)
2891 rhs.free_temps(code)
2892 else:
2893 if (self.obj.type.is_extension_type
2894 and self.needs_none_check
2895 and code.globalstate.directives['nonecheck']):
2896 self.put_nonecheck(code)
2898 select_code = self.result()
2899 if self.type.is_pyobject:
2900 rhs.make_owned_reference(code)
2901 code.put_giveref(rhs.py_result())
2902 code.put_gotref(select_code)
2903 code.put_decref(select_code, self.ctype())
2904 code.putln(
2905 "%s = %s;" % (
2906 select_code,
2907 rhs.result_as(self.ctype())))
2908 #rhs.result()))
2909 rhs.generate_post_assignment_code(code)
2910 rhs.free_temps(code)
2911 self.obj.generate_disposal_code(code)
2912 self.obj.free_temps(code)
2914 def generate_deletion_code(self, code):
2915 self.obj.generate_evaluation_code(code)
2916 if self.is_py_attr:
2917 code.put_error_if_neg(self.pos,
2918 'PyObject_DelAttr(%s, %s)' % (
2919 self.obj.py_result(),
2920 self.interned_attr_cname))
2921 else:
2922 error(self.pos, "Cannot delete C attribute of extension type")
2923 self.obj.generate_disposal_code(code)
2924 self.obj.free_temps(code)
2926 def annotate(self, code):
2927 if self.is_py_attr:
2928 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2929 else:
2930 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2932 def put_nonecheck(self, code):
2933 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2934 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2935 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2936 code.putln(code.error_goto(self.pos))
2937 code.putln("}")
2940 #-------------------------------------------------------------------
2942 # Constructor nodes
2944 #-------------------------------------------------------------------
2946 class SequenceNode(NewTempExprNode):
2947 # Base class for list and tuple constructor nodes.
2948 # Contains common code for performing sequence unpacking.
2950 # args [ExprNode]
2951 # iterator ExprNode
2952 # unpacked_items [ExprNode] or None
2953 # coerced_unpacked_items [ExprNode] or None
2955 subexprs = ['args']
2957 is_sequence_constructor = 1
2958 unpacked_items = None
2960 def compile_time_value_list(self, denv):
2961 return [arg.compile_time_value(denv) for arg in self.args]
2963 def analyse_target_declaration(self, env):
2964 for arg in self.args:
2965 arg.analyse_target_declaration(env)
2967 def analyse_types(self, env, skip_children=False):
2968 for i in range(len(self.args)):
2969 arg = self.args[i]
2970 if not skip_children: arg.analyse_types(env)
2971 self.args[i] = arg.coerce_to_pyobject(env)
2972 self.type = py_object_type
2973 self.gil_check(env)
2974 self.is_temp = 1
2976 def analyse_target_types(self, env):
2977 self.iterator = PyTempNode(self.pos, env)
2978 self.unpacked_items = []
2979 self.coerced_unpacked_items = []
2980 for arg in self.args:
2981 arg.analyse_target_types(env)
2982 unpacked_item = PyTempNode(self.pos, env)
2983 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2984 self.unpacked_items.append(unpacked_item)
2985 self.coerced_unpacked_items.append(coerced_unpacked_item)
2986 self.type = py_object_type
2987 env.use_utility_code(unpacking_utility_code)
2989 def allocate_target_temps(self, env, rhs):
2990 self.iterator.allocate_temps(env)
2991 for arg, node in zip(self.args, self.coerced_unpacked_items):
2992 node.allocate_temps(env)
2993 arg.allocate_target_temps(env, None)
2994 #arg.release_target_temp(env)
2995 #node.release_temp(env)
2996 if rhs:
2997 rhs.release_temp(env)
2998 self.iterator.release_temp(env)
2999 for node in self.coerced_unpacked_items:
3000 node.release_temp(env)
3002 # def release_target_temp(self, env):
3003 # #for arg in self.args:
3004 # # arg.release_target_temp(env)
3005 # #for node in self.coerced_unpacked_items:
3006 # # node.release_temp(env)
3007 # self.iterator.release_temp(env)
3009 def generate_result_code(self, code):
3010 self.generate_operation_code(code)
3012 def generate_assignment_code(self, rhs, code):
3013 # Need to work around the fact that generate_evaluation_code
3014 # allocates the temps in a rather hacky way -- the assignment
3015 # is evaluated twice, within each if-block.
3017 if rhs.type is tuple_type:
3018 tuple_check = "likely(%s != Py_None)"
3019 else:
3020 tuple_check = "PyTuple_CheckExact(%s)"
3021 code.putln(
3022 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3023 tuple_check % rhs.py_result(),
3024 rhs.py_result(),
3025 len(self.args)))
3026 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3027 for i in range(len(self.args)):
3028 item = self.unpacked_items[i]
3029 code.put(
3030 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3031 item.result(),
3032 i))
3033 code.put_incref(item.result(), item.ctype())
3034 value_node = self.coerced_unpacked_items[i]
3035 value_node.generate_evaluation_code(code)
3036 rhs.generate_disposal_code(code)
3038 for i in range(len(self.args)):
3039 self.args[i].generate_assignment_code(
3040 self.coerced_unpacked_items[i], code)
3042 code.putln("} else {")
3044 if rhs.type is tuple_type:
3045 code.globalstate.use_utility_code(raise_none_iter_error_utility_code)
3046 code.putln("if (%s == Py_None) {" %
3047 rhs.py_result())
3048 code.putln("__Pyx_RaiseNoneNotIterableError();")
3049 code.putln("} else if (PyTuple_GET_SIZE(%s) < %s) {" % (
3050 rhs.py_result(), len(self.args)))
3051 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3052 code.putln("__Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(%s));" %
3053 rhs.py_result());
3054 code.putln("} else {")
3055 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3056 code.putln("__Pyx_RaiseTooManyValuesError();");
3057 code.putln("}")
3058 code.putln(
3059 code.error_goto(self.pos))
3060 else:
3061 code.putln(
3062 "%s = PyObject_GetIter(%s); %s" % (
3063 self.iterator.result(),
3064 rhs.py_result(),
3065 code.error_goto_if_null(self.iterator.result(), self.pos)))
3066 code.put_gotref(self.iterator.py_result())
3067 rhs.generate_disposal_code(code)
3068 for i in range(len(self.args)):
3069 item = self.unpacked_items[i]
3070 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3071 self.iterator.py_result(), i)
3072 code.putln(
3073 "%s = %s; %s" % (
3074 item.result(),
3075 typecast(item.ctype(), py_object_type, unpack_code),
3076 code.error_goto_if_null(item.result(), self.pos)))
3077 code.put_gotref(item.py_result())
3078 value_node = self.coerced_unpacked_items[i]
3079 value_node.generate_evaluation_code(code)
3080 code.put_error_if_neg(self.pos,
3081 "__Pyx_EndUnpack(%s)" % (
3082 self.iterator.py_result()))
3083 if debug_disposal_code:
3084 print("UnpackNode.generate_assignment_code:")
3085 print("...generating disposal code for %s" % self.iterator)
3086 self.iterator.generate_disposal_code(code)
3087 self.iterator.free_temps(code)
3089 for i in range(len(self.args)):
3090 self.args[i].generate_assignment_code(
3091 self.coerced_unpacked_items[i], code)
3093 code.putln("}")
3094 rhs.free_temps(code)
3096 def annotate(self, code):
3097 for arg in self.args:
3098 arg.annotate(code)
3099 if self.unpacked_items:
3100 for arg in self.unpacked_items:
3101 arg.annotate(code)
3102 for arg in self.coerced_unpacked_items:
3103 arg.annotate(code)
3106 class TupleNode(SequenceNode):
3107 # Tuple constructor.
3109 gil_message = "Constructing Python tuple"
3111 def analyse_types(self, env, skip_children=False):
3112 if len(self.args) == 0:
3113 self.is_temp = 0
3114 self.is_literal = 1
3115 else:
3116 SequenceNode.analyse_types(self, env, skip_children)
3117 self.type = tuple_type
3119 def calculate_result_code(self):
3120 if len(self.args) > 0:
3121 error(self.pos, "Positive length tuples must be constructed.")
3122 else:
3123 return Naming.empty_tuple
3125 def calculate_constant_result(self):
3126 self.constant_result = tuple([
3127 arg.constant_result for arg in self.args])
3129 def compile_time_value(self, denv):
3130 values = self.compile_time_value_list(denv)
3131 try:
3132 return tuple(values)
3133 except Exception, e:
3134 self.compile_time_value_error(e)
3136 def generate_operation_code(self, code):
3137 if len(self.args) == 0:
3138 # result_code is Naming.empty_tuple
3139 return
3140 code.putln(
3141 "%s = PyTuple_New(%s); %s" % (
3142 self.result(),
3143 len(self.args),
3144 code.error_goto_if_null(self.result(), self.pos)))
3145 code.put_gotref(self.py_result())
3146 for i in range(len(self.args)):
3147 arg = self.args[i]
3148 if not arg.result_in_temp():
3149 code.put_incref(arg.result(), arg.ctype())
3150 code.putln(
3151 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3152 self.result(),
3153 i,
3154 arg.py_result()))
3155 code.put_giveref(arg.py_result())
3157 def generate_subexpr_disposal_code(self, code):
3158 # We call generate_post_assignment_code here instead
3159 # of generate_disposal_code, because values were stored
3160 # in the tuple using a reference-stealing operation.
3161 for arg in self.args:
3162 arg.generate_post_assignment_code(code)
3163 # Should NOT call free_temps -- this is invoked by the default
3164 # generate_evaluation_code which will do that.
3167 class ListNode(SequenceNode):
3168 # List constructor.
3170 # obj_conversion_errors [PyrexError] used internally
3171 # orignial_args [ExprNode] used internally
3173 gil_message = "Constructing Python list"
3175 def analyse_expressions(self, env):
3176 SequenceNode.analyse_expressions(self, env)
3177 self.coerce_to_pyobject(env)
3179 def analyse_types(self, env):
3180 hold_errors()
3181 self.original_args = list(self.args)
3182 SequenceNode.analyse_types(self, env)
3183 self.type = list_type
3184 self.obj_conversion_errors = held_errors()
3185 release_errors(ignore=True)
3187 def coerce_to(self, dst_type, env):
3188 if dst_type.is_pyobject:
3189 for err in self.obj_conversion_errors:
3190 report_error(err)
3191 self.obj_conversion_errors = []
3192 if not self.type.subtype_of(dst_type):
3193 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3194 elif dst_type.is_ptr:
3195 base_type = dst_type.base_type
3196 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3197 for i in range(len(self.original_args)):
3198 arg = self.args[i]
3199 if isinstance(arg, CoerceToPyTypeNode):
3200 arg = arg.arg
3201 self.args[i] = arg.coerce_to(base_type, env)
3202 elif dst_type.is_struct:
3203 if len(self.args) > len(dst_type.scope.var_entries):
3204 error(self.pos, "Too may members for '%s'" % dst_type)
3205 else:
3206 if len(self.args) < len(dst_type.scope.var_entries):
3207 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3208 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3209 if isinstance(arg, CoerceToPyTypeNode):
3210 arg = arg.arg
3211 self.args[i] = arg.coerce_to(member.type, env)
3212 self.type = dst_type
3213 else:
3214 self.type = error_type
3215 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3216 return self
3218 def release_temp(self, env):
3219 if self.type.is_array:
3220 # To be valid C++, we must allocate the memory on the stack
3221 # manually and be sure not to reuse it for something else.
3222 pass
3223 else:
3224 SequenceNode.release_temp(self, env)
3226 def calculate_constant_result(self):
3227 self.constant_result = [
3228 arg.constant_result for arg in self.args]
3230 def compile_time_value(self, denv):
3231 return self.compile_time_value_list(denv)
3233 def generate_operation_code(self, code):
3234 if self.type.is_pyobject:
3235 for err in self.obj_conversion_errors:
3236 report_error(err)
3237 code.putln("%s = PyList_New(%s); %s" %
3238 (self.result(),
3239 len(self.args),
3240 code.error_goto_if_null(self.result(), self.pos)))
3241 code.put_gotref(self.py_result())
3242 for i in range(len(self.args)):
3243 arg = self.args[i]
3244 #if not arg.is_temp:
3245 if not arg.result_in_temp():
3246 code.put_incref(arg.result(), arg.ctype())
3247 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3248 (self.result(),
3249 i,
3250 arg.py_result()))
3251 code.put_giveref(arg.py_result())
3252 elif self.type.is_array:
3253 for i, arg in enumerate(self.args):
3254 code.putln("%s[%s] = %s;" % (
3255 self.result(),
3256 i,
3257 arg.result()))
3258 elif self.type.is_struct:
3259 for arg, member in zip(self.args, self.type.scope.var_entries):
3260 code.putln("%s.%s = %s;" % (
3261 self.result(),
3262 member.cname,
3263 arg.result()))
3264 else:
3265 raise InternalError("List type never specified")
3267 def generate_subexpr_disposal_code(self, code):
3268 # We call generate_post_assignment_code here instead
3269 # of generate_disposal_code, because values were stored
3270 # in the list using a reference-stealing operation.
3271 for arg in self.args:
3272 arg.generate_post_assignment_code(code)
3273 # Should NOT call free_temps -- this is invoked by the default
3274 # generate_evaluation_code which will do that.
3277 class ComprehensionNode(NewTempExprNode):
3278 subexprs = ["target"]
3279 child_attrs = ["loop", "append"]
3281 def analyse_types(self, env):
3282 self.target.analyse_expressions(env)
3283 self.type = self.target.type
3284 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3285 self.loop.analyse_declarations(env)
3287 def allocate_temps(self, env, result = None):
3288 if debug_temp_alloc:
3289 print("%s Allocating temps" % self)
3290 self.allocate_temp(env, result)
3291 # call loop.analyse_expressions() now to make sure temps get
3292 # allocated at the right time
3293 self.loop.analyse_expressions(env)
3295 def calculate_result_code(self):
3296 return self.target.result()
3298 def generate_result_code(self, code):
3299 self.generate_operation_code(code)
3301 def generate_operation_code(self, code):
3302 self.loop.generate_execution_code(code)
3304 def annotate(self, code):
3305 self.loop.annotate(code)
3308 class ComprehensionAppendNode(NewTempExprNode):
3309 # Need to be careful to avoid infinite recursion:
3310 # target must not be in child_attrs/subexprs
3311 subexprs = ['expr']
3313 def analyse_types(self, env):
3314 self.expr.analyse_types(env)
3315 if not self.expr.type.is_pyobject:
3316 self.expr = self.expr.coerce_to_pyobject(env)
3317 self.type = PyrexTypes.c_int_type
3318 self.is_temp = 1
3320 def generate_result_code(self, code):
3321 if self.target.type is list_type:
3322 function = "PyList_Append"
3323 elif self.target.type is set_type:
3324 function = "PySet_Add"
3325 else:
3326 raise InternalError(
3327 "Invalid type for comprehension node: %s" % self.target.type)
3329 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3330 (self.result(),
3331 function,
3332 self.target.result(),
3333 self.expr.result(),
3334 code.error_goto_if(self.result(), self.pos)))
3336 class DictComprehensionAppendNode(ComprehensionAppendNode):
3337 subexprs = ['key_expr', 'value_expr']
3339 def analyse_types(self, env):
3340 self.key_expr.analyse_types(env)
3341 if not self.key_expr.type.is_pyobject:
3342 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3343 self.value_expr.analyse_types(env)
3344 if not self.value_expr.type.is_pyobject:
3345 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3346 self.type = PyrexTypes.c_int_type
3347 self.is_temp = 1
3349 def generate_result_code(self, code):
3350 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3351 (self.result(),
3352 self.target.result(),
3353 self.key_expr.result(),
3354 self.value_expr.result(),
3355 code.error_goto_if(self.result(), self.pos)))
3358 class SetNode(NewTempExprNode):
3359 # Set constructor.
3361 subexprs = ['args']
3363 gil_message = "Constructing Python set"
3365 def analyse_types(self, env):
3366 for i in range(len(self.args)):
3367 arg = self.args[i]
3368 arg.analyse_types(env)
3369 self.args[i] = arg.coerce_to_pyobject(env)
3370 self.type = set_type
3371 self.gil_check(env)
3372 self.is_temp = 1
3374 def calculate_constant_result(self):
3375 self.constant_result = set([
3376 arg.constant_result for arg in self.args])
3378 def compile_time_value(self, denv):
3379 values = [arg.compile_time_value(denv) for arg in self.args]
3380 try:
3381 return set(values)
3382 except Exception, e:
3383 self.compile_time_value_error(e)
3385 def generate_evaluation_code(self, code):
3386 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3387 self.allocate_temp_result(code)
3388 code.putln(
3389 "%s = PySet_New(0); %s" % (
3390 self.result(),
3391 code.error_goto_if_null(self.result(), self.pos)))
3392 code.put_gotref(self.py_result())
3393 for arg in self.args:
3394 arg.generate_evaluation_code(code)
3395 code.putln(
3396 code.error_goto_if_neg(
3397 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3398 self.pos))
3399 arg.generate_disposal_code(code)
3400 arg.free_temps(code)
3403 class DictNode(ExprNode):
3404 # Dictionary constructor.
3406 # key_value_pairs [DictItemNode]
3408 # obj_conversion_errors [PyrexError] used internally
3410 subexprs = ['key_value_pairs']
3412 def calculate_constant_result(self):
3413 self.constant_result = dict([
3414 item.constant_result for item in self.key_value_pairs])
3416 def compile_time_value(self, denv):
3417 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3418 for item in self.key_value_pairs]
3419 try:
3420 return dict(pairs)
3421 except Exception, e:
3422 self.compile_time_value_error(e)
3424 def analyse_types(self, env):
3425 hold_errors()
3426 self.type = dict_type
3427 for item in self.key_value_pairs:
3428 item.analyse_types(env)
3429 self.gil_check(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 def calculate_constant_result(self):
3520 self.constant_result = (
3521 self.key.constant_result, self.value.constant_result)
3523 def analyse_types(self, env):
3524 self.key.analyse_types(env)
3525 self.value.analyse_types(env)
3526 self.key = self.key.coerce_to_pyobject(env)
3527 self.value = self.value.coerce_to_pyobject(env)
3529 def generate_evaluation_code(self, code):
3530 self.key.generate_evaluation_code(code)
3531 self.value.generate_evaluation_code(code)
3533 def generate_disposal_code(self, code):
3534 self.key.generate_disposal_code(code)
3535 self.value.generate_disposal_code(code)
3537 def free_temps(self, code):
3538 self.key.free_temps(code)
3539 self.value.free_temps(code)
3541 def __iter__(self):
3542 return iter([self.key, self.value])
3545 class ClassNode(ExprNode):
3546 # Helper class used in the implementation of Python
3547 # class definitions. Constructs a class object given
3548 # a name, tuple of bases and class dictionary.
3550 # name EncodedString Name of the class
3551 # cname string Class name as a Python string
3552 # bases ExprNode Base class tuple
3553 # dict ExprNode Class dict (not owned by this node)
3554 # doc ExprNode or None Doc string
3555 # module_name string Name of defining module
3557 subexprs = ['bases', 'doc']
3559 def analyse_types(self, env):
3560 self.cname = env.intern_identifier(self.name)
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.gil_check(env)
3568 self.is_temp = 1
3569 env.use_utility_code(create_class_utility_code);
3571 gil_message = "Constructing Python class"
3573 def generate_result_code(self, code):
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 self.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.gil_check(env)
3604 self.is_temp = 1
3606 gil_message = "Constructing an unbound method"
3608 def generate_result_code(self, code):
3609 code.putln(
3610 "%s = PyMethod_New(%s, 0, %s); %s" % (
3611 self.result(),
3612 self.function.py_result(),
3613 self.class_cname,
3614 code.error_goto_if_null(self.result(), self.pos)))
3615 code.put_gotref(self.py_result())
3617 class PyCFunctionNode(AtomicNewTempExprNode):
3618 # Helper class used in the implementation of Python
3619 # class definitions. Constructs a PyCFunction object
3620 # from a PyMethodDef struct.
3622 # pymethdef_cname string PyMethodDef structure
3624 def analyse_types(self, env):
3625 self.type = py_object_type
3626 self.gil_check(env)
3627 self.is_temp = 1
3629 gil_message = "Constructing Python function"
3631 def generate_result_code(self, code):
3632 code.putln(
3633 "%s = PyCFunction_New(&%s, 0); %s" % (
3634 self.result(),
3635 self.pymethdef_cname,
3636 code.error_goto_if_null(self.result(), self.pos)))
3637 code.put_gotref(self.py_result())
3639 #-------------------------------------------------------------------
3641 # Unary operator nodes
3643 #-------------------------------------------------------------------
3645 compile_time_unary_operators = {
3646 'not': operator.not_,
3647 '~': operator.inv,
3648 '-': operator.neg,
3649 '+': operator.pos,
3652 class UnopNode(ExprNode):
3653 # operator string
3654 # operand ExprNode
3656 # Processing during analyse_expressions phase:
3658 # analyse_c_operation
3659 # Called when the operand is not a pyobject.
3660 # - Check operand type and coerce if needed.
3661 # - Determine result type and result code fragment.
3662 # - Allocate temporary for result if needed.
3664 subexprs = ['operand']
3666 def calculate_constant_result(self):
3667 func = compile_time_unary_operators[self.operator]
3668 self.constant_result = func(self.operand.constant_result)
3670 def compile_time_value(self, denv):
3671 func = compile_time_unary_operators.get(self.operator)
3672 if not func:
3673 error(self.pos,
3674 "Unary '%s' not supported in compile-time expression"
3675 % self.operator)
3676 operand = self.operand.compile_time_value(denv)
3677 try:
3678 return func(operand)
3679 except Exception, e:
3680 self.compile_time_value_error(e)
3682 def analyse_types(self, env):
3683 self.operand.analyse_types(env)
3684 if self.is_py_operation():
3685 self.coerce_operand_to_pyobject(env)
3686 self.type = py_object_type
3687 self.gil_check(env)
3688 self.is_temp = 1
3689 else:
3690 self.analyse_c_operation(env)
3692 def check_const(self):
3693 self.operand.check_const()
3695 def is_py_operation(self):
3696 return self.operand.type.is_pyobject
3698 def coerce_operand_to_pyobject(self, env):
3699 self.operand = self.operand.coerce_to_pyobject(env)
3701 def generate_result_code(self, code):
3702 if self.operand.type.is_pyobject:
3703 self.generate_py_operation_code(code)
3704 else:
3705 if self.is_temp:
3706 self.generate_c_operation_code(code)
3708 def generate_py_operation_code(self, code):
3709 function = self.py_operation_function()
3710 code.putln(
3711 "%s = %s(%s); %s" % (
3712 self.result(),
3713 function,
3714 self.operand.py_result(),
3715 code.error_goto_if_null(self.result(), self.pos)))
3716 code.put_gotref(self.py_result())
3718 def type_error(self):
3719 if not self.operand.type.is_error:
3720 error(self.pos, "Invalid operand type for '%s' (%s)" %
3721 (self.operator, self.operand.type))
3722 self.type = PyrexTypes.error_type
3725 class NotNode(ExprNode):
3726 # 'not' operator
3728 # operand ExprNode
3730 def calculate_constant_result(self):
3731 self.constant_result = not self.operand.constant_result
3733 def compile_time_value(self, denv):
3734 operand = self.operand.compile_time_value(denv)
3735 try:
3736 return not operand
3737 except Exception, e:
3738 self.compile_time_value_error(e)
3740 subexprs = ['operand']
3742 def analyse_types(self, env):
3743 self.operand.analyse_types(env)
3744 self.operand = self.operand.coerce_to_boolean(env)
3745 self.type = PyrexTypes.c_bint_type
3747 def calculate_result_code(self):
3748 return "(!%s)" % self.operand.result()
3750 def generate_result_code(self, code):
3751 pass
3754 class UnaryPlusNode(UnopNode):
3755 # unary '+' operator
3757 operator = '+'
3759 def analyse_c_operation(self, env):
3760 self.type = self.operand.type
3762 def py_operation_function(self):
3763 return "PyNumber_Positive"
3765 def calculate_result_code(self):
3766 return self.operand.result()
3769 class UnaryMinusNode(UnopNode):
3770 # unary '-' operator
3772 operator = '-'
3774 def analyse_c_operation(self, env):
3775 if self.operand.type.is_numeric:
3776 self.type = self.operand.type
3777 else:
3778 self.type_error()
3780 def py_operation_function(self):
3781 return "PyNumber_Negative"
3783 def calculate_result_code(self):
3784 return "(-%s)" % self.operand.result()
3787 class TildeNode(UnopNode):
3788 # unary '~' operator
3790 def analyse_c_operation(self, env):
3791 if self.operand.type.is_int:
3792 self.type = self.operand.type
3793 else:
3794 self.type_error()
3796 def py_operation_function(self):
3797 return "PyNumber_Invert"
3799 def calculate_result_code(self):
3800 return "(~%s)" % self.operand.result()
3803 class AmpersandNode(ExprNode):
3804 # The C address-of operator.
3806 # operand ExprNode
3808 subexprs = ['operand']
3810 def analyse_types(self, env):
3811 self.operand.analyse_types(env)
3812 argtype = self.operand.type
3813 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3814 self.error("Taking address of non-lvalue")
3815 return
3816 if argtype.is_pyobject:
3817 self.error("Cannot take address of Python variable")
3818 return
3819 self.type = PyrexTypes.c_ptr_type(argtype)
3821 def check_const(self):
3822 self.operand.check_const_addr()
3824 def error(self, mess):
3825 error(self.pos, mess)
3826 self.type = PyrexTypes.error_type
3827 self.result_code = "<error>"
3829 def calculate_result_code(self):
3830 return "(&%s)" % self.operand.result()
3832 def generate_result_code(self, code):
3833 pass
3836 unop_node_classes = {
3837 "+": UnaryPlusNode,
3838 "-": UnaryMinusNode,
3839 "~": TildeNode,
3842 def unop_node(pos, operator, operand):
3843 # Construct unnop node of appropriate class for
3844 # given operator.
3845 if isinstance(operand, IntNode) and operator == '-':
3846 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3847 elif isinstance(operand, UnopNode) and operand.operator == operator:
3848 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3849 return unop_node_classes[operator](pos,
3850 operator = operator,
3851 operand = operand)
3854 class TypecastNode(NewTempExprNode):
3855 # C type cast
3857 # operand ExprNode
3858 # base_type CBaseTypeNode
3859 # declarator CDeclaratorNode
3861 # If used from a transform, one can if wanted specify the attribute
3862 # "type" directly and leave base_type and declarator to None
3864 subexprs = ['operand']
3865 base_type = declarator = type = None
3867 def analyse_types(self, env):
3868 if self.type is None:
3869 base_type = self.base_type.analyse(env)
3870 _, self.type = self.declarator.analyse(base_type, env)
3871 if self.type.is_cfunction:
3872 error(self.pos,
3873 "Cannot cast to a function type")
3874 self.type = PyrexTypes.error_type
3875 self.operand.analyse_types(env)
3876 to_py = self.type.is_pyobject
3877 from_py = self.operand.type.is_pyobject
3878 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3879 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3880 if to_py and not from_py:
3881 if (self.operand.type.to_py_function and
3882 self.operand.type.create_convert_utility_code(env)):
3883 self.result_ctype = py_object_type
3884 self.operand = self.operand.coerce_to_pyobject(env)
3885 else:
3886 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3887 self.operand = self.operand.coerce_to_simple(env)
3888 elif from_py and not to_py:
3889 if self.type.from_py_function:
3890 self.operand = self.operand.coerce_to(self.type, env)
3891 else:
3892 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3893 elif from_py and to_py:
3894 if self.typecheck and self.type.is_extension_type:
3895 self.operand = PyTypeTestNode(self.operand, self.type, env)
3897 def check_const(self):
3898 self.operand.check_const()
3900 def calculate_constant_result(self):
3901 self.constant_result = self.operand.constant_result
3903 def calculate_result_code(self):
3904 opnd = self.operand
3905 return self.type.cast_code(opnd.result())
3907 def result_as(self, type):
3908 if self.type.is_pyobject and not self.is_temp:
3909 # Optimise away some unnecessary casting
3910 return self.operand.result_as(type)
3911 else:
3912 return ExprNode.result_as(self, type)
3914 def generate_result_code(self, code):
3915 if self.is_temp:
3916 code.putln(
3917 "%s = (PyObject *)%s;" % (
3918 self.result(),
3919 self.operand.result()))
3920 code.put_incref(self.result(), self.ctype())
3923 class SizeofNode(ExprNode):
3924 # Abstract base class for sizeof(x) expression nodes.
3926 type = PyrexTypes.c_size_t_type
3928 def check_const(self):
3929 pass
3931 def generate_result_code(self, code):
3932 pass
3935 class SizeofTypeNode(SizeofNode):
3936 # C sizeof function applied to a type
3938 # base_type CBaseTypeNode
3939 # declarator CDeclaratorNode
3941 subexprs = []
3942 arg_type = None
3944 def analyse_types(self, env):
3945 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3946 # this could be better handled by more uniformly treating types as runtime-available objects
3947 if 0 and self.base_type.module_path:
3948 path = self.base_type.module_path
3949 obj = env.lookup(path[0])
3950 if obj.as_module is None:
3951 operand = NameNode(pos=self.pos, name=path[0])
3952 for attr in path[1:]:
3953 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3954 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3955 self.operand = operand
3956 self.__class__ = SizeofVarNode
3957 self.analyse_types(env)
3958 return
3959 if self.arg_type is None:
3960 base_type = self.base_type.analyse(env)
3961 _, arg_type = self.declarator.analyse(base_type, env)
3962 self.arg_type = arg_type
3963 self.check_type()
3965 def check_type(self):
3966 arg_type = self.arg_type
3967 if arg_type.is_pyobject and not arg_type.is_extension_type:
3968 error(self.pos, "Cannot take sizeof Python object")
3969 elif arg_type.is_void:
3970 error(self.pos, "Cannot take sizeof void")
3971 elif not arg_type.is_complete():
3972 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3974 def calculate_result_code(self):
3975 if self.arg_type.is_extension_type:
3976 # the size of the pointer is boring
3977 # we want the size of the actual struct
3978 arg_code = self.arg_type.declaration_code("", deref=1)
3979 else:
3980 arg_code = self.arg_type.declaration_code("")
3981 return "(sizeof(%s))" % arg_code
3984 class SizeofVarNode(SizeofNode):
3985 # C sizeof function applied to a variable
3987 # operand ExprNode
3989 subexprs = ['operand']
3991 def analyse_types(self, env):
3992 # We may actually be looking at a type rather than a variable...
3993 # If we are, traditional analysis would fail...
3994 operand_as_type = self.operand.analyse_as_type(env)
3995 if operand_as_type:
3996 self.arg_type = operand_as_type
3997 self.__class__ = SizeofTypeNode
3998 self.check_type()
3999 else:
4000 self.operand.analyse_types(env)
4002 def calculate_result_code(self):
4003 return "(sizeof(%s))" % self.operand.result()
4005 def generate_result_code(self, code):
4006 pass
4009 #-------------------------------------------------------------------
4011 # Binary operator nodes
4013 #-------------------------------------------------------------------
4015 def _not_in(x, seq):
4016 return x not in seq
4018 compile_time_binary_operators = {
4019 '<': operator.lt,
4020 '<=': operator.le,
4021 '==': operator.eq,
4022 '!=': operator.ne,
4023 '>=': operator.ge,
4024 '>': operator.gt,
4025 'is': operator.is_,
4026 'is_not': operator.is_not,
4027 '+': operator.add,
4028 '&': operator.and_,
4029 '/': operator.div,
4030 '//': operator.floordiv,
4031 '<<': operator.lshift,
4032 '%': operator.mod,
4033 '*': operator.mul,
4034 '|': operator.or_,
4035 '**': operator.pow,
4036 '>>': operator.rshift,
4037 '-': operator.sub,
4038 #'/': operator.truediv,
4039 '^': operator.xor,
4040 'in': operator.contains,
4041 'not_in': _not_in,
4044 def get_compile_time_binop(node):
4045 func = compile_time_binary_operators.get(node.operator)
4046 if not func:
4047 error(node.pos,
4048 "Binary '%s' not supported in compile-time expression"
4049 % node.operator)
4050 return func
4052 class BinopNode(NewTempExprNode):
4053 # operator string
4054 # operand1 ExprNode
4055 # operand2 ExprNode
4057 # Processing during analyse_expressions phase:
4059 # analyse_c_operation
4060 # Called when neither operand is a pyobject.
4061 # - Check operand types and coerce if needed.
4062 # - Determine result type and result code fragment.
4063 # - Allocate temporary for result if needed.
4065 subexprs = ['operand1', 'operand2']
4067 def calculate_constant_result(self):
4068 func = compile_time_binary_operators[self.operator]
4069 self.constant_result = func(
4070 self.operand1.constant_result,
4071 self.operand2.constant_result)
4073 def compile_time_value(self, denv):
4074 func = get_compile_time_binop(self)
4075 operand1 = self.operand1.compile_time_value(denv)
4076 operand2 = self.operand2.compile_time_value(denv)
4077 try:
4078 return func(operand1, operand2)
4079 except Exception, e:
4080 self.compile_time_value_error(e)
4082 def analyse_types(self, env):
4083 self.operand1.analyse_types(env)
4084 self.operand2.analyse_types(env)
4085 if self.is_py_operation():
4086 self.coerce_operands_to_pyobjects(env)
4087 self.type = py_object_type
4088 self.gil_check(env)
4089 self.is_temp = 1
4090 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4091 self.operand1 = self.operand1.coerce_to_temp(env)
4092 else:
4093 self.analyse_c_operation(env)
4095 def is_py_operation(self):
4096 return (self.operand1.type.is_pyobject
4097 or self.operand2.type.is_pyobject)
4099 def coerce_operands_to_pyobjects(self, env):
4100 self.operand1 = self.operand1.coerce_to_pyobject(env)
4101 self.operand2 = self.operand2.coerce_to_pyobject(env)
4103 def check_const(self):
4104 self.operand1.check_const()
4105 self.operand2.check_const()
4107 def generate_result_code(self, code):
4108 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4109 if self.operand1.type.is_pyobject:
4110 function = self.py_operation_function()
4111 if function == "PyNumber_Power":
4112 extra_args = ", Py_None"
4113 else:
4114 extra_args = ""
4115 code.putln(
4116 "%s = %s(%s, %s%s); %s" % (
4117 self.result(),
4118 function,
4119 self.operand1.py_result(),
4120 self.operand2.py_result(),
4121 extra_args,
4122 code.error_goto_if_null(self.result(), self.pos)))
4123 code.put_gotref(self.py_result())
4124 else:
4125 if self.is_temp:
4126 self.generate_c_operation_code(code)
4128 def type_error(self):
4129 if not (self.operand1.type.is_error
4130 or self.operand2.type.is_error):
4131 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4132 (self.operator, self.operand1.type,
4133 self.operand2.type))
4134 self.type = PyrexTypes.error_type
4137 class NumBinopNode(BinopNode):
4138 # Binary operation taking numeric arguments.
4140 def analyse_c_operation(self, env):
4141 type1 = self.operand1.type
4142 type2 = self.operand2.type
4143 self.type = self.compute_c_result_type(type1, type2)
4144 if not self.type:
4145 self.type_error()
4147 def compute_c_result_type(self, type1, type2):
4148 if self.c_types_okay(type1, type2):
4149 return PyrexTypes.widest_numeric_type(type1, type2)
4150 else:
4151 return None
4153 def c_types_okay(self, type1, type2):
4154 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4155 return (type1.is_numeric or type1.is_enum) \
4156 and (type2.is_numeric or type2.is_enum)
4158 def calculate_result_code(self):
4159 return "(%s %s %s)" % (
4160 self.operand1.result(),
4161 self.operator,
4162 self.operand2.result())
4164 def py_operation_function(self):
4165 return self.py_functions[self.operator]
4167 py_functions = {
4168 "|": "PyNumber_Or",
4169 "^": "PyNumber_Xor",
4170 "&": "PyNumber_And",
4171 "<<": "PyNumber_Lshift",
4172 ">>": "PyNumber_Rshift",
4173 "+": "PyNumber_Add",
4174 "-": "PyNumber_Subtract",
4175 "*": "PyNumber_Multiply",
4176 "/": "__Pyx_PyNumber_Divide",
4177 "//": "PyNumber_FloorDivide",
4178 "%": "PyNumber_Remainder",
4179 "**": "PyNumber_Power"
4183 class IntBinopNode(NumBinopNode):
4184 # Binary operation taking integer arguments.
4186 def c_types_okay(self, type1, type2):
4187 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4188 return (type1.is_int or type1.is_enum) \
4189 and (type2.is_int or type2.is_enum)
4192 class AddNode(NumBinopNode):
4193 # '+' operator.
4195 def is_py_operation(self):
4196 if self.operand1.type.is_string \
4197 and self.operand2.type.is_string:
4198 return 1
4199 else:
4200 return NumBinopNode.is_py_operation(self)
4202 def compute_c_result_type(self, type1, type2):
4203 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4204 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4205 return type1
4206 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4207 return type2
4208 else:
4209 return NumBinopNode.compute_c_result_type(
4210 self, type1, type2)
4213 class SubNode(NumBinopNode):
4214 # '-' operator.
4216 def compute_c_result_type(self, type1, type2):
4217 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4218 return type1
4219 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4220 return PyrexTypes.c_int_type
4221 else:
4222 return NumBinopNode.compute_c_result_type(
4223 self, type1, type2)
4226 class MulNode(NumBinopNode):
4227 # '*' operator.
4229 def is_py_operation(self):
4230 type1 = self.operand1.type
4231 type2 = self.operand2.type
4232 if (type1.is_string and type2.is_int) \
4233 or (type2.is_string and type1.is_int):
4234 return 1
4235 else:
4236 return NumBinopNode.is_py_operation(self)
4239 class FloorDivNode(NumBinopNode):
4240 # '//' operator.
4242 def calculate_result_code(self):
4243 return "(%s %s %s)" % (
4244 self.operand1.result(),
4245 "/", # c division is by default floor-div
4246 self.operand2.result())
4249 class ModNode(NumBinopNode):
4250 # '%' operator.
4252 def is_py_operation(self):
4253 return (self.operand1.type.is_string
4254 or self.operand2.type.is_string
4255 or NumBinopNode.is_py_operation(self))
4257 def calculate_result_code(self):
4258 if self.operand1.type.is_float or self.operand2.type.is_float:
4259 return "fmod(%s, %s)" % (
4260 self.operand1.result(),
4261 self.operand2.result())
4262 else:
4263 return "(%s %% %s)" % (
4264 self.operand1.result(),
4265 self.operand2.result())
4267 class PowNode(NumBinopNode):
4268 # '**' operator.
4270 def compute_c_result_type(self, type1, type2):
4271 if self.c_types_okay(type1, type2):
4272 return PyrexTypes.c_double_type
4273 else:
4274 return None
4276 def c_types_okay(self, type1, type2):
4277 return (type1.is_float or type2.is_float) and \
4278 NumBinopNode.c_types_okay(self, type1, type2)
4280 def type_error(self):
4281 if not (self.operand1.type.is_error or self.operand2.type.is_error):
4282 if self.operand1.type.is_int and self.operand2.type.is_int:
4283 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
4284 (self.operator, self.operand1.type, self.operand2.type))
4285 else:
4286 NumBinopNode.type_error(self)
4287 self.type = PyrexTypes.error_type
4289 def calculate_result_code(self):
4290 return "pow(%s, %s)" % (
4291 self.operand1.result(), self.operand2.result())
4294 # Note: This class is temporary "shut down" into an ineffective mode temp
4295 # allocation mode.
4297 # More sophisticated temp reuse was going on before,
4298 # one could have a look at adding this again after /all/ classes
4299 # are converted to the new temp scheme. (The temp juggling cannot work
4300 # otherwise).
4301 class BoolBinopNode(NewTempExprNode):
4302 # Short-circuiting boolean operation.
4304 # operator string
4305 # operand1 ExprNode
4306 # operand2 ExprNode
4308 subexprs = ['operand1', 'operand2']
4310 def calculate_constant_result(self):
4311 if self.operator == 'and':
4312 self.constant_result = \
4313 self.operand1.constant_result and \
4314 self.operand2.constant_result
4315 else:
4316 self.constant_result = \
4317 self.operand1.constant_result or \
4318 self.operand2.constant_result
4320 def compile_time_value(self, denv):
4321 if self.operator == 'and':
4322 return self.operand1.compile_time_value(denv) \
4323 and self.operand2.compile_time_value(denv)
4324 else:
4325 return self.operand1.compile_time_value(denv) \
4326 or self.operand2.compile_time_value(denv)
4328 def coerce_to_boolean(self, env):
4329 self.operand1 = self.operand1.coerce_to_boolean(env)
4330 self.operand2 = self.operand2.coerce_to_boolean(env)
4331 self.type = PyrexTypes.c_bint_type
4332 return self
4334 def analyse_types(self, env):
4335 self.operand1.analyse_types(env)
4336 self.operand2.analyse_types(env)
4337 if self.operand1.type.is_pyobject or \
4338 self.operand2.type.is_pyobject:
4339 self.operand1 = self.operand1.coerce_to_pyobject(env)
4340 self.operand2 = self.operand2.coerce_to_pyobject(env)
4341 self.type = py_object_type
4342 self.gil_check(env)
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.gil_check(env)
4953 self.result_ctype = arg.ctype()
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.gil_check(env)
4996 self.is_temp = 1
4997 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4998 error(arg.pos,
4999 "Cannot convert '%s' to Python object" % arg.type)
5001 gil_message = "Converting to Python object"
5003 def coerce_to_boolean(self, env):
5004 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5006 def coerce_to_integer(self, env):
5007 # If not already some C integer type, coerce to longint.
5008 if self.arg.type.is_int:
5009 return self.arg
5010 else:
5011 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5013 def analyse_types(self, env):
5014 # The arg is always already analysed
5015 pass
5017 def generate_result_code(self, code):
5018 function = self.arg.type.to_py_function
5019 code.putln('%s = %s(%s); %s' % (
5020 self.result(),
5021 function,
5022 self.arg.result(),
5023 code.error_goto_if_null(self.result(), self.pos)))
5024 code.put_gotref(self.py_result())
5027 class CoerceFromPyTypeNode(CoercionNode):
5028 # This node is used to convert a Python object
5029 # to a C data type.
5031 def __init__(self, result_type, arg, env):
5032 CoercionNode.__init__(self, arg)
5033 self.type = result_type
5034 self.is_temp = 1
5035 if not result_type.from_py_function:
5036 error(arg.pos,
5037 "Cannot convert Python object to '%s'" % result_type)
5038 if self.type.is_string and self.arg.is_ephemeral():
5039 error(arg.pos,
5040 "Obtaining char * from temporary Python value")
5042 def analyse_types(self, env):
5043 # The arg is always already analysed
5044 pass
5046 def generate_result_code(self, code):
5047 function = self.type.from_py_function
5048 operand = self.arg.py_result()
5049 rhs = "%s(%s)" % (function, operand)
5050 if self.type.is_enum:
5051 rhs = typecast(self.type, c_long_type, rhs)
5052 code.putln('%s = %s; %s' % (
5053 self.result(),
5054 rhs,
5055 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5056 if self.type.is_pyobject:
5057 code.put_gotref(self.py_result())
5060 class CoerceToBooleanNode(CoercionNode):
5061 # This node is used when a result needs to be used
5062 # in a boolean context.
5064 def __init__(self, arg, env):
5065 CoercionNode.__init__(self, arg)
5066 self.type = PyrexTypes.c_bint_type
5067 if arg.type.is_pyobject:
5068 if env.nogil:
5069 self.gil_error()
5070 self.is_temp = 1
5072 gil_message = "Truth-testing Python object"
5074 def check_const(self):
5075 if self.is_temp:
5076 self.not_const()
5077 self.arg.check_const()
5079 def calculate_result_code(self):
5080 return "(%s != 0)" % self.arg.result()
5082 def generate_result_code(self, code):
5083 if self.arg.type.is_pyobject:
5084 code.putln(
5085 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5086 self.result(),
5087 self.arg.py_result(),
5088 code.error_goto_if_neg(self.result(), self.pos)))
5091 class CoerceToTempNode(CoercionNode):
5092 # This node is used to force the result of another node
5093 # to be stored in a temporary. It is only used if the
5094 # argument node's result is not already in a temporary.
5096 def __init__(self, arg, env):
5097 CoercionNode.__init__(self, arg)
5098 self.type = self.arg.type
5099 self.is_temp = 1
5100 if self.type.is_pyobject:
5101 self.gil_check(env)
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
5135 def __init__(self, arg):
5136 CoercionNode.__init__(self, arg)
5137 if hasattr(arg, 'type'):
5138 self.type = arg.type
5139 self.result_ctype = arg.result_ctype
5140 if hasattr(arg, 'entry'):
5141 self.entry = arg.entry
5143 def result(self):
5144 return self.arg.result()
5146 def analyse_types(self, env):
5147 self.type = self.arg.type
5148 self.result_ctype = self.arg.result_ctype
5149 self.is_temp = 1
5150 if hasattr(self.arg, 'entry'):
5151 self.entry = self.arg.entry
5153 def generate_evaluation_code(self, code):
5154 pass
5156 def generate_result_code(self, code):
5157 pass
5159 def generate_disposal_code(self, code):
5160 pass
5162 def allocate_temps(self, env):
5163 pass
5165 def release_temp(self, env):
5166 pass
5168 def free_temps(self, code):
5169 pass
5172 #------------------------------------------------------------------------------------
5174 # Runtime support code
5176 #------------------------------------------------------------------------------------
5178 get_name_interned_utility_code = UtilityCode(
5179 proto = """
5180 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5181 """,
5182 impl = """
5183 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5184 PyObject *result;
5185 result = PyObject_GetAttr(dict, name);
5186 if (!result)
5187 PyErr_SetObject(PyExc_NameError, name);
5188 return result;
5190 """)
5192 #------------------------------------------------------------------------------------
5194 import_utility_code = UtilityCode(
5195 proto = """
5196 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5197 """,
5198 impl = """
5199 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5200 PyObject *__import__ = 0;
5201 PyObject *empty_list = 0;
5202 PyObject *module = 0;
5203 PyObject *global_dict = 0;
5204 PyObject *empty_dict = 0;
5205 PyObject *list;
5206 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5207 if (!__import__)
5208 goto bad;
5209 if (from_list)
5210 list = from_list;
5211 else {
5212 empty_list = PyList_New(0);
5213 if (!empty_list)
5214 goto bad;
5215 list = empty_list;
5217 global_dict = PyModule_GetDict(%(GLOBALS)s);
5218 if (!global_dict)
5219 goto bad;
5220 empty_dict = PyDict_New();
5221 if (!empty_dict)
5222 goto bad;
5223 module = PyObject_CallFunctionObjArgs(__import__,
5224 name, global_dict, empty_dict, list, NULL);
5225 bad:
5226 Py_XDECREF(empty_list);
5227 Py_XDECREF(__import__);
5228 Py_XDECREF(empty_dict);
5229 return module;
5231 """ % {
5232 "BUILTINS": Naming.builtins_cname,
5233 "GLOBALS": Naming.module_cname,
5234 })
5236 #------------------------------------------------------------------------------------
5238 get_exception_utility_code = UtilityCode(
5239 proto = """
5240 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5241 """,
5242 impl = """
5243 static PyObject *__Pyx_GetExcValue(void) {
5244 PyObject *type = 0, *value = 0, *tb = 0;
5245 PyObject *tmp_type, *tmp_value, *tmp_tb;
5246 PyObject *result = 0;
5247 PyThreadState *tstate = PyThreadState_Get();
5248 PyErr_Fetch(&type, &value, &tb);
5249 PyErr_NormalizeException(&type, &value, &tb);
5250 if (PyErr_Occurred())
5251 goto bad;
5252 if (!value) {
5253 value = Py_None;
5254 Py_INCREF(value);
5256 tmp_type = tstate->exc_type;
5257 tmp_value = tstate->exc_value;
5258 tmp_tb = tstate->exc_traceback;
5259 tstate->exc_type = type;
5260 tstate->exc_value = value;
5261 tstate->exc_traceback = tb;
5262 /* Make sure tstate is in a consistent state when we XDECREF
5263 these objects (XDECREF may run arbitrary code). */
5264 Py_XDECREF(tmp_type);
5265 Py_XDECREF(tmp_value);
5266 Py_XDECREF(tmp_tb);
5267 result = value;
5268 Py_XINCREF(result);
5269 type = 0;
5270 value = 0;
5271 tb = 0;
5272 bad:
5273 Py_XDECREF(type);
5274 Py_XDECREF(value);
5275 Py_XDECREF(tb);
5276 return result;
5278 """)
5280 #------------------------------------------------------------------------------------
5282 type_test_utility_code = UtilityCode(
5283 proto = """
5284 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5285 """,
5286 impl = """
5287 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5288 if (!type) {
5289 PyErr_Format(PyExc_SystemError, "Missing type object");
5290 return 0;
5292 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5293 return 1;
5294 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5295 Py_TYPE(obj)->tp_name, type->tp_name);
5296 return 0;
5298 """)
5300 #------------------------------------------------------------------------------------
5302 create_class_utility_code = UtilityCode(
5303 proto = """
5304 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5305 """,
5306 impl = """
5307 static PyObject *__Pyx_CreateClass(
5308 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5310 PyObject *py_modname;
5311 PyObject *result = 0;
5313 #if PY_MAJOR_VERSION < 3
5314 py_modname = PyString_FromString(modname);
5315 #else
5316 py_modname = PyUnicode_FromString(modname);
5317 #endif
5318 if (!py_modname)
5319 goto bad;
5320 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5321 goto bad;
5322 #if PY_MAJOR_VERSION < 3
5323 result = PyClass_New(bases, dict, name);
5324 #else
5325 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5326 #endif
5327 bad:
5328 Py_XDECREF(py_modname);
5329 return result;
5331 """)
5333 #------------------------------------------------------------------------------------
5335 cpp_exception_utility_code = UtilityCode(
5336 proto = """
5337 #ifndef __Pyx_CppExn2PyErr
5338 static void __Pyx_CppExn2PyErr() {
5339 try {
5340 if (PyErr_Occurred())
5341 ; // let the latest Python exn pass through and ignore the current one
5342 else
5343 throw;
5344 } catch (const std::out_of_range& exn) {
5345 // catch out_of_range explicitly so the proper Python exn may be raised
5346 PyErr_SetString(PyExc_IndexError, exn.what());
5347 } catch (const std::exception& exn) {
5348 PyErr_SetString(PyExc_RuntimeError, exn.what());
5350 catch (...)
5352 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5355 #endif
5356 """,
5357 impl = ""
5360 #------------------------------------------------------------------------------------
5362 append_utility_code = UtilityCode(
5363 proto = """
5364 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5365 if (likely(PyList_CheckExact(L))) {
5366 if (PyList_Append(L, x) < 0) return NULL;
5367 Py_INCREF(Py_None);
5368 return Py_None; /* this is just to have an accurate signature */
5370 else {
5371 PyObject *r, *m;
5372 m = __Pyx_GetAttrString(L, "append");
5373 if (!m) return NULL;
5374 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5375 Py_DECREF(m);
5376 return r;
5379 """,
5380 impl = ""
5383 #------------------------------------------------------------------------------------
5385 # If the is_unsigned flag is set, we need to do some extra work to make
5386 # sure the index doesn't become negative.
5388 getitem_int_utility_code = UtilityCode(
5389 proto = """
5391 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5392 PyObject *r;
5393 if (!j) return NULL;
5394 r = PyObject_GetItem(o, j);
5395 Py_DECREF(j);
5396 return r;
5399 """ + ''.join([
5400 """
5401 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5402 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5403 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5405 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5406 if (likely(o != Py_None)) {
5407 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5408 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5409 Py_INCREF(r);
5410 return r;
5412 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5413 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5414 Py_INCREF(r);
5415 return r;
5418 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5420 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5421 ]) + """
5423 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5424 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5425 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5427 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5428 PyObject *r;
5429 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5430 r = PyList_GET_ITEM(o, i);
5431 Py_INCREF(r);
5433 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5434 r = PyTuple_GET_ITEM(o, i);
5435 Py_INCREF(r);
5437 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5438 r = PySequence_GetItem(o, i);
5440 else {
5441 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5443 return r;
5445 """,
5446 impl = """
5447 """)
5451 #------------------------------------------------------------------------------------
5453 setitem_int_utility_code = UtilityCode(
5454 proto = """
5455 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5456 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5457 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5459 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5460 int r;
5461 if (!j) return -1;
5462 r = PyObject_SetItem(o, j, v);
5463 Py_DECREF(j);
5464 return r;
5467 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5468 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5469 Py_DECREF(PyList_GET_ITEM(o, i));
5470 Py_INCREF(v);
5471 PyList_SET_ITEM(o, i, v);
5472 return 1;
5474 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5475 return PySequence_SetItem(o, i, v);
5476 else {
5477 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5478 return __Pyx_SetItemInt_Generic(o, j, v);
5481 """,
5482 impl = """
5483 """)
5485 #------------------------------------------------------------------------------------
5487 delitem_int_utility_code = UtilityCode(
5488 proto = """
5489 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5490 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5491 __Pyx_DelItem_Generic(o, to_py_func(i)))
5493 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5494 int r;
5495 if (!j) return -1;
5496 r = PyObject_DelItem(o, j);
5497 Py_DECREF(j);
5498 return r;
5501 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5502 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5503 return PySequence_DelItem(o, i);
5504 else {
5505 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5506 return __Pyx_DelItem_Generic(o, j);
5509 """,
5510 impl = """
5511 """)
5513 #------------------------------------------------------------------------------------
5515 raise_noneattr_error_utility_code = UtilityCode(
5516 proto = """
5517 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5518 """,
5519 impl = '''
5520 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5521 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5523 ''')
5525 raise_noneindex_error_utility_code = UtilityCode(
5526 proto = """
5527 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5528 """,
5529 impl = '''
5530 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5531 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5533 ''')
5535 raise_none_iter_error_utility_code = UtilityCode(
5536 proto = """
5537 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5538 """,
5539 impl = '''
5540 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5541 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5543 ''')
5545 raise_too_many_values_to_unpack = UtilityCode(
5546 proto = """
5547 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5548 """,
5549 impl = '''
5550 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5551 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5553 ''')
5555 raise_need_more_values_to_unpack = UtilityCode(
5556 proto = """
5557 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5558 """,
5559 impl = '''
5560 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5561 PyErr_Format(PyExc_ValueError,
5562 #if PY_VERSION_HEX < 0x02050000
5563 "need more than %d value%s to unpack", (int)index,
5564 #else
5565 "need more than %zd value%s to unpack", index,
5566 #endif
5567 (index == 1) ? "" : "s");
5569 ''')
5571 #------------------------------------------------------------------------------------
5573 unpacking_utility_code = UtilityCode(
5574 proto = """
5575 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5576 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5577 """,
5578 impl = """
5579 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5580 PyObject *item;
5581 if (!(item = PyIter_Next(iter))) {
5582 if (!PyErr_Occurred()) {
5583 __Pyx_RaiseNeedMoreValuesError(index);
5586 return item;
5589 static int __Pyx_EndUnpack(PyObject *iter) {
5590 PyObject *item;
5591 if ((item = PyIter_Next(iter))) {
5592 Py_DECREF(item);
5593 __Pyx_RaiseTooManyValuesError();
5594 return -1;
5596 else if (!PyErr_Occurred())
5597 return 0;
5598 else
5599 return -1;
5601 """,
5602 requires = [raise_need_more_values_to_unpack,
5603 raise_too_many_values_to_unpack]