Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 1729:85680600a6c9
Fix memleak in cascaded comparisons.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Fri Feb 20 21:55:25 2009 -0800 (3 years ago) |
| parents | 249cf0073c3a |
| children | 6692a0f0e87a |
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
1027 #
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.
1055 #
1056 # name string Python name of the variable
1057 #
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 # in Py2.6+, we need to invalidate the method cache
1306 code.putln("PyType_Modified(%s);" %
1307 entry.scope.parent_type.typeptr_cname)
1308 else:
1309 code.put_error_if_neg(self.pos,
1310 'PyObject_SetAttr(%s, %s, %s)' % (
1311 namespace,
1312 self.interned_cname,
1313 rhs.py_result()))
1314 if debug_disposal_code:
1315 print("NameNode.generate_assignment_code:")
1316 print("...generating disposal code for %s" % rhs)
1317 rhs.generate_disposal_code(code)
1318 rhs.free_temps(code)
1319 else:
1320 if self.type.is_buffer:
1321 # Generate code for doing the buffer release/acquisition.
1322 # This might raise an exception in which case the assignment (done
1323 # below) will not happen.
1324 #
1325 # The reason this is not in a typetest-like node is because the
1326 # variables that the acquired buffer info is stored to is allocated
1327 # per entry and coupled with it.
1328 self.generate_acquire_buffer(rhs, code)
1330 if self.type.is_pyobject:
1331 rhs.make_owned_reference(code)
1332 #print "NameNode.generate_assignment_code: to", self.name ###
1333 #print "...from", rhs ###
1334 #print "...LHS type", self.type, "ctype", self.ctype() ###
1335 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1336 if entry.is_cglobal:
1337 code.put_gotref(self.py_result())
1338 if not self.lhs_of_first_assignment:
1339 if entry.is_local and not Options.init_local_none:
1340 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1341 if initalized is True:
1342 code.put_decref(self.result(), self.ctype())
1343 elif initalized is None:
1344 code.put_xdecref(self.result(), self.ctype())
1345 else:
1346 code.put_decref(self.result(), self.ctype())
1347 if entry.is_cglobal:
1348 code.put_giveref(rhs.py_result())
1349 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1350 if debug_disposal_code:
1351 print("NameNode.generate_assignment_code:")
1352 print("...generating post-assignment code for %s" % rhs)
1353 rhs.generate_post_assignment_code(code)
1354 rhs.free_temps(code)
1356 def generate_acquire_buffer(self, rhs, code):
1357 # rhstmp is only used in case the rhs is a complicated expression leading to
1358 # the object, to avoid repeating the same C expression for every reference
1359 # to the rhs. It does NOT hold a reference.
1360 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1361 if pretty_rhs:
1362 rhstmp = rhs.result_as(self.ctype())
1363 else:
1364 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1365 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1367 buffer_aux = self.entry.buffer_aux
1368 bufstruct = buffer_aux.buffer_info_var.cname
1369 import Buffer
1370 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1371 is_initialized=not self.lhs_of_first_assignment,
1372 pos=self.pos, code=code)
1374 if not pretty_rhs:
1375 code.putln("%s = 0;" % rhstmp)
1376 code.funcstate.release_temp(rhstmp)
1378 def generate_deletion_code(self, code):
1379 if self.entry is None:
1380 return # There was an error earlier
1381 if not self.entry.is_pyglobal:
1382 error(self.pos, "Deletion of local or C global name not supported")
1383 return
1384 code.put_error_if_neg(self.pos,
1385 '__Pyx_DelAttrString(%s, "%s")' % (
1386 Naming.module_cname,
1387 self.entry.name))
1389 def annotate(self, code):
1390 if hasattr(self, 'is_called') and self.is_called:
1391 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1392 if self.type.is_pyobject:
1393 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1394 else:
1395 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1397 class BackquoteNode(ExprNode):
1398 # `expr`
1399 #
1400 # arg ExprNode
1402 subexprs = ['arg']
1404 def analyse_types(self, env):
1405 self.arg.analyse_types(env)
1406 self.arg = self.arg.coerce_to_pyobject(env)
1407 self.type = py_object_type
1408 self.gil_check(env)
1409 self.is_temp = 1
1411 gil_message = "Backquote expression"
1413 def calculate_constant_result(self):
1414 self.constant_result = repr(self.arg.constant_result)
1416 def generate_result_code(self, code):
1417 code.putln(
1418 "%s = PyObject_Repr(%s); %s" % (
1419 self.result(),
1420 self.arg.py_result(),
1421 code.error_goto_if_null(self.result(), self.pos)))
1422 code.put_gotref(self.py_result())
1426 class ImportNode(ExprNode):
1427 # Used as part of import statement implementation.
1428 # Implements result =
1429 # __import__(module_name, globals(), None, name_list)
1430 #
1431 # module_name IdentifierStringNode dotted name of module
1432 # name_list ListNode or None list of names to be imported
1434 subexprs = ['module_name', 'name_list']
1436 def analyse_types(self, env):
1437 self.module_name.analyse_types(env)
1438 self.module_name = self.module_name.coerce_to_pyobject(env)
1439 if self.name_list:
1440 self.name_list.analyse_types(env)
1441 self.name_list.coerce_to_pyobject(env)
1442 self.type = py_object_type
1443 self.gil_check(env)
1444 self.is_temp = 1
1445 env.use_utility_code(import_utility_code)
1447 gil_message = "Python import"
1449 def generate_result_code(self, code):
1450 if self.name_list:
1451 name_list_code = self.name_list.py_result()
1452 else:
1453 name_list_code = "0"
1454 code.putln(
1455 "%s = __Pyx_Import(%s, %s); %s" % (
1456 self.result(),
1457 self.module_name.py_result(),
1458 name_list_code,
1459 code.error_goto_if_null(self.result(), self.pos)))
1460 code.put_gotref(self.py_result())
1463 class IteratorNode(NewTempExprNode):
1464 # Used as part of for statement implementation.
1465 #
1466 # allocate_counter_temp/release_counter_temp needs to be called
1467 # by parent (ForInStatNode)
1468 #
1469 # Implements result = iter(sequence)
1470 #
1471 # sequence ExprNode
1473 subexprs = ['sequence']
1475 def analyse_types(self, env):
1476 self.sequence.analyse_types(env)
1477 self.sequence = self.sequence.coerce_to_pyobject(env)
1478 self.type = py_object_type
1479 self.gil_check(env)
1480 self.is_temp = 1
1482 gil_message = "Iterating over Python object"
1484 def allocate_counter_temp(self, code):
1485 self.counter_cname = code.funcstate.allocate_temp(
1486 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1488 def release_counter_temp(self, code):
1489 code.funcstate.release_temp(self.counter_cname)
1491 def generate_result_code(self, code):
1492 is_builtin_sequence = self.sequence.type is list_type or \
1493 self.sequence.type is tuple_type
1494 if is_builtin_sequence:
1495 code.putln(
1496 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1497 else:
1498 code.putln(
1499 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1500 self.sequence.py_result(),
1501 self.sequence.py_result()))
1502 code.putln(
1503 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1504 self.counter_cname,
1505 self.result(),
1506 self.sequence.py_result(),
1507 self.result()))
1508 code.putln("} else {")
1509 if is_builtin_sequence:
1510 code.putln(
1511 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1512 code.error_goto(self.pos))
1513 else:
1514 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1515 self.counter_cname,
1516 self.result(),
1517 self.sequence.py_result(),
1518 code.error_goto_if_null(self.result(), self.pos)))
1519 code.put_gotref(self.py_result())
1520 code.putln("}")
1523 class NextNode(AtomicNewTempExprNode):
1524 # Used as part of for statement implementation.
1525 # Implements result = iterator.next()
1526 # Created during analyse_types phase.
1527 # The iterator is not owned by this node.
1528 #
1529 # iterator ExprNode
1531 def __init__(self, iterator, env):
1532 self.pos = iterator.pos
1533 self.iterator = iterator
1534 self.type = py_object_type
1535 self.is_temp = 1
1537 def generate_result_code(self, code):
1538 if self.iterator.sequence.type is list_type:
1539 type_checks = [(list_type, "List")]
1540 elif self.iterator.sequence.type is tuple_type:
1541 type_checks = [(tuple_type, "Tuple")]
1542 else:
1543 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1545 for py_type, prefix in type_checks:
1546 if len(type_checks) > 1:
1547 code.putln(
1548 "if (likely(Py%s_CheckExact(%s))) {" % (
1549 prefix, self.iterator.py_result()))
1550 code.putln(
1551 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1552 self.iterator.counter_cname,
1553 prefix,
1554 self.iterator.py_result()))
1555 code.putln(
1556 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1557 self.result(),
1558 prefix,
1559 self.iterator.py_result(),
1560 self.iterator.counter_cname,
1561 self.result(),
1562 self.iterator.counter_cname))
1563 if len(type_checks) > 1:
1564 code.put("} else ")
1565 if len(type_checks) == 1:
1566 return
1567 code.putln("{")
1568 code.putln(
1569 "%s = PyIter_Next(%s);" % (
1570 self.result(),
1571 self.iterator.py_result()))
1572 code.putln(
1573 "if (!%s) {" %
1574 self.result())
1575 code.putln(code.error_goto_if_PyErr(self.pos))
1576 code.putln("break;")
1577 code.putln("}")
1578 code.put_gotref(self.py_result())
1579 code.putln("}")
1582 class ExcValueNode(AtomicNewTempExprNode):
1583 # Node created during analyse_types phase
1584 # of an ExceptClauseNode to fetch the current
1585 # exception value.
1587 def __init__(self, pos, env, var):
1588 ExprNode.__init__(self, pos)
1589 self.type = py_object_type
1590 self.var = var
1592 def calculate_result_code(self):
1593 return self.var
1595 def generate_result_code(self, code):
1596 pass
1598 def analyse_types(self, env):
1599 pass
1602 class TempNode(ExprNode):
1603 # Node created during analyse_types phase
1604 # of some nodes to hold a temporary value.
1606 subexprs = []
1608 def __init__(self, pos, type, env):
1609 ExprNode.__init__(self, pos)
1610 self.type = type
1611 if type.is_pyobject:
1612 self.result_ctype = py_object_type
1613 self.is_temp = 1
1615 def analyse_types(self, env):
1616 return self.type
1618 def generate_result_code(self, code):
1619 pass
1622 class PyTempNode(TempNode):
1623 # TempNode holding a Python value.
1625 def __init__(self, pos, env):
1626 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1629 #-------------------------------------------------------------------
1630 #
1631 # Trailer nodes
1632 #
1633 #-------------------------------------------------------------------
1635 class IndexNode(ExprNode):
1636 # Sequence indexing.
1637 #
1638 # base ExprNode
1639 # index ExprNode
1640 # indices [ExprNode]
1641 # is_buffer_access boolean Whether this is a buffer access.
1642 #
1643 # indices is used on buffer access, index on non-buffer access.
1644 # The former contains a clean list of index parameters, the
1645 # latter whatever Python object is needed for index access.
1647 subexprs = ['base', 'index', 'indices']
1648 indices = None
1650 def __init__(self, pos, index, *args, **kw):
1651 ExprNode.__init__(self, pos, index=index, *args, **kw)
1652 self._index = index
1654 def calculate_constant_result(self):
1655 self.constant_result = \
1656 self.base.constant_result[self.index.constant_result]
1658 def compile_time_value(self, denv):
1659 base = self.base.compile_time_value(denv)
1660 index = self.index.compile_time_value(denv)
1661 try:
1662 return base[index]
1663 except Exception, e:
1664 self.compile_time_value_error(e)
1666 def is_ephemeral(self):
1667 return self.base.is_ephemeral()
1669 def analyse_target_declaration(self, env):
1670 pass
1672 def analyse_as_type(self, env):
1673 base_type = self.base.analyse_as_type(env)
1674 if base_type and not base_type.is_pyobject:
1675 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1676 return None
1678 def analyse_types(self, env):
1679 self.analyse_base_and_index_types(env, getting = 1)
1681 def analyse_target_types(self, env):
1682 self.analyse_base_and_index_types(env, setting = 1)
1684 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1685 # Note: This might be cleaned up by having IndexNode
1686 # parsed in a saner way and only construct the tuple if
1687 # needed.
1689 # Note that this function must leave IndexNode in a cloneable state.
1690 # For buffers, self.index is packed out on the initial analysis, and
1691 # when cloning self.indices is copied.
1692 self.is_buffer_access = False
1694 self.base.analyse_types(env)
1695 # Handle the case where base is a literal char* (and we expect a string, not an int)
1696 if isinstance(self.base, StringNode):
1697 self.base = self.base.coerce_to_pyobject(env)
1699 skip_child_analysis = False
1700 buffer_access = False
1701 if self.base.type.is_buffer:
1702 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1703 if self.indices:
1704 indices = self.indices
1705 else:
1706 # On cloning, indices is cloned. Otherwise, unpack index into indices
1707 assert not isinstance(self.index, CloneNode)
1708 if isinstance(self.index, TupleNode):
1709 indices = self.index.args
1710 else:
1711 indices = [self.index]
1712 if len(indices) == self.base.type.ndim:
1713 buffer_access = True
1714 skip_child_analysis = True
1715 for x in indices:
1716 x.analyse_types(env)
1717 if not x.type.is_int:
1718 buffer_access = False
1720 if buffer_access:
1721 self.indices = indices
1722 self.index = None
1723 self.type = self.base.type.dtype
1724 self.is_buffer_access = True
1725 self.buffer_type = self.base.entry.type
1727 if getting and self.type.is_pyobject:
1728 self.is_temp = True
1729 if setting:
1730 if not self.base.entry.type.writable:
1731 error(self.pos, "Writing to readonly buffer")
1732 else:
1733 self.base.entry.buffer_aux.writable_needed = True
1734 else:
1735 if isinstance(self.index, TupleNode):
1736 self.index.analyse_types(env, skip_children=skip_child_analysis)
1737 elif not skip_child_analysis:
1738 self.index.analyse_types(env)
1739 self.original_index_type = self.index.type
1740 if self.base.type.is_pyobject:
1741 if self.index.type.is_int and not self.index.type.is_longlong:
1742 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1743 else:
1744 self.index = self.index.coerce_to_pyobject(env)
1745 self.type = py_object_type
1746 self.gil_check(env)
1747 self.is_temp = 1
1748 else:
1749 if self.base.type.is_ptr or self.base.type.is_array:
1750 self.type = self.base.type.base_type
1751 else:
1752 error(self.pos,
1753 "Attempting to index non-array type '%s'" %
1754 self.base.type)
1755 self.type = PyrexTypes.error_type
1756 if self.index.type.is_pyobject:
1757 self.index = self.index.coerce_to(
1758 PyrexTypes.c_py_ssize_t_type, env)
1759 if not self.index.type.is_int:
1760 error(self.pos,
1761 "Invalid index type '%s'" %
1762 self.index.type)
1764 gil_message = "Indexing Python object"
1766 def check_const_addr(self):
1767 self.base.check_const_addr()
1768 self.index.check_const()
1770 def is_lvalue(self):
1771 return 1
1773 def calculate_result_code(self):
1774 if self.is_buffer_access:
1775 return "(*%s)" % self.buffer_ptr_code
1776 else:
1777 return "(%s[%s])" % (
1778 self.base.result(), self.index.result())
1780 def index_unsigned_parameter(self):
1781 if self.index.type.is_int:
1782 if self.original_index_type.signed:
1783 return ", 0"
1784 else:
1785 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1786 else:
1787 return ""
1789 def generate_subexpr_evaluation_code(self, code):
1790 self.base.generate_evaluation_code(code)
1791 if not self.indices:
1792 self.index.generate_evaluation_code(code)
1793 else:
1794 for i in self.indices:
1795 i.generate_evaluation_code(code)
1797 def generate_subexpr_disposal_code(self, code):
1798 self.base.generate_disposal_code(code)
1799 if not self.indices:
1800 self.index.generate_disposal_code(code)
1801 else:
1802 for i in self.indices:
1803 i.generate_disposal_code(code)
1805 def free_subexpr_temps(self, code):
1806 self.base.free_temps(code)
1807 if not self.indices:
1808 self.index.free_temps(code)
1809 else:
1810 for i in self.indices:
1811 i.free_temps(code)
1813 def generate_result_code(self, code):
1814 if self.is_buffer_access:
1815 if code.globalstate.directives['nonecheck']:
1816 self.put_nonecheck(code)
1817 self.buffer_ptr_code = self.buffer_lookup_code(code)
1818 if self.type.is_pyobject:
1819 # is_temp is True, so must pull out value and incref it.
1820 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1821 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1822 elif self.type.is_pyobject:
1823 if self.index.type.is_int:
1824 function = "__Pyx_GetItemInt"
1825 index_code = self.index.result()
1826 code.globalstate.use_utility_code(getitem_int_utility_code)
1827 else:
1828 function = "PyObject_GetItem"
1829 index_code = self.index.py_result()
1830 sign_code = ""
1831 code.putln(
1832 "%s = %s(%s, %s%s); if (!%s) %s" % (
1833 self.result(),
1834 function,
1835 self.base.py_result(),
1836 index_code,
1837 self.index_unsigned_parameter(),
1838 self.result(),
1839 code.error_goto(self.pos)))
1840 code.put_gotref(self.py_result())
1842 def generate_setitem_code(self, value_code, code):
1843 if self.index.type.is_int:
1844 function = "__Pyx_SetItemInt"
1845 index_code = self.index.result()
1846 code.globalstate.use_utility_code(setitem_int_utility_code)
1847 else:
1848 index_code = self.index.py_result()
1849 if self.base.type is dict_type:
1850 function = "PyDict_SetItem"
1851 elif self.base.type is list_type:
1852 function = "PyList_SetItem"
1853 # don't use PyTuple_SetItem(), as we'd normally get a
1854 # TypeError when changing a tuple, while PyTuple_SetItem()
1855 # would allow updates
1856 #
1857 #elif self.base.type is tuple_type:
1858 # function = "PyTuple_SetItem"
1859 else:
1860 function = "PyObject_SetItem"
1861 code.putln(
1862 "if (%s(%s, %s, %s%s) < 0) %s" % (
1863 function,
1864 self.base.py_result(),
1865 index_code,
1866 value_code,
1867 self.index_unsigned_parameter(),
1868 code.error_goto(self.pos)))
1870 def generate_buffer_setitem_code(self, rhs, code, op=""):
1871 # Used from generate_assignment_code and InPlaceAssignmentNode
1872 if code.globalstate.directives['nonecheck']:
1873 self.put_nonecheck(code)
1874 ptrexpr = self.buffer_lookup_code(code)
1875 if self.buffer_type.dtype.is_pyobject:
1876 # Must manage refcounts. Decref what is already there
1877 # and incref what we put in.
1878 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1879 rhs_code = rhs.result()
1880 code.putln("%s = %s;" % (ptr, ptrexpr))
1881 code.put_gotref("*%s" % ptr)
1882 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1883 ptr, rhs_code
1884 ))
1885 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1886 code.put_giveref("*%s" % ptr)
1887 code.funcstate.release_temp(ptr)
1888 else:
1889 # Simple case
1890 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1892 def generate_assignment_code(self, rhs, code):
1893 self.generate_subexpr_evaluation_code(code)
1894 if self.is_buffer_access:
1895 self.generate_buffer_setitem_code(rhs, code)
1896 elif self.type.is_pyobject:
1897 self.generate_setitem_code(rhs.py_result(), code)
1898 else:
1899 code.putln(
1900 "%s = %s;" % (
1901 self.result(), rhs.result()))
1902 self.generate_subexpr_disposal_code(code)
1903 self.free_subexpr_temps(code)
1904 rhs.generate_disposal_code(code)
1905 rhs.free_temps(code)
1907 def generate_deletion_code(self, code):
1908 self.generate_subexpr_evaluation_code(code)
1909 #if self.type.is_pyobject:
1910 if self.index.type.is_int:
1911 function = "__Pyx_DelItemInt"
1912 index_code = self.index.result()
1913 code.globalstate.use_utility_code(delitem_int_utility_code)
1914 else:
1915 index_code = self.index.py_result()
1916 if self.base.type is dict_type:
1917 function = "PyDict_DelItem"
1918 else:
1919 function = "PyObject_DelItem"
1920 code.putln(
1921 "if (%s(%s, %s%s) < 0) %s" % (
1922 function,
1923 self.base.py_result(),
1924 index_code,
1925 self.index_unsigned_parameter(),
1926 code.error_goto(self.pos)))
1927 self.generate_subexpr_disposal_code(code)
1929 def buffer_lookup_code(self, code):
1930 # Assign indices to temps
1931 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1932 for temp, index in zip(index_temps, self.indices):
1933 code.putln("%s = %s;" % (temp, index.result()))
1934 # Generate buffer access code using these temps
1935 import Buffer
1936 # The above could happen because child_attrs is wrong somewhere so that
1937 # options are not propagated.
1938 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1939 index_signeds=[i.type.signed for i in self.indices],
1940 index_cnames=index_temps,
1941 options=code.globalstate.directives,
1942 pos=self.pos, code=code)
1944 def put_nonecheck(self, code):
1945 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1946 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1947 code.putln("__Pyx_RaiseNoneIndexingError();")
1948 code.putln(code.error_goto(self.pos))
1949 code.putln("}")
1951 class SliceIndexNode(ExprNode):
1952 # 2-element slice indexing
1953 #
1954 # base ExprNode
1955 # start ExprNode or None
1956 # stop ExprNode or None
1958 subexprs = ['base', 'start', 'stop']
1960 def calculate_constant_result(self):
1961 self.constant_result = self.base.constant_result[
1962 self.start.constant_result : self.stop.constant_result]
1964 def compile_time_value(self, denv):
1965 base = self.base.compile_time_value(denv)
1966 if self.start is None:
1967 start = 0
1968 else:
1969 start = self.start.compile_time_value(denv)
1970 if self.stop is None:
1971 stop = None
1972 else:
1973 stop = self.stop.compile_time_value(denv)
1974 try:
1975 return base[start:stop]
1976 except Exception, e:
1977 self.compile_time_value_error(e)
1979 def analyse_target_declaration(self, env):
1980 pass
1982 def analyse_types(self, env):
1983 self.base.analyse_types(env)
1984 if self.start:
1985 self.start.analyse_types(env)
1986 if self.stop:
1987 self.stop.analyse_types(env)
1988 if self.base.type.is_string:
1989 self.type = py_object_type
1990 elif self.base.type.is_array or self.base.type.is_ptr:
1991 # we need a ptr type here instead of an array type, as
1992 # array types can result in invalid type casts in the C
1993 # code
1994 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
1995 else:
1996 self.base = self.base.coerce_to_pyobject(env)
1997 self.type = py_object_type
1998 c_int = PyrexTypes.c_py_ssize_t_type
1999 if self.start:
2000 self.start = self.start.coerce_to(c_int, env)
2001 if self.stop:
2002 self.stop = self.stop.coerce_to(c_int, env)
2003 self.gil_check(env)
2004 self.is_temp = 1
2006 gil_message = "Slicing Python object"
2008 def generate_result_code(self, code):
2009 if not self.type.is_pyobject:
2010 error(self.pos,
2011 "Slicing is not currently supported for '%s'." % self.type)
2012 return
2013 if self.base.type.is_string:
2014 if self.stop is None:
2015 code.putln(
2016 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2017 self.result(),
2018 self.base.result(),
2019 self.start_code(),
2020 code.error_goto_if_null(self.result(), self.pos)))
2021 else:
2022 code.putln(
2023 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2024 self.result(),
2025 self.base.result(),
2026 self.start_code(),
2027 self.stop_code(),
2028 self.start_code(),
2029 code.error_goto_if_null(self.result(), self.pos)))
2030 else:
2031 code.putln(
2032 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2033 self.result(),
2034 self.base.py_result(),
2035 self.start_code(),
2036 self.stop_code(),
2037 code.error_goto_if_null(self.result(), self.pos)))
2038 code.put_gotref(self.py_result())
2040 def generate_assignment_code(self, rhs, code):
2041 self.generate_subexpr_evaluation_code(code)
2042 if self.type.is_pyobject:
2043 code.put_error_if_neg(self.pos,
2044 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2045 self.base.py_result(),
2046 self.start_code(),
2047 self.stop_code(),
2048 rhs.result()))
2049 else:
2050 start_offset = ''
2051 if self.start:
2052 start_offset = self.start_code()
2053 if start_offset == '0':
2054 start_offset = ''
2055 else:
2056 start_offset += '+'
2057 if rhs.type.is_array:
2058 array_length = rhs.type.size
2059 self.generate_slice_guard_code(code, array_length)
2060 else:
2061 error("Slice assignments from pointers are not yet supported.")
2062 # FIXME: fix the array size according to start/stop
2063 array_length = self.base.type.size
2064 for i in range(array_length):
2065 code.putln("%s[%s%s] = %s[%d];" % (
2066 self.base.result(), start_offset, i,
2067 rhs.result(), i))
2068 self.generate_subexpr_disposal_code(code)
2069 self.free_subexpr_temps(code)
2070 rhs.generate_disposal_code(code)
2071 rhs.free_temps(code)
2073 def generate_deletion_code(self, code):
2074 if not self.base.type.is_pyobject:
2075 error(self.pos,
2076 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2077 return
2078 self.generate_subexpr_evaluation_code(code)
2079 code.put_error_if_neg(self.pos,
2080 "PySequence_DelSlice(%s, %s, %s)" % (
2081 self.base.py_result(),
2082 self.start_code(),
2083 self.stop_code()))
2084 self.generate_subexpr_disposal_code(code)
2086 def generate_slice_guard_code(self, code, target_size):
2087 if not self.base.type.is_array:
2088 return
2089 slice_size = self.base.type.size
2090 start = stop = None
2091 if self.stop:
2092 stop = self.stop.result()
2093 try:
2094 stop = int(stop)
2095 if stop < 0:
2096 slice_size = self.base.type.size + stop
2097 else:
2098 slice_size = stop
2099 stop = None
2100 except ValueError:
2101 pass
2102 if self.start:
2103 start = self.start.result()
2104 try:
2105 start = int(start)
2106 if start < 0:
2107 start = self.base.type.size + start
2108 slice_size -= start
2109 start = None
2110 except ValueError:
2111 pass
2112 check = None
2113 if slice_size < 0:
2114 if target_size > 0:
2115 error(self.pos, "Assignment to empty slice.")
2116 elif start is None and stop is None:
2117 # we know the exact slice length
2118 if target_size != slice_size:
2119 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2120 slice_size, target_size))
2121 elif start is not None:
2122 if stop is None:
2123 stop = slice_size
2124 check = "(%s)-(%s)" % (stop, start)
2125 else: # stop is not None:
2126 check = stop
2127 if check:
2128 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2129 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2130 target_size, check))
2131 code.putln(code.error_goto(self.pos))
2132 code.putln("}")
2134 def start_code(self):
2135 if self.start:
2136 return self.start.result()
2137 else:
2138 return "0"
2140 def stop_code(self):
2141 if self.stop:
2142 return self.stop.result()
2143 elif self.base.type.is_array:
2144 return self.base.type.size
2145 else:
2146 return "PY_SSIZE_T_MAX"
2148 def calculate_result_code(self):
2149 # self.result() is not used, but this method must exist
2150 return "<unused>"
2153 class SliceNode(ExprNode):
2154 # start:stop:step in subscript list
2155 #
2156 # start ExprNode
2157 # stop ExprNode
2158 # step ExprNode
2160 def calculate_constant_result(self):
2161 self.constant_result = self.base.constant_result[
2162 self.start.constant_result : \
2163 self.stop.constant_result : \
2164 self.step.constant_result]
2166 def compile_time_value(self, denv):
2167 start = self.start.compile_time_value(denv)
2168 if self.stop is None:
2169 stop = None
2170 else:
2171 stop = self.stop.compile_time_value(denv)
2172 if self.step is None:
2173 step = None
2174 else:
2175 step = self.step.compile_time_value(denv)
2176 try:
2177 return slice(start, stop, step)
2178 except Exception, e:
2179 self.compile_time_value_error(e)
2181 subexprs = ['start', 'stop', 'step']
2183 def analyse_types(self, env):
2184 self.start.analyse_types(env)
2185 self.stop.analyse_types(env)
2186 self.step.analyse_types(env)
2187 self.start = self.start.coerce_to_pyobject(env)
2188 self.stop = self.stop.coerce_to_pyobject(env)
2189 self.step = self.step.coerce_to_pyobject(env)
2190 self.type = py_object_type
2191 self.gil_check(env)
2192 self.is_temp = 1
2194 gil_message = "Constructing Python slice object"
2196 def generate_result_code(self, code):
2197 code.putln(
2198 "%s = PySlice_New(%s, %s, %s); %s" % (
2199 self.result(),
2200 self.start.py_result(),
2201 self.stop.py_result(),
2202 self.step.py_result(),
2203 code.error_goto_if_null(self.result(), self.pos)))
2204 code.put_gotref(self.py_result())
2207 class CallNode(NewTempExprNode):
2208 def gil_check(self, env):
2209 # Make sure we're not in a nogil environment
2210 if env.nogil:
2211 error(self.pos, "Calling gil-requiring function without gil")
2213 def analyse_as_type_constructor(self, env):
2214 type = self.function.analyse_as_type(env)
2215 if type and type.is_struct_or_union:
2216 args, kwds = self.explicit_args_kwds()
2217 items = []
2218 for arg, member in zip(args, type.scope.var_entries):
2219 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2220 if kwds:
2221 items += kwds.key_value_pairs
2222 self.key_value_pairs = items
2223 self.__class__ = DictNode
2224 self.analyse_types(env)
2225 self.coerce_to(type, env)
2226 return True
2229 class SimpleCallNode(CallNode):
2230 # Function call without keyword, * or ** args.
2231 #
2232 # function ExprNode
2233 # args [ExprNode]
2234 # arg_tuple ExprNode or None used internally
2235 # self ExprNode or None used internally
2236 # coerced_self ExprNode or None used internally
2237 # wrapper_call bool used internally
2238 # has_optional_args bool used internally
2240 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2242 self = None
2243 coerced_self = None
2244 arg_tuple = None
2245 wrapper_call = False
2246 has_optional_args = False
2248 def compile_time_value(self, denv):
2249 function = self.function.compile_time_value(denv)
2250 args = [arg.compile_time_value(denv) for arg in self.args]
2251 try:
2252 return function(*args)
2253 except Exception, e:
2254 self.compile_time_value_error(e)
2256 def analyse_as_type(self, env):
2257 attr = self.function.as_cython_attribute()
2258 if attr == 'pointer':
2259 if len(self.args) != 1:
2260 error(self.args.pos, "only one type allowed.")
2261 else:
2262 type = self.args[0].analyse_as_type(env)
2263 if not type:
2264 error(self.args[0].pos, "Unknown type")
2265 else:
2266 return PyrexTypes.CPtrType(type)
2268 def explicit_args_kwds(self):
2269 return self.args, None
2271 def analyse_types(self, env):
2272 if self.analyse_as_type_constructor(env):
2273 return
2274 function = self.function
2275 function.is_called = 1
2276 self.function.analyse_types(env)
2277 if function.is_attribute and function.is_py_attr and \
2278 function.attribute == "append" and len(self.args) == 1:
2279 # L.append(x) is almost always applied to a list
2280 self.py_func = self.function
2281 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2282 self.function.analyse_types(env)
2283 self.self = self.py_func.obj
2284 function.obj = CloneNode(self.self)
2285 env.use_utility_code(append_utility_code)
2286 if function.is_attribute and function.entry and function.entry.is_cmethod:
2287 # Take ownership of the object from which the attribute
2288 # was obtained, because we need to pass it as 'self'.
2289 self.self = function.obj
2290 function.obj = CloneNode(self.self)
2291 func_type = self.function_type()
2292 if func_type.is_pyobject:
2293 self.arg_tuple = TupleNode(self.pos, args = self.args)
2294 self.arg_tuple.analyse_types(env)
2295 self.args = None
2296 self.type = py_object_type
2297 self.gil_check(env)
2298 self.is_temp = 1
2299 else:
2300 for arg in self.args:
2301 arg.analyse_types(env)
2302 if self.self and func_type.args:
2303 # Coerce 'self' to the type expected by the method.
2304 expected_type = func_type.args[0].type
2305 self.coerced_self = CloneNode(self.self).coerce_to(
2306 expected_type, env)
2307 # Insert coerced 'self' argument into argument list.
2308 self.args.insert(0, self.coerced_self)
2309 self.analyse_c_function_call(env)
2311 def function_type(self):
2312 # Return the type of the function being called, coercing a function
2313 # pointer to a function if necessary.
2314 func_type = self.function.type
2315 if func_type.is_ptr:
2316 func_type = func_type.base_type
2317 return func_type
2319 def analyse_c_function_call(self, env):
2320 func_type = self.function_type()
2321 # Check function type
2322 if not func_type.is_cfunction:
2323 if not func_type.is_error:
2324 error(self.pos, "Calling non-function type '%s'" %
2325 func_type)
2326 self.type = PyrexTypes.error_type
2327 self.result_code = "<error>"
2328 return
2329 # Check no. of args
2330 max_nargs = len(func_type.args)
2331 expected_nargs = max_nargs - func_type.optional_arg_count
2332 actual_nargs = len(self.args)
2333 if actual_nargs < expected_nargs \
2334 or (not func_type.has_varargs and actual_nargs > max_nargs):
2335 expected_str = str(expected_nargs)
2336 if func_type.has_varargs:
2337 expected_str = "at least " + expected_str
2338 elif func_type.optional_arg_count:
2339 if actual_nargs < max_nargs:
2340 expected_str = "at least " + expected_str
2341 else:
2342 expected_str = "at most " + str(max_nargs)
2343 error(self.pos,
2344 "Call with wrong number of arguments (expected %s, got %s)"
2345 % (expected_str, actual_nargs))
2346 self.args = None
2347 self.type = PyrexTypes.error_type
2348 self.result_code = "<error>"
2349 return
2350 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2351 self.has_optional_args = 1
2352 self.is_temp = 1
2353 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2354 env.release_temp(self.opt_arg_struct)
2355 # Coerce arguments
2356 for i in range(min(max_nargs, actual_nargs)):
2357 formal_type = func_type.args[i].type
2358 self.args[i] = self.args[i].coerce_to(formal_type, env)
2359 for i in range(max_nargs, actual_nargs):
2360 if self.args[i].type.is_pyobject:
2361 error(self.args[i].pos,
2362 "Python object cannot be passed as a varargs parameter")
2363 # Calc result type and code fragment
2364 self.type = func_type.return_type
2365 if self.type.is_pyobject:
2366 self.result_ctype = py_object_type
2367 self.is_temp = 1
2368 elif func_type.exception_value is not None \
2369 or func_type.exception_check:
2370 self.is_temp = 1
2371 # C++ exception handler
2372 if func_type.exception_check == '+':
2373 if func_type.exception_value is None:
2374 env.use_utility_code(cpp_exception_utility_code)
2375 # Check gil
2376 if not func_type.nogil:
2377 self.gil_check(env)
2379 def calculate_result_code(self):
2380 return self.c_call_code()
2382 def c_call_code(self):
2383 func_type = self.function_type()
2384 if self.args is None or not func_type.is_cfunction:
2385 return "<error>"
2386 formal_args = func_type.args
2387 arg_list_code = []
2388 args = zip(formal_args, self.args)
2389 max_nargs = len(func_type.args)
2390 expected_nargs = max_nargs - func_type.optional_arg_count
2391 actual_nargs = len(self.args)
2392 for formal_arg, actual_arg in args[:expected_nargs]:
2393 arg_code = actual_arg.result_as(formal_arg.type)
2394 arg_list_code.append(arg_code)
2396 if func_type.is_overridable:
2397 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2399 if func_type.optional_arg_count:
2400 if expected_nargs == actual_nargs:
2401 optional_args = 'NULL'
2402 else:
2403 optional_args = "&%s" % self.opt_arg_struct
2404 arg_list_code.append(optional_args)
2406 for actual_arg in self.args[len(formal_args):]:
2407 arg_list_code.append(actual_arg.result())
2408 result = "%s(%s)" % (self.function.result(),
2409 ', '.join(arg_list_code))
2410 # if self.wrapper_call or \
2411 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2412 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2413 return result
2415 def generate_result_code(self, code):
2416 func_type = self.function_type()
2417 if func_type.is_pyobject:
2418 arg_code = self.arg_tuple.py_result()
2419 code.putln(
2420 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2421 self.result(),
2422 self.function.py_result(),
2423 arg_code,
2424 code.error_goto_if_null(self.result(), self.pos)))
2425 code.put_gotref(self.py_result())
2426 elif func_type.is_cfunction:
2427 if self.has_optional_args:
2428 actual_nargs = len(self.args)
2429 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2430 code.putln("%s.%s = %s;" % (
2431 self.opt_arg_struct,
2432 Naming.pyrex_prefix + "n",
2433 len(self.args) - expected_nargs))
2434 args = zip(func_type.args, self.args)
2435 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2436 code.putln("%s.%s = %s;" % (
2437 self.opt_arg_struct,
2438 formal_arg.name,
2439 actual_arg.result_as(formal_arg.type)))
2440 exc_checks = []
2441 if self.type.is_pyobject:
2442 exc_checks.append("!%s" % self.result())
2443 else:
2444 exc_val = func_type.exception_value
2445 exc_check = func_type.exception_check
2446 if exc_val is not None:
2447 exc_checks.append("%s == %s" % (self.result(), exc_val))
2448 if exc_check:
2449 exc_checks.append("PyErr_Occurred()")
2450 if self.is_temp or exc_checks:
2451 rhs = self.c_call_code()
2452 if self.result():
2453 lhs = "%s = " % self.result()
2454 if self.is_temp and self.type.is_pyobject:
2455 #return_type = self.type # func_type.return_type
2456 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2457 # "from", return_type, "to pyobject" ###
2458 rhs = typecast(py_object_type, self.type, rhs)
2459 else:
2460 lhs = ""
2461 if func_type.exception_check == '+':
2462 if func_type.exception_value is None:
2463 raise_py_exception = "__Pyx_CppExn2PyErr()"
2464 elif func_type.exception_value.type.is_pyobject:
2465 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2466 else:
2467 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2468 code.putln(
2469 "try {%s%s;} catch(...) {%s; %s}" % (
2470 lhs,
2471 rhs,
2472 raise_py_exception,
2473 code.error_goto(self.pos)))
2474 else:
2475 if exc_checks:
2476 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2477 else:
2478 goto_error = ""
2479 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2480 if self.type.is_pyobject and self.result():
2481 code.put_gotref(self.py_result())
2484 class GeneralCallNode(CallNode):
2485 # General Python function call, including keyword,
2486 # * and ** arguments.
2487 #
2488 # function ExprNode
2489 # positional_args ExprNode Tuple of positional arguments
2490 # keyword_args ExprNode or None Dict of keyword arguments
2491 # starstar_arg ExprNode or None Dict of extra keyword args
2493 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2495 def compile_time_value(self, denv):
2496 function = self.function.compile_time_value(denv)
2497 positional_args = self.positional_args.compile_time_value(denv)
2498 keyword_args = self.keyword_args.compile_time_value(denv)
2499 starstar_arg = self.starstar_arg.compile_time_value(denv)
2500 try:
2501 keyword_args.update(starstar_arg)
2502 return function(*positional_args, **keyword_args)
2503 except Exception, e:
2504 self.compile_time_value_error(e)
2506 def explicit_args_kwds(self):
2507 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2508 raise PostParseError(self.pos,
2509 'Compile-time keyword arguments must be explicit.')
2510 return self.positional_args.args, self.keyword_args
2512 def analyse_types(self, env):
2513 if self.analyse_as_type_constructor(env):
2514 return
2515 self.function.analyse_types(env)
2516 self.positional_args.analyse_types(env)
2517 if self.keyword_args:
2518 self.keyword_args.analyse_types(env)
2519 if self.starstar_arg:
2520 self.starstar_arg.analyse_types(env)
2521 self.function = self.function.coerce_to_pyobject(env)
2522 self.positional_args = \
2523 self.positional_args.coerce_to_pyobject(env)
2524 if self.starstar_arg:
2525 self.starstar_arg = \
2526 self.starstar_arg.coerce_to_pyobject(env)
2527 self.type = py_object_type
2528 self.gil_check(env)
2529 self.is_temp = 1
2531 def generate_result_code(self, code):
2532 if self.keyword_args and self.starstar_arg:
2533 code.put_error_if_neg(self.pos,
2534 "PyDict_Update(%s, %s)" % (
2535 self.keyword_args.py_result(),
2536 self.starstar_arg.py_result()))
2537 keyword_code = self.keyword_args.py_result()
2538 elif self.keyword_args:
2539 keyword_code = self.keyword_args.py_result()
2540 elif self.starstar_arg:
2541 keyword_code = self.starstar_arg.py_result()
2542 else:
2543 keyword_code = None
2544 if not keyword_code:
2545 call_code = "PyObject_Call(%s, %s, NULL)" % (
2546 self.function.py_result(),
2547 self.positional_args.py_result())
2548 else:
2549 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2550 self.function.py_result(),
2551 self.positional_args.py_result(),
2552 keyword_code)
2553 code.putln(
2554 "%s = %s; %s" % (
2555 self.result(),
2556 call_code,
2557 code.error_goto_if_null(self.result(), self.pos)))
2558 code.put_gotref(self.py_result())
2561 class AsTupleNode(ExprNode):
2562 # Convert argument to tuple. Used for normalising
2563 # the * argument of a function call.
2564 #
2565 # arg ExprNode
2567 subexprs = ['arg']
2569 def calculate_constant_result(self):
2570 self.constant_result = tuple(self.base.constant_result)
2572 def compile_time_value(self, denv):
2573 arg = self.arg.compile_time_value(denv)
2574 try:
2575 return tuple(arg)
2576 except Exception, e:
2577 self.compile_time_value_error(e)
2579 def analyse_types(self, env):
2580 self.arg.analyse_types(env)
2581 self.arg = self.arg.coerce_to_pyobject(env)
2582 self.type = tuple_type
2583 self.gil_check(env)
2584 self.is_temp = 1
2586 gil_message = "Constructing Python tuple"
2588 def generate_result_code(self, code):
2589 code.putln(
2590 "%s = PySequence_Tuple(%s); %s" % (
2591 self.result(),
2592 self.arg.py_result(),
2593 code.error_goto_if_null(self.result(), self.pos)))
2594 code.put_gotref(self.py_result())
2597 class AttributeNode(NewTempExprNode):
2598 # obj.attribute
2599 #
2600 # obj ExprNode
2601 # attribute string
2602 # needs_none_check boolean Used if obj is an extension type.
2603 # If set to True, it is known that the type is not None.
2604 #
2605 # Used internally:
2606 #
2607 # is_py_attr boolean Is a Python getattr operation
2608 # member string C name of struct member
2609 # is_called boolean Function call is being done on result
2610 # entry Entry Symbol table entry of attribute
2611 # interned_attr_cname string C name of interned attribute name
2613 is_attribute = 1
2614 subexprs = ['obj']
2616 type = PyrexTypes.error_type
2617 entry = None
2618 is_called = 0
2619 needs_none_check = True
2621 def as_cython_attribute(self):
2622 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2623 return self.attribute
2625 def coerce_to(self, dst_type, env):
2626 # If coercing to a generic pyobject and this is a cpdef function
2627 # we can create the corresponding attribute
2628 if dst_type is py_object_type:
2629 entry = self.entry
2630 if entry and entry.is_cfunction and entry.as_variable:
2631 # must be a cpdef function
2632 self.is_temp = 1
2633 self.entry = entry.as_variable
2634 self.analyse_as_python_attribute(env)
2635 return self
2636 return ExprNode.coerce_to(self, dst_type, env)
2638 def calculate_constant_result(self):
2639 attr = self.attribute
2640 if attr.startswith("__") and attr.endswith("__"):
2641 return
2642 self.constant_result = getattr(self.obj.constant_result, attr)
2644 def compile_time_value(self, denv):
2645 attr = self.attribute
2646 if attr.startswith("__") and attr.endswith("__"):
2647 self.error("Invalid attribute name '%s' in compile-time expression"
2648 % attr)
2649 return None
2650 obj = self.obj.compile_time_value(denv)
2651 try:
2652 return getattr(obj, attr)
2653 except Exception, e:
2654 self.compile_time_value_error(e)
2656 def analyse_target_declaration(self, env):
2657 pass
2659 def analyse_target_types(self, env):
2660 self.analyse_types(env, target = 1)
2662 def analyse_types(self, env, target = 0):
2663 if self.analyse_as_cimported_attribute(env, target):
2664 return
2665 if not target and self.analyse_as_unbound_cmethod(env):
2666 return
2667 self.analyse_as_ordinary_attribute(env, target)
2669 def analyse_as_cimported_attribute(self, env, target):
2670 # Try to interpret this as a reference to an imported
2671 # C const, type, var or function. If successful, mutates
2672 # this node into a NameNode and returns 1, otherwise
2673 # returns 0.
2674 module_scope = self.obj.analyse_as_module(env)
2675 if module_scope:
2676 entry = module_scope.lookup_here(self.attribute)
2677 if entry and (
2678 entry.is_cglobal or entry.is_cfunction
2679 or entry.is_type or entry.is_const):
2680 self.mutate_into_name_node(env, entry, target)
2681 return 1
2682 return 0
2684 def analyse_as_unbound_cmethod(self, env):
2685 # Try to interpret this as a reference to an unbound
2686 # C method of an extension type. If successful, mutates
2687 # this node into a NameNode and returns 1, otherwise
2688 # returns 0.
2689 type = self.obj.analyse_as_extension_type(env)
2690 if type:
2691 entry = type.scope.lookup_here(self.attribute)
2692 if entry and entry.is_cmethod:
2693 # Create a temporary entry describing the C method
2694 # as an ordinary function.
2695 ubcm_entry = Symtab.Entry(entry.name,
2696 "%s->%s" % (type.vtabptr_cname, entry.cname),
2697 entry.type)
2698 ubcm_entry.is_cfunction = 1
2699 ubcm_entry.func_cname = entry.func_cname
2700 ubcm_entry.is_unbound_cmethod = 1
2701 self.mutate_into_name_node(env, ubcm_entry, None)
2702 return 1
2703 return 0
2705 def analyse_as_type(self, env):
2706 module_scope = self.obj.analyse_as_module(env)
2707 if module_scope:
2708 return module_scope.lookup_type(self.attribute)
2709 return None
2711 def analyse_as_extension_type(self, env):
2712 # Try to interpret this as a reference to an extension type
2713 # in a cimported module. Returns the extension type, or None.
2714 module_scope = self.obj.analyse_as_module(env)
2715 if module_scope:
2716 entry = module_scope.lookup_here(self.attribute)
2717 if entry and entry.is_type and entry.type.is_extension_type:
2718 return entry.type
2719 return None
2721 def analyse_as_module(self, env):
2722 # Try to interpret this as a reference to a cimported module
2723 # in another cimported module. Returns the module scope, or None.
2724 module_scope = self.obj.analyse_as_module(env)
2725 if module_scope:
2726 entry = module_scope.lookup_here(self.attribute)
2727 if entry and entry.as_module:
2728 return entry.as_module
2729 return None
2731 def mutate_into_name_node(self, env, entry, target):
2732 # Mutate this node into a NameNode and complete the
2733 # analyse_types phase.
2734 self.__class__ = NameNode
2735 self.name = self.attribute
2736 self.entry = entry
2737 del self.obj
2738 del self.attribute
2739 if target:
2740 NameNode.analyse_target_types(self, env)
2741 else:
2742 NameNode.analyse_rvalue_entry(self, env)
2744 def analyse_as_ordinary_attribute(self, env, target):
2745 self.obj.analyse_types(env)
2746 self.analyse_attribute(env)
2747 if self.entry and self.entry.is_cmethod and not self.is_called:
2748 # error(self.pos, "C method can only be called")
2749 pass
2750 ## Reference to C array turns into pointer to first element.
2751 #while self.type.is_array:
2752 # self.type = self.type.element_ptr_type()
2753 if self.is_py_attr:
2754 if not target:
2755 self.is_temp = 1
2756 self.result_ctype = py_object_type
2758 def analyse_attribute(self, env):
2759 # Look up attribute and set self.type and self.member.
2760 self.is_py_attr = 0
2761 self.member = self.attribute
2762 if self.obj.type.is_string:
2763 self.obj = self.obj.coerce_to_pyobject(env)
2764 obj_type = self.obj.type
2765 if obj_type.is_ptr or obj_type.is_array:
2766 obj_type = obj_type.base_type
2767 self.op = "->"
2768 elif obj_type.is_extension_type:
2769 self.op = "->"
2770 else:
2771 self.op = "."
2772 if obj_type.has_attributes:
2773 entry = None
2774 if obj_type.attributes_known():
2775 entry = obj_type.scope.lookup_here(self.attribute)
2776 if entry and entry.is_member:
2777 entry = None
2778 else:
2779 error(self.pos,
2780 "Cannot select attribute of incomplete type '%s'"
2781 % obj_type)
2782 self.type = PyrexTypes.error_type
2783 return
2784 self.entry = entry
2785 if entry:
2786 if obj_type.is_extension_type and entry.name == "__weakref__":
2787 error(self.pos, "Illegal use of special attribute __weakref__")
2788 # methods need the normal attribute lookup
2789 # because they do not have struct entries
2790 if entry.is_variable or entry.is_cmethod:
2791 self.type = entry.type
2792 self.member = entry.cname
2793 return
2794 else:
2795 # If it's not a variable or C method, it must be a Python
2796 # method of an extension type, so we treat it like a Python
2797 # attribute.
2798 pass
2799 # If we get here, the base object is not a struct/union/extension
2800 # type, or it is an extension type and the attribute is either not
2801 # declared or is declared as a Python method. Treat it as a Python
2802 # attribute reference.
2803 self.analyse_as_python_attribute(env)
2805 def analyse_as_python_attribute(self, env):
2806 obj_type = self.obj.type
2807 self.member = self.attribute
2808 if obj_type.is_pyobject:
2809 self.type = py_object_type
2810 self.is_py_attr = 1
2811 self.interned_attr_cname = env.intern_identifier(self.attribute)
2812 self.gil_check(env)
2813 else:
2814 if not obj_type.is_error:
2815 error(self.pos,
2816 "Object of type '%s' has no attribute '%s'" %
2817 (obj_type, self.attribute))
2819 gil_message = "Accessing Python attribute"
2821 def is_simple(self):
2822 if self.obj:
2823 return self.result_in_temp() or self.obj.is_simple()
2824 else:
2825 return NameNode.is_simple(self)
2827 def is_lvalue(self):
2828 if self.obj:
2829 return 1
2830 else:
2831 return NameNode.is_lvalue(self)
2833 def is_ephemeral(self):
2834 if self.obj:
2835 return self.obj.is_ephemeral()
2836 else:
2837 return NameNode.is_ephemeral(self)
2839 def calculate_result_code(self):
2840 #print "AttributeNode.calculate_result_code:", self.member ###
2841 #print "...obj node =", self.obj, "code", self.obj.result() ###
2842 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2843 obj = self.obj
2844 obj_code = obj.result_as(obj.type)
2845 #print "...obj_code =", obj_code ###
2846 if self.entry and self.entry.is_cmethod:
2847 if obj.type.is_extension_type:
2848 return "((struct %s *)%s%s%s)->%s" % (
2849 obj.type.vtabstruct_cname, obj_code, self.op,
2850 obj.type.vtabslot_cname, self.member)
2851 else:
2852 return self.member
2853 else:
2854 return "%s%s%s" % (obj_code, self.op, self.member)
2856 def generate_result_code(self, code):
2857 if self.is_py_attr:
2858 code.putln(
2859 '%s = PyObject_GetAttr(%s, %s); %s' % (
2860 self.result(),
2861 self.obj.py_result(),
2862 self.interned_attr_cname,
2863 code.error_goto_if_null(self.result(), self.pos)))
2864 code.put_gotref(self.py_result())
2865 else:
2866 # result_code contains what is needed, but we may need to insert
2867 # a check and raise an exception
2868 if (self.obj.type.is_extension_type
2869 and self.needs_none_check
2870 and code.globalstate.directives['nonecheck']):
2871 self.put_nonecheck(code)
2873 def generate_assignment_code(self, rhs, code):
2874 self.obj.generate_evaluation_code(code)
2875 if self.is_py_attr:
2876 code.put_error_if_neg(self.pos,
2877 'PyObject_SetAttr(%s, %s, %s)' % (
2878 self.obj.py_result(),
2879 self.interned_attr_cname,
2880 rhs.py_result()))
2881 rhs.generate_disposal_code(code)
2882 rhs.free_temps(code)
2883 else:
2884 if (self.obj.type.is_extension_type
2885 and self.needs_none_check
2886 and code.globalstate.directives['nonecheck']):
2887 self.put_nonecheck(code)
2889 select_code = self.result()
2890 if self.type.is_pyobject:
2891 rhs.make_owned_reference(code)
2892 code.put_giveref(rhs.py_result())
2893 code.put_gotref(select_code)
2894 code.put_decref(select_code, self.ctype())
2895 code.putln(
2896 "%s = %s;" % (
2897 select_code,
2898 rhs.result_as(self.ctype())))
2899 #rhs.result()))
2900 rhs.generate_post_assignment_code(code)
2901 rhs.free_temps(code)
2902 self.obj.generate_disposal_code(code)
2903 self.obj.free_temps(code)
2905 def generate_deletion_code(self, code):
2906 self.obj.generate_evaluation_code(code)
2907 if self.is_py_attr:
2908 code.put_error_if_neg(self.pos,
2909 'PyObject_DelAttr(%s, %s)' % (
2910 self.obj.py_result(),
2911 self.interned_attr_cname))
2912 else:
2913 error(self.pos, "Cannot delete C attribute of extension type")
2914 self.obj.generate_disposal_code(code)
2915 self.obj.free_temps(code)
2917 def annotate(self, code):
2918 if self.is_py_attr:
2919 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2920 else:
2921 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2923 def put_nonecheck(self, code):
2924 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2925 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2926 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2927 code.putln(code.error_goto(self.pos))
2928 code.putln("}")
2931 #-------------------------------------------------------------------
2932 #
2933 # Constructor nodes
2934 #
2935 #-------------------------------------------------------------------
2937 class SequenceNode(NewTempExprNode):
2938 # Base class for list and tuple constructor nodes.
2939 # Contains common code for performing sequence unpacking.
2940 #
2941 # args [ExprNode]
2942 # iterator ExprNode
2943 # unpacked_items [ExprNode] or None
2944 # coerced_unpacked_items [ExprNode] or None
2946 subexprs = ['args']
2948 is_sequence_constructor = 1
2949 unpacked_items = None
2951 def compile_time_value_list(self, denv):
2952 return [arg.compile_time_value(denv) for arg in self.args]
2954 def analyse_target_declaration(self, env):
2955 for arg in self.args:
2956 arg.analyse_target_declaration(env)
2958 def analyse_types(self, env, skip_children=False):
2959 for i in range(len(self.args)):
2960 arg = self.args[i]
2961 if not skip_children: arg.analyse_types(env)
2962 self.args[i] = arg.coerce_to_pyobject(env)
2963 self.type = py_object_type
2964 self.gil_check(env)
2965 self.is_temp = 1
2967 def analyse_target_types(self, env):
2968 self.iterator = PyTempNode(self.pos, env)
2969 self.unpacked_items = []
2970 self.coerced_unpacked_items = []
2971 for arg in self.args:
2972 arg.analyse_target_types(env)
2973 unpacked_item = PyTempNode(self.pos, env)
2974 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2975 self.unpacked_items.append(unpacked_item)
2976 self.coerced_unpacked_items.append(coerced_unpacked_item)
2977 self.type = py_object_type
2978 env.use_utility_code(unpacking_utility_code)
2980 def allocate_target_temps(self, env, rhs):
2981 self.iterator.allocate_temps(env)
2982 for arg, node in zip(self.args, self.coerced_unpacked_items):
2983 node.allocate_temps(env)
2984 arg.allocate_target_temps(env, None)
2985 #arg.release_target_temp(env)
2986 #node.release_temp(env)
2987 if rhs:
2988 rhs.release_temp(env)
2989 self.iterator.release_temp(env)
2990 for node in self.coerced_unpacked_items:
2991 node.release_temp(env)
2993 # def release_target_temp(self, env):
2994 # #for arg in self.args:
2995 # # arg.release_target_temp(env)
2996 # #for node in self.coerced_unpacked_items:
2997 # # node.release_temp(env)
2998 # self.iterator.release_temp(env)
3000 def generate_result_code(self, code):
3001 self.generate_operation_code(code)
3003 def generate_assignment_code(self, rhs, code):
3004 # Need to work around the fact that generate_evaluation_code
3005 # allocates the temps in a rather hacky way -- the assignment
3006 # is evaluated twice, within each if-block.
3008 code.putln(
3009 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
3010 rhs.py_result(),
3011 rhs.py_result(),
3012 len(self.args)))
3013 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3014 for i in range(len(self.args)):
3015 item = self.unpacked_items[i]
3016 code.put(
3017 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3018 item.result(),
3019 i))
3020 code.put_incref(item.result(), item.ctype())
3021 value_node = self.coerced_unpacked_items[i]
3022 value_node.generate_evaluation_code(code)
3023 rhs.generate_disposal_code(code)
3025 for i in range(len(self.args)):
3026 self.args[i].generate_assignment_code(
3027 self.coerced_unpacked_items[i], code)
3029 code.putln("} else {")
3031 code.putln(
3032 "%s = PyObject_GetIter(%s); %s" % (
3033 self.iterator.result(),
3034 rhs.py_result(),
3035 code.error_goto_if_null(self.iterator.result(), self.pos)))
3036 code.put_gotref(self.iterator.py_result())
3037 rhs.generate_disposal_code(code)
3038 for i in range(len(self.args)):
3039 item = self.unpacked_items[i]
3040 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3041 self.iterator.py_result(), i)
3042 code.putln(
3043 "%s = %s; %s" % (
3044 item.result(),
3045 typecast(item.ctype(), py_object_type, unpack_code),
3046 code.error_goto_if_null(item.result(), self.pos)))
3047 code.put_gotref(item.py_result())
3048 value_node = self.coerced_unpacked_items[i]
3049 value_node.generate_evaluation_code(code)
3050 code.put_error_if_neg(self.pos,
3051 "__Pyx_EndUnpack(%s)" % (
3052 self.iterator.py_result()))
3053 if debug_disposal_code:
3054 print("UnpackNode.generate_assignment_code:")
3055 print("...generating disposal code for %s" % self.iterator)
3056 self.iterator.generate_disposal_code(code)
3057 self.iterator.free_temps(code)
3059 for i in range(len(self.args)):
3060 self.args[i].generate_assignment_code(
3061 self.coerced_unpacked_items[i], code)
3062 code.putln("}")
3063 rhs.free_temps(code)
3065 def annotate(self, code):
3066 for arg in self.args:
3067 arg.annotate(code)
3068 if self.unpacked_items:
3069 for arg in self.unpacked_items:
3070 arg.annotate(code)
3071 for arg in self.coerced_unpacked_items:
3072 arg.annotate(code)
3075 class TupleNode(SequenceNode):
3076 # Tuple constructor.
3078 gil_message = "Constructing Python tuple"
3080 def analyse_types(self, env, skip_children=False):
3081 if len(self.args) == 0:
3082 self.is_temp = 0
3083 self.is_literal = 1
3084 else:
3085 SequenceNode.analyse_types(self, env, skip_children)
3086 self.type = tuple_type
3088 def calculate_result_code(self):
3089 if len(self.args) > 0:
3090 error(self.pos, "Positive length tuples must be constructed.")
3091 else:
3092 return Naming.empty_tuple
3094 def calculate_constant_result(self):
3095 self.constant_result = tuple([
3096 arg.constant_result for arg in self.args])
3098 def compile_time_value(self, denv):
3099 values = self.compile_time_value_list(denv)
3100 try:
3101 return tuple(values)
3102 except Exception, e:
3103 self.compile_time_value_error(e)
3105 def generate_operation_code(self, code):
3106 if len(self.args) == 0:
3107 # result_code is Naming.empty_tuple
3108 return
3109 code.putln(
3110 "%s = PyTuple_New(%s); %s" % (
3111 self.result(),
3112 len(self.args),
3113 code.error_goto_if_null(self.result(), self.pos)))
3114 code.put_gotref(self.py_result())
3115 for i in range(len(self.args)):
3116 arg = self.args[i]
3117 if not arg.result_in_temp():
3118 code.put_incref(arg.result(), arg.ctype())
3119 code.putln(
3120 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3121 self.result(),
3122 i,
3123 arg.py_result()))
3124 code.put_giveref(arg.py_result())
3126 def generate_subexpr_disposal_code(self, code):
3127 # We call generate_post_assignment_code here instead
3128 # of generate_disposal_code, because values were stored
3129 # in the tuple using a reference-stealing operation.
3130 for arg in self.args:
3131 arg.generate_post_assignment_code(code)
3132 # Should NOT call free_temps -- this is invoked by the default
3133 # generate_evaluation_code which will do that.
3136 class ListNode(SequenceNode):
3137 # List constructor.
3139 # obj_conversion_errors [PyrexError] used internally
3140 # orignial_args [ExprNode] used internally
3142 gil_message = "Constructing Python list"
3144 def analyse_expressions(self, env):
3145 SequenceNode.analyse_expressions(self, env)
3146 self.coerce_to_pyobject(env)
3148 def analyse_types(self, env):
3149 hold_errors()
3150 self.original_args = list(self.args)
3151 SequenceNode.analyse_types(self, env)
3152 self.type = list_type
3153 self.obj_conversion_errors = held_errors()
3154 release_errors(ignore=True)
3156 def coerce_to(self, dst_type, env):
3157 if dst_type.is_pyobject:
3158 for err in self.obj_conversion_errors:
3159 report_error(err)
3160 self.obj_conversion_errors = []
3161 if not self.type.subtype_of(dst_type):
3162 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3163 elif dst_type.is_ptr:
3164 base_type = dst_type.base_type
3165 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3166 for i in range(len(self.original_args)):
3167 arg = self.args[i]
3168 if isinstance(arg, CoerceToPyTypeNode):
3169 arg = arg.arg
3170 self.args[i] = arg.coerce_to(base_type, env)
3171 elif dst_type.is_struct:
3172 if len(self.args) > len(dst_type.scope.var_entries):
3173 error(self.pos, "Too may members for '%s'" % dst_type)
3174 else:
3175 if len(self.args) < len(dst_type.scope.var_entries):
3176 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3177 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3178 if isinstance(arg, CoerceToPyTypeNode):
3179 arg = arg.arg
3180 self.args[i] = arg.coerce_to(member.type, env)
3181 self.type = dst_type
3182 else:
3183 self.type = error_type
3184 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3185 return self
3187 def release_temp(self, env):
3188 if self.type.is_array:
3189 # To be valid C++, we must allocate the memory on the stack
3190 # manually and be sure not to reuse it for something else.
3191 pass
3192 else:
3193 SequenceNode.release_temp(self, env)
3195 def calculate_constant_result(self):
3196 self.constant_result = [
3197 arg.constant_result for arg in self.args]
3199 def compile_time_value(self, denv):
3200 return self.compile_time_value_list(denv)
3202 def generate_operation_code(self, code):
3203 if self.type.is_pyobject:
3204 for err in self.obj_conversion_errors:
3205 report_error(err)
3206 code.putln("%s = PyList_New(%s); %s" %
3207 (self.result(),
3208 len(self.args),
3209 code.error_goto_if_null(self.result(), self.pos)))
3210 code.put_gotref(self.py_result())
3211 for i in range(len(self.args)):
3212 arg = self.args[i]
3213 #if not arg.is_temp:
3214 if not arg.result_in_temp():
3215 code.put_incref(arg.result(), arg.ctype())
3216 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3217 (self.result(),
3218 i,
3219 arg.py_result()))
3220 code.put_giveref(arg.py_result())
3221 elif self.type.is_array:
3222 for i, arg in enumerate(self.args):
3223 code.putln("%s[%s] = %s;" % (
3224 self.result(),
3225 i,
3226 arg.result()))
3227 elif self.type.is_struct:
3228 for arg, member in zip(self.args, self.type.scope.var_entries):
3229 code.putln("%s.%s = %s;" % (
3230 self.result(),
3231 member.cname,
3232 arg.result()))
3233 else:
3234 raise InternalError("List type never specified")
3236 def generate_subexpr_disposal_code(self, code):
3237 # We call generate_post_assignment_code here instead
3238 # of generate_disposal_code, because values were stored
3239 # in the list using a reference-stealing operation.
3240 for arg in self.args:
3241 arg.generate_post_assignment_code(code)
3242 # Should NOT call free_temps -- this is invoked by the default
3243 # generate_evaluation_code which will do that.
3246 class ComprehensionNode(NewTempExprNode):
3247 subexprs = ["target"]
3248 child_attrs = ["loop", "append"]
3250 def analyse_types(self, env):
3251 self.target.analyse_expressions(env)
3252 self.type = self.target.type
3253 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3254 self.loop.analyse_declarations(env)
3256 def allocate_temps(self, env, result = None):
3257 if debug_temp_alloc:
3258 print("%s Allocating temps" % self)
3259 self.allocate_temp(env, result)
3260 # call loop.analyse_expressions() now to make sure temps get
3261 # allocated at the right time
3262 self.loop.analyse_expressions(env)
3264 def calculate_result_code(self):
3265 return self.target.result()
3267 def generate_result_code(self, code):
3268 self.generate_operation_code(code)
3270 def generate_operation_code(self, code):
3271 self.loop.generate_execution_code(code)
3273 def annotate(self, code):
3274 self.loop.annotate(code)
3277 class ComprehensionAppendNode(NewTempExprNode):
3278 # Need to be careful to avoid infinite recursion:
3279 # target must not be in child_attrs/subexprs
3280 subexprs = ['expr']
3282 def analyse_types(self, env):
3283 self.expr.analyse_types(env)
3284 if not self.expr.type.is_pyobject:
3285 self.expr = self.expr.coerce_to_pyobject(env)
3286 self.type = PyrexTypes.c_int_type
3287 self.is_temp = 1
3289 def generate_result_code(self, code):
3290 if self.target.type is list_type:
3291 function = "PyList_Append"
3292 elif self.target.type is set_type:
3293 function = "PySet_Add"
3294 else:
3295 raise InternalError(
3296 "Invalid type for comprehension node: %s" % self.target.type)
3298 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3299 (self.result(),
3300 function,
3301 self.target.result(),
3302 self.expr.result(),
3303 code.error_goto_if(self.result(), self.pos)))
3305 class DictComprehensionAppendNode(ComprehensionAppendNode):
3306 subexprs = ['key_expr', 'value_expr']
3308 def analyse_types(self, env):
3309 self.key_expr.analyse_types(env)
3310 if not self.key_expr.type.is_pyobject:
3311 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3312 self.value_expr.analyse_types(env)
3313 if not self.value_expr.type.is_pyobject:
3314 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3315 self.type = PyrexTypes.c_int_type
3316 self.is_temp = 1
3318 def generate_result_code(self, code):
3319 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3320 (self.result(),
3321 self.target.result(),
3322 self.key_expr.result(),
3323 self.value_expr.result(),
3324 code.error_goto_if(self.result(), self.pos)))
3327 class SetNode(NewTempExprNode):
3328 # Set constructor.
3330 subexprs = ['args']
3332 gil_message = "Constructing Python set"
3334 def analyse_types(self, env):
3335 for i in range(len(self.args)):
3336 arg = self.args[i]
3337 arg.analyse_types(env)
3338 self.args[i] = arg.coerce_to_pyobject(env)
3339 self.type = set_type
3340 self.gil_check(env)
3341 self.is_temp = 1
3343 def calculate_constant_result(self):
3344 self.constant_result = set([
3345 arg.constant_result for arg in self.args])
3347 def compile_time_value(self, denv):
3348 values = [arg.compile_time_value(denv) for arg in self.args]
3349 try:
3350 return set(values)
3351 except Exception, e:
3352 self.compile_time_value_error(e)
3354 def generate_evaluation_code(self, code):
3355 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3356 self.allocate_temp_result(code)
3357 code.putln(
3358 "%s = PySet_New(0); %s" % (
3359 self.result(),
3360 code.error_goto_if_null(self.result(), self.pos)))
3361 code.put_gotref(self.py_result())
3362 for arg in self.args:
3363 arg.generate_evaluation_code(code)
3364 code.putln(
3365 code.error_goto_if_neg(
3366 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3367 self.pos))
3368 arg.generate_disposal_code(code)
3369 arg.free_temps(code)
3372 class DictNode(ExprNode):
3373 # Dictionary constructor.
3374 #
3375 # key_value_pairs [DictItemNode]
3376 #
3377 # obj_conversion_errors [PyrexError] used internally
3379 subexprs = ['key_value_pairs']
3381 def calculate_constant_result(self):
3382 self.constant_result = dict([
3383 item.constant_result for item in self.key_value_pairs])
3385 def compile_time_value(self, denv):
3386 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3387 for item in self.key_value_pairs]
3388 try:
3389 return dict(pairs)
3390 except Exception, e:
3391 self.compile_time_value_error(e)
3393 def analyse_types(self, env):
3394 hold_errors()
3395 self.type = dict_type
3396 for item in self.key_value_pairs:
3397 item.analyse_types(env)
3398 self.gil_check(env)
3399 self.obj_conversion_errors = held_errors()
3400 release_errors(ignore=True)
3401 self.is_temp = 1
3403 def coerce_to(self, dst_type, env):
3404 if dst_type.is_pyobject:
3405 self.release_errors()
3406 if not self.type.subtype_of(dst_type):
3407 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3408 elif dst_type.is_struct_or_union:
3409 self.type = dst_type
3410 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3411 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3412 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3413 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3414 for item in self.key_value_pairs:
3415 if isinstance(item.key, CoerceToPyTypeNode):
3416 item.key = item.key.arg
3417 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3418 error(item.key.pos, "Invalid struct field identifier")
3419 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3420 else:
3421 member = dst_type.scope.lookup_here(item.key.value)
3422 if not member:
3423 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3424 else:
3425 value = item.value
3426 if isinstance(value, CoerceToPyTypeNode):
3427 value = value.arg
3428 item.value = value.coerce_to(member.type, env)
3429 else:
3430 self.type = error_type
3431 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3432 return self
3434 def release_errors(self):
3435 for err in self.obj_conversion_errors:
3436 report_error(err)
3437 self.obj_conversion_errors = []
3439 gil_message = "Constructing Python dict"
3441 def allocate_temps(self, env, result = None):
3442 # Custom method used here because key-value
3443 # pairs are evaluated and used one at a time.
3444 self.allocate_temp(env, result)
3445 for item in self.key_value_pairs:
3446 item.key.allocate_temps(env)
3447 item.value.allocate_temps(env)
3448 item.key.release_temp(env)
3449 item.value.release_temp(env)
3451 def generate_evaluation_code(self, code):
3452 # Custom method used here because key-value
3453 # pairs are evaluated and used one at a time.
3454 if self.type.is_pyobject:
3455 self.release_errors()
3456 code.putln(
3457 "%s = PyDict_New(); %s" % (
3458 self.result(),
3459 code.error_goto_if_null(self.result(), self.pos)))
3460 code.put_gotref(self.py_result())
3461 for item in self.key_value_pairs:
3462 item.generate_evaluation_code(code)
3463 if self.type.is_pyobject:
3464 code.put_error_if_neg(self.pos,
3465 "PyDict_SetItem(%s, %s, %s)" % (
3466 self.result(),
3467 item.key.py_result(),
3468 item.value.py_result()))
3469 else:
3470 code.putln("%s.%s = %s;" % (
3471 self.result(),
3472 item.key.value,
3473 item.value.result()))
3474 item.generate_disposal_code(code)
3475 item.free_temps(code)
3477 def annotate(self, code):
3478 for item in self.key_value_pairs:
3479 item.annotate(code)
3481 class DictItemNode(ExprNode):
3482 # Represents a single item in a DictNode
3483 #
3484 # key ExprNode
3485 # value ExprNode
3486 subexprs = ['key', 'value']
3488 def calculate_constant_result(self):
3489 self.constant_result = (
3490 self.key.constant_result, self.value.constant_result)
3492 def analyse_types(self, env):
3493 self.key.analyse_types(env)
3494 self.value.analyse_types(env)
3495 self.key = self.key.coerce_to_pyobject(env)
3496 self.value = self.value.coerce_to_pyobject(env)
3498 def generate_evaluation_code(self, code):
3499 self.key.generate_evaluation_code(code)
3500 self.value.generate_evaluation_code(code)
3502 def generate_disposal_code(self, code):
3503 self.key.generate_disposal_code(code)
3504 self.value.generate_disposal_code(code)
3506 def free_temps(self, code):
3507 self.key.free_temps(code)
3508 self.value.free_temps(code)
3510 def __iter__(self):
3511 return iter([self.key, self.value])
3514 class ClassNode(ExprNode):
3515 # Helper class used in the implementation of Python
3516 # class definitions. Constructs a class object given
3517 # a name, tuple of bases and class dictionary.
3518 #
3519 # name EncodedString Name of the class
3520 # cname string Class name as a Python string
3521 # bases ExprNode Base class tuple
3522 # dict ExprNode Class dict (not owned by this node)
3523 # doc ExprNode or None Doc string
3524 # module_name string Name of defining module
3526 subexprs = ['bases', 'doc']
3528 def analyse_types(self, env):
3529 self.cname = env.intern_identifier(self.name)
3530 self.bases.analyse_types(env)
3531 if self.doc:
3532 self.doc.analyse_types(env)
3533 self.doc = self.doc.coerce_to_pyobject(env)
3534 self.module_name = env.global_scope().qualified_name
3535 self.type = py_object_type
3536 self.gil_check(env)
3537 self.is_temp = 1
3538 env.use_utility_code(create_class_utility_code);
3540 gil_message = "Constructing Python class"
3542 def generate_result_code(self, code):
3543 if self.doc:
3544 code.put_error_if_neg(self.pos,
3545 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3546 self.dict.py_result(),
3547 self.doc.py_result()))
3548 code.putln(
3549 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3550 self.result(),
3551 self.bases.py_result(),
3552 self.dict.py_result(),
3553 self.cname,
3554 self.module_name,
3555 code.error_goto_if_null(self.result(), self.pos)))
3556 code.put_gotref(self.py_result())
3559 class UnboundMethodNode(ExprNode):
3560 # Helper class used in the implementation of Python
3561 # class definitions. Constructs an unbound method
3562 # object from a class and a function.
3563 #
3564 # class_cname string C var holding the class object
3565 # function ExprNode Function object
3567 subexprs = ['function']
3569 def analyse_types(self, env):
3570 self.function.analyse_types(env)
3571 self.type = py_object_type
3572 self.gil_check(env)
3573 self.is_temp = 1
3575 gil_message = "Constructing an unbound method"
3577 def generate_result_code(self, code):
3578 code.putln(
3579 "%s = PyMethod_New(%s, 0, %s); %s" % (
3580 self.result(),
3581 self.function.py_result(),
3582 self.class_cname,
3583 code.error_goto_if_null(self.result(), self.pos)))
3584 code.put_gotref(self.py_result())
3586 class PyCFunctionNode(AtomicNewTempExprNode):
3587 # Helper class used in the implementation of Python
3588 # class definitions. Constructs a PyCFunction object
3589 # from a PyMethodDef struct.
3590 #
3591 # pymethdef_cname string PyMethodDef structure
3593 def analyse_types(self, env):
3594 self.type = py_object_type
3595 self.gil_check(env)
3596 self.is_temp = 1
3598 gil_message = "Constructing Python function"
3600 def generate_result_code(self, code):
3601 code.putln(
3602 "%s = PyCFunction_New(&%s, 0); %s" % (
3603 self.result(),
3604 self.pymethdef_cname,
3605 code.error_goto_if_null(self.result(), self.pos)))
3606 code.put_gotref(self.py_result())
3608 #-------------------------------------------------------------------
3609 #
3610 # Unary operator nodes
3611 #
3612 #-------------------------------------------------------------------
3614 compile_time_unary_operators = {
3615 'not': operator.not_,
3616 '~': operator.inv,
3617 '-': operator.neg,
3618 '+': operator.pos,
3619 }
3621 class UnopNode(ExprNode):
3622 # operator string
3623 # operand ExprNode
3624 #
3625 # Processing during analyse_expressions phase:
3626 #
3627 # analyse_c_operation
3628 # Called when the operand is not a pyobject.
3629 # - Check operand type and coerce if needed.
3630 # - Determine result type and result code fragment.
3631 # - Allocate temporary for result if needed.
3633 subexprs = ['operand']
3635 def calculate_constant_result(self):
3636 func = compile_time_unary_operators[self.operator]
3637 self.constant_result = func(self.operand.constant_result)
3639 def compile_time_value(self, denv):
3640 func = compile_time_unary_operators.get(self.operator)
3641 if not func:
3642 error(self.pos,
3643 "Unary '%s' not supported in compile-time expression"
3644 % self.operator)
3645 operand = self.operand.compile_time_value(denv)
3646 try:
3647 return func(operand)
3648 except Exception, e:
3649 self.compile_time_value_error(e)
3651 def analyse_types(self, env):
3652 self.operand.analyse_types(env)
3653 if self.is_py_operation():
3654 self.coerce_operand_to_pyobject(env)
3655 self.type = py_object_type
3656 self.gil_check(env)
3657 self.is_temp = 1
3658 else:
3659 self.analyse_c_operation(env)
3661 def check_const(self):
3662 self.operand.check_const()
3664 def is_py_operation(self):
3665 return self.operand.type.is_pyobject
3667 def coerce_operand_to_pyobject(self, env):
3668 self.operand = self.operand.coerce_to_pyobject(env)
3670 def generate_result_code(self, code):
3671 if self.operand.type.is_pyobject:
3672 self.generate_py_operation_code(code)
3673 else:
3674 if self.is_temp:
3675 self.generate_c_operation_code(code)
3677 def generate_py_operation_code(self, code):
3678 function = self.py_operation_function()
3679 code.putln(
3680 "%s = %s(%s); %s" % (
3681 self.result(),
3682 function,
3683 self.operand.py_result(),
3684 code.error_goto_if_null(self.result(), self.pos)))
3685 code.put_gotref(self.py_result())
3687 def type_error(self):
3688 if not self.operand.type.is_error:
3689 error(self.pos, "Invalid operand type for '%s' (%s)" %
3690 (self.operator, self.operand.type))
3691 self.type = PyrexTypes.error_type
3694 class NotNode(ExprNode):
3695 # 'not' operator
3696 #
3697 # operand ExprNode
3699 def calculate_constant_result(self):
3700 self.constant_result = not self.operand.constant_result
3702 def compile_time_value(self, denv):
3703 operand = self.operand.compile_time_value(denv)
3704 try:
3705 return not operand
3706 except Exception, e:
3707 self.compile_time_value_error(e)
3709 subexprs = ['operand']
3711 def analyse_types(self, env):
3712 self.operand.analyse_types(env)
3713 self.operand = self.operand.coerce_to_boolean(env)
3714 self.type = PyrexTypes.c_bint_type
3716 def calculate_result_code(self):
3717 return "(!%s)" % self.operand.result()
3719 def generate_result_code(self, code):
3720 pass
3723 class UnaryPlusNode(UnopNode):
3724 # unary '+' operator
3726 operator = '+'
3728 def analyse_c_operation(self, env):
3729 self.type = self.operand.type
3731 def py_operation_function(self):
3732 return "PyNumber_Positive"
3734 def calculate_result_code(self):
3735 return self.operand.result()
3738 class UnaryMinusNode(UnopNode):
3739 # unary '-' operator
3741 operator = '-'
3743 def analyse_c_operation(self, env):
3744 if self.operand.type.is_numeric:
3745 self.type = self.operand.type
3746 else:
3747 self.type_error()
3749 def py_operation_function(self):
3750 return "PyNumber_Negative"
3752 def calculate_result_code(self):
3753 return "(-%s)" % self.operand.result()
3756 class TildeNode(UnopNode):
3757 # unary '~' operator
3759 def analyse_c_operation(self, env):
3760 if self.operand.type.is_int:
3761 self.type = self.operand.type
3762 else:
3763 self.type_error()
3765 def py_operation_function(self):
3766 return "PyNumber_Invert"
3768 def calculate_result_code(self):
3769 return "(~%s)" % self.operand.result()
3772 class AmpersandNode(ExprNode):
3773 # The C address-of operator.
3774 #
3775 # operand ExprNode
3777 subexprs = ['operand']
3779 def analyse_types(self, env):
3780 self.operand.analyse_types(env)
3781 argtype = self.operand.type
3782 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3783 self.error("Taking address of non-lvalue")
3784 return
3785 if argtype.is_pyobject:
3786 self.error("Cannot take address of Python variable")
3787 return
3788 self.type = PyrexTypes.c_ptr_type(argtype)
3790 def check_const(self):
3791 self.operand.check_const_addr()
3793 def error(self, mess):
3794 error(self.pos, mess)
3795 self.type = PyrexTypes.error_type
3796 self.result_code = "<error>"
3798 def calculate_result_code(self):
3799 return "(&%s)" % self.operand.result()
3801 def generate_result_code(self, code):
3802 pass
3805 unop_node_classes = {
3806 "+": UnaryPlusNode,
3807 "-": UnaryMinusNode,
3808 "~": TildeNode,
3809 }
3811 def unop_node(pos, operator, operand):
3812 # Construct unnop node of appropriate class for
3813 # given operator.
3814 if isinstance(operand, IntNode) and operator == '-':
3815 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3816 elif isinstance(operand, UnopNode) and operand.operator == operator:
3817 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3818 return unop_node_classes[operator](pos,
3819 operator = operator,
3820 operand = operand)
3823 class TypecastNode(NewTempExprNode):
3824 # C type cast
3825 #
3826 # operand ExprNode
3827 # base_type CBaseTypeNode
3828 # declarator CDeclaratorNode
3829 #
3830 # If used from a transform, one can if wanted specify the attribute
3831 # "type" directly and leave base_type and declarator to None
3833 subexprs = ['operand']
3834 base_type = declarator = type = None
3836 def analyse_types(self, env):
3837 if self.type is None:
3838 base_type = self.base_type.analyse(env)
3839 _, self.type = self.declarator.analyse(base_type, env)
3840 if self.type.is_cfunction:
3841 error(self.pos,
3842 "Cannot cast to a function type")
3843 self.type = PyrexTypes.error_type
3844 self.operand.analyse_types(env)
3845 to_py = self.type.is_pyobject
3846 from_py = self.operand.type.is_pyobject
3847 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3848 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3849 if to_py and not from_py:
3850 if (self.operand.type.to_py_function and
3851 self.operand.type.create_convert_utility_code(env)):
3852 self.result_ctype = py_object_type
3853 self.operand = self.operand.coerce_to_pyobject(env)
3854 else:
3855 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3856 self.operand = self.operand.coerce_to_simple(env)
3857 elif from_py and not to_py:
3858 if self.type.from_py_function:
3859 self.operand = self.operand.coerce_to(self.type, env)
3860 else:
3861 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3862 elif from_py and to_py:
3863 if self.typecheck and self.type.is_extension_type:
3864 self.operand = PyTypeTestNode(self.operand, self.type, env)
3866 def check_const(self):
3867 self.operand.check_const()
3869 def calculate_constant_result(self):
3870 self.constant_result = self.operand.constant_result
3872 def calculate_result_code(self):
3873 opnd = self.operand
3874 return self.type.cast_code(opnd.result())
3876 def result_as(self, type):
3877 if self.type.is_pyobject and not self.is_temp:
3878 # Optimise away some unnecessary casting
3879 return self.operand.result_as(type)
3880 else:
3881 return ExprNode.result_as(self, type)
3883 def generate_result_code(self, code):
3884 if self.is_temp:
3885 code.putln(
3886 "%s = (PyObject *)%s;" % (
3887 self.result(),
3888 self.operand.result()))
3889 code.put_incref(self.result(), self.ctype())
3892 class SizeofNode(ExprNode):
3893 # Abstract base class for sizeof(x) expression nodes.
3895 type = PyrexTypes.c_size_t_type
3897 def check_const(self):
3898 pass
3900 def generate_result_code(self, code):
3901 pass
3904 class SizeofTypeNode(SizeofNode):
3905 # C sizeof function applied to a type
3906 #
3907 # base_type CBaseTypeNode
3908 # declarator CDeclaratorNode
3910 subexprs = []
3911 arg_type = None
3913 def analyse_types(self, env):
3914 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3915 # this could be better handled by more uniformly treating types as runtime-available objects
3916 if 0 and self.base_type.module_path:
3917 path = self.base_type.module_path
3918 obj = env.lookup(path[0])
3919 if obj.as_module is None:
3920 operand = NameNode(pos=self.pos, name=path[0])
3921 for attr in path[1:]:
3922 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3923 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3924 self.operand = operand
3925 self.__class__ = SizeofVarNode
3926 self.analyse_types(env)
3927 return
3928 if self.arg_type is None:
3929 base_type = self.base_type.analyse(env)
3930 _, arg_type = self.declarator.analyse(base_type, env)
3931 self.arg_type = arg_type
3932 self.check_type()
3934 def check_type(self):
3935 arg_type = self.arg_type
3936 if arg_type.is_pyobject and not arg_type.is_extension_type:
3937 error(self.pos, "Cannot take sizeof Python object")
3938 elif arg_type.is_void:
3939 error(self.pos, "Cannot take sizeof void")
3940 elif not arg_type.is_complete():
3941 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3943 def calculate_result_code(self):
3944 if self.arg_type.is_extension_type:
3945 # the size of the pointer is boring
3946 # we want the size of the actual struct
3947 arg_code = self.arg_type.declaration_code("", deref=1)
3948 else:
3949 arg_code = self.arg_type.declaration_code("")
3950 return "(sizeof(%s))" % arg_code
3953 class SizeofVarNode(SizeofNode):
3954 # C sizeof function applied to a variable
3955 #
3956 # operand ExprNode
3958 subexprs = ['operand']
3960 def analyse_types(self, env):
3961 # We may actually be looking at a type rather than a variable...
3962 # If we are, traditional analysis would fail...
3963 operand_as_type = self.operand.analyse_as_type(env)
3964 if operand_as_type:
3965 self.arg_type = operand_as_type
3966 self.__class__ = SizeofTypeNode
3967 self.check_type()
3968 else:
3969 self.operand.analyse_types(env)
3971 def calculate_result_code(self):
3972 return "(sizeof(%s))" % self.operand.result()
3974 def generate_result_code(self, code):
3975 pass
3978 #-------------------------------------------------------------------
3979 #
3980 # Binary operator nodes
3981 #
3982 #-------------------------------------------------------------------
3984 def _not_in(x, seq):
3985 return x not in seq
3987 compile_time_binary_operators = {
3988 '<': operator.lt,
3989 '<=': operator.le,
3990 '==': operator.eq,
3991 '!=': operator.ne,
3992 '>=': operator.ge,
3993 '>': operator.gt,
3994 'is': operator.is_,
3995 'is_not': operator.is_not,
3996 '+': operator.add,
3997 '&': operator.and_,
3998 '/': operator.div,
3999 '//': operator.floordiv,
4000 '<<': operator.lshift,
4001 '%': operator.mod,
4002 '*': operator.mul,
4003 '|': operator.or_,
4004 '**': operator.pow,
4005 '>>': operator.rshift,
4006 '-': operator.sub,
4007 #'/': operator.truediv,
4008 '^': operator.xor,
4009 'in': operator.contains,
4010 'not_in': _not_in,
4011 }
4013 def get_compile_time_binop(node):
4014 func = compile_time_binary_operators.get(node.operator)
4015 if not func:
4016 error(node.pos,
4017 "Binary '%s' not supported in compile-time expression"
4018 % node.operator)
4019 return func
4021 class BinopNode(NewTempExprNode):
4022 # operator string
4023 # operand1 ExprNode
4024 # operand2 ExprNode
4025 #
4026 # Processing during analyse_expressions phase:
4027 #
4028 # analyse_c_operation
4029 # Called when neither operand is a pyobject.
4030 # - Check operand types and coerce if needed.
4031 # - Determine result type and result code fragment.
4032 # - Allocate temporary for result if needed.
4034 subexprs = ['operand1', 'operand2']
4036 def calculate_constant_result(self):
4037 func = compile_time_binary_operators[self.operator]
4038 self.constant_result = func(
4039 self.operand1.constant_result,
4040 self.operand2.constant_result)
4042 def compile_time_value(self, denv):
4043 func = get_compile_time_binop(self)
4044 operand1 = self.operand1.compile_time_value(denv)
4045 operand2 = self.operand2.compile_time_value(denv)
4046 try:
4047 return func(operand1, operand2)
4048 except Exception, e:
4049 self.compile_time_value_error(e)
4051 def analyse_types(self, env):
4052 self.operand1.analyse_types(env)
4053 self.operand2.analyse_types(env)
4054 if self.is_py_operation():
4055 self.coerce_operands_to_pyobjects(env)
4056 self.type = py_object_type
4057 self.gil_check(env)
4058 self.is_temp = 1
4059 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4060 self.operand1 = self.operand1.coerce_to_temp(env)
4061 else:
4062 self.analyse_c_operation(env)
4064 def is_py_operation(self):
4065 return (self.operand1.type.is_pyobject
4066 or self.operand2.type.is_pyobject)
4068 def coerce_operands_to_pyobjects(self, env):
4069 self.operand1 = self.operand1.coerce_to_pyobject(env)
4070 self.operand2 = self.operand2.coerce_to_pyobject(env)
4072 def check_const(self):
4073 self.operand1.check_const()
4074 self.operand2.check_const()
4076 def generate_result_code(self, code):
4077 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4078 if self.operand1.type.is_pyobject:
4079 function = self.py_operation_function()
4080 if function == "PyNumber_Power":
4081 extra_args = ", Py_None"
4082 else:
4083 extra_args = ""
4084 code.putln(
4085 "%s = %s(%s, %s%s); %s" % (
4086 self.result(),
4087 function,
4088 self.operand1.py_result(),
4089 self.operand2.py_result(),
4090 extra_args,
4091 code.error_goto_if_null(self.result(), self.pos)))
4092 code.put_gotref(self.py_result())
4093 else:
4094 if self.is_temp:
4095 self.generate_c_operation_code(code)
4097 def type_error(self):
4098 if not (self.operand1.type.is_error
4099 or self.operand2.type.is_error):
4100 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4101 (self.operator, self.operand1.type,
4102 self.operand2.type))
4103 self.type = PyrexTypes.error_type
4106 class NumBinopNode(BinopNode):
4107 # Binary operation taking numeric arguments.
4109 def analyse_c_operation(self, env):
4110 type1 = self.operand1.type
4111 type2 = self.operand2.type
4112 self.type = self.compute_c_result_type(type1, type2)
4113 if not self.type:
4114 self.type_error()
4116 def compute_c_result_type(self, type1, type2):
4117 if self.c_types_okay(type1, type2):
4118 return PyrexTypes.widest_numeric_type(type1, type2)
4119 else:
4120 return None
4122 def c_types_okay(self, type1, type2):
4123 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4124 return (type1.is_numeric or type1.is_enum) \
4125 and (type2.is_numeric or type2.is_enum)
4127 def calculate_result_code(self):
4128 return "(%s %s %s)" % (
4129 self.operand1.result(),
4130 self.operator,
4131 self.operand2.result())
4133 def py_operation_function(self):
4134 return self.py_functions[self.operator]
4136 py_functions = {
4137 "|": "PyNumber_Or",
4138 "^": "PyNumber_Xor",
4139 "&": "PyNumber_And",
4140 "<<": "PyNumber_Lshift",
4141 ">>": "PyNumber_Rshift",
4142 "+": "PyNumber_Add",
4143 "-": "PyNumber_Subtract",
4144 "*": "PyNumber_Multiply",
4145 "/": "__Pyx_PyNumber_Divide",
4146 "//": "PyNumber_FloorDivide",
4147 "%": "PyNumber_Remainder",
4148 "**": "PyNumber_Power"
4149 }
4152 class IntBinopNode(NumBinopNode):
4153 # Binary operation taking integer arguments.
4155 def c_types_okay(self, type1, type2):
4156 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4157 return (type1.is_int or type1.is_enum) \
4158 and (type2.is_int or type2.is_enum)
4161 class AddNode(NumBinopNode):
4162 # '+' operator.
4164 def is_py_operation(self):
4165 if self.operand1.type.is_string \
4166 and self.operand2.type.is_string:
4167 return 1
4168 else:
4169 return NumBinopNode.is_py_operation(self)
4171 def compute_c_result_type(self, type1, type2):
4172 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4173 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4174 return type1
4175 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4176 return type2
4177 else:
4178 return NumBinopNode.compute_c_result_type(
4179 self, type1, type2)
4182 class SubNode(NumBinopNode):
4183 # '-' operator.
4185 def compute_c_result_type(self, type1, type2):
4186 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4187 return type1
4188 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4189 return PyrexTypes.c_int_type
4190 else:
4191 return NumBinopNode.compute_c_result_type(
4192 self, type1, type2)
4195 class MulNode(NumBinopNode):
4196 # '*' operator.
4198 def is_py_operation(self):
4199 type1 = self.operand1.type
4200 type2 = self.operand2.type
4201 if (type1.is_string and type2.is_int) \
4202 or (type2.is_string and type1.is_int):
4203 return 1
4204 else:
4205 return NumBinopNode.is_py_operation(self)
4208 class FloorDivNode(NumBinopNode):
4209 # '//' operator.
4211 def calculate_result_code(self):
4212 return "(%s %s %s)" % (
4213 self.operand1.result(),
4214 "/", # c division is by default floor-div
4215 self.operand2.result())
4218 class ModNode(NumBinopNode):
4219 # '%' operator.
4221 def is_py_operation(self):
4222 return (self.operand1.type.is_string
4223 or self.operand2.type.is_string
4224 or NumBinopNode.is_py_operation(self))
4226 def calculate_result_code(self):
4227 if self.operand1.type.is_float or self.operand2.type.is_float:
4228 return "fmod(%s, %s)" % (
4229 self.operand1.result(),
4230 self.operand2.result())
4231 else:
4232 return "(%s %% %s)" % (
4233 self.operand1.result(),
4234 self.operand2.result())
4236 class PowNode(NumBinopNode):
4237 # '**' operator.
4239 def compute_c_result_type(self, type1, type2):
4240 if self.c_types_okay(type1, type2):
4241 return PyrexTypes.c_double_type
4242 else:
4243 return None
4245 def c_types_okay(self, type1, type2):
4246 return (type1.is_float or type2.is_float) and \
4247 NumBinopNode.c_types_okay(self, type1, type2)
4249 def type_error(self):
4250 if not (self.operand1.type.is_error or self.operand2.type.is_error):
4251 if self.operand1.type.is_int and self.operand2.type.is_int:
4252 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
4253 (self.operator, self.operand1.type, self.operand2.type))
4254 else:
4255 NumBinopNode.type_error(self)
4256 self.type = PyrexTypes.error_type
4258 def calculate_result_code(self):
4259 return "pow(%s, %s)" % (
4260 self.operand1.result(), self.operand2.result())
4263 # Note: This class is temporary "shut down" into an ineffective mode temp
4264 # allocation mode.
4265 #
4266 # More sophisticated temp reuse was going on before,
4267 # one could have a look at adding this again after /all/ classes
4268 # are converted to the new temp scheme. (The temp juggling cannot work
4269 # otherwise).
4270 class BoolBinopNode(NewTempExprNode):
4271 # Short-circuiting boolean operation.
4272 #
4273 # operator string
4274 # operand1 ExprNode
4275 # operand2 ExprNode
4277 subexprs = ['operand1', 'operand2']
4279 def calculate_constant_result(self):
4280 if self.operator == 'and':
4281 self.constant_result = \
4282 self.operand1.constant_result and \
4283 self.operand2.constant_result
4284 else:
4285 self.constant_result = \
4286 self.operand1.constant_result or \
4287 self.operand2.constant_result
4289 def compile_time_value(self, denv):
4290 if self.operator == 'and':
4291 return self.operand1.compile_time_value(denv) \
4292 and self.operand2.compile_time_value(denv)
4293 else:
4294 return self.operand1.compile_time_value(denv) \
4295 or self.operand2.compile_time_value(denv)
4297 def coerce_to_boolean(self, env):
4298 self.operand1 = self.operand1.coerce_to_boolean(env)
4299 self.operand2 = self.operand2.coerce_to_boolean(env)
4300 self.type = PyrexTypes.c_bint_type
4301 return self
4303 def analyse_types(self, env):
4304 self.operand1.analyse_types(env)
4305 self.operand2.analyse_types(env)
4306 if self.operand1.type.is_pyobject or \
4307 self.operand2.type.is_pyobject:
4308 self.operand1 = self.operand1.coerce_to_pyobject(env)
4309 self.operand2 = self.operand2.coerce_to_pyobject(env)
4310 self.type = py_object_type
4311 self.gil_check(env)
4312 else:
4313 self.operand1 = self.operand1.coerce_to_boolean(env)
4314 self.operand2 = self.operand2.coerce_to_boolean(env)
4315 self.type = PyrexTypes.c_bint_type
4317 # Below disabled for
4319 # For what we're about to do, it's vital that
4320 # both operands be temp nodes.
4321 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4322 # self.operand2 = self.operand2.coerce_to_temp(env)
4323 self.is_temp = 1
4325 gil_message = "Truth-testing Python object"
4327 ## def allocate_temps(self, env, result_code = None):
4328 ## # We don't need both operands at the same time, and
4329 ## # one of the operands will also be our result. So we
4330 ## # use an allocation strategy here which results in
4331 ## # this node and both its operands sharing the same
4332 ## # result variable. This allows us to avoid some
4333 ## # assignments and increfs/decrefs that would otherwise
4334 ## # be necessary.
4335 ## self.allocate_temp(env, result_code)
4336 ## self.operand1.allocate_temps(env, self.result())
4337 ## self.operand2.allocate_temps(env, self.result())
4338 ## # We haven't called release_temp on either operand,
4339 ## # because although they are temp nodes, they don't own
4340 ## # their result variable. And because they are temp
4341 ## # nodes, any temps in their subnodes will have been
4342 ## # released before their allocate_temps returned.
4343 ## # Therefore, they contain no temp vars that need to
4344 ## # be released.
4346 def check_const(self):
4347 self.operand1.check_const()
4348 self.operand2.check_const()
4350 def calculate_result_code(self):
4351 return "(%s %s %s)" % (
4352 self.operand1.result(),
4353 self.py_to_c_op[self.operator],
4354 self.operand2.result())
4356 py_to_c_op = {'and': "&&", 'or': "||"}
4358 def generate_evaluation_code(self, code):
4359 code.mark_pos(self.pos)
4360 self.operand1.generate_evaluation_code(code)
4361 test_result, uses_temp = self.generate_operand1_test(code)
4362 if self.operator == 'and':
4363 sense = ""
4364 else:
4365 sense = "!"
4366 code.putln(
4367 "if (%s%s) {" % (
4368 sense,
4369 test_result))
4370 if uses_temp:
4371 code.funcstate.release_temp(test_result)
4372 self.operand1.generate_disposal_code(code)
4373 self.operand2.generate_evaluation_code(code)
4374 self.allocate_temp_result(code)
4375 self.operand2.make_owned_reference(code)
4376 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4377 self.operand2.generate_post_assignment_code(code)
4378 self.operand2.free_temps(code)
4379 code.putln("} else {")
4380 self.operand1.make_owned_reference(code)
4381 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4382 self.operand1.generate_post_assignment_code(code)
4383 self.operand1.free_temps(code)
4384 code.putln("}")
4386 def generate_operand1_test(self, code):
4387 # Generate code to test the truth of the first operand.
4388 if self.type.is_pyobject:
4389 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4390 manage_ref=False)
4391 code.putln(
4392 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4393 test_result,
4394 self.operand1.py_result(),
4395 code.error_goto_if_neg(test_result, self.pos)))
4396 else:
4397 test_result = self.operand1.result()
4398 return (test_result, self.type.is_pyobject)
4401 class CondExprNode(ExprNode):
4402 # Short-circuiting conditional expression.
4403 #
4404 # test ExprNode
4405 # true_val ExprNode
4406 # false_val ExprNode
4408 true_val = None
4409 false_val = None
4411 subexprs = ['test', 'true_val', 'false_val']
4413 def calculate_constant_result(self):
4414 if self.test.constant_result:
4415 self.constant_result = self.true_val.constant_result
4416 else:
4417 self.constant_result = self.false_val.constant_result
4419 def analyse_types(self, env):
4420 self.test.analyse_types(env)
4421 self.test = self.test.coerce_to_boolean(env)
4422 self.true_val.analyse_types(env)
4423 self.false_val.analyse_types(env)
4424 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4425 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4426 self.true_val = self.true_val.coerce_to(self.type, env)
4427 self.false_val = self.false_val.coerce_to(self.type, env)
4428 # must be tmp variables so they can share a result
4429 self.true_val = self.true_val.coerce_to_temp(env)
4430 self.false_val = self.false_val.coerce_to_temp(env)
4431 self.is_temp = 1
4432 if self.type == PyrexTypes.error_type:
4433 self.type_error()
4435 def allocate_temps(self, env, result_code = None):
4436 # We only ever evaluate one side, and this is
4437 # after evaluating the truth value, so we may
4438 # use an allocation strategy here which results in
4439 # this node and both its operands sharing the same
4440 # result variable. This allows us to avoid some
4441 # assignments and increfs/decrefs that would otherwise
4442 # be necessary.
4443 self.allocate_temp(env, result_code)
4444 self.test.allocate_temps(env, result_code)
4445 self.true_val.allocate_temps(env, self.result())
4446 self.false_val.allocate_temps(env, self.result())
4447 # We haven't called release_temp on either value,
4448 # because although they are temp nodes, they don't own
4449 # their result variable. And because they are temp
4450 # nodes, any temps in their subnodes will have been
4451 # released before their allocate_temps returned.
4452 # Therefore, they contain no temp vars that need to
4453 # be released.
4455 def compute_result_type(self, type1, type2):
4456 if type1 == type2:
4457 return type1
4458 elif type1.is_numeric and type2.is_numeric:
4459 return PyrexTypes.widest_numeric_type(type1, type2)
4460 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4461 return type2
4462 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4463 return type1
4464 elif type1.is_pyobject or type2.is_pyobject:
4465 return py_object_type
4466 elif type1.assignable_from(type2):
4467 return type1
4468 elif type2.assignable_from(type1):
4469 return type2
4470 else:
4471 return PyrexTypes.error_type
4473 def type_error(self):
4474 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4475 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4476 (self.true_val.type, self.false_val.type))
4477 self.type = PyrexTypes.error_type
4479 def check_const(self):
4480 self.test.check_const()
4481 self.true_val.check_const()
4482 self.false_val.check_const()
4484 def generate_evaluation_code(self, code):
4485 self.test.generate_evaluation_code(code)
4486 code.putln("if (%s) {" % self.test.result() )
4487 self.true_val.generate_evaluation_code(code)
4488 code.putln("} else {")
4489 self.false_val.generate_evaluation_code(code)
4490 code.putln("}")
4491 self.test.generate_disposal_code(code)
4492 self.test.free_temps(code)
4494 richcmp_constants = {
4495 "<" : "Py_LT",
4496 "<=": "Py_LE",
4497 "==": "Py_EQ",
4498 "!=": "Py_NE",
4499 "<>": "Py_NE",
4500 ">" : "Py_GT",
4501 ">=": "Py_GE",
4502 }
4504 class CmpNode(object):
4505 # Mixin class containing code common to PrimaryCmpNodes
4506 # and CascadedCmpNodes.
4508 def calculate_cascaded_constant_result(self, operand1_result):
4509 func = compile_time_binary_operators[self.operator]
4510 operand2_result = self.operand2.constant_result
4511 result = func(operand1_result, operand2_result)
4512 if result and self.cascade:
4513 result = result and \
4514 self.cascade.cascaded_compile_time_value(operand2_result)
4515 self.constant_result = result
4517 def cascaded_compile_time_value(self, operand1, denv):
4518 func = get_compile_time_binop(self)
4519 operand2 = self.operand2.compile_time_value(denv)
4520 try:
4521 result = func(operand1, operand2)
4522 except Exception, e:
4523 self.compile_time_value_error(e)
4524 result = None
4525 if result:
4526 cascade = self.cascade
4527 if cascade:
4528 # FIXME: I bet this must call cascaded_compile_time_value()
4529 result = result and cascade.compile_time_value(operand2, denv)
4530 return result
4532 def is_python_comparison(self):
4533 return (self.has_python_operands()
4534 or (self.cascade and self.cascade.is_python_comparison())
4535 or self.operator in ('in', 'not_in'))
4537 def is_python_result(self):
4538 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4539 or (self.cascade and self.cascade.is_python_result()))
4541 def check_types(self, env, operand1, op, operand2):
4542 if not self.types_okay(operand1, op, operand2):
4543 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4544 (self.operator, operand1.type, operand2.type))
4546 def types_okay(self, operand1, op, operand2):
4547 type1 = operand1.type
4548 type2 = operand2.type
4549 if type1.is_error or type2.is_error:
4550 return 1
4551 if type1.is_pyobject: # type2 will be, too
4552 return 1
4553 elif type1.is_ptr or type1.is_array:
4554 return type1.is_null_ptr or type2.is_null_ptr \
4555 or ((type2.is_ptr or type2.is_array)
4556 and type1.base_type.same_as(type2.base_type))
4557 elif ((type1.is_numeric and type2.is_numeric
4558 or type1.is_enum and (type1 is type2 or type2.is_int)
4559 or type1.is_int and type2.is_enum)
4560 and op not in ('is', 'is_not')):
4561 return 1
4562 else:
4563 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4565 def generate_operation_code(self, code, result_code,
4566 operand1, op , operand2):
4567 if self.type is PyrexTypes.py_object_type:
4568 coerce_result = "__Pyx_PyBool_FromLong"
4569 else:
4570 coerce_result = ""
4571 if 'not' in op: negation = "!"
4572 else: negation = ""
4573 if op == 'in' or op == 'not_in':
4574 code.putln(
4575 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4576 result_code,
4577 coerce_result,
4578 negation,
4579 operand2.py_result(),
4580 operand1.py_result(),
4581 code.error_goto_if_neg(result_code, self.pos)))
4582 elif (operand1.type.is_pyobject
4583 and op not in ('is', 'is_not')):
4584 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4585 result_code,
4586 operand1.py_result(),
4587 operand2.py_result(),
4588 richcmp_constants[op],
4589 code.error_goto_if_null(result_code, self.pos)))
4590 code.put_gotref(result_code)
4591 else:
4592 type1 = operand1.type
4593 type2 = operand2.type
4594 if (type1.is_extension_type or type2.is_extension_type) \
4595 and not type1.same_as(type2):
4596 common_type = py_object_type
4597 elif type1.is_numeric:
4598 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4599 else:
4600 common_type = type1
4601 code1 = operand1.result_as(common_type)
4602 code2 = operand2.result_as(common_type)
4603 code.putln("%s = %s(%s %s %s);" % (
4604 result_code,
4605 coerce_result,
4606 code1,
4607 self.c_operator(op),
4608 code2))
4610 def c_operator(self, op):
4611 if op == 'is':
4612 return "=="
4613 elif op == 'is_not':
4614 return "!="
4615 else:
4616 return op
4619 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4620 # Non-cascaded comparison or first comparison of
4621 # a cascaded sequence.
4622 #
4623 # operator string
4624 # operand1 ExprNode
4625 # operand2 ExprNode
4626 # cascade CascadedCmpNode
4628 # We don't use the subexprs mechanism, because
4629 # things here are too complicated for it to handle.
4630 # Instead, we override all the framework methods
4631 # which use it.
4633 child_attrs = ['operand1', 'operand2', 'cascade']
4635 cascade = None
4637 def calculate_constant_result(self):
4638 self.constant_result = self.calculate_cascaded_constant_result(
4639 self.operand1.constant_result)
4641 def compile_time_value(self, denv):
4642 operand1 = self.operand1.compile_time_value(denv)
4643 return self.cascaded_compile_time_value(operand1, denv)
4645 def analyse_types(self, env):
4646 self.operand1.analyse_types(env)
4647 self.operand2.analyse_types(env)
4648 if self.cascade:
4649 self.cascade.analyse_types(env, self.operand2)
4650 self.is_pycmp = self.is_python_comparison()
4651 if self.is_pycmp:
4652 self.coerce_operands_to_pyobjects(env)
4653 if self.has_int_operands():
4654 self.coerce_chars_to_ints(env)
4655 if self.cascade:
4656 self.operand2 = self.operand2.coerce_to_simple(env)
4657 self.cascade.coerce_cascaded_operands_to_temp(env)
4658 self.check_operand_types(env)
4659 if self.is_python_result():
4660 self.type = PyrexTypes.py_object_type
4661 else:
4662 self.type = PyrexTypes.c_bint_type
4663 cdr = self.cascade
4664 while cdr:
4665 cdr.type = self.type
4666 cdr = cdr.cascade
4667 if self.is_pycmp or self.cascade:
4668 self.is_temp = 1
4670 def check_operand_types(self, env):
4671 self.check_types(env,
4672 self.operand1, self.operator, self.operand2)
4673 if self.cascade:
4674 self.cascade.check_operand_types(env, self.operand2)
4676 def has_python_operands(self):
4677 return (self.operand1.type.is_pyobject
4678 or self.operand2.type.is_pyobject)
4680 def coerce_operands_to_pyobjects(self, env):
4681 self.operand1 = self.operand1.coerce_to_pyobject(env)
4682 self.operand2 = self.operand2.coerce_to_pyobject(env)
4683 if self.cascade:
4684 self.cascade.coerce_operands_to_pyobjects(env)
4686 def has_int_operands(self):
4687 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4688 or (self.cascade and self.cascade.has_int_operands())
4690 def coerce_chars_to_ints(self, env):
4691 # coerce literal single-char strings to c chars
4692 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4693 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4694 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4695 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4696 if self.cascade:
4697 self.cascade.coerce_chars_to_ints(env)
4699 def allocate_subexpr_temps(self, env):
4700 self.operand1.allocate_temps(env)
4701 self.operand2.allocate_temps(env)
4702 if self.cascade:
4703 self.cascade.allocate_subexpr_temps(env)
4705 def release_subexpr_temps(self, env):
4706 self.operand1.release_temp(env)
4707 self.operand2.release_temp(env)
4708 if self.cascade:
4709 self.cascade.release_subexpr_temps(env)
4711 def check_const(self):
4712 self.operand1.check_const()
4713 self.operand2.check_const()
4714 if self.cascade:
4715 self.not_const()
4717 def calculate_result_code(self):
4718 return "(%s %s %s)" % (
4719 self.operand1.result(),
4720 self.c_operator(self.operator),
4721 self.operand2.result())
4723 def generate_evaluation_code(self, code):
4724 self.operand1.generate_evaluation_code(code)
4725 self.operand2.generate_evaluation_code(code)
4726 if self.is_temp:
4727 self.allocate_temp_result(code)
4728 self.generate_operation_code(code, self.result(),
4729 self.operand1, self.operator, self.operand2)
4730 if self.cascade:
4731 self.cascade.generate_evaluation_code(code,
4732 self.result(), self.operand2)
4733 self.operand1.generate_disposal_code(code)
4734 self.operand1.free_temps(code)
4735 self.operand2.generate_disposal_code(code)
4736 self.operand2.free_temps(code)
4738 def generate_subexpr_disposal_code(self, code):
4739 # If this is called, it is a non-cascaded cmp,
4740 # so only need to dispose of the two main operands.
4741 self.operand1.generate_disposal_code(code)
4742 self.operand2.generate_disposal_code(code)
4744 def free_subexpr_temps(self, code):
4745 # If this is called, it is a non-cascaded cmp,
4746 # so only need to dispose of the two main operands.
4747 self.operand1.free_temps(code)
4748 self.operand2.free_temps(code)
4750 def annotate(self, code):
4751 self.operand1.annotate(code)
4752 self.operand2.annotate(code)
4753 if self.cascade:
4754 self.cascade.annotate(code)
4757 class CascadedCmpNode(Node, CmpNode):
4758 # A CascadedCmpNode is not a complete expression node. It
4759 # hangs off the side of another comparison node, shares
4760 # its left operand with that node, and shares its result
4761 # with the PrimaryCmpNode at the head of the chain.
4762 #
4763 # operator string
4764 # operand2 ExprNode
4765 # cascade CascadedCmpNode
4767 child_attrs = ['operand2', 'cascade']
4769 cascade = None
4770 constant_result = constant_value_not_set # FIXME: where to calculate this?
4772 def analyse_types(self, env, operand1):
4773 self.operand2.analyse_types(env)
4774 if self.cascade:
4775 self.cascade.analyse_types(env, self.operand2)
4777 def check_operand_types(self, env, operand1):
4778 self.check_types(env,
4779 operand1, self.operator, self.operand2)
4780 if self.cascade:
4781 self.cascade.check_operand_types(env, self.operand2)
4783 def has_python_operands(self):
4784 return self.operand2.type.is_pyobject
4786 def coerce_operands_to_pyobjects(self, env):
4787 self.operand2 = self.operand2.coerce_to_pyobject(env)
4788 if self.cascade:
4789 self.cascade.coerce_operands_to_pyobjects(env)
4791 def has_int_operands(self):
4792 return self.operand2.type.is_int
4794 def coerce_chars_to_ints(self, env):
4795 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4796 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4798 def coerce_cascaded_operands_to_temp(self, env):
4799 if self.cascade:
4800 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4801 self.operand2 = self.operand2.coerce_to_simple(env)
4802 self.cascade.coerce_cascaded_operands_to_temp(env)
4804 def allocate_subexpr_temps(self, env):
4805 self.operand2.allocate_temps(env)
4806 if self.cascade:
4807 self.cascade.allocate_subexpr_temps(env)
4809 def release_subexpr_temps(self, env):
4810 self.operand2.release_temp(env)
4811 if self.cascade:
4812 self.cascade.release_subexpr_temps(env)
4814 def generate_evaluation_code(self, code, result, operand1):
4815 if self.type.is_pyobject:
4816 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4817 code.put_decref(result, self.type)
4818 else:
4819 code.putln("if (%s) {" % result)
4820 self.operand2.generate_evaluation_code(code)
4821 self.generate_operation_code(code, result,
4822 operand1, self.operator, self.operand2)
4823 if self.cascade:
4824 self.cascade.generate_evaluation_code(
4825 code, result, self.operand2)
4826 # Cascaded cmp result is always temp
4827 self.operand2.generate_disposal_code(code)
4828 self.operand2.free_temps(code)
4829 code.putln("}")
4831 def annotate(self, code):
4832 self.operand2.annotate(code)
4833 if self.cascade:
4834 self.cascade.annotate(code)
4837 binop_node_classes = {
4838 "or": BoolBinopNode,
4839 "and": BoolBinopNode,
4840 "|": IntBinopNode,
4841 "^": IntBinopNode,
4842 "&": IntBinopNode,
4843 "<<": IntBinopNode,
4844 ">>": IntBinopNode,
4845 "+": AddNode,
4846 "-": SubNode,
4847 "*": MulNode,
4848 "/": NumBinopNode,
4849 "//": FloorDivNode,
4850 "%": ModNode,
4851 "**": PowNode
4852 }
4854 def binop_node(pos, operator, operand1, operand2):
4855 # Construct binop node of appropriate class for
4856 # given operator.
4857 return binop_node_classes[operator](pos,
4858 operator = operator,
4859 operand1 = operand1,
4860 operand2 = operand2)
4862 #-------------------------------------------------------------------
4863 #
4864 # Coercion nodes
4865 #
4866 # Coercion nodes are special in that they are created during
4867 # the analyse_types phase of parse tree processing.
4868 # Their __init__ methods consequently incorporate some aspects
4869 # of that phase.
4870 #
4871 #-------------------------------------------------------------------
4873 class CoercionNode(NewTempExprNode):
4874 # Abstract base class for coercion nodes.
4875 #
4876 # arg ExprNode node being coerced
4878 subexprs = ['arg']
4880 def __init__(self, arg):
4881 self.pos = arg.pos
4882 self.arg = arg
4883 if debug_coercion:
4884 print("%s Coercing %s" % (self, self.arg))
4886 def calculate_constant_result(self):
4887 self.constant_result = self.arg.constant_result
4889 def annotate(self, code):
4890 self.arg.annotate(code)
4891 if self.arg.type != self.type:
4892 file, line, col = self.pos
4893 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4896 class CastNode(CoercionNode):
4897 # Wrap a node in a C type cast.
4899 def __init__(self, arg, new_type):
4900 CoercionNode.__init__(self, arg)
4901 self.type = new_type
4903 def calculate_result_code(self):
4904 return self.arg.result_as(self.type)
4906 def generate_result_code(self, code):
4907 self.arg.generate_result_code(code)
4910 class PyTypeTestNode(CoercionNode):
4911 # This node is used to check that a generic Python
4912 # object is an instance of a particular extension type.
4913 # This node borrows the result of its argument node.
4915 def __init__(self, arg, dst_type, env):
4916 # The arg is know to be a Python object, and
4917 # the dst_type is known to be an extension type.
4918 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4919 CoercionNode.__init__(self, arg)
4920 self.type = dst_type
4921 self.gil_check(env)
4922 self.result_ctype = arg.ctype()
4924 gil_message = "Python type test"
4926 def analyse_types(self, env):
4927 pass
4929 def result_in_temp(self):
4930 return self.arg.result_in_temp()
4932 def is_ephemeral(self):
4933 return self.arg.is_ephemeral()
4935 def calculate_result_code(self):
4936 return self.arg.result()
4938 def generate_result_code(self, code):
4939 if self.type.typeobj_is_available():
4940 if not self.type.is_builtin_type:
4941 code.globalstate.use_utility_code(type_test_utility_code)
4942 code.putln(
4943 "if (!(%s)) %s" % (
4944 self.type.type_test_code(self.arg.py_result()),
4945 code.error_goto(self.pos)))
4946 else:
4947 error(self.pos, "Cannot test type of extern C class "
4948 "without type object name specification")
4950 def generate_post_assignment_code(self, code):
4951 self.arg.generate_post_assignment_code(code)
4953 def free_temps(self, code):
4954 self.arg.free_temps(code)
4957 class CoerceToPyTypeNode(CoercionNode):
4958 # This node is used to convert a C data type
4959 # to a Python object.
4961 def __init__(self, arg, env):
4962 CoercionNode.__init__(self, arg)
4963 self.type = py_object_type
4964 self.gil_check(env)
4965 self.is_temp = 1
4966 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4967 error(arg.pos,
4968 "Cannot convert '%s' to Python object" % arg.type)
4970 gil_message = "Converting to Python object"
4972 def coerce_to_boolean(self, env):
4973 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
4975 def coerce_to_integer(self, env):
4976 # If not already some C integer type, coerce to longint.
4977 if self.arg.type.is_int:
4978 return self.arg
4979 else:
4980 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
4982 def analyse_types(self, env):
4983 # The arg is always already analysed
4984 pass
4986 def generate_result_code(self, code):
4987 function = self.arg.type.to_py_function
4988 code.putln('%s = %s(%s); %s' % (
4989 self.result(),
4990 function,
4991 self.arg.result(),
4992 code.error_goto_if_null(self.result(), self.pos)))
4993 code.put_gotref(self.py_result())
4996 class CoerceFromPyTypeNode(CoercionNode):
4997 # This node is used to convert a Python object
4998 # to a C data type.
5000 def __init__(self, result_type, arg, env):
5001 CoercionNode.__init__(self, arg)
5002 self.type = result_type
5003 self.is_temp = 1
5004 if not result_type.from_py_function:
5005 error(arg.pos,
5006 "Cannot convert Python object to '%s'" % result_type)
5007 if self.type.is_string and self.arg.is_ephemeral():
5008 error(arg.pos,
5009 "Obtaining char * from temporary Python value")
5011 def analyse_types(self, env):
5012 # The arg is always already analysed
5013 pass
5015 def generate_result_code(self, code):
5016 function = self.type.from_py_function
5017 operand = self.arg.py_result()
5018 rhs = "%s(%s)" % (function, operand)
5019 if self.type.is_enum:
5020 rhs = typecast(self.type, c_long_type, rhs)
5021 code.putln('%s = %s; %s' % (
5022 self.result(),
5023 rhs,
5024 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5025 if self.type.is_pyobject:
5026 code.put_gotref(self.py_result())
5029 class CoerceToBooleanNode(CoercionNode):
5030 # This node is used when a result needs to be used
5031 # in a boolean context.
5033 def __init__(self, arg, env):
5034 CoercionNode.__init__(self, arg)
5035 self.type = PyrexTypes.c_bint_type
5036 if arg.type.is_pyobject:
5037 if env.nogil:
5038 self.gil_error()
5039 self.is_temp = 1
5041 gil_message = "Truth-testing Python object"
5043 def check_const(self):
5044 if self.is_temp:
5045 self.not_const()
5046 self.arg.check_const()
5048 def calculate_result_code(self):
5049 return "(%s != 0)" % self.arg.result()
5051 def generate_result_code(self, code):
5052 if self.arg.type.is_pyobject:
5053 code.putln(
5054 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5055 self.result(),
5056 self.arg.py_result(),
5057 code.error_goto_if_neg(self.result(), self.pos)))
5060 class CoerceToTempNode(CoercionNode):
5061 # This node is used to force the result of another node
5062 # to be stored in a temporary. It is only used if the
5063 # argument node's result is not already in a temporary.
5065 def __init__(self, arg, env):
5066 CoercionNode.__init__(self, arg)
5067 self.type = self.arg.type
5068 self.is_temp = 1
5069 if self.type.is_pyobject:
5070 self.gil_check(env)
5071 self.result_ctype = py_object_type
5073 gil_message = "Creating temporary Python reference"
5075 def analyse_types(self, env):
5076 # The arg is always already analysed
5077 pass
5079 def coerce_to_boolean(self, env):
5080 self.arg = self.arg.coerce_to_boolean(env)
5081 self.type = self.arg.type
5082 self.result_ctype = self.type
5083 return self
5085 def generate_result_code(self, code):
5086 #self.arg.generate_evaluation_code(code) # Already done
5087 # by generic generate_subexpr_evaluation_code!
5088 code.putln("%s = %s;" % (
5089 self.result(), self.arg.result_as(self.ctype())))
5090 if self.type.is_pyobject:
5091 code.put_incref(self.result(), self.ctype())
5094 class CloneNode(CoercionNode):
5095 # This node is employed when the result of another node needs
5096 # to be used multiple times. The argument node's result must
5097 # be in a temporary. This node "borrows" the result from the
5098 # argument node, and does not generate any evaluation or
5099 # disposal code for it. The original owner of the argument
5100 # node is responsible for doing those things.
5102 subexprs = [] # Arg is not considered a subexpr
5104 def __init__(self, arg):
5105 CoercionNode.__init__(self, arg)
5106 if hasattr(arg, 'type'):
5107 self.type = arg.type
5108 self.result_ctype = arg.result_ctype
5109 if hasattr(arg, 'entry'):
5110 self.entry = arg.entry
5112 def result(self):
5113 return self.arg.result()
5115 def analyse_types(self, env):
5116 self.type = self.arg.type
5117 self.result_ctype = self.arg.result_ctype
5118 self.is_temp = 1
5119 if hasattr(self.arg, 'entry'):
5120 self.entry = self.arg.entry
5122 def generate_evaluation_code(self, code):
5123 pass
5125 def generate_result_code(self, code):
5126 pass
5128 def generate_disposal_code(self, code):
5129 pass
5131 def allocate_temps(self, env):
5132 pass
5134 def release_temp(self, env):
5135 pass
5137 def free_temps(self, code):
5138 pass
5141 #------------------------------------------------------------------------------------
5142 #
5143 # Runtime support code
5144 #
5145 #------------------------------------------------------------------------------------
5147 get_name_interned_utility_code = UtilityCode(
5148 proto = """
5149 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5150 """,
5151 impl = """
5152 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5153 PyObject *result;
5154 result = PyObject_GetAttr(dict, name);
5155 if (!result)
5156 PyErr_SetObject(PyExc_NameError, name);
5157 return result;
5158 }
5159 """)
5161 #------------------------------------------------------------------------------------
5163 import_utility_code = UtilityCode(
5164 proto = """
5165 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5166 """,
5167 impl = """
5168 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5169 PyObject *__import__ = 0;
5170 PyObject *empty_list = 0;
5171 PyObject *module = 0;
5172 PyObject *global_dict = 0;
5173 PyObject *empty_dict = 0;
5174 PyObject *list;
5175 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5176 if (!__import__)
5177 goto bad;
5178 if (from_list)
5179 list = from_list;
5180 else {
5181 empty_list = PyList_New(0);
5182 if (!empty_list)
5183 goto bad;
5184 list = empty_list;
5185 }
5186 global_dict = PyModule_GetDict(%(GLOBALS)s);
5187 if (!global_dict)
5188 goto bad;
5189 empty_dict = PyDict_New();
5190 if (!empty_dict)
5191 goto bad;
5192 module = PyObject_CallFunctionObjArgs(__import__,
5193 name, global_dict, empty_dict, list, NULL);
5194 bad:
5195 Py_XDECREF(empty_list);
5196 Py_XDECREF(__import__);
5197 Py_XDECREF(empty_dict);
5198 return module;
5199 }
5200 """ % {
5201 "BUILTINS": Naming.builtins_cname,
5202 "GLOBALS": Naming.module_cname,
5203 })
5205 #------------------------------------------------------------------------------------
5207 get_exception_utility_code = UtilityCode(
5208 proto = """
5209 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5210 """,
5211 impl = """
5212 static PyObject *__Pyx_GetExcValue(void) {
5213 PyObject *type = 0, *value = 0, *tb = 0;
5214 PyObject *tmp_type, *tmp_value, *tmp_tb;
5215 PyObject *result = 0;
5216 PyThreadState *tstate = PyThreadState_Get();
5217 PyErr_Fetch(&type, &value, &tb);
5218 PyErr_NormalizeException(&type, &value, &tb);
5219 if (PyErr_Occurred())
5220 goto bad;
5221 if (!value) {
5222 value = Py_None;
5223 Py_INCREF(value);
5224 }
5225 tmp_type = tstate->exc_type;
5226 tmp_value = tstate->exc_value;
5227 tmp_tb = tstate->exc_traceback;
5228 tstate->exc_type = type;
5229 tstate->exc_value = value;
5230 tstate->exc_traceback = tb;
5231 /* Make sure tstate is in a consistent state when we XDECREF
5232 these objects (XDECREF may run arbitrary code). */
5233 Py_XDECREF(tmp_type);
5234 Py_XDECREF(tmp_value);
5235 Py_XDECREF(tmp_tb);
5236 result = value;
5237 Py_XINCREF(result);
5238 type = 0;
5239 value = 0;
5240 tb = 0;
5241 bad:
5242 Py_XDECREF(type);
5243 Py_XDECREF(value);
5244 Py_XDECREF(tb);
5245 return result;
5246 }
5247 """)
5249 #------------------------------------------------------------------------------------
5251 unpacking_utility_code = UtilityCode(
5252 proto = """
5253 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5254 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5255 """,
5256 impl = """
5257 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5258 PyObject *item;
5259 if (!(item = PyIter_Next(iter))) {
5260 if (!PyErr_Occurred()) {
5261 PyErr_Format(PyExc_ValueError,
5262 #if PY_VERSION_HEX < 0x02050000
5263 "need more than %d values to unpack", (int)index);
5264 #else
5265 "need more than %zd values to unpack", index);
5266 #endif
5267 }
5268 }
5269 return item;
5270 }
5272 static int __Pyx_EndUnpack(PyObject *iter) {
5273 PyObject *item;
5274 if ((item = PyIter_Next(iter))) {
5275 Py_DECREF(item);
5276 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5277 return -1;
5278 }
5279 else if (!PyErr_Occurred())
5280 return 0;
5281 else
5282 return -1;
5283 }
5284 """)
5286 #------------------------------------------------------------------------------------
5288 type_test_utility_code = UtilityCode(
5289 proto = """
5290 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5291 """,
5292 impl = """
5293 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5294 if (!type) {
5295 PyErr_Format(PyExc_SystemError, "Missing type object");
5296 return 0;
5297 }
5298 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5299 return 1;
5300 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5301 Py_TYPE(obj)->tp_name, type->tp_name);
5302 return 0;
5303 }
5304 """)
5306 #------------------------------------------------------------------------------------
5308 create_class_utility_code = UtilityCode(
5309 proto = """
5310 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5311 """,
5312 impl = """
5313 static PyObject *__Pyx_CreateClass(
5314 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5315 {
5316 PyObject *py_modname;
5317 PyObject *result = 0;
5319 #if PY_MAJOR_VERSION < 3
5320 py_modname = PyString_FromString(modname);
5321 #else
5322 py_modname = PyUnicode_FromString(modname);
5323 #endif
5324 if (!py_modname)
5325 goto bad;
5326 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5327 goto bad;
5328 #if PY_MAJOR_VERSION < 3
5329 result = PyClass_New(bases, dict, name);
5330 #else
5331 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5332 #endif
5333 bad:
5334 Py_XDECREF(py_modname);
5335 return result;
5336 }
5337 """)
5339 #------------------------------------------------------------------------------------
5341 cpp_exception_utility_code = UtilityCode(
5342 proto = """
5343 #ifndef __Pyx_CppExn2PyErr
5344 static void __Pyx_CppExn2PyErr() {
5345 try {
5346 if (PyErr_Occurred())
5347 ; // let the latest Python exn pass through and ignore the current one
5348 else
5349 throw;
5350 } catch (const std::out_of_range& exn) {
5351 // catch out_of_range explicitly so the proper Python exn may be raised
5352 PyErr_SetString(PyExc_IndexError, exn.what());
5353 } catch (const std::exception& exn) {
5354 PyErr_SetString(PyExc_RuntimeError, exn.what());
5355 }
5356 catch (...)
5357 {
5358 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5359 }
5360 }
5361 #endif
5362 """,
5363 impl = ""
5364 )
5366 #------------------------------------------------------------------------------------
5368 append_utility_code = UtilityCode(
5369 proto = """
5370 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5371 if (likely(PyList_CheckExact(L))) {
5372 if (PyList_Append(L, x) < 0) return NULL;
5373 Py_INCREF(Py_None);
5374 return Py_None; /* this is just to have an accurate signature */
5375 }
5376 else {
5377 PyObject *r, *m;
5378 m = __Pyx_GetAttrString(L, "append");
5379 if (!m) return NULL;
5380 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5381 Py_DECREF(m);
5382 return r;
5383 }
5384 }
5385 """,
5386 impl = ""
5387 )
5389 #------------------------------------------------------------------------------------
5391 # If the is_unsigned flag is set, we need to do some extra work to make
5392 # sure the index doesn't become negative.
5394 getitem_int_utility_code = UtilityCode(
5395 proto = """
5396 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5397 PyObject *r;
5398 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5399 r = PyList_GET_ITEM(o, i);
5400 Py_INCREF(r);
5401 }
5402 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
5403 r = PyTuple_GET_ITEM(o, i);
5404 Py_INCREF(r);
5405 }
5406 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
5407 r = PySequence_GetItem(o, i);
5408 else {
5409 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5410 if (!j)
5411 return 0;
5412 r = PyObject_GetItem(o, j);
5413 Py_DECREF(j);
5414 }
5415 return r;
5416 }
5417 """,
5418 impl = """
5419 """)
5421 #------------------------------------------------------------------------------------
5423 setitem_int_utility_code = UtilityCode(
5424 proto = """
5425 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
5426 int r;
5427 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5428 Py_DECREF(PyList_GET_ITEM(o, i));
5429 Py_INCREF(v);
5430 PyList_SET_ITEM(o, i, v);
5431 return 1;
5432 }
5433 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5434 r = PySequence_SetItem(o, i, v);
5435 else {
5436 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5437 if (!j)
5438 return -1;
5439 r = PyObject_SetItem(o, j, v);
5440 Py_DECREF(j);
5441 }
5442 return r;
5443 }
5444 """,
5445 impl = """
5446 """)
5448 #------------------------------------------------------------------------------------
5450 delitem_int_utility_code = UtilityCode(
5451 proto = """
5452 static INLINE int __Pyx_DelItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5453 int r;
5454 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5455 r = PySequence_DelItem(o, i);
5456 else {
5457 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
5458 if (!j)
5459 return -1;
5460 r = PyObject_DelItem(o, j);
5461 Py_DECREF(j);
5462 }
5463 return r;
5464 }
5465 """,
5466 impl = """
5467 """)
5469 #------------------------------------------------------------------------------------
5471 raise_noneattr_error_utility_code = UtilityCode(
5472 proto = """
5473 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5474 """,
5475 impl = """
5476 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5477 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5478 }
5479 """)
5481 raise_noneindex_error_utility_code = UtilityCode(
5482 proto = """
5483 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5484 """,
5485 impl = """
5486 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5487 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5488 }
5489 """)
