Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 1486:8a2e7b51e770

initial constant folding transform: calculate constant values in node.constant_result
author Stefan Behnel <scoder@users.berlios.de>
date Sat Dec 13 22:23:00 2008 +0100 (3 years ago)
parents ae2b5e4187b9
children 90f28b61a142
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 not_a_constant = object()
31 constant_value_not_set = object()
33 class ExprNode(Node):
34 # subexprs [string] Class var holding names of subexpr node attrs
35 # type PyrexType Type of the result
36 # result_code string Code fragment
37 # result_ctype string C type of result_code if different from type
38 # is_temp boolean Result is in a temporary variable
39 # is_sequence_constructor
40 # boolean Is a list or tuple constructor expression
41 # saved_subexpr_nodes
42 # [ExprNode or [ExprNode or None] or None]
43 # Cached result of subexpr_nodes()
45 result_ctype = None
46 type = None
48 # The Analyse Expressions phase for expressions is split
49 # into two sub-phases:
50 #
51 # Analyse Types
52 # Determines the result type of the expression based
53 # on the types of its sub-expressions, and inserts
54 # coercion nodes into the expression tree where needed.
55 # Marks nodes which will need to have temporary variables
56 # allocated.
57 #
58 # Allocate Temps
59 # Allocates temporary variables where needed, and fills
60 # in the result_code field of each node.
61 #
62 # ExprNode provides some convenience routines which
63 # perform both of the above phases. These should only
64 # be called from statement nodes, and only when no
65 # coercion nodes need to be added around the expression
66 # being analysed. In that case, the above two phases
67 # should be invoked separately.
68 #
69 # Framework code in ExprNode provides much of the common
70 # processing for the various phases. It makes use of the
71 # 'subexprs' class attribute of ExprNodes, which should
72 # contain a list of the names of attributes which can
73 # hold sub-nodes or sequences of sub-nodes.
74 #
75 # The framework makes use of a number of abstract methods.
76 # Their responsibilities are as follows.
77 #
78 # Declaration Analysis phase
79 #
80 # analyse_target_declaration
81 # Called during the Analyse Declarations phase to analyse
82 # the LHS of an assignment or argument of a del statement.
83 # Nodes which cannot be the LHS of an assignment need not
84 # implement it.
85 #
86 # Expression Analysis phase
87 #
88 # analyse_types
89 # - Call analyse_types on all sub-expressions.
90 # - Check operand types, and wrap coercion nodes around
91 # sub-expressions where needed.
92 # - Set the type of this node.
93 # - If a temporary variable will be required for the
94 # result, set the is_temp flag of this node.
95 #
96 # analyse_target_types
97 # Called during the Analyse Types phase to analyse
98 # the LHS of an assignment or argument of a del
99 # statement. Similar responsibilities to analyse_types.
100 #
101 # allocate_temps
102 # - Call allocate_temps for all sub-nodes.
103 # - Call allocate_temp for this node.
104 # - If a temporary was allocated, call release_temp on
105 # all sub-expressions.
106 #
107 # allocate_target_temps
108 # - Call allocate_temps on sub-nodes and allocate any other
109 # temps used during assignment.
110 # - Fill in result_code with a C lvalue if needed.
111 # - If a rhs node is supplied, call release_temp on it.
112 # - Call release_temp on sub-nodes and release any other
113 # temps used during assignment.
114 #
115 # target_code
116 # Called by the default implementation of allocate_target_temps.
117 # Should return a C lvalue for assigning to the node. The default
118 # implementation calls calculate_result_code.
119 #
120 # check_const
121 # - Check that this node and its subnodes form a
122 # legal constant expression. If so, do nothing,
123 # otherwise call not_const.
124 #
125 # The default implementation of check_const
126 # assumes that the expression is not constant.
127 #
128 # check_const_addr
129 # - Same as check_const, except check that the
130 # expression is a C lvalue whose address is
131 # constant. Otherwise, call addr_not_const.
132 #
133 # The default implementation of calc_const_addr
134 # assumes that the expression is not a constant
135 # lvalue.
136 #
137 # Code Generation phase
138 #
139 # generate_evaluation_code
140 # - Call generate_evaluation_code for sub-expressions.
141 # - Perform the functions of generate_result_code
142 # (see below).
143 # - If result is temporary, call generate_disposal_code
144 # on all sub-expressions.
145 #
146 # A default implementation of generate_evaluation_code
147 # is provided which uses the following abstract methods:
148 #
149 # generate_result_code
150 # - Generate any C statements necessary to calculate
151 # the result of this node from the results of its
152 # sub-expressions.
153 #
154 # calculate_result_code
155 # - Should return a C code fragment evaluating to the
156 # result. This is only called when the result is not
157 # a temporary.
158 #
159 # generate_assignment_code
160 # Called on the LHS of an assignment.
161 # - Call generate_evaluation_code for sub-expressions.
162 # - Generate code to perform the assignment.
163 # - If the assignment absorbed a reference, call
164 # generate_post_assignment_code on the RHS,
165 # otherwise call generate_disposal_code on it.
166 #
167 # generate_deletion_code
168 # Called on an argument of a del statement.
169 # - Call generate_evaluation_code for sub-expressions.
170 # - Generate code to perform the deletion.
171 # - Call generate_disposal_code on all sub-expressions.
172 #
173 #
175 is_sequence_constructor = 0
176 is_attribute = 0
178 saved_subexpr_nodes = None
179 is_temp = 0
180 is_target = 0
182 constant_result = constant_value_not_set
184 def get_child_attrs(self):
185 return self.subexprs
186 child_attrs = property(fget=get_child_attrs)
188 def not_implemented(self, method_name):
189 print_call_chain(method_name, "not implemented") ###
190 raise InternalError(
191 "%s.%s not implemented" %
192 (self.__class__.__name__, method_name))
194 def is_lvalue(self):
195 return 0
197 def is_ephemeral(self):
198 # An ephemeral node is one whose result is in
199 # a Python temporary and we suspect there are no
200 # other references to it. Certain operations are
201 # disallowed on such values, since they are
202 # likely to result in a dangling pointer.
203 return self.type.is_pyobject and self.is_temp
205 def subexpr_nodes(self):
206 # Extract a list of subexpression nodes based
207 # on the contents of the subexprs class attribute.
208 nodes = []
209 for name in self.subexprs:
210 item = getattr(self, name)
211 if item:
212 if isinstance(item, ExprNode):
213 nodes.append(item)
214 else:
215 nodes.extend(item)
216 return nodes
218 def result(self):
219 if not self.is_temp or self.is_target:
220 return self.calculate_result_code()
221 else: # i.e. self.is_temp:
222 return self.result_code
224 def result_as(self, type = None):
225 # Return the result code cast to the specified C type.
226 return typecast(type, self.ctype(), self.result())
228 def py_result(self):
229 # Return the result code cast to PyObject *.
230 return self.result_as(py_object_type)
232 def ctype(self):
233 # Return the native C type of the result (i.e. the
234 # C type of the result_code expression).
235 return self.result_ctype or self.type
237 def calculate_constant_result(self):
238 # Calculate the constant result of this expression and store
239 # it in ``self.constant_result``. Does nothing by default,
240 # thus leaving ``self.constant_result`` unknown.
241 #
242 # This must only be called when it is assured that all
243 # sub-expressions have a valid constant_result value. The
244 # ConstantFolding transform will do this.
245 pass
247 def compile_time_value(self, denv):
248 # Return value of compile-time expression, or report error.
249 error(self.pos, "Invalid compile-time expression")
251 def compile_time_value_error(self, e):
252 error(self.pos, "Error in compile-time expression: %s: %s" % (
253 e.__class__.__name__, e))
255 # ------------- Declaration Analysis ----------------
257 def analyse_target_declaration(self, env):
258 error(self.pos, "Cannot assign to or delete this")
260 # ------------- Expression Analysis ----------------
262 def analyse_const_expression(self, env):
263 # Called during the analyse_declarations phase of a
264 # constant expression. Analyses the expression's type,
265 # checks whether it is a legal const expression,
266 # and determines its value.
267 self.analyse_types(env)
268 self.allocate_temps(env)
269 self.check_const()
271 def analyse_expressions(self, env):
272 # Convenience routine performing both the Type
273 # Analysis and Temp Allocation phases for a whole
274 # expression.
275 self.analyse_types(env)
276 self.allocate_temps(env)
278 def analyse_target_expression(self, env, rhs):
279 # Convenience routine performing both the Type
280 # Analysis and Temp Allocation phases for the LHS of
281 # an assignment.
282 self.analyse_target_types(env)
283 self.allocate_target_temps(env, rhs)
285 def analyse_boolean_expression(self, env):
286 # Analyse expression and coerce to a boolean.
287 self.analyse_types(env)
288 bool = self.coerce_to_boolean(env)
289 bool.allocate_temps(env)
290 return bool
292 def analyse_temp_boolean_expression(self, env):
293 # Analyse boolean expression and coerce result into
294 # a temporary. This is used when a branch is to be
295 # performed on the result and we won't have an
296 # opportunity to ensure disposal code is executed
297 # afterwards. By forcing the result into a temporary,
298 # we ensure that all disposal has been done by the
299 # time we get the result.
300 self.analyse_types(env)
301 bool = self.coerce_to_boolean(env)
302 temp_bool = bool.coerce_to_temp(env)
303 temp_bool.allocate_temps(env)
304 return temp_bool
306 # --------------- Type Analysis ------------------
308 def analyse_as_module(self, env):
309 # If this node can be interpreted as a reference to a
310 # cimported module, return its scope, else None.
311 return None
313 def analyse_as_type(self, env):
314 # If this node can be interpreted as a reference to a
315 # type, return that type, else None.
316 return None
318 def analyse_as_extension_type(self, env):
319 # If this node can be interpreted as a reference to an
320 # extension type, return its type, else None.
321 return None
323 def analyse_types(self, env):
324 self.not_implemented("analyse_types")
326 def analyse_target_types(self, env):
327 self.analyse_types(env)
329 def gil_assignment_check(self, env):
330 if env.nogil and self.type.is_pyobject:
331 error(self.pos, "Assignment of Python object not allowed without gil")
333 def check_const(self):
334 self.not_const()
336 def not_const(self):
337 error(self.pos, "Not allowed in a constant expression")
339 def check_const_addr(self):
340 self.addr_not_const()
342 def addr_not_const(self):
343 error(self.pos, "Address is not constant")
345 def gil_check(self, env):
346 if env.nogil and self.type.is_pyobject:
347 self.gil_error()
349 # ----------------- Result Allocation -----------------
351 def result_in_temp(self):
352 # Return true if result is in a temporary owned by
353 # this node or one of its subexpressions. Overridden
354 # by certain nodes which can share the result of
355 # a subnode.
356 return self.is_temp
358 def allocate_target_temps(self, env, rhs):
359 # Perform temp allocation for the LHS of an assignment.
360 if debug_temp_alloc:
361 print("%s Allocating target temps" % self)
362 self.allocate_subexpr_temps(env)
363 self.is_target = True
364 if rhs:
365 rhs.release_temp(env)
366 self.release_subexpr_temps(env)
368 def allocate_temps(self, env, result = None):
369 # Allocate temporary variables for this node and
370 # all its sub-expressions. If a result is specified,
371 # this must be a temp node and the specified variable
372 # is used as the result instead of allocating a new
373 # one.
374 if debug_temp_alloc:
375 print("%s Allocating temps" % self)
376 self.allocate_subexpr_temps(env)
377 self.allocate_temp(env, result)
378 if self.is_temp:
379 self.release_subexpr_temps(env)
381 def allocate_subexpr_temps(self, env):
382 # Allocate temporary variables for all sub-expressions
383 # of this node.
384 if debug_temp_alloc:
385 print("%s Allocating temps for: %s" % (self, self.subexprs))
386 for node in self.subexpr_nodes():
387 if node:
388 if debug_temp_alloc:
389 print("%s Allocating temps for %s" % (self, node))
390 node.allocate_temps(env)
392 def allocate_temp(self, env, result = None):
393 # If this node requires a temporary variable for its
394 # result, allocate one, otherwise set the result to
395 # a C code fragment. If a result is specified,
396 # this must be a temp node and the specified variable
397 # is used as the result instead of allocating a new
398 # one.
399 if debug_temp_alloc:
400 print("%s Allocating temp" % self)
401 if result:
402 if not self.is_temp:
403 raise InternalError("Result forced on non-temp node")
404 self.result_code = result
405 elif self.is_temp:
406 type = self.type
407 if not type.is_void:
408 if type.is_pyobject:
409 type = PyrexTypes.py_object_type
410 self.result_code = env.allocate_temp(type)
411 else:
412 self.result_code = None
413 if debug_temp_alloc:
414 print("%s Allocated result %s" % (self, self.result_code))
416 def target_code(self):
417 # Return code fragment for use as LHS of a C assignment.
418 return self.calculate_result_code()
420 def calculate_result_code(self):
421 self.not_implemented("calculate_result_code")
423 # def release_target_temp(self, env):
424 # # Release temporaries used by LHS of an assignment.
425 # self.release_subexpr_temps(env)
427 def release_temp(self, env):
428 # If this node owns a temporary result, release it,
429 # otherwise release results of its sub-expressions.
430 if self.is_temp:
431 if debug_temp_alloc:
432 print("%s Releasing result %s" % (self, self.result_code))
433 env.release_temp(self.result_code)
434 else:
435 self.release_subexpr_temps(env)
437 def release_subexpr_temps(self, env):
438 # Release the results of all sub-expressions of
439 # this node.
440 for node in self.subexpr_nodes():
441 if node:
442 node.release_temp(env)
444 # ---------------- Code Generation -----------------
446 def make_owned_reference(self, code):
447 # If result is a pyobject, make sure we own
448 # a reference to it.
449 if self.type.is_pyobject and not self.result_in_temp():
450 code.put_incref(self.result(), self.ctype())
452 def generate_evaluation_code(self, code):
453 code.mark_pos(self.pos)
454 # Generate code to evaluate this node and
455 # its sub-expressions, and dispose of any
456 # temporary results of its sub-expressions.
457 self.generate_subexpr_evaluation_code(code)
458 self.generate_result_code(code)
459 if self.is_temp:
460 self.generate_subexpr_disposal_code(code)
461 self.free_subexpr_temps(code)
463 def generate_subexpr_evaluation_code(self, code):
464 for node in self.subexpr_nodes():
465 node.generate_evaluation_code(code)
467 def generate_result_code(self, code):
468 self.not_implemented("generate_result_code")
470 def generate_disposal_code(self, code):
471 # If necessary, generate code to dispose of
472 # temporary Python reference.
473 if self.is_temp:
474 if self.type.is_pyobject:
475 code.put_decref_clear(self.result(), self.ctype())
476 else:
477 self.generate_subexpr_disposal_code(code)
479 def generate_subexpr_disposal_code(self, code):
480 # Generate code to dispose of temporary results
481 # of all sub-expressions.
482 for node in self.subexpr_nodes():
483 node.generate_disposal_code(code)
485 def generate_post_assignment_code(self, code):
486 # Same as generate_disposal_code except that
487 # assignment will have absorbed a reference to
488 # the result if it is a Python object.
489 if self.is_temp:
490 if self.type.is_pyobject:
491 code.putln("%s = 0;" % self.result())
492 else:
493 self.generate_subexpr_disposal_code(code)
495 def generate_assignment_code(self, rhs, code):
496 # Stub method for nodes which are not legal as
497 # the LHS of an assignment. An error will have
498 # been reported earlier.
499 pass
501 def generate_deletion_code(self, code):
502 # Stub method for nodes that are not legal as
503 # the argument of a del statement. An error
504 # will have been reported earlier.
505 pass
507 def free_temps(self, code):
508 pass
510 def free_subexpr_temps(self, code):
511 for sub in self.subexpr_nodes():
512 sub.free_temps(code)
514 # ---------------- Annotation ---------------------
516 def annotate(self, code):
517 for node in self.subexpr_nodes():
518 node.annotate(code)
520 # ----------------- Coercion ----------------------
522 def coerce_to(self, dst_type, env):
523 # Coerce the result so that it can be assigned to
524 # something of type dst_type. If processing is necessary,
525 # wraps this node in a coercion node and returns that.
526 # Otherwise, returns this node unchanged.
527 #
528 # This method is called during the analyse_expressions
529 # phase of the src_node's processing.
530 src = self
531 src_type = self.type
532 src_is_py_type = src_type.is_pyobject
533 dst_is_py_type = dst_type.is_pyobject
535 if dst_type.is_pyobject:
536 if not src.type.is_pyobject:
537 src = CoerceToPyTypeNode(src, env)
538 if not src.type.subtype_of(dst_type):
539 if not isinstance(src, NoneNode):
540 src = PyTypeTestNode(src, dst_type, env)
541 elif src.type.is_pyobject:
542 src = CoerceFromPyTypeNode(dst_type, src, env)
543 else: # neither src nor dst are py types
544 # Added the string comparison, since for c types that
545 # is enough, but Cython gets confused when the types are
546 # in different files.
547 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
548 error(self.pos, "Cannot assign type '%s' to '%s'" %
549 (src.type, dst_type))
550 return src
552 def coerce_to_pyobject(self, env):
553 return self.coerce_to(PyrexTypes.py_object_type, env)
555 def coerce_to_boolean(self, env):
556 # Coerce result to something acceptable as
557 # a boolean value.
558 type = self.type
559 if type.is_pyobject or type.is_ptr or type.is_float:
560 return CoerceToBooleanNode(self, env)
561 else:
562 if not type.is_int and not type.is_error:
563 error(self.pos,
564 "Type '%s' not acceptable as a boolean" % type)
565 return self
567 def coerce_to_integer(self, env):
568 # If not already some C integer type, coerce to longint.
569 if self.type.is_int:
570 return self
571 else:
572 return self.coerce_to(PyrexTypes.c_long_type, env)
574 def coerce_to_temp(self, env):
575 # Ensure that the result is in a temporary.
576 if self.result_in_temp():
577 return self
578 else:
579 return CoerceToTempNode(self, env)
581 def coerce_to_simple(self, env):
582 # Ensure that the result is simple (see is_simple).
583 if self.is_simple():
584 return self
585 else:
586 return self.coerce_to_temp(env)
588 def is_simple(self):
589 # A node is simple if its result is something that can
590 # be referred to without performing any operations, e.g.
591 # a constant, local var, C global var, struct member
592 # reference, or temporary.
593 return self.result_in_temp()
595 def as_cython_attribute(self):
596 return None
599 class RemoveAllocateTemps(type):
600 def __init__(cls, name, bases, dct):
601 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
602 def noop(self, env): pass
603 setattr(cls, 'allocate_temps', noop)
604 setattr(cls, 'allocate_temp', noop)
605 setattr(cls, 'release_temp', noop)
607 class NewTempExprNode(ExprNode):
608 backwards_compatible_result = None
609 temp_code = None
611 # Do not enable this unless you are trying to make all ExprNodes
612 # NewTempExprNodes (child nodes reached via recursion may not have
613 # transferred).
614 # __metaclass__ = RemoveAllocateTemps
616 def result(self):
617 if self.is_temp:
618 return self.temp_code
619 else:
620 return self.calculate_result_code()
622 def allocate_target_temps(self, env, rhs):
623 self.allocate_subexpr_temps(env)
624 self.is_target = True
625 if rhs:
626 rhs.release_temp(env)
627 self.release_subexpr_temps(env)
629 def allocate_temps(self, env, result = None):
630 self.allocate_subexpr_temps(env)
631 self.backwards_compatible_result = result
632 if self.is_temp:
633 self.release_subexpr_temps(env)
635 def allocate_temp(self, env, result = None):
636 assert result is None
638 def release_temp(self, env):
639 if self.is_temp:
640 pass
641 else:
642 self.release_subexpr_temps(env)
644 def allocate_temp_result(self, code):
645 if self.temp_code:
646 raise RuntimeError("Temp allocated multiple times")
647 type = self.type
648 if not type.is_void:
649 if type.is_pyobject:
650 type = PyrexTypes.py_object_type
651 if self.backwards_compatible_result:
652 self.temp_code = self.backwards_compatible_result
653 else:
654 self.temp_code = code.funcstate.allocate_temp(
655 type, manage_ref=True)
656 else:
657 self.temp_code = None
659 def release_temp_result(self, code):
660 if not self.temp_code:
661 if self.old_temp:
662 raise RuntimeError("temp %s released multiple times in %s" % (
663 self.old_temp, self.__class__.__name__))
664 else:
665 raise RuntimeError("no temp, but release requested in %s" % (
666 self.__class__.__name__))
667 code.funcstate.release_temp(self.temp_code)
668 self.old_temp = self.temp_code
669 self.temp_code = None
671 def generate_evaluation_code(self, code):
672 code.mark_pos(self.pos)
674 # Generate code to evaluate this node and
675 # its sub-expressions, and dispose of any
676 # temporary results of its sub-expressions.
677 self.generate_subexpr_evaluation_code(code)
679 if self.is_temp:
680 self.allocate_temp_result(code)
682 self.generate_result_code(code)
683 if self.is_temp:
684 # If we are temp we do not need to wait until this node is disposed
685 # before disposing children.
686 self.generate_subexpr_disposal_code(code)
687 self.free_subexpr_temps(code)
689 def generate_disposal_code(self, code):
690 if self.is_temp:
691 if self.type.is_pyobject:
692 code.put_decref_clear(self.result(), self.ctype())
693 else:
694 # Already done if self.is_temp
695 self.generate_subexpr_disposal_code(code)
697 def generate_post_assignment_code(self, code):
698 if self.is_temp:
699 if self.type.is_pyobject:
700 code.putln("%s = 0;" % self.result())
701 else:
702 self.generate_subexpr_disposal_code(code)
704 def free_temps(self, code):
705 if self.is_temp:
706 if not self.type.is_void:
707 self.release_temp_result(code)
708 else:
709 self.free_subexpr_temps(code)
711 # ExprNode = NewTempExprNode
713 class AtomicExprNode(ExprNode):
714 # Abstract base class for expression nodes which have
715 # no sub-expressions.
717 subexprs = []
719 class AtomicNewTempExprNode(NewTempExprNode):
720 # I do not dare to convert NameNode yet. This is now
721 # ancestor of all former AtomicExprNode except
722 # NameNode. Should be renamed to AtomicExprNode
723 # when done.
725 # Abstract base class for expression nodes which have
726 # no sub-expressions.
728 subexprs = []
730 # Override to optimize -- we know we have no children
731 def generate_subexpr_evaluation_code(self, code):
732 pass
733 def generate_subexpr_disposal_code(self, code):
734 pass
736 class PyConstNode(AtomicNewTempExprNode):
737 # Abstract base class for constant Python values.
739 is_literal = 1
741 def is_simple(self):
742 return 1
744 def analyse_types(self, env):
745 self.type = py_object_type
747 def calculate_result_code(self):
748 return self.value
750 def generate_result_code(self, code):
751 pass
754 class NoneNode(PyConstNode):
755 # The constant value None
757 value = "Py_None"
759 constant_result = None
761 def compile_time_value(self, denv):
762 return None
764 class EllipsisNode(PyConstNode):
765 # '...' in a subscript list.
767 value = "Py_Ellipsis"
769 constant_result = Ellipsis
771 def compile_time_value(self, denv):
772 return Ellipsis
775 class ConstNode(AtomicNewTempExprNode):
776 # Abstract base type for literal constant nodes.
777 #
778 # value string C code fragment
780 is_literal = 1
782 def is_simple(self):
783 return 1
785 def analyse_types(self, env):
786 pass # Types are held in class variables
788 def check_const(self):
789 pass
791 def calculate_result_code(self):
792 return str(self.value)
794 def generate_result_code(self, code):
795 pass
798 class BoolNode(ConstNode):
799 type = PyrexTypes.c_bint_type
800 # The constant value True or False
802 def calculate_constant_result(self):
803 self.constant_result = self.value
805 def compile_time_value(self, denv):
806 return self.value
808 def calculate_result_code(self):
809 return str(int(self.value))
811 class NullNode(ConstNode):
812 type = PyrexTypes.c_null_ptr_type
813 value = "NULL"
814 constant_result = 0
817 class CharNode(ConstNode):
818 type = PyrexTypes.c_char_type
820 def calculate_constant_result(self):
821 self.constant_result = ord(self.value)
823 def compile_time_value(self, denv):
824 return ord(self.value)
826 def calculate_result_code(self):
827 return "'%s'" % StringEncoding.escape_character(self.value)
830 class IntNode(ConstNode):
832 # unsigned "" or "U"
833 # longness "" or "L" or "LL"
835 unsigned = ""
836 longness = ""
837 type = PyrexTypes.c_long_type
839 def coerce_to(self, dst_type, env):
840 if dst_type.is_numeric:
841 self.type = PyrexTypes.c_long_type
842 return self
843 # Arrange for a Python version of the number to be pre-allocated
844 # when coercing to a Python type.
845 if dst_type.is_pyobject:
846 self.entry = env.get_py_num(self.value, self.longness)
847 self.type = PyrexTypes.py_object_type
848 # We still need to perform normal coerce_to processing on the
849 # result, because we might be coercing to an extension type,
850 # in which case a type test node will be needed.
851 return ConstNode.coerce_to(self, dst_type, env)
853 def coerce_to_boolean(self, env):
854 self.type = PyrexTypes.c_bint_type
855 return self
857 def calculate_result_code(self):
858 if self.type.is_pyobject:
859 return self.entry.cname
860 else:
861 return str(self.value) + self.unsigned + self.longness
863 def calculate_constant_result(self):
864 self.constant_result = int(self.value, 0)
866 def compile_time_value(self, denv):
867 return int(self.value, 0)
870 class FloatNode(ConstNode):
871 type = PyrexTypes.c_double_type
873 def compile_time_value(self, denv):
874 return float(self.value)
876 def calculate_result_code(self):
877 strval = str(self.value)
878 if strval == 'nan':
879 return "(Py_HUGE_VAL * 0)"
880 elif strval == 'inf':
881 return "Py_HUGE_VAL"
882 elif strval == '-inf':
883 return "(-Py_HUGE_VAL)"
884 else:
885 return strval
888 class StringNode(ConstNode):
889 # entry Symtab.Entry
891 type = PyrexTypes.c_char_ptr_type
893 def compile_time_value(self, denv):
894 return self.value
896 def analyse_types(self, env):
897 self.entry = env.add_string_const(self.value)
899 def analyse_as_type(self, env):
900 type = PyrexTypes.parse_basic_type(self.value)
901 if type is not None:
902 return type
903 from TreeFragment import TreeFragment
904 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
905 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
906 sizeof_node = declaration.root.stats[0].expr
907 sizeof_node.analyse_types(env)
908 if isinstance(sizeof_node, SizeofTypeNode):
909 return sizeof_node.arg_type
911 def coerce_to(self, dst_type, env):
912 if dst_type == PyrexTypes.c_char_ptr_type:
913 self.type = PyrexTypes.c_char_ptr_type
914 return self
916 if dst_type.is_int:
917 if not self.type.is_pyobject and len(self.entry.init) == 1:
918 return CharNode(self.pos, value=self.value)
919 else:
920 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
921 return self
922 # Arrange for a Python version of the string to be pre-allocated
923 # when coercing to a Python type.
924 if dst_type.is_pyobject and not self.type.is_pyobject:
925 node = self.as_py_string_node(env)
926 else:
927 node = self
928 # We still need to perform normal coerce_to processing on the
929 # result, because we might be coercing to an extension type,
930 # in which case a type test node will be needed.
931 return ConstNode.coerce_to(node, dst_type, env)
933 def as_py_string_node(self, env):
934 # Return a new StringNode with the same entry as this node
935 # but whose type is a Python type instead of a C type.
936 entry = self.entry
937 env.add_py_string(entry)
938 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
940 def calculate_result_code(self):
941 if self.type.is_pyobject:
942 return self.entry.pystring_cname
943 else:
944 return self.entry.cname
947 class UnicodeNode(PyConstNode):
948 # entry Symtab.Entry
950 type = unicode_type
952 def analyse_types(self, env):
953 self.entry = env.add_string_const(self.value)
954 env.add_py_string(self.entry)
956 def calculate_result_code(self):
957 return self.entry.pystring_cname
959 def _coerce_to(self, dst_type, env):
960 if not dst_type.is_pyobject:
961 node = StringNode(self.pos, entry = entry, type = py_object_type)
962 return ConstNode.coerce_to(node, dst_type, env)
963 else:
964 return self
965 # We still need to perform normal coerce_to processing on the
966 # result, because we might be coercing to an extension type,
967 # in which case a type test node will be needed.
969 def compile_time_value(self, env):
970 return self.value
973 class IdentifierStringNode(ConstNode):
974 # A Python string that behaves like an identifier, e.g. for
975 # keyword arguments in a call, or for imported names
976 type = PyrexTypes.py_object_type
978 def analyse_types(self, env):
979 self.cname = env.intern_identifier(self.value)
981 def calculate_result_code(self):
982 return self.cname
985 class LongNode(AtomicNewTempExprNode):
986 # Python long integer literal
987 #
988 # value string
990 def calculate_constant_result(self):
991 self.constant_result = long(self.value)
993 def compile_time_value(self, denv):
994 return long(self.value)
996 gil_message = "Constructing Python long int"
998 def analyse_types(self, env):
999 self.type = py_object_type
1000 self.gil_check(env)
1001 self.is_temp = 1
1003 gil_message = "Constructing Python long int"
1005 def generate_result_code(self, code):
1006 code.putln(
1007 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1008 self.result(),
1009 self.value,
1010 code.error_goto_if_null(self.result(), self.pos)))
1013 class ImagNode(AtomicNewTempExprNode):
1014 # Imaginary number literal
1016 # value float imaginary part
1018 def calculate_constant_result(self):
1019 self.constant_result = complex(0.0, self.value)
1021 def compile_time_value(self, denv):
1022 return complex(0.0, self.value)
1024 def analyse_types(self, env):
1025 self.type = py_object_type
1026 self.gil_check(env)
1027 self.is_temp = 1
1029 gil_message = "Constructing complex number"
1031 def generate_result_code(self, code):
1032 code.putln(
1033 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
1034 self.result(),
1035 self.value,
1036 code.error_goto_if_null(self.result(), self.pos)))
1039 class NameNode(AtomicExprNode):
1040 # Reference to a local or global variable name.
1042 # name string Python name of the variable
1044 # entry Entry Symbol table entry
1045 # interned_cname string
1047 is_name = True
1048 is_cython_module = False
1049 cython_attribute = None
1050 lhs_of_first_assignment = False
1051 entry = None
1053 def create_analysed_rvalue(pos, env, entry):
1054 node = NameNode(pos)
1055 node.analyse_types(env, entry=entry)
1056 return node
1058 def as_cython_attribute(self):
1059 return self.cython_attribute
1061 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1063 def compile_time_value(self, denv):
1064 try:
1065 return denv.lookup(self.name)
1066 except KeyError:
1067 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1069 def coerce_to(self, dst_type, env):
1070 # If coercing to a generic pyobject and this is a builtin
1071 # C function with a Python equivalent, manufacture a NameNode
1072 # referring to the Python builtin.
1073 #print "NameNode.coerce_to:", self.name, dst_type ###
1074 if dst_type is py_object_type:
1075 entry = self.entry
1076 if entry and entry.is_cfunction:
1077 var_entry = entry.as_variable
1078 if var_entry:
1079 if var_entry.is_builtin and Options.cache_builtins:
1080 var_entry = env.declare_builtin(var_entry.name, self.pos)
1081 node = NameNode(self.pos, name = self.name)
1082 node.entry = var_entry
1083 node.analyse_rvalue_entry(env)
1084 return node
1085 return AtomicExprNode.coerce_to(self, dst_type, env)
1087 def analyse_as_module(self, env):
1088 # Try to interpret this as a reference to a cimported module.
1089 # Returns the module scope, or None.
1090 entry = self.entry
1091 if not entry:
1092 entry = env.lookup(self.name)
1093 if entry and entry.as_module:
1094 return entry.as_module
1095 return None
1097 def analyse_as_type(self, env):
1098 if self.cython_attribute:
1099 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1100 else:
1101 type = PyrexTypes.parse_basic_type(self.name)
1102 if type:
1103 return type
1104 entry = self.entry
1105 if not entry:
1106 entry = env.lookup(self.name)
1107 if entry and entry.is_type:
1108 return entry.type
1109 else:
1110 return None
1112 def analyse_as_extension_type(self, env):
1113 # Try to interpret this as a reference to an extension type.
1114 # Returns the extension type, or None.
1115 entry = self.entry
1116 if not entry:
1117 entry = env.lookup(self.name)
1118 if entry and entry.is_type and entry.type.is_extension_type:
1119 return entry.type
1120 else:
1121 return None
1123 def analyse_target_declaration(self, env):
1124 if not self.entry:
1125 self.entry = env.lookup_here(self.name)
1126 if not self.entry:
1127 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1128 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1129 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1130 if self.entry.is_declared_generic:
1131 self.result_ctype = py_object_type
1133 def analyse_types(self, env):
1134 if self.entry is None:
1135 self.entry = env.lookup(self.name)
1136 if not self.entry:
1137 self.entry = env.declare_builtin(self.name, self.pos)
1138 if not self.entry:
1139 self.type = PyrexTypes.error_type
1140 return
1141 self.analyse_rvalue_entry(env)
1143 def analyse_target_types(self, env):
1144 self.analyse_entry(env)
1145 if not self.is_lvalue():
1146 error(self.pos, "Assignment to non-lvalue '%s'"
1147 % self.name)
1148 self.type = PyrexTypes.error_type
1149 self.entry.used = 1
1150 if self.entry.type.is_buffer:
1151 import Buffer
1152 Buffer.used_buffer_aux_vars(self.entry)
1154 def analyse_rvalue_entry(self, env):
1155 #print "NameNode.analyse_rvalue_entry:", self.name ###
1156 #print "Entry:", self.entry.__dict__ ###
1157 self.analyse_entry(env)
1158 entry = self.entry
1159 if entry.is_declared_generic:
1160 self.result_ctype = py_object_type
1161 if entry.is_pyglobal or entry.is_builtin:
1162 if Options.cache_builtins and entry.is_builtin:
1163 self.is_temp = 0
1164 else:
1165 self.is_temp = 1
1166 env.use_utility_code(get_name_interned_utility_code)
1167 self.gil_check(env)
1169 gil_message = "Accessing Python global or builtin"
1171 def analyse_entry(self, env):
1172 #print "NameNode.analyse_entry:", self.name ###
1173 self.check_identifier_kind()
1174 entry = self.entry
1175 type = entry.type
1176 self.type = type
1177 if entry.is_pyglobal or entry.is_builtin:
1178 assert type.is_pyobject, "Python global or builtin not a Python object"
1179 self.interned_cname = self.entry.interned_cname = \
1180 env.intern_identifier(self.entry.name)
1182 def check_identifier_kind(self):
1183 #print "NameNode.check_identifier_kind:", self.entry.name ###
1184 #print self.entry.__dict__ ###
1185 entry = self.entry
1186 #entry.used = 1
1187 if not (entry.is_const or entry.is_variable
1188 or entry.is_builtin or entry.is_cfunction):
1189 if self.entry.as_variable:
1190 self.entry = self.entry.as_variable
1191 else:
1192 error(self.pos,
1193 "'%s' is not a constant, variable or function identifier" % self.name)
1195 def is_simple(self):
1196 # If it's not a C variable, it'll be in a temp.
1197 return 1
1199 def calculate_target_results(self, env):
1200 pass
1202 def check_const(self):
1203 entry = self.entry
1204 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1205 self.not_const()
1207 def check_const_addr(self):
1208 entry = self.entry
1209 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1210 self.addr_not_const()
1212 def is_lvalue(self):
1213 return self.entry.is_variable and \
1214 not self.entry.type.is_array and \
1215 not self.entry.is_readonly
1217 def is_ephemeral(self):
1218 # Name nodes are never ephemeral, even if the
1219 # result is in a temporary.
1220 return 0
1222 def allocate_temp(self, env, result = None):
1223 AtomicExprNode.allocate_temp(self, env, result)
1224 entry = self.entry
1225 if entry:
1226 entry.used = 1
1227 if entry.type.is_buffer:
1228 import Buffer
1229 Buffer.used_buffer_aux_vars(entry)
1230 if entry.utility_code:
1231 env.use_utility_code(entry.utility_code)
1233 def calculate_result_code(self):
1234 entry = self.entry
1235 if not entry:
1236 return "<error>" # There was an error earlier
1237 return entry.cname
1239 def generate_result_code(self, code):
1240 assert hasattr(self, 'entry')
1241 entry = self.entry
1242 if entry is None:
1243 return # There was an error earlier
1244 if entry.is_builtin and Options.cache_builtins:
1245 return # Lookup already cached
1246 elif entry.is_pyglobal or entry.is_builtin:
1247 if entry.is_builtin:
1248 namespace = Naming.builtins_cname
1249 else: # entry.is_pyglobal
1250 namespace = entry.scope.namespace_cname
1251 code.putln(
1252 '%s = __Pyx_GetName(%s, %s); %s' % (
1253 self.result(),
1254 namespace,
1255 self.interned_cname,
1256 code.error_goto_if_null(self.result(), self.pos)))
1257 elif entry.is_local and False:
1258 # control flow not good enough yet
1259 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1260 if assigned is False:
1261 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1262 elif not Options.init_local_none and assigned is None:
1263 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1264 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1266 def generate_assignment_code(self, rhs, code):
1267 #print "NameNode.generate_assignment_code:", self.name ###
1268 entry = self.entry
1269 if entry is None:
1270 return # There was an error earlier
1272 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1273 and not self.lhs_of_first_assignment):
1274 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1276 # is_pyglobal seems to be True for module level-globals only.
1277 # We use this to access class->tp_dict if necessary.
1278 if entry.is_pyglobal:
1279 namespace = self.entry.scope.namespace_cname
1280 if entry.is_member:
1281 # if the entry is a member we have to cheat: SetAttr does not work
1282 # on types, so we create a descriptor which is then added to tp_dict
1283 code.put_error_if_neg(self.pos,
1284 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1285 namespace,
1286 self.interned_cname,
1287 rhs.py_result()))
1288 # in Py2.6+, we need to invalidate the method cache
1289 code.putln("PyType_Modified(%s);" %
1290 entry.scope.parent_type.typeptr_cname)
1291 else:
1292 code.put_error_if_neg(self.pos,
1293 'PyObject_SetAttr(%s, %s, %s)' % (
1294 namespace,
1295 self.interned_cname,
1296 rhs.py_result()))
1297 if debug_disposal_code:
1298 print("NameNode.generate_assignment_code:")
1299 print("...generating disposal code for %s" % rhs)
1300 rhs.generate_disposal_code(code)
1301 rhs.free_temps(code)
1302 else:
1303 if self.type.is_buffer:
1304 # Generate code for doing the buffer release/acquisition.
1305 # This might raise an exception in which case the assignment (done
1306 # below) will not happen.
1308 # The reason this is not in a typetest-like node is because the
1309 # variables that the acquired buffer info is stored to is allocated
1310 # per entry and coupled with it.
1311 self.generate_acquire_buffer(rhs, code)
1313 if self.type.is_pyobject:
1314 rhs.make_owned_reference(code)
1315 #print "NameNode.generate_assignment_code: to", self.name ###
1316 #print "...from", rhs ###
1317 #print "...LHS type", self.type, "ctype", self.ctype() ###
1318 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1319 if not self.lhs_of_first_assignment:
1320 if entry.is_local and not Options.init_local_none:
1321 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1322 if initalized is True:
1323 code.put_decref(self.result(), self.ctype())
1324 elif initalized is None:
1325 code.put_xdecref(self.result(), self.ctype())
1326 else:
1327 code.put_decref(self.result(), self.ctype())
1328 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1329 if debug_disposal_code:
1330 print("NameNode.generate_assignment_code:")
1331 print("...generating post-assignment code for %s" % rhs)
1332 rhs.generate_post_assignment_code(code)
1333 rhs.free_temps(code)
1335 def generate_acquire_buffer(self, rhs, code):
1336 # rhstmp is only used in case the rhs is a complicated expression leading to
1337 # the object, to avoid repeating the same C expression for every reference
1338 # to the rhs. It does NOT hold a reference.
1339 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1340 if pretty_rhs:
1341 rhstmp = rhs.result_as(self.ctype())
1342 else:
1343 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1344 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1346 buffer_aux = self.entry.buffer_aux
1347 bufstruct = buffer_aux.buffer_info_var.cname
1348 import Buffer
1349 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1350 is_initialized=not self.lhs_of_first_assignment,
1351 pos=self.pos, code=code)
1353 if not pretty_rhs:
1354 code.putln("%s = 0;" % rhstmp)
1355 code.funcstate.release_temp(rhstmp)
1357 def generate_deletion_code(self, code):
1358 if self.entry is None:
1359 return # There was an error earlier
1360 if not self.entry.is_pyglobal:
1361 error(self.pos, "Deletion of local or C global name not supported")
1362 return
1363 code.put_error_if_neg(self.pos,
1364 'PyObject_DelAttrString(%s, "%s")' % (
1365 Naming.module_cname,
1366 self.entry.name))
1368 def annotate(self, code):
1369 if hasattr(self, 'is_called') and self.is_called:
1370 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1371 if self.type.is_pyobject:
1372 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1373 else:
1374 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1376 class BackquoteNode(ExprNode):
1377 # `expr`
1379 # arg ExprNode
1381 subexprs = ['arg']
1383 def analyse_types(self, env):
1384 self.arg.analyse_types(env)
1385 self.arg = self.arg.coerce_to_pyobject(env)
1386 self.type = py_object_type
1387 self.gil_check(env)
1388 self.is_temp = 1
1390 gil_message = "Backquote expression"
1392 def calculate_constant_result(self):
1393 self.constant_result = repr(self.arg.constant_result)
1395 def generate_result_code(self, code):
1396 code.putln(
1397 "%s = PyObject_Repr(%s); %s" % (
1398 self.result(),
1399 self.arg.py_result(),
1400 code.error_goto_if_null(self.result(), self.pos)))
1403 class ImportNode(ExprNode):
1404 # Used as part of import statement implementation.
1405 # Implements result =
1406 # __import__(module_name, globals(), None, name_list)
1408 # module_name IdentifierStringNode dotted name of module
1409 # name_list ListNode or None list of names to be imported
1411 subexprs = ['module_name', 'name_list']
1413 def analyse_types(self, env):
1414 self.module_name.analyse_types(env)
1415 self.module_name = self.module_name.coerce_to_pyobject(env)
1416 if self.name_list:
1417 self.name_list.analyse_types(env)
1418 self.name_list.coerce_to_pyobject(env)
1419 self.type = py_object_type
1420 self.gil_check(env)
1421 self.is_temp = 1
1422 env.use_utility_code(import_utility_code)
1424 gil_message = "Python import"
1426 def generate_result_code(self, code):
1427 if self.name_list:
1428 name_list_code = self.name_list.py_result()
1429 else:
1430 name_list_code = "0"
1431 code.putln(
1432 "%s = __Pyx_Import(%s, %s); %s" % (
1433 self.result(),
1434 self.module_name.py_result(),
1435 name_list_code,
1436 code.error_goto_if_null(self.result(), self.pos)))
1439 class IteratorNode(NewTempExprNode):
1440 # Used as part of for statement implementation.
1442 # allocate_counter_temp/release_counter_temp needs to be called
1443 # by parent (ForInStatNode)
1445 # Implements result = iter(sequence)
1447 # sequence ExprNode
1449 subexprs = ['sequence']
1451 def analyse_types(self, env):
1452 self.sequence.analyse_types(env)
1453 self.sequence = self.sequence.coerce_to_pyobject(env)
1454 self.type = py_object_type
1455 self.gil_check(env)
1456 self.is_temp = 1
1458 gil_message = "Iterating over Python object"
1460 def allocate_counter_temp(self, code):
1461 self.counter_cname = code.funcstate.allocate_temp(
1462 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1464 def release_counter_temp(self, code):
1465 code.funcstate.release_temp(self.counter_cname)
1467 def generate_result_code(self, code):
1468 is_builtin_sequence = self.sequence.type is list_type or \
1469 self.sequence.type is tuple_type
1470 if is_builtin_sequence:
1471 code.putln(
1472 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1473 else:
1474 code.putln(
1475 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1476 self.sequence.py_result(),
1477 self.sequence.py_result()))
1478 code.putln(
1479 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1480 self.counter_cname,
1481 self.result(),
1482 self.sequence.py_result(),
1483 self.result()))
1484 code.putln("} else {")
1485 if is_builtin_sequence:
1486 code.putln(
1487 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1488 code.error_goto(self.pos))
1489 else:
1490 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1491 self.counter_cname,
1492 self.result(),
1493 self.sequence.py_result(),
1494 code.error_goto_if_null(self.result(), self.pos)))
1495 code.putln("}")
1498 class NextNode(AtomicNewTempExprNode):
1499 # Used as part of for statement implementation.
1500 # Implements result = iterator.next()
1501 # Created during analyse_types phase.
1502 # The iterator is not owned by this node.
1504 # iterator ExprNode
1506 def __init__(self, iterator, env):
1507 self.pos = iterator.pos
1508 self.iterator = iterator
1509 self.type = py_object_type
1510 self.is_temp = 1
1512 def generate_result_code(self, code):
1513 if self.iterator.sequence.type is list_type:
1514 type_checks = [(list_type, "List")]
1515 elif self.iterator.sequence.type is tuple_type:
1516 type_checks = [(tuple_type, "Tuple")]
1517 else:
1518 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1520 for py_type, prefix in type_checks:
1521 if len(type_checks) > 1:
1522 code.putln(
1523 "if (likely(Py%s_CheckExact(%s))) {" % (
1524 prefix, self.iterator.py_result()))
1525 code.putln(
1526 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1527 self.iterator.counter_cname,
1528 prefix,
1529 self.iterator.py_result()))
1530 code.putln(
1531 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1532 self.result(),
1533 prefix,
1534 self.iterator.py_result(),
1535 self.iterator.counter_cname,
1536 self.result(),
1537 self.iterator.counter_cname))
1538 if len(type_checks) > 1:
1539 code.put("} else ")
1540 if len(type_checks) == 1:
1541 return
1542 code.putln("{")
1543 code.putln(
1544 "%s = PyIter_Next(%s);" % (
1545 self.result(),
1546 self.iterator.py_result()))
1547 code.putln(
1548 "if (!%s) {" %
1549 self.result())
1550 code.putln(code.error_goto_if_PyErr(self.pos))
1551 code.putln("break;")
1552 code.putln("}")
1553 code.putln("}")
1556 class ExcValueNode(AtomicNewTempExprNode):
1557 # Node created during analyse_types phase
1558 # of an ExceptClauseNode to fetch the current
1559 # exception value.
1561 def __init__(self, pos, env, var):
1562 ExprNode.__init__(self, pos)
1563 self.type = py_object_type
1564 self.var = var
1566 def calculate_result_code(self):
1567 return self.var
1569 def generate_result_code(self, code):
1570 pass
1572 def analyse_types(self, env):
1573 pass
1576 class TempNode(ExprNode):
1577 # Node created during analyse_types phase
1578 # of some nodes to hold a temporary value.
1580 subexprs = []
1582 def __init__(self, pos, type, env):
1583 ExprNode.__init__(self, pos)
1584 self.type = type
1585 if type.is_pyobject:
1586 self.result_ctype = py_object_type
1587 self.is_temp = 1
1589 def analyse_types(self, env):
1590 return self.type
1592 def generate_result_code(self, code):
1593 pass
1596 class PyTempNode(TempNode):
1597 # TempNode holding a Python value.
1599 def __init__(self, pos, env):
1600 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1603 #-------------------------------------------------------------------
1605 # Trailer nodes
1607 #-------------------------------------------------------------------
1609 class IndexNode(ExprNode):
1610 # Sequence indexing.
1612 # base ExprNode
1613 # index ExprNode
1614 # indices [ExprNode]
1615 # is_buffer_access boolean Whether this is a buffer access.
1617 # indices is used on buffer access, index on non-buffer access.
1618 # The former contains a clean list of index parameters, the
1619 # latter whatever Python object is needed for index access.
1621 subexprs = ['base', 'index', 'indices']
1622 indices = None
1624 def __init__(self, pos, index, *args, **kw):
1625 ExprNode.__init__(self, pos, index=index, *args, **kw)
1626 self._index = index
1628 def calculate_constant_result(self):
1629 self.constant_result = \
1630 self.base.constant_result[self.index.constant_result]
1632 def compile_time_value(self, denv):
1633 base = self.base.compile_time_value(denv)
1634 index = self.index.compile_time_value(denv)
1635 try:
1636 return base[index]
1637 except Exception, e:
1638 self.compile_time_value_error(e)
1640 def is_ephemeral(self):
1641 return self.base.is_ephemeral()
1643 def analyse_target_declaration(self, env):
1644 pass
1646 def analyse_as_type(self, env):
1647 base_type = self.base.analyse_as_type(env)
1648 if base_type and not base_type.is_pyobject:
1649 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1650 return None
1652 def analyse_types(self, env):
1653 self.analyse_base_and_index_types(env, getting = 1)
1655 def analyse_target_types(self, env):
1656 self.analyse_base_and_index_types(env, setting = 1)
1658 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1659 # Note: This might be cleaned up by having IndexNode
1660 # parsed in a saner way and only construct the tuple if
1661 # needed.
1663 # Note that this function must leave IndexNode in a cloneable state.
1664 # For buffers, self.index is packed out on the initial analysis, and
1665 # when cloning self.indices is copied.
1666 self.is_buffer_access = False
1668 self.base.analyse_types(env)
1669 # Handle the case where base is a literal char* (and we expect a string, not an int)
1670 if isinstance(self.base, StringNode):
1671 self.base = self.base.coerce_to_pyobject(env)
1673 skip_child_analysis = False
1674 buffer_access = False
1675 if self.base.type.is_buffer:
1676 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1677 if self.indices:
1678 indices = self.indices
1679 else:
1680 # On cloning, indices is cloned. Otherwise, unpack index into indices
1681 assert not isinstance(self.index, CloneNode)
1682 if isinstance(self.index, TupleNode):
1683 indices = self.index.args
1684 else:
1685 indices = [self.index]
1686 if len(indices) == self.base.type.ndim:
1687 buffer_access = True
1688 skip_child_analysis = True
1689 for x in indices:
1690 x.analyse_types(env)
1691 if not x.type.is_int:
1692 buffer_access = False
1694 if buffer_access:
1695 self.indices = indices
1696 self.index = None
1697 self.type = self.base.type.dtype
1698 self.is_buffer_access = True
1699 self.buffer_type = self.base.entry.type
1701 if getting and self.type.is_pyobject:
1702 self.is_temp = True
1703 if setting:
1704 if not self.base.entry.type.writable:
1705 error(self.pos, "Writing to readonly buffer")
1706 else:
1707 self.base.entry.buffer_aux.writable_needed = True
1708 else:
1709 if isinstance(self.index, TupleNode):
1710 self.index.analyse_types(env, skip_children=skip_child_analysis)
1711 elif not skip_child_analysis:
1712 self.index.analyse_types(env)
1713 self.original_index_type = self.index.type
1714 if self.base.type.is_pyobject:
1715 if self.index.type.is_int and not self.index.type.is_longlong:
1716 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1717 else:
1718 self.index = self.index.coerce_to_pyobject(env)
1719 self.type = py_object_type
1720 self.gil_check(env)
1721 self.is_temp = 1
1722 else:
1723 if self.base.type.is_ptr or self.base.type.is_array:
1724 self.type = self.base.type.base_type
1725 else:
1726 error(self.pos,
1727 "Attempting to index non-array type '%s'" %
1728 self.base.type)
1729 self.type = PyrexTypes.error_type
1730 if self.index.type.is_pyobject:
1731 self.index = self.index.coerce_to(
1732 PyrexTypes.c_py_ssize_t_type, env)
1733 if not self.index.type.is_int:
1734 error(self.pos,
1735 "Invalid index type '%s'" %
1736 self.index.type)
1738 gil_message = "Indexing Python object"
1740 def check_const_addr(self):
1741 self.base.check_const_addr()
1742 self.index.check_const()
1744 def is_lvalue(self):
1745 return 1
1747 def calculate_result_code(self):
1748 if self.is_buffer_access:
1749 return "(*%s)" % self.buffer_ptr_code
1750 else:
1751 return "(%s[%s])" % (
1752 self.base.result(), self.index.result())
1754 def index_unsigned_parameter(self):
1755 if self.index.type.is_int:
1756 if self.original_index_type.signed:
1757 return ", 0"
1758 else:
1759 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1760 else:
1761 return ""
1763 def generate_subexpr_evaluation_code(self, code):
1764 self.base.generate_evaluation_code(code)
1765 if not self.indices:
1766 self.index.generate_evaluation_code(code)
1767 else:
1768 for i in self.indices:
1769 i.generate_evaluation_code(code)
1771 def generate_subexpr_disposal_code(self, code):
1772 self.base.generate_disposal_code(code)
1773 if not self.indices:
1774 self.index.generate_disposal_code(code)
1775 else:
1776 for i in self.indices:
1777 i.generate_disposal_code(code)
1779 def free_subexpr_temps(self, code):
1780 self.base.free_temps(code)
1781 if not self.indices:
1782 self.index.free_temps(code)
1783 else:
1784 for i in self.indices:
1785 i.free_temps(code)
1787 def generate_result_code(self, code):
1788 if self.is_buffer_access:
1789 if code.globalstate.directives['nonecheck']:
1790 self.put_nonecheck(code)
1791 self.buffer_ptr_code = self.buffer_lookup_code(code)
1792 if self.type.is_pyobject:
1793 # is_temp is True, so must pull out value and incref it.
1794 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1795 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1796 elif self.type.is_pyobject:
1797 if self.index.type.is_int:
1798 function = "__Pyx_GetItemInt"
1799 index_code = self.index.result()
1800 code.globalstate.use_utility_code(getitem_int_utility_code)
1801 else:
1802 function = "PyObject_GetItem"
1803 index_code = self.index.py_result()
1804 sign_code = ""
1805 code.putln(
1806 "%s = %s(%s, %s%s); if (!%s) %s" % (
1807 self.result(),
1808 function,
1809 self.base.py_result(),
1810 index_code,
1811 self.index_unsigned_parameter(),
1812 self.result(),
1813 code.error_goto(self.pos)))
1815 def generate_setitem_code(self, value_code, code):
1816 if self.index.type.is_int:
1817 function = "__Pyx_SetItemInt"
1818 index_code = self.index.result()
1819 code.globalstate.use_utility_code(setitem_int_utility_code)
1820 else:
1821 index_code = self.index.py_result()
1822 if self.base.type is dict_type:
1823 function = "PyDict_SetItem"
1824 elif self.base.type is list_type:
1825 function = "PyList_SetItem"
1826 # don't use PyTuple_SetItem(), as we'd normally get a
1827 # TypeError when changing a tuple, while PyTuple_SetItem()
1828 # would allow updates
1830 #elif self.base.type is tuple_type:
1831 # function = "PyTuple_SetItem"
1832 else:
1833 function = "PyObject_SetItem"
1834 code.putln(
1835 "if (%s(%s, %s, %s%s) < 0) %s" % (
1836 function,
1837 self.base.py_result(),
1838 index_code,
1839 value_code,
1840 self.index_unsigned_parameter(),
1841 code.error_goto(self.pos)))
1843 def generate_buffer_setitem_code(self, rhs, code, op=""):
1844 # Used from generate_assignment_code and InPlaceAssignmentNode
1845 if code.globalstate.directives['nonecheck']:
1846 self.put_nonecheck(code)
1847 ptrexpr = self.buffer_lookup_code(code)
1848 if self.buffer_type.dtype.is_pyobject:
1849 # Must manage refcounts. Decref what is already there
1850 # and incref what we put in.
1851 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1852 rhs_code = rhs.result()
1853 code.putln("%s = %s;" % (ptr, ptrexpr))
1854 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1855 ptr, rhs_code
1856 ))
1857 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1858 code.funcstate.release_temp(ptr)
1859 else:
1860 # Simple case
1861 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1863 def generate_assignment_code(self, rhs, code):
1864 self.generate_subexpr_evaluation_code(code)
1865 if self.is_buffer_access:
1866 self.generate_buffer_setitem_code(rhs, code)
1867 elif self.type.is_pyobject:
1868 self.generate_setitem_code(rhs.py_result(), code)
1869 else:
1870 code.putln(
1871 "%s = %s;" % (
1872 self.result(), rhs.result()))
1873 self.generate_subexpr_disposal_code(code)
1874 self.free_subexpr_temps(code)
1875 rhs.generate_disposal_code(code)
1876 rhs.free_temps(code)
1878 def generate_deletion_code(self, code):
1879 self.generate_subexpr_evaluation_code(code)
1880 #if self.type.is_pyobject:
1881 if self.index.type.is_int:
1882 function = "__Pyx_DelItemInt"
1883 index_code = self.index.result()
1884 code.globalstate.use_utility_code(delitem_int_utility_code)
1885 else:
1886 index_code = self.index.py_result()
1887 if self.base.type is dict_type:
1888 function = "PyDict_DelItem"
1889 else:
1890 function = "PyObject_DelItem"
1891 code.putln(
1892 "if (%s(%s, %s%s) < 0) %s" % (
1893 function,
1894 self.base.py_result(),
1895 index_code,
1896 self.index_unsigned_parameter(),
1897 code.error_goto(self.pos)))
1898 self.generate_subexpr_disposal_code(code)
1900 def buffer_lookup_code(self, code):
1901 # Assign indices to temps
1902 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
1903 for temp, index in zip(index_temps, self.indices):
1904 code.putln("%s = %s;" % (temp, index.result()))
1905 # Generate buffer access code using these temps
1906 import Buffer
1907 # The above could happen because child_attrs is wrong somewhere so that
1908 # options are not propagated.
1909 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1910 index_signeds=[i.type.signed for i in self.indices],
1911 index_cnames=index_temps,
1912 options=code.globalstate.directives,
1913 pos=self.pos, code=code)
1915 def put_nonecheck(self, code):
1916 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1917 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1918 code.putln("__Pyx_RaiseNoneIndexingError();")
1919 code.putln(code.error_goto(self.pos))
1920 code.putln("}")
1922 class SliceIndexNode(ExprNode):
1923 # 2-element slice indexing
1925 # base ExprNode
1926 # start ExprNode or None
1927 # stop ExprNode or None
1929 subexprs = ['base', 'start', 'stop']
1931 def calculate_constant_result(self):
1932 self.constant_result = self.base.constant_result[
1933 self.start.constant_result : self.stop.constant_result]
1935 def compile_time_value(self, denv):
1936 base = self.base.compile_time_value(denv)
1937 if self.start is None:
1938 start = 0
1939 else:
1940 start = self.start.compile_time_value(denv)
1941 if self.stop is None:
1942 stop = None
1943 else:
1944 stop = self.stop.compile_time_value(denv)
1945 try:
1946 return base[start:stop]
1947 except Exception, e:
1948 self.compile_time_value_error(e)
1950 def analyse_target_declaration(self, env):
1951 pass
1953 def analyse_types(self, env):
1954 self.base.analyse_types(env)
1955 if self.start:
1956 self.start.analyse_types(env)
1957 if self.stop:
1958 self.stop.analyse_types(env)
1959 if self.base.type.is_array or self.base.type.is_ptr:
1960 # we need a ptr type here instead of an array type, as
1961 # array types can result in invalid type casts in the C
1962 # code
1963 self.type = PyrexTypes.CPtrType(self.base.type.base_type)
1964 else:
1965 self.base = self.base.coerce_to_pyobject(env)
1966 self.type = py_object_type
1967 c_int = PyrexTypes.c_py_ssize_t_type
1968 if self.start:
1969 self.start = self.start.coerce_to(c_int, env)
1970 if self.stop:
1971 self.stop = self.stop.coerce_to(c_int, env)
1972 self.gil_check(env)
1973 self.is_temp = 1
1975 gil_message = "Slicing Python object"
1977 def generate_result_code(self, code):
1978 if not self.type.is_pyobject:
1979 error(self.pos,
1980 "Slicing is not currently supported for '%s'." % self.type)
1981 return
1982 code.putln(
1983 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1984 self.result(),
1985 self.base.py_result(),
1986 self.start_code(),
1987 self.stop_code(),
1988 code.error_goto_if_null(self.result(), self.pos)))
1990 def generate_assignment_code(self, rhs, code):
1991 self.generate_subexpr_evaluation_code(code)
1992 if self.type.is_pyobject:
1993 code.put_error_if_neg(self.pos,
1994 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1995 self.base.py_result(),
1996 self.start_code(),
1997 self.stop_code(),
1998 rhs.result()))
1999 else:
2000 start_offset = ''
2001 if self.start:
2002 start_offset = self.start_code()
2003 if start_offset == '0':
2004 start_offset = ''
2005 else:
2006 start_offset += '+'
2007 if rhs.type.is_array:
2008 array_length = rhs.type.size
2009 self.generate_slice_guard_code(code, array_length)
2010 else:
2011 error("Slice assignments from pointers are not yet supported.")
2012 # FIXME: fix the array size according to start/stop
2013 array_length = self.base.type.size
2014 for i in range(array_length):
2015 code.putln("%s[%s%s] = %s[%d];" % (
2016 self.base.result(), start_offset, i,
2017 rhs.result(), i))
2018 self.generate_subexpr_disposal_code(code)
2019 rhs.generate_disposal_code(code)
2020 rhs.free_temps(code)
2022 def generate_deletion_code(self, code):
2023 if not self.type.is_pyobject:
2024 error(self.pos,
2025 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2026 return
2027 self.generate_subexpr_evaluation_code(code)
2028 code.put_error_if_neg(self.pos,
2029 "PySequence_DelSlice(%s, %s, %s)" % (
2030 self.base.py_result(),
2031 self.start_code(),
2032 self.stop_code()))
2033 self.generate_subexpr_disposal_code(code)
2035 def generate_slice_guard_code(self, code, target_size):
2036 if not self.base.type.is_array:
2037 return
2038 slice_size = self.base.type.size
2039 start = stop = None
2040 if self.stop:
2041 stop = self.stop.result()
2042 try:
2043 stop = int(stop)
2044 if stop < 0:
2045 slice_size = self.base.type.size + stop
2046 else:
2047 slice_size = stop
2048 stop = None
2049 except ValueError:
2050 pass
2051 if self.start:
2052 start = self.start.result()
2053 try:
2054 start = int(start)
2055 if start < 0:
2056 start = self.base.type.size + start
2057 slice_size -= start
2058 start = None
2059 except ValueError:
2060 pass
2061 check = None
2062 if slice_size < 0:
2063 if target_size > 0:
2064 error(self.pos, "Assignment to empty slice.")
2065 elif start is None and stop is None:
2066 # we know the exact slice length
2067 if target_size != slice_size:
2068 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2069 slice_size, target_size))
2070 elif start is not None:
2071 if stop is None:
2072 stop = slice_size
2073 check = "(%s)-(%s)" % (stop, start)
2074 else: # stop is not None:
2075 check = stop
2076 if check:
2077 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2078 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % (
2079 target_size, check))
2080 code.putln(code.error_goto(self.pos))
2081 code.putln("}")
2083 def start_code(self):
2084 if self.start:
2085 return self.start.result()
2086 else:
2087 return "0"
2089 def stop_code(self):
2090 if self.stop:
2091 return self.stop.result()
2092 elif self.base.type.is_array:
2093 return self.base.type.size
2094 else:
2095 return "PY_SSIZE_T_MAX"
2097 def calculate_result_code(self):
2098 # self.result() is not used, but this method must exist
2099 return "<unused>"
2102 class SliceNode(ExprNode):
2103 # start:stop:step in subscript list
2105 # start ExprNode
2106 # stop ExprNode
2107 # step ExprNode
2109 def calculate_constant_result(self):
2110 self.constant_result = self.base.constant_result[
2111 self.start.constant_result : \
2112 self.stop.constant_result : \
2113 self.step.constant_result]
2115 def compile_time_value(self, denv):
2116 start = self.start.compile_time_value(denv)
2117 if self.stop is None:
2118 stop = None
2119 else:
2120 stop = self.stop.compile_time_value(denv)
2121 if self.step is None:
2122 step = None
2123 else:
2124 step = self.step.compile_time_value(denv)
2125 try:
2126 return slice(start, stop, step)
2127 except Exception, e:
2128 self.compile_time_value_error(e)
2130 subexprs = ['start', 'stop', 'step']
2132 def analyse_types(self, env):
2133 self.start.analyse_types(env)
2134 self.stop.analyse_types(env)
2135 self.step.analyse_types(env)
2136 self.start = self.start.coerce_to_pyobject(env)
2137 self.stop = self.stop.coerce_to_pyobject(env)
2138 self.step = self.step.coerce_to_pyobject(env)
2139 self.type = py_object_type
2140 self.gil_check(env)
2141 self.is_temp = 1
2143 gil_message = "Constructing Python slice object"
2145 def generate_result_code(self, code):
2146 code.putln(
2147 "%s = PySlice_New(%s, %s, %s); %s" % (
2148 self.result(),
2149 self.start.py_result(),
2150 self.stop.py_result(),
2151 self.step.py_result(),
2152 code.error_goto_if_null(self.result(), self.pos)))
2155 class CallNode(NewTempExprNode):
2156 def gil_check(self, env):
2157 # Make sure we're not in a nogil environment
2158 if env.nogil:
2159 error(self.pos, "Calling gil-requiring function without gil")
2161 def analyse_as_type_constructor(self, env):
2162 type = self.function.analyse_as_type(env)
2163 if type and type.is_struct_or_union:
2164 args, kwds = self.explicit_args_kwds()
2165 items = []
2166 for arg, member in zip(args, type.scope.var_entries):
2167 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2168 if kwds:
2169 items += kwds.key_value_pairs
2170 self.key_value_pairs = items
2171 self.__class__ = DictNode
2172 self.analyse_types(env)
2173 self.coerce_to(type, env)
2174 return True
2177 class SimpleCallNode(CallNode):
2178 # Function call without keyword, * or ** args.
2180 # function ExprNode
2181 # args [ExprNode]
2182 # arg_tuple ExprNode or None used internally
2183 # self ExprNode or None used internally
2184 # coerced_self ExprNode or None used internally
2185 # wrapper_call bool used internally
2186 # has_optional_args bool used internally
2188 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2190 self = None
2191 coerced_self = None
2192 arg_tuple = None
2193 wrapper_call = False
2194 has_optional_args = False
2196 def compile_time_value(self, denv):
2197 function = self.function.compile_time_value(denv)
2198 args = [arg.compile_time_value(denv) for arg in self.args]
2199 try:
2200 return function(*args)
2201 except Exception, e:
2202 self.compile_time_value_error(e)
2204 def analyse_as_type(self, env):
2205 attr = self.function.as_cython_attribute()
2206 if attr == 'pointer':
2207 if len(self.args) != 1:
2208 error(self.args.pos, "only one type allowed.")
2209 else:
2210 type = self.args[0].analyse_as_type(env)
2211 if not type:
2212 error(self.args[0].pos, "Unknown type")
2213 else:
2214 return PyrexTypes.CPtrType(type)
2216 def explicit_args_kwds(self):
2217 return self.args, None
2219 def analyse_types(self, env):
2220 if self.analyse_as_type_constructor(env):
2221 return
2222 function = self.function
2223 function.is_called = 1
2224 self.function.analyse_types(env)
2225 if function.is_attribute and function.is_py_attr and \
2226 function.attribute == "append" and len(self.args) == 1:
2227 # L.append(x) is almost always applied to a list
2228 self.py_func = self.function
2229 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2230 self.function.analyse_types(env)
2231 self.self = self.py_func.obj
2232 function.obj = CloneNode(self.self)
2233 env.use_utility_code(append_utility_code)
2234 if function.is_attribute and function.entry and function.entry.is_cmethod:
2235 # Take ownership of the object from which the attribute
2236 # was obtained, because we need to pass it as 'self'.
2237 self.self = function.obj
2238 function.obj = CloneNode(self.self)
2239 func_type = self.function_type()
2240 if func_type.is_pyobject:
2241 self.arg_tuple = TupleNode(self.pos, args = self.args)
2242 self.arg_tuple.analyse_types(env)
2243 self.args = None
2244 self.type = py_object_type
2245 self.gil_check(env)
2246 self.is_temp = 1
2247 else:
2248 for arg in self.args:
2249 arg.analyse_types(env)
2250 if self.self and func_type.args:
2251 # Coerce 'self' to the type expected by the method.
2252 expected_type = func_type.args[0].type
2253 self.coerced_self = CloneNode(self.self).coerce_to(
2254 expected_type, env)
2255 # Insert coerced 'self' argument into argument list.
2256 self.args.insert(0, self.coerced_self)
2257 self.analyse_c_function_call(env)
2259 def function_type(self):
2260 # Return the type of the function being called, coercing a function
2261 # pointer to a function if necessary.
2262 func_type = self.function.type
2263 if func_type.is_ptr:
2264 func_type = func_type.base_type
2265 return func_type
2267 def analyse_c_function_call(self, env):
2268 func_type = self.function_type()
2269 # Check function type
2270 if not func_type.is_cfunction:
2271 if not func_type.is_error:
2272 error(self.pos, "Calling non-function type '%s'" %
2273 func_type)
2274 self.type = PyrexTypes.error_type
2275 self.result_code = "<error>"
2276 return
2277 # Check no. of args
2278 max_nargs = len(func_type.args)
2279 expected_nargs = max_nargs - func_type.optional_arg_count
2280 actual_nargs = len(self.args)
2281 if actual_nargs < expected_nargs \
2282 or (not func_type.has_varargs and actual_nargs > max_nargs):
2283 expected_str = str(expected_nargs)
2284 if func_type.has_varargs:
2285 expected_str = "at least " + expected_str
2286 elif func_type.optional_arg_count:
2287 if actual_nargs < max_nargs:
2288 expected_str = "at least " + expected_str
2289 else:
2290 expected_str = "at most " + str(max_nargs)
2291 error(self.pos,
2292 "Call with wrong number of arguments (expected %s, got %s)"
2293 % (expected_str, actual_nargs))
2294 self.args = None
2295 self.type = PyrexTypes.error_type
2296 self.result_code = "<error>"
2297 return
2298 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2299 self.has_optional_args = 1
2300 self.is_temp = 1
2301 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2302 env.release_temp(self.opt_arg_struct)
2303 # Coerce arguments
2304 for i in range(min(max_nargs, actual_nargs)):
2305 formal_type = func_type.args[i].type
2306 self.args[i] = self.args[i].coerce_to(formal_type, env)
2307 for i in range(max_nargs, actual_nargs):
2308 if self.args[i].type.is_pyobject:
2309 error(self.args[i].pos,
2310 "Python object cannot be passed as a varargs parameter")
2311 # Calc result type and code fragment
2312 self.type = func_type.return_type
2313 if self.type.is_pyobject \
2314 or func_type.exception_value is not None \
2315 or func_type.exception_check:
2316 self.is_temp = 1
2317 if self.type.is_pyobject:
2318 self.result_ctype = py_object_type
2319 # C++ exception handler
2320 if func_type.exception_check == '+':
2321 if func_type.exception_value is None:
2322 env.use_utility_code(cpp_exception_utility_code)
2323 # Check gil
2324 if not func_type.nogil:
2325 self.gil_check(env)
2327 def calculate_result_code(self):
2328 return self.c_call_code()
2330 def c_call_code(self):
2331 func_type = self.function_type()
2332 if self.args is None or not func_type.is_cfunction:
2333 return "<error>"
2334 formal_args = func_type.args
2335 arg_list_code = []
2336 args = zip(formal_args, self.args)
2337 max_nargs = len(func_type.args)
2338 expected_nargs = max_nargs - func_type.optional_arg_count
2339 actual_nargs = len(self.args)
2340 for formal_arg, actual_arg in args[:expected_nargs]:
2341 arg_code = actual_arg.result_as(formal_arg.type)
2342 arg_list_code.append(arg_code)
2344 if func_type.is_overridable:
2345 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2347 if func_type.optional_arg_count:
2348 if expected_nargs == actual_nargs:
2349 optional_args = 'NULL'
2350 else:
2351 optional_args = "&%s" % self.opt_arg_struct
2352 arg_list_code.append(optional_args)
2354 for actual_arg in self.args[len(formal_args):]:
2355 arg_list_code.append(actual_arg.result())
2356 result = "%s(%s)" % (self.function.result(),
2357 ', '.join(arg_list_code))
2358 # if self.wrapper_call or \
2359 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2360 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2361 return result
2363 def generate_result_code(self, code):
2364 func_type = self.function_type()
2365 if func_type.is_pyobject:
2366 arg_code = self.arg_tuple.py_result()
2367 code.putln(
2368 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2369 self.result(),
2370 self.function.py_result(),
2371 arg_code,
2372 code.error_goto_if_null(self.result(), self.pos)))
2373 elif func_type.is_cfunction:
2374 if self.has_optional_args:
2375 actual_nargs = len(self.args)
2376 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2377 code.putln("%s.%s = %s;" % (
2378 self.opt_arg_struct,
2379 Naming.pyrex_prefix + "n",
2380 len(self.args) - expected_nargs))
2381 args = zip(func_type.args, self.args)
2382 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2383 code.putln("%s.%s = %s;" % (
2384 self.opt_arg_struct,
2385 formal_arg.name,
2386 actual_arg.result_as(formal_arg.type)))
2387 exc_checks = []
2388 if self.type.is_pyobject:
2389 exc_checks.append("!%s" % self.result())
2390 else:
2391 exc_val = func_type.exception_value
2392 exc_check = func_type.exception_check
2393 if exc_val is not None:
2394 exc_checks.append("%s == %s" % (self.result(), exc_val))
2395 if exc_check:
2396 exc_checks.append("PyErr_Occurred()")
2397 if self.is_temp or exc_checks:
2398 rhs = self.c_call_code()
2399 if self.result():
2400 lhs = "%s = " % self.result()
2401 if self.is_temp and self.type.is_pyobject:
2402 #return_type = self.type # func_type.return_type
2403 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2404 # "from", return_type, "to pyobject" ###
2405 rhs = typecast(py_object_type, self.type, rhs)
2406 else:
2407 lhs = ""
2408 if func_type.exception_check == '+':
2409 if func_type.exception_value is None:
2410 raise_py_exception = "__Pyx_CppExn2PyErr()"
2411 elif func_type.exception_value.type.is_pyobject:
2412 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2413 else:
2414 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2415 code.putln(
2416 "try {%s%s;} catch(...) {%s; %s}" % (
2417 lhs,
2418 rhs,
2419 raise_py_exception,
2420 code.error_goto(self.pos)))
2421 else:
2422 if exc_checks:
2423 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2424 else:
2425 goto_error = ""
2426 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2428 class GeneralCallNode(CallNode):
2429 # General Python function call, including keyword,
2430 # * and ** arguments.
2432 # function ExprNode
2433 # positional_args ExprNode Tuple of positional arguments
2434 # keyword_args ExprNode or None Dict of keyword arguments
2435 # starstar_arg ExprNode or None Dict of extra keyword args
2437 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2439 def compile_time_value(self, denv):
2440 function = self.function.compile_time_value(denv)
2441 positional_args = self.positional_args.compile_time_value(denv)
2442 keyword_args = self.keyword_args.compile_time_value(denv)
2443 starstar_arg = self.starstar_arg.compile_time_value(denv)
2444 try:
2445 keyword_args.update(starstar_arg)
2446 return function(*positional_args, **keyword_args)
2447 except Exception, e:
2448 self.compile_time_value_error(e)
2450 def explicit_args_kwds(self):
2451 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2452 raise PostParseError(self.pos,
2453 'Compile-time keyword arguments must be explicit.')
2454 return self.positional_args.args, self.keyword_args
2456 def analyse_types(self, env):
2457 if self.analyse_as_type_constructor(env):
2458 return
2459 self.function.analyse_types(env)
2460 self.positional_args.analyse_types(env)
2461 if self.keyword_args:
2462 self.keyword_args.analyse_types(env)
2463 if self.starstar_arg:
2464 self.starstar_arg.analyse_types(env)
2465 self.function = self.function.coerce_to_pyobject(env)
2466 self.positional_args = \
2467 self.positional_args.coerce_to_pyobject(env)
2468 if self.starstar_arg:
2469 self.starstar_arg = \
2470 self.starstar_arg.coerce_to_pyobject(env)
2471 self.type = py_object_type
2472 self.gil_check(env)
2473 self.is_temp = 1
2475 def generate_result_code(self, code):
2476 if self.keyword_args and self.starstar_arg:
2477 code.put_error_if_neg(self.pos,
2478 "PyDict_Update(%s, %s)" % (
2479 self.keyword_args.py_result(),
2480 self.starstar_arg.py_result()))
2481 keyword_code = self.keyword_args.py_result()
2482 elif self.keyword_args:
2483 keyword_code = self.keyword_args.py_result()
2484 elif self.starstar_arg:
2485 keyword_code = self.starstar_arg.py_result()
2486 else:
2487 keyword_code = None
2488 if not keyword_code:
2489 call_code = "PyObject_Call(%s, %s, NULL)" % (
2490 self.function.py_result(),
2491 self.positional_args.py_result())
2492 else:
2493 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2494 self.function.py_result(),
2495 self.positional_args.py_result(),
2496 keyword_code)
2497 code.putln(
2498 "%s = %s; %s" % (
2499 self.result(),
2500 call_code,
2501 code.error_goto_if_null(self.result(), self.pos)))
2504 class AsTupleNode(ExprNode):
2505 # Convert argument to tuple. Used for normalising
2506 # the * argument of a function call.
2508 # arg ExprNode
2510 subexprs = ['arg']
2512 def calculate_constant_result(self):
2513 self.constant_result = tuple(self.base.constant_result)
2515 def compile_time_value(self, denv):
2516 arg = self.arg.compile_time_value(denv)
2517 try:
2518 return tuple(arg)
2519 except Exception, e:
2520 self.compile_time_value_error(e)
2522 def analyse_types(self, env):
2523 self.arg.analyse_types(env)
2524 self.arg = self.arg.coerce_to_pyobject(env)
2525 self.type = tuple_type
2526 self.gil_check(env)
2527 self.is_temp = 1
2529 gil_message = "Constructing Python tuple"
2531 def generate_result_code(self, code):
2532 code.putln(
2533 "%s = PySequence_Tuple(%s); %s" % (
2534 self.result(),
2535 self.arg.py_result(),
2536 code.error_goto_if_null(self.result(), self.pos)))
2539 class AttributeNode(ExprNode):
2540 # obj.attribute
2542 # obj ExprNode
2543 # attribute string
2544 # needs_none_check boolean Used if obj is an extension type.
2545 # If set to True, it is known that the type is not None.
2547 # Used internally:
2549 # is_py_attr boolean Is a Python getattr operation
2550 # member string C name of struct member
2551 # is_called boolean Function call is being done on result
2552 # entry Entry Symbol table entry of attribute
2553 # interned_attr_cname string C name of interned attribute name
2555 is_attribute = 1
2556 subexprs = ['obj']
2558 type = PyrexTypes.error_type
2559 entry = None
2560 is_called = 0
2561 needs_none_check = True
2563 def as_cython_attribute(self):
2564 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2565 return self.attribute
2567 def coerce_to(self, dst_type, env):
2568 # If coercing to a generic pyobject and this is a cpdef function
2569 # we can create the corresponding attribute
2570 if dst_type is py_object_type:
2571 entry = self.entry
2572 if entry and entry.is_cfunction and entry.as_variable:
2573 # must be a cpdef function
2574 self.is_temp = 1
2575 self.entry = entry.as_variable
2576 self.analyse_as_python_attribute(env)
2577 return self
2578 return ExprNode.coerce_to(self, dst_type, env)
2580 def calculate_constant_result(self):
2581 attr = self.attribute
2582 if attr.beginswith("__") and attr.endswith("__"):
2583 return
2584 self.constant_result = getattr(self.obj.constant_result, attr)
2586 def compile_time_value(self, denv):
2587 attr = self.attribute
2588 if attr.beginswith("__") and attr.endswith("__"):
2589 self.error("Invalid attribute name '%s' in compile-time expression"
2590 % attr)
2591 return None
2592 obj = self.arg.compile_time_value(denv)
2593 try:
2594 return getattr(obj, attr)
2595 except Exception, e:
2596 self.compile_time_value_error(e)
2598 def analyse_target_declaration(self, env):
2599 pass
2601 def analyse_target_types(self, env):
2602 self.analyse_types(env, target = 1)
2604 def analyse_types(self, env, target = 0):
2605 if self.analyse_as_cimported_attribute(env, target):
2606 return
2607 if not target and self.analyse_as_unbound_cmethod(env):
2608 return
2609 self.analyse_as_ordinary_attribute(env, target)
2611 def analyse_as_cimported_attribute(self, env, target):
2612 # Try to interpret this as a reference to an imported
2613 # C const, type, var or function. If successful, mutates
2614 # this node into a NameNode and returns 1, otherwise
2615 # returns 0.
2616 module_scope = self.obj.analyse_as_module(env)
2617 if module_scope:
2618 entry = module_scope.lookup_here(self.attribute)
2619 if entry and (
2620 entry.is_cglobal or entry.is_cfunction
2621 or entry.is_type or entry.is_const):
2622 self.mutate_into_name_node(env, entry, target)
2623 return 1
2624 return 0
2626 def analyse_as_unbound_cmethod(self, env):
2627 # Try to interpret this as a reference to an unbound
2628 # C method of an extension type. If successful, mutates
2629 # this node into a NameNode and returns 1, otherwise
2630 # returns 0.
2631 type = self.obj.analyse_as_extension_type(env)
2632 if type:
2633 entry = type.scope.lookup_here(self.attribute)
2634 if entry and entry.is_cmethod:
2635 # Create a temporary entry describing the C method
2636 # as an ordinary function.
2637 ubcm_entry = Symtab.Entry(entry.name,
2638 "%s->%s" % (type.vtabptr_cname, entry.cname),
2639 entry.type)
2640 ubcm_entry.is_cfunction = 1
2641 ubcm_entry.func_cname = entry.func_cname
2642 ubcm_entry.is_unbound_cmethod = 1
2643 self.mutate_into_name_node(env, ubcm_entry, None)
2644 return 1
2645 return 0
2647 def analyse_as_type(self, env):
2648 module_scope = self.obj.analyse_as_module(env)
2649 if module_scope:
2650 return module_scope.lookup_type(self.attribute)
2651 return None
2653 def analyse_as_extension_type(self, env):
2654 # Try to interpret this as a reference to an extension type
2655 # in a cimported module. Returns the extension type, or None.
2656 module_scope = self.obj.analyse_as_module(env)
2657 if module_scope:
2658 entry = module_scope.lookup_here(self.attribute)
2659 if entry and entry.is_type and entry.type.is_extension_type:
2660 return entry.type
2661 return None
2663 def analyse_as_module(self, env):
2664 # Try to interpret this as a reference to a cimported module
2665 # in another cimported module. Returns the module scope, or None.
2666 module_scope = self.obj.analyse_as_module(env)
2667 if module_scope:
2668 entry = module_scope.lookup_here(self.attribute)
2669 if entry and entry.as_module:
2670 return entry.as_module
2671 return None
2673 def mutate_into_name_node(self, env, entry, target):
2674 # Mutate this node into a NameNode and complete the
2675 # analyse_types phase.
2676 self.__class__ = NameNode
2677 self.name = self.attribute
2678 self.entry = entry
2679 del self.obj
2680 del self.attribute
2681 if target:
2682 NameNode.analyse_target_types(self, env)
2683 else:
2684 NameNode.analyse_rvalue_entry(self, env)
2686 def analyse_as_ordinary_attribute(self, env, target):
2687 self.obj.analyse_types(env)
2688 self.analyse_attribute(env)
2689 if self.entry and self.entry.is_cmethod and not self.is_called:
2690 # error(self.pos, "C method can only be called")
2691 pass
2692 ## Reference to C array turns into pointer to first element.
2693 #while self.type.is_array:
2694 # self.type = self.type.element_ptr_type()
2695 if self.is_py_attr:
2696 if not target:
2697 self.is_temp = 1
2698 self.result_ctype = py_object_type
2700 def analyse_attribute(self, env):
2701 # Look up attribute and set self.type and self.member.
2702 self.is_py_attr = 0
2703 self.member = self.attribute
2704 if self.obj.type.is_string:
2705 self.obj = self.obj.coerce_to_pyobject(env)
2706 obj_type = self.obj.type
2707 if obj_type.is_ptr or obj_type.is_array:
2708 obj_type = obj_type.base_type
2709 self.op = "->"
2710 elif obj_type.is_extension_type:
2711 self.op = "->"
2712 else:
2713 self.op = "."
2714 if obj_type.has_attributes:
2715 entry = None
2716 if obj_type.attributes_known():
2717 entry = obj_type.scope.lookup_here(self.attribute)
2718 if entry and entry.is_member:
2719 entry = None
2720 else:
2721 error(self.pos,
2722 "Cannot select attribute of incomplete type '%s'"
2723 % obj_type)
2724 self.type = PyrexTypes.error_type
2725 return
2726 self.entry = entry
2727 if entry:
2728 if obj_type.is_extension_type and entry.name == "__weakref__":
2729 error(self.pos, "Illegal use of special attribute __weakref__")
2730 # methods need the normal attribute lookup
2731 # because they do not have struct entries
2732 if entry.is_variable or entry.is_cmethod:
2733 self.type = entry.type
2734 self.member = entry.cname
2735 return
2736 else:
2737 # If it's not a variable or C method, it must be a Python
2738 # method of an extension type, so we treat it like a Python
2739 # attribute.
2740 pass
2741 # If we get here, the base object is not a struct/union/extension
2742 # type, or it is an extension type and the attribute is either not
2743 # declared or is declared as a Python method. Treat it as a Python
2744 # attribute reference.
2745 self.analyse_as_python_attribute(env)
2747 def analyse_as_python_attribute(self, env):
2748 obj_type = self.obj.type
2749 self.member = self.attribute
2750 if obj_type.is_pyobject:
2751 self.type = py_object_type
2752 self.is_py_attr = 1
2753 self.interned_attr_cname = env.intern_identifier(self.attribute)
2754 self.gil_check(env)
2755 else:
2756 if not obj_type.is_error:
2757 error(self.pos,
2758 "Object of type '%s' has no attribute '%s'" %
2759 (obj_type, self.attribute))
2761 gil_message = "Accessing Python attribute"
2763 def is_simple(self):
2764 if self.obj:
2765 return self.result_in_temp() or self.obj.is_simple()
2766 else:
2767 return NameNode.is_simple(self)
2769 def is_lvalue(self):
2770 if self.obj:
2771 return 1
2772 else:
2773 return NameNode.is_lvalue(self)
2775 def is_ephemeral(self):
2776 if self.obj:
2777 return self.obj.is_ephemeral()
2778 else:
2779 return NameNode.is_ephemeral(self)
2781 def calculate_result_code(self):
2782 #print "AttributeNode.calculate_result_code:", self.member ###
2783 #print "...obj node =", self.obj, "code", self.obj.result() ###
2784 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2785 obj = self.obj
2786 obj_code = obj.result_as(obj.type)
2787 #print "...obj_code =", obj_code ###
2788 if self.entry and self.entry.is_cmethod:
2789 if obj.type.is_extension_type:
2790 return "((struct %s *)%s%s%s)->%s" % (
2791 obj.type.vtabstruct_cname, obj_code, self.op,
2792 obj.type.vtabslot_cname, self.member)
2793 else:
2794 return self.member
2795 else:
2796 return "%s%s%s" % (obj_code, self.op, self.member)
2798 def generate_result_code(self, code):
2799 if self.is_py_attr:
2800 code.putln(
2801 '%s = PyObject_GetAttr(%s, %s); %s' % (
2802 self.result(),
2803 self.obj.py_result(),
2804 self.interned_attr_cname,
2805 code.error_goto_if_null(self.result(), self.pos)))
2806 else:
2807 # result_code contains what is needed, but we may need to insert
2808 # a check and raise an exception
2809 if (self.obj.type.is_extension_type
2810 and self.needs_none_check
2811 and code.globalstate.directives['nonecheck']):
2812 self.put_nonecheck(code)
2814 def generate_assignment_code(self, rhs, code):
2815 self.obj.generate_evaluation_code(code)
2816 if self.is_py_attr:
2817 code.put_error_if_neg(self.pos,
2818 'PyObject_SetAttr(%s, %s, %s)' % (
2819 self.obj.py_result(),
2820 self.interned_attr_cname,
2821 rhs.py_result()))
2822 rhs.generate_disposal_code(code)
2823 rhs.free_temps(code)
2824 else:
2825 if (self.obj.type.is_extension_type
2826 and self.needs_none_check
2827 and code.globalstate.directives['nonecheck']):
2828 self.put_nonecheck(code)
2830 select_code = self.result()
2831 if self.type.is_pyobject:
2832 rhs.make_owned_reference(code)
2833 code.put_decref(select_code, self.ctype())
2834 code.putln(
2835 "%s = %s;" % (
2836 select_code,
2837 rhs.result_as(self.ctype())))
2838 #rhs.result()))
2839 rhs.generate_post_assignment_code(code)
2840 rhs.free_temps(code)
2841 self.obj.generate_disposal_code(code)
2842 self.obj.free_temps(code)
2844 def generate_deletion_code(self, code):
2845 self.obj.generate_evaluation_code(code)
2846 if self.is_py_attr:
2847 code.put_error_if_neg(self.pos,
2848 'PyObject_DelAttr(%s, %s)' % (
2849 self.obj.py_result(),
2850 self.interned_attr_cname))
2851 else:
2852 error(self.pos, "Cannot delete C attribute of extension type")
2853 self.obj.generate_disposal_code(code)
2854 self.obj.free_temps(code)
2856 def annotate(self, code):
2857 if self.is_py_attr:
2858 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2859 else:
2860 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2862 def put_nonecheck(self, code):
2863 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2864 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2865 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2866 code.putln(code.error_goto(self.pos))
2867 code.putln("}")
2870 #-------------------------------------------------------------------
2872 # Constructor nodes
2874 #-------------------------------------------------------------------
2876 class SequenceNode(NewTempExprNode):
2877 # Base class for list and tuple constructor nodes.
2878 # Contains common code for performing sequence unpacking.
2880 # args [ExprNode]
2881 # iterator ExprNode
2882 # unpacked_items [ExprNode] or None
2883 # coerced_unpacked_items [ExprNode] or None
2885 subexprs = ['args']
2887 is_sequence_constructor = 1
2888 unpacked_items = None
2890 def compile_time_value_list(self, denv):
2891 return [arg.compile_time_value(denv) for arg in self.args]
2893 def analyse_target_declaration(self, env):
2894 for arg in self.args:
2895 arg.analyse_target_declaration(env)
2897 def analyse_types(self, env, skip_children=False):
2898 for i in range(len(self.args)):
2899 arg = self.args[i]
2900 if not skip_children: arg.analyse_types(env)
2901 self.args[i] = arg.coerce_to_pyobject(env)
2902 self.type = py_object_type
2903 self.gil_check(env)
2904 self.is_temp = 1
2906 def analyse_target_types(self, env):
2907 self.iterator = PyTempNode(self.pos, env)
2908 self.unpacked_items = []
2909 self.coerced_unpacked_items = []
2910 for arg in self.args:
2911 arg.analyse_target_types(env)
2912 unpacked_item = PyTempNode(self.pos, env)
2913 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2914 self.unpacked_items.append(unpacked_item)
2915 self.coerced_unpacked_items.append(coerced_unpacked_item)
2916 self.type = py_object_type
2917 env.use_utility_code(unpacking_utility_code)
2919 def allocate_target_temps(self, env, rhs):
2920 self.iterator.allocate_temps(env)
2921 for arg, node in zip(self.args, self.coerced_unpacked_items):
2922 node.allocate_temps(env)
2923 arg.allocate_target_temps(env, None)
2924 #arg.release_target_temp(env)
2925 #node.release_temp(env)
2926 if rhs:
2927 rhs.release_temp(env)
2928 self.iterator.release_temp(env)
2929 for node in self.coerced_unpacked_items:
2930 node.release_temp(env)
2932 # def release_target_temp(self, env):
2933 # #for arg in self.args:
2934 # # arg.release_target_temp(env)
2935 # #for node in self.coerced_unpacked_items:
2936 # # node.release_temp(env)
2937 # self.iterator.release_temp(env)
2939 def generate_result_code(self, code):
2940 self.generate_operation_code(code)
2942 def generate_assignment_code(self, rhs, code):
2943 # Need to work around the fact that generate_evaluation_code
2944 # allocates the temps in a rather hacky way -- the assignment
2945 # is evaluated twice, within each if-block.
2947 code.putln(
2948 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2949 rhs.py_result(),
2950 rhs.py_result(),
2951 len(self.args)))
2952 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2953 for i in range(len(self.args)):
2954 item = self.unpacked_items[i]
2955 code.put(
2956 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
2957 item.result(),
2958 i))
2959 code.put_incref(item.result(), item.ctype())
2960 value_node = self.coerced_unpacked_items[i]
2961 value_node.generate_evaluation_code(code)
2962 rhs.generate_disposal_code(code)
2964 for i in range(len(self.args)):
2965 self.args[i].generate_assignment_code(
2966 self.coerced_unpacked_items[i], code)
2968 code.putln("} else {")
2970 code.putln(
2971 "%s = PyObject_GetIter(%s); %s" % (
2972 self.iterator.result(),
2973 rhs.py_result(),
2974 code.error_goto_if_null(self.iterator.result(), self.pos)))
2975 rhs.generate_disposal_code(code)
2976 for i in range(len(self.args)):
2977 item = self.unpacked_items[i]
2978 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2979 self.iterator.py_result(), i)
2980 code.putln(
2981 "%s = %s; %s" % (
2982 item.result(),
2983 typecast(item.ctype(), py_object_type, unpack_code),
2984 code.error_goto_if_null(item.result(), self.pos)))
2985 value_node = self.coerced_unpacked_items[i]
2986 value_node.generate_evaluation_code(code)
2987 code.put_error_if_neg(self.pos,
2988 "__Pyx_EndUnpack(%s)" % (
2989 self.iterator.py_result()))
2990 if debug_disposal_code:
2991 print("UnpackNode.generate_assignment_code:")
2992 print("...generating disposal code for %s" % self.iterator)
2993 self.iterator.generate_disposal_code(code)
2994 self.iterator.free_temps(code)
2996 for i in range(len(self.args)):
2997 self.args[i].generate_assignment_code(
2998 self.coerced_unpacked_items[i], code)
2999 code.putln("}")
3000 rhs.free_temps(code)
3002 def annotate(self, code):
3003 for arg in self.args:
3004 arg.annotate(code)
3005 if self.unpacked_items:
3006 for arg in self.unpacked_items:
3007 arg.annotate(code)
3008 for arg in self.coerced_unpacked_items:
3009 arg.annotate(code)
3012 class TupleNode(SequenceNode):
3013 # Tuple constructor.
3015 gil_message = "Constructing Python tuple"
3017 def analyse_types(self, env, skip_children=False):
3018 if len(self.args) == 0:
3019 self.is_temp = 0
3020 self.is_literal = 1
3021 else:
3022 SequenceNode.analyse_types(self, env, skip_children)
3023 self.type = tuple_type
3025 def calculate_result_code(self):
3026 if len(self.args) > 0:
3027 error(self.pos, "Positive length tuples must be constructed.")
3028 else:
3029 return Naming.empty_tuple
3031 def calculate_constant_result(self):
3032 self.constant_result = tuple([
3033 arg.constant_result for arg in self.args])
3035 def compile_time_value(self, denv):
3036 values = self.compile_time_value_list(denv)
3037 try:
3038 return tuple(values)
3039 except Exception, e:
3040 self.compile_time_value_error(e)
3042 def generate_operation_code(self, code):
3043 if len(self.args) == 0:
3044 # result_code is Naming.empty_tuple
3045 return
3046 code.putln(
3047 "%s = PyTuple_New(%s); %s" % (
3048 self.result(),
3049 len(self.args),
3050 code.error_goto_if_null(self.result(), self.pos)))
3051 for i in range(len(self.args)):
3052 arg = self.args[i]
3053 if not arg.result_in_temp():
3054 code.put_incref(arg.result(), arg.ctype())
3055 code.putln(
3056 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3057 self.result(),
3058 i,
3059 arg.py_result()))
3061 def generate_subexpr_disposal_code(self, code):
3062 # We call generate_post_assignment_code here instead
3063 # of generate_disposal_code, because values were stored
3064 # in the tuple using a reference-stealing operation.
3065 for arg in self.args:
3066 arg.generate_post_assignment_code(code)
3067 # Should NOT call free_temps -- this is invoked by the default
3068 # generate_evaluation_code which will do that.
3071 class ListNode(SequenceNode):
3072 # List constructor.
3074 # obj_conversion_errors [PyrexError] used internally
3075 # orignial_args [ExprNode] used internally
3077 gil_message = "Constructing Python list"
3079 def analyse_expressions(self, env):
3080 SequenceNode.analyse_expressions(self, env)
3081 self.coerce_to_pyobject(env)
3083 def analyse_types(self, env):
3084 hold_errors()
3085 self.original_args = list(self.args)
3086 SequenceNode.analyse_types(self, env)
3087 self.type = list_type
3088 self.obj_conversion_errors = held_errors()
3089 release_errors(ignore=True)
3091 def coerce_to(self, dst_type, env):
3092 if dst_type.is_pyobject:
3093 for err in self.obj_conversion_errors:
3094 report_error(err)
3095 self.obj_conversion_errors = []
3096 if not self.type.subtype_of(dst_type):
3097 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3098 elif dst_type.is_ptr:
3099 base_type = dst_type.base_type
3100 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3101 for i in range(len(self.original_args)):
3102 arg = self.args[i]
3103 if isinstance(arg, CoerceToPyTypeNode):
3104 arg = arg.arg
3105 self.args[i] = arg.coerce_to(base_type, env)
3106 elif dst_type.is_struct:
3107 if len(self.args) > len(dst_type.scope.var_entries):
3108 error(self.pos, "Too may members for '%s'" % dst_type)
3109 else:
3110 if len(self.args) < len(dst_type.scope.var_entries):
3111 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3112 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3113 if isinstance(arg, CoerceToPyTypeNode):
3114 arg = arg.arg
3115 self.args[i] = arg.coerce_to(member.type, env)
3116 self.type = dst_type
3117 else:
3118 self.type = error_type
3119 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3120 return self
3122 def release_temp(self, env):
3123 if self.type.is_array:
3124 # To be valid C++, we must allocate the memory on the stack
3125 # manually and be sure not to reuse it for something else.
3126 pass
3127 else:
3128 SequenceNode.release_temp(self, env)
3130 def calculate_constant_result(self):
3131 self.constant_result = [
3132 arg.constant_result for arg in self.args]
3134 def compile_time_value(self, denv):
3135 return self.compile_time_value_list(denv)
3137 def generate_operation_code(self, code):
3138 if self.type.is_pyobject:
3139 for err in self.obj_conversion_errors:
3140 report_error(err)
3141 code.putln("%s = PyList_New(%s); %s" %
3142 (self.result(),
3143 len(self.args),
3144 code.error_goto_if_null(self.result(), self.pos)))
3145 for i in range(len(self.args)):
3146 arg = self.args[i]
3147 #if not arg.is_temp:
3148 if not arg.result_in_temp():
3149 code.put_incref(arg.result(), arg.ctype())
3150 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3151 (self.result(),
3152 i,
3153 arg.py_result()))
3154 elif self.type.is_array:
3155 for i, arg in enumerate(self.args):
3156 code.putln("%s[%s] = %s;" % (
3157 self.result(),
3158 i,
3159 arg.result()))
3160 elif self.type.is_struct:
3161 for arg, member in zip(self.args, self.type.scope.var_entries):
3162 code.putln("%s.%s = %s;" % (
3163 self.result(),
3164 member.cname,
3165 arg.result()))
3166 else:
3167 raise InternalError("List type never specified")
3169 def generate_subexpr_disposal_code(self, code):
3170 # We call generate_post_assignment_code here instead
3171 # of generate_disposal_code, because values were stored
3172 # in the list using a reference-stealing operation.
3173 for arg in self.args:
3174 arg.generate_post_assignment_code(code)
3175 # Should NOT call free_temps -- this is invoked by the default
3176 # generate_evaluation_code which will do that.
3179 class ComprehensionNode(SequenceNode):
3180 subexprs = []
3181 is_sequence_constructor = 0 # not unpackable
3182 comp_result_type = py_object_type
3184 child_attrs = ["loop", "append"]
3186 def analyse_types(self, env):
3187 self.type = self.comp_result_type
3188 self.is_temp = 1
3189 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3191 def allocate_temps(self, env, result = None):
3192 if debug_temp_alloc:
3193 print("%s Allocating temps" % self)
3194 self.allocate_temp(env, result)
3195 self.loop.analyse_declarations(env)
3196 self.loop.analyse_expressions(env)
3198 def generate_operation_code(self, code):
3199 code.putln("%s = PyList_New(%s); %s" %
3200 (self.result(),
3201 0,
3202 code.error_goto_if_null(self.result(), self.pos)))
3203 self.loop.generate_execution_code(code)
3205 def annotate(self, code):
3206 self.loop.annotate(code)
3209 class ListComprehensionNode(ComprehensionNode):
3210 comp_result_type = list_type
3212 def generate_operation_code(self, code):
3213 code.putln("%s = PyList_New(%s); %s" %
3214 (self.result(),
3215 0,
3216 code.error_goto_if_null(self.result(), self.pos)))
3217 self.loop.generate_execution_code(code)
3219 class SetComprehensionNode(ComprehensionNode):
3220 comp_result_type = set_type
3222 def generate_operation_code(self, code):
3223 code.putln("%s = PySet_New(0); %s" % # arg == iterable, not size!
3224 (self.result(),
3225 code.error_goto_if_null(self.result(), self.pos)))
3226 self.loop.generate_execution_code(code)
3228 class DictComprehensionNode(ComprehensionNode):
3229 comp_result_type = dict_type
3231 def generate_operation_code(self, code):
3232 code.putln("%s = PyDict_New(); %s" %
3233 (self.result(),
3234 code.error_goto_if_null(self.result(), self.pos)))
3235 self.loop.generate_execution_code(code)
3238 class ComprehensionAppendNode(NewTempExprNode):
3239 # Need to be careful to avoid infinite recursion:
3240 # target must not be in child_attrs/subexprs
3241 subexprs = ['expr']
3243 def analyse_types(self, env):
3244 self.expr.analyse_types(env)
3245 if not self.expr.type.is_pyobject:
3246 self.expr = self.expr.coerce_to_pyobject(env)
3247 self.type = PyrexTypes.c_int_type
3248 self.is_temp = 1
3250 class ListComprehensionAppendNode(ComprehensionAppendNode):
3251 def generate_result_code(self, code):
3252 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
3253 (self.result(),
3254 self.target.result(),
3255 self.expr.result(),
3256 code.error_goto_if(self.result(), self.pos)))
3258 class SetComprehensionAppendNode(ComprehensionAppendNode):
3259 def generate_result_code(self, code):
3260 code.putln("%s = PySet_Add(%s, (PyObject*)%s); %s" %
3261 (self.result(),
3262 self.target.result(),
3263 self.expr.result(),
3264 code.error_goto_if(self.result(), self.pos)))
3266 class DictComprehensionAppendNode(ComprehensionAppendNode):
3267 subexprs = ['key_expr', 'value_expr']
3269 def analyse_types(self, env):
3270 self.key_expr.analyse_types(env)
3271 if not self.key_expr.type.is_pyobject:
3272 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3273 self.value_expr.analyse_types(env)
3274 if not self.value_expr.type.is_pyobject:
3275 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3276 self.type = PyrexTypes.c_int_type
3277 self.is_temp = 1
3279 def generate_result_code(self, code):
3280 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3281 (self.result(),
3282 self.target.result(),
3283 self.key_expr.result(),
3284 self.value_expr.result(),
3285 code.error_goto_if(self.result(), self.pos)))
3288 class SetNode(NewTempExprNode):
3289 # Set constructor.
3291 subexprs = ['args']
3293 gil_message = "Constructing Python set"
3295 def analyse_types(self, env):
3296 for i in range(len(self.args)):
3297 arg = self.args[i]
3298 arg.analyse_types(env)
3299 self.args[i] = arg.coerce_to_pyobject(env)
3300 self.type = set_type
3301 self.gil_check(env)
3302 self.is_temp = 1
3304 def calculate_constant_result(self):
3305 self.constant_result = set([
3306 arg.constant_result for arg in self.args])
3308 def compile_time_value(self, denv):
3309 values = [arg.compile_time_value(denv) for arg in self.args]
3310 try:
3311 return set(values)
3312 except Exception, e:
3313 self.compile_time_value_error(e)
3315 def generate_evaluation_code(self, code):
3316 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3317 self.allocate_temp_result(code)
3318 code.putln(
3319 "%s = PySet_New(0); %s" % (
3320 self.result(),
3321 code.error_goto_if_null(self.result(), self.pos)))
3322 for arg in self.args:
3323 arg.generate_evaluation_code(code)
3324 code.putln(
3325 code.error_goto_if_neg(
3326 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3327 self.pos))
3328 arg.generate_disposal_code(code)
3329 arg.free_temps(code)
3332 class DictNode(ExprNode):
3333 # Dictionary constructor.
3335 # key_value_pairs [DictItemNode]
3337 # obj_conversion_errors [PyrexError] used internally
3339 subexprs = ['key_value_pairs']
3341 def calculate_constant_result(self):
3342 self.constant_result = dict([
3343 item.constant_result for item in self.key_value_pairs])
3345 def compile_time_value(self, denv):
3346 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3347 for item in self.key_value_pairs]
3348 try:
3349 return dict(pairs)
3350 except Exception, e:
3351 self.compile_time_value_error(e)
3353 def analyse_types(self, env):
3354 hold_errors()
3355 self.type = dict_type
3356 for item in self.key_value_pairs:
3357 item.analyse_types(env)
3358 self.gil_check(env)
3359 self.obj_conversion_errors = held_errors()
3360 release_errors(ignore=True)
3361 self.is_temp = 1
3363 def coerce_to(self, dst_type, env):
3364 if dst_type.is_pyobject:
3365 self.release_errors()
3366 if not self.type.subtype_of(dst_type):
3367 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3368 elif dst_type.is_struct_or_union:
3369 self.type = dst_type
3370 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3371 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3372 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3373 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3374 for item in self.key_value_pairs:
3375 if isinstance(item.key, CoerceToPyTypeNode):
3376 item.key = item.key.arg
3377 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3378 error(item.key.pos, "Invalid struct field identifier")
3379 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3380 else:
3381 member = dst_type.scope.lookup_here(item.key.value)
3382 if not member:
3383 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3384 else:
3385 value = item.value
3386 if isinstance(value, CoerceToPyTypeNode):
3387 value = value.arg
3388 item.value = value.coerce_to(member.type, env)
3389 else:
3390 self.type = error_type
3391 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3392 return self
3394 def release_errors(self):
3395 for err in self.obj_conversion_errors:
3396 report_error(err)
3397 self.obj_conversion_errors = []
3399 gil_message = "Constructing Python dict"
3401 def allocate_temps(self, env, result = None):
3402 # Custom method used here because key-value
3403 # pairs are evaluated and used one at a time.
3404 self.allocate_temp(env, result)
3405 for item in self.key_value_pairs:
3406 item.key.allocate_temps(env)
3407 item.value.allocate_temps(env)
3408 item.key.release_temp(env)
3409 item.value.release_temp(env)
3411 def generate_evaluation_code(self, code):
3412 # Custom method used here because key-value
3413 # pairs are evaluated and used one at a time.
3414 if self.type.is_pyobject:
3415 self.release_errors()
3416 code.putln(
3417 "%s = PyDict_New(); %s" % (
3418 self.result(),
3419 code.error_goto_if_null(self.result(), self.pos)))
3420 for item in self.key_value_pairs:
3421 item.generate_evaluation_code(code)
3422 if self.type.is_pyobject:
3423 code.put_error_if_neg(self.pos,
3424 "PyDict_SetItem(%s, %s, %s)" % (
3425 self.result(),
3426 item.key.py_result(),
3427 item.value.py_result()))
3428 else:
3429 code.putln("%s.%s = %s;" % (
3430 self.result(),
3431 item.key.value,
3432 item.value.result()))
3433 item.generate_disposal_code(code)
3434 item.free_temps(code)
3436 def annotate(self, code):
3437 for item in self.key_value_pairs:
3438 item.annotate(code)
3440 class DictItemNode(ExprNode):
3441 # Represents a single item in a DictNode
3443 # key ExprNode
3444 # value ExprNode
3445 subexprs = ['key', 'value']
3447 def calculate_constant_result(self):
3448 self.constant_result = (
3449 self.key.constant_result, self.value.constant_result)
3451 def analyse_types(self, env):
3452 self.key.analyse_types(env)
3453 self.value.analyse_types(env)
3454 self.key = self.key.coerce_to_pyobject(env)
3455 self.value = self.value.coerce_to_pyobject(env)
3457 def generate_evaluation_code(self, code):
3458 self.key.generate_evaluation_code(code)
3459 self.value.generate_evaluation_code(code)
3461 def generate_disposal_code(self, code):
3462 self.key.generate_disposal_code(code)
3463 self.value.generate_disposal_code(code)
3465 def free_temps(self, code):
3466 self.key.free_temps(code)
3467 self.value.free_temps(code)
3469 def __iter__(self):
3470 return iter([self.key, self.value])
3473 class ClassNode(ExprNode):
3474 # Helper class used in the implementation of Python
3475 # class definitions. Constructs a class object given
3476 # a name, tuple of bases and class dictionary.
3478 # name EncodedString Name of the class
3479 # cname string Class name as a Python string
3480 # bases ExprNode Base class tuple
3481 # dict ExprNode Class dict (not owned by this node)
3482 # doc ExprNode or None Doc string
3483 # module_name string Name of defining module
3485 subexprs = ['bases', 'doc']
3487 def analyse_types(self, env):
3488 self.cname = env.intern_identifier(self.name)
3489 self.bases.analyse_types(env)
3490 if self.doc:
3491 self.doc.analyse_types(env)
3492 self.doc = self.doc.coerce_to_pyobject(env)
3493 self.module_name = env.global_scope().qualified_name
3494 self.type = py_object_type
3495 self.gil_check(env)
3496 self.is_temp = 1
3497 env.use_utility_code(create_class_utility_code);
3499 gil_message = "Constructing Python class"
3501 def generate_result_code(self, code):
3502 if self.doc:
3503 code.put_error_if_neg(self.pos,
3504 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3505 self.dict.py_result(),
3506 self.doc.py_result()))
3507 code.putln(
3508 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3509 self.result(),
3510 self.bases.py_result(),
3511 self.dict.py_result(),
3512 self.cname,
3513 self.module_name,
3514 code.error_goto_if_null(self.result(), self.pos)))
3517 class UnboundMethodNode(ExprNode):
3518 # Helper class used in the implementation of Python
3519 # class definitions. Constructs an unbound method
3520 # object from a class and a function.
3522 # class_cname string C var holding the class object
3523 # function ExprNode Function object
3525 subexprs = ['function']
3527 def analyse_types(self, env):
3528 self.function.analyse_types(env)
3529 self.type = py_object_type
3530 self.gil_check(env)
3531 self.is_temp = 1
3533 gil_message = "Constructing an unbound method"
3535 def generate_result_code(self, code):
3536 code.putln(
3537 "%s = PyMethod_New(%s, 0, %s); %s" % (
3538 self.result(),
3539 self.function.py_result(),
3540 self.class_cname,
3541 code.error_goto_if_null(self.result(), self.pos)))
3544 class PyCFunctionNode(AtomicNewTempExprNode):
3545 # Helper class used in the implementation of Python
3546 # class definitions. Constructs a PyCFunction object
3547 # from a PyMethodDef struct.
3549 # pymethdef_cname string PyMethodDef structure
3551 def analyse_types(self, env):
3552 self.type = py_object_type
3553 self.gil_check(env)
3554 self.is_temp = 1
3556 gil_message = "Constructing Python function"
3558 def generate_result_code(self, code):
3559 code.putln(
3560 "%s = PyCFunction_New(&%s, 0); %s" % (
3561 self.result(),
3562 self.pymethdef_cname,
3563 code.error_goto_if_null(self.result(), self.pos)))
3565 #-------------------------------------------------------------------
3567 # Unary operator nodes
3569 #-------------------------------------------------------------------
3571 compile_time_unary_operators = {
3572 'not': operator.not_,
3573 '~': operator.inv,
3574 '-': operator.neg,
3575 '+': operator.pos,
3578 class UnopNode(ExprNode):
3579 # operator string
3580 # operand ExprNode
3582 # Processing during analyse_expressions phase:
3584 # analyse_c_operation
3585 # Called when the operand is not a pyobject.
3586 # - Check operand type and coerce if needed.
3587 # - Determine result type and result code fragment.
3588 # - Allocate temporary for result if needed.
3590 subexprs = ['operand']
3592 def calculate_constant_result(self):
3593 func = compile_time_unary_operators[self.operator]
3594 self.constant_result = func(self.operand.constant_result)
3596 def compile_time_value(self, denv):
3597 func = compile_time_unary_operators.get(self.operator)
3598 if not func:
3599 error(self.pos,
3600 "Unary '%s' not supported in compile-time expression"
3601 % self.operator)
3602 operand = self.operand.compile_time_value(denv)
3603 try:
3604 return func(operand)
3605 except Exception, e:
3606 self.compile_time_value_error(e)
3608 def analyse_types(self, env):
3609 self.operand.analyse_types(env)
3610 if self.is_py_operation():
3611 self.coerce_operand_to_pyobject(env)
3612 self.type = py_object_type
3613 self.gil_check(env)
3614 self.is_temp = 1
3615 else:
3616 self.analyse_c_operation(env)
3618 def check_const(self):
3619 self.operand.check_const()
3621 def is_py_operation(self):
3622 return self.operand.type.is_pyobject
3624 def coerce_operand_to_pyobject(self, env):
3625 self.operand = self.operand.coerce_to_pyobject(env)
3627 def generate_result_code(self, code):
3628 if self.operand.type.is_pyobject:
3629 self.generate_py_operation_code(code)
3630 else:
3631 if self.is_temp:
3632 self.generate_c_operation_code(code)
3634 def generate_py_operation_code(self, code):
3635 function = self.py_operation_function()
3636 code.putln(
3637 "%s = %s(%s); %s" % (
3638 self.result(),
3639 function,
3640 self.operand.py_result(),
3641 code.error_goto_if_null(self.result(), self.pos)))
3643 def type_error(self):
3644 if not self.operand.type.is_error:
3645 error(self.pos, "Invalid operand type for '%s' (%s)" %
3646 (self.operator, self.operand.type))
3647 self.type = PyrexTypes.error_type
3650 class NotNode(ExprNode):
3651 # 'not' operator
3653 # operand ExprNode
3655 def calculate_constant_result(self):
3656 self.constant_result = not self.operand.constant_result
3658 def compile_time_value(self, denv):
3659 operand = self.operand.compile_time_value(denv)
3660 try:
3661 return not operand
3662 except Exception, e:
3663 self.compile_time_value_error(e)
3665 subexprs = ['operand']
3667 def analyse_types(self, env):
3668 self.operand.analyse_types(env)
3669 self.operand = self.operand.coerce_to_boolean(env)
3670 self.type = PyrexTypes.c_bint_type
3672 def calculate_result_code(self):
3673 return "(!%s)" % self.operand.result()
3675 def generate_result_code(self, code):
3676 pass
3679 class UnaryPlusNode(UnopNode):
3680 # unary '+' operator
3682 operator = '+'
3684 def analyse_c_operation(self, env):
3685 self.type = self.operand.type
3687 def py_operation_function(self):
3688 return "PyNumber_Positive"
3690 def calculate_result_code(self):
3691 return self.operand.result()
3694 class UnaryMinusNode(UnopNode):
3695 # unary '-' operator
3697 operator = '-'
3699 def analyse_c_operation(self, env):
3700 if self.operand.type.is_numeric:
3701 self.type = self.operand.type
3702 else:
3703 self.type_error()
3705 def py_operation_function(self):
3706 return "PyNumber_Negative"
3708 def calculate_result_code(self):
3709 return "(-%s)" % self.operand.result()
3712 class TildeNode(UnopNode):
3713 # unary '~' operator
3715 def analyse_c_operation(self, env):
3716 if self.operand.type.is_int:
3717 self.type = self.operand.type
3718 else:
3719 self.type_error()
3721 def py_operation_function(self):
3722 return "PyNumber_Invert"
3724 def calculate_result_code(self):
3725 return "(~%s)" % self.operand.result()
3728 class AmpersandNode(ExprNode):
3729 # The C address-of operator.
3731 # operand ExprNode
3733 subexprs = ['operand']
3735 def analyse_types(self, env):
3736 self.operand.analyse_types(env)
3737 argtype = self.operand.type
3738 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3739 self.error("Taking address of non-lvalue")
3740 return
3741 if argtype.is_pyobject:
3742 self.error("Cannot take address of Python variable")
3743 return
3744 self.type = PyrexTypes.c_ptr_type(argtype)
3746 def check_const(self):
3747 self.operand.check_const_addr()
3749 def error(self, mess):
3750 error(self.pos, mess)
3751 self.type = PyrexTypes.error_type
3752 self.result_code = "<error>"
3754 def calculate_result_code(self):
3755 return "(&%s)" % self.operand.result()
3757 def generate_result_code(self, code):
3758 pass
3761 unop_node_classes = {
3762 "+": UnaryPlusNode,
3763 "-": UnaryMinusNode,
3764 "~": TildeNode,
3767 def unop_node(pos, operator, operand):
3768 # Construct unnop node of appropriate class for
3769 # given operator.
3770 if isinstance(operand, IntNode) and operator == '-':
3771 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3772 elif isinstance(operand, UnopNode) and operand.operator == operator:
3773 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3774 return unop_node_classes[operator](pos,
3775 operator = operator,
3776 operand = operand)
3779 class TypecastNode(NewTempExprNode):
3780 # C type cast
3782 # operand ExprNode
3783 # base_type CBaseTypeNode
3784 # declarator CDeclaratorNode
3786 # If used from a transform, one can if wanted specify the attribute
3787 # "type" directly and leave base_type and declarator to None
3789 subexprs = ['operand']
3790 base_type = declarator = type = None
3792 def analyse_types(self, env):
3793 if self.type is None:
3794 base_type = self.base_type.analyse(env)
3795 _, self.type = self.declarator.analyse(base_type, env)
3796 if self.type.is_cfunction:
3797 error(self.pos,
3798 "Cannot cast to a function type")
3799 self.type = PyrexTypes.error_type
3800 self.operand.analyse_types(env)
3801 to_py = self.type.is_pyobject
3802 from_py = self.operand.type.is_pyobject
3803 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3804 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3805 if to_py and not from_py:
3806 if (self.operand.type.to_py_function and
3807 self.operand.type.create_convert_utility_code(env)):
3808 self.result_ctype = py_object_type
3809 self.operand = self.operand.coerce_to_pyobject(env)
3810 else:
3811 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3812 self.operand = self.operand.coerce_to_simple(env)
3813 elif from_py and not to_py:
3814 if self.type.from_py_function:
3815 self.operand = self.operand.coerce_to(self.type, env)
3816 else:
3817 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3818 elif from_py and to_py:
3819 if self.typecheck and self.type.is_extension_type:
3820 self.operand = PyTypeTestNode(self.operand, self.type, env)
3822 def check_const(self):
3823 self.operand.check_const()
3825 def calculate_result_code(self):
3826 opnd = self.operand
3827 return self.type.cast_code(opnd.result())
3829 def result_as(self, type):
3830 if self.type.is_pyobject and not self.is_temp:
3831 # Optimise away some unnecessary casting
3832 return self.operand.result_as(type)
3833 else:
3834 return ExprNode.result_as(self, type)
3836 def generate_result_code(self, code):
3837 if self.is_temp:
3838 code.putln(
3839 "%s = (PyObject *)%s;" % (
3840 self.result(),
3841 self.operand.result()))
3842 code.put_incref(self.result(), self.ctype())
3845 class SizeofNode(ExprNode):
3846 # Abstract base class for sizeof(x) expression nodes.
3848 type = PyrexTypes.c_int_type
3850 def check_const(self):
3851 pass
3853 def generate_result_code(self, code):
3854 pass
3857 class SizeofTypeNode(SizeofNode):
3858 # C sizeof function applied to a type
3860 # base_type CBaseTypeNode
3861 # declarator CDeclaratorNode
3863 subexprs = []
3864 arg_type = None
3866 def analyse_types(self, env):
3867 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3868 # this could be better handled by more uniformly treating types as runtime-available objects
3869 if 0 and self.base_type.module_path:
3870 path = self.base_type.module_path
3871 obj = env.lookup(path[0])
3872 if obj.as_module is None:
3873 operand = NameNode(pos=self.pos, name=path[0])
3874 for attr in path[1:]:
3875 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3876 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3877 self.operand = operand
3878 self.__class__ = SizeofVarNode
3879 self.analyse_types(env)
3880 return
3881 if self.arg_type is None:
3882 base_type = self.base_type.analyse(env)
3883 _, arg_type = self.declarator.analyse(base_type, env)
3884 self.arg_type = arg_type
3885 self.check_type()
3887 def check_type(self):
3888 arg_type = self.arg_type
3889 if arg_type.is_pyobject and not arg_type.is_extension_type:
3890 error(self.pos, "Cannot take sizeof Python object")
3891 elif arg_type.is_void:
3892 error(self.pos, "Cannot take sizeof void")
3893 elif not arg_type.is_complete():
3894 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3896 def calculate_result_code(self):
3897 if self.arg_type.is_extension_type:
3898 # the size of the pointer is boring
3899 # we want the size of the actual struct
3900 arg_code = self.arg_type.declaration_code("", deref=1)
3901 else:
3902 arg_code = self.arg_type.declaration_code("")
3903 return "(sizeof(%s))" % arg_code
3906 class SizeofVarNode(SizeofNode):
3907 # C sizeof function applied to a variable
3909 # operand ExprNode
3911 subexprs = ['operand']
3913 def analyse_types(self, env):
3914 # We may actually be looking at a type rather than a variable...
3915 # If we are, traditional analysis would fail...
3916 operand_as_type = self.operand.analyse_as_type(env)
3917 if operand_as_type:
3918 self.arg_type = operand_as_type
3919 self.__class__ = SizeofTypeNode
3920 self.check_type()
3921 else:
3922 self.operand.analyse_types(env)
3924 def calculate_result_code(self):
3925 return "(sizeof(%s))" % self.operand.result()
3927 def generate_result_code(self, code):
3928 pass
3931 #-------------------------------------------------------------------
3933 # Binary operator nodes
3935 #-------------------------------------------------------------------
3937 def _not_in(x, seq):
3938 return x not in seq
3940 compile_time_binary_operators = {
3941 '<': operator.lt,
3942 '<=': operator.le,
3943 '==': operator.eq,
3944 '!=': operator.ne,
3945 '>=': operator.ge,
3946 '>': operator.gt,
3947 'is': operator.is_,
3948 'is_not': operator.is_not,
3949 '+': operator.add,
3950 '&': operator.and_,
3951 '/': operator.div,
3952 '//': operator.floordiv,
3953 '<<': operator.lshift,
3954 '%': operator.mod,
3955 '*': operator.mul,
3956 '|': operator.or_,
3957 '**': operator.pow,
3958 '>>': operator.rshift,
3959 '-': operator.sub,
3960 #'/': operator.truediv,
3961 '^': operator.xor,
3962 'in': operator.contains,
3963 'not_in': _not_in,
3966 def get_compile_time_binop(node):
3967 func = compile_time_binary_operators.get(node.operator)
3968 if not func:
3969 error(node.pos,
3970 "Binary '%s' not supported in compile-time expression"
3971 % node.operator)
3972 return func
3974 class BinopNode(NewTempExprNode):
3975 # operator string
3976 # operand1 ExprNode
3977 # operand2 ExprNode
3979 # Processing during analyse_expressions phase:
3981 # analyse_c_operation
3982 # Called when neither operand is a pyobject.
3983 # - Check operand types and coerce if needed.
3984 # - Determine result type and result code fragment.
3985 # - Allocate temporary for result if needed.
3987 subexprs = ['operand1', 'operand2']
3989 def calculate_constant_result(self):
3990 func = compile_time_binary_operators[self.operator]
3991 self.constant_result = func(
3992 self.operand1.constant_result,
3993 self.operand2.constant_result)
3995 def compile_time_value(self, denv):
3996 func = get_compile_time_binop(self)
3997 operand1 = self.operand1.compile_time_value(denv)
3998 operand2 = self.operand2.compile_time_value(denv)
3999 try:
4000 return func(operand1, operand2)
4001 except Exception, e:
4002 self.compile_time_value_error(e)
4004 def analyse_types(self, env):
4005 self.operand1.analyse_types(env)
4006 self.operand2.analyse_types(env)
4007 if self.is_py_operation():
4008 self.coerce_operands_to_pyobjects(env)
4009 self.type = py_object_type
4010 self.gil_check(env)
4011 self.is_temp = 1
4012 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4013 self.operand1 = self.operand1.coerce_to_temp(env)
4014 else:
4015 self.analyse_c_operation(env)
4017 def is_py_operation(self):
4018 return (self.operand1.type.is_pyobject
4019 or self.operand2.type.is_pyobject)
4021 def coerce_operands_to_pyobjects(self, env):
4022 self.operand1 = self.operand1.coerce_to_pyobject(env)
4023 self.operand2 = self.operand2.coerce_to_pyobject(env)
4025 def check_const(self):
4026 self.operand1.check_const()
4027 self.operand2.check_const()
4029 def generate_result_code(self, code):
4030 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4031 if self.operand1.type.is_pyobject:
4032 function = self.py_operation_function()
4033 if function == "PyNumber_Power":
4034 extra_args = ", Py_None"
4035 else:
4036 extra_args = ""
4037 code.putln(
4038 "%s = %s(%s, %s%s); %s" % (
4039 self.result(),
4040 function,
4041 self.operand1.py_result(),
4042 self.operand2.py_result(),
4043 extra_args,
4044 code.error_goto_if_null(self.result(), self.pos)))
4045 else:
4046 if self.is_temp:
4047 self.generate_c_operation_code(code)
4049 def type_error(self):
4050 if not (self.operand1.type.is_error
4051 or self.operand2.type.is_error):
4052 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4053 (self.operator, self.operand1.type,
4054 self.operand2.type))
4055 self.type = PyrexTypes.error_type
4058 class NumBinopNode(BinopNode):
4059 # Binary operation taking numeric arguments.
4061 def analyse_c_operation(self, env):
4062 type1 = self.operand1.type
4063 type2 = self.operand2.type
4064 if self.operator == "**" and type1.is_int and type2.is_int:
4065 error(self.pos, "** with two C int types is ambiguous")
4066 self.type = error_type
4067 return
4068 self.type = self.compute_c_result_type(type1, type2)
4069 if not self.type:
4070 self.type_error()
4072 def compute_c_result_type(self, type1, type2):
4073 if self.c_types_okay(type1, type2):
4074 return PyrexTypes.widest_numeric_type(type1, type2)
4075 else:
4076 return None
4078 def c_types_okay(self, type1, type2):
4079 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4080 return (type1.is_numeric or type1.is_enum) \
4081 and (type2.is_numeric or type2.is_enum)
4083 def calculate_result_code(self):
4084 return "(%s %s %s)" % (
4085 self.operand1.result(),
4086 self.operator,
4087 self.operand2.result())
4089 def py_operation_function(self):
4090 return self.py_functions[self.operator]
4092 py_functions = {
4093 "|": "PyNumber_Or",
4094 "^": "PyNumber_Xor",
4095 "&": "PyNumber_And",
4096 "<<": "PyNumber_Lshift",
4097 ">>": "PyNumber_Rshift",
4098 "+": "PyNumber_Add",
4099 "-": "PyNumber_Subtract",
4100 "*": "PyNumber_Multiply",
4101 "/": "__Pyx_PyNumber_Divide",
4102 "//": "PyNumber_FloorDivide",
4103 "%": "PyNumber_Remainder",
4104 "**": "PyNumber_Power"
4108 class IntBinopNode(NumBinopNode):
4109 # Binary operation taking integer arguments.
4111 def c_types_okay(self, type1, type2):
4112 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4113 return (type1.is_int or type1.is_enum) \
4114 and (type2.is_int or type2.is_enum)
4117 class AddNode(NumBinopNode):
4118 # '+' operator.
4120 def is_py_operation(self):
4121 if self.operand1.type.is_string \
4122 and self.operand2.type.is_string:
4123 return 1
4124 else:
4125 return NumBinopNode.is_py_operation(self)
4127 def compute_c_result_type(self, type1, type2):
4128 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4129 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4130 return type1
4131 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4132 return type2
4133 else:
4134 return NumBinopNode.compute_c_result_type(
4135 self, type1, type2)
4138 class SubNode(NumBinopNode):
4139 # '-' operator.
4141 def compute_c_result_type(self, type1, type2):
4142 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4143 return type1
4144 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4145 return PyrexTypes.c_int_type
4146 else:
4147 return NumBinopNode.compute_c_result_type(
4148 self, type1, type2)
4151 class MulNode(NumBinopNode):
4152 # '*' operator.
4154 def is_py_operation(self):
4155 type1 = self.operand1.type
4156 type2 = self.operand2.type
4157 if (type1.is_string and type2.is_int) \
4158 or (type2.is_string and type1.is_int):
4159 return 1
4160 else:
4161 return NumBinopNode.is_py_operation(self)
4164 class FloorDivNode(NumBinopNode):
4165 # '//' operator.
4167 def calculate_result_code(self):
4168 return "(%s %s %s)" % (
4169 self.operand1.result(),
4170 "/", # c division is by default floor-div
4171 self.operand2.result())
4174 class ModNode(NumBinopNode):
4175 # '%' operator.
4177 def is_py_operation(self):
4178 return (self.operand1.type.is_string
4179 or self.operand2.type.is_string
4180 or NumBinopNode.is_py_operation(self))
4182 def calculate_result_code(self):
4183 if self.operand1.type.is_float or self.operand2.type.is_float:
4184 return "fmod(%s, %s)" % (
4185 self.operand1.result(),
4186 self.operand2.result())
4187 else:
4188 return "(%s %% %s)" % (
4189 self.operand1.result(),
4190 self.operand2.result())
4192 class PowNode(NumBinopNode):
4193 # '**' operator.
4195 def compute_c_result_type(self, type1, type2):
4196 if self.c_types_okay(type1, type2):
4197 return PyrexTypes.c_double_type
4198 else:
4199 return None
4201 def c_types_okay(self, type1, type2):
4202 return (type1.is_float or type2.is_float) and \
4203 NumBinopNode.c_types_okay(self, type1, type2)
4205 def type_error(self):
4206 if not (self.operand1.type.is_error or self.operand2.type.is_error):
4207 if self.operand1.type.is_int and self.operand2.type.is_int:
4208 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
4209 (self.operator, self.operand1.type, self.operand2.type))
4210 else:
4211 NumBinopNode.type_error(self)
4212 self.type = PyrexTypes.error_type
4214 def calculate_result_code(self):
4215 return "pow(%s, %s)" % (
4216 self.operand1.result(), self.operand2.result())
4219 # Note: This class is temporary "shut down" into an ineffective mode temp
4220 # allocation mode.
4222 # More sophisticated temp reuse was going on before,
4223 # one could have a look at adding this again after /all/ classes
4224 # are converted to the new temp scheme. (The temp juggling cannot work
4225 # otherwise).
4226 class BoolBinopNode(NewTempExprNode):
4227 # Short-circuiting boolean operation.
4229 # operator string
4230 # operand1 ExprNode
4231 # operand2 ExprNode
4233 subexprs = ['operand1', 'operand2']
4235 def calculate_constant_result(self):
4236 if self.operator == 'and':
4237 self.constant_result = \
4238 self.operand1.constant_result and \
4239 self.operand2.constant_result
4240 else:
4241 self.constant_result = \
4242 self.operand1.constant_result or \
4243 self.operand2.constant_result
4245 def compile_time_value(self, denv):
4246 if self.operator == 'and':
4247 return self.operand1.compile_time_value(denv) \
4248 and self.operand2.compile_time_value(denv)
4249 else:
4250 return self.operand1.compile_time_value(denv) \
4251 or self.operand2.compile_time_value(denv)
4253 def coerce_to_boolean(self, env):
4254 self.operand1 = self.operand1.coerce_to_boolean(env)
4255 self.operand2 = self.operand2.coerce_to_boolean(env)
4256 self.type = PyrexTypes.c_bint_type
4257 return self
4259 def analyse_types(self, env):
4260 self.operand1.analyse_types(env)
4261 self.operand2.analyse_types(env)
4262 if self.operand1.type.is_pyobject or \
4263 self.operand2.type.is_pyobject:
4264 self.operand1 = self.operand1.coerce_to_pyobject(env)
4265 self.operand2 = self.operand2.coerce_to_pyobject(env)
4266 self.type = py_object_type
4267 self.gil_check(env)
4268 else:
4269 self.operand1 = self.operand1.coerce_to_boolean(env)
4270 self.operand2 = self.operand2.coerce_to_boolean(env)
4271 self.type = PyrexTypes.c_bint_type
4273 # Below disabled for
4275 # For what we're about to do, it's vital that
4276 # both operands be temp nodes.
4277 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4278 # self.operand2 = self.operand2.coerce_to_temp(env)
4279 self.is_temp = 1
4281 gil_message = "Truth-testing Python object"
4283 ## def allocate_temps(self, env, result_code = None):
4284 ## # We don't need both operands at the same time, and
4285 ## # one of the operands will also be our result. So we
4286 ## # use an allocation strategy here which results in
4287 ## # this node and both its operands sharing the same
4288 ## # result variable. This allows us to avoid some
4289 ## # assignments and increfs/decrefs that would otherwise
4290 ## # be necessary.
4291 ## self.allocate_temp(env, result_code)
4292 ## self.operand1.allocate_temps(env, self.result())
4293 ## self.operand2.allocate_temps(env, self.result())
4294 ## # We haven't called release_temp on either operand,
4295 ## # because although they are temp nodes, they don't own
4296 ## # their result variable. And because they are temp
4297 ## # nodes, any temps in their subnodes will have been
4298 ## # released before their allocate_temps returned.
4299 ## # Therefore, they contain no temp vars that need to
4300 ## # be released.
4302 def check_const(self):
4303 self.operand1.check_const()
4304 self.operand2.check_const()
4306 def calculate_result_code(self):
4307 return "(%s %s %s)" % (
4308 self.operand1.result(),
4309 self.py_to_c_op[self.operator],
4310 self.operand2.result())
4312 py_to_c_op = {'and': "&&", 'or': "||"}
4314 def generate_evaluation_code(self, code):
4315 code.mark_pos(self.pos)
4316 self.operand1.generate_evaluation_code(code)
4317 test_result, uses_temp = self.generate_operand1_test(code)
4318 if self.operator == 'and':
4319 sense = ""
4320 else:
4321 sense = "!"
4322 code.putln(
4323 "if (%s%s) {" % (
4324 sense,
4325 test_result))
4326 if uses_temp:
4327 code.funcstate.release_temp(test_result)
4328 self.operand1.generate_disposal_code(code)
4329 self.operand2.generate_evaluation_code(code)
4330 self.allocate_temp_result(code)
4331 self.operand2.make_owned_reference(code)
4332 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4333 self.operand2.generate_post_assignment_code(code)
4334 self.operand2.free_temps(code)
4335 code.putln("} else {")
4336 self.operand1.make_owned_reference(code)
4337 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4338 self.operand1.generate_post_assignment_code(code)
4339 self.operand1.free_temps(code)
4340 code.putln("}")
4342 def generate_operand1_test(self, code):
4343 # Generate code to test the truth of the first operand.
4344 if self.type.is_pyobject:
4345 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4346 manage_ref=False)
4347 code.putln(
4348 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4349 test_result,
4350 self.operand1.py_result(),
4351 code.error_goto_if_neg(test_result, self.pos)))
4352 else:
4353 test_result = self.operand1.result()
4354 return (test_result, self.type.is_pyobject)
4357 class CondExprNode(ExprNode):
4358 # Short-circuiting conditional expression.
4360 # test ExprNode
4361 # true_val ExprNode
4362 # false_val ExprNode
4364 true_val = None
4365 false_val = None
4367 subexprs = ['test', 'true_val', 'false_val']
4369 def calculate_constant_result(self):
4370 if self.test.constant_result:
4371 self.constant_result = self.true_val.constant_result
4372 else:
4373 self.constant_result = self.false_val.constant_result
4375 def analyse_types(self, env):
4376 self.test.analyse_types(env)
4377 self.test = self.test.coerce_to_boolean(env)
4378 self.true_val.analyse_types(env)
4379 self.false_val.analyse_types(env)
4380 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4381 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4382 self.true_val = self.true_val.coerce_to(self.type, env)
4383 self.false_val = self.false_val.coerce_to(self.type, env)
4384 # must be tmp variables so they can share a result
4385 self.true_val = self.true_val.coerce_to_temp(env)
4386 self.false_val = self.false_val.coerce_to_temp(env)
4387 self.is_temp = 1
4388 if self.type == PyrexTypes.error_type:
4389 self.type_error()
4391 def allocate_temps(self, env, result_code = None):
4392 # We only ever evaluate one side, and this is
4393 # after evaluating the truth value, so we may
4394 # use an allocation strategy here which results in
4395 # this node and both its operands sharing the same
4396 # result variable. This allows us to avoid some
4397 # assignments and increfs/decrefs that would otherwise
4398 # be necessary.
4399 self.allocate_temp(env, result_code)
4400 self.test.allocate_temps(env, result_code)
4401 self.true_val.allocate_temps(env, self.result())
4402 self.false_val.allocate_temps(env, self.result())
4403 # We haven't called release_temp on either value,
4404 # because although they are temp nodes, they don't own
4405 # their result variable. And because they are temp
4406 # nodes, any temps in their subnodes will have been
4407 # released before their allocate_temps returned.
4408 # Therefore, they contain no temp vars that need to
4409 # be released.
4411 def compute_result_type(self, type1, type2):
4412 if type1 == type2:
4413 return type1
4414 elif type1.is_numeric and type2.is_numeric:
4415 return PyrexTypes.widest_numeric_type(type1, type2)
4416 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4417 return type2
4418 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4419 return type1
4420 elif type1.is_pyobject or type2.is_pyobject:
4421 return py_object_type
4422 elif type1.assignable_from(type2):
4423 return type1
4424 elif type2.assignable_from(type1):
4425 return type2
4426 else:
4427 return PyrexTypes.error_type
4429 def type_error(self):
4430 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4431 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4432 (self.true_val.type, self.false_val.type))
4433 self.type = PyrexTypes.error_type
4435 def check_const(self):
4436 self.test.check_const()
4437 self.true_val.check_const()
4438 self.false_val.check_const()
4440 def generate_evaluation_code(self, code):
4441 self.test.generate_evaluation_code(code)
4442 code.putln("if (%s) {" % self.test.result() )
4443 self.true_val.generate_evaluation_code(code)
4444 code.putln("} else {")
4445 self.false_val.generate_evaluation_code(code)
4446 code.putln("}")
4447 self.test.generate_disposal_code(code)
4448 self.test.free_temps(code)
4450 richcmp_constants = {
4451 "<" : "Py_LT",
4452 "<=": "Py_LE",
4453 "==": "Py_EQ",
4454 "!=": "Py_NE",
4455 "<>": "Py_NE",
4456 ">" : "Py_GT",
4457 ">=": "Py_GE",
4460 class CmpNode:
4461 # Mixin class containing code common to PrimaryCmpNodes
4462 # and CascadedCmpNodes.
4464 def calculate_cascaded_constant_result(self, operand1_result):
4465 func = compile_time_binary_operators[self.operator]
4466 operand2_result = self.operand2.constant_result
4467 result = func(operand1_result, operand2_result)
4468 if result and self.cascade:
4469 result = result and \
4470 self.cascade.cascaded_compile_time_value(operand2_result)
4471 self.constant_result = result
4473 def cascaded_compile_time_value(self, operand1, denv):
4474 func = get_compile_time_binop(self)
4475 operand2 = self.operand2.compile_time_value(denv)
4476 try:
4477 result = func(operand1, operand2)
4478 except Exception, e:
4479 self.compile_time_value_error(e)
4480 result = None
4481 if result:
4482 cascade = self.cascade
4483 if cascade:
4484 # FIXME: I bet this must call cascaded_compile_time_value()
4485 result = result and cascade.compile_time_value(operand2, denv)
4486 return result
4488 def is_python_comparison(self):
4489 return (self.has_python_operands()
4490 or (self.cascade and self.cascade.is_python_comparison())
4491 or self.operator in ('in', 'not_in'))
4493 def is_python_result(self):
4494 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4495 or (self.cascade and self.cascade.is_python_result()))
4497 def check_types(self, env, operand1, op, operand2):
4498 if not self.types_okay(operand1, op, operand2):
4499 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4500 (self.operator, operand1.type, operand2.type))
4502 def types_okay(self, operand1, op, operand2):
4503 type1 = operand1.type
4504 type2 = operand2.type
4505 if type1.is_error or type2.is_error:
4506 return 1
4507 if type1.is_pyobject: # type2 will be, too
4508 return 1
4509 elif type1.is_ptr or type1.is_array:
4510 return type1.is_null_ptr or type2.is_null_ptr \
4511 or ((type2.is_ptr or type2.is_array)
4512 and type1.base_type.same_as(type2.base_type))
4513 elif ((type1.is_numeric and type2.is_numeric
4514 or type1.is_enum and (type1 is type2 or type2.is_int)
4515 or type1.is_int and type2.is_enum)
4516 and op not in ('is', 'is_not')):
4517 return 1
4518 else:
4519 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4521 def generate_operation_code(self, code, result_code,
4522 operand1, op , operand2):
4523 if self.type is PyrexTypes.py_object_type:
4524 coerce_result = "__Pyx_PyBool_FromLong"
4525 else:
4526 coerce_result = ""
4527 if 'not' in op: negation = "!"
4528 else: negation = ""
4529 if op == 'in' or op == 'not_in':
4530 code.putln(
4531 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4532 result_code,
4533 coerce_result,
4534 negation,
4535 operand2.py_result(),
4536 operand1.py_result(),
4537 code.error_goto_if_neg(result_code, self.pos)))
4538 elif (operand1.type.is_pyobject
4539 and op not in ('is', 'is_not')):
4540 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4541 result_code,
4542 operand1.py_result(),
4543 operand2.py_result(),
4544 richcmp_constants[op],
4545 code.error_goto_if_null(result_code, self.pos)))
4546 else:
4547 type1 = operand1.type
4548 type2 = operand2.type
4549 if (type1.is_extension_type or type2.is_extension_type) \
4550 and not type1.same_as(type2):
4551 common_type = py_object_type
4552 elif type1.is_numeric:
4553 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4554 else:
4555 common_type = type1
4556 code1 = operand1.result_as(common_type)
4557 code2 = operand2.result_as(common_type)
4558 code.putln("%s = %s(%s %s %s);" % (
4559 result_code,
4560 coerce_result,
4561 code1,
4562 self.c_operator(op),
4563 code2))
4565 def c_operator(self, op):
4566 if op == 'is':
4567 return "=="
4568 elif op == 'is_not':
4569 return "!="
4570 else:
4571 return op
4574 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4575 # Non-cascaded comparison or first comparison of
4576 # a cascaded sequence.
4578 # operator string
4579 # operand1 ExprNode
4580 # operand2 ExprNode
4581 # cascade CascadedCmpNode
4583 # We don't use the subexprs mechanism, because
4584 # things here are too complicated for it to handle.
4585 # Instead, we override all the framework methods
4586 # which use it.
4588 child_attrs = ['operand1', 'operand2', 'cascade']
4590 cascade = None
4592 def calculate_constant_result(self):
4593 self.constant_result = self.calculate_cascaded_constant_result(
4594 self.operand1.constant_result)
4596 def compile_time_value(self, denv):
4597 operand1 = self.operand1.compile_time_value(denv)
4598 return self.cascaded_compile_time_value(operand1, denv)
4600 def analyse_types(self, env):
4601 self.operand1.analyse_types(env)
4602 self.operand2.analyse_types(env)
4603 if self.cascade:
4604 self.cascade.analyse_types(env, self.operand2)
4605 self.is_pycmp = self.is_python_comparison()
4606 if self.is_pycmp:
4607 self.coerce_operands_to_pyobjects(env)
4608 if self.has_int_operands():
4609 self.coerce_chars_to_ints(env)
4610 if self.cascade:
4611 self.operand2 = self.operand2.coerce_to_simple(env)
4612 self.cascade.coerce_cascaded_operands_to_temp(env)
4613 self.check_operand_types(env)
4614 if self.is_python_result():
4615 self.type = PyrexTypes.py_object_type
4616 else:
4617 self.type = PyrexTypes.c_bint_type
4618 cdr = self.cascade
4619 while cdr:
4620 cdr.type = self.type
4621 cdr = cdr.cascade
4622 if self.is_pycmp or self.cascade:
4623 self.is_temp = 1
4625 def check_operand_types(self, env):
4626 self.check_types(env,
4627 self.operand1, self.operator, self.operand2)
4628 if self.cascade:
4629 self.cascade.check_operand_types(env, self.operand2)
4631 def has_python_operands(self):
4632 return (self.operand1.type.is_pyobject
4633 or self.operand2.type.is_pyobject)
4635 def coerce_operands_to_pyobjects(self, env):
4636 self.operand1 = self.operand1.coerce_to_pyobject(env)
4637 self.operand2 = self.operand2.coerce_to_pyobject(env)
4638 if self.cascade:
4639 self.cascade.coerce_operands_to_pyobjects(env)
4641 def has_int_operands(self):
4642 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4643 or (self.cascade and self.cascade.has_int_operands())
4645 def coerce_chars_to_ints(self, env):
4646 # coerce literal single-char strings to c chars
4647 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4648 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4649 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4650 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4651 if self.cascade:
4652 self.cascade.coerce_chars_to_ints(env)
4654 def allocate_subexpr_temps(self, env):
4655 self.operand1.allocate_temps(env)
4656 self.operand2.allocate_temps(env)
4657 if self.cascade:
4658 self.cascade.allocate_subexpr_temps(env)
4660 def release_subexpr_temps(self, env):
4661 self.operand1.release_temp(env)
4662 self.operand2.release_temp(env)
4663 if self.cascade:
4664 self.cascade.release_subexpr_temps(env)
4666 def check_const(self):
4667 self.operand1.check_const()
4668 self.operand2.check_const()
4669 if self.cascade:
4670 self.not_const()
4672 def calculate_result_code(self):
4673 return "(%s %s %s)" % (
4674 self.operand1.result(),
4675 self.c_operator(self.operator),
4676 self.operand2.result())
4678 def generate_evaluation_code(self, code):
4679 self.operand1.generate_evaluation_code(code)
4680 self.operand2.generate_evaluation_code(code)
4681 if self.is_temp:
4682 self.allocate_temp_result(code)
4683 self.generate_operation_code(code, self.result(),
4684 self.operand1, self.operator, self.operand2)
4685 if self.cascade:
4686 self.cascade.generate_evaluation_code(code,
4687 self.result(), self.operand2)
4688 self.operand1.generate_disposal_code(code)
4689 self.operand1.free_temps(code)
4690 self.operand2.generate_disposal_code(code)
4691 self.operand2.free_temps(code)
4693 def generate_subexpr_disposal_code(self, code):
4694 # If this is called, it is a non-cascaded cmp,
4695 # so only need to dispose of the two main operands.
4696 self.operand1.generate_disposal_code(code)
4697 self.operand2.generate_disposal_code(code)
4699 def free_subexpr_temps(self, code):
4700 # If this is called, it is a non-cascaded cmp,
4701 # so only need to dispose of the two main operands.
4702 self.operand1.free_temps(code)
4703 self.operand2.free_temps(code)
4705 def annotate(self, code):
4706 self.operand1.annotate(code)
4707 self.operand2.annotate(code)
4708 if self.cascade:
4709 self.cascade.annotate(code)
4712 class CascadedCmpNode(Node, CmpNode):
4713 # A CascadedCmpNode is not a complete expression node. It
4714 # hangs off the side of another comparison node, shares
4715 # its left operand with that node, and shares its result
4716 # with the PrimaryCmpNode at the head of the chain.
4718 # operator string
4719 # operand2 ExprNode
4720 # cascade CascadedCmpNode
4722 child_attrs = ['operand2', 'cascade']
4724 cascade = None
4725 constant_result = constant_value_not_set # FIXME: where to calculate this?
4727 def analyse_types(self, env, operand1):
4728 self.operand2.analyse_types(env)
4729 if self.cascade:
4730 self.cascade.analyse_types(env, self.operand2)
4732 def check_operand_types(self, env, operand1):
4733 self.check_types(env,
4734 operand1, self.operator, self.operand2)
4735 if self.cascade:
4736 self.cascade.check_operand_types(env, self.operand2)
4738 def has_python_operands(self):
4739 return self.operand2.type.is_pyobject
4741 def coerce_operands_to_pyobjects(self, env):
4742 self.operand2 = self.operand2.coerce_to_pyobject(env)
4743 if self.cascade:
4744 self.cascade.coerce_operands_to_pyobjects(env)
4746 def has_int_operands(self):
4747 return self.operand2.type.is_int
4749 def coerce_chars_to_ints(self, env):
4750 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4751 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4753 def coerce_cascaded_operands_to_temp(self, env):
4754 if self.cascade:
4755 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4756 self.operand2 = self.operand2.coerce_to_simple(env)
4757 self.cascade.coerce_cascaded_operands_to_temp(env)
4759 def allocate_subexpr_temps(self, env):
4760 self.operand2.allocate_temps(env)
4761 if self.cascade:
4762 self.cascade.allocate_subexpr_temps(env)
4764 def release_subexpr_temps(self, env):
4765 self.operand2.release_temp(env)
4766 if self.cascade:
4767 self.cascade.release_subexpr_temps(env)
4769 def generate_evaluation_code(self, code, result, operand1):
4770 if self.type.is_pyobject:
4771 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4772 else:
4773 code.putln("if (%s) {" % result)
4774 self.operand2.generate_evaluation_code(code)
4775 self.generate_operation_code(code, result,
4776 operand1, self.operator, self.operand2)
4777 if self.cascade:
4778 self.cascade.generate_evaluation_code(
4779 code, result, self.operand2)
4780 # Cascaded cmp result is always temp
4781 self.operand2.generate_disposal_code(code)
4782 self.operand2.free_temps(code)
4783 code.putln("}")
4785 def annotate(self, code):
4786 self.operand2.annotate(code)
4787 if self.cascade:
4788 self.cascade.annotate(code)
4791 binop_node_classes = {
4792 "or": BoolBinopNode,
4793 "and": BoolBinopNode,
4794 "|": IntBinopNode,
4795 "^": IntBinopNode,
4796 "&": IntBinopNode,
4797 "<<": IntBinopNode,
4798 ">>": IntBinopNode,
4799 "+": AddNode,
4800 "-": SubNode,
4801 "*": MulNode,
4802 "/": NumBinopNode,
4803 "//": FloorDivNode,
4804 "%": ModNode,
4805 "**": PowNode
4808 def binop_node(pos, operator, operand1, operand2):
4809 # Construct binop node of appropriate class for
4810 # given operator.
4811 return binop_node_classes[operator](pos,
4812 operator = operator,
4813 operand1 = operand1,
4814 operand2 = operand2)
4816 #-------------------------------------------------------------------
4818 # Coercion nodes
4820 # Coercion nodes are special in that they are created during
4821 # the analyse_types phase of parse tree processing.
4822 # Their __init__ methods consequently incorporate some aspects
4823 # of that phase.
4825 #-------------------------------------------------------------------
4827 class CoercionNode(NewTempExprNode):
4828 # Abstract base class for coercion nodes.
4830 # arg ExprNode node being coerced
4832 subexprs = ['arg']
4834 def __init__(self, arg):
4835 self.pos = arg.pos
4836 self.arg = arg
4837 if debug_coercion:
4838 print("%s Coercing %s" % (self, self.arg))
4840 def annotate(self, code):
4841 self.arg.annotate(code)
4842 if self.arg.type != self.type:
4843 file, line, col = self.pos
4844 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4847 class CastNode(CoercionNode):
4848 # Wrap a node in a C type cast.
4850 def __init__(self, arg, new_type):
4851 CoercionNode.__init__(self, arg)
4852 self.type = new_type
4854 def calculate_result_code(self):
4855 return self.arg.result_as(self.type)
4857 def generate_result_code(self, code):
4858 self.arg.generate_result_code(code)
4861 class PyTypeTestNode(CoercionNode):
4862 # This node is used to check that a generic Python
4863 # object is an instance of a particular extension type.
4864 # This node borrows the result of its argument node.
4866 def __init__(self, arg, dst_type, env):
4867 # The arg is know to be a Python object, and
4868 # the dst_type is known to be an extension type.
4869 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4870 CoercionNode.__init__(self, arg)
4871 self.type = dst_type
4872 self.gil_check(env)
4873 self.result_ctype = arg.ctype()
4875 gil_message = "Python type test"
4877 def analyse_types(self, env):
4878 pass
4880 def result_in_temp(self):
4881 return self.arg.result_in_temp()
4883 def is_ephemeral(self):
4884 return self.arg.is_ephemeral()
4886 def calculate_result_code(self):
4887 return self.arg.result()
4889 def generate_result_code(self, code):
4890 if self.type.typeobj_is_available():
4891 if not self.type.is_builtin_type:
4892 code.globalstate.use_utility_code(type_test_utility_code)
4893 code.putln(
4894 "if (!(%s)) %s" % (
4895 self.type.type_test_code(self.arg.py_result()),
4896 code.error_goto(self.pos)))
4897 else:
4898 error(self.pos, "Cannot test type of extern C class "
4899 "without type object name specification")
4901 def generate_post_assignment_code(self, code):
4902 self.arg.generate_post_assignment_code(code)
4904 def free_temps(self, code):
4905 self.arg.free_temps(code)
4908 class CoerceToPyTypeNode(CoercionNode):
4909 # This node is used to convert a C data type
4910 # to a Python object.
4912 def __init__(self, arg, env):
4913 CoercionNode.__init__(self, arg)
4914 self.type = py_object_type
4915 self.gil_check(env)
4916 self.is_temp = 1
4917 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4918 error(arg.pos,
4919 "Cannot convert '%s' to Python object" % arg.type)
4921 gil_message = "Converting to Python object"
4923 def coerce_to_boolean(self, env):
4924 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
4926 def analyse_types(self, env):
4927 # The arg is always already analysed
4928 pass
4930 def generate_result_code(self, code):
4931 function = self.arg.type.to_py_function
4932 code.putln('%s = %s(%s); %s' % (
4933 self.result(),
4934 function,
4935 self.arg.result(),
4936 code.error_goto_if_null(self.result(), self.pos)))
4939 class CoerceFromPyTypeNode(CoercionNode):
4940 # This node is used to convert a Python object
4941 # to a C data type.
4943 def __init__(self, result_type, arg, env):
4944 CoercionNode.__init__(self, arg)
4945 self.type = result_type
4946 self.is_temp = 1
4947 if not result_type.from_py_function:
4948 error(arg.pos,
4949 "Cannot convert Python object to '%s'" % result_type)
4950 if self.type.is_string and self.arg.is_ephemeral():
4951 error(arg.pos,
4952 "Obtaining char * from temporary Python value")
4954 def analyse_types(self, env):
4955 # The arg is always already analysed
4956 pass
4958 def generate_result_code(self, code):
4959 function = self.type.from_py_function
4960 operand = self.arg.py_result()
4961 rhs = "%s(%s)" % (function, operand)
4962 if self.type.is_enum:
4963 rhs = typecast(self.type, c_long_type, rhs)
4964 code.putln('%s = %s; %s' % (
4965 self.result(),
4966 rhs,
4967 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4970 class CoerceToBooleanNode(CoercionNode):
4971 # This node is used when a result needs to be used
4972 # in a boolean context.
4974 def __init__(self, arg, env):
4975 CoercionNode.__init__(self, arg)
4976 self.type = PyrexTypes.c_bint_type
4977 if arg.type.is_pyobject:
4978 if env.nogil:
4979 self.gil_error()
4980 self.is_temp = 1
4982 gil_message = "Truth-testing Python object"
4984 def check_const(self):
4985 if self.is_temp:
4986 self.not_const()
4987 self.arg.check_const()
4989 def calculate_result_code(self):
4990 return "(%s != 0)" % self.arg.result()
4992 def generate_result_code(self, code):
4993 if self.arg.type.is_pyobject:
4994 code.putln(
4995 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4996 self.result(),
4997 self.arg.py_result(),
4998 code.error_goto_if_neg(self.result(), self.pos)))
5001 class CoerceToTempNode(CoercionNode):
5002 # This node is used to force the result of another node
5003 # to be stored in a temporary. It is only used if the
5004 # argument node's result is not already in a temporary.
5006 def __init__(self, arg, env):
5007 CoercionNode.__init__(self, arg)
5008 self.type = self.arg.type
5009 self.is_temp = 1
5010 if self.type.is_pyobject:
5011 self.gil_check(env)
5012 self.result_ctype = py_object_type
5014 gil_message = "Creating temporary Python reference"
5016 def analyse_types(self, env):
5017 # The arg is always already analysed
5018 pass
5020 def coerce_to_boolean(self, env):
5021 self.arg = self.arg.coerce_to_boolean(env)
5022 self.type = self.arg.type
5023 self.result_ctype = self.type
5024 return self
5026 def generate_result_code(self, code):
5027 #self.arg.generate_evaluation_code(code) # Already done
5028 # by generic generate_subexpr_evaluation_code!
5029 code.putln("%s = %s;" % (
5030 self.result(), self.arg.result_as(self.ctype())))
5031 if self.type.is_pyobject:
5032 code.put_incref(self.result(), self.ctype())
5035 class CloneNode(CoercionNode):
5036 # This node is employed when the result of another node needs
5037 # to be used multiple times. The argument node's result must
5038 # be in a temporary. This node "borrows" the result from the
5039 # argument node, and does not generate any evaluation or
5040 # disposal code for it. The original owner of the argument
5041 # node is responsible for doing those things.
5043 subexprs = [] # Arg is not considered a subexpr
5045 def __init__(self, arg):
5046 CoercionNode.__init__(self, arg)
5047 if hasattr(arg, 'type'):
5048 self.type = arg.type
5049 self.result_ctype = arg.result_ctype
5050 if hasattr(arg, 'entry'):
5051 self.entry = arg.entry
5053 def result(self):
5054 return self.arg.result()
5056 def analyse_types(self, env):
5057 self.type = self.arg.type
5058 self.result_ctype = self.arg.result_ctype
5059 self.is_temp = 1
5060 if hasattr(self.arg, 'entry'):
5061 self.entry = self.arg.entry
5063 def generate_evaluation_code(self, code):
5064 pass
5066 def generate_result_code(self, code):
5067 pass
5069 def generate_disposal_code(self, code):
5070 pass
5072 def allocate_temps(self, env):
5073 pass
5075 def release_temp(self, env):
5076 pass
5078 def free_temps(self, code):
5079 pass
5082 #------------------------------------------------------------------------------------
5084 # Runtime support code
5086 #------------------------------------------------------------------------------------
5088 get_name_interned_utility_code = UtilityCode(
5089 proto = """
5090 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5091 """,
5092 impl = """
5093 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5094 PyObject *result;
5095 result = PyObject_GetAttr(dict, name);
5096 if (!result)
5097 PyErr_SetObject(PyExc_NameError, name);
5098 return result;
5100 """)
5102 #------------------------------------------------------------------------------------
5104 import_utility_code = UtilityCode(
5105 proto = """
5106 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5107 """,
5108 impl = """
5109 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5110 PyObject *__import__ = 0;
5111 PyObject *empty_list = 0;
5112 PyObject *module = 0;
5113 PyObject *global_dict = 0;
5114 PyObject *empty_dict = 0;
5115 PyObject *list;
5116 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
5117 if (!__import__)
5118 goto bad;
5119 if (from_list)
5120 list = from_list;
5121 else {
5122 empty_list = PyList_New(0);
5123 if (!empty_list)
5124 goto bad;
5125 list = empty_list;
5127 global_dict = PyModule_GetDict(%(GLOBALS)s);
5128 if (!global_dict)
5129 goto bad;
5130 empty_dict = PyDict_New();
5131 if (!empty_dict)
5132 goto bad;
5133 module = PyObject_CallFunctionObjArgs(__import__,
5134 name, global_dict, empty_dict, list, NULL);
5135 bad:
5136 Py_XDECREF(empty_list);
5137 Py_XDECREF(__import__);
5138 Py_XDECREF(empty_dict);
5139 return module;
5141 """ % {
5142 "BUILTINS": Naming.builtins_cname,
5143 "GLOBALS": Naming.module_cname,
5144 })
5146 #------------------------------------------------------------------------------------
5148 get_exception_utility_code = UtilityCode(
5149 proto = """
5150 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5151 """,
5152 impl = """
5153 static PyObject *__Pyx_GetExcValue(void) {
5154 PyObject *type = 0, *value = 0, *tb = 0;
5155 PyObject *tmp_type, *tmp_value, *tmp_tb;
5156 PyObject *result = 0;
5157 PyThreadState *tstate = PyThreadState_Get();
5158 PyErr_Fetch(&type, &value, &tb);
5159 PyErr_NormalizeException(&type, &value, &tb);
5160 if (PyErr_Occurred())
5161 goto bad;
5162 if (!value) {
5163 value = Py_None;
5164 Py_INCREF(value);
5166 tmp_type = tstate->exc_type;
5167 tmp_value = tstate->exc_value;
5168 tmp_tb = tstate->exc_traceback;
5169 tstate->exc_type = type;
5170 tstate->exc_value = value;
5171 tstate->exc_traceback = tb;
5172 /* Make sure tstate is in a consistent state when we XDECREF
5173 these objects (XDECREF may run arbitrary code). */
5174 Py_XDECREF(tmp_type);
5175 Py_XDECREF(tmp_value);
5176 Py_XDECREF(tmp_tb);
5177 result = value;
5178 Py_XINCREF(result);
5179 type = 0;
5180 value = 0;
5181 tb = 0;
5182 bad:
5183 Py_XDECREF(type);
5184 Py_XDECREF(value);
5185 Py_XDECREF(tb);
5186 return result;
5188 """)
5190 #------------------------------------------------------------------------------------
5192 unpacking_utility_code = UtilityCode(
5193 proto = """
5194 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5195 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5196 """,
5197 impl = """
5198 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5199 PyObject *item;
5200 if (!(item = PyIter_Next(iter))) {
5201 if (!PyErr_Occurred()) {
5202 PyErr_Format(PyExc_ValueError,
5203 #if PY_VERSION_HEX < 0x02050000
5204 "need more than %d values to unpack", (int)index);
5205 #else
5206 "need more than %zd values to unpack", index);
5207 #endif
5210 return item;
5213 static int __Pyx_EndUnpack(PyObject *iter) {
5214 PyObject *item;
5215 if ((item = PyIter_Next(iter))) {
5216 Py_DECREF(item);
5217 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5218 return -1;
5220 else if (!PyErr_Occurred())
5221 return 0;
5222 else
5223 return -1;
5225 """)
5227 #------------------------------------------------------------------------------------
5229 type_test_utility_code = UtilityCode(
5230 proto = """
5231 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5232 """,
5233 impl = """
5234 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5235 if (!type) {
5236 PyErr_Format(PyExc_SystemError, "Missing type object");
5237 return 0;
5239 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5240 return 1;
5241 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5242 Py_TYPE(obj)->tp_name, type->tp_name);
5243 return 0;
5245 """)
5247 #------------------------------------------------------------------------------------
5249 create_class_utility_code = UtilityCode(
5250 proto = """
5251 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5252 """,
5253 impl = """
5254 static PyObject *__Pyx_CreateClass(
5255 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5257 PyObject *py_modname;
5258 PyObject *result = 0;
5260 #if PY_MAJOR_VERSION < 3
5261 py_modname = PyString_FromString(modname);
5262 #else
5263 py_modname = PyUnicode_FromString(modname);
5264 #endif
5265 if (!py_modname)
5266 goto bad;
5267 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5268 goto bad;
5269 #if PY_MAJOR_VERSION < 3
5270 result = PyClass_New(bases, dict, name);
5271 #else
5272 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5273 #endif
5274 bad:
5275 Py_XDECREF(py_modname);
5276 return result;
5278 """)
5280 #------------------------------------------------------------------------------------
5282 cpp_exception_utility_code = UtilityCode(
5283 proto = """
5284 #ifndef __Pyx_CppExn2PyErr
5285 static void __Pyx_CppExn2PyErr() {
5286 try {
5287 if (PyErr_Occurred())
5288 ; // let the latest Python exn pass through and ignore the current one
5289 else
5290 throw;
5291 } catch (const std::out_of_range& exn) {
5292 // catch out_of_range explicitly so the proper Python exn may be raised
5293 PyErr_SetString(PyExc_IndexError, exn.what());
5294 } catch (const std::exception& exn) {
5295 PyErr_SetString(PyExc_RuntimeError, exn.what());
5297 catch (...)
5299 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5302 #endif
5303 """,
5304 impl = ""
5307 #------------------------------------------------------------------------------------
5309 append_utility_code = UtilityCode(
5310 proto = """
5311 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5312 if (likely(PyList_CheckExact(L))) {
5313 if (PyList_Append(L, x) < 0) return NULL;
5314 Py_INCREF(Py_None);
5315 return Py_None; /* this is just to have an accurate signature */
5317 else {
5318 PyObject *r, *m;
5319 m = PyObject_GetAttrString(L, "append");
5320 if (!m) return NULL;
5321 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5322 Py_DECREF(m);
5323 return r;
5326 """,
5327 impl = ""
5330 #------------------------------------------------------------------------------------
5332 # If the is_unsigned flag is set, we need to do some extra work to make
5333 # sure the index doesn't become negative.
5335 getitem_int_utility_code = UtilityCode(
5336 proto = """
5337 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5338 PyObject *r;
5339 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5340 r = PyList_GET_ITEM(o, i);
5341 Py_INCREF(r);
5343 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
5344 r = PyTuple_GET_ITEM(o, i);
5345 Py_INCREF(r);
5347 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
5348 r = PySequence_GetItem(o, i);
5349 else {
5350 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);
5351 if (!j)
5352 return 0;
5353 r = PyObject_GetItem(o, j);
5354 Py_DECREF(j);
5356 return r;
5358 """,
5359 impl = """
5360 """)
5362 #------------------------------------------------------------------------------------
5364 setitem_int_utility_code = UtilityCode(
5365 proto = """
5366 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
5367 int r;
5368 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
5369 Py_DECREF(PyList_GET_ITEM(o, i));
5370 Py_INCREF(v);
5371 PyList_SET_ITEM(o, i, v);
5372 return 1;
5374 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5375 r = PySequence_SetItem(o, i, v);
5376 else {
5377 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);
5378 if (!j)
5379 return -1;
5380 r = PyObject_SetItem(o, j, v);
5381 Py_DECREF(j);
5383 return r;
5385 """,
5386 impl = """
5387 """)
5389 #------------------------------------------------------------------------------------
5391 delitem_int_utility_code = UtilityCode(
5392 proto = """
5393 static INLINE int __Pyx_DelItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
5394 int r;
5395 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
5396 r = PySequence_DelItem(o, i);
5397 else {
5398 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);
5399 if (!j)
5400 return -1;
5401 r = PyObject_DelItem(o, j);
5402 Py_DECREF(j);
5404 return r;
5406 """,
5407 impl = """
5408 """)
5410 #------------------------------------------------------------------------------------
5412 raise_noneattr_error_utility_code = UtilityCode(
5413 proto = """
5414 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5415 """,
5416 impl = """
5417 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5418 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5420 """)
5422 raise_noneindex_error_utility_code = UtilityCode(
5423 proto = """
5424 static INLINE void __Pyx_RaiseNoneIndexingError();
5425 """,
5426 impl = """
5427 static INLINE void __Pyx_RaiseNoneIndexingError() {
5428 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5430 """)