Cython has moved to github.

cython-devel

view Cython/Compiler/ExprNodes.py @ 1213:302abc2245aa

lists as literal structs
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Oct 07 15:02:54 2008 -0700 (3 years ago)
parents c086038b5c07
children fd38efcd7236
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 import StringEncoding
10 import Naming
11 from Nodes import Node
12 import PyrexTypes
13 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
14 from Builtin import list_type, tuple_type, dict_type, unicode_type
15 import Symtab
16 import Options
17 from Annotate import AnnotationItem
19 from Cython.Debugging import print_call_chain
20 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
21 debug_coercion
24 class ExprNode(Node):
25 # subexprs [string] Class var holding names of subexpr node attrs
26 # type PyrexType Type of the result
27 # result_code string Code fragment
28 # result_ctype string C type of result_code if different from type
29 # is_temp boolean Result is in a temporary variable
30 # is_sequence_constructor
31 # boolean Is a list or tuple constructor expression
32 # saved_subexpr_nodes
33 # [ExprNode or [ExprNode or None] or None]
34 # Cached result of subexpr_nodes()
36 result_ctype = None
37 type = None
39 # The Analyse Expressions phase for expressions is split
40 # into two sub-phases:
41 #
42 # Analyse Types
43 # Determines the result type of the expression based
44 # on the types of its sub-expressions, and inserts
45 # coercion nodes into the expression tree where needed.
46 # Marks nodes which will need to have temporary variables
47 # allocated.
48 #
49 # Allocate Temps
50 # Allocates temporary variables where needed, and fills
51 # in the result_code field of each node.
52 #
53 # ExprNode provides some convenience routines which
54 # perform both of the above phases. These should only
55 # be called from statement nodes, and only when no
56 # coercion nodes need to be added around the expression
57 # being analysed. In that case, the above two phases
58 # should be invoked separately.
59 #
60 # Framework code in ExprNode provides much of the common
61 # processing for the various phases. It makes use of the
62 # 'subexprs' class attribute of ExprNodes, which should
63 # contain a list of the names of attributes which can
64 # hold sub-nodes or sequences of sub-nodes.
65 #
66 # The framework makes use of a number of abstract methods.
67 # Their responsibilities are as follows.
68 #
69 # Declaration Analysis phase
70 #
71 # analyse_target_declaration
72 # Called during the Analyse Declarations phase to analyse
73 # the LHS of an assignment or argument of a del statement.
74 # Nodes which cannot be the LHS of an assignment need not
75 # implement it.
76 #
77 # Expression Analysis phase
78 #
79 # analyse_types
80 # - Call analyse_types on all sub-expressions.
81 # - Check operand types, and wrap coercion nodes around
82 # sub-expressions where needed.
83 # - Set the type of this node.
84 # - If a temporary variable will be required for the
85 # result, set the is_temp flag of this node.
86 #
87 # analyse_target_types
88 # Called during the Analyse Types phase to analyse
89 # the LHS of an assignment or argument of a del
90 # statement. Similar responsibilities to analyse_types.
91 #
92 # allocate_temps
93 # - Call allocate_temps for all sub-nodes.
94 # - Call allocate_temp for this node.
95 # - If a temporary was allocated, call release_temp on
96 # all sub-expressions.
97 #
98 # allocate_target_temps
99 # - Call allocate_temps on sub-nodes and allocate any other
100 # temps used during assignment.
101 # - Fill in result_code with a C lvalue if needed.
102 # - If a rhs node is supplied, call release_temp on it.
103 # - Call release_temp on sub-nodes and release any other
104 # temps used during assignment.
105 #
106 # target_code
107 # Called by the default implementation of allocate_target_temps.
108 # Should return a C lvalue for assigning to the node. The default
109 # implementation calls calculate_result_code.
110 #
111 # check_const
112 # - Check that this node and its subnodes form a
113 # legal constant expression. If so, do nothing,
114 # otherwise call not_const.
115 #
116 # The default implementation of check_const
117 # assumes that the expression is not constant.
118 #
119 # check_const_addr
120 # - Same as check_const, except check that the
121 # expression is a C lvalue whose address is
122 # constant. Otherwise, call addr_not_const.
123 #
124 # The default implementation of calc_const_addr
125 # assumes that the expression is not a constant
126 # lvalue.
127 #
128 # Code Generation phase
129 #
130 # generate_evaluation_code
131 # - Call generate_evaluation_code for sub-expressions.
132 # - Perform the functions of generate_result_code
133 # (see below).
134 # - If result is temporary, call generate_disposal_code
135 # on all sub-expressions.
136 #
137 # A default implementation of generate_evaluation_code
138 # is provided which uses the following abstract methods:
139 #
140 # generate_result_code
141 # - Generate any C statements necessary to calculate
142 # the result of this node from the results of its
143 # sub-expressions.
144 #
145 # calculate_result_code
146 # - Should return a C code fragment evaluating to the
147 # result. This is only called when the result is not
148 # a temporary.
149 #
150 # generate_assignment_code
151 # Called on the LHS of an assignment.
152 # - Call generate_evaluation_code for sub-expressions.
153 # - Generate code to perform the assignment.
154 # - If the assignment absorbed a reference, call
155 # generate_post_assignment_code on the RHS,
156 # otherwise call generate_disposal_code on it.
157 #
158 # generate_deletion_code
159 # Called on an argument of a del statement.
160 # - Call generate_evaluation_code for sub-expressions.
161 # - Generate code to perform the deletion.
162 # - Call generate_disposal_code on all sub-expressions.
163 #
164 #
166 is_sequence_constructor = 0
167 is_attribute = 0
169 saved_subexpr_nodes = None
170 is_temp = 0
172 def get_child_attrs(self):
173 return self.subexprs
174 child_attrs = property(fget=get_child_attrs)
176 def not_implemented(self, method_name):
177 print_call_chain(method_name, "not implemented") ###
178 raise InternalError(
179 "%s.%s not implemented" %
180 (self.__class__.__name__, method_name))
182 def is_lvalue(self):
183 return 0
185 def is_ephemeral(self):
186 # An ephemeral node is one whose result is in
187 # a Python temporary and we suspect there are no
188 # other references to it. Certain operations are
189 # disallowed on such values, since they are
190 # likely to result in a dangling pointer.
191 return self.type.is_pyobject and self.is_temp
193 def subexpr_nodes(self):
194 # Extract a list of subexpression nodes based
195 # on the contents of the subexprs class attribute.
196 if self.saved_subexpr_nodes is None:
197 nodes = []
198 for name in self.subexprs:
199 item = getattr(self, name)
200 if item:
201 if isinstance(item, ExprNode):
202 nodes.append(item)
203 else:
204 nodes.extend(item)
205 self.saved_subexpr_nodes = nodes
206 return self.saved_subexpr_nodes
208 def result(self):
209 if self.is_temp:
210 return self.result_code
211 else:
212 return self.calculate_result_code()
214 def result_as(self, type = None):
215 # Return the result code cast to the specified C type.
216 return typecast(type, self.ctype(), self.result())
218 def py_result(self):
219 # Return the result code cast to PyObject *.
220 return self.result_as(py_object_type)
222 def ctype(self):
223 # Return the native C type of the result (i.e. the
224 # C type of the result_code expression).
225 return self.result_ctype or self.type
227 def compile_time_value(self, denv):
228 # Return value of compile-time expression, or report error.
229 error(self.pos, "Invalid compile-time expression")
231 def compile_time_value_error(self, e):
232 error(self.pos, "Error in compile-time expression: %s: %s" % (
233 e.__class__.__name__, e))
235 # ------------- Declaration Analysis ----------------
237 def analyse_target_declaration(self, env):
238 error(self.pos, "Cannot assign to or delete this")
240 # ------------- Expression Analysis ----------------
242 def analyse_const_expression(self, env):
243 # Called during the analyse_declarations phase of a
244 # constant expression. Analyses the expression's type,
245 # checks whether it is a legal const expression,
246 # and determines its value.
247 self.analyse_types(env)
248 self.allocate_temps(env)
249 self.check_const()
251 def analyse_expressions(self, env):
252 # Convenience routine performing both the Type
253 # Analysis and Temp Allocation phases for a whole
254 # expression.
255 self.analyse_types(env)
256 self.allocate_temps(env)
258 def analyse_target_expression(self, env, rhs):
259 # Convenience routine performing both the Type
260 # Analysis and Temp Allocation phases for the LHS of
261 # an assignment.
262 self.analyse_target_types(env)
263 self.allocate_target_temps(env, rhs)
265 def analyse_boolean_expression(self, env):
266 # Analyse expression and coerce to a boolean.
267 self.analyse_types(env)
268 bool = self.coerce_to_boolean(env)
269 bool.allocate_temps(env)
270 return bool
272 def analyse_temp_boolean_expression(self, env):
273 # Analyse boolean expression and coerce result into
274 # a temporary. This is used when a branch is to be
275 # performed on the result and we won't have an
276 # opportunity to ensure disposal code is executed
277 # afterwards. By forcing the result into a temporary,
278 # we ensure that all disposal has been done by the
279 # time we get the result.
280 self.analyse_types(env)
281 bool = self.coerce_to_boolean(env)
282 temp_bool = bool.coerce_to_temp(env)
283 temp_bool.allocate_temps(env)
284 return temp_bool
286 # --------------- Type Analysis ------------------
288 def analyse_as_module(self, env):
289 # If this node can be interpreted as a reference to a
290 # cimported module, return its scope, else None.
291 return None
293 def analyse_as_type(self, env):
294 # If this node can be interpreted as a reference to a
295 # type, return that type, else None.
296 return None
298 def analyse_as_extension_type(self, env):
299 # If this node can be interpreted as a reference to an
300 # extension type, return its type, else None.
301 return None
303 def analyse_types(self, env):
304 self.not_implemented("analyse_types")
306 def analyse_target_types(self, env):
307 self.analyse_types(env)
309 def gil_assignment_check(self, env):
310 if env.nogil and self.type.is_pyobject:
311 error(self.pos, "Assignment of Python object not allowed without gil")
313 def check_const(self):
314 self.not_const()
316 def not_const(self):
317 error(self.pos, "Not allowed in a constant expression")
319 def check_const_addr(self):
320 self.addr_not_const()
322 def addr_not_const(self):
323 error(self.pos, "Address is not constant")
325 def gil_check(self, env):
326 if env.nogil and self.type.is_pyobject:
327 self.gil_error()
329 # ----------------- Result Allocation -----------------
331 def result_in_temp(self):
332 # Return true if result is in a temporary owned by
333 # this node or one of its subexpressions. Overridden
334 # by certain nodes which can share the result of
335 # a subnode.
336 return self.is_temp
338 def allocate_target_temps(self, env, rhs):
339 # Perform temp allocation for the LHS of an assignment.
340 if debug_temp_alloc:
341 print("%s Allocating target temps" % self)
342 self.allocate_subexpr_temps(env)
343 self.result_code = self.target_code()
344 if rhs:
345 rhs.release_temp(env)
346 self.release_subexpr_temps(env)
348 def allocate_temps(self, env, result = None):
349 # Allocate temporary variables for this node and
350 # all its sub-expressions. If a result is specified,
351 # this must be a temp node and the specified variable
352 # is used as the result instead of allocating a new
353 # one.
354 if debug_temp_alloc:
355 print("%s Allocating temps" % self)
356 self.allocate_subexpr_temps(env)
357 self.allocate_temp(env, result)
358 if self.is_temp:
359 self.release_subexpr_temps(env)
361 def allocate_subexpr_temps(self, env):
362 # Allocate temporary variables for all sub-expressions
363 # of this node.
364 if debug_temp_alloc:
365 print("%s Allocating temps for: %s" % (self, self.subexprs))
366 for node in self.subexpr_nodes():
367 if node:
368 if debug_temp_alloc:
369 print("%s Allocating temps for %s" % (self, node))
370 node.allocate_temps(env)
372 def allocate_temp(self, env, result = None):
373 # If this node requires a temporary variable for its
374 # result, allocate one, otherwise set the result to
375 # a C code fragment. If a result is specified,
376 # this must be a temp node and the specified variable
377 # is used as the result instead of allocating a new
378 # one.
379 if debug_temp_alloc:
380 print("%s Allocating temp" % self)
381 if result:
382 if not self.is_temp:
383 raise InternalError("Result forced on non-temp node")
384 self.result_code = result
385 elif self.is_temp:
386 type = self.type
387 if not type.is_void:
388 if type.is_pyobject:
389 type = PyrexTypes.py_object_type
390 self.result_code = env.allocate_temp(type)
391 else:
392 self.result_code = None
393 if debug_temp_alloc:
394 print("%s Allocated result %s" % (self, self.result_code))
396 def target_code(self):
397 # Return code fragment for use as LHS of a C assignment.
398 return self.calculate_result_code()
400 def calculate_result_code(self):
401 self.not_implemented("calculate_result_code")
403 # def release_target_temp(self, env):
404 # # Release temporaries used by LHS of an assignment.
405 # self.release_subexpr_temps(env)
407 def release_temp(self, env):
408 # If this node owns a temporary result, release it,
409 # otherwise release results of its sub-expressions.
410 if self.is_temp:
411 if debug_temp_alloc:
412 print("%s Releasing result %s" % (self, self.result_code))
413 env.release_temp(self.result_code)
414 else:
415 self.release_subexpr_temps(env)
417 def release_subexpr_temps(self, env):
418 # Release the results of all sub-expressions of
419 # this node.
420 for node in self.subexpr_nodes():
421 if node:
422 node.release_temp(env)
424 # ---------------- Code Generation -----------------
426 def make_owned_reference(self, code):
427 # If result is a pyobject, make sure we own
428 # a reference to it.
429 if self.type.is_pyobject and not self.result_in_temp():
430 code.put_incref(self.result(), self.ctype())
432 def generate_evaluation_code(self, code):
433 code.mark_pos(self.pos)
434 # Generate code to evaluate this node and
435 # its sub-expressions, and dispose of any
436 # temporary results of its sub-expressions.
437 self.generate_subexpr_evaluation_code(code)
438 self.generate_result_code(code)
439 if self.is_temp:
440 self.generate_subexpr_disposal_code(code)
442 def generate_subexpr_evaluation_code(self, code):
443 for node in self.subexpr_nodes():
444 node.generate_evaluation_code(code)
446 def generate_result_code(self, code):
447 self.not_implemented("generate_result_code")
449 def generate_disposal_code(self, code):
450 # If necessary, generate code to dispose of
451 # temporary Python reference.
452 if self.is_temp:
453 if self.type.is_pyobject:
454 code.put_decref_clear(self.result(), self.ctype())
455 else:
456 self.generate_subexpr_disposal_code(code)
458 def generate_subexpr_disposal_code(self, code):
459 # Generate code to dispose of temporary results
460 # of all sub-expressions.
461 for node in self.subexpr_nodes():
462 node.generate_disposal_code(code)
464 def generate_post_assignment_code(self, code):
465 # Same as generate_disposal_code except that
466 # assignment will have absorbed a reference to
467 # the result if it is a Python object.
468 if self.is_temp:
469 if self.type.is_pyobject:
470 code.putln("%s = 0;" % self.result())
471 else:
472 self.generate_subexpr_disposal_code(code)
474 def generate_assignment_code(self, rhs, code):
475 # Stub method for nodes which are not legal as
476 # the LHS of an assignment. An error will have
477 # been reported earlier.
478 pass
480 def generate_deletion_code(self, code):
481 # Stub method for nodes that are not legal as
482 # the argument of a del statement. An error
483 # will have been reported earlier.
484 pass
486 # ---------------- Annotation ---------------------
488 def annotate(self, code):
489 for node in self.subexpr_nodes():
490 node.annotate(code)
492 # ----------------- Coercion ----------------------
494 def coerce_to(self, dst_type, env):
495 # Coerce the result so that it can be assigned to
496 # something of type dst_type. If processing is necessary,
497 # wraps this node in a coercion node and returns that.
498 # Otherwise, returns this node unchanged.
499 #
500 # This method is called during the analyse_expressions
501 # phase of the src_node's processing.
502 src = self
503 src_type = self.type
504 src_is_py_type = src_type.is_pyobject
505 dst_is_py_type = dst_type.is_pyobject
507 if dst_type.is_pyobject:
508 if not src.type.is_pyobject:
509 src = CoerceToPyTypeNode(src, env)
510 if not src.type.subtype_of(dst_type):
511 if not isinstance(src, NoneNode):
512 src = PyTypeTestNode(src, dst_type, env)
513 elif src.type.is_pyobject:
514 src = CoerceFromPyTypeNode(dst_type, src, env)
515 else: # neither src nor dst are py types
516 # Added the string comparison, since for c types that
517 # is enough, but Cython gets confused when the types are
518 # in different files.
519 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
520 error(self.pos, "Cannot assign type '%s' to '%s'" %
521 (src.type, dst_type))
522 return src
524 def coerce_to_pyobject(self, env):
525 return self.coerce_to(PyrexTypes.py_object_type, env)
527 def coerce_to_boolean(self, env):
528 # Coerce result to something acceptable as
529 # a boolean value.
530 type = self.type
531 if type.is_pyobject or type.is_ptr or type.is_float:
532 return CoerceToBooleanNode(self, env)
533 else:
534 if not type.is_int and not type.is_error:
535 error(self.pos,
536 "Type '%s' not acceptable as a boolean" % type)
537 return self
539 def coerce_to_integer(self, env):
540 # If not already some C integer type, coerce to longint.
541 if self.type.is_int:
542 return self
543 else:
544 return self.coerce_to(PyrexTypes.c_long_type, env)
546 def coerce_to_temp(self, env):
547 # Ensure that the result is in a temporary.
548 if self.result_in_temp():
549 return self
550 else:
551 return CoerceToTempNode(self, env)
553 def coerce_to_simple(self, env):
554 # Ensure that the result is simple (see is_simple).
555 if self.is_simple():
556 return self
557 else:
558 return self.coerce_to_temp(env)
560 def is_simple(self):
561 # A node is simple if its result is something that can
562 # be referred to without performing any operations, e.g.
563 # a constant, local var, C global var, struct member
564 # reference, or temporary.
565 return self.result_in_temp()
567 def magic_cython_method(self):
568 return None
571 class AtomicExprNode(ExprNode):
572 # Abstract base class for expression nodes which have
573 # no sub-expressions.
575 subexprs = []
578 class PyConstNode(AtomicExprNode):
579 # Abstract base class for constant Python values.
581 is_literal = 1
583 def is_simple(self):
584 return 1
586 def analyse_types(self, env):
587 self.type = py_object_type
589 def calculate_result_code(self):
590 return self.value
592 def generate_result_code(self, code):
593 pass
596 class NoneNode(PyConstNode):
597 # The constant value None
599 value = "Py_None"
601 def compile_time_value(self, denv):
602 return None
604 class EllipsisNode(PyConstNode):
605 # '...' in a subscript list.
607 value = "Py_Ellipsis"
609 def compile_time_value(self, denv):
610 return Ellipsis
613 class ConstNode(AtomicExprNode):
614 # Abstract base type for literal constant nodes.
615 #
616 # value string C code fragment
618 is_literal = 1
620 def is_simple(self):
621 return 1
623 def analyse_types(self, env):
624 pass # Types are held in class variables
626 def check_const(self):
627 pass
629 def calculate_result_code(self):
630 return str(self.value)
632 def generate_result_code(self, code):
633 pass
636 class BoolNode(ConstNode):
637 type = PyrexTypes.c_bint_type
638 # The constant value True or False
640 def compile_time_value(self, denv):
641 return self.value
643 def calculate_result_code(self):
644 return str(int(self.value))
646 class NullNode(ConstNode):
647 type = PyrexTypes.c_null_ptr_type
648 value = "NULL"
651 class CharNode(ConstNode):
652 type = PyrexTypes.c_char_type
654 def compile_time_value(self, denv):
655 return ord(self.value)
657 def calculate_result_code(self):
658 return "'%s'" % StringEncoding.escape_character(self.value)
661 class IntNode(ConstNode):
663 # unsigned "" or "U"
664 # longness "" or "L" or "LL"
666 unsigned = ""
667 longness = ""
668 type = PyrexTypes.c_long_type
670 def coerce_to(self, dst_type, env):
671 # Arrange for a Python version of the string to be pre-allocated
672 # when coercing to a Python type.
673 if dst_type.is_pyobject:
674 self.entry = env.get_py_num(self.value, self.longness)
675 self.type = PyrexTypes.py_object_type
676 # We still need to perform normal coerce_to processing on the
677 # result, because we might be coercing to an extension type,
678 # in which case a type test node will be needed.
679 return ConstNode.coerce_to(self, dst_type, env)
681 def calculate_result_code(self):
682 if self.type.is_pyobject:
683 return self.entry.cname
684 else:
685 return str(self.value) + self.unsigned + self.longness
687 def compile_time_value(self, denv):
688 return int(self.value, 0)
691 class FloatNode(ConstNode):
692 type = PyrexTypes.c_double_type
694 def compile_time_value(self, denv):
695 return float(self.value)
697 def calculate_result_code(self):
698 strval = str(self.value)
699 if strval == 'nan':
700 return "(Py_HUGE_VAL * 0)"
701 elif strval == 'inf':
702 return "Py_HUGE_VAL"
703 elif strval == '-inf':
704 return "(-Py_HUGE_VAL)"
705 else:
706 return strval
709 class StringNode(ConstNode):
710 # entry Symtab.Entry
712 type = PyrexTypes.c_char_ptr_type
714 def compile_time_value(self, denv):
715 return self.value
717 def analyse_types(self, env):
718 self.entry = env.add_string_const(self.value)
720 def analyse_as_type(self, env):
721 type = PyrexTypes.parse_basic_type(self.value)
722 if type is not None:
723 return type
724 from TreeFragment import TreeFragment
725 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
726 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
727 sizeof_node = declaration.root.stats[0].expr
728 sizeof_node.analyse_types(env)
729 if isinstance(sizeof_node, SizeofTypeNode):
730 return sizeof_node.arg_type
732 def coerce_to(self, dst_type, env):
733 if dst_type.is_int:
734 if not self.type.is_pyobject and len(self.entry.init) == 1:
735 return CharNode(self.pos, value=self.value)
736 else:
737 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
738 return self
739 # Arrange for a Python version of the string to be pre-allocated
740 # when coercing to a Python type.
741 if dst_type.is_pyobject and not self.type.is_pyobject:
742 node = self.as_py_string_node(env)
743 else:
744 node = self
745 # We still need to perform normal coerce_to processing on the
746 # result, because we might be coercing to an extension type,
747 # in which case a type test node will be needed.
748 return ConstNode.coerce_to(node, dst_type, env)
750 def as_py_string_node(self, env):
751 # Return a new StringNode with the same entry as this node
752 # but whose type is a Python type instead of a C type.
753 entry = self.entry
754 env.add_py_string(entry)
755 return StringNode(self.pos, entry = entry, type = py_object_type)
757 def calculate_result_code(self):
758 if self.type.is_pyobject:
759 return self.entry.pystring_cname
760 else:
761 return self.entry.cname
764 class UnicodeNode(PyConstNode):
765 # entry Symtab.Entry
767 type = unicode_type
769 def analyse_types(self, env):
770 self.entry = env.add_string_const(self.value)
771 env.add_py_string(self.entry)
773 def calculate_result_code(self):
774 return self.entry.pystring_cname
776 def _coerce_to(self, dst_type, env):
777 if not dst_type.is_pyobject:
778 node = StringNode(self.pos, entry = entry, type = py_object_type)
779 return ConstNode.coerce_to(node, dst_type, env)
780 else:
781 return self
782 # We still need to perform normal coerce_to processing on the
783 # result, because we might be coercing to an extension type,
784 # in which case a type test node will be needed.
786 def compile_time_value(self, env):
787 return self.value
790 class IdentifierStringNode(ConstNode):
791 # A Python string that behaves like an identifier, e.g. for
792 # keyword arguments in a call, or for imported names
793 type = PyrexTypes.py_object_type
795 def analyse_types(self, env):
796 self.cname = env.intern_identifier(self.value)
798 def calculate_result_code(self):
799 return self.cname
802 class LongNode(AtomicExprNode):
803 # Python long integer literal
804 #
805 # value string
807 def compile_time_value(self, denv):
808 return long(self.value)
810 gil_message = "Constructing Python long int"
812 def analyse_types(self, env):
813 self.type = py_object_type
814 self.gil_check(env)
815 self.is_temp = 1
817 gil_message = "Constructing Python long int"
819 def generate_evaluation_code(self, code):
820 code.putln(
821 '%s = PyLong_FromString("%s", 0, 0); %s' % (
822 self.result(),
823 self.value,
824 code.error_goto_if_null(self.result(), self.pos)))
827 class ImagNode(AtomicExprNode):
828 # Imaginary number literal
829 #
830 # value float imaginary part
832 def compile_time_value(self, denv):
833 return complex(0.0, self.value)
835 def analyse_types(self, env):
836 self.type = py_object_type
837 self.gil_check(env)
838 self.is_temp = 1
840 gil_message = "Constructing complex number"
842 def generate_evaluation_code(self, code):
843 code.putln(
844 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
845 self.result(),
846 self.value,
847 code.error_goto_if_null(self.result(), self.pos)))
850 class NameNode(AtomicExprNode):
851 # Reference to a local or global variable name.
852 #
853 # name string Python name of the variable
854 #
855 # entry Entry Symbol table entry
856 # interned_cname string
858 is_name = True
859 is_cython_module = False
860 cython_attribute = None
861 skip_assignment_decref = False
862 entry = None
864 def create_analysed_rvalue(pos, env, entry):
865 node = NameNode(pos)
866 node.analyse_types(env, entry=entry)
867 return node
869 def magic_cython_method(self):
870 return self.cython_attribute
872 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
874 def compile_time_value(self, denv):
875 try:
876 return denv.lookup(self.name)
877 except KeyError:
878 error(self.pos, "Compile-time name '%s' not defined" % self.name)
880 def coerce_to(self, dst_type, env):
881 # If coercing to a generic pyobject and this is a builtin
882 # C function with a Python equivalent, manufacture a NameNode
883 # referring to the Python builtin.
884 #print "NameNode.coerce_to:", self.name, dst_type ###
885 if dst_type is py_object_type:
886 entry = self.entry
887 if entry and entry.is_cfunction:
888 var_entry = entry.as_variable
889 if var_entry:
890 if var_entry.is_builtin and Options.cache_builtins:
891 var_entry = env.declare_builtin(var_entry.name, self.pos)
892 node = NameNode(self.pos, name = self.name)
893 node.entry = var_entry
894 node.analyse_rvalue_entry(env)
895 return node
896 return AtomicExprNode.coerce_to(self, dst_type, env)
898 def analyse_as_module(self, env):
899 # Try to interpret this as a reference to a cimported module.
900 # Returns the module scope, or None.
901 entry = self.entry
902 if not entry:
903 entry = env.lookup(self.name)
904 if entry and entry.as_module:
905 return entry.as_module
906 return None
908 def analyse_as_type(self, env):
909 type = PyrexTypes.parse_basic_type(self.name)
910 if type:
911 return type
912 entry = self.entry
913 if not entry:
914 entry = env.lookup(self.name)
915 if entry and entry.is_type:
916 return entry.type
917 else:
918 return None
920 def analyse_as_extension_type(self, env):
921 # Try to interpret this as a reference to an extension type.
922 # Returns the extension type, or None.
923 entry = self.entry
924 if not entry:
925 entry = env.lookup(self.name)
926 if entry and entry.is_type and entry.type.is_extension_type:
927 return entry.type
928 else:
929 return None
931 def analyse_target_declaration(self, env):
932 if not self.entry:
933 self.entry = env.lookup_here(self.name)
934 if not self.entry:
935 self.entry = env.declare_var(self.name, py_object_type, self.pos)
936 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
937 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
938 if self.entry.is_declared_generic:
939 self.result_ctype = py_object_type
941 def analyse_types(self, env):
942 if self.entry is None:
943 self.entry = env.lookup(self.name)
944 if not self.entry:
945 self.entry = env.declare_builtin(self.name, self.pos)
946 if not self.entry:
947 self.type = PyrexTypes.error_type
948 return
949 self.analyse_rvalue_entry(env)
951 def analyse_target_types(self, env):
952 self.analyse_entry(env)
953 if not self.is_lvalue():
954 error(self.pos, "Assignment to non-lvalue '%s'"
955 % self.name)
956 self.type = PyrexTypes.error_type
957 self.entry.used = 1
958 if self.entry.type.is_buffer:
959 import Buffer
960 Buffer.used_buffer_aux_vars(self.entry)
962 def analyse_rvalue_entry(self, env):
963 #print "NameNode.analyse_rvalue_entry:", self.name ###
964 #print "Entry:", self.entry.__dict__ ###
965 self.analyse_entry(env)
966 entry = self.entry
967 if entry.is_declared_generic:
968 self.result_ctype = py_object_type
969 if entry.is_pyglobal or entry.is_builtin:
970 if Options.cache_builtins and entry.is_builtin:
971 self.is_temp = 0
972 else:
973 self.is_temp = 1
974 env.use_utility_code(get_name_interned_utility_code)
975 self.gil_check(env)
977 gil_message = "Accessing Python global or builtin"
979 def analyse_entry(self, env):
980 #print "NameNode.analyse_entry:", self.name ###
981 self.check_identifier_kind()
982 entry = self.entry
983 type = entry.type
984 self.type = type
985 if entry.is_pyglobal or entry.is_builtin:
986 assert type.is_pyobject, "Python global or builtin not a Python object"
987 self.interned_cname = self.entry.interned_cname = \
988 env.intern_identifier(self.entry.name)
990 def check_identifier_kind(self):
991 #print "NameNode.check_identifier_kind:", self.entry.name ###
992 #print self.entry.__dict__ ###
993 entry = self.entry
994 #entry.used = 1
995 if not (entry.is_const or entry.is_variable
996 or entry.is_builtin or entry.is_cfunction):
997 if self.entry.as_variable:
998 self.entry = self.entry.as_variable
999 else:
1000 error(self.pos,
1001 "'%s' is not a constant, variable or function identifier" % self.name)
1003 def is_simple(self):
1004 # If it's not a C variable, it'll be in a temp.
1005 return 1
1007 def calculate_target_results(self, env):
1008 pass
1010 def check_const(self):
1011 entry = self.entry
1012 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1013 self.not_const()
1015 def check_const_addr(self):
1016 entry = self.entry
1017 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1018 self.addr_not_const()
1020 def is_lvalue(self):
1021 return self.entry.is_variable and \
1022 not self.entry.type.is_array and \
1023 not self.entry.is_readonly
1025 def is_ephemeral(self):
1026 # Name nodes are never ephemeral, even if the
1027 # result is in a temporary.
1028 return 0
1030 def allocate_temp(self, env, result = None):
1031 AtomicExprNode.allocate_temp(self, env, result)
1032 entry = self.entry
1033 if entry:
1034 entry.used = 1
1035 if entry.type.is_buffer:
1036 import Buffer
1037 Buffer.used_buffer_aux_vars(entry)
1038 if entry.utility_code:
1039 env.use_utility_code(entry.utility_code)
1041 def calculate_result_code(self):
1042 entry = self.entry
1043 if not entry:
1044 return "<error>" # There was an error earlier
1045 return entry.cname
1047 def generate_result_code(self, code):
1048 assert hasattr(self, 'entry')
1049 entry = self.entry
1050 if entry is None:
1051 return # There was an error earlier
1052 if entry.is_builtin and Options.cache_builtins:
1053 return # Lookup already cached
1054 elif entry.is_pyglobal or entry.is_builtin:
1055 if entry.is_builtin:
1056 namespace = Naming.builtins_cname
1057 else: # entry.is_pyglobal
1058 namespace = entry.scope.namespace_cname
1059 code.putln(
1060 '%s = __Pyx_GetName(%s, %s); %s' % (
1061 self.result(),
1062 namespace,
1063 self.interned_cname,
1064 code.error_goto_if_null(self.result(), self.pos)))
1065 elif entry.is_local and False:
1066 # control flow not good enough yet
1067 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1068 if assigned is False:
1069 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1070 elif not Options.init_local_none and assigned is None:
1071 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1072 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1074 def generate_assignment_code(self, rhs, code):
1075 #print "NameNode.generate_assignment_code:", self.name ###
1076 entry = self.entry
1077 if entry is None:
1078 return # There was an error earlier
1080 # is_pyglobal seems to be True for module level-globals only.
1081 # We use this to access class->tp_dict if necessary.
1082 if entry.is_pyglobal:
1083 namespace = self.entry.scope.namespace_cname
1084 if entry.is_member:
1085 # if the entry is a member we have to cheat: SetAttr does not work
1086 # on types, so we create a descriptor which is then added to tp_dict
1087 code.put_error_if_neg(self.pos,
1088 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1089 namespace,
1090 self.interned_cname,
1091 rhs.py_result()))
1092 # in Py2.6+, we need to invalidate the method cache
1093 code.putln("PyType_Modified(%s);" %
1094 entry.scope.parent_type.typeptr_cname)
1095 else:
1096 code.put_error_if_neg(self.pos,
1097 'PyObject_SetAttr(%s, %s, %s)' % (
1098 namespace,
1099 self.interned_cname,
1100 rhs.py_result()))
1101 if debug_disposal_code:
1102 print("NameNode.generate_assignment_code:")
1103 print("...generating disposal code for %s" % rhs)
1104 rhs.generate_disposal_code(code)
1106 else:
1107 if self.type.is_buffer:
1108 # Generate code for doing the buffer release/acquisition.
1109 # This might raise an exception in which case the assignment (done
1110 # below) will not happen.
1112 # The reason this is not in a typetest-like node is because the
1113 # variables that the acquired buffer info is stored to is allocated
1114 # per entry and coupled with it.
1115 self.generate_acquire_buffer(rhs, code)
1117 if self.type.is_pyobject:
1118 rhs.make_owned_reference(code)
1119 #print "NameNode.generate_assignment_code: to", self.name ###
1120 #print "...from", rhs ###
1121 #print "...LHS type", self.type, "ctype", self.ctype() ###
1122 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1123 if not self.skip_assignment_decref:
1124 if entry.is_local and not Options.init_local_none:
1125 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1126 if initalized is True:
1127 code.put_decref(self.result(), self.ctype())
1128 elif initalized is None:
1129 code.put_xdecref(self.result(), self.ctype())
1130 else:
1131 code.put_decref(self.result(), self.ctype())
1132 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1133 if debug_disposal_code:
1134 print("NameNode.generate_assignment_code:")
1135 print("...generating post-assignment code for %s" % rhs)
1136 rhs.generate_post_assignment_code(code)
1138 def generate_acquire_buffer(self, rhs, code):
1139 rhstmp = code.funcstate.allocate_temp(self.entry.type)
1140 buffer_aux = self.entry.buffer_aux
1141 bufstruct = buffer_aux.buffer_info_var.cname
1142 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1144 import Buffer
1145 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1146 is_initialized=not self.skip_assignment_decref,
1147 pos=self.pos, code=code)
1148 code.putln("%s = 0;" % rhstmp)
1149 code.funcstate.release_temp(rhstmp)
1151 def generate_deletion_code(self, code):
1152 if self.entry is None:
1153 return # There was an error earlier
1154 if not self.entry.is_pyglobal:
1155 error(self.pos, "Deletion of local or C global name not supported")
1156 return
1157 code.put_error_if_neg(self.pos,
1158 'PyObject_DelAttrString(%s, "%s")' % (
1159 Naming.module_cname,
1160 self.entry.name))
1162 def annotate(self, code):
1163 if hasattr(self, 'is_called') and self.is_called:
1164 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1165 if self.type.is_pyobject:
1166 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1167 else:
1168 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1170 class BackquoteNode(ExprNode):
1171 # `expr`
1173 # arg ExprNode
1175 subexprs = ['arg']
1177 def analyse_types(self, env):
1178 self.arg.analyse_types(env)
1179 self.arg = self.arg.coerce_to_pyobject(env)
1180 self.type = py_object_type
1181 self.gil_check(env)
1182 self.is_temp = 1
1184 gil_message = "Backquote expression"
1186 def generate_result_code(self, code):
1187 code.putln(
1188 "%s = PyObject_Repr(%s); %s" % (
1189 self.result(),
1190 self.arg.py_result(),
1191 code.error_goto_if_null(self.result(), self.pos)))
1194 class ImportNode(ExprNode):
1195 # Used as part of import statement implementation.
1196 # Implements result =
1197 # __import__(module_name, globals(), None, name_list)
1199 # module_name IdentifierStringNode dotted name of module
1200 # name_list ListNode or None list of names to be imported
1202 subexprs = ['module_name', 'name_list']
1204 def analyse_types(self, env):
1205 self.module_name.analyse_types(env)
1206 self.module_name = self.module_name.coerce_to_pyobject(env)
1207 if self.name_list:
1208 self.name_list.analyse_types(env)
1209 self.type = py_object_type
1210 self.gil_check(env)
1211 self.is_temp = 1
1212 env.use_utility_code(import_utility_code)
1214 gil_message = "Python import"
1216 def generate_result_code(self, code):
1217 if self.name_list:
1218 name_list_code = self.name_list.py_result()
1219 else:
1220 name_list_code = "0"
1221 code.putln(
1222 "%s = __Pyx_Import(%s, %s); %s" % (
1223 self.result(),
1224 self.module_name.py_result(),
1225 name_list_code,
1226 code.error_goto_if_null(self.result(), self.pos)))
1229 class IteratorNode(ExprNode):
1230 # Used as part of for statement implementation.
1231 # Implements result = iter(sequence)
1233 # sequence ExprNode
1235 subexprs = ['sequence']
1237 def analyse_types(self, env):
1238 self.sequence.analyse_types(env)
1239 self.sequence = self.sequence.coerce_to_pyobject(env)
1240 self.type = py_object_type
1241 self.gil_check(env)
1242 self.is_temp = 1
1244 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1245 self.counter.allocate_temp(env)
1247 gil_message = "Iterating over Python object"
1249 def release_temp(self, env):
1250 env.release_temp(self.result())
1251 self.counter.release_temp(env)
1253 def generate_result_code(self, code):
1254 code.putln(
1255 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1256 self.sequence.py_result(),
1257 self.sequence.py_result()))
1258 code.putln(
1259 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1260 self.counter.result(),
1261 self.result(),
1262 self.sequence.py_result(),
1263 self.result()))
1264 code.putln("} else {")
1265 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1266 self.counter.result(),
1267 self.result(),
1268 self.sequence.py_result(),
1269 code.error_goto_if_null(self.result(), self.pos)))
1270 code.putln("}")
1273 class NextNode(AtomicExprNode):
1274 # Used as part of for statement implementation.
1275 # Implements result = iterator.next()
1276 # Created during analyse_types phase.
1277 # The iterator is not owned by this node.
1279 # iterator ExprNode
1281 def __init__(self, iterator, env):
1282 self.pos = iterator.pos
1283 self.iterator = iterator
1284 self.type = py_object_type
1285 self.is_temp = 1
1287 def generate_result_code(self, code):
1288 for py_type in ["List", "Tuple"]:
1289 code.putln(
1290 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1291 code.putln(
1292 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1293 self.iterator.counter.result(),
1294 py_type,
1295 self.iterator.py_result()))
1296 code.putln(
1297 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1298 self.result(),
1299 py_type,
1300 self.iterator.py_result(),
1301 self.iterator.counter.result(),
1302 self.result(),
1303 self.iterator.counter.result()))
1304 code.put("} else ")
1305 code.putln("{")
1306 code.putln(
1307 "%s = PyIter_Next(%s);" % (
1308 self.result(),
1309 self.iterator.py_result()))
1310 code.putln(
1311 "if (!%s) {" %
1312 self.result())
1313 code.putln(code.error_goto_if_PyErr(self.pos))
1314 code.putln("break;")
1315 code.putln("}")
1316 code.putln("}")
1319 class ExcValueNode(AtomicExprNode):
1320 # Node created during analyse_types phase
1321 # of an ExceptClauseNode to fetch the current
1322 # exception value.
1324 def __init__(self, pos, env, var):
1325 ExprNode.__init__(self, pos)
1326 self.type = py_object_type
1327 self.var = var
1329 def calculate_result_code(self):
1330 return self.var
1332 def generate_result_code(self, code):
1333 pass
1335 def analyse_types(self, env):
1336 pass
1339 class TempNode(AtomicExprNode):
1340 # Node created during analyse_types phase
1341 # of some nodes to hold a temporary value.
1343 def __init__(self, pos, type, env):
1344 ExprNode.__init__(self, pos)
1345 self.type = type
1346 if type.is_pyobject:
1347 self.result_ctype = py_object_type
1348 self.is_temp = 1
1350 def analyse_types(self, env):
1351 return self.type
1353 def generate_result_code(self, code):
1354 pass
1357 class PyTempNode(TempNode):
1358 # TempNode holding a Python value.
1360 def __init__(self, pos, env):
1361 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1364 #-------------------------------------------------------------------
1366 # Trailer nodes
1368 #-------------------------------------------------------------------
1370 class IndexNode(ExprNode):
1371 # Sequence indexing.
1373 # base ExprNode
1374 # index ExprNode
1375 # indices [ExprNode]
1376 # is_buffer_access boolean Whether this is a buffer access.
1378 # indices is used on buffer access, index on non-buffer access.
1379 # The former contains a clean list of index parameters, the
1380 # latter whatever Python object is needed for index access.
1382 subexprs = ['base', 'index', 'indices']
1383 indices = None
1385 def __init__(self, pos, index, *args, **kw):
1386 ExprNode.__init__(self, pos, index=index, *args, **kw)
1387 self._index = index
1389 def compile_time_value(self, denv):
1390 base = self.base.compile_time_value(denv)
1391 index = self.index.compile_time_value(denv)
1392 try:
1393 return base[index]
1394 except Exception, e:
1395 self.compile_time_value_error(e)
1397 def is_ephemeral(self):
1398 return self.base.is_ephemeral()
1400 def analyse_target_declaration(self, env):
1401 pass
1403 def analyse_as_type(self, env):
1404 base_type = self.base.analyse_as_type(env)
1405 if base_type and not base_type.is_pyobject:
1406 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1407 return None
1409 def analyse_types(self, env):
1410 self.analyse_base_and_index_types(env, getting = 1)
1412 def analyse_target_types(self, env):
1413 self.analyse_base_and_index_types(env, setting = 1)
1415 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1416 # Note: This might be cleaned up by having IndexNode
1417 # parsed in a saner way and only construct the tuple if
1418 # needed.
1420 # Note that this function must leave IndexNode in a cloneable state.
1421 # For buffers, self.index is packed out on the initial analysis, and
1422 # when cloning self.indices is copied.
1423 self.is_buffer_access = False
1425 self.base.analyse_types(env)
1426 # Handle the case where base is a literal char* (and we expect a string, not an int)
1427 if isinstance(self.base, StringNode):
1428 self.base = self.base.coerce_to_pyobject(env)
1430 skip_child_analysis = False
1431 buffer_access = False
1432 if self.base.type.is_buffer:
1433 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1434 if self.indices:
1435 indices = self.indices
1436 else:
1437 # On cloning, indices is cloned. Otherwise, unpack index into indices
1438 assert not isinstance(self.index, CloneNode)
1439 if isinstance(self.index, TupleNode):
1440 indices = self.index.args
1441 else:
1442 indices = [self.index]
1443 if len(indices) == self.base.type.ndim:
1444 buffer_access = True
1445 skip_child_analysis = True
1446 for x in indices:
1447 x.analyse_types(env)
1448 if not x.type.is_int:
1449 buffer_access = False
1451 if buffer_access:
1452 self.indices = indices
1453 self.index = None
1454 self.type = self.base.type.dtype
1455 self.is_buffer_access = True
1456 self.buffer_type = self.base.entry.type
1458 if getting:
1459 # we only need a temp because result_code isn't refactored to
1460 # generation time, but this seems an ok shortcut to take
1461 self.is_temp = True
1462 if setting:
1463 if not self.base.entry.type.writable:
1464 error(self.pos, "Writing to readonly buffer")
1465 else:
1466 self.base.entry.buffer_aux.writable_needed = True
1467 else:
1468 if isinstance(self.index, TupleNode):
1469 self.index.analyse_types(env, skip_children=skip_child_analysis)
1470 elif not skip_child_analysis:
1471 self.index.analyse_types(env)
1472 if self.base.type.is_pyobject:
1473 if self.index.type.is_int and not self.index.type.is_longlong:
1474 self.original_index_type = self.index.type
1475 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1476 if getting:
1477 env.use_utility_code(getitem_int_utility_code)
1478 if setting:
1479 env.use_utility_code(setitem_int_utility_code)
1480 else:
1481 self.index = self.index.coerce_to_pyobject(env)
1482 self.type = py_object_type
1483 self.gil_check(env)
1484 self.is_temp = 1
1485 else:
1486 if self.base.type.is_ptr or self.base.type.is_array:
1487 self.type = self.base.type.base_type
1488 else:
1489 error(self.pos,
1490 "Attempting to index non-array type '%s'" %
1491 self.base.type)
1492 self.type = PyrexTypes.error_type
1493 if self.index.type.is_pyobject:
1494 self.index = self.index.coerce_to(
1495 PyrexTypes.c_py_ssize_t_type, env)
1496 if not self.index.type.is_int:
1497 error(self.pos,
1498 "Invalid index type '%s'" %
1499 self.index.type)
1501 gil_message = "Indexing Python object"
1503 def check_const_addr(self):
1504 self.base.check_const_addr()
1505 self.index.check_const()
1507 def is_lvalue(self):
1508 return 1
1510 def calculate_result_code(self):
1511 if self.is_buffer_access:
1512 return "<not used>"
1513 else:
1514 return "(%s[%s])" % (
1515 self.base.result(), self.index.result())
1517 def index_unsigned_parameter(self):
1518 if self.index.type.is_int:
1519 if self.original_index_type.signed:
1520 return ", 0"
1521 else:
1522 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1523 else:
1524 return ""
1526 def generate_subexpr_evaluation_code(self, code):
1527 self.base.generate_evaluation_code(code)
1528 if not self.indices:
1529 self.index.generate_evaluation_code(code)
1530 else:
1531 for i in self.indices:
1532 i.generate_evaluation_code(code)
1534 def generate_subexpr_disposal_code(self, code):
1535 self.base.generate_disposal_code(code)
1536 if not self.indices:
1537 self.index.generate_disposal_code(code)
1538 else:
1539 for i in self.indices:
1540 i.generate_disposal_code(code)
1542 def generate_result_code(self, code):
1543 if self.is_buffer_access:
1544 if code.globalstate.directives['nonecheck']:
1545 self.put_nonecheck(code)
1546 ptrcode = self.buffer_lookup_code(code)
1547 code.putln("%s = *%s;" % (
1548 self.result(),
1549 self.buffer_type.buffer_ptr_type.cast_code(ptrcode)))
1550 # Must incref the value we pulled out.
1551 if self.buffer_type.dtype.is_pyobject:
1552 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1553 elif self.type.is_pyobject:
1554 if self.index.type.is_int:
1555 function = "__Pyx_GetItemInt"
1556 index_code = self.index.result()
1557 else:
1558 function = "PyObject_GetItem"
1559 index_code = self.index.py_result()
1560 sign_code = ""
1561 code.putln(
1562 "%s = %s(%s, %s%s); if (!%s) %s" % (
1563 self.result(),
1564 function,
1565 self.base.py_result(),
1566 index_code,
1567 self.index_unsigned_parameter(),
1568 self.result(),
1569 code.error_goto(self.pos)))
1571 def generate_setitem_code(self, value_code, code):
1572 if self.index.type.is_int:
1573 function = "__Pyx_SetItemInt"
1574 index_code = self.index.result()
1575 else:
1576 function = "PyObject_SetItem"
1577 index_code = self.index.py_result()
1578 code.putln(
1579 "if (%s(%s, %s, %s%s) < 0) %s" % (
1580 function,
1581 self.base.py_result(),
1582 index_code,
1583 value_code,
1584 self.index_unsigned_parameter(),
1585 code.error_goto(self.pos)))
1587 def generate_buffer_setitem_code(self, rhs, code, op=""):
1588 # Used from generate_assignment_code and InPlaceAssignmentNode
1589 if code.globalstate.directives['nonecheck']:
1590 self.put_nonecheck(code)
1591 ptrexpr = self.buffer_lookup_code(code)
1592 if self.buffer_type.dtype.is_pyobject:
1593 # Must manage refcounts. Decref what is already there
1594 # and incref what we put in.
1595 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
1596 if rhs.is_temp:
1597 rhs_code = code.funcstate.allocate_temp(rhs.type)
1598 else:
1599 rhs_code = rhs.result()
1600 code.putln("%s = %s;" % (ptr, ptrexpr))
1601 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1602 ptr, rhs_code
1603 ))
1604 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1605 if rhs.is_temp:
1606 code.funcstate.release_temp(rhs_code)
1607 code.funcstate.release_temp(ptr)
1608 else:
1609 # Simple case
1610 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1612 def generate_assignment_code(self, rhs, code):
1613 self.generate_subexpr_evaluation_code(code)
1614 if self.is_buffer_access:
1615 self.generate_buffer_setitem_code(rhs, code)
1616 elif self.type.is_pyobject:
1617 self.generate_setitem_code(rhs.py_result(), code)
1618 else:
1619 code.putln(
1620 "%s = %s;" % (
1621 self.result(), rhs.result()))
1622 self.generate_subexpr_disposal_code(code)
1623 rhs.generate_disposal_code(code)
1625 def generate_deletion_code(self, code):
1626 self.generate_subexpr_evaluation_code(code)
1627 #if self.type.is_pyobject:
1628 if self.index.type.is_int:
1629 function = "PySequence_DelItem"
1630 index_code = self.index.result()
1631 else:
1632 function = "PyObject_DelItem"
1633 index_code = self.index.py_result()
1634 code.putln(
1635 "if (%s(%s, %s) < 0) %s" % (
1636 function,
1637 self.base.py_result(),
1638 index_code,
1639 code.error_goto(self.pos)))
1640 self.generate_subexpr_disposal_code(code)
1642 def buffer_lookup_code(self, code):
1643 # Assign indices to temps
1644 index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
1645 for temp, index in zip(index_temps, self.indices):
1646 code.putln("%s = %s;" % (temp, index.result()))
1647 # Generate buffer access code using these temps
1648 import Buffer
1649 # The above could happen because child_attrs is wrong somewhere so that
1650 # options are not propagated.
1651 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1652 index_signeds=[i.type.signed for i in self.indices],
1653 index_cnames=index_temps,
1654 options=code.globalstate.directives,
1655 pos=self.pos, code=code)
1657 def put_nonecheck(self, code):
1658 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1659 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1660 code.putln("__Pyx_RaiseNoneIndexingError();")
1661 code.putln(code.error_goto(self.pos))
1662 code.putln("}")
1664 class SliceIndexNode(ExprNode):
1665 # 2-element slice indexing
1667 # base ExprNode
1668 # start ExprNode or None
1669 # stop ExprNode or None
1671 subexprs = ['base', 'start', 'stop']
1673 def compile_time_value(self, denv):
1674 base = self.base.compile_time_value(denv)
1675 start = self.start.compile_time_value(denv)
1676 stop = self.stop.compile_time_value(denv)
1677 try:
1678 return base[start:stop]
1679 except Exception, e:
1680 self.compile_time_value_error(e)
1682 def analyse_target_declaration(self, env):
1683 pass
1685 def analyse_types(self, env):
1686 self.base.analyse_types(env)
1687 if self.start:
1688 self.start.analyse_types(env)
1689 if self.stop:
1690 self.stop.analyse_types(env)
1691 self.base = self.base.coerce_to_pyobject(env)
1692 c_int = PyrexTypes.c_py_ssize_t_type
1693 if self.start:
1694 self.start = self.start.coerce_to(c_int, env)
1695 if self.stop:
1696 self.stop = self.stop.coerce_to(c_int, env)
1697 self.type = py_object_type
1698 self.gil_check(env)
1699 self.is_temp = 1
1701 gil_message = "Slicing Python object"
1703 def generate_result_code(self, code):
1704 code.putln(
1705 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1706 self.result(),
1707 self.base.py_result(),
1708 self.start_code(),
1709 self.stop_code(),
1710 code.error_goto_if_null(self.result(), self.pos)))
1712 def generate_assignment_code(self, rhs, code):
1713 self.generate_subexpr_evaluation_code(code)
1714 code.put_error_if_neg(self.pos,
1715 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1716 self.base.py_result(),
1717 self.start_code(),
1718 self.stop_code(),
1719 rhs.result()))
1720 self.generate_subexpr_disposal_code(code)
1721 rhs.generate_disposal_code(code)
1723 def generate_deletion_code(self, code):
1724 self.generate_subexpr_evaluation_code(code)
1725 code.put_error_if_neg(self.pos,
1726 "PySequence_DelSlice(%s, %s, %s)" % (
1727 self.base.py_result(),
1728 self.start_code(),
1729 self.stop_code()))
1730 self.generate_subexpr_disposal_code(code)
1732 def start_code(self):
1733 if self.start:
1734 return self.start.result()
1735 else:
1736 return "0"
1738 def stop_code(self):
1739 if self.stop:
1740 return self.stop.result()
1741 else:
1742 return "PY_SSIZE_T_MAX"
1744 def calculate_result_code(self):
1745 # self.result() is not used, but this method must exist
1746 return "<unused>"
1749 class SliceNode(ExprNode):
1750 # start:stop:step in subscript list
1752 # start ExprNode
1753 # stop ExprNode
1754 # step ExprNode
1756 def compile_time_value(self, denv):
1757 start = self.start.compile_time_value(denv)
1758 stop = self.stop.compile_time_value(denv)
1759 step = step.step.compile_time_value(denv)
1760 try:
1761 return slice(start, stop, step)
1762 except Exception, e:
1763 self.compile_time_value_error(e)
1765 subexprs = ['start', 'stop', 'step']
1767 def analyse_types(self, env):
1768 self.start.analyse_types(env)
1769 self.stop.analyse_types(env)
1770 self.step.analyse_types(env)
1771 self.start = self.start.coerce_to_pyobject(env)
1772 self.stop = self.stop.coerce_to_pyobject(env)
1773 self.step = self.step.coerce_to_pyobject(env)
1774 self.type = py_object_type
1775 self.gil_check(env)
1776 self.is_temp = 1
1778 gil_message = "Constructing Python slice object"
1780 def generate_result_code(self, code):
1781 code.putln(
1782 "%s = PySlice_New(%s, %s, %s); %s" % (
1783 self.result(),
1784 self.start.py_result(),
1785 self.stop.py_result(),
1786 self.step.py_result(),
1787 code.error_goto_if_null(self.result(), self.pos)))
1790 class CallNode(ExprNode):
1791 def gil_check(self, env):
1792 # Make sure we're not in a nogil environment
1793 if env.nogil:
1794 error(self.pos, "Calling gil-requiring function without gil")
1797 class SimpleCallNode(CallNode):
1798 # Function call without keyword, * or ** args.
1800 # function ExprNode
1801 # args [ExprNode]
1802 # arg_tuple ExprNode or None used internally
1803 # self ExprNode or None used internally
1804 # coerced_self ExprNode or None used internally
1805 # wrapper_call bool used internally
1806 # has_optional_args bool used internally
1808 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1810 self = None
1811 coerced_self = None
1812 arg_tuple = None
1813 wrapper_call = False
1814 has_optional_args = False
1816 def compile_time_value(self, denv):
1817 function = self.function.compile_time_value(denv)
1818 args = [arg.compile_time_value(denv) for arg in self.args]
1819 try:
1820 return function(*args)
1821 except Exception, e:
1822 self.compile_time_value_error(e)
1824 def analyse_as_type(self, env):
1825 attr = self.function.magic_cython_method()
1826 if attr == 'pointer':
1827 if len(self.args) != 1:
1828 error(self.args.pos, "only one type allowed.")
1829 else:
1830 type = self.args[0].analyse_as_type(env)
1831 if not type:
1832 error(self.args[0].pos, "Unknown type")
1833 else:
1834 return PyrexTypes.CPtrType(type)
1836 def explicit_args_kwds(self):
1837 return self.args, None
1839 def analyse_types(self, env):
1840 function = self.function
1841 function.is_called = 1
1842 self.function.analyse_types(env)
1843 if function.is_attribute and function.is_py_attr and \
1844 function.attribute == "append" and len(self.args) == 1:
1845 # L.append(x) is almost always applied to a list
1846 self.py_func = self.function
1847 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1848 self.function.analyse_types(env)
1849 self.self = self.py_func.obj
1850 function.obj = CloneNode(self.self)
1851 env.use_utility_code(append_utility_code)
1852 if function.is_attribute and function.entry and function.entry.is_cmethod:
1853 # Take ownership of the object from which the attribute
1854 # was obtained, because we need to pass it as 'self'.
1855 self.self = function.obj
1856 function.obj = CloneNode(self.self)
1857 func_type = self.function_type()
1858 if func_type.is_pyobject:
1859 self.arg_tuple = TupleNode(self.pos, args = self.args)
1860 self.arg_tuple.analyse_types(env)
1861 self.args = None
1862 self.type = py_object_type
1863 self.gil_check(env)
1864 self.is_temp = 1
1865 else:
1866 for arg in self.args:
1867 arg.analyse_types(env)
1868 if self.self and func_type.args:
1869 # Coerce 'self' to the type expected by the method.
1870 expected_type = func_type.args[0].type
1871 self.coerced_self = CloneNode(self.self).coerce_to(
1872 expected_type, env)
1873 # Insert coerced 'self' argument into argument list.
1874 self.args.insert(0, self.coerced_self)
1875 self.analyse_c_function_call(env)
1877 def function_type(self):
1878 # Return the type of the function being called, coercing a function
1879 # pointer to a function if necessary.
1880 func_type = self.function.type
1881 if func_type.is_ptr:
1882 func_type = func_type.base_type
1883 return func_type
1885 def analyse_c_function_call(self, env):
1886 func_type = self.function_type()
1887 # Check function type
1888 if not func_type.is_cfunction:
1889 if not func_type.is_error:
1890 error(self.pos, "Calling non-function type '%s'" %
1891 func_type)
1892 self.type = PyrexTypes.error_type
1893 self.result_code = "<error>"
1894 return
1895 # Check no. of args
1896 max_nargs = len(func_type.args)
1897 expected_nargs = max_nargs - func_type.optional_arg_count
1898 actual_nargs = len(self.args)
1899 if actual_nargs < expected_nargs \
1900 or (not func_type.has_varargs and actual_nargs > max_nargs):
1901 expected_str = str(expected_nargs)
1902 if func_type.has_varargs:
1903 expected_str = "at least " + expected_str
1904 elif func_type.optional_arg_count:
1905 if actual_nargs < max_nargs:
1906 expected_str = "at least " + expected_str
1907 else:
1908 expected_str = "at most " + str(max_nargs)
1909 error(self.pos,
1910 "Call with wrong number of arguments (expected %s, got %s)"
1911 % (expected_str, actual_nargs))
1912 self.args = None
1913 self.type = PyrexTypes.error_type
1914 self.result_code = "<error>"
1915 return
1916 if func_type.optional_arg_count and expected_nargs != actual_nargs:
1917 self.has_optional_args = 1
1918 self.is_temp = 1
1919 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
1920 env.release_temp(self.opt_arg_struct)
1921 # Coerce arguments
1922 for i in range(min(max_nargs, actual_nargs)):
1923 formal_type = func_type.args[i].type
1924 self.args[i] = self.args[i].coerce_to(formal_type, env)
1925 for i in range(max_nargs, actual_nargs):
1926 if self.args[i].type.is_pyobject:
1927 error(self.args[i].pos,
1928 "Python object cannot be passed as a varargs parameter")
1929 # Calc result type and code fragment
1930 self.type = func_type.return_type
1931 if self.type.is_pyobject \
1932 or func_type.exception_value is not None \
1933 or func_type.exception_check:
1934 self.is_temp = 1
1935 if self.type.is_pyobject:
1936 self.result_ctype = py_object_type
1937 # C++ exception handler
1938 if func_type.exception_check == '+':
1939 if func_type.exception_value is None:
1940 env.use_utility_code(cpp_exception_utility_code)
1941 # Check gil
1942 if not func_type.nogil:
1943 self.gil_check(env)
1945 def calculate_result_code(self):
1946 return self.c_call_code()
1948 def c_call_code(self):
1949 func_type = self.function_type()
1950 if self.args is None or not func_type.is_cfunction:
1951 return "<error>"
1952 formal_args = func_type.args
1953 arg_list_code = []
1954 args = zip(formal_args, self.args)
1955 max_nargs = len(func_type.args)
1956 expected_nargs = max_nargs - func_type.optional_arg_count
1957 actual_nargs = len(self.args)
1958 for formal_arg, actual_arg in args[:expected_nargs]:
1959 arg_code = actual_arg.result_as(formal_arg.type)
1960 arg_list_code.append(arg_code)
1962 if func_type.is_overridable:
1963 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
1965 if func_type.optional_arg_count:
1966 if expected_nargs == actual_nargs:
1967 optional_args = 'NULL'
1968 else:
1969 optional_args = "&%s" % self.opt_arg_struct
1970 arg_list_code.append(optional_args)
1972 for actual_arg in self.args[len(formal_args):]:
1973 arg_list_code.append(actual_arg.result())
1974 result = "%s(%s)" % (self.function.result(),
1975 join(arg_list_code, ", "))
1976 # if self.wrapper_call or \
1977 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
1978 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
1979 return result
1981 def generate_result_code(self, code):
1982 func_type = self.function_type()
1983 if func_type.is_pyobject:
1984 arg_code = self.arg_tuple.py_result()
1985 code.putln(
1986 "%s = PyObject_Call(%s, %s, NULL); %s" % (
1987 self.result(),
1988 self.function.py_result(),
1989 arg_code,
1990 code.error_goto_if_null(self.result(), self.pos)))
1991 elif func_type.is_cfunction:
1992 if self.has_optional_args:
1993 actual_nargs = len(self.args)
1994 expected_nargs = len(func_type.args) - func_type.optional_arg_count
1995 code.putln("%s.%s = %s;" % (
1996 self.opt_arg_struct,
1997 Naming.pyrex_prefix + "n",
1998 len(self.args) - expected_nargs))
1999 args = zip(func_type.args, self.args)
2000 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2001 code.putln("%s.%s = %s;" % (
2002 self.opt_arg_struct,
2003 formal_arg.name,
2004 actual_arg.result_as(formal_arg.type)))
2005 exc_checks = []
2006 if self.type.is_pyobject:
2007 exc_checks.append("!%s" % self.result())
2008 else:
2009 exc_val = func_type.exception_value
2010 exc_check = func_type.exception_check
2011 if exc_val is not None:
2012 exc_checks.append("%s == %s" % (self.result(), exc_val))
2013 if exc_check:
2014 exc_checks.append("PyErr_Occurred()")
2015 if self.is_temp or exc_checks:
2016 rhs = self.c_call_code()
2017 if self.result():
2018 lhs = "%s = " % self.result()
2019 if self.is_temp and self.type.is_pyobject:
2020 #return_type = self.type # func_type.return_type
2021 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2022 # "from", return_type, "to pyobject" ###
2023 rhs = typecast(py_object_type, self.type, rhs)
2024 else:
2025 lhs = ""
2026 if func_type.exception_check == '+':
2027 if func_type.exception_value is None:
2028 raise_py_exception = "__Pyx_CppExn2PyErr()"
2029 elif func_type.exception_value.type.is_pyobject:
2030 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2031 else:
2032 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2033 code.putln(
2034 "try {%s%s;} catch(...) {%s; %s}" % (
2035 lhs,
2036 rhs,
2037 raise_py_exception,
2038 code.error_goto(self.pos)))
2039 else:
2040 if exc_checks:
2041 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2042 else:
2043 goto_error = ""
2044 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2046 class GeneralCallNode(CallNode):
2047 # General Python function call, including keyword,
2048 # * and ** arguments.
2050 # function ExprNode
2051 # positional_args ExprNode Tuple of positional arguments
2052 # keyword_args ExprNode or None Dict of keyword arguments
2053 # starstar_arg ExprNode or None Dict of extra keyword args
2055 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2057 def compile_time_value(self, denv):
2058 function = self.function.compile_time_value(denv)
2059 positional_args = self.positional_args.compile_time_value(denv)
2060 keyword_args = self.keyword_args.compile_time_value(denv)
2061 starstar_arg = self.starstar_arg.compile_time_value(denv)
2062 try:
2063 keyword_args.update(starstar_arg)
2064 return function(*positional_args, **keyword_args)
2065 except Exception, e:
2066 self.compile_time_value_error(e)
2068 def explicit_args_kwds(self):
2069 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2070 raise PostParseError(self.pos,
2071 'Compile-time keyword arguments must be explicit.')
2072 return self.positional_args.args, self.keyword_args
2074 def analyse_types(self, env):
2075 self.function.analyse_types(env)
2076 self.positional_args.analyse_types(env)
2077 if self.keyword_args:
2078 self.keyword_args.analyse_types(env)
2079 if self.starstar_arg:
2080 self.starstar_arg.analyse_types(env)
2081 self.function = self.function.coerce_to_pyobject(env)
2082 self.positional_args = \
2083 self.positional_args.coerce_to_pyobject(env)
2084 if self.starstar_arg:
2085 self.starstar_arg = \
2086 self.starstar_arg.coerce_to_pyobject(env)
2087 self.type = py_object_type
2088 self.gil_check(env)
2089 self.is_temp = 1
2091 def generate_result_code(self, code):
2092 if self.keyword_args and self.starstar_arg:
2093 code.put_error_if_neg(self.pos,
2094 "PyDict_Update(%s, %s)" % (
2095 self.keyword_args.py_result(),
2096 self.starstar_arg.py_result()))
2097 keyword_code = self.keyword_args.py_result()
2098 elif self.keyword_args:
2099 keyword_code = self.keyword_args.py_result()
2100 elif self.starstar_arg:
2101 keyword_code = self.starstar_arg.py_result()
2102 else:
2103 keyword_code = None
2104 if not keyword_code:
2105 call_code = "PyObject_Call(%s, %s, NULL)" % (
2106 self.function.py_result(),
2107 self.positional_args.py_result())
2108 else:
2109 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2110 self.function.py_result(),
2111 self.positional_args.py_result(),
2112 keyword_code)
2113 code.putln(
2114 "%s = %s; %s" % (
2115 self.result(),
2116 call_code,
2117 code.error_goto_if_null(self.result(), self.pos)))
2120 class AsTupleNode(ExprNode):
2121 # Convert argument to tuple. Used for normalising
2122 # the * argument of a function call.
2124 # arg ExprNode
2126 subexprs = ['arg']
2128 def compile_time_value(self, denv):
2129 arg = self.arg.compile_time_value(denv)
2130 try:
2131 return tuple(arg)
2132 except Exception, e:
2133 self.compile_time_value_error(e)
2135 def analyse_types(self, env):
2136 self.arg.analyse_types(env)
2137 self.arg = self.arg.coerce_to_pyobject(env)
2138 self.type = py_object_type
2139 self.gil_check(env)
2140 self.is_temp = 1
2142 gil_message = "Constructing Python tuple"
2144 def generate_result_code(self, code):
2145 code.putln(
2146 "%s = PySequence_Tuple(%s); %s" % (
2147 self.result(),
2148 self.arg.py_result(),
2149 code.error_goto_if_null(self.result(), self.pos)))
2152 class AttributeNode(ExprNode):
2153 # obj.attribute
2155 # obj ExprNode
2156 # attribute string
2157 # needs_none_check boolean Used if obj is an extension type.
2158 # If set to True, it is known that the type is not None.
2160 # Used internally:
2162 # is_py_attr boolean Is a Python getattr operation
2163 # member string C name of struct member
2164 # is_called boolean Function call is being done on result
2165 # entry Entry Symbol table entry of attribute
2166 # interned_attr_cname string C name of interned attribute name
2168 is_attribute = 1
2169 subexprs = ['obj']
2171 type = PyrexTypes.error_type
2172 entry = None
2173 is_called = 0
2174 needs_none_check = True
2176 def magic_cython_method(self):
2177 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2178 return self.attribute
2180 def coerce_to(self, dst_type, env):
2181 # If coercing to a generic pyobject and this is a cpdef function
2182 # we can create the corresponding attribute
2183 if dst_type is py_object_type:
2184 entry = self.entry
2185 if entry and entry.is_cfunction and entry.as_variable:
2186 # must be a cpdef function
2187 self.is_temp = 1
2188 self.entry = entry.as_variable
2189 self.analyse_as_python_attribute(env)
2190 return self
2191 return ExprNode.coerce_to(self, dst_type, env)
2193 def compile_time_value(self, denv):
2194 attr = self.attribute
2195 if attr.beginswith("__") and attr.endswith("__"):
2196 self.error("Invalid attribute name '%s' in compile-time expression"
2197 % attr)
2198 return None
2199 obj = self.arg.compile_time_value(denv)
2200 try:
2201 return getattr(obj, attr)
2202 except Exception, e:
2203 self.compile_time_value_error(e)
2205 def analyse_target_declaration(self, env):
2206 pass
2208 def analyse_target_types(self, env):
2209 self.analyse_types(env, target = 1)
2211 def analyse_types(self, env, target = 0):
2212 if self.analyse_as_cimported_attribute(env, target):
2213 return
2214 if not target and self.analyse_as_unbound_cmethod(env):
2215 return
2216 self.analyse_as_ordinary_attribute(env, target)
2218 def analyse_as_cimported_attribute(self, env, target):
2219 # Try to interpret this as a reference to an imported
2220 # C const, type, var or function. If successful, mutates
2221 # this node into a NameNode and returns 1, otherwise
2222 # returns 0.
2223 module_scope = self.obj.analyse_as_module(env)
2224 if module_scope:
2225 entry = module_scope.lookup_here(self.attribute)
2226 if entry and (
2227 entry.is_cglobal or entry.is_cfunction
2228 or entry.is_type or entry.is_const):
2229 self.mutate_into_name_node(env, entry, target)
2230 return 1
2231 return 0
2233 def analyse_as_unbound_cmethod(self, env):
2234 # Try to interpret this as a reference to an unbound
2235 # C method of an extension type. If successful, mutates
2236 # this node into a NameNode and returns 1, otherwise
2237 # returns 0.
2238 type = self.obj.analyse_as_extension_type(env)
2239 if type:
2240 entry = type.scope.lookup_here(self.attribute)
2241 if entry and entry.is_cmethod:
2242 # Create a temporary entry describing the C method
2243 # as an ordinary function.
2244 ubcm_entry = Symtab.Entry(entry.name,
2245 "%s->%s" % (type.vtabptr_cname, entry.cname),
2246 entry.type)
2247 ubcm_entry.is_cfunction = 1
2248 ubcm_entry.func_cname = entry.func_cname
2249 ubcm_entry.is_unbound_cmethod = 1
2250 self.mutate_into_name_node(env, ubcm_entry, None)
2251 return 1
2252 return 0
2254 def analyse_as_type(self, env):
2255 module_scope = self.obj.analyse_as_module(env)
2256 if module_scope:
2257 return module_scope.lookup_type(self.attribute)
2258 return None
2260 def analyse_as_extension_type(self, env):
2261 # Try to interpret this as a reference to an extension type
2262 # in a cimported module. Returns the extension type, or None.
2263 module_scope = self.obj.analyse_as_module(env)
2264 if module_scope:
2265 entry = module_scope.lookup_here(self.attribute)
2266 if entry and entry.is_type and entry.type.is_extension_type:
2267 return entry.type
2268 return None
2270 def analyse_as_module(self, env):
2271 # Try to interpret this as a reference to a cimported module
2272 # in another cimported module. Returns the module scope, or None.
2273 module_scope = self.obj.analyse_as_module(env)
2274 if module_scope:
2275 entry = module_scope.lookup_here(self.attribute)
2276 if entry and entry.as_module:
2277 return entry.as_module
2278 return None
2280 def mutate_into_name_node(self, env, entry, target):
2281 # Mutate this node into a NameNode and complete the
2282 # analyse_types phase.
2283 self.__class__ = NameNode
2284 self.name = self.attribute
2285 self.entry = entry
2286 del self.obj
2287 del self.attribute
2288 if target:
2289 NameNode.analyse_target_types(self, env)
2290 else:
2291 NameNode.analyse_rvalue_entry(self, env)
2293 def analyse_as_ordinary_attribute(self, env, target):
2294 self.obj.analyse_types(env)
2295 self.analyse_attribute(env)
2296 if self.entry and self.entry.is_cmethod and not self.is_called:
2297 # error(self.pos, "C method can only be called")
2298 pass
2299 ## Reference to C array turns into pointer to first element.
2300 #while self.type.is_array:
2301 # self.type = self.type.element_ptr_type()
2302 if self.is_py_attr:
2303 if not target:
2304 self.is_temp = 1
2305 self.result_ctype = py_object_type
2307 def analyse_attribute(self, env):
2308 # Look up attribute and set self.type and self.member.
2309 self.is_py_attr = 0
2310 self.member = self.attribute
2311 if self.obj.type.is_string:
2312 self.obj = self.obj.coerce_to_pyobject(env)
2313 obj_type = self.obj.type
2314 if obj_type.is_ptr or obj_type.is_array:
2315 obj_type = obj_type.base_type
2316 self.op = "->"
2317 elif obj_type.is_extension_type:
2318 self.op = "->"
2319 else:
2320 self.op = "."
2321 if obj_type.has_attributes:
2322 entry = None
2323 if obj_type.attributes_known():
2324 entry = obj_type.scope.lookup_here(self.attribute)
2325 if entry and entry.is_member:
2326 entry = None
2327 else:
2328 error(self.pos,
2329 "Cannot select attribute of incomplete type '%s'"
2330 % obj_type)
2331 self.type = PyrexTypes.error_type
2332 return
2333 self.entry = entry
2334 if entry:
2335 if obj_type.is_extension_type and entry.name == "__weakref__":
2336 error(self.pos, "Illegal use of special attribute __weakref__")
2337 # methods need the normal attribute lookup
2338 # because they do not have struct entries
2339 if entry.is_variable or entry.is_cmethod:
2340 self.type = entry.type
2341 self.member = entry.cname
2342 return
2343 else:
2344 # If it's not a variable or C method, it must be a Python
2345 # method of an extension type, so we treat it like a Python
2346 # attribute.
2347 pass
2348 # If we get here, the base object is not a struct/union/extension
2349 # type, or it is an extension type and the attribute is either not
2350 # declared or is declared as a Python method. Treat it as a Python
2351 # attribute reference.
2352 self.analyse_as_python_attribute(env)
2354 def analyse_as_python_attribute(self, env):
2355 obj_type = self.obj.type
2356 self.member = self.attribute
2357 if obj_type.is_pyobject:
2358 self.type = py_object_type
2359 self.is_py_attr = 1
2360 self.interned_attr_cname = env.intern_identifier(self.attribute)
2361 self.gil_check(env)
2362 else:
2363 if not obj_type.is_error:
2364 error(self.pos,
2365 "Object of type '%s' has no attribute '%s'" %
2366 (obj_type, self.attribute))
2368 gil_message = "Accessing Python attribute"
2370 def is_simple(self):
2371 if self.obj:
2372 return self.result_in_temp() or self.obj.is_simple()
2373 else:
2374 return NameNode.is_simple(self)
2376 def is_lvalue(self):
2377 if self.obj:
2378 return 1
2379 else:
2380 return NameNode.is_lvalue(self)
2382 def is_ephemeral(self):
2383 if self.obj:
2384 return self.obj.is_ephemeral()
2385 else:
2386 return NameNode.is_ephemeral(self)
2388 def calculate_result_code(self):
2389 #print "AttributeNode.calculate_result_code:", self.member ###
2390 #print "...obj node =", self.obj, "code", self.obj.result() ###
2391 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2392 obj = self.obj
2393 obj_code = obj.result_as(obj.type)
2394 #print "...obj_code =", obj_code ###
2395 if self.entry and self.entry.is_cmethod:
2396 if obj.type.is_extension_type:
2397 return "((struct %s *)%s%s%s)->%s" % (
2398 obj.type.vtabstruct_cname, obj_code, self.op,
2399 obj.type.vtabslot_cname, self.member)
2400 else:
2401 return self.member
2402 else:
2403 return "%s%s%s" % (obj_code, self.op, self.member)
2405 def generate_result_code(self, code):
2406 if self.is_py_attr:
2407 code.putln(
2408 '%s = PyObject_GetAttr(%s, %s); %s' % (
2409 self.result(),
2410 self.obj.py_result(),
2411 self.interned_attr_cname,
2412 code.error_goto_if_null(self.result(), self.pos)))
2413 else:
2414 # result_code contains what is needed, but we may need to insert
2415 # a check and raise an exception
2416 if (self.obj.type.is_extension_type
2417 and self.needs_none_check
2418 and code.globalstate.directives['nonecheck']):
2419 self.put_nonecheck(code)
2421 def generate_assignment_code(self, rhs, code):
2422 self.obj.generate_evaluation_code(code)
2423 if self.is_py_attr:
2424 code.put_error_if_neg(self.pos,
2425 'PyObject_SetAttr(%s, %s, %s)' % (
2426 self.obj.py_result(),
2427 self.interned_attr_cname,
2428 rhs.py_result()))
2429 rhs.generate_disposal_code(code)
2430 else:
2431 if (self.obj.type.is_extension_type
2432 and self.needs_none_check
2433 and code.globalstate.directives['nonecheck']):
2434 self.put_nonecheck(code)
2436 select_code = self.result()
2437 if self.type.is_pyobject:
2438 rhs.make_owned_reference(code)
2439 code.put_decref(select_code, self.ctype())
2440 code.putln(
2441 "%s = %s;" % (
2442 select_code,
2443 rhs.result_as(self.ctype())))
2444 #rhs.result()))
2445 rhs.generate_post_assignment_code(code)
2446 self.obj.generate_disposal_code(code)
2448 def generate_deletion_code(self, code):
2449 self.obj.generate_evaluation_code(code)
2450 if self.is_py_attr:
2451 code.put_error_if_neg(self.pos,
2452 'PyObject_DelAttr(%s, %s)' % (
2453 self.obj.py_result(),
2454 self.interned_attr_cname))
2455 else:
2456 error(self.pos, "Cannot delete C attribute of extension type")
2457 self.obj.generate_disposal_code(code)
2459 def annotate(self, code):
2460 if self.is_py_attr:
2461 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2462 else:
2463 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2465 def put_nonecheck(self, code):
2466 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2467 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2468 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2469 code.putln(code.error_goto(self.pos))
2470 code.putln("}")
2473 #-------------------------------------------------------------------
2475 # Constructor nodes
2477 #-------------------------------------------------------------------
2479 class SequenceNode(ExprNode):
2480 # Base class for list and tuple constructor nodes.
2481 # Contains common code for performing sequence unpacking.
2483 # args [ExprNode]
2484 # iterator ExprNode
2485 # unpacked_items [ExprNode] or None
2486 # coerced_unpacked_items [ExprNode] or None
2488 subexprs = ['args']
2490 is_sequence_constructor = 1
2491 unpacked_items = None
2493 def compile_time_value_list(self, denv):
2494 return [arg.compile_time_value(denv) for arg in self.args]
2496 def analyse_target_declaration(self, env):
2497 for arg in self.args:
2498 arg.analyse_target_declaration(env)
2500 def analyse_types(self, env, skip_children=False):
2501 for i in range(len(self.args)):
2502 arg = self.args[i]
2503 if not skip_children: arg.analyse_types(env)
2504 self.args[i] = arg.coerce_to_pyobject(env)
2505 self.type = py_object_type
2506 self.gil_check(env)
2507 self.is_temp = 1
2509 def analyse_target_types(self, env):
2510 self.iterator = PyTempNode(self.pos, env)
2511 self.unpacked_items = []
2512 self.coerced_unpacked_items = []
2513 for arg in self.args:
2514 arg.analyse_target_types(env)
2515 unpacked_item = PyTempNode(self.pos, env)
2516 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2517 self.unpacked_items.append(unpacked_item)
2518 self.coerced_unpacked_items.append(coerced_unpacked_item)
2519 self.type = py_object_type
2520 env.use_utility_code(unpacking_utility_code)
2522 def allocate_target_temps(self, env, rhs):
2523 self.iterator.allocate_temps(env)
2524 for arg, node in zip(self.args, self.coerced_unpacked_items):
2525 node.allocate_temps(env)
2526 arg.allocate_target_temps(env, node)
2527 #arg.release_target_temp(env)
2528 #node.release_temp(env)
2529 if rhs:
2530 rhs.release_temp(env)
2531 self.iterator.release_temp(env)
2533 # def release_target_temp(self, env):
2534 # #for arg in self.args:
2535 # # arg.release_target_temp(env)
2536 # #for node in self.coerced_unpacked_items:
2537 # # node.release_temp(env)
2538 # self.iterator.release_temp(env)
2540 def generate_result_code(self, code):
2541 self.generate_operation_code(code)
2543 def generate_assignment_code(self, rhs, code):
2544 code.putln(
2545 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2546 rhs.py_result(),
2547 rhs.py_result(),
2548 len(self.args)))
2549 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2550 for i in range(len(self.args)):
2551 item = self.unpacked_items[i]
2552 code.putln(
2553 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2554 item.result(),
2555 i))
2556 code.put_incref(item.result(), item.ctype())
2557 value_node = self.coerced_unpacked_items[i]
2558 value_node.generate_evaluation_code(code)
2559 self.args[i].generate_assignment_code(value_node, code)
2561 rhs.generate_disposal_code(code)
2562 code.putln("}")
2563 code.putln("else {")
2565 code.putln(
2566 "%s = PyObject_GetIter(%s); %s" % (
2567 self.iterator.result(),
2568 rhs.py_result(),
2569 code.error_goto_if_null(self.iterator.result(), self.pos)))
2570 rhs.generate_disposal_code(code)
2571 for i in range(len(self.args)):
2572 item = self.unpacked_items[i]
2573 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2574 self.iterator.py_result(), i)
2575 code.putln(
2576 "%s = %s; %s" % (
2577 item.result(),
2578 typecast(item.ctype(), py_object_type, unpack_code),
2579 code.error_goto_if_null(item.result(), self.pos)))
2580 value_node = self.coerced_unpacked_items[i]
2581 value_node.generate_evaluation_code(code)
2582 self.args[i].generate_assignment_code(value_node, code)
2583 code.put_error_if_neg(self.pos,
2584 "__Pyx_EndUnpack(%s)" % (
2585 self.iterator.py_result()))
2586 if debug_disposal_code:
2587 print("UnpackNode.generate_assignment_code:")
2588 print("...generating disposal code for %s" % self.iterator)
2589 self.iterator.generate_disposal_code(code)
2591 code.putln("}")
2593 def annotate(self, code):
2594 for arg in self.args:
2595 arg.annotate(code)
2596 if self.unpacked_items:
2597 for arg in self.unpacked_items:
2598 arg.annotate(code)
2599 for arg in self.coerced_unpacked_items:
2600 arg.annotate(code)
2603 class TupleNode(SequenceNode):
2604 # Tuple constructor.
2606 gil_message = "Constructing Python tuple"
2608 def analyse_types(self, env, skip_children=False):
2609 if len(self.args) == 0:
2610 self.is_temp = 0
2611 self.is_literal = 1
2612 else:
2613 SequenceNode.analyse_types(self, env, skip_children)
2614 self.type = tuple_type
2616 def calculate_result_code(self):
2617 if len(self.args) > 0:
2618 error(self.pos, "Positive length tuples must be constructed.")
2619 else:
2620 return Naming.empty_tuple
2622 def compile_time_value(self, denv):
2623 values = self.compile_time_value_list(denv)
2624 try:
2625 return tuple(values)
2626 except Exception, e:
2627 self.compile_time_value_error(e)
2629 def generate_operation_code(self, code):
2630 if len(self.args) == 0:
2631 # result_code is Naming.empty_tuple
2632 return
2633 code.putln(
2634 "%s = PyTuple_New(%s); %s" % (
2635 self.result(),
2636 len(self.args),
2637 code.error_goto_if_null(self.result(), self.pos)))
2638 for i in range(len(self.args)):
2639 arg = self.args[i]
2640 if not arg.result_in_temp():
2641 code.put_incref(arg.result(), arg.ctype())
2642 code.putln(
2643 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2644 self.result(),
2645 i,
2646 arg.py_result()))
2648 def generate_subexpr_disposal_code(self, code):
2649 # We call generate_post_assignment_code here instead
2650 # of generate_disposal_code, because values were stored
2651 # in the tuple using a reference-stealing operation.
2652 for arg in self.args:
2653 arg.generate_post_assignment_code(code)
2656 class ListNode(SequenceNode):
2657 # List constructor.
2659 gil_message = "Constructing Python list"
2661 def analyse_types(self, env):
2662 for arg in self.args:
2663 arg.analyse_types(env)
2664 self.is_temp = 1
2665 self.type = PyrexTypes.unspecified_type
2667 def coerce_to(self, dst_type, env):
2668 if dst_type.is_pyobject:
2669 self.gil_check(env)
2670 self.type = list_type
2671 for i in range(len(self.args)):
2672 arg = self.args[i]
2673 if not arg.type.is_pyobject:
2674 self.args[i] = arg.coerce_to_pyobject(env)
2675 if not self.type.subtype_of(dst_type):
2676 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2677 elif dst_type.is_ptr:
2678 base_type = dst_type.base_type
2679 self.type = dst_type
2680 for i in range(len(self.args)):
2681 arg = self.args[i]
2682 self.args[i] = arg.coerce_to(base_type, env)
2683 elif dst_type.is_struct:
2684 if len(self.args) > len(dst_type.scope.var_entries):
2685 error(self.pos, "Too may members for '%s'" % dst_type)
2686 else:
2687 if len(self.args) < len(dst_type.scope.var_entries):
2688 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
2689 for i, (arg, member) in enumerate(zip(self.args, dst_type.scope.var_entries)):
2690 self.args[i] = arg.coerce_to(member.type, env)
2691 self.type = dst_type
2692 else:
2693 self.type = error_type
2694 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2695 return self
2697 def compile_time_value(self, denv):
2698 return self.compile_time_value_list(denv)
2700 def generate_operation_code(self, code):
2701 if self.type.is_pyobject:
2702 code.putln("%s = PyList_New(%s); %s" %
2703 (self.result(),
2704 len(self.args),
2705 code.error_goto_if_null(self.result(), self.pos)))
2706 for i in range(len(self.args)):
2707 arg = self.args[i]
2708 #if not arg.is_temp:
2709 if not arg.result_in_temp():
2710 code.put_incref(arg.result(), arg.ctype())
2711 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2712 (self.result(),
2713 i,
2714 arg.py_result()))
2715 elif self.type.is_ptr:
2716 code.putln("%s = (%s[]) {" % (self.result(), self.type.base_type))
2717 for arg in self.args:
2718 code.put(arg.result())
2719 code.put(", ")
2720 code.putln();
2721 code.putln("};")
2722 else:
2723 for arg, member in zip(self.args, self.type.scope.var_entries):
2724 code.putln("%s.%s = %s;" % (
2725 self.result(),
2726 member.cname,
2727 arg.result()))
2729 def generate_subexpr_disposal_code(self, code):
2730 # We call generate_post_assignment_code here instead
2731 # of generate_disposal_code, because values were stored
2732 # in the list using a reference-stealing operation.
2733 for arg in self.args:
2734 arg.generate_post_assignment_code(code)
2737 class ListComprehensionNode(SequenceNode):
2739 subexprs = []
2740 is_sequence_constructor = 0 # not unpackable
2742 child_attrs = ["loop", "append"]
2744 def analyse_types(self, env):
2745 self.type = list_type
2746 self.is_temp = 1
2747 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2749 def allocate_temps(self, env, result = None):
2750 if debug_temp_alloc:
2751 print("%s Allocating temps" % self)
2752 self.allocate_temp(env, result)
2753 self.loop.analyse_declarations(env)
2754 self.loop.analyse_expressions(env)
2756 def generate_operation_code(self, code):
2757 code.putln("%s = PyList_New(%s); %s" %
2758 (self.result(),
2759 0,
2760 code.error_goto_if_null(self.result(), self.pos)))
2761 self.loop.generate_execution_code(code)
2763 def annotate(self, code):
2764 self.loop.annotate(code)
2767 class ListComprehensionAppendNode(ExprNode):
2769 # Need to be careful to avoid infinite recursion:
2770 # target must not be in child_attrs/subexprs
2771 subexprs = ['expr']
2773 def analyse_types(self, env):
2774 self.expr.analyse_types(env)
2775 if self.expr.type != py_object_type:
2776 self.expr = self.expr.coerce_to_pyobject(env)
2777 self.type = PyrexTypes.c_int_type
2778 self.is_temp = 1
2780 def generate_result_code(self, code):
2781 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
2782 (self.result(),
2783 self.target.result(),
2784 self.expr.result(),
2785 code.error_goto_if(self.result(), self.pos)))
2788 class DictNode(ExprNode):
2789 # Dictionary constructor.
2791 # key_value_pairs [DictItemNode]
2793 subexprs = ['key_value_pairs']
2795 def compile_time_value(self, denv):
2796 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2797 for item in self.key_value_pairs]
2798 try:
2799 return dict(pairs)
2800 except Exception, e:
2801 self.compile_time_value_error(e)
2803 def analyse_types(self, env):
2804 for item in self.key_value_pairs:
2805 item.analyse_types(env)
2806 self.type = dict_type
2807 self.gil_check(env)
2808 self.is_temp = 1
2810 gil_message = "Constructing Python dict"
2812 def allocate_temps(self, env, result = None):
2813 # Custom method used here because key-value
2814 # pairs are evaluated and used one at a time.
2815 self.allocate_temp(env, result)
2816 for item in self.key_value_pairs:
2817 item.key.allocate_temps(env)
2818 item.value.allocate_temps(env)
2819 item.key.release_temp(env)
2820 item.value.release_temp(env)
2822 def generate_evaluation_code(self, code):
2823 # Custom method used here because key-value
2824 # pairs are evaluated and used one at a time.
2825 code.putln(
2826 "%s = PyDict_New(); %s" % (
2827 self.result(),
2828 code.error_goto_if_null(self.result(), self.pos)))
2829 for item in self.key_value_pairs:
2830 item.generate_evaluation_code(code)
2831 code.put_error_if_neg(self.pos,
2832 "PyDict_SetItem(%s, %s, %s)" % (
2833 self.result(),
2834 item.key.py_result(),
2835 item.value.py_result()))
2836 item.generate_disposal_code(code)
2838 def annotate(self, code):
2839 for item in self.key_value_pairs:
2840 item.annotate(code)
2842 class DictItemNode(ExprNode):
2843 # Represents a single item in a DictNode
2845 # key ExprNode
2846 # value ExprNode
2847 subexprs = ['key', 'value']
2849 def analyse_types(self, env):
2850 self.key.analyse_types(env)
2851 self.value.analyse_types(env)
2852 self.key = self.key.coerce_to_pyobject(env)
2853 self.value = self.value.coerce_to_pyobject(env)
2855 def generate_evaluation_code(self, code):
2856 self.key.generate_evaluation_code(code)
2857 self.value.generate_evaluation_code(code)
2859 def generate_disposal_code(self, code):
2860 self.key.generate_disposal_code(code)
2861 self.value.generate_disposal_code(code)
2863 def __iter__(self):
2864 return iter([self.key, self.value])
2867 class ClassNode(ExprNode):
2868 # Helper class used in the implementation of Python
2869 # class definitions. Constructs a class object given
2870 # a name, tuple of bases and class dictionary.
2872 # name EncodedString Name of the class
2873 # cname string Class name as a Python string
2874 # bases ExprNode Base class tuple
2875 # dict ExprNode Class dict (not owned by this node)
2876 # doc ExprNode or None Doc string
2877 # module_name string Name of defining module
2879 subexprs = ['bases', 'doc']
2881 def analyse_types(self, env):
2882 self.cname = env.intern_identifier(self.name)
2883 self.bases.analyse_types(env)
2884 if self.doc:
2885 self.doc.analyse_types(env)
2886 self.doc = self.doc.coerce_to_pyobject(env)
2887 self.module_name = env.global_scope().qualified_name
2888 self.type = py_object_type
2889 self.gil_check(env)
2890 self.is_temp = 1
2891 env.use_utility_code(create_class_utility_code);
2893 gil_message = "Constructing Python class"
2895 def generate_result_code(self, code):
2896 if self.doc:
2897 code.put_error_if_neg(self.pos,
2898 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2899 self.dict.py_result(),
2900 self.doc.py_result()))
2901 code.putln(
2902 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
2903 self.result(),
2904 self.bases.py_result(),
2905 self.dict.py_result(),
2906 self.cname,
2907 self.module_name,
2908 code.error_goto_if_null(self.result(), self.pos)))
2911 class UnboundMethodNode(ExprNode):
2912 # Helper class used in the implementation of Python
2913 # class definitions. Constructs an unbound method
2914 # object from a class and a function.
2916 # class_cname string C var holding the class object
2917 # function ExprNode Function object
2919 subexprs = ['function']
2921 def analyse_types(self, env):
2922 self.function.analyse_types(env)
2923 self.type = py_object_type
2924 self.gil_check(env)
2925 self.is_temp = 1
2927 gil_message = "Constructing an unbound method"
2929 def generate_result_code(self, code):
2930 code.putln(
2931 "%s = PyMethod_New(%s, 0, %s); %s" % (
2932 self.result(),
2933 self.function.py_result(),
2934 self.class_cname,
2935 code.error_goto_if_null(self.result(), self.pos)))
2938 class PyCFunctionNode(AtomicExprNode):
2939 # Helper class used in the implementation of Python
2940 # class definitions. Constructs a PyCFunction object
2941 # from a PyMethodDef struct.
2943 # pymethdef_cname string PyMethodDef structure
2945 def analyse_types(self, env):
2946 self.type = py_object_type
2947 self.gil_check(env)
2948 self.is_temp = 1
2950 gil_message = "Constructing Python function"
2952 def generate_result_code(self, code):
2953 code.putln(
2954 "%s = PyCFunction_New(&%s, 0); %s" % (
2955 self.result(),
2956 self.pymethdef_cname,
2957 code.error_goto_if_null(self.result(), self.pos)))
2959 #-------------------------------------------------------------------
2961 # Unary operator nodes
2963 #-------------------------------------------------------------------
2965 compile_time_unary_operators = {
2966 'not': operator.not_,
2967 '~': operator.inv,
2968 '-': operator.neg,
2969 '+': operator.pos,
2972 class UnopNode(ExprNode):
2973 # operator string
2974 # operand ExprNode
2976 # Processing during analyse_expressions phase:
2978 # analyse_c_operation
2979 # Called when the operand is not a pyobject.
2980 # - Check operand type and coerce if needed.
2981 # - Determine result type and result code fragment.
2982 # - Allocate temporary for result if needed.
2984 subexprs = ['operand']
2986 def compile_time_value(self, denv):
2987 func = compile_time_unary_operators.get(self.operator)
2988 if not func:
2989 error(self.pos,
2990 "Unary '%s' not supported in compile-time expression"
2991 % self.operator)
2992 operand = self.operand.compile_time_value(denv)
2993 try:
2994 return func(operand)
2995 except Exception, e:
2996 self.compile_time_value_error(e)
2998 def analyse_types(self, env):
2999 self.operand.analyse_types(env)
3000 if self.is_py_operation():
3001 self.coerce_operand_to_pyobject(env)
3002 self.type = py_object_type
3003 self.gil_check(env)
3004 self.is_temp = 1
3005 else:
3006 self.analyse_c_operation(env)
3008 def check_const(self):
3009 self.operand.check_const()
3011 def is_py_operation(self):
3012 return self.operand.type.is_pyobject
3014 def coerce_operand_to_pyobject(self, env):
3015 self.operand = self.operand.coerce_to_pyobject(env)
3017 def generate_result_code(self, code):
3018 if self.operand.type.is_pyobject:
3019 self.generate_py_operation_code(code)
3020 else:
3021 if self.is_temp:
3022 self.generate_c_operation_code(code)
3024 def generate_py_operation_code(self, code):
3025 function = self.py_operation_function()
3026 code.putln(
3027 "%s = %s(%s); %s" % (
3028 self.result(),
3029 function,
3030 self.operand.py_result(),
3031 code.error_goto_if_null(self.result(), self.pos)))
3033 def type_error(self):
3034 if not self.operand.type.is_error:
3035 error(self.pos, "Invalid operand type for '%s' (%s)" %
3036 (self.operator, self.operand.type))
3037 self.type = PyrexTypes.error_type
3040 class NotNode(ExprNode):
3041 # 'not' operator
3043 # operand ExprNode
3045 def compile_time_value(self, denv):
3046 operand = self.operand.compile_time_value(denv)
3047 try:
3048 return not operand
3049 except Exception, e:
3050 self.compile_time_value_error(e)
3052 subexprs = ['operand']
3054 def analyse_types(self, env):
3055 self.operand.analyse_types(env)
3056 self.operand = self.operand.coerce_to_boolean(env)
3057 self.type = PyrexTypes.c_bint_type
3059 def calculate_result_code(self):
3060 return "(!%s)" % self.operand.result()
3062 def generate_result_code(self, code):
3063 pass
3066 class UnaryPlusNode(UnopNode):
3067 # unary '+' operator
3069 operator = '+'
3071 def analyse_c_operation(self, env):
3072 self.type = self.operand.type
3074 def py_operation_function(self):
3075 return "PyNumber_Positive"
3077 def calculate_result_code(self):
3078 return self.operand.result()
3081 class UnaryMinusNode(UnopNode):
3082 # unary '-' operator
3084 operator = '-'
3086 def analyse_c_operation(self, env):
3087 if self.operand.type.is_numeric:
3088 self.type = self.operand.type
3089 else:
3090 self.type_error()
3092 def py_operation_function(self):
3093 return "PyNumber_Negative"
3095 def calculate_result_code(self):
3096 return "(-%s)" % self.operand.result()
3099 class TildeNode(UnopNode):
3100 # unary '~' operator
3102 def analyse_c_operation(self, env):
3103 if self.operand.type.is_int:
3104 self.type = self.operand.type
3105 else:
3106 self.type_error()
3108 def py_operation_function(self):
3109 return "PyNumber_Invert"
3111 def calculate_result_code(self):
3112 return "(~%s)" % self.operand.result()
3115 class AmpersandNode(ExprNode):
3116 # The C address-of operator.
3118 # operand ExprNode
3120 subexprs = ['operand']
3122 def analyse_types(self, env):
3123 self.operand.analyse_types(env)
3124 argtype = self.operand.type
3125 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3126 self.error("Taking address of non-lvalue")
3127 return
3128 if argtype.is_pyobject:
3129 self.error("Cannot take address of Python variable")
3130 return
3131 self.type = PyrexTypes.c_ptr_type(argtype)
3133 def check_const(self):
3134 self.operand.check_const_addr()
3136 def error(self, mess):
3137 error(self.pos, mess)
3138 self.type = PyrexTypes.error_type
3139 self.result_code = "<error>"
3141 def calculate_result_code(self):
3142 return "(&%s)" % self.operand.result()
3144 def generate_result_code(self, code):
3145 pass
3148 unop_node_classes = {
3149 "+": UnaryPlusNode,
3150 "-": UnaryMinusNode,
3151 "~": TildeNode,
3154 def unop_node(pos, operator, operand):
3155 # Construct unnop node of appropriate class for
3156 # given operator.
3157 if isinstance(operand, IntNode) and operator == '-':
3158 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3159 elif isinstance(operand, UnopNode) and operand.operator == operator:
3160 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3161 return unop_node_classes[operator](pos,
3162 operator = operator,
3163 operand = operand)
3166 class TypecastNode(ExprNode):
3167 # C type cast
3169 # operand ExprNode
3170 # base_type CBaseTypeNode
3171 # declarator CDeclaratorNode
3173 # If used from a transform, one can if wanted specify the attribute
3174 # "type" directly and leave base_type and declarator to None
3176 subexprs = ['operand']
3177 base_type = declarator = type = None
3179 def analyse_types(self, env):
3180 if self.type is None:
3181 base_type = self.base_type.analyse(env)
3182 _, self.type = self.declarator.analyse(base_type, env)
3183 if self.type.is_cfunction:
3184 error(self.pos,
3185 "Cannot cast to a function type")
3186 self.type = PyrexTypes.error_type
3187 self.operand.analyse_types(env)
3188 to_py = self.type.is_pyobject
3189 from_py = self.operand.type.is_pyobject
3190 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3191 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3192 if to_py and not from_py:
3193 if self.operand.type.to_py_function:
3194 self.result_ctype = py_object_type
3195 self.operand = self.operand.coerce_to_pyobject(env)
3196 else:
3197 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3198 self.operand = self.operand.coerce_to_simple(env)
3199 elif from_py and not to_py:
3200 if self.type.from_py_function:
3201 self.operand = self.operand.coerce_to(self.type, env)
3202 else:
3203 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3204 elif from_py and to_py:
3205 if self.typecheck and self.type.is_extension_type:
3206 self.operand = PyTypeTestNode(self.operand, self.type, env)
3208 def check_const(self):
3209 self.operand.check_const()
3211 def calculate_result_code(self):
3212 opnd = self.operand
3213 return self.type.cast_code(opnd.result())
3215 def result_as(self, type):
3216 if self.type.is_pyobject and not self.is_temp:
3217 # Optimise away some unnecessary casting
3218 return self.operand.result_as(type)
3219 else:
3220 return ExprNode.result_as(self, type)
3222 def generate_result_code(self, code):
3223 if self.is_temp:
3224 code.putln(
3225 "%s = (PyObject *)%s;" % (
3226 self.result(),
3227 self.operand.result()))
3228 code.put_incref(self.result(), self.ctype())
3231 class SizeofNode(ExprNode):
3232 # Abstract base class for sizeof(x) expression nodes.
3234 type = PyrexTypes.c_int_type
3236 def check_const(self):
3237 pass
3239 def generate_result_code(self, code):
3240 pass
3243 class SizeofTypeNode(SizeofNode):
3244 # C sizeof function applied to a type
3246 # base_type CBaseTypeNode
3247 # declarator CDeclaratorNode
3249 subexprs = []
3250 arg_type = None
3252 def analyse_types(self, env):
3253 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3254 # this could be better handled by more uniformly treating types as runtime-available objects
3255 if 0 and self.base_type.module_path:
3256 path = self.base_type.module_path
3257 obj = env.lookup(path[0])
3258 if obj.as_module is None:
3259 operand = NameNode(pos=self.pos, name=path[0])
3260 for attr in path[1:]:
3261 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3262 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3263 self.operand = operand
3264 self.__class__ = SizeofVarNode
3265 self.analyse_types(env)
3266 return
3267 if self.arg_type is None:
3268 base_type = self.base_type.analyse(env)
3269 _, arg_type = self.declarator.analyse(base_type, env)
3270 self.arg_type = arg_type
3271 self.check_type()
3273 def check_type(self):
3274 arg_type = self.arg_type
3275 if arg_type.is_pyobject and not arg_type.is_extension_type:
3276 error(self.pos, "Cannot take sizeof Python object")
3277 elif arg_type.is_void:
3278 error(self.pos, "Cannot take sizeof void")
3279 elif not arg_type.is_complete():
3280 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3282 def calculate_result_code(self):
3283 if self.arg_type.is_extension_type:
3284 # the size of the pointer is boring
3285 # we want the size of the actual struct
3286 arg_code = self.arg_type.declaration_code("", deref=1)
3287 else:
3288 arg_code = self.arg_type.declaration_code("")
3289 return "(sizeof(%s))" % arg_code
3292 class SizeofVarNode(SizeofNode):
3293 # C sizeof function applied to a variable
3295 # operand ExprNode
3297 subexprs = ['operand']
3299 def analyse_types(self, env):
3300 # We may actually be looking at a type rather than a variable...
3301 # If we are, traditional analysis would fail...
3302 operand_as_type = self.operand.analyse_as_type(env)
3303 if operand_as_type:
3304 self.arg_type = operand_as_type
3305 self.__class__ = SizeofTypeNode
3306 self.check_type()
3307 else:
3308 self.operand.analyse_types(env)
3310 def calculate_result_code(self):
3311 return "(sizeof(%s))" % self.operand.result()
3313 def generate_result_code(self, code):
3314 pass
3317 #-------------------------------------------------------------------
3319 # Binary operator nodes
3321 #-------------------------------------------------------------------
3323 def _not_in(x, seq):
3324 return x not in seq
3326 compile_time_binary_operators = {
3327 '<': operator.lt,
3328 '<=': operator.le,
3329 '==': operator.eq,
3330 '!=': operator.ne,
3331 '>=': operator.ge,
3332 '>': operator.gt,
3333 'is': operator.is_,
3334 'is_not': operator.is_not,
3335 '+': operator.add,
3336 '&': operator.and_,
3337 '/': operator.div,
3338 '//': operator.floordiv,
3339 '<<': operator.lshift,
3340 '%': operator.mod,
3341 '*': operator.mul,
3342 '|': operator.or_,
3343 '**': operator.pow,
3344 '>>': operator.rshift,
3345 '-': operator.sub,
3346 #'/': operator.truediv,
3347 '^': operator.xor,
3348 'in': operator.contains,
3349 'not_in': _not_in,
3352 def get_compile_time_binop(node):
3353 func = compile_time_binary_operators.get(node.operator)
3354 if not func:
3355 error(node.pos,
3356 "Binary '%s' not supported in compile-time expression"
3357 % node.operator)
3358 return func
3360 class BinopNode(ExprNode):
3361 # operator string
3362 # operand1 ExprNode
3363 # operand2 ExprNode
3365 # Processing during analyse_expressions phase:
3367 # analyse_c_operation
3368 # Called when neither operand is a pyobject.
3369 # - Check operand types and coerce if needed.
3370 # - Determine result type and result code fragment.
3371 # - Allocate temporary for result if needed.
3373 subexprs = ['operand1', 'operand2']
3375 def compile_time_value(self, denv):
3376 func = get_compile_time_binop(self)
3377 operand1 = self.operand1.compile_time_value(denv)
3378 operand2 = self.operand2.compile_time_value(denv)
3379 try:
3380 return func(operand1, operand2)
3381 except Exception, e:
3382 self.compile_time_value_error(e)
3384 def analyse_types(self, env):
3385 self.operand1.analyse_types(env)
3386 self.operand2.analyse_types(env)
3387 if self.is_py_operation():
3388 self.coerce_operands_to_pyobjects(env)
3389 self.type = py_object_type
3390 self.gil_check(env)
3391 self.is_temp = 1
3392 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3393 self.operand1 = self.operand1.coerce_to_temp(env)
3394 else:
3395 self.analyse_c_operation(env)
3397 def is_py_operation(self):
3398 return (self.operand1.type.is_pyobject
3399 or self.operand2.type.is_pyobject)
3401 def coerce_operands_to_pyobjects(self, env):
3402 self.operand1 = self.operand1.coerce_to_pyobject(env)
3403 self.operand2 = self.operand2.coerce_to_pyobject(env)
3405 def check_const(self):
3406 self.operand1.check_const()
3407 self.operand2.check_const()
3409 def generate_result_code(self, code):
3410 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3411 if self.operand1.type.is_pyobject:
3412 function = self.py_operation_function()
3413 if function == "PyNumber_Power":
3414 extra_args = ", Py_None"
3415 else:
3416 extra_args = ""
3417 code.putln(
3418 "%s = %s(%s, %s%s); %s" % (
3419 self.result(),
3420 function,
3421 self.operand1.py_result(),
3422 self.operand2.py_result(),
3423 extra_args,
3424 code.error_goto_if_null(self.result(), self.pos)))
3425 else:
3426 if self.is_temp:
3427 self.generate_c_operation_code(code)
3429 def type_error(self):
3430 if not (self.operand1.type.is_error
3431 or self.operand2.type.is_error):
3432 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3433 (self.operator, self.operand1.type,
3434 self.operand2.type))
3435 self.type = PyrexTypes.error_type
3438 class NumBinopNode(BinopNode):
3439 # Binary operation taking numeric arguments.
3441 def analyse_c_operation(self, env):
3442 type1 = self.operand1.type
3443 type2 = self.operand2.type
3444 if self.operator == "**" and type1.is_int and type2.is_int:
3445 error(self.pos, "** with two C int types is ambiguous")
3446 self.type = error_type
3447 return
3448 self.type = self.compute_c_result_type(type1, type2)
3449 if not self.type:
3450 self.type_error()
3452 def compute_c_result_type(self, type1, type2):
3453 if self.c_types_okay(type1, type2):
3454 return PyrexTypes.widest_numeric_type(type1, type2)
3455 else:
3456 return None
3458 def c_types_okay(self, type1, type2):
3459 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3460 return (type1.is_numeric or type1.is_enum) \
3461 and (type2.is_numeric or type2.is_enum)
3463 def calculate_result_code(self):
3464 return "(%s %s %s)" % (
3465 self.operand1.result(),
3466 self.operator,
3467 self.operand2.result())
3469 def py_operation_function(self):
3470 return self.py_functions[self.operator]
3472 py_functions = {
3473 "|": "PyNumber_Or",
3474 "^": "PyNumber_Xor",
3475 "&": "PyNumber_And",
3476 "<<": "PyNumber_Lshift",
3477 ">>": "PyNumber_Rshift",
3478 "+": "PyNumber_Add",
3479 "-": "PyNumber_Subtract",
3480 "*": "PyNumber_Multiply",
3481 "/": "__Pyx_PyNumber_Divide",
3482 "//": "PyNumber_FloorDivide",
3483 "%": "PyNumber_Remainder",
3484 "**": "PyNumber_Power"
3488 class IntBinopNode(NumBinopNode):
3489 # Binary operation taking integer arguments.
3491 def c_types_okay(self, type1, type2):
3492 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3493 return (type1.is_int or type1.is_enum) \
3494 and (type2.is_int or type2.is_enum)
3497 class AddNode(NumBinopNode):
3498 # '+' operator.
3500 def is_py_operation(self):
3501 if self.operand1.type.is_string \
3502 and self.operand2.type.is_string:
3503 return 1
3504 else:
3505 return NumBinopNode.is_py_operation(self)
3507 def compute_c_result_type(self, type1, type2):
3508 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3509 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3510 return type1
3511 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3512 return type2
3513 else:
3514 return NumBinopNode.compute_c_result_type(
3515 self, type1, type2)
3518 class SubNode(NumBinopNode):
3519 # '-' operator.
3521 def compute_c_result_type(self, type1, type2):
3522 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3523 return type1
3524 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3525 return PyrexTypes.c_int_type
3526 else:
3527 return NumBinopNode.compute_c_result_type(
3528 self, type1, type2)
3531 class MulNode(NumBinopNode):
3532 # '*' operator.
3534 def is_py_operation(self):
3535 type1 = self.operand1.type
3536 type2 = self.operand2.type
3537 if (type1.is_string and type2.is_int) \
3538 or (type2.is_string and type1.is_int):
3539 return 1
3540 else:
3541 return NumBinopNode.is_py_operation(self)
3544 class FloorDivNode(NumBinopNode):
3545 # '//' operator.
3547 def calculate_result_code(self):
3548 return "(%s %s %s)" % (
3549 self.operand1.result(),
3550 "/", # c division is by default floor-div
3551 self.operand2.result())
3554 class ModNode(NumBinopNode):
3555 # '%' operator.
3557 def is_py_operation(self):
3558 return (self.operand1.type.is_string
3559 or self.operand2.type.is_string
3560 or NumBinopNode.is_py_operation(self))
3562 def calculate_result_code(self):
3563 if self.operand1.type.is_float or self.operand2.type.is_float:
3564 return "fmod(%s, %s)" % (
3565 self.operand1.result(),
3566 self.operand2.result())
3567 else:
3568 return "(%s %% %s)" % (
3569 self.operand1.result(),
3570 self.operand2.result())
3572 class PowNode(NumBinopNode):
3573 # '**' operator.
3575 def compute_c_result_type(self, type1, type2):
3576 if self.c_types_okay(type1, type2):
3577 return PyrexTypes.c_double_type
3578 else:
3579 return None
3581 def c_types_okay(self, type1, type2):
3582 return (type1.is_float or type2.is_float) and \
3583 NumBinopNode.c_types_okay(self, type1, type2)
3585 def type_error(self):
3586 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3587 if self.operand1.type.is_int and self.operand2.type.is_int:
3588 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3589 (self.operator, self.operand1.type, self.operand2.type))
3590 else:
3591 NumBinopNode.type_error(self)
3592 self.type = PyrexTypes.error_type
3594 def calculate_result_code(self):
3595 return "pow(%s, %s)" % (
3596 self.operand1.result(), self.operand2.result())
3599 class BoolBinopNode(ExprNode):
3600 # Short-circuiting boolean operation.
3602 # operator string
3603 # operand1 ExprNode
3604 # operand2 ExprNode
3605 # temp_bool ExprNode used internally
3607 temp_bool = None
3609 subexprs = ['operand1', 'operand2', 'temp_bool']
3611 def compile_time_value(self, denv):
3612 if self.operator == 'and':
3613 return self.operand1.compile_time_value(denv) \
3614 and self.operand2.compile_time_value(denv)
3615 else:
3616 return self.operand1.compile_time_value(denv) \
3617 or self.operand2.compile_time_value(denv)
3619 def analyse_types(self, env):
3620 self.operand1.analyse_types(env)
3621 self.operand2.analyse_types(env)
3622 if self.operand1.type.is_pyobject or \
3623 self.operand2.type.is_pyobject:
3624 self.operand1 = self.operand1.coerce_to_pyobject(env)
3625 self.operand2 = self.operand2.coerce_to_pyobject(env)
3626 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3627 self.type = py_object_type
3628 self.gil_check(env)
3629 else:
3630 self.operand1 = self.operand1.coerce_to_boolean(env)
3631 self.operand2 = self.operand2.coerce_to_boolean(env)
3632 self.type = PyrexTypes.c_bint_type
3633 # For what we're about to do, it's vital that
3634 # both operands be temp nodes.
3635 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3636 self.operand2 = self.operand2.coerce_to_temp(env)
3637 self.is_temp = 1
3639 gil_message = "Truth-testing Python object"
3641 def allocate_temps(self, env, result_code = None):
3642 # We don't need both operands at the same time, and
3643 # one of the operands will also be our result. So we
3644 # use an allocation strategy here which results in
3645 # this node and both its operands sharing the same
3646 # result variable. This allows us to avoid some
3647 # assignments and increfs/decrefs that would otherwise
3648 # be necessary.
3649 self.allocate_temp(env, result_code)
3650 self.operand1.allocate_temps(env, self.result())
3651 if self.temp_bool:
3652 self.temp_bool.allocate_temp(env)
3653 self.temp_bool.release_temp(env)
3654 self.operand2.allocate_temps(env, self.result())
3655 # We haven't called release_temp on either operand,
3656 # because although they are temp nodes, they don't own
3657 # their result variable. And because they are temp
3658 # nodes, any temps in their subnodes will have been
3659 # released before their allocate_temps returned.
3660 # Therefore, they contain no temp vars that need to
3661 # be released.
3663 def check_const(self):
3664 self.operand1.check_const()
3665 self.operand2.check_const()
3667 def calculate_result_code(self):
3668 return "(%s %s %s)" % (
3669 self.operand1.result(),
3670 self.py_to_c_op[self.operator],
3671 self.operand2.result())
3673 py_to_c_op = {'and': "&&", 'or': "||"}
3675 def generate_evaluation_code(self, code):
3676 self.operand1.generate_evaluation_code(code)
3677 test_result = self.generate_operand1_test(code)
3678 if self.operator == 'and':
3679 sense = ""
3680 else:
3681 sense = "!"
3682 code.putln(
3683 "if (%s%s) {" % (
3684 sense,
3685 test_result))
3686 self.operand1.generate_disposal_code(code)
3687 self.operand2.generate_evaluation_code(code)
3688 code.putln(
3689 "}")
3691 def generate_operand1_test(self, code):
3692 # Generate code to test the truth of the first operand.
3693 if self.type.is_pyobject:
3694 test_result = self.temp_bool.result()
3695 code.putln(
3696 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3697 test_result,
3698 self.operand1.py_result(),
3699 code.error_goto_if_neg(test_result, self.pos)))
3700 else:
3701 test_result = self.operand1.result()
3702 return test_result
3705 class CondExprNode(ExprNode):
3706 # Short-circuiting conditional expression.
3708 # test ExprNode
3709 # true_val ExprNode
3710 # false_val ExprNode
3712 temp_bool = None
3713 true_val = None
3714 false_val = None
3716 subexprs = ['test', 'true_val', 'false_val']
3718 def analyse_types(self, env):
3719 self.test.analyse_types(env)
3720 self.test = self.test.coerce_to_boolean(env)
3721 self.true_val.analyse_types(env)
3722 self.false_val.analyse_types(env)
3723 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3724 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3725 self.true_val = self.true_val.coerce_to(self.type, env)
3726 self.false_val = self.false_val.coerce_to(self.type, env)
3727 # must be tmp variables so they can share a result
3728 self.true_val = self.true_val.coerce_to_temp(env)
3729 self.false_val = self.false_val.coerce_to_temp(env)
3730 self.is_temp = 1
3731 if self.type == PyrexTypes.error_type:
3732 self.type_error()
3734 def allocate_temps(self, env, result_code = None):
3735 # We only ever evaluate one side, and this is
3736 # after evaluating the truth value, so we may
3737 # use an allocation strategy here which results in
3738 # this node and both its operands sharing the same
3739 # result variable. This allows us to avoid some
3740 # assignments and increfs/decrefs that would otherwise
3741 # be necessary.
3742 self.allocate_temp(env, result_code)
3743 self.test.allocate_temps(env, result_code)
3744 self.true_val.allocate_temps(env, self.result())
3745 self.false_val.allocate_temps(env, self.result())
3746 # We haven't called release_temp on either value,
3747 # because although they are temp nodes, they don't own
3748 # their result variable. And because they are temp
3749 # nodes, any temps in their subnodes will have been
3750 # released before their allocate_temps returned.
3751 # Therefore, they contain no temp vars that need to
3752 # be released.
3754 def compute_result_type(self, type1, type2):
3755 if type1 == type2:
3756 return type1
3757 elif type1.is_numeric and type2.is_numeric:
3758 return PyrexTypes.widest_numeric_type(type1, type2)
3759 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3760 return type2
3761 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3762 return type1
3763 elif type1.is_pyobject or type2.is_pyobject:
3764 return py_object_type
3765 elif type1.assignable_from(type2):
3766 return type1
3767 elif type2.assignable_from(type1):
3768 return type2
3769 else:
3770 return PyrexTypes.error_type
3772 def type_error(self):
3773 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3774 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3775 (self.true_val.type, self.false_val.type))
3776 self.type = PyrexTypes.error_type
3778 def check_const(self):
3779 self.test.check_const()
3780 self.true_val.check_const()
3781 self.false_val.check_const()
3783 def generate_evaluation_code(self, code):
3784 self.test.generate_evaluation_code(code)
3785 code.putln("if (%s) {" % self.test.result() )
3786 self.true_val.generate_evaluation_code(code)
3787 code.putln("} else {")
3788 self.false_val.generate_evaluation_code(code)
3789 code.putln("}")
3790 self.test.generate_disposal_code(code)
3792 richcmp_constants = {
3793 "<" : "Py_LT",
3794 "<=": "Py_LE",
3795 "==": "Py_EQ",
3796 "!=": "Py_NE",
3797 "<>": "Py_NE",
3798 ">" : "Py_GT",
3799 ">=": "Py_GE",
3802 class CmpNode:
3803 # Mixin class containing code common to PrimaryCmpNodes
3804 # and CascadedCmpNodes.
3806 def cascaded_compile_time_value(self, operand1, denv):
3807 func = get_compile_time_binop(self)
3808 operand2 = self.operand2.compile_time_value(denv)
3809 try:
3810 result = func(operand1, operand2)
3811 except Exception, e:
3812 self.compile_time_value_error(e)
3813 result = None
3814 if result:
3815 cascade = self.cascade
3816 if cascade:
3817 result = result and cascade.compile_time_value(operand2, denv)
3818 return result
3820 def is_python_comparison(self):
3821 return (self.has_python_operands()
3822 or (self.cascade and self.cascade.is_python_comparison())
3823 or self.operator in ('in', 'not_in'))
3825 def is_python_result(self):
3826 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3827 or (self.cascade and self.cascade.is_python_result()))
3829 def check_types(self, env, operand1, op, operand2):
3830 if not self.types_okay(operand1, op, operand2):
3831 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3832 (self.operator, operand1.type, operand2.type))
3834 def types_okay(self, operand1, op, operand2):
3835 type1 = operand1.type
3836 type2 = operand2.type
3837 if type1.is_error or type2.is_error:
3838 return 1
3839 if type1.is_pyobject: # type2 will be, too
3840 return 1
3841 elif type1.is_ptr or type1.is_array:
3842 return type1.is_null_ptr or type2.is_null_ptr \
3843 or ((type2.is_ptr or type2.is_array)
3844 and type1.base_type.same_as(type2.base_type))
3845 elif ((type1.is_numeric and type2.is_numeric
3846 or type1.is_enum and (type1 is type2 or type2.is_int)
3847 or type1.is_int and type2.is_enum)
3848 and op not in ('is', 'is_not')):
3849 return 1
3850 else:
3851 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3853 def generate_operation_code(self, code, result_code,
3854 operand1, op , operand2):
3855 if self.type is PyrexTypes.py_object_type:
3856 coerce_result = "__Pyx_PyBool_FromLong"
3857 else:
3858 coerce_result = ""
3859 if 'not' in op: negation = "!"
3860 else: negation = ""
3861 if op == 'in' or op == 'not_in':
3862 code.putln(
3863 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
3864 result_code,
3865 coerce_result,
3866 negation,
3867 operand2.py_result(),
3868 operand1.py_result(),
3869 code.error_goto_if_neg(result_code, self.pos)))
3870 elif (operand1.type.is_pyobject
3871 and op not in ('is', 'is_not')):
3872 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
3873 result_code,
3874 operand1.py_result(),
3875 operand2.py_result(),
3876 richcmp_constants[op],
3877 code.error_goto_if_null(result_code, self.pos)))
3878 else:
3879 type1 = operand1.type
3880 type2 = operand2.type
3881 if (type1.is_extension_type or type2.is_extension_type) \
3882 and not type1.same_as(type2):
3883 common_type = py_object_type
3884 elif type1.is_numeric:
3885 common_type = PyrexTypes.widest_numeric_type(type1, type2)
3886 else:
3887 common_type = type1
3888 code1 = operand1.result_as(common_type)
3889 code2 = operand2.result_as(common_type)
3890 code.putln("%s = %s(%s %s %s);" % (
3891 result_code,
3892 coerce_result,
3893 code1,
3894 self.c_operator(op),
3895 code2))
3897 def c_operator(self, op):
3898 if op == 'is':
3899 return "=="
3900 elif op == 'is_not':
3901 return "!="
3902 else:
3903 return op
3906 class PrimaryCmpNode(ExprNode, CmpNode):
3907 # Non-cascaded comparison or first comparison of
3908 # a cascaded sequence.
3910 # operator string
3911 # operand1 ExprNode
3912 # operand2 ExprNode
3913 # cascade CascadedCmpNode
3915 # We don't use the subexprs mechanism, because
3916 # things here are too complicated for it to handle.
3917 # Instead, we override all the framework methods
3918 # which use it.
3920 child_attrs = ['operand1', 'operand2', 'cascade']
3922 cascade = None
3924 def compile_time_value(self, denv):
3925 operand1 = self.operand1.compile_time_value(denv)
3926 return self.cascaded_compile_time_value(operand1, denv)
3928 def analyse_types(self, env):
3929 self.operand1.analyse_types(env)
3930 self.operand2.analyse_types(env)
3931 if self.cascade:
3932 self.cascade.analyse_types(env, self.operand2)
3933 self.is_pycmp = self.is_python_comparison()
3934 if self.is_pycmp:
3935 self.coerce_operands_to_pyobjects(env)
3936 if self.has_int_operands():
3937 self.coerce_chars_to_ints(env)
3938 if self.cascade:
3939 self.operand2 = self.operand2.coerce_to_simple(env)
3940 self.cascade.coerce_cascaded_operands_to_temp(env)
3941 self.check_operand_types(env)
3942 if self.is_python_result():
3943 self.type = PyrexTypes.py_object_type
3944 else:
3945 self.type = PyrexTypes.c_bint_type
3946 cdr = self.cascade
3947 while cdr:
3948 cdr.type = self.type
3949 cdr = cdr.cascade
3950 if self.is_pycmp or self.cascade:
3951 self.is_temp = 1
3953 def check_operand_types(self, env):
3954 self.check_types(env,
3955 self.operand1, self.operator, self.operand2)
3956 if self.cascade:
3957 self.cascade.check_operand_types(env, self.operand2)
3959 def has_python_operands(self):
3960 return (self.operand1.type.is_pyobject
3961 or self.operand2.type.is_pyobject)
3963 def coerce_operands_to_pyobjects(self, env):
3964 self.operand1 = self.operand1.coerce_to_pyobject(env)
3965 self.operand2 = self.operand2.coerce_to_pyobject(env)
3966 if self.cascade:
3967 self.cascade.coerce_operands_to_pyobjects(env)
3969 def has_int_operands(self):
3970 return (self.operand1.type.is_int or self.operand2.type.is_int) \
3971 or (self.cascade and self.cascade.has_int_operands())
3973 def coerce_chars_to_ints(self, env):
3974 # coerce literal single-char strings to c chars
3975 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
3976 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
3977 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
3978 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
3979 if self.cascade:
3980 self.cascade.coerce_chars_to_ints(env)
3982 def allocate_subexpr_temps(self, env):
3983 self.operand1.allocate_temps(env)
3984 self.operand2.allocate_temps(env)
3985 if self.cascade:
3986 self.cascade.allocate_subexpr_temps(env)
3988 def release_subexpr_temps(self, env):
3989 self.operand1.release_temp(env)
3990 self.operand2.release_temp(env)
3991 if self.cascade:
3992 self.cascade.release_subexpr_temps(env)
3994 def check_const(self):
3995 self.operand1.check_const()
3996 self.operand2.check_const()
3997 if self.cascade:
3998 self.not_const()
4000 def calculate_result_code(self):
4001 return "(%s %s %s)" % (
4002 self.operand1.result(),
4003 self.c_operator(self.operator),
4004 self.operand2.result())
4006 def generate_evaluation_code(self, code):
4007 self.operand1.generate_evaluation_code(code)
4008 self.operand2.generate_evaluation_code(code)
4009 if self.is_temp:
4010 self.generate_operation_code(code, self.result(),
4011 self.operand1, self.operator, self.operand2)
4012 if self.cascade:
4013 self.cascade.generate_evaluation_code(code,
4014 self.result(), self.operand2)
4015 self.operand1.generate_disposal_code(code)
4016 self.operand2.generate_disposal_code(code)
4018 def generate_subexpr_disposal_code(self, code):
4019 # If this is called, it is a non-cascaded cmp,
4020 # so only need to dispose of the two main operands.
4021 self.operand1.generate_disposal_code(code)
4022 self.operand2.generate_disposal_code(code)
4024 def annotate(self, code):
4025 self.operand1.annotate(code)
4026 self.operand2.annotate(code)
4027 if self.cascade:
4028 self.cascade.annotate(code)
4031 class CascadedCmpNode(Node, CmpNode):
4032 # A CascadedCmpNode is not a complete expression node. It
4033 # hangs off the side of another comparison node, shares
4034 # its left operand with that node, and shares its result
4035 # with the PrimaryCmpNode at the head of the chain.
4037 # operator string
4038 # operand2 ExprNode
4039 # cascade CascadedCmpNode
4041 child_attrs = ['operand2', 'cascade']
4043 cascade = None
4045 def analyse_types(self, env, operand1):
4046 self.operand2.analyse_types(env)
4047 if self.cascade:
4048 self.cascade.analyse_types(env, self.operand2)
4050 def check_operand_types(self, env, operand1):
4051 self.check_types(env,
4052 operand1, self.operator, self.operand2)
4053 if self.cascade:
4054 self.cascade.check_operand_types(env, self.operand2)
4056 def has_python_operands(self):
4057 return self.operand2.type.is_pyobject
4059 def coerce_operands_to_pyobjects(self, env):
4060 self.operand2 = self.operand2.coerce_to_pyobject(env)
4061 if self.cascade:
4062 self.cascade.coerce_operands_to_pyobjects(env)
4064 def has_int_operands(self):
4065 return self.operand2.type.is_int
4067 def coerce_chars_to_ints(self, env):
4068 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4069 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4071 def coerce_cascaded_operands_to_temp(self, env):
4072 if self.cascade:
4073 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4074 self.operand2 = self.operand2.coerce_to_simple(env)
4075 self.cascade.coerce_cascaded_operands_to_temp(env)
4077 def allocate_subexpr_temps(self, env):
4078 self.operand2.allocate_temps(env)
4079 if self.cascade:
4080 self.cascade.allocate_subexpr_temps(env)
4082 def release_subexpr_temps(self, env):
4083 self.operand2.release_temp(env)
4084 if self.cascade:
4085 self.cascade.release_subexpr_temps(env)
4087 def generate_evaluation_code(self, code, result, operand1):
4088 if self.type.is_pyobject:
4089 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4090 else:
4091 code.putln("if (%s) {" % result)
4092 self.operand2.generate_evaluation_code(code)
4093 self.generate_operation_code(code, result,
4094 operand1, self.operator, self.operand2)
4095 if self.cascade:
4096 self.cascade.generate_evaluation_code(
4097 code, result, self.operand2)
4098 # Cascaded cmp result is always temp
4099 self.operand2.generate_disposal_code(code)
4100 code.putln("}")
4102 def annotate(self, code):
4103 self.operand2.annotate(code)
4104 if self.cascade:
4105 self.cascade.annotate(code)
4108 binop_node_classes = {
4109 "or": BoolBinopNode,
4110 "and": BoolBinopNode,
4111 "|": IntBinopNode,
4112 "^": IntBinopNode,
4113 "&": IntBinopNode,
4114 "<<": IntBinopNode,
4115 ">>": IntBinopNode,
4116 "+": AddNode,
4117 "-": SubNode,
4118 "*": MulNode,
4119 "/": NumBinopNode,
4120 "//": FloorDivNode,
4121 "%": ModNode,
4122 "**": PowNode
4125 def binop_node(pos, operator, operand1, operand2):
4126 # Construct binop node of appropriate class for
4127 # given operator.
4128 return binop_node_classes[operator](pos,
4129 operator = operator,
4130 operand1 = operand1,
4131 operand2 = operand2)
4133 #-------------------------------------------------------------------
4135 # Coercion nodes
4137 # Coercion nodes are special in that they are created during
4138 # the analyse_types phase of parse tree processing.
4139 # Their __init__ methods consequently incorporate some aspects
4140 # of that phase.
4142 #-------------------------------------------------------------------
4144 class CoercionNode(ExprNode):
4145 # Abstract base class for coercion nodes.
4147 # arg ExprNode node being coerced
4149 subexprs = ['arg']
4151 def __init__(self, arg):
4152 self.pos = arg.pos
4153 self.arg = arg
4154 if debug_coercion:
4155 print("%s Coercing %s" % (self, self.arg))
4157 def annotate(self, code):
4158 self.arg.annotate(code)
4159 if self.arg.type != self.type:
4160 file, line, col = self.pos
4161 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4164 class CastNode(CoercionNode):
4165 # Wrap a node in a C type cast.
4167 def __init__(self, arg, new_type):
4168 CoercionNode.__init__(self, arg)
4169 self.type = new_type
4171 def calculate_result_code(self):
4172 return self.arg.result_as(self.type)
4174 def generate_result_code(self, code):
4175 self.arg.generate_result_code(code)
4178 class PyTypeTestNode(CoercionNode):
4179 # This node is used to check that a generic Python
4180 # object is an instance of a particular extension type.
4181 # This node borrows the result of its argument node.
4183 def __init__(self, arg, dst_type, env):
4184 # The arg is know to be a Python object, and
4185 # the dst_type is known to be an extension type.
4186 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4187 CoercionNode.__init__(self, arg)
4188 self.type = dst_type
4189 self.gil_check(env)
4190 self.result_ctype = arg.ctype()
4191 env.use_utility_code(type_test_utility_code)
4193 gil_message = "Python type test"
4195 def analyse_types(self, env):
4196 pass
4198 def result_in_temp(self):
4199 return self.arg.result_in_temp()
4201 def is_ephemeral(self):
4202 return self.arg.is_ephemeral()
4204 def calculate_result_code(self):
4205 return self.arg.result()
4207 def generate_result_code(self, code):
4208 if self.type.typeobj_is_available():
4209 code.putln(
4210 "if (!(%s)) %s" % (
4211 self.type.type_test_code(self.arg.py_result()),
4212 code.error_goto(self.pos)))
4213 else:
4214 error(self.pos, "Cannot test type of extern C class "
4215 "without type object name specification")
4217 def generate_post_assignment_code(self, code):
4218 self.arg.generate_post_assignment_code(code)
4221 class CoerceToPyTypeNode(CoercionNode):
4222 # This node is used to convert a C data type
4223 # to a Python object.
4225 def __init__(self, arg, env):
4226 CoercionNode.__init__(self, arg)
4227 self.type = py_object_type
4228 self.gil_check(env)
4229 self.is_temp = 1
4230 if not arg.type.to_py_function:
4231 error(arg.pos,
4232 "Cannot convert '%s' to Python object" % arg.type)
4234 gil_message = "Converting to Python object"
4236 def analyse_types(self, env):
4237 # The arg is always already analysed
4238 pass
4240 def generate_result_code(self, code):
4241 function = self.arg.type.to_py_function
4242 code.putln('%s = %s(%s); %s' % (
4243 self.result(),
4244 function,
4245 self.arg.result(),
4246 code.error_goto_if_null(self.result(), self.pos)))
4249 class CoerceFromPyTypeNode(CoercionNode):
4250 # This node is used to convert a Python object
4251 # to a C data type.
4253 def __init__(self, result_type, arg, env):
4254 CoercionNode.__init__(self, arg)
4255 self.type = result_type
4256 self.is_temp = 1
4257 if not result_type.from_py_function:
4258 error(arg.pos,
4259 "Cannot convert Python object to '%s'" % result_type)
4260 if self.type.is_string and self.arg.is_ephemeral():
4261 error(arg.pos,
4262 "Obtaining char * from temporary Python value")
4264 def analyse_types(self, env):
4265 # The arg is always already analysed
4266 pass
4268 def generate_result_code(self, code):
4269 function = self.type.from_py_function
4270 operand = self.arg.py_result()
4271 rhs = "%s(%s)" % (function, operand)
4272 if self.type.is_enum:
4273 rhs = typecast(self.type, c_long_type, rhs)
4274 code.putln('%s = %s; %s' % (
4275 self.result(),
4276 rhs,
4277 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4280 class CoerceToBooleanNode(CoercionNode):
4281 # This node is used when a result needs to be used
4282 # in a boolean context.
4284 def __init__(self, arg, env):
4285 CoercionNode.__init__(self, arg)
4286 self.type = PyrexTypes.c_bint_type
4287 if arg.type.is_pyobject:
4288 if env.nogil:
4289 self.gil_error()
4290 self.is_temp = 1
4292 gil_message = "Truth-testing Python object"
4294 def check_const(self):
4295 if self.is_temp:
4296 self.not_const()
4297 self.arg.check_const()
4299 def calculate_result_code(self):
4300 return "(%s != 0)" % self.arg.result()
4302 def generate_result_code(self, code):
4303 if self.arg.type.is_pyobject:
4304 code.putln(
4305 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4306 self.result(),
4307 self.arg.py_result(),
4308 code.error_goto_if_neg(self.result(), self.pos)))
4311 class CoerceToTempNode(CoercionNode):
4312 # This node is used to force the result of another node
4313 # to be stored in a temporary. It is only used if the
4314 # argument node's result is not already in a temporary.
4316 def __init__(self, arg, env):
4317 CoercionNode.__init__(self, arg)
4318 self.type = self.arg.type
4319 self.is_temp = 1
4320 if self.type.is_pyobject:
4321 self.gil_check(env)
4322 self.result_ctype = py_object_type
4324 gil_message = "Creating temporary Python reference"
4326 def analyse_types(self, env):
4327 # The arg is always already analysed
4328 pass
4330 def generate_result_code(self, code):
4331 #self.arg.generate_evaluation_code(code) # Already done
4332 # by generic generate_subexpr_evaluation_code!
4333 code.putln("%s = %s;" % (
4334 self.result(), self.arg.result_as(self.ctype())))
4335 if self.type.is_pyobject:
4336 code.put_incref(self.result(), self.ctype())
4339 class CloneNode(CoercionNode):
4340 # This node is employed when the result of another node needs
4341 # to be used multiple times. The argument node's result must
4342 # be in a temporary. This node "borrows" the result from the
4343 # argument node, and does not generate any evaluation or
4344 # disposal code for it. The original owner of the argument
4345 # node is responsible for doing those things.
4347 subexprs = [] # Arg is not considered a subexpr
4349 def __init__(self, arg):
4350 CoercionNode.__init__(self, arg)
4351 if hasattr(arg, 'type'):
4352 self.type = arg.type
4353 self.result_ctype = arg.result_ctype
4354 if hasattr(arg, 'entry'):
4355 self.entry = arg.entry
4357 def calculate_result_code(self):
4358 return self.arg.result()
4360 def analyse_types(self, env):
4361 self.type = self.arg.type
4362 self.result_ctype = self.arg.result_ctype
4363 self.is_temp = 1
4364 if hasattr(self.arg, 'entry'):
4365 self.entry = self.arg.entry
4367 def generate_evaluation_code(self, code):
4368 pass
4370 def generate_result_code(self, code):
4371 pass
4373 def generate_disposal_code(self, code):
4374 pass
4376 def allocate_temps(self, env):
4377 self.result_code = self.calculate_result_code()
4379 def release_temp(self, env):
4380 pass
4382 class PersistentNode(ExprNode):
4383 # A PersistentNode is like a CloneNode except it handles the temporary
4384 # allocation itself by keeping track of the number of times it has been
4385 # used.
4387 subexprs = ["arg"]
4388 temp_counter = 0
4389 generate_counter = 0
4390 analyse_counter = 0
4391 result_code = None
4393 def __init__(self, arg, uses):
4394 self.pos = arg.pos
4395 self.arg = arg
4396 self.uses = uses
4398 def analyse_types(self, env):
4399 if self.analyse_counter == 0:
4400 self.arg.analyse_types(env)
4401 self.type = self.arg.type
4402 self.result_ctype = self.arg.result_ctype
4403 self.is_temp = 1
4404 self.analyse_counter += 1
4406 def calculate_result_code(self):
4407 return self.result()
4409 def generate_evaluation_code(self, code):
4410 if self.generate_counter == 0:
4411 self.arg.generate_evaluation_code(code)
4412 code.putln("%s = %s;" % (
4413 self.result(), self.arg.result_as(self.ctype())))
4414 if self.type.is_pyobject:
4415 code.put_incref(self.result(), self.ctype())
4416 self.arg.generate_disposal_code(code)
4417 self.generate_counter += 1
4419 def generate_disposal_code(self, code):
4420 if self.generate_counter == self.uses:
4421 if self.type.is_pyobject:
4422 code.put_decref_clear(self.result(), self.ctype())
4424 def allocate_temps(self, env, result=None):
4425 if self.temp_counter == 0:
4426 self.arg.allocate_temps(env)
4427 self.allocate_temp(env, result)
4428 self.arg.release_temp(env)
4429 self.temp_counter += 1
4431 def allocate_temp(self, env, result=None):
4432 if result is None:
4433 self.result_code = env.allocate_temp(self.type)
4434 else:
4435 self.result_code = result
4437 def release_temp(self, env):
4438 if self.temp_counter == self.uses:
4439 env.release_temp(self.result())
4441 #------------------------------------------------------------------------------------
4443 # Runtime support code
4445 #------------------------------------------------------------------------------------
4447 get_name_interned_utility_code = [
4448 """
4449 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4450 ""","""
4451 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4452 PyObject *result;
4453 result = PyObject_GetAttr(dict, name);
4454 if (!result)
4455 PyErr_SetObject(PyExc_NameError, name);
4456 return result;
4458 """]
4460 #------------------------------------------------------------------------------------
4462 import_utility_code = [
4463 """
4464 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4465 ""","""
4466 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4467 PyObject *__import__ = 0;
4468 PyObject *empty_list = 0;
4469 PyObject *module = 0;
4470 PyObject *global_dict = 0;
4471 PyObject *empty_dict = 0;
4472 PyObject *list;
4473 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4474 if (!__import__)
4475 goto bad;
4476 if (from_list)
4477 list = from_list;
4478 else {
4479 empty_list = PyList_New(0);
4480 if (!empty_list)
4481 goto bad;
4482 list = empty_list;
4484 global_dict = PyModule_GetDict(%(GLOBALS)s);
4485 if (!global_dict)
4486 goto bad;
4487 empty_dict = PyDict_New();
4488 if (!empty_dict)
4489 goto bad;
4490 module = PyObject_CallFunction(__import__, "OOOO",
4491 name, global_dict, empty_dict, list);
4492 bad:
4493 Py_XDECREF(empty_list);
4494 Py_XDECREF(__import__);
4495 Py_XDECREF(empty_dict);
4496 return module;
4498 """ % {
4499 "BUILTINS": Naming.builtins_cname,
4500 "GLOBALS": Naming.module_cname,
4501 }]
4503 #------------------------------------------------------------------------------------
4505 get_exception_utility_code = [
4506 """
4507 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4508 ""","""
4509 static PyObject *__Pyx_GetExcValue(void) {
4510 PyObject *type = 0, *value = 0, *tb = 0;
4511 PyObject *tmp_type, *tmp_value, *tmp_tb;
4512 PyObject *result = 0;
4513 PyThreadState *tstate = PyThreadState_Get();
4514 PyErr_Fetch(&type, &value, &tb);
4515 PyErr_NormalizeException(&type, &value, &tb);
4516 if (PyErr_Occurred())
4517 goto bad;
4518 if (!value) {
4519 value = Py_None;
4520 Py_INCREF(value);
4522 tmp_type = tstate->exc_type;
4523 tmp_value = tstate->exc_value;
4524 tmp_tb = tstate->exc_traceback;
4525 tstate->exc_type = type;
4526 tstate->exc_value = value;
4527 tstate->exc_traceback = tb;
4528 /* Make sure tstate is in a consistent state when we XDECREF
4529 these objects (XDECREF may run arbitrary code). */
4530 Py_XDECREF(tmp_type);
4531 Py_XDECREF(tmp_value);
4532 Py_XDECREF(tmp_tb);
4533 result = value;
4534 Py_XINCREF(result);
4535 type = 0;
4536 value = 0;
4537 tb = 0;
4538 bad:
4539 Py_XDECREF(type);
4540 Py_XDECREF(value);
4541 Py_XDECREF(tb);
4542 return result;
4544 """]
4546 #------------------------------------------------------------------------------------
4548 unpacking_utility_code = [
4549 """
4550 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4551 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4552 ""","""
4553 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4554 PyObject *item;
4555 if (!(item = PyIter_Next(iter))) {
4556 if (!PyErr_Occurred()) {
4557 PyErr_Format(PyExc_ValueError,
4558 #if PY_VERSION_HEX < 0x02050000
4559 "need more than %d values to unpack", (int)index);
4560 #else
4561 "need more than %zd values to unpack", index);
4562 #endif
4565 return item;
4568 static int __Pyx_EndUnpack(PyObject *iter) {
4569 PyObject *item;
4570 if ((item = PyIter_Next(iter))) {
4571 Py_DECREF(item);
4572 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4573 return -1;
4575 else if (!PyErr_Occurred())
4576 return 0;
4577 else
4578 return -1;
4580 """]
4582 #------------------------------------------------------------------------------------
4584 type_test_utility_code = [
4585 """
4586 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4587 ""","""
4588 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4589 if (!type) {
4590 PyErr_Format(PyExc_SystemError, "Missing type object");
4591 return 0;
4593 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4594 return 1;
4595 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4596 Py_TYPE(obj)->tp_name, type->tp_name);
4597 return 0;
4599 """]
4601 #------------------------------------------------------------------------------------
4603 create_class_utility_code = [
4604 """
4605 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4606 ""","""
4607 static PyObject *__Pyx_CreateClass(
4608 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4610 PyObject *py_modname;
4611 PyObject *result = 0;
4613 #if PY_MAJOR_VERSION < 3
4614 py_modname = PyString_FromString(modname);
4615 #else
4616 py_modname = PyUnicode_FromString(modname);
4617 #endif
4618 if (!py_modname)
4619 goto bad;
4620 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4621 goto bad;
4622 #if PY_MAJOR_VERSION < 3
4623 result = PyClass_New(bases, dict, name);
4624 #else
4625 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4626 #endif
4627 bad:
4628 Py_XDECREF(py_modname);
4629 return result;
4631 """]
4633 #------------------------------------------------------------------------------------
4635 cpp_exception_utility_code = [
4636 """
4637 #ifndef __Pyx_CppExn2PyErr
4638 static void __Pyx_CppExn2PyErr() {
4639 try {
4640 if (PyErr_Occurred())
4641 ; // let the latest Python exn pass through and ignore the current one
4642 else
4643 throw;
4644 } catch (const std::out_of_range& exn) {
4645 // catch out_of_range explicitly so the proper Python exn may be raised
4646 PyErr_SetString(PyExc_IndexError, exn.what());
4647 } catch (const std::exception& exn) {
4648 PyErr_SetString(PyExc_RuntimeError, exn.what());
4650 catch (...)
4652 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4655 #endif
4656 """,""]
4658 #------------------------------------------------------------------------------------
4660 append_utility_code = [
4661 """
4662 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4663 if (likely(PyList_CheckExact(L))) {
4664 if (PyList_Append(L, x) < 0) return NULL;
4665 Py_INCREF(Py_None);
4666 return Py_None; // this is just to have an accurate signature
4668 else {
4669 return PyObject_CallMethod(L, "append", "(O)", x);
4672 """,""
4675 #------------------------------------------------------------------------------------
4677 # If the is_unsigned flag is set, we need to do some extra work to make
4678 # sure the index doesn't become negative.
4680 getitem_int_utility_code = [
4681 """
4682 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4683 PyObject *r;
4684 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4685 r = PyList_GET_ITEM(o, i);
4686 Py_INCREF(r);
4688 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4689 r = PyTuple_GET_ITEM(o, i);
4690 Py_INCREF(r);
4692 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4693 r = PySequence_GetItem(o, i);
4694 else {
4695 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);
4696 if (!j)
4697 return 0;
4698 r = PyObject_GetItem(o, j);
4699 Py_DECREF(j);
4701 return r;
4703 """,
4704 """
4705 """]
4707 #------------------------------------------------------------------------------------
4709 setitem_int_utility_code = [
4710 """
4711 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4712 int r;
4713 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4714 Py_DECREF(PyList_GET_ITEM(o, i));
4715 Py_INCREF(v);
4716 PyList_SET_ITEM(o, i, v);
4717 return 1;
4719 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4720 r = PySequence_SetItem(o, i, v);
4721 else {
4722 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);
4723 if (!j)
4724 return -1;
4725 r = PyObject_SetItem(o, j, v);
4726 Py_DECREF(j);
4728 return r;
4730 """,
4731 """
4732 """]
4733 #------------------------------------------------------------------------------------
4735 raise_noneattr_error_utility_code = [
4736 """
4737 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname);
4738 """, """
4739 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname) {
4740 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
4742 """]
4744 raise_noneindex_error_utility_code = [
4745 """
4746 static INLINE void __Pyx_RaiseNoneIndexingError();
4747 """, """
4748 static INLINE void __Pyx_RaiseNoneIndexingError() {
4749 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
4751 """]