Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 1282:471a5c710a28

Ticket #60, compiler crash on bad array
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Oct 28 17:33:00 2008 -0700 (3 years ago)
parents cedb01d56181
children 1f1a398eda71
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
6 from string import join
8 from Errors import error, warning, InternalError
9 from Errors import hold_errors, release_errors, held_errors, report_error
10 from Cython.Utils import UtilityCode
11 import StringEncoding
12 import Naming
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
16 from Builtin import list_type, tuple_type, dict_type, unicode_type
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
26 class ExprNode(Node):
27 # subexprs [string] Class var holding names of subexpr node attrs
28 # type PyrexType Type of the result
29 # result_code string Code fragment
30 # result_ctype string C type of result_code if different from type
31 # is_temp boolean Result is in a temporary variable
32 # is_sequence_constructor
33 # boolean Is a list or tuple constructor expression
34 # saved_subexpr_nodes
35 # [ExprNode or [ExprNode or None] or None]
36 # Cached result of subexpr_nodes()
38 result_ctype = None
39 type = None
41 # The Analyse Expressions phase for expressions is split
42 # into two sub-phases:
43 #
44 # Analyse Types
45 # Determines the result type of the expression based
46 # on the types of its sub-expressions, and inserts
47 # coercion nodes into the expression tree where needed.
48 # Marks nodes which will need to have temporary variables
49 # allocated.
50 #
51 # Allocate Temps
52 # Allocates temporary variables where needed, and fills
53 # in the result_code field of each node.
54 #
55 # ExprNode provides some convenience routines which
56 # perform both of the above phases. These should only
57 # be called from statement nodes, and only when no
58 # coercion nodes need to be added around the expression
59 # being analysed. In that case, the above two phases
60 # should be invoked separately.
61 #
62 # Framework code in ExprNode provides much of the common
63 # processing for the various phases. It makes use of the
64 # 'subexprs' class attribute of ExprNodes, which should
65 # contain a list of the names of attributes which can
66 # hold sub-nodes or sequences of sub-nodes.
67 #
68 # The framework makes use of a number of abstract methods.
69 # Their responsibilities are as follows.
70 #
71 # Declaration Analysis phase
72 #
73 # analyse_target_declaration
74 # Called during the Analyse Declarations phase to analyse
75 # the LHS of an assignment or argument of a del statement.
76 # Nodes which cannot be the LHS of an assignment need not
77 # implement it.
78 #
79 # Expression Analysis phase
80 #
81 # analyse_types
82 # - Call analyse_types on all sub-expressions.
83 # - Check operand types, and wrap coercion nodes around
84 # sub-expressions where needed.
85 # - Set the type of this node.
86 # - If a temporary variable will be required for the
87 # result, set the is_temp flag of this node.
88 #
89 # analyse_target_types
90 # Called during the Analyse Types phase to analyse
91 # the LHS of an assignment or argument of a del
92 # statement. Similar responsibilities to analyse_types.
93 #
94 # allocate_temps
95 # - Call allocate_temps for all sub-nodes.
96 # - Call allocate_temp for this node.
97 # - If a temporary was allocated, call release_temp on
98 # all sub-expressions.
99 #
100 # allocate_target_temps
101 # - Call allocate_temps on sub-nodes and allocate any other
102 # temps used during assignment.
103 # - Fill in result_code with a C lvalue if needed.
104 # - If a rhs node is supplied, call release_temp on it.
105 # - Call release_temp on sub-nodes and release any other
106 # temps used during assignment.
107 #
108 # target_code
109 # Called by the default implementation of allocate_target_temps.
110 # Should return a C lvalue for assigning to the node. The default
111 # implementation calls calculate_result_code.
112 #
113 # check_const
114 # - Check that this node and its subnodes form a
115 # legal constant expression. If so, do nothing,
116 # otherwise call not_const.
117 #
118 # The default implementation of check_const
119 # assumes that the expression is not constant.
120 #
121 # check_const_addr
122 # - Same as check_const, except check that the
123 # expression is a C lvalue whose address is
124 # constant. Otherwise, call addr_not_const.
125 #
126 # The default implementation of calc_const_addr
127 # assumes that the expression is not a constant
128 # lvalue.
129 #
130 # Code Generation phase
131 #
132 # generate_evaluation_code
133 # - Call generate_evaluation_code for sub-expressions.
134 # - Perform the functions of generate_result_code
135 # (see below).
136 # - If result is temporary, call generate_disposal_code
137 # on all sub-expressions.
138 #
139 # A default implementation of generate_evaluation_code
140 # is provided which uses the following abstract methods:
141 #
142 # generate_result_code
143 # - Generate any C statements necessary to calculate
144 # the result of this node from the results of its
145 # sub-expressions.
146 #
147 # calculate_result_code
148 # - Should return a C code fragment evaluating to the
149 # result. This is only called when the result is not
150 # a temporary.
151 #
152 # generate_assignment_code
153 # Called on the LHS of an assignment.
154 # - Call generate_evaluation_code for sub-expressions.
155 # - Generate code to perform the assignment.
156 # - If the assignment absorbed a reference, call
157 # generate_post_assignment_code on the RHS,
158 # otherwise call generate_disposal_code on it.
159 #
160 # generate_deletion_code
161 # Called on an argument of a del statement.
162 # - Call generate_evaluation_code for sub-expressions.
163 # - Generate code to perform the deletion.
164 # - Call generate_disposal_code on all sub-expressions.
165 #
166 #
168 is_sequence_constructor = 0
169 is_attribute = 0
171 saved_subexpr_nodes = None
172 is_temp = 0
173 is_target = 0
175 def get_child_attrs(self):
176 return self.subexprs
177 child_attrs = property(fget=get_child_attrs)
179 def not_implemented(self, method_name):
180 print_call_chain(method_name, "not implemented") ###
181 raise InternalError(
182 "%s.%s not implemented" %
183 (self.__class__.__name__, method_name))
185 def is_lvalue(self):
186 return 0
188 def is_ephemeral(self):
189 # An ephemeral node is one whose result is in
190 # a Python temporary and we suspect there are no
191 # other references to it. Certain operations are
192 # disallowed on such values, since they are
193 # likely to result in a dangling pointer.
194 return self.type.is_pyobject and self.is_temp
196 def subexpr_nodes(self):
197 # Extract a list of subexpression nodes based
198 # on the contents of the subexprs class attribute.
199 if self.saved_subexpr_nodes is None:
200 nodes = []
201 for name in self.subexprs:
202 item = getattr(self, name)
203 if item:
204 if isinstance(item, ExprNode):
205 nodes.append(item)
206 else:
207 nodes.extend(item)
208 self.saved_subexpr_nodes = nodes
209 return self.saved_subexpr_nodes
211 def result(self):
212 if not self.is_temp or self.is_target:
213 return self.calculate_result_code()
214 else: # i.e. self.is_temp:
215 return self.result_code
217 def result_as(self, type = None):
218 # Return the result code cast to the specified C type.
219 return typecast(type, self.ctype(), self.result())
221 def py_result(self):
222 # Return the result code cast to PyObject *.
223 return self.result_as(py_object_type)
225 def ctype(self):
226 # Return the native C type of the result (i.e. the
227 # C type of the result_code expression).
228 return self.result_ctype or self.type
230 def compile_time_value(self, denv):
231 # Return value of compile-time expression, or report error.
232 error(self.pos, "Invalid compile-time expression")
234 def compile_time_value_error(self, e):
235 error(self.pos, "Error in compile-time expression: %s: %s" % (
236 e.__class__.__name__, e))
238 # ------------- Declaration Analysis ----------------
240 def analyse_target_declaration(self, env):
241 error(self.pos, "Cannot assign to or delete this")
243 # ------------- Expression Analysis ----------------
245 def analyse_const_expression(self, env):
246 # Called during the analyse_declarations phase of a
247 # constant expression. Analyses the expression's type,
248 # checks whether it is a legal const expression,
249 # and determines its value.
250 self.analyse_types(env)
251 self.allocate_temps(env)
252 self.check_const()
254 def analyse_expressions(self, env):
255 # Convenience routine performing both the Type
256 # Analysis and Temp Allocation phases for a whole
257 # expression.
258 self.analyse_types(env)
259 self.allocate_temps(env)
261 def analyse_target_expression(self, env, rhs):
262 # Convenience routine performing both the Type
263 # Analysis and Temp Allocation phases for the LHS of
264 # an assignment.
265 self.analyse_target_types(env)
266 self.allocate_target_temps(env, rhs)
268 def analyse_boolean_expression(self, env):
269 # Analyse expression and coerce to a boolean.
270 self.analyse_types(env)
271 bool = self.coerce_to_boolean(env)
272 bool.allocate_temps(env)
273 return bool
275 def analyse_temp_boolean_expression(self, env):
276 # Analyse boolean expression and coerce result into
277 # a temporary. This is used when a branch is to be
278 # performed on the result and we won't have an
279 # opportunity to ensure disposal code is executed
280 # afterwards. By forcing the result into a temporary,
281 # we ensure that all disposal has been done by the
282 # time we get the result.
283 self.analyse_types(env)
284 bool = self.coerce_to_boolean(env)
285 temp_bool = bool.coerce_to_temp(env)
286 temp_bool.allocate_temps(env)
287 return temp_bool
289 # --------------- Type Analysis ------------------
291 def analyse_as_module(self, env):
292 # If this node can be interpreted as a reference to a
293 # cimported module, return its scope, else None.
294 return None
296 def analyse_as_type(self, env):
297 # If this node can be interpreted as a reference to a
298 # type, return that type, else None.
299 return None
301 def analyse_as_extension_type(self, env):
302 # If this node can be interpreted as a reference to an
303 # extension type, return its type, else None.
304 return None
306 def analyse_types(self, env):
307 self.not_implemented("analyse_types")
309 def analyse_target_types(self, env):
310 self.analyse_types(env)
312 def gil_assignment_check(self, env):
313 if env.nogil and self.type.is_pyobject:
314 error(self.pos, "Assignment of Python object not allowed without gil")
316 def check_const(self):
317 self.not_const()
319 def not_const(self):
320 error(self.pos, "Not allowed in a constant expression")
322 def check_const_addr(self):
323 self.addr_not_const()
325 def addr_not_const(self):
326 error(self.pos, "Address is not constant")
328 def gil_check(self, env):
329 if env.nogil and self.type.is_pyobject:
330 self.gil_error()
332 # ----------------- Result Allocation -----------------
334 def result_in_temp(self):
335 # Return true if result is in a temporary owned by
336 # this node or one of its subexpressions. Overridden
337 # by certain nodes which can share the result of
338 # a subnode.
339 return self.is_temp
341 def allocate_target_temps(self, env, rhs):
342 # Perform temp allocation for the LHS of an assignment.
343 if debug_temp_alloc:
344 print("%s Allocating target temps" % self)
345 self.allocate_subexpr_temps(env)
346 self.is_target = True
347 if rhs:
348 rhs.release_temp(env)
349 self.release_subexpr_temps(env)
351 def allocate_temps(self, env, result = None):
352 # Allocate temporary variables for this node and
353 # all its sub-expressions. If a result is specified,
354 # this must be a temp node and the specified variable
355 # is used as the result instead of allocating a new
356 # one.
357 if debug_temp_alloc:
358 print("%s Allocating temps" % self)
359 self.allocate_subexpr_temps(env)
360 self.allocate_temp(env, result)
361 if self.is_temp:
362 self.release_subexpr_temps(env)
364 def allocate_subexpr_temps(self, env):
365 # Allocate temporary variables for all sub-expressions
366 # of this node.
367 if debug_temp_alloc:
368 print("%s Allocating temps for: %s" % (self, self.subexprs))
369 for node in self.subexpr_nodes():
370 if node:
371 if debug_temp_alloc:
372 print("%s Allocating temps for %s" % (self, node))
373 node.allocate_temps(env)
375 def allocate_temp(self, env, result = None):
376 # If this node requires a temporary variable for its
377 # result, allocate one, otherwise set the result to
378 # a C code fragment. If a result is specified,
379 # this must be a temp node and the specified variable
380 # is used as the result instead of allocating a new
381 # one.
382 if debug_temp_alloc:
383 print("%s Allocating temp" % self)
384 if result:
385 if not self.is_temp:
386 raise InternalError("Result forced on non-temp node")
387 self.result_code = result
388 elif self.is_temp:
389 type = self.type
390 if not type.is_void:
391 if type.is_pyobject:
392 type = PyrexTypes.py_object_type
393 self.result_code = env.allocate_temp(type)
394 else:
395 self.result_code = None
396 if debug_temp_alloc:
397 print("%s Allocated result %s" % (self, self.result_code))
399 def target_code(self):
400 # Return code fragment for use as LHS of a C assignment.
401 return self.calculate_result_code()
403 def calculate_result_code(self):
404 self.not_implemented("calculate_result_code")
406 # def release_target_temp(self, env):
407 # # Release temporaries used by LHS of an assignment.
408 # self.release_subexpr_temps(env)
410 def release_temp(self, env):
411 # If this node owns a temporary result, release it,
412 # otherwise release results of its sub-expressions.
413 if self.is_temp:
414 if debug_temp_alloc:
415 print("%s Releasing result %s" % (self, self.result_code))
416 env.release_temp(self.result_code)
417 else:
418 self.release_subexpr_temps(env)
420 def release_subexpr_temps(self, env):
421 # Release the results of all sub-expressions of
422 # this node.
423 for node in self.subexpr_nodes():
424 if node:
425 node.release_temp(env)
427 # ---------------- Code Generation -----------------
429 def make_owned_reference(self, code):
430 # If result is a pyobject, make sure we own
431 # a reference to it.
432 if self.type.is_pyobject and not self.result_in_temp():
433 code.put_incref(self.result(), self.ctype())
435 def generate_evaluation_code(self, code):
436 code.mark_pos(self.pos)
437 # Generate code to evaluate this node and
438 # its sub-expressions, and dispose of any
439 # temporary results of its sub-expressions.
440 self.generate_subexpr_evaluation_code(code)
441 self.pre_generate_result_code(code)
442 self.generate_result_code(code)
443 if self.is_temp:
444 self.generate_subexpr_disposal_code(code)
446 def pre_generate_result_code(self, code):
447 pass
449 def generate_subexpr_evaluation_code(self, code):
450 for node in self.subexpr_nodes():
451 node.generate_evaluation_code(code)
453 def generate_result_code(self, code):
454 self.not_implemented("generate_result_code")
456 def generate_disposal_code(self, code):
457 # If necessary, generate code to dispose of
458 # temporary Python reference.
459 if self.is_temp:
460 if self.type.is_pyobject:
461 code.put_decref_clear(self.result(), self.ctype())
462 else:
463 self.generate_subexpr_disposal_code(code)
465 def generate_subexpr_disposal_code(self, code):
466 # Generate code to dispose of temporary results
467 # of all sub-expressions.
468 for node in self.subexpr_nodes():
469 node.generate_disposal_code(code)
471 def generate_post_assignment_code(self, code):
472 # Same as generate_disposal_code except that
473 # assignment will have absorbed a reference to
474 # the result if it is a Python object.
475 if self.is_temp:
476 if self.type.is_pyobject:
477 code.putln("%s = 0;" % self.result())
478 else:
479 self.generate_subexpr_disposal_code(code)
481 def generate_assignment_code(self, rhs, code):
482 # Stub method for nodes which are not legal as
483 # the LHS of an assignment. An error will have
484 # been reported earlier.
485 pass
487 def generate_deletion_code(self, code):
488 # Stub method for nodes that are not legal as
489 # the argument of a del statement. An error
490 # will have been reported earlier.
491 pass
493 # ---------------- Annotation ---------------------
495 def annotate(self, code):
496 for node in self.subexpr_nodes():
497 node.annotate(code)
499 # ----------------- Coercion ----------------------
501 def coerce_to(self, dst_type, env):
502 # Coerce the result so that it can be assigned to
503 # something of type dst_type. If processing is necessary,
504 # wraps this node in a coercion node and returns that.
505 # Otherwise, returns this node unchanged.
506 #
507 # This method is called during the analyse_expressions
508 # phase of the src_node's processing.
509 src = self
510 src_type = self.type
511 src_is_py_type = src_type.is_pyobject
512 dst_is_py_type = dst_type.is_pyobject
514 if dst_type.is_pyobject:
515 if not src.type.is_pyobject:
516 src = CoerceToPyTypeNode(src, env)
517 if not src.type.subtype_of(dst_type):
518 if not isinstance(src, NoneNode):
519 src = PyTypeTestNode(src, dst_type, env)
520 elif src.type.is_pyobject:
521 src = CoerceFromPyTypeNode(dst_type, src, env)
522 else: # neither src nor dst are py types
523 # Added the string comparison, since for c types that
524 # is enough, but Cython gets confused when the types are
525 # in different files.
526 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
527 error(self.pos, "Cannot assign type '%s' to '%s'" %
528 (src.type, dst_type))
529 return src
531 def coerce_to_pyobject(self, env):
532 return self.coerce_to(PyrexTypes.py_object_type, env)
534 def coerce_to_boolean(self, env):
535 # Coerce result to something acceptable as
536 # a boolean value.
537 type = self.type
538 if type.is_pyobject or type.is_ptr or type.is_float:
539 return CoerceToBooleanNode(self, env)
540 else:
541 if not type.is_int and not type.is_error:
542 error(self.pos,
543 "Type '%s' not acceptable as a boolean" % type)
544 return self
546 def coerce_to_integer(self, env):
547 # If not already some C integer type, coerce to longint.
548 if self.type.is_int:
549 return self
550 else:
551 return self.coerce_to(PyrexTypes.c_long_type, env)
553 def coerce_to_temp(self, env):
554 # Ensure that the result is in a temporary.
555 if self.result_in_temp():
556 return self
557 else:
558 return CoerceToTempNode(self, env)
560 def coerce_to_simple(self, env):
561 # Ensure that the result is simple (see is_simple).
562 if self.is_simple():
563 return self
564 else:
565 return self.coerce_to_temp(env)
567 def is_simple(self):
568 # A node is simple if its result is something that can
569 # be referred to without performing any operations, e.g.
570 # a constant, local var, C global var, struct member
571 # reference, or temporary.
572 return self.result_in_temp()
574 def as_cython_attribute(self):
575 return None
578 class NewTempExprNode(ExprNode):
579 backwards_compatible_result = None
581 def result(self):
582 if self.is_temp:
583 return self.temp_code
584 else:
585 return self.calculate_result_code()
587 def allocate_target_temps(self, env, rhs):
588 self.allocate_subexpr_temps(env)
589 rhs.release_temp(rhs)
590 self.release_subexpr_temps(env)
592 def allocate_temps(self, env, result = None):
593 self.allocate_subexpr_temps(env)
594 self.backwards_compatible_result = result
595 if self.is_temp:
596 self.release_subexpr_temps(env)
598 def allocate_temp(self, env, result = None):
599 assert result is None
601 def release_temp(self, env):
602 pass
604 def pre_generate_result_code(self, code):
605 if self.is_temp:
606 type = self.type
607 if not type.is_void:
608 if type.is_pyobject:
609 type = PyrexTypes.py_object_type
610 if self.backwards_compatible_result:
611 self.temp_code = self.backwards_compatible_result
612 else:
613 self.temp_code = code.funcstate.allocate_temp(type)
614 else:
615 self.temp_code = None
617 def generate_disposal_code(self, code):
618 if self.is_temp:
619 if self.type.is_pyobject:
620 code.put_decref_clear(self.result(), self.ctype())
621 if not self.backwards_compatible_result:
622 code.funcstate.release_temp(self.temp_code)
623 else:
624 self.generate_subexpr_disposal_code(code)
626 def generate_post_assignment_code(self, code):
627 if self.is_temp:
628 if self.type.is_pyobject:
629 code.putln("%s = 0;" % self.temp_code)
630 if not self.backwards_compatible_result:
631 code.funcstate.release_temp(self.temp_code)
632 else:
633 self.generate_subexpr_disposal_code(code)
638 class AtomicExprNode(ExprNode):
639 # Abstract base class for expression nodes which have
640 # no sub-expressions.
642 subexprs = []
645 class PyConstNode(AtomicExprNode):
646 # Abstract base class for constant Python values.
648 is_literal = 1
650 def is_simple(self):
651 return 1
653 def analyse_types(self, env):
654 self.type = py_object_type
656 def calculate_result_code(self):
657 return self.value
659 def generate_result_code(self, code):
660 pass
663 class NoneNode(PyConstNode):
664 # The constant value None
666 value = "Py_None"
668 def compile_time_value(self, denv):
669 return None
671 class EllipsisNode(PyConstNode):
672 # '...' in a subscript list.
674 value = "Py_Ellipsis"
676 def compile_time_value(self, denv):
677 return Ellipsis
680 class ConstNode(AtomicExprNode):
681 # Abstract base type for literal constant nodes.
682 #
683 # value string C code fragment
685 is_literal = 1
687 def is_simple(self):
688 return 1
690 def analyse_types(self, env):
691 pass # Types are held in class variables
693 def check_const(self):
694 pass
696 def calculate_result_code(self):
697 return str(self.value)
699 def generate_result_code(self, code):
700 pass
703 class BoolNode(ConstNode):
704 type = PyrexTypes.c_bint_type
705 # The constant value True or False
707 def compile_time_value(self, denv):
708 return self.value
710 def calculate_result_code(self):
711 return str(int(self.value))
713 class NullNode(ConstNode):
714 type = PyrexTypes.c_null_ptr_type
715 value = "NULL"
718 class CharNode(ConstNode):
719 type = PyrexTypes.c_char_type
721 def compile_time_value(self, denv):
722 return ord(self.value)
724 def calculate_result_code(self):
725 return "'%s'" % StringEncoding.escape_character(self.value)
728 class IntNode(ConstNode):
730 # unsigned "" or "U"
731 # longness "" or "L" or "LL"
733 unsigned = ""
734 longness = ""
735 type = PyrexTypes.c_long_type
737 def coerce_to(self, dst_type, env):
738 if dst_type.is_numeric:
739 self.type = PyrexTypes.c_long_type
740 return self
741 # Arrange for a Python version of the number to be pre-allocated
742 # when coercing to a Python type.
743 if dst_type.is_pyobject:
744 self.entry = env.get_py_num(self.value, self.longness)
745 self.type = PyrexTypes.py_object_type
746 # We still need to perform normal coerce_to processing on the
747 # result, because we might be coercing to an extension type,
748 # in which case a type test node will be needed.
749 return ConstNode.coerce_to(self, dst_type, env)
751 def coerce_to_boolean(self, env):
752 self.type = PyrexTypes.c_bint_type
753 return self
755 def calculate_result_code(self):
756 if self.type.is_pyobject:
757 return self.entry.cname
758 else:
759 return str(self.value) + self.unsigned + self.longness
761 def compile_time_value(self, denv):
762 return int(self.value, 0)
765 class FloatNode(ConstNode):
766 type = PyrexTypes.c_double_type
768 def compile_time_value(self, denv):
769 return float(self.value)
771 def calculate_result_code(self):
772 strval = str(self.value)
773 if strval == 'nan':
774 return "(Py_HUGE_VAL * 0)"
775 elif strval == 'inf':
776 return "Py_HUGE_VAL"
777 elif strval == '-inf':
778 return "(-Py_HUGE_VAL)"
779 else:
780 return strval
783 class StringNode(ConstNode):
784 # entry Symtab.Entry
786 type = PyrexTypes.c_char_ptr_type
788 def compile_time_value(self, denv):
789 return self.value
791 def analyse_types(self, env):
792 self.entry = env.add_string_const(self.value)
794 def analyse_as_type(self, env):
795 type = PyrexTypes.parse_basic_type(self.value)
796 if type is not None:
797 return type
798 from TreeFragment import TreeFragment
799 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
800 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
801 sizeof_node = declaration.root.stats[0].expr
802 sizeof_node.analyse_types(env)
803 if isinstance(sizeof_node, SizeofTypeNode):
804 return sizeof_node.arg_type
806 def coerce_to(self, dst_type, env):
807 if dst_type == PyrexTypes.c_char_ptr_type:
808 self.type = PyrexTypes.c_char_ptr_type
809 return self
811 if dst_type.is_int:
812 if not self.type.is_pyobject and len(self.entry.init) == 1:
813 return CharNode(self.pos, value=self.value)
814 else:
815 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
816 return self
817 # Arrange for a Python version of the string to be pre-allocated
818 # when coercing to a Python type.
819 if dst_type.is_pyobject and not self.type.is_pyobject:
820 node = self.as_py_string_node(env)
821 else:
822 node = self
823 # We still need to perform normal coerce_to processing on the
824 # result, because we might be coercing to an extension type,
825 # in which case a type test node will be needed.
826 return ConstNode.coerce_to(node, dst_type, env)
828 def as_py_string_node(self, env):
829 # Return a new StringNode with the same entry as this node
830 # but whose type is a Python type instead of a C type.
831 entry = self.entry
832 env.add_py_string(entry)
833 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
835 def calculate_result_code(self):
836 if self.type.is_pyobject:
837 return self.entry.pystring_cname
838 else:
839 return self.entry.cname
842 class UnicodeNode(PyConstNode):
843 # entry Symtab.Entry
845 type = unicode_type
847 def analyse_types(self, env):
848 self.entry = env.add_string_const(self.value)
849 env.add_py_string(self.entry)
851 def calculate_result_code(self):
852 return self.entry.pystring_cname
854 def _coerce_to(self, dst_type, env):
855 if not dst_type.is_pyobject:
856 node = StringNode(self.pos, entry = entry, type = py_object_type)
857 return ConstNode.coerce_to(node, dst_type, env)
858 else:
859 return self
860 # We still need to perform normal coerce_to processing on the
861 # result, because we might be coercing to an extension type,
862 # in which case a type test node will be needed.
864 def compile_time_value(self, env):
865 return self.value
868 class IdentifierStringNode(ConstNode):
869 # A Python string that behaves like an identifier, e.g. for
870 # keyword arguments in a call, or for imported names
871 type = PyrexTypes.py_object_type
873 def analyse_types(self, env):
874 self.cname = env.intern_identifier(self.value)
876 def calculate_result_code(self):
877 return self.cname
880 class LongNode(AtomicExprNode):
881 # Python long integer literal
882 #
883 # value string
885 def compile_time_value(self, denv):
886 return long(self.value)
888 gil_message = "Constructing Python long int"
890 def analyse_types(self, env):
891 self.type = py_object_type
892 self.gil_check(env)
893 self.is_temp = 1
895 gil_message = "Constructing Python long int"
897 def generate_evaluation_code(self, code):
898 code.putln(
899 '%s = PyLong_FromString("%s", 0, 0); %s' % (
900 self.result(),
901 self.value,
902 code.error_goto_if_null(self.result(), self.pos)))
905 class ImagNode(AtomicExprNode):
906 # Imaginary number literal
907 #
908 # value float imaginary part
910 def compile_time_value(self, denv):
911 return complex(0.0, self.value)
913 def analyse_types(self, env):
914 self.type = py_object_type
915 self.gil_check(env)
916 self.is_temp = 1
918 gil_message = "Constructing complex number"
920 def generate_evaluation_code(self, code):
921 code.putln(
922 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
923 self.result(),
924 self.value,
925 code.error_goto_if_null(self.result(), self.pos)))
928 class NameNode(AtomicExprNode):
929 # Reference to a local or global variable name.
930 #
931 # name string Python name of the variable
932 #
933 # entry Entry Symbol table entry
934 # interned_cname string
936 is_name = True
937 is_cython_module = False
938 cython_attribute = None
939 lhs_of_first_assignment = False
940 entry = None
942 def create_analysed_rvalue(pos, env, entry):
943 node = NameNode(pos)
944 node.analyse_types(env, entry=entry)
945 return node
947 def as_cython_attribute(self):
948 return self.cython_attribute
950 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
952 def compile_time_value(self, denv):
953 try:
954 return denv.lookup(self.name)
955 except KeyError:
956 error(self.pos, "Compile-time name '%s' not defined" % self.name)
958 def coerce_to(self, dst_type, env):
959 # If coercing to a generic pyobject and this is a builtin
960 # C function with a Python equivalent, manufacture a NameNode
961 # referring to the Python builtin.
962 #print "NameNode.coerce_to:", self.name, dst_type ###
963 if dst_type is py_object_type:
964 entry = self.entry
965 if entry and entry.is_cfunction:
966 var_entry = entry.as_variable
967 if var_entry:
968 if var_entry.is_builtin and Options.cache_builtins:
969 var_entry = env.declare_builtin(var_entry.name, self.pos)
970 node = NameNode(self.pos, name = self.name)
971 node.entry = var_entry
972 node.analyse_rvalue_entry(env)
973 return node
974 return AtomicExprNode.coerce_to(self, dst_type, env)
976 def analyse_as_module(self, env):
977 # Try to interpret this as a reference to a cimported module.
978 # Returns the module scope, or None.
979 entry = self.entry
980 if not entry:
981 entry = env.lookup(self.name)
982 if entry and entry.as_module:
983 return entry.as_module
984 return None
986 def analyse_as_type(self, env):
987 if self.cython_attribute:
988 type = PyrexTypes.parse_basic_type(self.cython_attribute)
989 else:
990 type = PyrexTypes.parse_basic_type(self.name)
991 if type:
992 return type
993 entry = self.entry
994 if not entry:
995 entry = env.lookup(self.name)
996 if entry and entry.is_type:
997 return entry.type
998 else:
999 return None
1001 def analyse_as_extension_type(self, env):
1002 # Try to interpret this as a reference to an extension type.
1003 # Returns the extension type, or None.
1004 entry = self.entry
1005 if not entry:
1006 entry = env.lookup(self.name)
1007 if entry and entry.is_type and entry.type.is_extension_type:
1008 return entry.type
1009 else:
1010 return None
1012 def analyse_target_declaration(self, env):
1013 if not self.entry:
1014 self.entry = env.lookup_here(self.name)
1015 if not self.entry:
1016 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1017 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1018 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1019 if self.entry.is_declared_generic:
1020 self.result_ctype = py_object_type
1022 def analyse_types(self, env):
1023 if self.entry is None:
1024 self.entry = env.lookup(self.name)
1025 if not self.entry:
1026 self.entry = env.declare_builtin(self.name, self.pos)
1027 if not self.entry:
1028 self.type = PyrexTypes.error_type
1029 return
1030 self.analyse_rvalue_entry(env)
1032 def analyse_target_types(self, env):
1033 self.analyse_entry(env)
1034 if not self.is_lvalue():
1035 error(self.pos, "Assignment to non-lvalue '%s'"
1036 % self.name)
1037 self.type = PyrexTypes.error_type
1038 self.entry.used = 1
1039 if self.entry.type.is_buffer:
1040 import Buffer
1041 Buffer.used_buffer_aux_vars(self.entry)
1043 def analyse_rvalue_entry(self, env):
1044 #print "NameNode.analyse_rvalue_entry:", self.name ###
1045 #print "Entry:", self.entry.__dict__ ###
1046 self.analyse_entry(env)
1047 entry = self.entry
1048 if entry.is_declared_generic:
1049 self.result_ctype = py_object_type
1050 if entry.is_pyglobal or entry.is_builtin:
1051 if Options.cache_builtins and entry.is_builtin:
1052 self.is_temp = 0
1053 else:
1054 self.is_temp = 1
1055 env.use_utility_code(get_name_interned_utility_code)
1056 self.gil_check(env)
1058 gil_message = "Accessing Python global or builtin"
1060 def analyse_entry(self, env):
1061 #print "NameNode.analyse_entry:", self.name ###
1062 self.check_identifier_kind()
1063 entry = self.entry
1064 type = entry.type
1065 self.type = type
1066 if entry.is_pyglobal or entry.is_builtin:
1067 assert type.is_pyobject, "Python global or builtin not a Python object"
1068 self.interned_cname = self.entry.interned_cname = \
1069 env.intern_identifier(self.entry.name)
1071 def check_identifier_kind(self):
1072 #print "NameNode.check_identifier_kind:", self.entry.name ###
1073 #print self.entry.__dict__ ###
1074 entry = self.entry
1075 #entry.used = 1
1076 if not (entry.is_const or entry.is_variable
1077 or entry.is_builtin or entry.is_cfunction):
1078 if self.entry.as_variable:
1079 self.entry = self.entry.as_variable
1080 else:
1081 error(self.pos,
1082 "'%s' is not a constant, variable or function identifier" % self.name)
1084 def is_simple(self):
1085 # If it's not a C variable, it'll be in a temp.
1086 return 1
1088 def calculate_target_results(self, env):
1089 pass
1091 def check_const(self):
1092 entry = self.entry
1093 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1094 self.not_const()
1096 def check_const_addr(self):
1097 entry = self.entry
1098 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1099 self.addr_not_const()
1101 def is_lvalue(self):
1102 return self.entry.is_variable and \
1103 not self.entry.type.is_array and \
1104 not self.entry.is_readonly
1106 def is_ephemeral(self):
1107 # Name nodes are never ephemeral, even if the
1108 # result is in a temporary.
1109 return 0
1111 def allocate_temp(self, env, result = None):
1112 AtomicExprNode.allocate_temp(self, env, result)
1113 entry = self.entry
1114 if entry:
1115 entry.used = 1
1116 if entry.type.is_buffer:
1117 import Buffer
1118 Buffer.used_buffer_aux_vars(entry)
1119 if entry.utility_code:
1120 env.use_utility_code(entry.utility_code)
1122 def calculate_result_code(self):
1123 entry = self.entry
1124 if not entry:
1125 return "<error>" # There was an error earlier
1126 return entry.cname
1128 def generate_result_code(self, code):
1129 assert hasattr(self, 'entry')
1130 entry = self.entry
1131 if entry is None:
1132 return # There was an error earlier
1133 if entry.is_builtin and Options.cache_builtins:
1134 return # Lookup already cached
1135 elif entry.is_pyglobal or entry.is_builtin:
1136 if entry.is_builtin:
1137 namespace = Naming.builtins_cname
1138 else: # entry.is_pyglobal
1139 namespace = entry.scope.namespace_cname
1140 code.putln(
1141 '%s = __Pyx_GetName(%s, %s); %s' % (
1142 self.result(),
1143 namespace,
1144 self.interned_cname,
1145 code.error_goto_if_null(self.result(), self.pos)))
1146 elif entry.is_local and False:
1147 # control flow not good enough yet
1148 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1149 if assigned is False:
1150 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1151 elif not Options.init_local_none and assigned is None:
1152 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1153 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1155 def generate_assignment_code(self, rhs, code):
1156 #print "NameNode.generate_assignment_code:", self.name ###
1157 entry = self.entry
1158 if entry is None:
1159 return # There was an error earlier
1161 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1162 and not self.lhs_of_first_assignment):
1163 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1165 # is_pyglobal seems to be True for module level-globals only.
1166 # We use this to access class->tp_dict if necessary.
1167 if entry.is_pyglobal:
1168 namespace = self.entry.scope.namespace_cname
1169 if entry.is_member:
1170 # if the entry is a member we have to cheat: SetAttr does not work
1171 # on types, so we create a descriptor which is then added to tp_dict
1172 code.put_error_if_neg(self.pos,
1173 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1174 namespace,
1175 self.interned_cname,
1176 rhs.py_result()))
1177 # in Py2.6+, we need to invalidate the method cache
1178 code.putln("PyType_Modified(%s);" %
1179 entry.scope.parent_type.typeptr_cname)
1180 else:
1181 code.put_error_if_neg(self.pos,
1182 'PyObject_SetAttr(%s, %s, %s)' % (
1183 namespace,
1184 self.interned_cname,
1185 rhs.py_result()))
1186 if debug_disposal_code:
1187 print("NameNode.generate_assignment_code:")
1188 print("...generating disposal code for %s" % rhs)
1189 rhs.generate_disposal_code(code)
1191 else:
1192 if self.type.is_buffer:
1193 # Generate code for doing the buffer release/acquisition.
1194 # This might raise an exception in which case the assignment (done
1195 # below) will not happen.
1197 # The reason this is not in a typetest-like node is because the
1198 # variables that the acquired buffer info is stored to is allocated
1199 # per entry and coupled with it.
1200 self.generate_acquire_buffer(rhs, code)
1202 if self.type.is_pyobject:
1203 rhs.make_owned_reference(code)
1204 #print "NameNode.generate_assignment_code: to", self.name ###
1205 #print "...from", rhs ###
1206 #print "...LHS type", self.type, "ctype", self.ctype() ###
1207 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1208 if not self.lhs_of_first_assignment:
1209 if entry.is_local and not Options.init_local_none:
1210 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1211 if initalized is True:
1212 code.put_decref(self.result(), self.ctype())
1213 elif initalized is None:
1214 code.put_xdecref(self.result(), self.ctype())
1215 else:
1216 code.put_decref(self.result(), self.ctype())
1217 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1218 if debug_disposal_code:
1219 print("NameNode.generate_assignment_code:")
1220 print("...generating post-assignment code for %s" % rhs)
1221 rhs.generate_post_assignment_code(code)
1223 def generate_acquire_buffer(self, rhs, code):
1224 rhstmp = code.funcstate.allocate_temp(self.entry.type)
1225 buffer_aux = self.entry.buffer_aux
1226 bufstruct = buffer_aux.buffer_info_var.cname
1227 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1229 import Buffer
1230 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1231 is_initialized=not self.lhs_of_first_assignment,
1232 pos=self.pos, code=code)
1233 code.putln("%s = 0;" % rhstmp)
1234 code.funcstate.release_temp(rhstmp)
1236 def generate_deletion_code(self, code):
1237 if self.entry is None:
1238 return # There was an error earlier
1239 if not self.entry.is_pyglobal:
1240 error(self.pos, "Deletion of local or C global name not supported")
1241 return
1242 code.put_error_if_neg(self.pos,
1243 'PyObject_DelAttrString(%s, "%s")' % (
1244 Naming.module_cname,
1245 self.entry.name))
1247 def annotate(self, code):
1248 if hasattr(self, 'is_called') and self.is_called:
1249 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1250 if self.type.is_pyobject:
1251 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1252 else:
1253 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1255 class BackquoteNode(ExprNode):
1256 # `expr`
1258 # arg ExprNode
1260 subexprs = ['arg']
1262 def analyse_types(self, env):
1263 self.arg.analyse_types(env)
1264 self.arg = self.arg.coerce_to_pyobject(env)
1265 self.type = py_object_type
1266 self.gil_check(env)
1267 self.is_temp = 1
1269 gil_message = "Backquote expression"
1271 def generate_result_code(self, code):
1272 code.putln(
1273 "%s = PyObject_Repr(%s); %s" % (
1274 self.result(),
1275 self.arg.py_result(),
1276 code.error_goto_if_null(self.result(), self.pos)))
1279 class ImportNode(ExprNode):
1280 # Used as part of import statement implementation.
1281 # Implements result =
1282 # __import__(module_name, globals(), None, name_list)
1284 # module_name IdentifierStringNode dotted name of module
1285 # name_list ListNode or None list of names to be imported
1287 subexprs = ['module_name', 'name_list']
1289 def analyse_types(self, env):
1290 self.module_name.analyse_types(env)
1291 self.module_name = self.module_name.coerce_to_pyobject(env)
1292 if self.name_list:
1293 self.name_list.analyse_types(env)
1294 self.name_list.coerce_to_pyobject(env)
1295 self.type = py_object_type
1296 self.gil_check(env)
1297 self.is_temp = 1
1298 env.use_utility_code(import_utility_code)
1300 gil_message = "Python import"
1302 def generate_result_code(self, code):
1303 if self.name_list:
1304 name_list_code = self.name_list.py_result()
1305 else:
1306 name_list_code = "0"
1307 code.putln(
1308 "%s = __Pyx_Import(%s, %s); %s" % (
1309 self.result(),
1310 self.module_name.py_result(),
1311 name_list_code,
1312 code.error_goto_if_null(self.result(), self.pos)))
1315 class IteratorNode(ExprNode):
1316 # Used as part of for statement implementation.
1317 # Implements result = iter(sequence)
1319 # sequence ExprNode
1321 subexprs = ['sequence']
1323 def analyse_types(self, env):
1324 self.sequence.analyse_types(env)
1325 self.sequence = self.sequence.coerce_to_pyobject(env)
1326 self.type = py_object_type
1327 self.gil_check(env)
1328 self.is_temp = 1
1330 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1331 self.counter.allocate_temp(env)
1333 gil_message = "Iterating over Python object"
1335 def release_temp(self, env):
1336 env.release_temp(self.result())
1337 self.counter.release_temp(env)
1339 def generate_result_code(self, code):
1340 code.putln(
1341 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1342 self.sequence.py_result(),
1343 self.sequence.py_result()))
1344 code.putln(
1345 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1346 self.counter.result(),
1347 self.result(),
1348 self.sequence.py_result(),
1349 self.result()))
1350 code.putln("} else {")
1351 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1352 self.counter.result(),
1353 self.result(),
1354 self.sequence.py_result(),
1355 code.error_goto_if_null(self.result(), self.pos)))
1356 code.putln("}")
1359 class NextNode(AtomicExprNode):
1360 # Used as part of for statement implementation.
1361 # Implements result = iterator.next()
1362 # Created during analyse_types phase.
1363 # The iterator is not owned by this node.
1365 # iterator ExprNode
1367 def __init__(self, iterator, env):
1368 self.pos = iterator.pos
1369 self.iterator = iterator
1370 self.type = py_object_type
1371 self.is_temp = 1
1373 def generate_result_code(self, code):
1374 for py_type in ["List", "Tuple"]:
1375 code.putln(
1376 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1377 code.putln(
1378 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1379 self.iterator.counter.result(),
1380 py_type,
1381 self.iterator.py_result()))
1382 code.putln(
1383 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1384 self.result(),
1385 py_type,
1386 self.iterator.py_result(),
1387 self.iterator.counter.result(),
1388 self.result(),
1389 self.iterator.counter.result()))
1390 code.put("} else ")
1391 code.putln("{")
1392 code.putln(
1393 "%s = PyIter_Next(%s);" % (
1394 self.result(),
1395 self.iterator.py_result()))
1396 code.putln(
1397 "if (!%s) {" %
1398 self.result())
1399 code.putln(code.error_goto_if_PyErr(self.pos))
1400 code.putln("break;")
1401 code.putln("}")
1402 code.putln("}")
1405 class ExcValueNode(AtomicExprNode):
1406 # Node created during analyse_types phase
1407 # of an ExceptClauseNode to fetch the current
1408 # exception value.
1410 def __init__(self, pos, env, var):
1411 ExprNode.__init__(self, pos)
1412 self.type = py_object_type
1413 self.var = var
1415 def calculate_result_code(self):
1416 return self.var
1418 def generate_result_code(self, code):
1419 pass
1421 def analyse_types(self, env):
1422 pass
1425 class TempNode(AtomicExprNode):
1426 # Node created during analyse_types phase
1427 # of some nodes to hold a temporary value.
1429 def __init__(self, pos, type, env):
1430 ExprNode.__init__(self, pos)
1431 self.type = type
1432 if type.is_pyobject:
1433 self.result_ctype = py_object_type
1434 self.is_temp = 1
1436 def analyse_types(self, env):
1437 return self.type
1439 def generate_result_code(self, code):
1440 pass
1443 class PyTempNode(TempNode):
1444 # TempNode holding a Python value.
1446 def __init__(self, pos, env):
1447 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1450 #-------------------------------------------------------------------
1452 # Trailer nodes
1454 #-------------------------------------------------------------------
1456 class IndexNode(ExprNode):
1457 # Sequence indexing.
1459 # base ExprNode
1460 # index ExprNode
1461 # indices [ExprNode]
1462 # is_buffer_access boolean Whether this is a buffer access.
1464 # indices is used on buffer access, index on non-buffer access.
1465 # The former contains a clean list of index parameters, the
1466 # latter whatever Python object is needed for index access.
1468 subexprs = ['base', 'index', 'indices']
1469 indices = None
1471 def __init__(self, pos, index, *args, **kw):
1472 ExprNode.__init__(self, pos, index=index, *args, **kw)
1473 self._index = index
1475 def compile_time_value(self, denv):
1476 base = self.base.compile_time_value(denv)
1477 index = self.index.compile_time_value(denv)
1478 try:
1479 return base[index]
1480 except Exception, e:
1481 self.compile_time_value_error(e)
1483 def is_ephemeral(self):
1484 return self.base.is_ephemeral()
1486 def analyse_target_declaration(self, env):
1487 pass
1489 def analyse_as_type(self, env):
1490 base_type = self.base.analyse_as_type(env)
1491 if base_type and not base_type.is_pyobject:
1492 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1493 return None
1495 def analyse_types(self, env):
1496 self.analyse_base_and_index_types(env, getting = 1)
1498 def analyse_target_types(self, env):
1499 self.analyse_base_and_index_types(env, setting = 1)
1501 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1502 # Note: This might be cleaned up by having IndexNode
1503 # parsed in a saner way and only construct the tuple if
1504 # needed.
1506 # Note that this function must leave IndexNode in a cloneable state.
1507 # For buffers, self.index is packed out on the initial analysis, and
1508 # when cloning self.indices is copied.
1509 self.is_buffer_access = False
1511 self.base.analyse_types(env)
1512 # Handle the case where base is a literal char* (and we expect a string, not an int)
1513 if isinstance(self.base, StringNode):
1514 self.base = self.base.coerce_to_pyobject(env)
1516 skip_child_analysis = False
1517 buffer_access = False
1518 if self.base.type.is_buffer:
1519 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1520 if self.indices:
1521 indices = self.indices
1522 else:
1523 # On cloning, indices is cloned. Otherwise, unpack index into indices
1524 assert not isinstance(self.index, CloneNode)
1525 if isinstance(self.index, TupleNode):
1526 indices = self.index.args
1527 else:
1528 indices = [self.index]
1529 if len(indices) == self.base.type.ndim:
1530 buffer_access = True
1531 skip_child_analysis = True
1532 for x in indices:
1533 x.analyse_types(env)
1534 if not x.type.is_int:
1535 buffer_access = False
1537 if buffer_access:
1538 self.indices = indices
1539 self.index = None
1540 self.type = self.base.type.dtype
1541 self.is_buffer_access = True
1542 self.buffer_type = self.base.entry.type
1544 if getting and self.type.is_pyobject:
1545 self.is_temp = True
1546 if setting:
1547 if not self.base.entry.type.writable:
1548 error(self.pos, "Writing to readonly buffer")
1549 else:
1550 self.base.entry.buffer_aux.writable_needed = True
1551 else:
1552 if isinstance(self.index, TupleNode):
1553 self.index.analyse_types(env, skip_children=skip_child_analysis)
1554 elif not skip_child_analysis:
1555 self.index.analyse_types(env)
1556 self.original_index_type = self.index.type
1557 if self.base.type.is_pyobject:
1558 if self.index.type.is_int and not self.index.type.is_longlong:
1559 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1560 else:
1561 self.index = self.index.coerce_to_pyobject(env)
1562 self.type = py_object_type
1563 self.gil_check(env)
1564 self.is_temp = 1
1565 else:
1566 if self.base.type.is_ptr or self.base.type.is_array:
1567 self.type = self.base.type.base_type
1568 else:
1569 error(self.pos,
1570 "Attempting to index non-array type '%s'" %
1571 self.base.type)
1572 self.type = PyrexTypes.error_type
1573 if self.index.type.is_pyobject:
1574 self.index = self.index.coerce_to(
1575 PyrexTypes.c_py_ssize_t_type, env)
1576 if not self.index.type.is_int:
1577 error(self.pos,
1578 "Invalid index type '%s'" %
1579 self.index.type)
1581 gil_message = "Indexing Python object"
1583 def check_const_addr(self):
1584 self.base.check_const_addr()
1585 self.index.check_const()
1587 def is_lvalue(self):
1588 return 1
1590 def calculate_result_code(self):
1591 if self.is_buffer_access:
1592 return "(*%s)" % self.buffer_ptr_code
1593 else:
1594 return "(%s[%s])" % (
1595 self.base.result(), self.index.result())
1597 def index_unsigned_parameter(self):
1598 if self.index.type.is_int:
1599 if self.original_index_type.signed:
1600 return ", 0"
1601 else:
1602 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1603 else:
1604 return ""
1606 def generate_subexpr_evaluation_code(self, code):
1607 self.base.generate_evaluation_code(code)
1608 if not self.indices:
1609 self.index.generate_evaluation_code(code)
1610 else:
1611 for i in self.indices:
1612 i.generate_evaluation_code(code)
1614 def generate_subexpr_disposal_code(self, code):
1615 self.base.generate_disposal_code(code)
1616 if not self.indices:
1617 self.index.generate_disposal_code(code)
1618 else:
1619 for i in self.indices:
1620 i.generate_disposal_code(code)
1622 def generate_result_code(self, code):
1623 if self.is_buffer_access:
1624 if code.globalstate.directives['nonecheck']:
1625 self.put_nonecheck(code)
1626 self.buffer_ptr_code = self.buffer_lookup_code(code)
1627 if self.type.is_pyobject:
1628 # is_temp is True, so must pull out value and incref it.
1629 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1630 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1631 elif self.type.is_pyobject:
1632 if self.index.type.is_int:
1633 function = "__Pyx_GetItemInt"
1634 index_code = self.index.result()
1635 code.globalstate.use_utility_code(getitem_int_utility_code)
1636 else:
1637 function = "PyObject_GetItem"
1638 index_code = self.index.py_result()
1639 sign_code = ""
1640 code.putln(
1641 "%s = %s(%s, %s%s); if (!%s) %s" % (
1642 self.result(),
1643 function,
1644 self.base.py_result(),
1645 index_code,
1646 self.index_unsigned_parameter(),
1647 self.result(),
1648 code.error_goto(self.pos)))
1650 def generate_setitem_code(self, value_code, code):
1651 if self.index.type.is_int:
1652 function = "__Pyx_SetItemInt"
1653 index_code = self.index.result()
1654 code.globalstate.use_utility_code(setitem_int_utility_code)
1655 else:
1656 function = "PyObject_SetItem"
1657 index_code = self.index.py_result()
1658 code.putln(
1659 "if (%s(%s, %s, %s%s) < 0) %s" % (
1660 function,
1661 self.base.py_result(),
1662 index_code,
1663 value_code,
1664 self.index_unsigned_parameter(),
1665 code.error_goto(self.pos)))
1667 def generate_buffer_setitem_code(self, rhs, code, op=""):
1668 # Used from generate_assignment_code and InPlaceAssignmentNode
1669 if code.globalstate.directives['nonecheck']:
1670 self.put_nonecheck(code)
1671 ptrexpr = self.buffer_lookup_code(code)
1672 if self.buffer_type.dtype.is_pyobject:
1673 # Must manage refcounts. Decref what is already there
1674 # and incref what we put in.
1675 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
1676 if rhs.is_temp:
1677 rhs_code = code.funcstate.allocate_temp(rhs.type)
1678 else:
1679 rhs_code = rhs.result()
1680 code.putln("%s = %s;" % (ptr, ptrexpr))
1681 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1682 ptr, rhs_code
1683 ))
1684 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1685 if rhs.is_temp:
1686 code.funcstate.release_temp(rhs_code)
1687 code.funcstate.release_temp(ptr)
1688 else:
1689 # Simple case
1690 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1692 def generate_assignment_code(self, rhs, code):
1693 self.generate_subexpr_evaluation_code(code)
1694 if self.is_buffer_access:
1695 self.generate_buffer_setitem_code(rhs, code)
1696 elif self.type.is_pyobject:
1697 self.generate_setitem_code(rhs.py_result(), code)
1698 else:
1699 code.putln(
1700 "%s = %s;" % (
1701 self.result(), rhs.result()))
1702 self.generate_subexpr_disposal_code(code)
1703 rhs.generate_disposal_code(code)
1705 def generate_deletion_code(self, code):
1706 self.generate_subexpr_evaluation_code(code)
1707 #if self.type.is_pyobject:
1708 if self.index.type.is_int:
1709 function = "__Pyx_DelItemInt"
1710 index_code = self.index.result()
1711 code.globalstate.use_utility_code(delitem_int_utility_code)
1712 else:
1713 function = "PyObject_DelItem"
1714 index_code = self.index.py_result()
1715 code.putln(
1716 "if (%s(%s, %s%s) < 0) %s" % (
1717 function,
1718 self.base.py_result(),
1719 index_code,
1720 self.index_unsigned_parameter(),
1721 code.error_goto(self.pos)))
1722 self.generate_subexpr_disposal_code(code)
1724 def buffer_lookup_code(self, code):
1725 # Assign indices to temps
1726 index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
1727 for temp, index in zip(index_temps, self.indices):
1728 code.putln("%s = %s;" % (temp, index.result()))
1729 # Generate buffer access code using these temps
1730 import Buffer
1731 # The above could happen because child_attrs is wrong somewhere so that
1732 # options are not propagated.
1733 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1734 index_signeds=[i.type.signed for i in self.indices],
1735 index_cnames=index_temps,
1736 options=code.globalstate.directives,
1737 pos=self.pos, code=code)
1739 def put_nonecheck(self, code):
1740 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1741 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1742 code.putln("__Pyx_RaiseNoneIndexingError();")
1743 code.putln(code.error_goto(self.pos))
1744 code.putln("}")
1746 class SliceIndexNode(ExprNode):
1747 # 2-element slice indexing
1749 # base ExprNode
1750 # start ExprNode or None
1751 # stop ExprNode or None
1753 subexprs = ['base', 'start', 'stop']
1755 def compile_time_value(self, denv):
1756 base = self.base.compile_time_value(denv)
1757 if self.start is None:
1758 start = 0
1759 else:
1760 start = self.start.compile_time_value(denv)
1761 if self.stop is None:
1762 stop = None
1763 else:
1764 stop = self.stop.compile_time_value(denv)
1765 try:
1766 return base[start:stop]
1767 except Exception, e:
1768 self.compile_time_value_error(e)
1770 def analyse_target_declaration(self, env):
1771 pass
1773 def analyse_types(self, env):
1774 self.base.analyse_types(env)
1775 if self.start:
1776 self.start.analyse_types(env)
1777 if self.stop:
1778 self.stop.analyse_types(env)
1779 self.base = self.base.coerce_to_pyobject(env)
1780 c_int = PyrexTypes.c_py_ssize_t_type
1781 if self.start:
1782 self.start = self.start.coerce_to(c_int, env)
1783 if self.stop:
1784 self.stop = self.stop.coerce_to(c_int, env)
1785 self.type = py_object_type
1786 self.gil_check(env)
1787 self.is_temp = 1
1789 gil_message = "Slicing Python object"
1791 def generate_result_code(self, code):
1792 code.putln(
1793 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1794 self.result(),
1795 self.base.py_result(),
1796 self.start_code(),
1797 self.stop_code(),
1798 code.error_goto_if_null(self.result(), self.pos)))
1800 def generate_assignment_code(self, rhs, code):
1801 self.generate_subexpr_evaluation_code(code)
1802 code.put_error_if_neg(self.pos,
1803 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1804 self.base.py_result(),
1805 self.start_code(),
1806 self.stop_code(),
1807 rhs.result()))
1808 self.generate_subexpr_disposal_code(code)
1809 rhs.generate_disposal_code(code)
1811 def generate_deletion_code(self, code):
1812 self.generate_subexpr_evaluation_code(code)
1813 code.put_error_if_neg(self.pos,
1814 "PySequence_DelSlice(%s, %s, %s)" % (
1815 self.base.py_result(),
1816 self.start_code(),
1817 self.stop_code()))
1818 self.generate_subexpr_disposal_code(code)
1820 def start_code(self):
1821 if self.start:
1822 return self.start.result()
1823 else:
1824 return "0"
1826 def stop_code(self):
1827 if self.stop:
1828 return self.stop.result()
1829 else:
1830 return "PY_SSIZE_T_MAX"
1832 def calculate_result_code(self):
1833 # self.result() is not used, but this method must exist
1834 return "<unused>"
1837 class SliceNode(ExprNode):
1838 # start:stop:step in subscript list
1840 # start ExprNode
1841 # stop ExprNode
1842 # step ExprNode
1844 def compile_time_value(self, denv):
1845 start = self.start.compile_time_value(denv)
1846 if self.stop is None:
1847 stop = None
1848 else:
1849 stop = self.stop.compile_time_value(denv)
1850 if self.step is None:
1851 step = None
1852 else:
1853 step = self.step.compile_time_value(denv)
1854 try:
1855 return slice(start, stop, step)
1856 except Exception, e:
1857 self.compile_time_value_error(e)
1859 subexprs = ['start', 'stop', 'step']
1861 def analyse_types(self, env):
1862 self.start.analyse_types(env)
1863 self.stop.analyse_types(env)
1864 self.step.analyse_types(env)
1865 self.start = self.start.coerce_to_pyobject(env)
1866 self.stop = self.stop.coerce_to_pyobject(env)
1867 self.step = self.step.coerce_to_pyobject(env)
1868 self.type = py_object_type
1869 self.gil_check(env)
1870 self.is_temp = 1
1872 gil_message = "Constructing Python slice object"
1874 def generate_result_code(self, code):
1875 code.putln(
1876 "%s = PySlice_New(%s, %s, %s); %s" % (
1877 self.result(),
1878 self.start.py_result(),
1879 self.stop.py_result(),
1880 self.step.py_result(),
1881 code.error_goto_if_null(self.result(), self.pos)))
1884 class CallNode(ExprNode):
1885 def gil_check(self, env):
1886 # Make sure we're not in a nogil environment
1887 if env.nogil:
1888 error(self.pos, "Calling gil-requiring function without gil")
1890 def analyse_as_type_constructor(self, env):
1891 type = self.function.analyse_as_type(env)
1892 if type and type.is_struct_or_union:
1893 args, kwds = self.explicit_args_kwds()
1894 items = []
1895 for arg, member in zip(args, type.scope.var_entries):
1896 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
1897 if kwds:
1898 items += kwds.key_value_pairs
1899 self.key_value_pairs = items
1900 self.__class__ = DictNode
1901 self.analyse_types(env)
1902 self.coerce_to(type, env)
1903 return True
1906 class SimpleCallNode(CallNode):
1907 # Function call without keyword, * or ** args.
1909 # function ExprNode
1910 # args [ExprNode]
1911 # arg_tuple ExprNode or None used internally
1912 # self ExprNode or None used internally
1913 # coerced_self ExprNode or None used internally
1914 # wrapper_call bool used internally
1915 # has_optional_args bool used internally
1917 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1919 self = None
1920 coerced_self = None
1921 arg_tuple = None
1922 wrapper_call = False
1923 has_optional_args = False
1925 def compile_time_value(self, denv):
1926 function = self.function.compile_time_value(denv)
1927 args = [arg.compile_time_value(denv) for arg in self.args]
1928 try:
1929 return function(*args)
1930 except Exception, e:
1931 self.compile_time_value_error(e)
1933 def analyse_as_type(self, env):
1934 attr = self.function.as_cython_attribute()
1935 if attr == 'pointer':
1936 if len(self.args) != 1:
1937 error(self.args.pos, "only one type allowed.")
1938 else:
1939 type = self.args[0].analyse_as_type(env)
1940 if not type:
1941 error(self.args[0].pos, "Unknown type")
1942 else:
1943 return PyrexTypes.CPtrType(type)
1945 def explicit_args_kwds(self):
1946 return self.args, None
1948 def analyse_types(self, env):
1949 if self.analyse_as_type_constructor(env):
1950 return
1951 function = self.function
1952 function.is_called = 1
1953 self.function.analyse_types(env)
1954 if function.is_attribute and function.is_py_attr and \
1955 function.attribute == "append" and len(self.args) == 1:
1956 # L.append(x) is almost always applied to a list
1957 self.py_func = self.function
1958 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1959 self.function.analyse_types(env)
1960 self.self = self.py_func.obj
1961 function.obj = CloneNode(self.self)
1962 env.use_utility_code(append_utility_code)
1963 if function.is_attribute and function.entry and function.entry.is_cmethod:
1964 # Take ownership of the object from which the attribute
1965 # was obtained, because we need to pass it as 'self'.
1966 self.self = function.obj
1967 function.obj = CloneNode(self.self)
1968 func_type = self.function_type()
1969 if func_type.is_pyobject:
1970 self.arg_tuple = TupleNode(self.pos, args = self.args)
1971 self.arg_tuple.analyse_types(env)
1972 self.args = None
1973 self.type = py_object_type
1974 self.gil_check(env)
1975 self.is_temp = 1
1976 else:
1977 for arg in self.args:
1978 arg.analyse_types(env)
1979 if self.self and func_type.args:
1980 # Coerce 'self' to the type expected by the method.
1981 expected_type = func_type.args[0].type
1982 self.coerced_self = CloneNode(self.self).coerce_to(
1983 expected_type, env)
1984 # Insert coerced 'self' argument into argument list.
1985 self.args.insert(0, self.coerced_self)
1986 self.analyse_c_function_call(env)
1988 def function_type(self):
1989 # Return the type of the function being called, coercing a function
1990 # pointer to a function if necessary.
1991 func_type = self.function.type
1992 if func_type.is_ptr:
1993 func_type = func_type.base_type
1994 return func_type
1996 def analyse_c_function_call(self, env):
1997 func_type = self.function_type()
1998 # Check function type
1999 if not func_type.is_cfunction:
2000 if not func_type.is_error:
2001 error(self.pos, "Calling non-function type '%s'" %
2002 func_type)
2003 self.type = PyrexTypes.error_type
2004 self.result_code = "<error>"
2005 return
2006 # Check no. of args
2007 max_nargs = len(func_type.args)
2008 expected_nargs = max_nargs - func_type.optional_arg_count
2009 actual_nargs = len(self.args)
2010 if actual_nargs < expected_nargs \
2011 or (not func_type.has_varargs and actual_nargs > max_nargs):
2012 expected_str = str(expected_nargs)
2013 if func_type.has_varargs:
2014 expected_str = "at least " + expected_str
2015 elif func_type.optional_arg_count:
2016 if actual_nargs < max_nargs:
2017 expected_str = "at least " + expected_str
2018 else:
2019 expected_str = "at most " + str(max_nargs)
2020 error(self.pos,
2021 "Call with wrong number of arguments (expected %s, got %s)"
2022 % (expected_str, actual_nargs))
2023 self.args = None
2024 self.type = PyrexTypes.error_type
2025 self.result_code = "<error>"
2026 return
2027 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2028 self.has_optional_args = 1
2029 self.is_temp = 1
2030 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2031 env.release_temp(self.opt_arg_struct)
2032 # Coerce arguments
2033 for i in range(min(max_nargs, actual_nargs)):
2034 formal_type = func_type.args[i].type
2035 self.args[i] = self.args[i].coerce_to(formal_type, env)
2036 for i in range(max_nargs, actual_nargs):
2037 if self.args[i].type.is_pyobject:
2038 error(self.args[i].pos,
2039 "Python object cannot be passed as a varargs parameter")
2040 # Calc result type and code fragment
2041 self.type = func_type.return_type
2042 if self.type.is_pyobject \
2043 or func_type.exception_value is not None \
2044 or func_type.exception_check:
2045 self.is_temp = 1
2046 if self.type.is_pyobject:
2047 self.result_ctype = py_object_type
2048 # C++ exception handler
2049 if func_type.exception_check == '+':
2050 if func_type.exception_value is None:
2051 env.use_utility_code(cpp_exception_utility_code)
2052 # Check gil
2053 if not func_type.nogil:
2054 self.gil_check(env)
2056 def calculate_result_code(self):
2057 return self.c_call_code()
2059 def c_call_code(self):
2060 func_type = self.function_type()
2061 if self.args is None or not func_type.is_cfunction:
2062 return "<error>"
2063 formal_args = func_type.args
2064 arg_list_code = []
2065 args = zip(formal_args, self.args)
2066 max_nargs = len(func_type.args)
2067 expected_nargs = max_nargs - func_type.optional_arg_count
2068 actual_nargs = len(self.args)
2069 for formal_arg, actual_arg in args[:expected_nargs]:
2070 arg_code = actual_arg.result_as(formal_arg.type)
2071 arg_list_code.append(arg_code)
2073 if func_type.is_overridable:
2074 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2076 if func_type.optional_arg_count:
2077 if expected_nargs == actual_nargs:
2078 optional_args = 'NULL'
2079 else:
2080 optional_args = "&%s" % self.opt_arg_struct
2081 arg_list_code.append(optional_args)
2083 for actual_arg in self.args[len(formal_args):]:
2084 arg_list_code.append(actual_arg.result())
2085 result = "%s(%s)" % (self.function.result(),
2086 join(arg_list_code, ", "))
2087 # if self.wrapper_call or \
2088 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2089 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2090 return result
2092 def generate_result_code(self, code):
2093 func_type = self.function_type()
2094 if func_type.is_pyobject:
2095 arg_code = self.arg_tuple.py_result()
2096 code.putln(
2097 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2098 self.result(),
2099 self.function.py_result(),
2100 arg_code,
2101 code.error_goto_if_null(self.result(), self.pos)))
2102 elif func_type.is_cfunction:
2103 if self.has_optional_args:
2104 actual_nargs = len(self.args)
2105 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2106 code.putln("%s.%s = %s;" % (
2107 self.opt_arg_struct,
2108 Naming.pyrex_prefix + "n",
2109 len(self.args) - expected_nargs))
2110 args = zip(func_type.args, self.args)
2111 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2112 code.putln("%s.%s = %s;" % (
2113 self.opt_arg_struct,
2114 formal_arg.name,
2115 actual_arg.result_as(formal_arg.type)))
2116 exc_checks = []
2117 if self.type.is_pyobject:
2118 exc_checks.append("!%s" % self.result())
2119 else:
2120 exc_val = func_type.exception_value
2121 exc_check = func_type.exception_check
2122 if exc_val is not None:
2123 exc_checks.append("%s == %s" % (self.result(), exc_val))
2124 if exc_check:
2125 exc_checks.append("PyErr_Occurred()")
2126 if self.is_temp or exc_checks:
2127 rhs = self.c_call_code()
2128 if self.result():
2129 lhs = "%s = " % self.result()
2130 if self.is_temp and self.type.is_pyobject:
2131 #return_type = self.type # func_type.return_type
2132 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2133 # "from", return_type, "to pyobject" ###
2134 rhs = typecast(py_object_type, self.type, rhs)
2135 else:
2136 lhs = ""
2137 if func_type.exception_check == '+':
2138 if func_type.exception_value is None:
2139 raise_py_exception = "__Pyx_CppExn2PyErr()"
2140 elif func_type.exception_value.type.is_pyobject:
2141 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2142 else:
2143 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2144 code.putln(
2145 "try {%s%s;} catch(...) {%s; %s}" % (
2146 lhs,
2147 rhs,
2148 raise_py_exception,
2149 code.error_goto(self.pos)))
2150 else:
2151 if exc_checks:
2152 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2153 else:
2154 goto_error = ""
2155 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2157 class GeneralCallNode(CallNode):
2158 # General Python function call, including keyword,
2159 # * and ** arguments.
2161 # function ExprNode
2162 # positional_args ExprNode Tuple of positional arguments
2163 # keyword_args ExprNode or None Dict of keyword arguments
2164 # starstar_arg ExprNode or None Dict of extra keyword args
2166 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2168 def compile_time_value(self, denv):
2169 function = self.function.compile_time_value(denv)
2170 positional_args = self.positional_args.compile_time_value(denv)
2171 keyword_args = self.keyword_args.compile_time_value(denv)
2172 starstar_arg = self.starstar_arg.compile_time_value(denv)
2173 try:
2174 keyword_args.update(starstar_arg)
2175 return function(*positional_args, **keyword_args)
2176 except Exception, e:
2177 self.compile_time_value_error(e)
2179 def explicit_args_kwds(self):
2180 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2181 raise PostParseError(self.pos,
2182 'Compile-time keyword arguments must be explicit.')
2183 return self.positional_args.args, self.keyword_args
2185 def analyse_types(self, env):
2186 if self.analyse_as_type_constructor(env):
2187 return
2188 self.function.analyse_types(env)
2189 self.positional_args.analyse_types(env)
2190 if self.keyword_args:
2191 self.keyword_args.analyse_types(env)
2192 if self.starstar_arg:
2193 self.starstar_arg.analyse_types(env)
2194 self.function = self.function.coerce_to_pyobject(env)
2195 self.positional_args = \
2196 self.positional_args.coerce_to_pyobject(env)
2197 if self.starstar_arg:
2198 self.starstar_arg = \
2199 self.starstar_arg.coerce_to_pyobject(env)
2200 self.type = py_object_type
2201 self.gil_check(env)
2202 self.is_temp = 1
2204 def generate_result_code(self, code):
2205 if self.keyword_args and self.starstar_arg:
2206 code.put_error_if_neg(self.pos,
2207 "PyDict_Update(%s, %s)" % (
2208 self.keyword_args.py_result(),
2209 self.starstar_arg.py_result()))
2210 keyword_code = self.keyword_args.py_result()
2211 elif self.keyword_args:
2212 keyword_code = self.keyword_args.py_result()
2213 elif self.starstar_arg:
2214 keyword_code = self.starstar_arg.py_result()
2215 else:
2216 keyword_code = None
2217 if not keyword_code:
2218 call_code = "PyObject_Call(%s, %s, NULL)" % (
2219 self.function.py_result(),
2220 self.positional_args.py_result())
2221 else:
2222 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2223 self.function.py_result(),
2224 self.positional_args.py_result(),
2225 keyword_code)
2226 code.putln(
2227 "%s = %s; %s" % (
2228 self.result(),
2229 call_code,
2230 code.error_goto_if_null(self.result(), self.pos)))
2233 class AsTupleNode(ExprNode):
2234 # Convert argument to tuple. Used for normalising
2235 # the * argument of a function call.
2237 # arg ExprNode
2239 subexprs = ['arg']
2241 def compile_time_value(self, denv):
2242 arg = self.arg.compile_time_value(denv)
2243 try:
2244 return tuple(arg)
2245 except Exception, e:
2246 self.compile_time_value_error(e)
2248 def analyse_types(self, env):
2249 self.arg.analyse_types(env)
2250 self.arg = self.arg.coerce_to_pyobject(env)
2251 self.type = py_object_type
2252 self.gil_check(env)
2253 self.is_temp = 1
2255 gil_message = "Constructing Python tuple"
2257 def generate_result_code(self, code):
2258 code.putln(
2259 "%s = PySequence_Tuple(%s); %s" % (
2260 self.result(),
2261 self.arg.py_result(),
2262 code.error_goto_if_null(self.result(), self.pos)))
2265 class AttributeNode(ExprNode):
2266 # obj.attribute
2268 # obj ExprNode
2269 # attribute string
2270 # needs_none_check boolean Used if obj is an extension type.
2271 # If set to True, it is known that the type is not None.
2273 # Used internally:
2275 # is_py_attr boolean Is a Python getattr operation
2276 # member string C name of struct member
2277 # is_called boolean Function call is being done on result
2278 # entry Entry Symbol table entry of attribute
2279 # interned_attr_cname string C name of interned attribute name
2281 is_attribute = 1
2282 subexprs = ['obj']
2284 type = PyrexTypes.error_type
2285 entry = None
2286 is_called = 0
2287 needs_none_check = True
2289 def as_cython_attribute(self):
2290 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2291 return self.attribute
2293 def coerce_to(self, dst_type, env):
2294 # If coercing to a generic pyobject and this is a cpdef function
2295 # we can create the corresponding attribute
2296 if dst_type is py_object_type:
2297 entry = self.entry
2298 if entry and entry.is_cfunction and entry.as_variable:
2299 # must be a cpdef function
2300 self.is_temp = 1
2301 self.entry = entry.as_variable
2302 self.analyse_as_python_attribute(env)
2303 return self
2304 return ExprNode.coerce_to(self, dst_type, env)
2306 def compile_time_value(self, denv):
2307 attr = self.attribute
2308 if attr.beginswith("__") and attr.endswith("__"):
2309 self.error("Invalid attribute name '%s' in compile-time expression"
2310 % attr)
2311 return None
2312 obj = self.arg.compile_time_value(denv)
2313 try:
2314 return getattr(obj, attr)
2315 except Exception, e:
2316 self.compile_time_value_error(e)
2318 def analyse_target_declaration(self, env):
2319 pass
2321 def analyse_target_types(self, env):
2322 self.analyse_types(env, target = 1)
2324 def analyse_types(self, env, target = 0):
2325 if self.analyse_as_cimported_attribute(env, target):
2326 return
2327 if not target and self.analyse_as_unbound_cmethod(env):
2328 return
2329 self.analyse_as_ordinary_attribute(env, target)
2331 def analyse_as_cimported_attribute(self, env, target):
2332 # Try to interpret this as a reference to an imported
2333 # C const, type, var or function. If successful, mutates
2334 # this node into a NameNode and returns 1, otherwise
2335 # returns 0.
2336 module_scope = self.obj.analyse_as_module(env)
2337 if module_scope:
2338 entry = module_scope.lookup_here(self.attribute)
2339 if entry and (
2340 entry.is_cglobal or entry.is_cfunction
2341 or entry.is_type or entry.is_const):
2342 self.mutate_into_name_node(env, entry, target)
2343 return 1
2344 return 0
2346 def analyse_as_unbound_cmethod(self, env):
2347 # Try to interpret this as a reference to an unbound
2348 # C method of an extension type. If successful, mutates
2349 # this node into a NameNode and returns 1, otherwise
2350 # returns 0.
2351 type = self.obj.analyse_as_extension_type(env)
2352 if type:
2353 entry = type.scope.lookup_here(self.attribute)
2354 if entry and entry.is_cmethod:
2355 # Create a temporary entry describing the C method
2356 # as an ordinary function.
2357 ubcm_entry = Symtab.Entry(entry.name,
2358 "%s->%s" % (type.vtabptr_cname, entry.cname),
2359 entry.type)
2360 ubcm_entry.is_cfunction = 1
2361 ubcm_entry.func_cname = entry.func_cname
2362 ubcm_entry.is_unbound_cmethod = 1
2363 self.mutate_into_name_node(env, ubcm_entry, None)
2364 return 1
2365 return 0
2367 def analyse_as_type(self, env):
2368 module_scope = self.obj.analyse_as_module(env)
2369 if module_scope:
2370 return module_scope.lookup_type(self.attribute)
2371 return None
2373 def analyse_as_extension_type(self, env):
2374 # Try to interpret this as a reference to an extension type
2375 # in a cimported module. Returns the extension type, or None.
2376 module_scope = self.obj.analyse_as_module(env)
2377 if module_scope:
2378 entry = module_scope.lookup_here(self.attribute)
2379 if entry and entry.is_type and entry.type.is_extension_type:
2380 return entry.type
2381 return None
2383 def analyse_as_module(self, env):
2384 # Try to interpret this as a reference to a cimported module
2385 # in another cimported module. Returns the module scope, or None.
2386 module_scope = self.obj.analyse_as_module(env)
2387 if module_scope:
2388 entry = module_scope.lookup_here(self.attribute)
2389 if entry and entry.as_module:
2390 return entry.as_module
2391 return None
2393 def mutate_into_name_node(self, env, entry, target):
2394 # Mutate this node into a NameNode and complete the
2395 # analyse_types phase.
2396 self.__class__ = NameNode
2397 self.name = self.attribute
2398 self.entry = entry
2399 del self.obj
2400 del self.attribute
2401 if target:
2402 NameNode.analyse_target_types(self, env)
2403 else:
2404 NameNode.analyse_rvalue_entry(self, env)
2406 def analyse_as_ordinary_attribute(self, env, target):
2407 self.obj.analyse_types(env)
2408 self.analyse_attribute(env)
2409 if self.entry and self.entry.is_cmethod and not self.is_called:
2410 # error(self.pos, "C method can only be called")
2411 pass
2412 ## Reference to C array turns into pointer to first element.
2413 #while self.type.is_array:
2414 # self.type = self.type.element_ptr_type()
2415 if self.is_py_attr:
2416 if not target:
2417 self.is_temp = 1
2418 self.result_ctype = py_object_type
2420 def analyse_attribute(self, env):
2421 # Look up attribute and set self.type and self.member.
2422 self.is_py_attr = 0
2423 self.member = self.attribute
2424 if self.obj.type.is_string:
2425 self.obj = self.obj.coerce_to_pyobject(env)
2426 obj_type = self.obj.type
2427 if obj_type.is_ptr or obj_type.is_array:
2428 obj_type = obj_type.base_type
2429 self.op = "->"
2430 elif obj_type.is_extension_type:
2431 self.op = "->"
2432 else:
2433 self.op = "."
2434 if obj_type.has_attributes:
2435 entry = None
2436 if obj_type.attributes_known():
2437 entry = obj_type.scope.lookup_here(self.attribute)
2438 if entry and entry.is_member:
2439 entry = None
2440 else:
2441 error(self.pos,
2442 "Cannot select attribute of incomplete type '%s'"
2443 % obj_type)
2444 self.type = PyrexTypes.error_type
2445 return
2446 self.entry = entry
2447 if entry:
2448 if obj_type.is_extension_type and entry.name == "__weakref__":
2449 error(self.pos, "Illegal use of special attribute __weakref__")
2450 # methods need the normal attribute lookup
2451 # because they do not have struct entries
2452 if entry.is_variable or entry.is_cmethod:
2453 self.type = entry.type
2454 self.member = entry.cname
2455 return
2456 else:
2457 # If it's not a variable or C method, it must be a Python
2458 # method of an extension type, so we treat it like a Python
2459 # attribute.
2460 pass
2461 # If we get here, the base object is not a struct/union/extension
2462 # type, or it is an extension type and the attribute is either not
2463 # declared or is declared as a Python method. Treat it as a Python
2464 # attribute reference.
2465 self.analyse_as_python_attribute(env)
2467 def analyse_as_python_attribute(self, env):
2468 obj_type = self.obj.type
2469 self.member = self.attribute
2470 if obj_type.is_pyobject:
2471 self.type = py_object_type
2472 self.is_py_attr = 1
2473 self.interned_attr_cname = env.intern_identifier(self.attribute)
2474 self.gil_check(env)
2475 else:
2476 if not obj_type.is_error:
2477 error(self.pos,
2478 "Object of type '%s' has no attribute '%s'" %
2479 (obj_type, self.attribute))
2481 gil_message = "Accessing Python attribute"
2483 def is_simple(self):
2484 if self.obj:
2485 return self.result_in_temp() or self.obj.is_simple()
2486 else:
2487 return NameNode.is_simple(self)
2489 def is_lvalue(self):
2490 if self.obj:
2491 return 1
2492 else:
2493 return NameNode.is_lvalue(self)
2495 def is_ephemeral(self):
2496 if self.obj:
2497 return self.obj.is_ephemeral()
2498 else:
2499 return NameNode.is_ephemeral(self)
2501 def calculate_result_code(self):
2502 #print "AttributeNode.calculate_result_code:", self.member ###
2503 #print "...obj node =", self.obj, "code", self.obj.result() ###
2504 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2505 obj = self.obj
2506 obj_code = obj.result_as(obj.type)
2507 #print "...obj_code =", obj_code ###
2508 if self.entry and self.entry.is_cmethod:
2509 if obj.type.is_extension_type:
2510 return "((struct %s *)%s%s%s)->%s" % (
2511 obj.type.vtabstruct_cname, obj_code, self.op,
2512 obj.type.vtabslot_cname, self.member)
2513 else:
2514 return self.member
2515 else:
2516 return "%s%s%s" % (obj_code, self.op, self.member)
2518 def generate_result_code(self, code):
2519 if self.is_py_attr:
2520 code.putln(
2521 '%s = PyObject_GetAttr(%s, %s); %s' % (
2522 self.result(),
2523 self.obj.py_result(),
2524 self.interned_attr_cname,
2525 code.error_goto_if_null(self.result(), self.pos)))
2526 else:
2527 # result_code contains what is needed, but we may need to insert
2528 # a check and raise an exception
2529 if (self.obj.type.is_extension_type
2530 and self.needs_none_check
2531 and code.globalstate.directives['nonecheck']):
2532 self.put_nonecheck(code)
2534 def generate_assignment_code(self, rhs, code):
2535 self.obj.generate_evaluation_code(code)
2536 if self.is_py_attr:
2537 code.put_error_if_neg(self.pos,
2538 'PyObject_SetAttr(%s, %s, %s)' % (
2539 self.obj.py_result(),
2540 self.interned_attr_cname,
2541 rhs.py_result()))
2542 rhs.generate_disposal_code(code)
2543 else:
2544 if (self.obj.type.is_extension_type
2545 and self.needs_none_check
2546 and code.globalstate.directives['nonecheck']):
2547 self.put_nonecheck(code)
2549 select_code = self.result()
2550 if self.type.is_pyobject:
2551 rhs.make_owned_reference(code)
2552 code.put_decref(select_code, self.ctype())
2553 code.putln(
2554 "%s = %s;" % (
2555 select_code,
2556 rhs.result_as(self.ctype())))
2557 #rhs.result()))
2558 rhs.generate_post_assignment_code(code)
2559 self.obj.generate_disposal_code(code)
2561 def generate_deletion_code(self, code):
2562 self.obj.generate_evaluation_code(code)
2563 if self.is_py_attr:
2564 code.put_error_if_neg(self.pos,
2565 'PyObject_DelAttr(%s, %s)' % (
2566 self.obj.py_result(),
2567 self.interned_attr_cname))
2568 else:
2569 error(self.pos, "Cannot delete C attribute of extension type")
2570 self.obj.generate_disposal_code(code)
2572 def annotate(self, code):
2573 if self.is_py_attr:
2574 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2575 else:
2576 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2578 def put_nonecheck(self, code):
2579 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2580 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2581 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2582 code.putln(code.error_goto(self.pos))
2583 code.putln("}")
2586 #-------------------------------------------------------------------
2588 # Constructor nodes
2590 #-------------------------------------------------------------------
2592 class SequenceNode(ExprNode):
2593 # Base class for list and tuple constructor nodes.
2594 # Contains common code for performing sequence unpacking.
2596 # args [ExprNode]
2597 # iterator ExprNode
2598 # unpacked_items [ExprNode] or None
2599 # coerced_unpacked_items [ExprNode] or None
2601 subexprs = ['args']
2603 is_sequence_constructor = 1
2604 unpacked_items = None
2606 def compile_time_value_list(self, denv):
2607 return [arg.compile_time_value(denv) for arg in self.args]
2609 def analyse_target_declaration(self, env):
2610 for arg in self.args:
2611 arg.analyse_target_declaration(env)
2613 def analyse_types(self, env, skip_children=False):
2614 for i in range(len(self.args)):
2615 arg = self.args[i]
2616 if not skip_children: arg.analyse_types(env)
2617 self.args[i] = arg.coerce_to_pyobject(env)
2618 self.type = py_object_type
2619 self.gil_check(env)
2620 self.is_temp = 1
2622 def analyse_target_types(self, env):
2623 self.iterator = PyTempNode(self.pos, env)
2624 self.unpacked_items = []
2625 self.coerced_unpacked_items = []
2626 for arg in self.args:
2627 arg.analyse_target_types(env)
2628 unpacked_item = PyTempNode(self.pos, env)
2629 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2630 self.unpacked_items.append(unpacked_item)
2631 self.coerced_unpacked_items.append(coerced_unpacked_item)
2632 self.type = py_object_type
2633 env.use_utility_code(unpacking_utility_code)
2635 def allocate_target_temps(self, env, rhs):
2636 self.iterator.allocate_temps(env)
2637 for arg, node in zip(self.args, self.coerced_unpacked_items):
2638 node.allocate_temps(env)
2639 arg.allocate_target_temps(env, node)
2640 #arg.release_target_temp(env)
2641 #node.release_temp(env)
2642 if rhs:
2643 rhs.release_temp(env)
2644 self.iterator.release_temp(env)
2646 # def release_target_temp(self, env):
2647 # #for arg in self.args:
2648 # # arg.release_target_temp(env)
2649 # #for node in self.coerced_unpacked_items:
2650 # # node.release_temp(env)
2651 # self.iterator.release_temp(env)
2653 def generate_result_code(self, code):
2654 self.generate_operation_code(code)
2656 def generate_assignment_code(self, rhs, code):
2657 code.putln(
2658 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2659 rhs.py_result(),
2660 rhs.py_result(),
2661 len(self.args)))
2662 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2663 for i in range(len(self.args)):
2664 item = self.unpacked_items[i]
2665 code.putln(
2666 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2667 item.result(),
2668 i))
2669 code.put_incref(item.result(), item.ctype())
2670 value_node = self.coerced_unpacked_items[i]
2671 value_node.generate_evaluation_code(code)
2672 self.args[i].generate_assignment_code(value_node, code)
2674 rhs.generate_disposal_code(code)
2675 code.putln("}")
2676 code.putln("else {")
2678 code.putln(
2679 "%s = PyObject_GetIter(%s); %s" % (
2680 self.iterator.result(),
2681 rhs.py_result(),
2682 code.error_goto_if_null(self.iterator.result(), self.pos)))
2683 rhs.generate_disposal_code(code)
2684 for i in range(len(self.args)):
2685 item = self.unpacked_items[i]
2686 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2687 self.iterator.py_result(), i)
2688 code.putln(
2689 "%s = %s; %s" % (
2690 item.result(),
2691 typecast(item.ctype(), py_object_type, unpack_code),
2692 code.error_goto_if_null(item.result(), self.pos)))
2693 value_node = self.coerced_unpacked_items[i]
2694 value_node.generate_evaluation_code(code)
2695 self.args[i].generate_assignment_code(value_node, code)
2696 code.put_error_if_neg(self.pos,
2697 "__Pyx_EndUnpack(%s)" % (
2698 self.iterator.py_result()))
2699 if debug_disposal_code:
2700 print("UnpackNode.generate_assignment_code:")
2701 print("...generating disposal code for %s" % self.iterator)
2702 self.iterator.generate_disposal_code(code)
2704 code.putln("}")
2706 def annotate(self, code):
2707 for arg in self.args:
2708 arg.annotate(code)
2709 if self.unpacked_items:
2710 for arg in self.unpacked_items:
2711 arg.annotate(code)
2712 for arg in self.coerced_unpacked_items:
2713 arg.annotate(code)
2716 class TupleNode(SequenceNode):
2717 # Tuple constructor.
2719 gil_message = "Constructing Python tuple"
2721 def analyse_types(self, env, skip_children=False):
2722 if len(self.args) == 0:
2723 self.is_temp = 0
2724 self.is_literal = 1
2725 else:
2726 SequenceNode.analyse_types(self, env, skip_children)
2727 self.type = tuple_type
2729 def calculate_result_code(self):
2730 if len(self.args) > 0:
2731 error(self.pos, "Positive length tuples must be constructed.")
2732 else:
2733 return Naming.empty_tuple
2735 def compile_time_value(self, denv):
2736 values = self.compile_time_value_list(denv)
2737 try:
2738 return tuple(values)
2739 except Exception, e:
2740 self.compile_time_value_error(e)
2742 def generate_operation_code(self, code):
2743 if len(self.args) == 0:
2744 # result_code is Naming.empty_tuple
2745 return
2746 code.putln(
2747 "%s = PyTuple_New(%s); %s" % (
2748 self.result(),
2749 len(self.args),
2750 code.error_goto_if_null(self.result(), self.pos)))
2751 for i in range(len(self.args)):
2752 arg = self.args[i]
2753 if not arg.result_in_temp():
2754 code.put_incref(arg.result(), arg.ctype())
2755 code.putln(
2756 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2757 self.result(),
2758 i,
2759 arg.py_result()))
2761 def generate_subexpr_disposal_code(self, code):
2762 # We call generate_post_assignment_code here instead
2763 # of generate_disposal_code, because values were stored
2764 # in the tuple using a reference-stealing operation.
2765 for arg in self.args:
2766 arg.generate_post_assignment_code(code)
2769 class ListNode(SequenceNode):
2770 # List constructor.
2772 # obj_conversion_errors [PyrexError] used internally
2773 # orignial_args [ExprNode] used internally
2775 gil_message = "Constructing Python list"
2777 def analyse_expressions(self, env):
2778 ExprNode.analyse_expressions(self, env)
2779 self.coerce_to_pyobject(env)
2781 def analyse_types(self, env):
2782 hold_errors()
2783 self.original_args = list(self.args)
2784 SequenceNode.analyse_types(self, env)
2785 self.type = list_type
2786 self.obj_conversion_errors = held_errors()
2787 release_errors(ignore=True)
2789 def coerce_to(self, dst_type, env):
2790 if dst_type.is_pyobject:
2791 for err in self.obj_conversion_errors:
2792 report_error(err)
2793 self.obj_conversion_errors = []
2794 if not self.type.subtype_of(dst_type):
2795 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2796 elif dst_type.is_ptr:
2797 base_type = dst_type.base_type
2798 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
2799 for i in range(len(self.original_args)):
2800 arg = self.args[i]
2801 if isinstance(arg, CoerceToPyTypeNode):
2802 arg = arg.arg
2803 self.args[i] = arg.coerce_to(base_type, env)
2804 elif dst_type.is_struct:
2805 if len(self.args) > len(dst_type.scope.var_entries):
2806 error(self.pos, "Too may members for '%s'" % dst_type)
2807 else:
2808 if len(self.args) < len(dst_type.scope.var_entries):
2809 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
2810 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
2811 if isinstance(arg, CoerceToPyTypeNode):
2812 arg = arg.arg
2813 self.args[i] = arg.coerce_to(member.type, env)
2814 self.type = dst_type
2815 else:
2816 self.type = error_type
2817 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2818 return self
2820 def release_temp(self, env):
2821 if self.type.is_array:
2822 # To be valid C++, we must allocate the memory on the stack
2823 # manually and be sure not to reuse it for something else.
2824 pass
2825 else:
2826 SequenceNode.release_temp(self, env)
2828 def compile_time_value(self, denv):
2829 return self.compile_time_value_list(denv)
2831 def generate_operation_code(self, code):
2832 if self.type.is_pyobject:
2833 for err in self.obj_conversion_errors:
2834 report_error(err)
2835 code.putln("%s = PyList_New(%s); %s" %
2836 (self.result(),
2837 len(self.args),
2838 code.error_goto_if_null(self.result(), self.pos)))
2839 for i in range(len(self.args)):
2840 arg = self.args[i]
2841 #if not arg.is_temp:
2842 if not arg.result_in_temp():
2843 code.put_incref(arg.result(), arg.ctype())
2844 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2845 (self.result(),
2846 i,
2847 arg.py_result()))
2848 elif self.type.is_array:
2849 for i, arg in enumerate(self.args):
2850 code.putln("%s[%s] = %s;" % (
2851 self.result(),
2852 i,
2853 arg.result()))
2854 elif self.type.is_struct:
2855 for arg, member in zip(self.args, self.type.scope.var_entries):
2856 code.putln("%s.%s = %s;" % (
2857 self.result(),
2858 member.cname,
2859 arg.result()))
2860 else:
2861 raise InternalError("List type never specified")
2863 def generate_subexpr_disposal_code(self, code):
2864 # We call generate_post_assignment_code here instead
2865 # of generate_disposal_code, because values were stored
2866 # in the list using a reference-stealing operation.
2867 for arg in self.args:
2868 arg.generate_post_assignment_code(code)
2871 class ListComprehensionNode(SequenceNode):
2873 subexprs = []
2874 is_sequence_constructor = 0 # not unpackable
2876 child_attrs = ["loop", "append"]
2878 def analyse_types(self, env):
2879 self.type = list_type
2880 self.is_temp = 1
2881 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2883 def allocate_temps(self, env, result = None):
2884 if debug_temp_alloc:
2885 print("%s Allocating temps" % self)
2886 self.allocate_temp(env, result)
2887 self.loop.analyse_declarations(env)
2888 self.loop.analyse_expressions(env)
2890 def generate_operation_code(self, code):
2891 code.putln("%s = PyList_New(%s); %s" %
2892 (self.result(),
2893 0,
2894 code.error_goto_if_null(self.result(), self.pos)))
2895 self.loop.generate_execution_code(code)
2897 def annotate(self, code):
2898 self.loop.annotate(code)
2901 class ListComprehensionAppendNode(ExprNode):
2903 # Need to be careful to avoid infinite recursion:
2904 # target must not be in child_attrs/subexprs
2905 subexprs = ['expr']
2907 def analyse_types(self, env):
2908 self.expr.analyse_types(env)
2909 if self.expr.type != py_object_type:
2910 self.expr = self.expr.coerce_to_pyobject(env)
2911 self.type = PyrexTypes.c_int_type
2912 self.is_temp = 1
2914 def generate_result_code(self, code):
2915 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
2916 (self.result(),
2917 self.target.result(),
2918 self.expr.result(),
2919 code.error_goto_if(self.result(), self.pos)))
2922 class DictNode(ExprNode):
2923 # Dictionary constructor.
2925 # key_value_pairs [DictItemNode]
2927 # obj_conversion_errors [PyrexError] used internally
2929 subexprs = ['key_value_pairs']
2931 def compile_time_value(self, denv):
2932 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2933 for item in self.key_value_pairs]
2934 try:
2935 return dict(pairs)
2936 except Exception, e:
2937 self.compile_time_value_error(e)
2939 def analyse_types(self, env):
2940 hold_errors()
2941 self.type = dict_type
2942 for item in self.key_value_pairs:
2943 item.analyse_types(env)
2944 self.gil_check(env)
2945 self.obj_conversion_errors = held_errors()
2946 release_errors(ignore=True)
2947 self.is_temp = 1
2949 def coerce_to(self, dst_type, env):
2950 if dst_type.is_pyobject:
2951 self.release_errors()
2952 if not self.type.subtype_of(dst_type):
2953 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
2954 elif dst_type.is_struct_or_union:
2955 self.type = dst_type
2956 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
2957 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
2958 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
2959 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
2960 for item in self.key_value_pairs:
2961 if isinstance(item.key, CoerceToPyTypeNode):
2962 item.key = item.key.arg
2963 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
2964 error(item.key.pos, "Invalid struct field identifier")
2965 item.key = IdentifierStringNode(item.key.pos, value="<error>")
2966 else:
2967 member = dst_type.scope.lookup_here(item.key.value)
2968 if not member:
2969 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
2970 else:
2971 value = item.value
2972 if isinstance(value, CoerceToPyTypeNode):
2973 value = value.arg
2974 item.value = value.coerce_to(member.type, env)
2975 else:
2976 self.type = error_type
2977 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
2978 return self
2980 def release_errors(self):
2981 for err in self.obj_conversion_errors:
2982 report_error(err)
2983 self.obj_conversion_errors = []
2985 gil_message = "Constructing Python dict"
2987 def allocate_temps(self, env, result = None):
2988 # Custom method used here because key-value
2989 # pairs are evaluated and used one at a time.
2990 self.allocate_temp(env, result)
2991 for item in self.key_value_pairs:
2992 item.key.allocate_temps(env)
2993 item.value.allocate_temps(env)
2994 item.key.release_temp(env)
2995 item.value.release_temp(env)
2997 def generate_evaluation_code(self, code):
2998 # Custom method used here because key-value
2999 # pairs are evaluated and used one at a time.
3000 if self.type.is_pyobject:
3001 self.release_errors()
3002 code.putln(
3003 "%s = PyDict_New(); %s" % (
3004 self.result(),
3005 code.error_goto_if_null(self.result(), self.pos)))
3006 for item in self.key_value_pairs:
3007 item.generate_evaluation_code(code)
3008 if self.type.is_pyobject:
3009 code.put_error_if_neg(self.pos,
3010 "PyDict_SetItem(%s, %s, %s)" % (
3011 self.result(),
3012 item.key.py_result(),
3013 item.value.py_result()))
3014 else:
3015 code.putln("%s.%s = %s;" % (
3016 self.result(),
3017 item.key.value,
3018 item.value.result()))
3019 item.generate_disposal_code(code)
3021 def annotate(self, code):
3022 for item in self.key_value_pairs:
3023 item.annotate(code)
3025 class DictItemNode(ExprNode):
3026 # Represents a single item in a DictNode
3028 # key ExprNode
3029 # value ExprNode
3030 subexprs = ['key', 'value']
3032 def analyse_types(self, env):
3033 self.key.analyse_types(env)
3034 self.value.analyse_types(env)
3035 self.key = self.key.coerce_to_pyobject(env)
3036 self.value = self.value.coerce_to_pyobject(env)
3038 def generate_evaluation_code(self, code):
3039 self.key.generate_evaluation_code(code)
3040 self.value.generate_evaluation_code(code)
3042 def generate_disposal_code(self, code):
3043 self.key.generate_disposal_code(code)
3044 self.value.generate_disposal_code(code)
3046 def __iter__(self):
3047 return iter([self.key, self.value])
3050 class ClassNode(ExprNode):
3051 # Helper class used in the implementation of Python
3052 # class definitions. Constructs a class object given
3053 # a name, tuple of bases and class dictionary.
3055 # name EncodedString Name of the class
3056 # cname string Class name as a Python string
3057 # bases ExprNode Base class tuple
3058 # dict ExprNode Class dict (not owned by this node)
3059 # doc ExprNode or None Doc string
3060 # module_name string Name of defining module
3062 subexprs = ['bases', 'doc']
3064 def analyse_types(self, env):
3065 self.cname = env.intern_identifier(self.name)
3066 self.bases.analyse_types(env)
3067 if self.doc:
3068 self.doc.analyse_types(env)
3069 self.doc = self.doc.coerce_to_pyobject(env)
3070 self.module_name = env.global_scope().qualified_name
3071 self.type = py_object_type
3072 self.gil_check(env)
3073 self.is_temp = 1
3074 env.use_utility_code(create_class_utility_code);
3076 gil_message = "Constructing Python class"
3078 def generate_result_code(self, code):
3079 if self.doc:
3080 code.put_error_if_neg(self.pos,
3081 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3082 self.dict.py_result(),
3083 self.doc.py_result()))
3084 code.putln(
3085 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3086 self.result(),
3087 self.bases.py_result(),
3088 self.dict.py_result(),
3089 self.cname,
3090 self.module_name,
3091 code.error_goto_if_null(self.result(), self.pos)))
3094 class UnboundMethodNode(ExprNode):
3095 # Helper class used in the implementation of Python
3096 # class definitions. Constructs an unbound method
3097 # object from a class and a function.
3099 # class_cname string C var holding the class object
3100 # function ExprNode Function object
3102 subexprs = ['function']
3104 def analyse_types(self, env):
3105 self.function.analyse_types(env)
3106 self.type = py_object_type
3107 self.gil_check(env)
3108 self.is_temp = 1
3110 gil_message = "Constructing an unbound method"
3112 def generate_result_code(self, code):
3113 code.putln(
3114 "%s = PyMethod_New(%s, 0, %s); %s" % (
3115 self.result(),
3116 self.function.py_result(),
3117 self.class_cname,
3118 code.error_goto_if_null(self.result(), self.pos)))
3121 class PyCFunctionNode(AtomicExprNode):
3122 # Helper class used in the implementation of Python
3123 # class definitions. Constructs a PyCFunction object
3124 # from a PyMethodDef struct.
3126 # pymethdef_cname string PyMethodDef structure
3128 def analyse_types(self, env):
3129 self.type = py_object_type
3130 self.gil_check(env)
3131 self.is_temp = 1
3133 gil_message = "Constructing Python function"
3135 def generate_result_code(self, code):
3136 code.putln(
3137 "%s = PyCFunction_New(&%s, 0); %s" % (
3138 self.result(),
3139 self.pymethdef_cname,
3140 code.error_goto_if_null(self.result(), self.pos)))
3142 #-------------------------------------------------------------------
3144 # Unary operator nodes
3146 #-------------------------------------------------------------------
3148 compile_time_unary_operators = {
3149 'not': operator.not_,
3150 '~': operator.inv,
3151 '-': operator.neg,
3152 '+': operator.pos,
3155 class UnopNode(ExprNode):
3156 # operator string
3157 # operand ExprNode
3159 # Processing during analyse_expressions phase:
3161 # analyse_c_operation
3162 # Called when the operand is not a pyobject.
3163 # - Check operand type and coerce if needed.
3164 # - Determine result type and result code fragment.
3165 # - Allocate temporary for result if needed.
3167 subexprs = ['operand']
3169 def compile_time_value(self, denv):
3170 func = compile_time_unary_operators.get(self.operator)
3171 if not func:
3172 error(self.pos,
3173 "Unary '%s' not supported in compile-time expression"
3174 % self.operator)
3175 operand = self.operand.compile_time_value(denv)
3176 try:
3177 return func(operand)
3178 except Exception, e:
3179 self.compile_time_value_error(e)
3181 def analyse_types(self, env):
3182 self.operand.analyse_types(env)
3183 if self.is_py_operation():
3184 self.coerce_operand_to_pyobject(env)
3185 self.type = py_object_type
3186 self.gil_check(env)
3187 self.is_temp = 1
3188 else:
3189 self.analyse_c_operation(env)
3191 def check_const(self):
3192 self.operand.check_const()
3194 def is_py_operation(self):
3195 return self.operand.type.is_pyobject
3197 def coerce_operand_to_pyobject(self, env):
3198 self.operand = self.operand.coerce_to_pyobject(env)
3200 def generate_result_code(self, code):
3201 if self.operand.type.is_pyobject:
3202 self.generate_py_operation_code(code)
3203 else:
3204 if self.is_temp:
3205 self.generate_c_operation_code(code)
3207 def generate_py_operation_code(self, code):
3208 function = self.py_operation_function()
3209 code.putln(
3210 "%s = %s(%s); %s" % (
3211 self.result(),
3212 function,
3213 self.operand.py_result(),
3214 code.error_goto_if_null(self.result(), self.pos)))
3216 def type_error(self):
3217 if not self.operand.type.is_error:
3218 error(self.pos, "Invalid operand type for '%s' (%s)" %
3219 (self.operator, self.operand.type))
3220 self.type = PyrexTypes.error_type
3223 class NotNode(ExprNode):
3224 # 'not' operator
3226 # operand ExprNode
3228 def compile_time_value(self, denv):
3229 operand = self.operand.compile_time_value(denv)
3230 try:
3231 return not operand
3232 except Exception, e:
3233 self.compile_time_value_error(e)
3235 subexprs = ['operand']
3237 def analyse_types(self, env):
3238 self.operand.analyse_types(env)
3239 self.operand = self.operand.coerce_to_boolean(env)
3240 self.type = PyrexTypes.c_bint_type
3242 def calculate_result_code(self):
3243 return "(!%s)" % self.operand.result()
3245 def generate_result_code(self, code):
3246 pass
3249 class UnaryPlusNode(UnopNode):
3250 # unary '+' operator
3252 operator = '+'
3254 def analyse_c_operation(self, env):
3255 self.type = self.operand.type
3257 def py_operation_function(self):
3258 return "PyNumber_Positive"
3260 def calculate_result_code(self):
3261 return self.operand.result()
3264 class UnaryMinusNode(UnopNode):
3265 # unary '-' operator
3267 operator = '-'
3269 def analyse_c_operation(self, env):
3270 if self.operand.type.is_numeric:
3271 self.type = self.operand.type
3272 else:
3273 self.type_error()
3275 def py_operation_function(self):
3276 return "PyNumber_Negative"
3278 def calculate_result_code(self):
3279 return "(-%s)" % self.operand.result()
3282 class TildeNode(UnopNode):
3283 # unary '~' operator
3285 def analyse_c_operation(self, env):
3286 if self.operand.type.is_int:
3287 self.type = self.operand.type
3288 else:
3289 self.type_error()
3291 def py_operation_function(self):
3292 return "PyNumber_Invert"
3294 def calculate_result_code(self):
3295 return "(~%s)" % self.operand.result()
3298 class AmpersandNode(ExprNode):
3299 # The C address-of operator.
3301 # operand ExprNode
3303 subexprs = ['operand']
3305 def analyse_types(self, env):
3306 self.operand.analyse_types(env)
3307 argtype = self.operand.type
3308 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3309 self.error("Taking address of non-lvalue")
3310 return
3311 if argtype.is_pyobject:
3312 self.error("Cannot take address of Python variable")
3313 return
3314 self.type = PyrexTypes.c_ptr_type(argtype)
3316 def check_const(self):
3317 self.operand.check_const_addr()
3319 def error(self, mess):
3320 error(self.pos, mess)
3321 self.type = PyrexTypes.error_type
3322 self.result_code = "<error>"
3324 def calculate_result_code(self):
3325 return "(&%s)" % self.operand.result()
3327 def generate_result_code(self, code):
3328 pass
3331 unop_node_classes = {
3332 "+": UnaryPlusNode,
3333 "-": UnaryMinusNode,
3334 "~": TildeNode,
3337 def unop_node(pos, operator, operand):
3338 # Construct unnop node of appropriate class for
3339 # given operator.
3340 if isinstance(operand, IntNode) and operator == '-':
3341 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3342 elif isinstance(operand, UnopNode) and operand.operator == operator:
3343 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3344 return unop_node_classes[operator](pos,
3345 operator = operator,
3346 operand = operand)
3349 class TypecastNode(ExprNode):
3350 # C type cast
3352 # operand ExprNode
3353 # base_type CBaseTypeNode
3354 # declarator CDeclaratorNode
3356 # If used from a transform, one can if wanted specify the attribute
3357 # "type" directly and leave base_type and declarator to None
3359 subexprs = ['operand']
3360 base_type = declarator = type = None
3362 def analyse_types(self, env):
3363 if self.type is None:
3364 base_type = self.base_type.analyse(env)
3365 _, self.type = self.declarator.analyse(base_type, env)
3366 if self.type.is_cfunction:
3367 error(self.pos,
3368 "Cannot cast to a function type")
3369 self.type = PyrexTypes.error_type
3370 self.operand.analyse_types(env)
3371 to_py = self.type.is_pyobject
3372 from_py = self.operand.type.is_pyobject
3373 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3374 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3375 if to_py and not from_py:
3376 if (self.operand.type.to_py_function and
3377 self.operand.type.create_convert_utility_code(env)):
3378 self.result_ctype = py_object_type
3379 self.operand = self.operand.coerce_to_pyobject(env)
3380 else:
3381 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3382 self.operand = self.operand.coerce_to_simple(env)
3383 elif from_py and not to_py:
3384 if self.type.from_py_function:
3385 self.operand = self.operand.coerce_to(self.type, env)
3386 else:
3387 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3388 elif from_py and to_py:
3389 if self.typecheck and self.type.is_extension_type:
3390 self.operand = PyTypeTestNode(self.operand, self.type, env)
3392 def check_const(self):
3393 self.operand.check_const()
3395 def calculate_result_code(self):
3396 opnd = self.operand
3397 return self.type.cast_code(opnd.result())
3399 def result_as(self, type):
3400 if self.type.is_pyobject and not self.is_temp:
3401 # Optimise away some unnecessary casting
3402 return self.operand.result_as(type)
3403 else:
3404 return ExprNode.result_as(self, type)
3406 def generate_result_code(self, code):
3407 if self.is_temp:
3408 code.putln(
3409 "%s = (PyObject *)%s;" % (
3410 self.result(),
3411 self.operand.result()))
3412 code.put_incref(self.result(), self.ctype())
3415 class SizeofNode(ExprNode):
3416 # Abstract base class for sizeof(x) expression nodes.
3418 type = PyrexTypes.c_int_type
3420 def check_const(self):
3421 pass
3423 def generate_result_code(self, code):
3424 pass
3427 class SizeofTypeNode(SizeofNode):
3428 # C sizeof function applied to a type
3430 # base_type CBaseTypeNode
3431 # declarator CDeclaratorNode
3433 subexprs = []
3434 arg_type = None
3436 def analyse_types(self, env):
3437 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3438 # this could be better handled by more uniformly treating types as runtime-available objects
3439 if 0 and self.base_type.module_path:
3440 path = self.base_type.module_path
3441 obj = env.lookup(path[0])
3442 if obj.as_module is None:
3443 operand = NameNode(pos=self.pos, name=path[0])
3444 for attr in path[1:]:
3445 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3446 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3447 self.operand = operand
3448 self.__class__ = SizeofVarNode
3449 self.analyse_types(env)
3450 return
3451 if self.arg_type is None:
3452 base_type = self.base_type.analyse(env)
3453 _, arg_type = self.declarator.analyse(base_type, env)
3454 self.arg_type = arg_type
3455 self.check_type()
3457 def check_type(self):
3458 arg_type = self.arg_type
3459 if arg_type.is_pyobject and not arg_type.is_extension_type:
3460 error(self.pos, "Cannot take sizeof Python object")
3461 elif arg_type.is_void:
3462 error(self.pos, "Cannot take sizeof void")
3463 elif not arg_type.is_complete():
3464 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3466 def calculate_result_code(self):
3467 if self.arg_type.is_extension_type:
3468 # the size of the pointer is boring
3469 # we want the size of the actual struct
3470 arg_code = self.arg_type.declaration_code("", deref=1)
3471 else:
3472 arg_code = self.arg_type.declaration_code("")
3473 return "(sizeof(%s))" % arg_code
3476 class SizeofVarNode(SizeofNode):
3477 # C sizeof function applied to a variable
3479 # operand ExprNode
3481 subexprs = ['operand']
3483 def analyse_types(self, env):
3484 # We may actually be looking at a type rather than a variable...
3485 # If we are, traditional analysis would fail...
3486 operand_as_type = self.operand.analyse_as_type(env)
3487 if operand_as_type:
3488 self.arg_type = operand_as_type
3489 self.__class__ = SizeofTypeNode
3490 self.check_type()
3491 else:
3492 self.operand.analyse_types(env)
3494 def calculate_result_code(self):
3495 return "(sizeof(%s))" % self.operand.result()
3497 def generate_result_code(self, code):
3498 pass
3501 #-------------------------------------------------------------------
3503 # Binary operator nodes
3505 #-------------------------------------------------------------------
3507 def _not_in(x, seq):
3508 return x not in seq
3510 compile_time_binary_operators = {
3511 '<': operator.lt,
3512 '<=': operator.le,
3513 '==': operator.eq,
3514 '!=': operator.ne,
3515 '>=': operator.ge,
3516 '>': operator.gt,
3517 'is': operator.is_,
3518 'is_not': operator.is_not,
3519 '+': operator.add,
3520 '&': operator.and_,
3521 '/': operator.div,
3522 '//': operator.floordiv,
3523 '<<': operator.lshift,
3524 '%': operator.mod,
3525 '*': operator.mul,
3526 '|': operator.or_,
3527 '**': operator.pow,
3528 '>>': operator.rshift,
3529 '-': operator.sub,
3530 #'/': operator.truediv,
3531 '^': operator.xor,
3532 'in': operator.contains,
3533 'not_in': _not_in,
3536 def get_compile_time_binop(node):
3537 func = compile_time_binary_operators.get(node.operator)
3538 if not func:
3539 error(node.pos,
3540 "Binary '%s' not supported in compile-time expression"
3541 % node.operator)
3542 return func
3544 class BinopNode(NewTempExprNode):
3545 # operator string
3546 # operand1 ExprNode
3547 # operand2 ExprNode
3549 # Processing during analyse_expressions phase:
3551 # analyse_c_operation
3552 # Called when neither operand is a pyobject.
3553 # - Check operand types and coerce if needed.
3554 # - Determine result type and result code fragment.
3555 # - Allocate temporary for result if needed.
3557 subexprs = ['operand1', 'operand2']
3559 def compile_time_value(self, denv):
3560 func = get_compile_time_binop(self)
3561 operand1 = self.operand1.compile_time_value(denv)
3562 operand2 = self.operand2.compile_time_value(denv)
3563 try:
3564 return func(operand1, operand2)
3565 except Exception, e:
3566 self.compile_time_value_error(e)
3568 def analyse_types(self, env):
3569 self.operand1.analyse_types(env)
3570 self.operand2.analyse_types(env)
3571 if self.is_py_operation():
3572 self.coerce_operands_to_pyobjects(env)
3573 self.type = py_object_type
3574 self.gil_check(env)
3575 self.is_temp = 1
3576 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3577 self.operand1 = self.operand1.coerce_to_temp(env)
3578 else:
3579 self.analyse_c_operation(env)
3581 def is_py_operation(self):
3582 return (self.operand1.type.is_pyobject
3583 or self.operand2.type.is_pyobject)
3585 def coerce_operands_to_pyobjects(self, env):
3586 self.operand1 = self.operand1.coerce_to_pyobject(env)
3587 self.operand2 = self.operand2.coerce_to_pyobject(env)
3589 def check_const(self):
3590 self.operand1.check_const()
3591 self.operand2.check_const()
3593 def generate_result_code(self, code):
3594 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3595 if self.operand1.type.is_pyobject:
3596 function = self.py_operation_function()
3597 if function == "PyNumber_Power":
3598 extra_args = ", Py_None"
3599 else:
3600 extra_args = ""
3601 code.putln(
3602 "%s = %s(%s, %s%s); %s" % (
3603 self.result(),
3604 function,
3605 self.operand1.py_result(),
3606 self.operand2.py_result(),
3607 extra_args,
3608 code.error_goto_if_null(self.result(), self.pos)))
3609 else:
3610 if self.is_temp:
3611 self.generate_c_operation_code(code)
3613 def type_error(self):
3614 if not (self.operand1.type.is_error
3615 or self.operand2.type.is_error):
3616 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3617 (self.operator, self.operand1.type,
3618 self.operand2.type))
3619 self.type = PyrexTypes.error_type
3622 class NumBinopNode(BinopNode):
3623 # Binary operation taking numeric arguments.
3625 def analyse_c_operation(self, env):
3626 type1 = self.operand1.type
3627 type2 = self.operand2.type
3628 if self.operator == "**" and type1.is_int and type2.is_int:
3629 error(self.pos, "** with two C int types is ambiguous")
3630 self.type = error_type
3631 return
3632 self.type = self.compute_c_result_type(type1, type2)
3633 if not self.type:
3634 self.type_error()
3636 def compute_c_result_type(self, type1, type2):
3637 if self.c_types_okay(type1, type2):
3638 return PyrexTypes.widest_numeric_type(type1, type2)
3639 else:
3640 return None
3642 def c_types_okay(self, type1, type2):
3643 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3644 return (type1.is_numeric or type1.is_enum) \
3645 and (type2.is_numeric or type2.is_enum)
3647 def calculate_result_code(self):
3648 return "(%s %s %s)" % (
3649 self.operand1.result(),
3650 self.operator,
3651 self.operand2.result())
3653 def py_operation_function(self):
3654 return self.py_functions[self.operator]
3656 py_functions = {
3657 "|": "PyNumber_Or",
3658 "^": "PyNumber_Xor",
3659 "&": "PyNumber_And",
3660 "<<": "PyNumber_Lshift",
3661 ">>": "PyNumber_Rshift",
3662 "+": "PyNumber_Add",
3663 "-": "PyNumber_Subtract",
3664 "*": "PyNumber_Multiply",
3665 "/": "__Pyx_PyNumber_Divide",
3666 "//": "PyNumber_FloorDivide",
3667 "%": "PyNumber_Remainder",
3668 "**": "PyNumber_Power"
3672 class IntBinopNode(NumBinopNode):
3673 # Binary operation taking integer arguments.
3675 def c_types_okay(self, type1, type2):
3676 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3677 return (type1.is_int or type1.is_enum) \
3678 and (type2.is_int or type2.is_enum)
3681 class AddNode(NumBinopNode):
3682 # '+' operator.
3684 def is_py_operation(self):
3685 if self.operand1.type.is_string \
3686 and self.operand2.type.is_string:
3687 return 1
3688 else:
3689 return NumBinopNode.is_py_operation(self)
3691 def compute_c_result_type(self, type1, type2):
3692 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3693 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3694 return type1
3695 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3696 return type2
3697 else:
3698 return NumBinopNode.compute_c_result_type(
3699 self, type1, type2)
3702 class SubNode(NumBinopNode):
3703 # '-' operator.
3705 def compute_c_result_type(self, type1, type2):
3706 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3707 return type1
3708 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3709 return PyrexTypes.c_int_type
3710 else:
3711 return NumBinopNode.compute_c_result_type(
3712 self, type1, type2)
3715 class MulNode(NumBinopNode):
3716 # '*' operator.
3718 def is_py_operation(self):
3719 type1 = self.operand1.type
3720 type2 = self.operand2.type
3721 if (type1.is_string and type2.is_int) \
3722 or (type2.is_string and type1.is_int):
3723 return 1
3724 else:
3725 return NumBinopNode.is_py_operation(self)
3728 class FloorDivNode(NumBinopNode):
3729 # '//' operator.
3731 def calculate_result_code(self):
3732 return "(%s %s %s)" % (
3733 self.operand1.result(),
3734 "/", # c division is by default floor-div
3735 self.operand2.result())
3738 class ModNode(NumBinopNode):
3739 # '%' operator.
3741 def is_py_operation(self):
3742 return (self.operand1.type.is_string
3743 or self.operand2.type.is_string
3744 or NumBinopNode.is_py_operation(self))
3746 def calculate_result_code(self):
3747 if self.operand1.type.is_float or self.operand2.type.is_float:
3748 return "fmod(%s, %s)" % (
3749 self.operand1.result(),
3750 self.operand2.result())
3751 else:
3752 return "(%s %% %s)" % (
3753 self.operand1.result(),
3754 self.operand2.result())
3756 class PowNode(NumBinopNode):
3757 # '**' operator.
3759 def compute_c_result_type(self, type1, type2):
3760 if self.c_types_okay(type1, type2):
3761 return PyrexTypes.c_double_type
3762 else:
3763 return None
3765 def c_types_okay(self, type1, type2):
3766 return (type1.is_float or type2.is_float) and \
3767 NumBinopNode.c_types_okay(self, type1, type2)
3769 def type_error(self):
3770 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3771 if self.operand1.type.is_int and self.operand2.type.is_int:
3772 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3773 (self.operator, self.operand1.type, self.operand2.type))
3774 else:
3775 NumBinopNode.type_error(self)
3776 self.type = PyrexTypes.error_type
3778 def calculate_result_code(self):
3779 return "pow(%s, %s)" % (
3780 self.operand1.result(), self.operand2.result())
3783 class BoolBinopNode(ExprNode):
3784 # Short-circuiting boolean operation.
3786 # operator string
3787 # operand1 ExprNode
3788 # operand2 ExprNode
3789 # temp_bool ExprNode used internally
3791 temp_bool = None
3793 subexprs = ['operand1', 'operand2', 'temp_bool']
3795 def compile_time_value(self, denv):
3796 if self.operator == 'and':
3797 return self.operand1.compile_time_value(denv) \
3798 and self.operand2.compile_time_value(denv)
3799 else:
3800 return self.operand1.compile_time_value(denv) \
3801 or self.operand2.compile_time_value(denv)
3803 def coerce_to_boolean(self, env):
3804 self.operand1 = self.operand1.coerce_to_boolean(env)
3805 self.operand2 = self.operand2.coerce_to_boolean(env)
3806 self.type = PyrexTypes.c_bint_type
3807 return self
3809 def analyse_types(self, env):
3810 self.operand1.analyse_types(env)
3811 self.operand2.analyse_types(env)
3812 if self.operand1.type.is_pyobject or \
3813 self.operand2.type.is_pyobject:
3814 self.operand1 = self.operand1.coerce_to_pyobject(env)
3815 self.operand2 = self.operand2.coerce_to_pyobject(env)
3816 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3817 self.type = py_object_type
3818 self.gil_check(env)
3819 else:
3820 self.operand1 = self.operand1.coerce_to_boolean(env)
3821 self.operand2 = self.operand2.coerce_to_boolean(env)
3822 self.type = PyrexTypes.c_bint_type
3823 # For what we're about to do, it's vital that
3824 # both operands be temp nodes.
3825 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3826 self.operand2 = self.operand2.coerce_to_temp(env)
3827 self.is_temp = 1
3829 gil_message = "Truth-testing Python object"
3831 def allocate_temps(self, env, result_code = None):
3832 # We don't need both operands at the same time, and
3833 # one of the operands will also be our result. So we
3834 # use an allocation strategy here which results in
3835 # this node and both its operands sharing the same
3836 # result variable. This allows us to avoid some
3837 # assignments and increfs/decrefs that would otherwise
3838 # be necessary.
3839 self.allocate_temp(env, result_code)
3840 self.operand1.allocate_temps(env, self.result())
3841 if self.temp_bool:
3842 self.temp_bool.allocate_temp(env)
3843 self.temp_bool.release_temp(env)
3844 self.operand2.allocate_temps(env, self.result())
3845 # We haven't called release_temp on either operand,
3846 # because although they are temp nodes, they don't own
3847 # their result variable. And because they are temp
3848 # nodes, any temps in their subnodes will have been
3849 # released before their allocate_temps returned.
3850 # Therefore, they contain no temp vars that need to
3851 # be released.
3853 def check_const(self):
3854 self.operand1.check_const()
3855 self.operand2.check_const()
3857 def calculate_result_code(self):
3858 return "(%s %s %s)" % (
3859 self.operand1.result(),
3860 self.py_to_c_op[self.operator],
3861 self.operand2.result())
3863 py_to_c_op = {'and': "&&", 'or': "||"}
3865 def generate_evaluation_code(self, code):
3866 self.operand1.generate_evaluation_code(code)
3867 test_result = self.generate_operand1_test(code)
3868 if self.operator == 'and':
3869 sense = ""
3870 else:
3871 sense = "!"
3872 code.putln(
3873 "if (%s%s) {" % (
3874 sense,
3875 test_result))
3876 self.operand1.generate_disposal_code(code)
3877 self.operand2.generate_evaluation_code(code)
3878 code.putln(
3879 "}")
3881 def generate_operand1_test(self, code):
3882 # Generate code to test the truth of the first operand.
3883 if self.type.is_pyobject:
3884 test_result = self.temp_bool.result()
3885 code.putln(
3886 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3887 test_result,
3888 self.operand1.py_result(),
3889 code.error_goto_if_neg(test_result, self.pos)))
3890 else:
3891 test_result = self.operand1.result()
3892 return test_result
3895 class CondExprNode(ExprNode):
3896 # Short-circuiting conditional expression.
3898 # test ExprNode
3899 # true_val ExprNode
3900 # false_val ExprNode
3902 temp_bool = None
3903 true_val = None
3904 false_val = None
3906 subexprs = ['test', 'true_val', 'false_val']
3908 def analyse_types(self, env):
3909 self.test.analyse_types(env)
3910 self.test = self.test.coerce_to_boolean(env)
3911 self.true_val.analyse_types(env)
3912 self.false_val.analyse_types(env)
3913 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3914 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3915 self.true_val = self.true_val.coerce_to(self.type, env)
3916 self.false_val = self.false_val.coerce_to(self.type, env)
3917 # must be tmp variables so they can share a result
3918 self.true_val = self.true_val.coerce_to_temp(env)
3919 self.false_val = self.false_val.coerce_to_temp(env)
3920 self.is_temp = 1
3921 if self.type == PyrexTypes.error_type:
3922 self.type_error()
3924 def allocate_temps(self, env, result_code = None):
3925 # We only ever evaluate one side, and this is
3926 # after evaluating the truth value, so we may
3927 # use an allocation strategy here which results in
3928 # this node and both its operands sharing the same
3929 # result variable. This allows us to avoid some
3930 # assignments and increfs/decrefs that would otherwise
3931 # be necessary.
3932 self.allocate_temp(env, result_code)
3933 self.test.allocate_temps(env, result_code)
3934 self.true_val.allocate_temps(env, self.result())
3935 self.false_val.allocate_temps(env, self.result())
3936 # We haven't called release_temp on either value,
3937 # because although they are temp nodes, they don't own
3938 # their result variable. And because they are temp
3939 # nodes, any temps in their subnodes will have been
3940 # released before their allocate_temps returned.
3941 # Therefore, they contain no temp vars that need to
3942 # be released.
3944 def compute_result_type(self, type1, type2):
3945 if type1 == type2:
3946 return type1
3947 elif type1.is_numeric and type2.is_numeric:
3948 return PyrexTypes.widest_numeric_type(type1, type2)
3949 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3950 return type2
3951 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3952 return type1
3953 elif type1.is_pyobject or type2.is_pyobject:
3954 return py_object_type
3955 elif type1.assignable_from(type2):
3956 return type1
3957 elif type2.assignable_from(type1):
3958 return type2
3959 else:
3960 return PyrexTypes.error_type
3962 def type_error(self):
3963 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3964 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3965 (self.true_val.type, self.false_val.type))
3966 self.type = PyrexTypes.error_type
3968 def check_const(self):
3969 self.test.check_const()
3970 self.true_val.check_const()
3971 self.false_val.check_const()
3973 def generate_evaluation_code(self, code):
3974 self.test.generate_evaluation_code(code)
3975 code.putln("if (%s) {" % self.test.result() )
3976 self.true_val.generate_evaluation_code(code)
3977 code.putln("} else {")
3978 self.false_val.generate_evaluation_code(code)
3979 code.putln("}")
3980 self.test.generate_disposal_code(code)
3982 richcmp_constants = {
3983 "<" : "Py_LT",
3984 "<=": "Py_LE",
3985 "==": "Py_EQ",
3986 "!=": "Py_NE",
3987 "<>": "Py_NE",
3988 ">" : "Py_GT",
3989 ">=": "Py_GE",
3992 class CmpNode:
3993 # Mixin class containing code common to PrimaryCmpNodes
3994 # and CascadedCmpNodes.
3996 def cascaded_compile_time_value(self, operand1, denv):
3997 func = get_compile_time_binop(self)
3998 operand2 = self.operand2.compile_time_value(denv)
3999 try:
4000 result = func(operand1, operand2)
4001 except Exception, e:
4002 self.compile_time_value_error(e)
4003 result = None
4004 if result:
4005 cascade = self.cascade
4006 if cascade:
4007 result = result and cascade.compile_time_value(operand2, denv)
4008 return result
4010 def is_python_comparison(self):
4011 return (self.has_python_operands()
4012 or (self.cascade and self.cascade.is_python_comparison())
4013 or self.operator in ('in', 'not_in'))
4015 def is_python_result(self):
4016 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4017 or (self.cascade and self.cascade.is_python_result()))
4019 def check_types(self, env, operand1, op, operand2):
4020 if not self.types_okay(operand1, op, operand2):
4021 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4022 (self.operator, operand1.type, operand2.type))
4024 def types_okay(self, operand1, op, operand2):
4025 type1 = operand1.type
4026 type2 = operand2.type
4027 if type1.is_error or type2.is_error:
4028 return 1
4029 if type1.is_pyobject: # type2 will be, too
4030 return 1
4031 elif type1.is_ptr or type1.is_array:
4032 return type1.is_null_ptr or type2.is_null_ptr \
4033 or ((type2.is_ptr or type2.is_array)
4034 and type1.base_type.same_as(type2.base_type))
4035 elif ((type1.is_numeric and type2.is_numeric
4036 or type1.is_enum and (type1 is type2 or type2.is_int)
4037 or type1.is_int and type2.is_enum)
4038 and op not in ('is', 'is_not')):
4039 return 1
4040 else:
4041 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4043 def generate_operation_code(self, code, result_code,
4044 operand1, op , operand2):
4045 if self.type is PyrexTypes.py_object_type:
4046 coerce_result = "__Pyx_PyBool_FromLong"
4047 else:
4048 coerce_result = ""
4049 if 'not' in op: negation = "!"
4050 else: negation = ""
4051 if op == 'in' or op == 'not_in':
4052 code.putln(
4053 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4054 result_code,
4055 coerce_result,
4056 negation,
4057 operand2.py_result(),
4058 operand1.py_result(),
4059 code.error_goto_if_neg(result_code, self.pos)))
4060 elif (operand1.type.is_pyobject
4061 and op not in ('is', 'is_not')):
4062 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4063 result_code,
4064 operand1.py_result(),
4065 operand2.py_result(),
4066 richcmp_constants[op],
4067 code.error_goto_if_null(result_code, self.pos)))
4068 else:
4069 type1 = operand1.type
4070 type2 = operand2.type
4071 if (type1.is_extension_type or type2.is_extension_type) \
4072 and not type1.same_as(type2):
4073 common_type = py_object_type
4074 elif type1.is_numeric:
4075 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4076 else:
4077 common_type = type1
4078 code1 = operand1.result_as(common_type)
4079 code2 = operand2.result_as(common_type)
4080 code.putln("%s = %s(%s %s %s);" % (
4081 result_code,
4082 coerce_result,
4083 code1,
4084 self.c_operator(op),
4085 code2))
4087 def c_operator(self, op):
4088 if op == 'is':
4089 return "=="
4090 elif op == 'is_not':
4091 return "!="
4092 else:
4093 return op
4096 class PrimaryCmpNode(ExprNode, CmpNode):
4097 # Non-cascaded comparison or first comparison of
4098 # a cascaded sequence.
4100 # operator string
4101 # operand1 ExprNode
4102 # operand2 ExprNode
4103 # cascade CascadedCmpNode
4105 # We don't use the subexprs mechanism, because
4106 # things here are too complicated for it to handle.
4107 # Instead, we override all the framework methods
4108 # which use it.
4110 child_attrs = ['operand1', 'operand2', 'cascade']
4112 cascade = None
4114 def compile_time_value(self, denv):
4115 operand1 = self.operand1.compile_time_value(denv)
4116 return self.cascaded_compile_time_value(operand1, denv)
4118 def analyse_types(self, env):
4119 self.operand1.analyse_types(env)
4120 self.operand2.analyse_types(env)
4121 if self.cascade:
4122 self.cascade.analyse_types(env, self.operand2)
4123 self.is_pycmp = self.is_python_comparison()
4124 if self.is_pycmp:
4125 self.coerce_operands_to_pyobjects(env)
4126 if self.has_int_operands():
4127 self.coerce_chars_to_ints(env)
4128 if self.cascade:
4129 self.operand2 = self.operand2.coerce_to_simple(env)
4130 self.cascade.coerce_cascaded_operands_to_temp(env)
4131 self.check_operand_types(env)
4132 if self.is_python_result():
4133 self.type = PyrexTypes.py_object_type
4134 else:
4135 self.type = PyrexTypes.c_bint_type
4136 cdr = self.cascade
4137 while cdr:
4138 cdr.type = self.type
4139 cdr = cdr.cascade
4140 if self.is_pycmp or self.cascade:
4141 self.is_temp = 1
4143 def check_operand_types(self, env):
4144 self.check_types(env,
4145 self.operand1, self.operator, self.operand2)
4146 if self.cascade:
4147 self.cascade.check_operand_types(env, self.operand2)
4149 def has_python_operands(self):
4150 return (self.operand1.type.is_pyobject
4151 or self.operand2.type.is_pyobject)
4153 def coerce_operands_to_pyobjects(self, env):
4154 self.operand1 = self.operand1.coerce_to_pyobject(env)
4155 self.operand2 = self.operand2.coerce_to_pyobject(env)
4156 if self.cascade:
4157 self.cascade.coerce_operands_to_pyobjects(env)
4159 def has_int_operands(self):
4160 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4161 or (self.cascade and self.cascade.has_int_operands())
4163 def coerce_chars_to_ints(self, env):
4164 # coerce literal single-char strings to c chars
4165 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4166 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4167 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4168 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4169 if self.cascade:
4170 self.cascade.coerce_chars_to_ints(env)
4172 def allocate_subexpr_temps(self, env):
4173 self.operand1.allocate_temps(env)
4174 self.operand2.allocate_temps(env)
4175 if self.cascade:
4176 self.cascade.allocate_subexpr_temps(env)
4178 def release_subexpr_temps(self, env):
4179 self.operand1.release_temp(env)
4180 self.operand2.release_temp(env)
4181 if self.cascade:
4182 self.cascade.release_subexpr_temps(env)
4184 def check_const(self):
4185 self.operand1.check_const()
4186 self.operand2.check_const()
4187 if self.cascade:
4188 self.not_const()
4190 def calculate_result_code(self):
4191 return "(%s %s %s)" % (
4192 self.operand1.result(),
4193 self.c_operator(self.operator),
4194 self.operand2.result())
4196 def generate_evaluation_code(self, code):
4197 self.operand1.generate_evaluation_code(code)
4198 self.operand2.generate_evaluation_code(code)
4199 if self.is_temp:
4200 self.generate_operation_code(code, self.result(),
4201 self.operand1, self.operator, self.operand2)
4202 if self.cascade:
4203 self.cascade.generate_evaluation_code(code,
4204 self.result(), self.operand2)
4205 self.operand1.generate_disposal_code(code)
4206 self.operand2.generate_disposal_code(code)
4208 def generate_subexpr_disposal_code(self, code):
4209 # If this is called, it is a non-cascaded cmp,
4210 # so only need to dispose of the two main operands.
4211 self.operand1.generate_disposal_code(code)
4212 self.operand2.generate_disposal_code(code)
4214 def annotate(self, code):
4215 self.operand1.annotate(code)
4216 self.operand2.annotate(code)
4217 if self.cascade:
4218 self.cascade.annotate(code)
4221 class CascadedCmpNode(Node, CmpNode):
4222 # A CascadedCmpNode is not a complete expression node. It
4223 # hangs off the side of another comparison node, shares
4224 # its left operand with that node, and shares its result
4225 # with the PrimaryCmpNode at the head of the chain.
4227 # operator string
4228 # operand2 ExprNode
4229 # cascade CascadedCmpNode
4231 child_attrs = ['operand2', 'cascade']
4233 cascade = None
4235 def analyse_types(self, env, operand1):
4236 self.operand2.analyse_types(env)
4237 if self.cascade:
4238 self.cascade.analyse_types(env, self.operand2)
4240 def check_operand_types(self, env, operand1):
4241 self.check_types(env,
4242 operand1, self.operator, self.operand2)
4243 if self.cascade:
4244 self.cascade.check_operand_types(env, self.operand2)
4246 def has_python_operands(self):
4247 return self.operand2.type.is_pyobject
4249 def coerce_operands_to_pyobjects(self, env):
4250 self.operand2 = self.operand2.coerce_to_pyobject(env)
4251 if self.cascade:
4252 self.cascade.coerce_operands_to_pyobjects(env)
4254 def has_int_operands(self):
4255 return self.operand2.type.is_int
4257 def coerce_chars_to_ints(self, env):
4258 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4259 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4261 def coerce_cascaded_operands_to_temp(self, env):
4262 if self.cascade:
4263 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4264 self.operand2 = self.operand2.coerce_to_simple(env)
4265 self.cascade.coerce_cascaded_operands_to_temp(env)
4267 def allocate_subexpr_temps(self, env):
4268 self.operand2.allocate_temps(env)
4269 if self.cascade:
4270 self.cascade.allocate_subexpr_temps(env)
4272 def release_subexpr_temps(self, env):
4273 self.operand2.release_temp(env)
4274 if self.cascade:
4275 self.cascade.release_subexpr_temps(env)
4277 def generate_evaluation_code(self, code, result, operand1):
4278 if self.type.is_pyobject:
4279 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4280 else:
4281 code.putln("if (%s) {" % result)
4282 self.operand2.generate_evaluation_code(code)
4283 self.generate_operation_code(code, result,
4284 operand1, self.operator, self.operand2)
4285 if self.cascade:
4286 self.cascade.generate_evaluation_code(
4287 code, result, self.operand2)
4288 # Cascaded cmp result is always temp
4289 self.operand2.generate_disposal_code(code)
4290 code.putln("}")
4292 def annotate(self, code):
4293 self.operand2.annotate(code)
4294 if self.cascade:
4295 self.cascade.annotate(code)
4298 binop_node_classes = {
4299 "or": BoolBinopNode,
4300 "and": BoolBinopNode,
4301 "|": IntBinopNode,
4302 "^": IntBinopNode,
4303 "&": IntBinopNode,
4304 "<<": IntBinopNode,
4305 ">>": IntBinopNode,
4306 "+": AddNode,
4307 "-": SubNode,
4308 "*": MulNode,
4309 "/": NumBinopNode,
4310 "//": FloorDivNode,
4311 "%": ModNode,
4312 "**": PowNode
4315 def binop_node(pos, operator, operand1, operand2):
4316 # Construct binop node of appropriate class for
4317 # given operator.
4318 return binop_node_classes[operator](pos,
4319 operator = operator,
4320 operand1 = operand1,
4321 operand2 = operand2)
4323 #-------------------------------------------------------------------
4325 # Coercion nodes
4327 # Coercion nodes are special in that they are created during
4328 # the analyse_types phase of parse tree processing.
4329 # Their __init__ methods consequently incorporate some aspects
4330 # of that phase.
4332 #-------------------------------------------------------------------
4334 class CoercionNode(ExprNode):
4335 # Abstract base class for coercion nodes.
4337 # arg ExprNode node being coerced
4339 subexprs = ['arg']
4341 def __init__(self, arg):
4342 self.pos = arg.pos
4343 self.arg = arg
4344 if debug_coercion:
4345 print("%s Coercing %s" % (self, self.arg))
4347 def annotate(self, code):
4348 self.arg.annotate(code)
4349 if self.arg.type != self.type:
4350 file, line, col = self.pos
4351 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4354 class CastNode(CoercionNode):
4355 # Wrap a node in a C type cast.
4357 def __init__(self, arg, new_type):
4358 CoercionNode.__init__(self, arg)
4359 self.type = new_type
4361 def calculate_result_code(self):
4362 return self.arg.result_as(self.type)
4364 def generate_result_code(self, code):
4365 self.arg.generate_result_code(code)
4368 class PyTypeTestNode(CoercionNode):
4369 # This node is used to check that a generic Python
4370 # object is an instance of a particular extension type.
4371 # This node borrows the result of its argument node.
4373 def __init__(self, arg, dst_type, env):
4374 # The arg is know to be a Python object, and
4375 # the dst_type is known to be an extension type.
4376 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4377 CoercionNode.__init__(self, arg)
4378 self.type = dst_type
4379 self.gil_check(env)
4380 self.result_ctype = arg.ctype()
4381 if not dst_type.is_builtin_type:
4382 env.use_utility_code(type_test_utility_code)
4384 gil_message = "Python type test"
4386 def analyse_types(self, env):
4387 pass
4389 def result_in_temp(self):
4390 return self.arg.result_in_temp()
4392 def is_ephemeral(self):
4393 return self.arg.is_ephemeral()
4395 def calculate_result_code(self):
4396 return self.arg.result()
4398 def generate_result_code(self, code):
4399 if self.type.typeobj_is_available():
4400 code.putln(
4401 "if (!(%s)) %s" % (
4402 self.type.type_test_code(self.arg.py_result()),
4403 code.error_goto(self.pos)))
4404 else:
4405 error(self.pos, "Cannot test type of extern C class "
4406 "without type object name specification")
4408 def generate_post_assignment_code(self, code):
4409 self.arg.generate_post_assignment_code(code)
4412 class CoerceToPyTypeNode(CoercionNode):
4413 # This node is used to convert a C data type
4414 # to a Python object.
4416 def __init__(self, arg, env):
4417 CoercionNode.__init__(self, arg)
4418 self.type = py_object_type
4419 self.gil_check(env)
4420 self.is_temp = 1
4421 if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
4422 error(arg.pos,
4423 "Cannot convert '%s' to Python object" % arg.type)
4425 gil_message = "Converting to Python object"
4427 def coerce_to_boolean(self, env):
4428 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
4430 def analyse_types(self, env):
4431 # The arg is always already analysed
4432 pass
4434 def generate_result_code(self, code):
4435 function = self.arg.type.to_py_function
4436 code.putln('%s = %s(%s); %s' % (
4437 self.result(),
4438 function,
4439 self.arg.result(),
4440 code.error_goto_if_null(self.result(), self.pos)))
4443 class CoerceFromPyTypeNode(CoercionNode):
4444 # This node is used to convert a Python object
4445 # to a C data type.
4447 def __init__(self, result_type, arg, env):
4448 CoercionNode.__init__(self, arg)
4449 self.type = result_type
4450 self.is_temp = 1
4451 if not result_type.from_py_function:
4452 error(arg.pos,
4453 "Cannot convert Python object to '%s'" % result_type)
4454 if self.type.is_string and self.arg.is_ephemeral():
4455 error(arg.pos,
4456 "Obtaining char * from temporary Python value")
4458 def analyse_types(self, env):
4459 # The arg is always already analysed
4460 pass
4462 def generate_result_code(self, code):
4463 function = self.type.from_py_function
4464 operand = self.arg.py_result()
4465 rhs = "%s(%s)" % (function, operand)
4466 if self.type.is_enum:
4467 rhs = typecast(self.type, c_long_type, rhs)
4468 code.putln('%s = %s; %s' % (
4469 self.result(),
4470 rhs,
4471 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4474 class CoerceToBooleanNode(CoercionNode):
4475 # This node is used when a result needs to be used
4476 # in a boolean context.
4478 def __init__(self, arg, env):
4479 CoercionNode.__init__(self, arg)
4480 self.type = PyrexTypes.c_bint_type
4481 if arg.type.is_pyobject:
4482 if env.nogil:
4483 self.gil_error()
4484 self.is_temp = 1
4486 gil_message = "Truth-testing Python object"
4488 def check_const(self):
4489 if self.is_temp:
4490 self.not_const()
4491 self.arg.check_const()
4493 def calculate_result_code(self):
4494 return "(%s != 0)" % self.arg.result()
4496 def generate_result_code(self, code):
4497 if self.arg.type.is_pyobject:
4498 code.putln(
4499 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4500 self.result(),
4501 self.arg.py_result(),
4502 code.error_goto_if_neg(self.result(), self.pos)))
4505 class CoerceToTempNode(CoercionNode):
4506 # This node is used to force the result of another node
4507 # to be stored in a temporary. It is only used if the
4508 # argument node's result is not already in a temporary.
4510 def __init__(self, arg, env):
4511 CoercionNode.__init__(self, arg)
4512 self.type = self.arg.type
4513 self.is_temp = 1
4514 if self.type.is_pyobject:
4515 self.gil_check(env)
4516 self.result_ctype = py_object_type
4518 gil_message = "Creating temporary Python reference"
4520 def analyse_types(self, env):
4521 # The arg is always already analysed
4522 pass
4524 def coerce_to_boolean(self, env):
4525 self.arg = self.arg.coerce_to_boolean(env)
4526 self.type = self.arg.type
4527 self.result_ctype = self.type
4528 return self
4530 def generate_result_code(self, code):
4531 #self.arg.generate_evaluation_code(code) # Already done
4532 # by generic generate_subexpr_evaluation_code!
4533 code.putln("%s = %s;" % (
4534 self.result(), self.arg.result_as(self.ctype())))
4535 if self.type.is_pyobject:
4536 code.put_incref(self.result(), self.ctype())
4539 class CloneNode(CoercionNode):
4540 # This node is employed when the result of another node needs
4541 # to be used multiple times. The argument node's result must
4542 # be in a temporary. This node "borrows" the result from the
4543 # argument node, and does not generate any evaluation or
4544 # disposal code for it. The original owner of the argument
4545 # node is responsible for doing those things.
4547 subexprs = [] # Arg is not considered a subexpr
4549 def __init__(self, arg):
4550 CoercionNode.__init__(self, arg)
4551 if hasattr(arg, 'type'):
4552 self.type = arg.type
4553 self.result_ctype = arg.result_ctype
4554 if hasattr(arg, 'entry'):
4555 self.entry = arg.entry
4557 def result(self):
4558 return self.arg.result()
4560 def analyse_types(self, env):
4561 self.type = self.arg.type
4562 self.result_ctype = self.arg.result_ctype
4563 self.is_temp = 1
4564 if hasattr(self.arg, 'entry'):
4565 self.entry = self.arg.entry
4567 def generate_evaluation_code(self, code):
4568 pass
4570 def generate_result_code(self, code):
4571 pass
4573 def generate_disposal_code(self, code):
4574 pass
4576 def allocate_temps(self, env):
4577 pass
4579 def release_temp(self, env):
4580 pass
4582 class PersistentNode(ExprNode):
4583 # A PersistentNode is like a CloneNode except it handles the temporary
4584 # allocation itself by keeping track of the number of times it has been
4585 # used.
4587 subexprs = ["arg"]
4588 temp_counter = 0
4589 generate_counter = 0
4590 analyse_counter = 0
4591 result_code = None
4593 def __init__(self, arg, uses):
4594 self.pos = arg.pos
4595 self.arg = arg
4596 self.uses = uses
4598 def analyse_types(self, env):
4599 if self.analyse_counter == 0:
4600 self.arg.analyse_types(env)
4601 self.type = self.arg.type
4602 self.result_ctype = self.arg.result_ctype
4603 self.is_temp = 1
4604 self.analyse_counter += 1
4606 def calculate_result_code(self):
4607 return self.result()
4609 def generate_evaluation_code(self, code):
4610 if self.generate_counter == 0:
4611 self.arg.generate_evaluation_code(code)
4612 code.putln("%s = %s;" % (
4613 self.result(), self.arg.result_as(self.ctype())))
4614 if self.type.is_pyobject:
4615 code.put_incref(self.result(), self.ctype())
4616 self.arg.generate_disposal_code(code)
4617 self.generate_counter += 1
4619 def generate_disposal_code(self, code):
4620 if self.generate_counter == self.uses:
4621 if self.type.is_pyobject:
4622 code.put_decref_clear(self.result(), self.ctype())
4624 def allocate_temps(self, env, result=None):
4625 if self.temp_counter == 0:
4626 self.arg.allocate_temps(env)
4627 self.allocate_temp(env, result)
4628 self.arg.release_temp(env)
4629 self.temp_counter += 1
4631 def allocate_temp(self, env, result=None):
4632 if result is None:
4633 self.result_code = env.allocate_temp(self.type)
4634 else:
4635 self.result_code = result
4637 def release_temp(self, env):
4638 if self.temp_counter == self.uses:
4639 env.release_temp(self.result())
4641 #------------------------------------------------------------------------------------
4643 # Runtime support code
4645 #------------------------------------------------------------------------------------
4647 get_name_interned_utility_code = UtilityCode(
4648 proto = """
4649 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4650 """,
4651 impl = """
4652 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4653 PyObject *result;
4654 result = PyObject_GetAttr(dict, name);
4655 if (!result)
4656 PyErr_SetObject(PyExc_NameError, name);
4657 return result;
4659 """)
4661 #------------------------------------------------------------------------------------
4663 import_utility_code = UtilityCode(
4664 proto = """
4665 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4666 """,
4667 impl = """
4668 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4669 PyObject *__import__ = 0;
4670 PyObject *empty_list = 0;
4671 PyObject *module = 0;
4672 PyObject *global_dict = 0;
4673 PyObject *empty_dict = 0;
4674 PyObject *list;
4675 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4676 if (!__import__)
4677 goto bad;
4678 if (from_list)
4679 list = from_list;
4680 else {
4681 empty_list = PyList_New(0);
4682 if (!empty_list)
4683 goto bad;
4684 list = empty_list;
4686 global_dict = PyModule_GetDict(%(GLOBALS)s);
4687 if (!global_dict)
4688 goto bad;
4689 empty_dict = PyDict_New();
4690 if (!empty_dict)
4691 goto bad;
4692 module = PyObject_CallFunction(__import__, "OOOO",
4693 name, global_dict, empty_dict, list);
4694 bad:
4695 Py_XDECREF(empty_list);
4696 Py_XDECREF(__import__);
4697 Py_XDECREF(empty_dict);
4698 return module;
4700 """ % {
4701 "BUILTINS": Naming.builtins_cname,
4702 "GLOBALS": Naming.module_cname,
4703 })
4705 #------------------------------------------------------------------------------------
4707 get_exception_utility_code = UtilityCode(
4708 proto = """
4709 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4710 """,
4711 impl = """
4712 static PyObject *__Pyx_GetExcValue(void) {
4713 PyObject *type = 0, *value = 0, *tb = 0;
4714 PyObject *tmp_type, *tmp_value, *tmp_tb;
4715 PyObject *result = 0;
4716 PyThreadState *tstate = PyThreadState_Get();
4717 PyErr_Fetch(&type, &value, &tb);
4718 PyErr_NormalizeException(&type, &value, &tb);
4719 if (PyErr_Occurred())
4720 goto bad;
4721 if (!value) {
4722 value = Py_None;
4723 Py_INCREF(value);
4725 tmp_type = tstate->exc_type;
4726 tmp_value = tstate->exc_value;
4727 tmp_tb = tstate->exc_traceback;
4728 tstate->exc_type = type;
4729 tstate->exc_value = value;
4730 tstate->exc_traceback = tb;
4731 /* Make sure tstate is in a consistent state when we XDECREF
4732 these objects (XDECREF may run arbitrary code). */
4733 Py_XDECREF(tmp_type);
4734 Py_XDECREF(tmp_value);
4735 Py_XDECREF(tmp_tb);
4736 result = value;
4737 Py_XINCREF(result);
4738 type = 0;
4739 value = 0;
4740 tb = 0;
4741 bad:
4742 Py_XDECREF(type);
4743 Py_XDECREF(value);
4744 Py_XDECREF(tb);
4745 return result;
4747 """)
4749 #------------------------------------------------------------------------------------
4751 unpacking_utility_code = UtilityCode(
4752 proto = """
4753 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4754 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4755 """,
4756 impl = """
4757 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4758 PyObject *item;
4759 if (!(item = PyIter_Next(iter))) {
4760 if (!PyErr_Occurred()) {
4761 PyErr_Format(PyExc_ValueError,
4762 #if PY_VERSION_HEX < 0x02050000
4763 "need more than %d values to unpack", (int)index);
4764 #else
4765 "need more than %zd values to unpack", index);
4766 #endif
4769 return item;
4772 static int __Pyx_EndUnpack(PyObject *iter) {
4773 PyObject *item;
4774 if ((item = PyIter_Next(iter))) {
4775 Py_DECREF(item);
4776 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4777 return -1;
4779 else if (!PyErr_Occurred())
4780 return 0;
4781 else
4782 return -1;
4784 """)
4786 #------------------------------------------------------------------------------------
4788 type_test_utility_code = UtilityCode(
4789 proto = """
4790 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4791 """,
4792 impl = """
4793 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4794 if (!type) {
4795 PyErr_Format(PyExc_SystemError, "Missing type object");
4796 return 0;
4798 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4799 return 1;
4800 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4801 Py_TYPE(obj)->tp_name, type->tp_name);
4802 return 0;
4804 """)
4806 #------------------------------------------------------------------------------------
4808 create_class_utility_code = UtilityCode(
4809 proto = """
4810 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4811 """,
4812 impl = """
4813 static PyObject *__Pyx_CreateClass(
4814 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4816 PyObject *py_modname;
4817 PyObject *result = 0;
4819 #if PY_MAJOR_VERSION < 3
4820 py_modname = PyString_FromString(modname);
4821 #else
4822 py_modname = PyUnicode_FromString(modname);
4823 #endif
4824 if (!py_modname)
4825 goto bad;
4826 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4827 goto bad;
4828 #if PY_MAJOR_VERSION < 3
4829 result = PyClass_New(bases, dict, name);
4830 #else
4831 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4832 #endif
4833 bad:
4834 Py_XDECREF(py_modname);
4835 return result;
4837 """)
4839 #------------------------------------------------------------------------------------
4841 cpp_exception_utility_code = UtilityCode(
4842 proto = """
4843 #ifndef __Pyx_CppExn2PyErr
4844 static void __Pyx_CppExn2PyErr() {
4845 try {
4846 if (PyErr_Occurred())
4847 ; // let the latest Python exn pass through and ignore the current one
4848 else
4849 throw;
4850 } catch (const std::out_of_range& exn) {
4851 // catch out_of_range explicitly so the proper Python exn may be raised
4852 PyErr_SetString(PyExc_IndexError, exn.what());
4853 } catch (const std::exception& exn) {
4854 PyErr_SetString(PyExc_RuntimeError, exn.what());
4856 catch (...)
4858 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4861 #endif
4862 """,
4863 impl = ""
4866 #------------------------------------------------------------------------------------
4868 append_utility_code = UtilityCode(
4869 proto = """
4870 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4871 if (likely(PyList_CheckExact(L))) {
4872 if (PyList_Append(L, x) < 0) return NULL;
4873 Py_INCREF(Py_None);
4874 return Py_None; // this is just to have an accurate signature
4876 else {
4877 return PyObject_CallMethod(L, "append", "(O)", x);
4880 """,
4881 impl = ""
4884 #------------------------------------------------------------------------------------
4886 # If the is_unsigned flag is set, we need to do some extra work to make
4887 # sure the index doesn't become negative.
4889 getitem_int_utility_code = UtilityCode(
4890 proto = """
4891 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4892 PyObject *r;
4893 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4894 r = PyList_GET_ITEM(o, i);
4895 Py_INCREF(r);
4897 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4898 r = PyTuple_GET_ITEM(o, i);
4899 Py_INCREF(r);
4901 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4902 r = PySequence_GetItem(o, i);
4903 else {
4904 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);
4905 if (!j)
4906 return 0;
4907 r = PyObject_GetItem(o, j);
4908 Py_DECREF(j);
4910 return r;
4912 """,
4913 impl = """
4914 """)
4916 #------------------------------------------------------------------------------------
4918 setitem_int_utility_code = UtilityCode(
4919 proto = """
4920 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4921 int r;
4922 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4923 Py_DECREF(PyList_GET_ITEM(o, i));
4924 Py_INCREF(v);
4925 PyList_SET_ITEM(o, i, v);
4926 return 1;
4928 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4929 r = PySequence_SetItem(o, i, v);
4930 else {
4931 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);
4932 if (!j)
4933 return -1;
4934 r = PyObject_SetItem(o, j, v);
4935 Py_DECREF(j);
4937 return r;
4939 """,
4940 impl = """
4941 """)
4943 #------------------------------------------------------------------------------------
4945 delitem_int_utility_code = UtilityCode(
4946 proto = """
4947 static INLINE int __Pyx_DelItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4948 int r;
4949 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4950 r = PySequence_DelItem(o, i);
4951 else {
4952 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);
4953 if (!j)
4954 return -1;
4955 r = PyObject_DelItem(o, j);
4956 Py_DECREF(j);
4958 return r;
4960 """,
4961 impl = """
4962 """)
4964 #------------------------------------------------------------------------------------
4966 raise_noneattr_error_utility_code = UtilityCode(
4967 proto = """
4968 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname);
4969 """,
4970 impl = """
4971 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname) {
4972 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
4974 """)
4976 raise_noneindex_error_utility_code = UtilityCode(
4977 proto = """
4978 static INLINE void __Pyx_RaiseNoneIndexingError();
4979 """,
4980 impl = """
4981 static INLINE void __Pyx_RaiseNoneIndexingError() {
4982 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
4984 """)