Cython has moved to github.

pyrex

view Pyrex/Compiler/ExprNodes.py @ 86:da6e97bb7e6d

Multiple compilation fixed
author Gregory Ewing <greg.ewing@canterbury.ac.nz>
date Sat May 24 15:50:12 2008 +1200 (4 years ago)
parents 12072e0e4fd5
children 37554acbb702
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
6 from string import join
8 from Errors import error, InternalError
9 import Naming
10 from Nodes import Node
11 import PyrexTypes
12 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
13 import Symtab
14 import Options
16 from Pyrex.Debugging import print_call_chain
17 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
18 debug_coercion
20 class ExprNode(Node):
21 # subexprs [string] Class var holding names of subexpr node attrs
22 # type PyrexType Type of the result
23 # result_code string Code fragment
24 # result_ctype string C type of result_code if different from type
25 # inplace_result string Temp var holding in-place operation result
26 # is_temp boolean Result is in a temporary variable
27 # is_sequence_constructor
28 # boolean Is a list or tuple constructor expression
29 # saved_subexpr_nodes
30 # [ExprNode or [ExprNode or None] or None]
31 # Cached result of subexpr_nodes()
33 result_ctype = None
35 # The Analyse Expressions phase for expressions is split
36 # into two sub-phases:
37 #
38 # Analyse Types
39 # Determines the result type of the expression based
40 # on the types of its sub-expressions, and inserts
41 # coercion nodes into the expression tree where needed.
42 # Marks nodes which will need to have temporary variables
43 # allocated.
44 #
45 # Allocate Temps
46 # Allocates temporary variables where needed, and fills
47 # in the result_code field of each node.
48 #
49 # ExprNode provides some convenience routines which
50 # perform both of the above phases. These should only
51 # be called from statement nodes, and only when no
52 # coercion nodes need to be added around the expression
53 # being analysed. If coercion is needed, the above two phases
54 # should be invoked separately.
55 #
56 # Framework code in ExprNode provides much of the common
57 # processing for the various phases. It makes use of the
58 # 'subexprs' class attribute of ExprNodes, which should
59 # contain a list of the names of attributes which can
60 # hold sub-nodes or sequences of sub-nodes.
61 #
62 # The framework makes use of a number of abstract methods.
63 # Their responsibilities are as follows.
64 #
65 # Declaration Analysis phase
66 #
67 # analyse_target_declaration
68 # Called during the Analyse Declarations phase to analyse
69 # the LHS of an assignment or argument of a del statement.
70 # Nodes which cannot be the LHS of an assignment need not
71 # implement it.
72 #
73 # Expression Analysis phase
74 #
75 # analyse_types
76 # - Call analyse_types on all sub-expressions.
77 # - Check operand types, and wrap coercion nodes around
78 # sub-expressions where needed.
79 # - Set the type of this node.
80 # - If a temporary variable will be required for the
81 # result, set the is_temp flag of this node.
82 #
83 # analyse_target_types
84 # Called during the Analyse Types phase to analyse
85 # the LHS of an assignment or argument of a del
86 # statement. Similar responsibilities to analyse_types.
87 #
88 # allocate_temps
89 # - Call allocate_temps for all sub-nodes.
90 # - Call allocate_temp for this node.
91 # - If a temporary was allocated, call release_temp on
92 # all sub-expressions.
93 #
94 # allocate_target_temps
95 # - Call allocate_temps on sub-nodes and allocate any other
96 # temps used during assignment.
97 # - Fill in result_code with a C lvalue if needed.
98 # - If a rhs node is supplied, call release_temp on it.
99 # - Call release_temp on sub-nodes and release any other
100 # temps used during assignment.
101 #
102 # #calculate_result_code
103 # # - Called during the Allocate Temps phase. Should return a
104 # # C code fragment evaluating to the result. This is only
105 # # called when the result is not a temporary.
106 #
107 # target_code
108 # Called by the default implementation of allocate_target_temps.
109 # Should return a C lvalue for assigning to the node. The default
110 # implementation calls calculate_result_code.
111 #
112 # check_const
113 # - Check that this node and its subnodes form a
114 # legal constant expression. If so, do nothing,
115 # otherwise call not_const.
116 #
117 # The default implementation of check_const
118 # assumes that the expression is not constant.
119 #
120 # check_const_addr
121 # - Same as check_const, except check that the
122 # expression is a C lvalue whose address is
123 # constant. Otherwise, call addr_not_const.
124 #
125 # The default implementation of calc_const_addr
126 # assumes that the expression is not a constant
127 # lvalue.
128 #
129 # Code Generation phase
130 #
131 # generate_evaluation_code
132 # 1. Call generate_evaluation_code for sub-expressions.
133 # 2. Generate any C statements necessary to calculate
134 # the result of this node from the results of its
135 # sub-expressions. If result is not in a temporary, record
136 # any information that will be needed by this node's
137 # implementation of calculate_result_code().
138 # 4. If result is in a temporary, call generate_disposal_code
139 # on all sub-expressions.
140 #
141 # A default implementation of generate_evaluation_code
142 # is provided which uses the folling abstract methods:
143 # generate_result_code (for no. 2)
144 #
145 # generate_assignment_code
146 # Called on the LHS of an assignment.
147 # - Call generate_evaluation_code for sub-expressions.
148 # - Generate code to perform the assignment.
149 # - If the assignment absorbed a reference, call
150 # generate_post_assignment_code on the RHS,
151 # otherwise call generate_disposal_code on it.
152 #
153 # generate_deletion_code
154 # Called on an argument of a del statement.
155 # - Call generate_evaluation_code for sub-expressions.
156 # - Generate code to perform the deletion.
157 # - Call generate_disposal_code on all sub-expressions.
158 #
159 # calculate_result_code
160 # Return a C code fragment representing the result of this node.
161 # This is only called if the result is not in a temporary.
162 #
164 is_sequence_constructor = 0
165 is_attribute = 0
167 saved_subexpr_nodes = None
168 is_temp = 0
170 def not_implemented(self, method_name):
171 print_call_chain(method_name, "not implemented") ###
172 raise InternalError(
173 "%s.%s not implemented" %
174 (self.__class__.__name__, method_name))
176 def is_lvalue(self):
177 return 0
179 def is_inplace_lvalue(self):
180 return 0
182 def is_ephemeral(self):
183 # An ephemeral node is one whose result is in
184 # a Python temporary and we suspect there are no
185 # other references to it. Certain operations are
186 # disallowed on such values, since they are
187 # likely to result in a dangling pointer.
188 return self.type.is_pyobject and self.is_temp
190 def subexpr_nodes(self):
191 # Extract a list of subexpression nodes based
192 # on the contents of the subexprs class attribute.
193 if self.saved_subexpr_nodes is None:
194 nodes = []
195 for name in self.subexprs:
196 item = getattr(self, name)
197 if item:
198 if isinstance(item, ExprNode):
199 nodes.append(item)
200 else:
201 nodes.extend(item)
202 self.saved_subexpr_nodes = nodes
203 return self.saved_subexpr_nodes
205 def result(self):
206 # Return a C code fragment for the result of this node.
207 if self.is_temp:
208 result_code = self.result_code
209 else:
210 result_code = self.calculate_result_code()
211 return result_code
213 def result_as(self, type = None):
214 # Return the result code cast to the specified C type.
215 return typecast(type, self.ctype(), self.result())
217 def py_result(self):
218 # Return the result code cast to PyObject *.
219 return self.result_as(py_object_type)
221 def ctype(self):
222 # Return the native C type of the result.
223 return self.result_ctype or self.type
225 def compile_time_value(self, denv):
226 # Return value of compile-time expression, or report error.
227 error(self.pos, "Invalid compile-time expression")
229 def compile_time_value_error(self, e):
230 error(self.pos, "Error in compile-time expression: %s: %s" % (
231 e.__class__.__name__, e))
233 # ------------- Declaration Analysis ----------------
235 def analyse_target_declaration(self, env):
236 error(self.pos, "Cannot assign to or delete this")
238 # ------------- Expression Analysis ----------------
240 def analyse_const_expression(self, env):
241 # Called during the analyse_declarations phase of a
242 # constant expression. Analyses the expression's type,
243 # checks whether it is a legal const expression,
244 # and determines its value.
245 self.analyse_types(env)
246 self.allocate_temps(env)
247 self.check_const()
249 def analyse_expressions(self, env):
250 # Convenience routine performing both the Type
251 # Analysis and Temp Allocation phases for a whole
252 # expression.
253 self.analyse_types(env)
254 self.allocate_temps(env)
256 def analyse_target_expression(self, env, rhs):
257 # Convenience routine performing both the Type
258 # Analysis and Temp Allocation phases for the LHS of
259 # an assignment.
260 self.analyse_target_types(env)
261 self.allocate_target_temps(env, rhs)
263 def analyse_boolean_expression(self, env):
264 # Analyse expression and coerce to a boolean.
265 self.analyse_types(env)
266 bool = self.coerce_to_boolean(env)
267 bool.allocate_temps(env)
268 return bool
270 def analyse_temp_boolean_expression(self, env):
271 # Analyse boolean expression and coerce result into
272 # a temporary. This is used when a branch is to be
273 # performed on the result and we won't have an
274 # opportunity to ensure disposal code is executed
275 # afterwards. By forcing the result into a temporary,
276 # we ensure that all disposal has been done by the
277 # time we get the result.
278 self.analyse_types(env)
279 bool = self.coerce_to_boolean(env)
280 temp_bool = bool.coerce_to_temp(env)
281 temp_bool.allocate_temps(env)
282 return temp_bool
284 # --------------- Type Analysis ------------------
286 def analyse_as_module(self, env):
287 # If this node can be interpreted as a reference to a
288 # cimported module, return its scope, else None.
289 return None
291 def analyse_as_extension_type(self, env):
292 # If this node can be interpreted as a reference to an
293 # extension type, return its type, else None.
294 return None
296 def analyse_types(self, env):
297 self.not_implemented("analyse_types")
299 def analyse_target_types(self, env):
300 self.analyse_types(env)
302 def analyse_inplace_types(self, env):
303 if self.is_inplace_lvalue():
304 self.analyse_types(env)
305 else:
306 error(self.pos, "Invalid target for in-place operation")
307 self.type = error_type
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, inplace = 0):
339 # Perform temp allocation for the LHS of an assignment.
340 if debug_temp_alloc:
341 print self, "Allocating target temps"
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_inplace_target_temps(self, env, rhs):
349 if debug_temp_alloc:
350 print self, "Allocating inplace target temps"
351 self.allocate_subexpr_temps(env)
352 #self.result_code = self.target_code()
353 py_inplace = self.type.is_pyobject
354 if py_inplace:
355 self.allocate_temp(env)
356 self.inplace_result = env.allocate_temp(py_object_type)
357 self.release_temp(env)
358 rhs.release_temp(env)
359 if py_inplace:
360 env.release_temp(self.inplace_result)
361 self.release_subexpr_temps(env)
363 def allocate_temps(self, env, result = None):
364 # Allocate temporary variables for this node and
365 # all its sub-expressions. If a result is specified,
366 # this must be a temp node and the specified variable
367 # is used as the result instead of allocating a new
368 # one.
369 if debug_temp_alloc:
370 print self, "Allocating temps"
371 self.allocate_subexpr_temps(env)
372 self.allocate_temp(env, result)
373 if self.is_temp:
374 self.release_subexpr_temps(env)
376 def allocate_subexpr_temps(self, env):
377 # Allocate temporary variables for all sub-expressions
378 # of this node.
379 if debug_temp_alloc:
380 print self, "Allocating temps for:", self.subexprs
381 for node in self.subexpr_nodes():
382 if node:
383 if debug_temp_alloc:
384 print self, "Allocating temps for", node
385 node.allocate_temps(env)
387 def allocate_temp(self, env, result = None):
388 # If this node requires a temporary variable for its
389 # result, allocate one. If a result is specified,
390 # this must be a temp node and the specified variable
391 # is used as the result instead of allocating a new
392 # one.
393 if debug_temp_alloc:
394 print self, "Allocating temp"
395 if result:
396 if not self.is_temp:
397 raise InternalError("Result forced on non-temp node")
398 self.result_code = result
399 elif self.is_temp:
400 type = self.type
401 if not type.is_void:
402 if type.is_pyobject:
403 type = PyrexTypes.py_object_type
404 self.result_code = env.allocate_temp(type)
405 else:
406 self.result_code = None
407 if debug_temp_alloc:
408 print self, "Allocated result", self.result_code
409 #else:
410 # self.result_code = self.calculate_result_code()
412 def target_code(self):
413 # Return code fragment for use as LHS of a C assignment.
414 return self.calculate_result_code()
416 def calculate_result_code(self):
417 self.not_implemented("calculate_result_code")
419 def release_temp(self, env):
420 # If this node owns a temporary result, release it,
421 # otherwise release results of its sub-expressions.
422 if self.is_temp:
423 if debug_temp_alloc:
424 print self, "Releasing result", self.result_code
425 env.release_temp(self.result_code)
426 else:
427 self.release_subexpr_temps(env)
429 def release_subexpr_temps(self, env):
430 # Release the results of all sub-expressions of
431 # this node.
432 for node in self.subexpr_nodes():
433 if node:
434 node.release_temp(env)
436 # ---------------- Code Generation -----------------
438 def make_owned_reference(self, code):
439 # If result is a pyobject, make sure we own
440 # a reference to it.
441 if self.type.is_pyobject and not self.result_in_temp():
442 code.put_incref(self.py_result())
444 def generate_evaluation_code(self, code):
445 # Generate code to evaluate this node and
446 # its sub-expressions, and dispose of any
447 # temporary results of its sub-expressions.
448 self.generate_subexpr_evaluation_code(code)
449 self.generate_result_code(code)
450 if self.is_temp:
451 self.generate_subexpr_disposal_code(code)
453 def generate_subexpr_evaluation_code(self, code):
454 for node in self.subexpr_nodes():
455 node.generate_evaluation_code(code)
457 def generate_result_code(self, code):
458 self.not_implemented("generate_result_code")
460 inplace_functions = {
461 "+=": "PyNumber_InPlaceAdd",
462 "-=": "PyNumber_InPlaceSubtract",
463 "*=": "PyNumber_InPlaceMultiply",
464 "/=": "PyNumber_InPlaceDivide",
465 "%=": "PyNumber_InPlaceRemainder",
466 "**=": "PyNumber_InPlacePower",
467 "<<=": "PyNumber_InPlaceLshift",
468 ">>=": "PyNumber_InPlaceRshift",
469 "&=": "PyNumber_InPlaceAnd",
470 "^=": "PyNumber_InPlaceXor",
471 "|=": "PyNumber_InPlaceOr",
472 }
474 def generate_inplace_operation_code(self, operator, rhs, code):
475 args = (self.py_result(), rhs.py_result())
476 if operator == "**=":
477 arg_code = "%s, %s, Py_None" % args
478 else:
479 arg_code = "%s, %s" % args
480 code.putln("%s = %s(%s); if (!%s) %s" % (
481 self.inplace_result,
482 self.inplace_functions[operator],
483 arg_code,
484 self.inplace_result,
485 code.error_goto(self.pos)))
486 if self.is_temp:
487 code.put_decref_clear(self.py_result())
488 rhs.generate_disposal_code(code)
489 if self.type.is_extension_type:
490 code.putln(
491 "if (!__Pyx_TypeTest(%s, %s)) %s" % (
492 self.inplace_result,
493 self.type.typeptr_cname,
494 code.error_goto(self.pos)))
496 def generate_disposal_code(self, code):
497 # If necessary, generate code to dispose of
498 # temporary Python reference.
499 if self.is_temp:
500 if self.type.is_pyobject:
501 code.put_decref_clear(self.py_result(), self.ctype())
502 else:
503 self.generate_subexpr_disposal_code(code)
505 def generate_subexpr_disposal_code(self, code):
506 # Generate code to dispose of temporary results
507 # of all sub-expressions.
508 for node in self.subexpr_nodes():
509 node.generate_disposal_code(code)
511 def generate_post_assignment_code(self, code):
512 # Same as generate_disposal_code except that
513 # assignment will have absorbed a reference to
514 # the result if it is a Python object.
515 if self.is_temp:
516 if self.type.is_pyobject:
517 code.putln("%s = 0;" % self.result())
518 else:
519 self.generate_subexpr_disposal_code(code)
521 def generate_inplace_result_disposal_code(self, code):
522 code.put_decref_clear(self.inplace_result, py_object_type)
524 def generate_assignment_code(self, rhs, code):
525 # Stub method for nodes which are not legal as
526 # the LHS of an assignment. An error will have
527 # been reported earlier.
528 pass
530 def generate_deletion_code(self, code):
531 # Stub method for nodes that are not legal as
532 # the argument of a del statement. An error
533 # will have been reported earlier.
534 pass
536 # ----------------- Coercion ----------------------
538 def coerce_to(self, dst_type, env):
539 # Coerce the result so that it can be assigned to
540 # something of type dst_type. If processing is necessary,
541 # wraps this node in a coercion node and returns that.
542 # Otherwise, returns this node unchanged.
543 #
544 # This method is called during the analyse_expressions
545 # phase of the src_node's processing.
546 src = self
547 src_type = self.type
548 src_is_py_type = src_type.is_pyobject
549 dst_is_py_type = dst_type.is_pyobject
551 if dst_type.is_pyobject:
552 if not src.type.is_pyobject:
553 src = CoerceToPyTypeNode(src, env)
554 if not src.type.subtype_of(dst_type):
555 if not isinstance(src, NoneNode):
556 src = PyTypeTestNode(src, dst_type, env)
557 elif src.type.is_pyobject:
558 src = CoerceFromPyTypeNode(dst_type, src, env)
559 else: # neither src nor dst are py types
560 if not dst_type.assignable_from(src_type):
561 error(self.pos, "Cannot assign type '%s' to '%s'" %
562 (src.type, dst_type))
563 return src
565 def coerce_to_pyobject(self, env):
566 return self.coerce_to(PyrexTypes.py_object_type, env)
568 def coerce_to_boolean(self, env):
569 # Coerce result to something acceptable as
570 # a boolean value.
571 type = self.type
572 if type.is_pyobject or type.is_ptr or type.is_float:
573 return CoerceToBooleanNode(self, env)
574 else:
575 if not type.is_int and not type.is_error:
576 error(self.pos,
577 "Type '%s' not acceptable as a boolean" % type)
578 return self
580 def coerce_to_integer(self, env):
581 # If not already some C integer type, coerce to longint.
582 if self.type.is_int:
583 return self
584 else:
585 return self.coerce_to(PyrexTypes.c_long_type, env)
587 def coerce_to_temp(self, env):
588 # Ensure that the result is in a temporary.
589 if self.result_in_temp():
590 return self
591 else:
592 return CoerceToTempNode(self, env)
594 def coerce_to_simple(self, env):
595 # Ensure that the result is simple (see is_simple).
596 if self.is_simple():
597 return self
598 else:
599 return self.coerce_to_temp(env)
601 def is_simple(self):
602 # A node is simple if its result is something that can
603 # be referred to without performing any operations, e.g.
604 # a constant, local var, C global var, struct member
605 # reference, or temporary.
606 return self.result_in_temp()
609 class AtomicExprNode(ExprNode):
610 # Abstract base class for expression nodes which have
611 # no sub-expressions.
613 subexprs = []
616 class PyConstNode(AtomicExprNode):
617 # Abstract base class for constant Python values.
619 def is_simple(self):
620 return 1
622 def analyse_types(self, env):
623 self.type = py_object_type
625 def calculate_result_code(self):
626 return self.value
628 def generate_result_code(self, code):
629 pass
632 class NoneNode(PyConstNode):
633 # The constant value None
635 value = "Py_None"
637 def compile_time_value(self, denv):
638 return None
641 class EllipsisNode(PyConstNode):
642 # '...' in a subscript list.
644 value = "Py_Ellipsis"
646 def compile_time_value(self, denv):
647 return Ellipsis
650 class ConstNode(AtomicExprNode):
651 # Abstract base type for literal constant nodes.
652 #
653 # value string C code fragment
655 is_literal = 1
657 def is_simple(self):
658 return 1
660 def analyse_types(self, env):
661 pass # Types are held in class variables
663 def check_const(self):
664 pass
666 def calculate_result_code(self):
667 return str(self.value)
669 def generate_result_code(self, code):
670 pass
673 class NullNode(ConstNode):
674 type = PyrexTypes.c_null_ptr_type
675 value = "NULL"
678 class CharNode(ConstNode):
679 type = PyrexTypes.c_char_type
681 def compile_time_value(self, denv):
682 return ord(self.value)
684 def calculate_result_code(self):
685 return "'%s'" % self.value
688 class IntNode(ConstNode):
689 type = PyrexTypes.c_long_type
691 def compile_time_value(self, denv):
692 return int(self.value)
695 class FloatNode(ConstNode):
696 type = PyrexTypes.c_double_type
698 def compile_time_value(self, denv):
699 return float(self.value)
701 def calculate_result_code(self):
702 strval = str(self.value)
703 if strval == 'nan':
704 return "NAN"
705 elif strval == 'inf':
706 return "INFINITY"
707 elif strval == '-inf':
708 return "(-INFINITY)"
709 else:
710 return strval
713 class StringNode(ConstNode):
714 # #entry Symtab.Entry
716 type = PyrexTypes.c_char_ptr_type
718 def compile_time_value(self, denv):
719 return eval('"%s"' % self.value)
721 # def analyse_types(self, env):
722 # self.entry = env.add_string_const(self.value)
724 def coerce_to(self, dst_type, env):
725 # Arrange for a Python version of the string to be pre-allocated
726 # when coercing to a Python type.
727 if dst_type.is_pyobject and not self.type.is_pyobject:
728 node = self.as_py_string_node(env)
729 else:
730 node = self
731 # We still need to perform normal coerce_to processing on the
732 # result, because we might be coercing to an extension type,
733 # in which case a type test node will be needed.
734 return ConstNode.coerce_to(node, dst_type, env)
736 def as_py_string_node(self, env):
737 # Return a new StringNode with the same value as this node
738 # but whose type is a Python type instead of a C type.
739 #entry = self.entry
740 #env.add_py_string(entry)
741 return StringNode(self.pos, type = py_object_type, value = self.value)
743 def generate_evaluation_code(self, code):
744 if self.type.is_pyobject:
745 self.result_code = code.get_py_string_const(self.value)
746 else:
747 self.result_code = code.get_string_const(self.value)
749 def calculate_result_code(self):
750 return self.result_code
753 class LongNode(AtomicExprNode):
754 # Python long integer literal
755 #
756 # value string
758 def compile_time_value(self, denv):
759 return long(self.value)
761 gil_message = "Constructing Python long int"
763 def analyse_types(self, env):
764 self.type = py_object_type
765 self.gil_check(env)
766 self.is_temp = 1
768 def generate_evaluation_code(self, code):
769 result = self.result()
770 code.putln(
771 '%s = PyLong_FromString("%s", 0, 0); if (!%s) %s' % (
772 self.result(),
773 self.value,
774 self.result(),
775 code.error_goto(self.pos)))
778 class ImagNode(AtomicExprNode):
779 # Imaginary number literal
780 #
781 # value float imaginary part
783 def compile_time_value(self, denv):
784 return complex(0.0, self.value)
786 gil_message = "Constructing complex number"
788 def analyse_types(self, env):
789 self.type = py_object_type
790 self.gil_check(env)
791 self.is_temp = 1
793 def generate_evaluation_code(self, code):
794 result = self.result()
795 code.putln(
796 "%s = PyComplex_FromDoubles(0.0, %s); if (!%s) %s" % (
797 self.result(),
798 self.value,
799 self.result(),
800 code.error_goto(self.pos)))
803 class NameNode(AtomicExprNode):
804 # Reference to a local or global variable name.
805 #
806 # name string Python name of the variable
807 #
808 # entry Entry Symbol table entry
809 # type_entry Entry For extension type names, the original type entry
810 # interned_cname string
812 is_name = 1
813 entry = None
814 type_entry = None
816 def compile_time_value(self, denv):
817 try:
818 return denv.lookup(self.name)
819 except KeyError:
820 error(self.pos, "Compile-time name '%s' not defined" % self.name)
822 def coerce_to(self, dst_type, env):
823 # If coercing to a generic pyobject and this is a builtin
824 # C function with a Python equivalent, manufacture a NameNode
825 # referring to the Python builtin.
826 #print "NameNode.coerce_to:", self.name, dst_type ###
827 if dst_type is py_object_type:
828 entry = self.entry
829 if entry.is_cfunction:
830 var_entry = entry.as_variable
831 if var_entry:
832 node = NameNode(self.pos, name = self.name)
833 node.entry = var_entry
834 node.analyse_rvalue_entry(env)
835 return node
836 return AtomicExprNode.coerce_to(self, dst_type, env)
838 def analyse_as_module(self, env):
839 # Try to interpret this as a reference to a cimported module.
840 # Returns the module scope, or None.
841 entry = env.lookup(self.name)
842 if entry and entry.as_module:
843 return entry.as_module
844 return None
846 def analyse_as_extension_type(self, env):
847 # Try to interpret this as a reference to an extension type.
848 # Returns the extension type, or None.
849 entry = env.lookup(self.name)
850 if entry and entry.is_type and entry.type.is_extension_type:
851 return entry.type
852 else:
853 return None
855 def analyse_target_declaration(self, env):
856 self.entry = env.lookup_here(self.name)
857 if not self.entry:
858 self.entry = env.declare_var(self.name, py_object_type, self.pos)
860 def analyse_types(self, env):
861 self.entry = env.lookup(self.name)
862 if not self.entry:
863 self.entry = env.declare_builtin(self.name, self.pos)
864 self.analyse_rvalue_entry(env)
866 def analyse_target_types(self, env):
867 self.analyse_entry(env)
868 self.finish_analysing_lvalue()
870 def analyse_inplace_types(self, env):
871 self.analyse_rvalue_entry(env)
872 self.finish_analysing_lvalue()
874 def finish_analysing_lvalue(self):
875 if self.entry.is_readonly:
876 error(self.pos, "Assignment to read-only name '%s'"
877 % self.name)
878 elif not self.is_lvalue():
879 error(self.pos, "Assignment to non-lvalue '%s'"
880 % self.name)
881 self.type = PyrexTypes.error_type
882 self.entry.used = 1
884 def analyse_rvalue_entry(self, env):
885 #print "NameNode.analyse_rvalue_entry:", self.name ###
886 #print "Entry:", self.entry.__dict__ ###
887 self.analyse_entry(env)
888 entry = self.entry
889 if entry.is_declared_generic:
890 self.result_ctype = py_object_type
891 if entry.is_pyglobal or entry.is_builtin:
892 self.is_temp = 1
893 self.gil_check(env)
895 gil_message = "Accessing Python global or builtin"
897 def analyse_entry(self, env):
898 #print "NameNode.analyse_entry:", self.name ###
899 self.check_identifier_kind()
900 entry = self.entry
901 type = entry.type
902 ctype = entry.ctype
903 self.type = type
904 if ctype:
905 self.result_ctype = ctype
906 if entry.is_pyglobal or entry.is_builtin:
907 assert type.is_pyobject, "Python global or builtin not a Python object"
908 #self.interned_cname = env.intern(self.entry.name)
910 def check_identifier_kind(self):
911 # Check that this is an appropriate kind of name for use in an expression.
912 # Also finds the variable entry associated with an extension type.
913 entry = self.entry
914 if entry.is_type and entry.type.is_extension_type:
915 self.type_entry = entry
916 if not (entry.is_const or entry.is_variable
917 or entry.is_builtin or entry.is_cfunction):
918 if self.entry.as_variable:
919 self.entry = self.entry.as_variable
920 else:
921 error(self.pos,
922 "'%s' is not a constant, variable or function identifier" % self.name)
924 def is_simple(self):
925 # If it's not a C variable, it'll be in a temp.
926 return 1
928 def calculate_target_results(self, env):
929 pass
931 def check_const(self):
932 entry = self.entry
933 if not (entry.is_const or entry.is_cfunction):
934 self.not_const()
936 def check_const_addr(self):
937 entry = self.entry
938 if not (entry.is_cglobal or entry.is_cfunction):
939 self.addr_not_const()
941 def is_lvalue(self):
942 entry = self.entry
943 return entry.is_variable and \
944 not entry.type.is_array and \
945 not entry.is_readonly
947 def is_inplace_lvalue(self):
948 return self.is_lvalue()
950 def is_ephemeral(self):
951 # Name nodes are never ephemeral, even if the
952 # result is in a temporary.
953 return 0
955 def allocate_temp(self, env, result = None):
956 AtomicExprNode.allocate_temp(self, env, result)
957 entry = self.entry
958 if entry:
959 entry.used = 1
960 # if entry.utility_code:
961 # env.use_utility_code(entry.utility_code)
963 def calculate_result_code(self):
964 entry = self.entry
965 if not entry:
966 return "<error>" # There was an error earlier
967 return entry.cname
969 def generate_result_code(self, code):
970 assert hasattr(self, 'entry')
971 entry = self.entry
972 if entry is None:
973 return # There was an error earlier
974 if entry.utility_code:
975 code.use_utility_code(entry.utility_code)
976 if entry.is_pyglobal or entry.is_builtin:
977 if entry.is_builtin:
978 namespace = Naming.builtins_cname
979 else: # entry.is_pyglobal
980 namespace = entry.namespace_cname
981 result = self.result()
982 cname = code.intern(self.entry.name)
983 code.use_utility_code(get_name_interned_utility_code)
984 code.putln(
985 '%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
986 result,
987 namespace,
988 cname,
989 result,
990 code.error_goto(self.pos)))
992 def generate_setattr_code(self, value_code, code):
993 entry = self.entry
994 namespace = self.entry.namespace_cname
995 cname = code.intern(self.entry.name)
996 code.putln(
997 'if (PyObject_SetAttr(%s, %s, %s) < 0) %s' % (
998 namespace,
999 cname,
1000 value_code,
1001 code.error_goto(self.pos)))
1003 def generate_assignment_code(self, rhs, code):
1004 #print "NameNode.generate_assignment_code:", self.name ###
1005 entry = self.entry
1006 if entry is None:
1007 return # There was an error earlier
1008 if entry.is_pyglobal:
1009 self.generate_setattr_code(rhs.py_result(), code)
1010 if debug_disposal_code:
1011 print "NameNode.generate_assignment_code:"
1012 print "...generating disposal code for", rhs
1013 rhs.generate_disposal_code(code)
1014 else:
1015 if self.type.is_pyobject:
1016 rhs.make_owned_reference(code)
1017 code.put_decref(self.py_result())
1018 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1019 if debug_disposal_code:
1020 print "NameNode.generate_assignment_code:"
1021 print "...generating post-assignment code for", rhs
1022 rhs.generate_post_assignment_code(code)
1024 def generate_inplace_assignment_code(self, operator, rhs, code):
1025 entry = self.entry
1026 if entry is None:
1027 return # There was an error earlier
1028 if self.type.is_pyobject:
1029 self.generate_result_code(code)
1030 self.generate_inplace_operation_code(operator, rhs, code)
1031 if entry.is_pyglobal:
1032 self.generate_setattr_code(self.inplace_result, code)
1033 self.generate_inplace_result_disposal_code(code)
1034 else:
1035 code.put_decref(self.py_result())
1036 cast_inplace_result = typecast(self.ctype(), py_object_type, self.inplace_result)
1037 code.putln('%s = %s;' % (self.result(), cast_inplace_result))
1038 else:
1039 code.putln("%s %s %s;" % (self.result(), operator, rhs.result()))
1040 rhs.generate_disposal_code(code)
1042 def generate_deletion_code(self, code):
1043 if self.entry is None:
1044 return # There was an error earlier
1045 if not self.entry.is_pyglobal:
1046 error(self.pos, "Deletion of local or C global name not supported")
1047 return
1048 cname = code.intern(self.entry.name)
1049 code.putln(
1050 'if (PyObject_DelAttr(%s, %s) < 0) %s' % (
1051 Naming.module_cname,
1052 cname,
1053 code.error_goto(self.pos)))
1056 class BackquoteNode(ExprNode):
1057 # `expr`
1059 # arg ExprNode
1061 subexprs = ['arg']
1063 def analyse_types(self, env):
1064 self.arg.analyse_types(env)
1065 self.arg = self.arg.coerce_to_pyobject(env)
1066 self.type = py_object_type
1067 self.gil_check(env)
1068 self.is_temp = 1
1070 gil_message = "Backquote expression"
1072 def generate_result_code(self, code):
1073 result = self.result()
1074 code.putln(
1075 "%s = PyObject_Repr(%s); if (!%s) %s" % (
1076 self.result(),
1077 self.arg.py_result(),
1078 self.result(),
1079 code.error_goto(self.pos)))
1082 class ImportNode(ExprNode):
1083 # Used as part of import statement implementation.
1084 # Implements result =
1085 # __import__(module_name, globals(), None, name_list)
1087 # module_name StringNode dotted name of module
1088 # name_list ListNode or None list of names to be imported
1090 subexprs = ['module_name', 'name_list']
1092 def analyse_types(self, env):
1093 self.module_name.analyse_types(env)
1094 self.module_name = self.module_name.coerce_to_pyobject(env)
1095 if self.name_list:
1096 self.name_list.analyse_types(env)
1097 self.type = py_object_type
1098 self.gil_check(env)
1099 self.is_temp = 1
1100 # env.use_utility_code(import_utility_code)
1102 gil_message = "Python import"
1104 def generate_result_code(self, code):
1105 if self.name_list:
1106 name_list_code = self.name_list.py_result()
1107 else:
1108 name_list_code = "0"
1109 code.use_utility_code(import_utility_code)
1110 result = self.result()
1111 code.putln(
1112 "%s = __Pyx_Import(%s, %s); if (!%s) %s" % (
1113 result,
1114 self.module_name.py_result(),
1115 name_list_code,
1116 result,
1117 code.error_goto(self.pos)))
1120 class IteratorNode(ExprNode):
1121 # Used as part of for statement implementation.
1122 # Implements result = iter(sequence)
1124 # sequence ExprNode
1126 subexprs = ['sequence']
1128 def analyse_types(self, env):
1129 self.sequence.analyse_types(env)
1130 self.sequence = self.sequence.coerce_to_pyobject(env)
1131 self.type = py_object_type
1132 self.gil_check(env)
1133 self.is_temp = 1
1135 gil_message = "Iterating over Python object"
1137 def generate_result_code(self, code):
1138 result = self.result()
1139 code.putln(
1140 "%s = PyObject_GetIter(%s); if (!%s) %s" % (
1141 result,
1142 self.sequence.py_result(),
1143 result,
1144 code.error_goto(self.pos)))
1147 class NextNode(AtomicExprNode):
1148 # Used as part of for statement implementation.
1149 # Implements result = iterator.next()
1150 # Created during analyse_types phase.
1151 # The iterator is not owned by this node.
1153 # iterator ExprNode
1155 def __init__(self, iterator, env):
1156 self.pos = iterator.pos
1157 self.iterator = iterator
1158 self.type = py_object_type
1159 self.is_temp = 1
1161 def generate_result_code(self, code):
1162 result = self.result()
1163 code.putln(
1164 "%s = PyIter_Next(%s);" % (
1165 result,
1166 self.iterator.py_result()))
1167 code.putln(
1168 "if (!%s) {" %
1169 result)
1170 code.putln(
1171 "if (PyErr_Occurred()) %s" %
1172 code.error_goto(self.pos))
1173 code.putln(
1174 "break;")
1175 code.putln(
1176 "}")
1179 class ExcValueNode(AtomicExprNode):
1180 # Node created during analyse_types phase
1181 # of an ExceptClauseNode to fetch the current
1182 # exception value.
1184 def __init__(self, pos, env, var):
1185 ExprNode.__init__(self, pos)
1186 self.type = py_object_type
1187 self.var = var
1189 def calculate_result_code(self):
1190 return self.var
1192 def generate_result_code(self, code):
1193 pass
1196 class TempNode(AtomicExprNode):
1197 # Node created during analyse_types phase
1198 # of some nodes to hold a temporary value.
1200 def __init__(self, pos, type, env):
1201 ExprNode.__init__(self, pos)
1202 self.type = type
1203 if type.is_pyobject:
1204 self.result_ctype = py_object_type
1205 self.is_temp = 1
1207 def generate_result_code(self, code):
1208 pass
1211 class PyTempNode(TempNode):
1212 # TempNode holding a Python value.
1214 def __init__(self, pos, env):
1215 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1218 #-------------------------------------------------------------------
1220 # Trailer nodes
1222 #-------------------------------------------------------------------
1224 class IndexNode(ExprNode):
1225 # Sequence indexing.
1227 # base ExprNode
1228 # index ExprNode
1230 subexprs = ['base', 'index']
1232 def compile_time_value(self, denv):
1233 base = self.base.compile_time_value(denv)
1234 index = self.index.compile_time_value(denv)
1235 try:
1236 return base[index]
1237 except Exception, e:
1238 self.compile_time_value_error(e)
1240 def is_ephemeral(self):
1241 return self.base.is_ephemeral()
1243 def analyse_target_declaration(self, env):
1244 pass
1246 def analyse_types(self, env):
1247 self.analyse_base_and_index_types(env, getting = 1)
1249 def analyse_target_types(self, env):
1250 self.analyse_base_and_index_types(env, setting = 1)
1252 def analyse_inplace_types(self, env):
1253 self.analyse_base_and_index_types(env, getting = 1, setting = 1)
1255 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1256 self.base.analyse_types(env)
1257 self.index.analyse_types(env)
1258 if self.base.type.is_pyobject:
1259 # if self.index.type.is_int:
1260 # if getting:
1261 # env.use_utility_code(getitem_int_utility_code)
1262 # if setting:
1263 # env.use_utility_code(setitem_int_utility_code)
1264 # else:
1265 if not self.index.type.is_int:
1266 self.index = self.index.coerce_to_pyobject(env)
1267 self.type = py_object_type
1268 self.gil_check(env)
1269 self.is_temp = 1
1270 else:
1271 if self.base.type.is_ptr or self.base.type.is_array:
1272 self.type = self.base.type.base_type
1273 else:
1274 error(self.pos,
1275 "Attempting to index non-array type '%s'" %
1276 self.base.type)
1277 self.type = PyrexTypes.error_type
1278 if self.index.type.is_pyobject:
1279 self.index = self.index.coerce_to(
1280 PyrexTypes.c_py_ssize_t_type, env)
1281 if not self.index.type.is_int:
1282 error(self.pos,
1283 "Invalid index type '%s'" %
1284 self.index.type)
1286 gil_message = "Indexing Python object"
1288 def check_const_addr(self):
1289 self.base.check_const_addr()
1290 self.index.check_const()
1292 def is_lvalue(self):
1293 return 1
1295 def is_inplace_lvalue(self):
1296 return 1
1298 def calculate_result_code(self):
1299 return "(%s[%s])" % (
1300 self.base.result(), self.index.result())
1302 def generate_result_code(self, code):
1303 if self.type.is_pyobject:
1304 if self.index.type.is_int:
1305 code.use_utility_code(getitem_int_utility_code)
1306 function = "__Pyx_GetItemInt"
1307 index_code = self.index.result()
1308 else:
1309 function = "PyObject_GetItem"
1310 index_code = self.index.py_result()
1311 result = self.result()
1312 code.putln(
1313 "%s = %s(%s, %s); if (!%s) %s" % (
1314 result,
1315 function,
1316 self.base.py_result(),
1317 index_code,
1318 result,
1319 code.error_goto(self.pos)))
1321 def generate_setitem_code(self, value_code, code):
1322 if self.index.type.is_int:
1323 code.use_utility_code(setitem_int_utility_code)
1324 function = "__Pyx_SetItemInt"
1325 index_code = self.index.result()
1326 else:
1327 function = "PyObject_SetItem"
1328 index_code = self.index.py_result()
1329 code.putln(
1330 "if (%s(%s, %s, %s) < 0) %s" % (
1331 function,
1332 self.base.py_result(),
1333 index_code,
1334 value_code,
1335 code.error_goto(self.pos)))
1337 def generate_assignment_code(self, rhs, code):
1338 self.generate_subexpr_evaluation_code(code)
1339 if self.type.is_pyobject:
1340 self.generate_setitem_code(rhs.py_result(), code)
1341 else:
1342 code.putln(
1343 "%s = %s;" % (
1344 self.result(), rhs.result()))
1345 self.generate_subexpr_disposal_code(code)
1346 rhs.generate_disposal_code(code)
1348 def generate_inplace_assignment_code(self, operator, rhs, code):
1349 self.generate_subexpr_evaluation_code(code)
1350 if self.type.is_pyobject:
1351 self.generate_result_code(code)
1352 self.generate_inplace_operation_code(operator, rhs, code)
1353 self.generate_setitem_code(self.inplace_result, code)
1354 self.generate_inplace_result_disposal_code(code)
1355 else:
1356 code.putln("%s %s %s;" % (self.result(), operator, rhs.result()))
1357 rhs.generate_disposal_code(code)
1358 self.generate_subexpr_disposal_code(code)
1360 def generate_deletion_code(self, code):
1361 self.generate_subexpr_evaluation_code(code)
1362 #if self.type.is_pyobject:
1363 if self.index.type.is_int:
1364 function = "PySequence_DelItem"
1365 index_code = self.index.result()
1366 else:
1367 function = "PyObject_DelItem"
1368 index_code = self.index.py_result()
1369 code.putln(
1370 "if (%s(%s, %s) < 0) %s" % (
1371 function,
1372 self.base.py_result(),
1373 index_code,
1374 code.error_goto(self.pos)))
1375 #else:
1376 # error(self.pos, "Cannot delete non-Python variable")
1377 self.generate_subexpr_disposal_code(code)
1380 class SliceIndexNode(ExprNode):
1381 # 2-element slice indexing
1383 # base ExprNode
1384 # start ExprNode or None
1385 # stop ExprNode or None
1387 subexprs = ['base', 'start', 'stop']
1389 def is_inplace_lvalue(self):
1390 return 1
1392 def compile_time_value(self, denv):
1393 base = self.base.compile_time_value(denv)
1394 start = self.start.compile_time_value(denv)
1395 stop = self.stop.compile_time_value(denv)
1396 try:
1397 return base[start:stop]
1398 except Exception, e:
1399 self.compile_time_value_error(e)
1401 def analyse_target_declaration(self, env):
1402 pass
1404 def analyse_types(self, env):
1405 self.base.analyse_types(env)
1406 if self.start:
1407 self.start.analyse_types(env)
1408 if self.stop:
1409 self.stop.analyse_types(env)
1410 self.base = self.base.coerce_to_pyobject(env)
1411 c_int = PyrexTypes.c_py_ssize_t_type
1412 if self.start:
1413 self.start = self.start.coerce_to(c_int, env)
1414 if self.stop:
1415 self.stop = self.stop.coerce_to(c_int, env)
1416 self.type = py_object_type
1417 self.gil_check(env)
1418 self.is_temp = 1
1420 gil_message = "Slicing Python object"
1422 def generate_result_code(self, code):
1423 result = self.result()
1424 code.putln(
1425 "%s = PySequence_GetSlice(%s, %s, %s); if (!%s) %s" % (
1426 result,
1427 self.base.py_result(),
1428 self.start_code(),
1429 self.stop_code(),
1430 result,
1431 code.error_goto(self.pos)))
1433 def generate_setslice_code(self, value_code, code):
1434 code.putln(
1435 "if (PySequence_SetSlice(%s, %s, %s, %s) < 0) %s" % (
1436 self.base.py_result(),
1437 self.start_code(),
1438 self.stop_code(),
1439 value_code,
1440 code.error_goto(self.pos)))
1442 def generate_assignment_code(self, rhs, code):
1443 self.generate_subexpr_evaluation_code(code)
1444 self.generate_setslice_code(rhs.result(), code)
1445 self.generate_subexpr_disposal_code(code)
1446 rhs.generate_disposal_code(code)
1448 def generate_inplace_assignment_code(self, operator, rhs, code):
1449 self.generate_subexpr_evaluation_code(code)
1450 self.generate_result_code(code)
1451 self.generate_inplace_operation_code(operator, rhs, code)
1452 self.generate_setslice_code(self.inplace_result, code)
1453 self.generate_inplace_result_disposal_code(code)
1454 self.generate_subexpr_disposal_code(code)
1456 def generate_deletion_code(self, code):
1457 self.generate_subexpr_evaluation_code(code)
1458 code.putln(
1459 "if (PySequence_DelSlice(%s, %s, %s) < 0) %s" % (
1460 self.base.py_result(),
1461 self.start_code(),
1462 self.stop_code(),
1463 code.error_goto(self.pos)))
1464 self.generate_subexpr_disposal_code(code)
1466 def start_code(self):
1467 if self.start:
1468 return self.start.result()
1469 else:
1470 return "0"
1472 def stop_code(self):
1473 if self.stop:
1474 return self.stop.result()
1475 else:
1476 return "PY_SSIZE_T_MAX"
1478 # def calculate_result_code(self):
1479 # # self.result_code is not used, but this method must exist
1480 # return "<unused>"
1483 class SliceNode(ExprNode):
1484 # start:stop:step in subscript list
1486 # start ExprNode
1487 # stop ExprNode
1488 # step ExprNode
1490 def compile_time_value(self, denv):
1491 start = self.start.compile_time_value(denv)
1492 stop = self.stop.compile_time_value(denv)
1493 step = step.step.compile_time_value(denv)
1494 try:
1495 return slice(start, stop, step)
1496 except Exception, e:
1497 self.compile_time_value_error(e)
1499 subexprs = ['start', 'stop', 'step']
1501 def analyse_types(self, env):
1502 self.start.analyse_types(env)
1503 self.stop.analyse_types(env)
1504 self.step.analyse_types(env)
1505 self.start = self.start.coerce_to_pyobject(env)
1506 self.stop = self.stop.coerce_to_pyobject(env)
1507 self.step = self.step.coerce_to_pyobject(env)
1508 self.type = py_object_type
1509 self.gil_check(env)
1510 self.is_temp = 1
1512 gil_message = "Constructing Python slice object"
1514 def generate_result_code(self, code):
1515 result = self.result()
1516 code.putln(
1517 "%s = PySlice_New(%s, %s, %s); if (!%s) %s" % (
1518 result,
1519 self.start.py_result(),
1520 self.stop.py_result(),
1521 self.step.py_result(),
1522 result,
1523 code.error_goto(self.pos)))
1526 class CallNode(ExprNode):
1528 def gil_check(self, env):
1529 # Make sure we're not in a nogil environment
1530 if env.nogil:
1531 error(self.pos, "Calling gil-requiring function without gil")
1534 class SimpleCallNode(CallNode):
1535 # Function call without keyword, * or ** args.
1537 # function ExprNode
1538 # args [ExprNode]
1539 # arg_tuple ExprNode or None used internally
1540 # self ExprNode or None used internally
1541 # coerced_self ExprNode or None used internally
1543 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1545 self = None
1546 coerced_self = None
1547 arg_tuple = None
1549 def compile_time_value(self, denv):
1550 function = self.function.compile_time_value(denv)
1551 args = [arg.compile_time_value(denv) for arg in self.args]
1552 try:
1553 return function(*args)
1554 except Exception, e:
1555 self.compile_time_value_error(e)
1557 def analyse_types(self, env):
1558 #print "SimpleCallNode.analyse_types:", self.pos ###
1559 function = self.function
1560 function.is_called = 1
1561 function.analyse_types(env)
1562 if function.is_name or function.is_attribute:
1563 func_entry = function.entry
1564 if func_entry:
1565 if func_entry.is_cmethod or func_entry.is_builtin_method:
1566 # Take ownership of the object from which the attribute
1567 # was obtained, because we need to pass it as 'self'.
1568 #print "SimpleCallNode: Snarfing self argument" ###
1569 self.self = function.obj
1570 function.obj = CloneNode(self.self)
1571 func_type = self.function_type()
1572 if func_type.is_pyobject:
1573 if self.args:
1574 self.arg_tuple = TupleNode(self.pos, args = self.args)
1575 self.arg_tuple.analyse_types(env)
1576 else:
1577 self.arg_tuple = None
1578 self.args = None
1579 if function.is_name and function.type_entry:
1580 # We are calling an extension type constructor
1581 self.type = function.type_entry.type
1582 self.result_ctype = py_object_type
1583 else:
1584 self.type = py_object_type
1585 self.gil_check(env)
1586 self.is_temp = 1
1587 else:
1588 for arg in self.args:
1589 arg.analyse_types(env)
1590 if self.self and func_type.args:
1591 #print "SimpleCallNode: Inserting self into argument list" ###
1592 # Coerce 'self' to the type expected by the method.
1593 expected_type = func_type.args[0].type
1594 self.coerced_self = CloneNode(self.self).coerce_to(
1595 expected_type, env)
1596 # Insert coerced 'self' argument into argument list.
1597 self.args.insert(0, self.coerced_self)
1598 self.analyse_c_function_call(env)
1600 def function_type(self):
1601 # Return the type of the function being called, coercing a function
1602 # pointer to a function if necessary.
1603 func_type = self.function.type
1604 if func_type.is_ptr:
1605 func_type = func_type.base_type
1606 return func_type
1608 def analyse_c_function_call(self, env):
1609 func_type = self.function_type()
1610 # Check function type
1611 if not func_type.is_cfunction:
1612 if not func_type.is_error:
1613 error(self.pos, "Calling non-function type '%s'" %
1614 func_type)
1615 self.type = PyrexTypes.error_type
1616 #self.result_code = "<error>"
1617 return
1618 # Check no. of args
1619 expected_nargs = len(func_type.args)
1620 actual_nargs = len(self.args)
1621 if actual_nargs < expected_nargs \
1622 or (not func_type.has_varargs and actual_nargs > expected_nargs):
1623 expected_str = str(expected_nargs)
1624 if func_type.has_varargs:
1625 expected_str = "at least " + expected_str
1626 error(self.pos,
1627 "Call with wrong number of arguments (expected %s, got %s)"
1628 % (expected_str, actual_nargs))
1629 self.args = None
1630 self.type = PyrexTypes.error_type
1631 #self.result_code = "<error>"
1632 return
1633 # Coerce arguments
1634 for i in range(expected_nargs):
1635 formal_type = func_type.args[i].type
1636 self.args[i] = self.args[i].coerce_to(formal_type, env)
1637 for i in range(expected_nargs, actual_nargs):
1638 if self.args[i].type.is_pyobject:
1639 error(self.args[i].pos,
1640 "Python object cannot be passed as a varargs parameter")
1641 # Calc result type and code fragment
1642 self.type = func_type.return_type
1643 if self.type.is_pyobject \
1644 or func_type.exception_value is not None \
1645 or func_type.exception_check:
1646 self.is_temp = 1
1647 if self.type.is_pyobject:
1648 self.result_ctype = py_object_type
1649 # Check gil
1650 if not func_type.nogil:
1651 self.gil_check(env)
1653 def calculate_result_code(self):
1654 return self.c_call_code()
1656 def c_call_code(self):
1657 func_type = self.function_type()
1658 if self.args is None or not func_type.is_cfunction:
1659 return "<error>"
1660 formal_args = func_type.args
1661 arg_list_code = []
1662 for (formal_arg, actual_arg) in zip(formal_args, self.args):
1663 arg_code = actual_arg.result_as(formal_arg.type)
1664 arg_list_code.append(arg_code)
1665 for actual_arg in self.args[len(formal_args):]:
1666 arg_list_code.append(actual_arg.result())
1667 result = "%s(%s)" % (self.function.result(),
1668 join(arg_list_code, ","))
1669 return result
1671 def generate_result_code(self, code):
1672 func_type = self.function_type()
1673 result = self.result()
1674 if func_type.is_pyobject:
1675 if self.arg_tuple:
1676 arg_code = self.arg_tuple.py_result()
1677 else:
1678 arg_code = "0"
1679 code.putln(
1680 "%s = PyObject_CallObject(%s, %s); if (!%s) %s" % (
1681 result,
1682 self.function.py_result(),
1683 arg_code,
1684 result,
1685 code.error_goto(self.pos)))
1686 elif func_type.is_cfunction:
1687 exc_checks = []
1688 if self.type.is_pyobject:
1689 exc_checks.append("!%s" % result)
1690 else:
1691 exc_val = func_type.exception_value
1692 exc_check = func_type.exception_check
1693 if exc_val is not None:
1694 exc_checks.append("%s == %s" % (self.result(), exc_val))
1695 if exc_check:
1696 exc_checks.append("PyErr_Occurred()")
1697 if self.is_temp or exc_checks:
1698 rhs = self.c_call_code()
1699 result = self.result()
1700 if result:
1701 lhs = "%s = " % result
1702 if self.is_temp and self.type.is_pyobject:
1703 #return_type = self.type # func_type.return_type
1704 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1705 # "from", return_type, "to pyobject" ###
1706 rhs = typecast(py_object_type, self.type, rhs)
1707 else:
1708 lhs = ""
1709 code.putln(
1710 "%s%s; if (%s) %s" % (
1711 lhs,
1712 rhs,
1713 " && ".join(exc_checks),
1714 code.error_goto(self.pos)))
1717 class GeneralCallNode(CallNode):
1718 # General Python function call, including keyword,
1719 # * and ** arguments.
1721 # function ExprNode
1722 # positional_args ExprNode Tuple of positional arguments
1723 # keyword_args ExprNode or None Dict of keyword arguments
1724 # starstar_arg ExprNode or None Dict of extra keyword args
1726 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1728 def compile_time_value(self, denv):
1729 function = self.function.compile_time_value(denv)
1730 positional_args = self.positional_args.compile_time_value(denv)
1731 keyword_args = self.keyword_args.compile_time_value(denv)
1732 starstar_arg = self.starstar_arg.compile_time_value(denv)
1733 try:
1734 keyword_args.update(starstar_arg)
1735 return function(*positional_args, **keyword_args)
1736 except Exception, e:
1737 self.compile_time_value_error(e)
1739 def analyse_types(self, env):
1740 function = self.function
1741 function.analyse_types(env)
1742 self.positional_args.analyse_types(env)
1743 if self.keyword_args:
1744 self.keyword_args.analyse_types(env)
1745 if self.starstar_arg:
1746 self.starstar_arg.analyse_types(env)
1747 self.function = self.function.coerce_to_pyobject(env)
1748 self.positional_args = \
1749 self.positional_args.coerce_to_pyobject(env)
1750 if self.starstar_arg:
1751 self.starstar_arg = \
1752 self.starstar_arg.coerce_to_pyobject(env)
1753 if function.is_name and function.type_entry:
1754 # We are calling an extension type constructor
1755 self.type = function.type_entry.type
1756 self.result_ctype = py_object_type
1757 else:
1758 self.type = py_object_type
1759 self.gil_check(env)
1760 self.is_temp = 1
1762 def generate_result_code(self, code):
1763 if self.keyword_args and self.starstar_arg:
1764 code.putln(
1765 "if (PyDict_Update(%s, %s) < 0) %s" % (
1766 self.keyword_args.py_result(),
1767 self.starstar_arg.py_result(),
1768 code.error_goto(self.pos)))
1769 keyword_code = self.keyword_args.py_result()
1770 elif self.keyword_args:
1771 keyword_code = self.keyword_args.py_result()
1772 elif self.starstar_arg:
1773 keyword_code = self.starstar_arg.py_result()
1774 else:
1775 keyword_code = None
1776 if not keyword_code:
1777 call_code = "PyObject_CallObject(%s, %s)" % (
1778 self.function.py_result(),
1779 self.positional_args.py_result())
1780 else:
1781 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1782 self.function.py_result(),
1783 self.positional_args.py_result(),
1784 keyword_code)
1785 result = self.result()
1786 code.putln(
1787 "%s = %s; if (!%s) %s" % (
1788 result,
1789 call_code,
1790 result,
1791 code.error_goto(self.pos)))
1794 class AsTupleNode(ExprNode):
1795 # Convert argument to tuple. Used for normalising
1796 # the * argument of a function call.
1798 # arg ExprNode
1800 subexprs = ['arg']
1802 def compile_time_value(self, denv):
1803 arg = self.arg.compile_time_value(denv)
1804 try:
1805 return tuple(arg)
1806 except Exception, e:
1807 self.compile_time_value_error(e)
1809 def analyse_types(self, env):
1810 self.arg.analyse_types(env)
1811 self.arg = self.arg.coerce_to_pyobject(env)
1812 self.type = py_object_type
1813 self.gil_check(env)
1814 self.is_temp = 1
1816 gil_message = "Constructing Python tuple"
1818 def generate_result_code(self, code):
1819 result = self.result()
1820 code.putln(
1821 "%s = PySequence_Tuple(%s); if (!%s) %s" % (
1822 result,
1823 self.arg.py_result(),
1824 result,
1825 code.error_goto(self.pos)))
1828 class AttributeNode(ExprNode):
1829 # obj.attribute
1831 # obj ExprNode
1832 # attribute string
1834 # Used internally:
1836 # is_py_attr boolean Is a Python getattr operation
1837 # member string C name of struct member
1838 # is_called boolean Function call is being done on result
1839 # entry Entry Symbol table entry of attribute
1840 # interned_attr_cname string C name of interned attribute name
1842 is_attribute = 1
1843 subexprs = ['obj']
1845 type = PyrexTypes.error_type
1846 result_code = "<error>"
1847 entry = None
1848 is_called = 0
1850 def compile_time_value(self, denv):
1851 attr = self.attribute
1852 if attr.beginswith("__") and attr.endswith("__"):
1853 self.error("Invalid attribute name '%s' in compile-time expression"
1854 % attr)
1855 return None
1856 obj = self.arg.compile_time_value(denv)
1857 try:
1858 return getattr(obj, attr)
1859 except Exception, e:
1860 self.compile_time_value_error(e)
1862 def analyse_target_declaration(self, env):
1863 pass
1865 def analyse_target_types(self, env):
1866 self.analyse_types(env, target = 1)
1868 def analyse_types(self, env, target = 0):
1869 if self.analyse_as_cimported_attribute(env, target):
1870 return
1871 if not target and self.analyse_as_unbound_cmethod(env):
1872 return
1873 self.analyse_as_ordinary_attribute(env, target)
1875 def analyse_as_cimported_attribute(self, env, target):
1876 # Try to interpret this as a reference to an imported
1877 # C const, type, var or function. If successful, mutates
1878 # this node into a NameNode and returns 1, otherwise
1879 # returns 0.
1880 module_scope = self.obj.analyse_as_module(env)
1881 if module_scope:
1882 entry = module_scope.lookup_here(self.attribute)
1883 if entry and (
1884 entry.is_cglobal or entry.is_cfunction
1885 or entry.is_type or entry.is_const):
1886 self.mutate_into_name_node(env, entry, target)
1887 return 1
1888 return 0
1890 def analyse_as_unbound_cmethod(self, env):
1891 # Try to interpret this as a reference to an unbound
1892 # C method of an extension type. If successful, mutates
1893 # this node into a NameNode and returns 1, otherwise
1894 # returns 0.
1895 type = self.obj.analyse_as_extension_type(env)
1896 if type:
1897 entry = type.scope.lookup_here(self.attribute)
1898 if entry and entry.is_cmethod:
1899 # Create a temporary entry describing the C method
1900 # as an ordinary function.
1901 ubcm_entry = Symtab.Entry(entry.name,
1902 "%s->%s" % (type.vtabptr_cname, entry.cname),
1903 entry.type)
1904 ubcm_entry.is_cfunction = 1
1905 ubcm_entry.func_cname = entry.func_cname
1906 self.mutate_into_name_node(env, ubcm_entry, None)
1907 return 1
1908 return 0
1910 def analyse_as_extension_type(self, env):
1911 # Try to interpret this as a reference to an extension type
1912 # in a cimported module. Returns the extension type, or None.
1913 module_scope = self.obj.analyse_as_module(env)
1914 if module_scope:
1915 entry = module_scope.lookup_here(self.attribute)
1916 if entry and entry.is_type and entry.type.is_extension_type:
1917 return entry.type
1918 return None
1920 def analyse_as_module(self, env):
1921 # Try to interpret this as a reference to a cimported module
1922 # in another cimported module. Returns the module scope, or None.
1923 module_scope = self.obj.analyse_as_module(env)
1924 if module_scope:
1925 entry = module_scope.lookup_here(self.attribute)
1926 if entry and entry.as_module:
1927 return entry.as_module
1928 return None
1930 def mutate_into_name_node(self, env, entry, target):
1931 # Mutate this node into a NameNode and complete the
1932 # analyse_types phase.
1933 self.__class__ = NameNode
1934 self.name = self.attribute
1935 self.entry = entry
1936 del self.obj
1937 del self.attribute
1938 if target:
1939 NameNode.analyse_target_types(self, env)
1940 else:
1941 NameNode.analyse_rvalue_entry(self, env)
1943 def analyse_as_ordinary_attribute(self, env, target):
1944 self.obj.analyse_types(env)
1945 self.analyse_attribute(env)
1946 if self.entry and self.entry.is_cmethod and not self.is_called:
1947 error(self.pos, "C method can only be called")
1948 if self.is_py_attr:
1949 if not target:
1950 self.is_temp = 1
1951 self.result_ctype = py_object_type
1953 def analyse_attribute(self, env):
1954 # Look up attribute and set self.type and self.member.
1955 self.is_py_attr = 0
1956 self.member = self.attribute
1957 if self.obj.type.is_string:
1958 self.obj = self.obj.coerce_to_pyobject(env)
1959 obj_type = self.obj.type
1960 if obj_type.is_ptr:
1961 obj_type = obj_type.base_type
1962 self.op = "->"
1963 elif obj_type.is_extension_type:
1964 self.op = "->"
1965 else:
1966 self.op = "."
1967 if obj_type.has_attributes:
1968 entry = None
1969 if obj_type.attributes_known():
1970 entry = obj_type.scope.lookup_here(self.attribute)
1971 else:
1972 error(self.pos,
1973 "Cannot select attribute of incomplete type '%s'"
1974 % obj_type)
1975 obj_type = PyrexTypes.error_type
1976 self.entry = entry
1977 if entry:
1978 if obj_type.is_extension_type and entry.name == "__weakref__":
1979 error(self.pos, "Illegal use of special attribute __weakref__")
1980 if entry.is_variable or entry.is_cmethod:
1981 self.type = entry.type
1982 self.member = entry.cname
1983 return
1984 if entry.is_builtin_method and self.is_called:
1985 # Mutate into NameNode referring to C function
1986 #print "AttributeNode: Mutating builtin method into NameNode" ###
1987 self.type = entry.type
1988 self.__class__ = NameNode
1989 return
1990 else:
1991 # If it's not a variable or C method, it must be a Python
1992 # method of an extension type, so we treat it like a Python
1993 # attribute.
1994 pass
1995 # If we get here, the base object is not a struct/union/extension
1996 # type, or it is an extension type and the attribute is either not
1997 # declared or is declared as a Python method. Treat it as a Python
1998 # attribute reference.
1999 if obj_type.is_pyobject:
2000 self.type = py_object_type
2001 self.is_py_attr = 1
2002 #self.interned_attr_cname = env.intern(self.attribute)
2003 self.gil_check(env)
2004 else:
2005 if not obj_type.is_error:
2006 error(self.pos,
2007 "Object of type '%s' has no attribute '%s'" %
2008 (obj_type, self.attribute))
2010 gil_message = "Accessing Python attribute"
2012 def is_simple(self):
2013 if self.obj:
2014 return self.result_in_temp() or self.obj.is_simple()
2015 else:
2016 return NameNode.is_simple(self)
2018 def is_lvalue(self):
2019 if self.obj:
2020 return 1
2021 else:
2022 return NameNode.is_lvalue(self)
2024 def is_inplace_lvalue(self):
2025 return self.is_lvalue()
2027 def is_ephemeral(self):
2028 if self.obj:
2029 return self.obj.is_ephemeral()
2030 else:
2031 return NameNode.is_ephemeral(self)
2033 def calculate_result_code(self):
2034 obj = self.obj
2035 obj_code = obj.result_as(obj.type)
2036 if self.entry and self.entry.is_cmethod:
2037 return "((struct %s *)%s%s%s)->%s" % (
2038 obj.type.vtabstruct_cname, obj_code, self.op,
2039 obj.type.vtabslot_cname, self.member)
2040 else:
2041 return "%s%s%s" % (obj_code, self.op, self.member)
2043 def generate_result_code(self, code):
2044 if self.is_py_attr:
2045 result = self.result()
2046 cname = code.intern(self.attribute)
2047 code.putln(
2048 '%s = PyObject_GetAttr(%s, %s); if (!%s) %s' % (
2049 result,
2050 self.obj.py_result(),
2051 cname,
2052 result,
2053 code.error_goto(self.pos)))
2055 def generate_setattr_code(self, value_code, code):
2056 cname = code.intern(self.attribute)
2057 code.putln(
2058 'if (PyObject_SetAttr(%s, %s, %s) < 0) %s' % (
2059 self.obj.py_result(),
2060 cname,
2061 value_code,
2062 code.error_goto(self.pos)))
2064 def generate_assignment_code(self, rhs, code):
2065 self.obj.generate_evaluation_code(code)
2066 if self.is_py_attr:
2067 self.generate_setattr_code(rhs.py_result(), code)
2068 rhs.generate_disposal_code(code)
2069 else:
2070 select_code = self.result()
2071 if self.type.is_pyobject:
2072 rhs.make_owned_reference(code)
2073 code.put_decref(select_code, self.ctype())
2074 code.putln(
2075 "%s = %s;" % (
2076 select_code,
2077 rhs.result_as(self.ctype())))
2078 rhs.generate_post_assignment_code(code)
2079 self.obj.generate_disposal_code(code)
2081 def generate_inplace_assignment_code(self, operator, rhs, code):
2082 self.obj.generate_evaluation_code(code)
2083 select_code = self.result()
2084 if self.type.is_pyobject:
2085 self.generate_result_code(code)
2086 self.generate_inplace_operation_code(operator, rhs, code)
2087 if self.is_py_attr:
2088 self.generate_setattr_code(self.inplace_result, code)
2089 self.generate_inplace_result_disposal_code(code)
2090 else:
2091 code.put_decref(select_code, self.ctype())
2092 cast_inplace_result = typecast(self.ctype(), py_object_type, self.inplace_result)
2093 code.putln("%s = %s;" % (select_code, cast_inplace_result))
2094 else:
2095 code.putln("%s %s %s;" % (select_code, operator, rhs.result()))
2096 rhs.generate_disposal_code(code)
2097 self.obj.generate_disposal_code(code)
2099 def generate_deletion_code(self, code):
2100 self.obj.generate_evaluation_code(code)
2101 if self.is_py_attr:
2102 cname = code.intern(self.attribute)
2103 code.putln(
2104 'if (PyObject_DelAttr(%s, %s) < 0) %s' % (
2105 self.obj.py_result(),
2106 cname,
2107 code.error_goto(self.pos)))
2108 else:
2109 error(self.pos, "Cannot delete C attribute of extension type")
2110 self.obj.generate_disposal_code(code)
2112 #-------------------------------------------------------------------
2114 # Constructor nodes
2116 #-------------------------------------------------------------------
2118 class SequenceNode(ExprNode):
2119 # Base class for list and tuple constructor nodes.
2120 # Contains common code for performing sequence unpacking.
2122 # args [ExprNode]
2123 # iterator ExprNode
2124 # unpacked_items [ExprNode] or None
2125 # coerced_unpacked_items [ExprNode] or None
2127 subexprs = ['args']
2129 is_sequence_constructor = 1
2130 unpacked_items = None
2132 def compile_time_value_list(self, denv):
2133 return [arg.compile_time_value(denv) for arg in self.args]
2135 def analyse_target_declaration(self, env):
2136 for arg in self.args:
2137 arg.analyse_target_declaration(env)
2139 def analyse_types(self, env):
2140 for i in range(len(self.args)):
2141 arg = self.args[i]
2142 arg.analyse_types(env)
2143 self.args[i] = arg.coerce_to_pyobject(env)
2144 self.type = py_object_type
2145 self.gil_check(env)
2146 self.is_temp = 1
2148 def analyse_target_types(self, env):
2149 self.iterator = PyTempNode(self.pos, env)
2150 self.unpacked_items = []
2151 self.coerced_unpacked_items = []
2152 for arg in self.args:
2153 arg.analyse_target_types(env)
2154 unpacked_item = PyTempNode(self.pos, env)
2155 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2156 self.unpacked_items.append(unpacked_item)
2157 self.coerced_unpacked_items.append(coerced_unpacked_item)
2158 self.type = py_object_type
2159 # env.use_utility_code(unpacking_utility_code)
2161 def allocate_target_temps(self, env, rhs):
2162 self.iterator.allocate_temps(env)
2163 if rhs:
2164 rhs.release_temp(env)
2165 for arg, node in zip(self.args, self.coerced_unpacked_items):
2166 node.allocate_temps(env)
2167 arg.allocate_target_temps(env, node)
2168 #arg.release_target_temp(env)
2169 #node.release_temp(env)
2170 self.iterator.release_temp(env)
2172 # def release_target_temp(self, env):
2173 # #for arg in self.args:
2174 # # arg.release_target_temp(env)
2175 # #for node in self.coerced_unpacked_items:
2176 # # node.release_temp(env)
2177 # self.iterator.release_temp(env)
2179 def generate_result_code(self, code):
2180 self.generate_operation_code(code)
2182 def generate_assignment_code(self, rhs, code):
2183 iter_result = self.iterator.result()
2184 code.putln(
2185 "%s = PyObject_GetIter(%s); if (!%s) %s" % (
2186 iter_result,
2187 rhs.py_result(),
2188 iter_result,
2189 code.error_goto(self.pos)))
2190 rhs.generate_disposal_code(code)
2191 for i in range(len(self.args)):
2192 item = self.unpacked_items[i]
2193 code.use_utility_code(unpacking_utility_code)
2194 unpack_code = "__Pyx_UnpackItem(%s)" % (
2195 self.iterator.py_result())
2196 item_result = item.result()
2197 code.putln(
2198 "%s = %s; if (!%s) %s" % (
2199 item_result,
2200 typecast(item.ctype(), py_object_type, unpack_code),
2201 item_result,
2202 code.error_goto(self.pos)))
2203 value_node = self.coerced_unpacked_items[i]
2204 value_node.generate_evaluation_code(code)
2205 self.args[i].generate_assignment_code(value_node, code)
2206 code.putln(
2207 "if (__Pyx_EndUnpack(%s) < 0) %s" % (
2208 self.iterator.py_result(),
2209 code.error_goto(self.pos)))
2210 if debug_disposal_code:
2211 print "UnpackNode.generate_assignment_code:"
2212 print "...generating disposal code for", rhs
2213 self.iterator.generate_disposal_code(code)
2216 class TupleNode(SequenceNode):
2217 # Tuple constructor.
2219 gil_message = "Constructing Python tuple"
2221 def compile_time_value(self, denv):
2222 values = self.compile_time_value_list(denv)
2223 try:
2224 return tuple(values)
2225 except Exception, e:
2226 self.compile_time_value_error(e)
2228 def generate_operation_code(self, code):
2229 result = self.result()
2230 code.putln(
2231 "%s = PyTuple_New(%s); if (!%s) %s" % (
2232 result,
2233 len(self.args),
2234 result,
2235 code.error_goto(self.pos)))
2236 for i in range(len(self.args)):
2237 arg = self.args[i]
2238 arg_result = arg.py_result()
2239 # ??? Change this to use make_owned_reference?
2240 if not arg.result_in_temp():
2241 code.put_incref(arg_result)
2242 code.putln(
2243 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2244 result,
2245 i,
2246 arg_result))
2248 def generate_subexpr_disposal_code(self, code):
2249 # We call generate_post_assignment_code here instead
2250 # of generate_disposal_code, because values were stored
2251 # in the tuple using a reference-stealing operation.
2252 for arg in self.args:
2253 arg.generate_post_assignment_code(code)
2256 class ListNode(SequenceNode):
2257 # List constructor.
2259 gil_message = "Constructing Python list"
2261 def compile_time_value(self, denv):
2262 return self.compile_time_value_list(denv)
2264 def generate_operation_code(self, code):
2265 result = self.result()
2266 code.putln("%s = PyList_New(%s); if (!%s) %s" %
2267 (result,
2268 len(self.args),
2269 result,
2270 code.error_goto(self.pos)))
2271 for i in range(len(self.args)):
2272 arg = self.args[i]
2273 arg_result = arg.py_result()
2274 #if not arg.is_temp:
2275 if not arg.result_in_temp():
2276 code.put_incref(arg_result)
2277 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2278 (result,
2279 i,
2280 arg_result))
2282 def generate_subexpr_disposal_code(self, code):
2283 # We call generate_post_assignment_code here instead
2284 # of generate_disposal_code, because values were stored
2285 # in the list using a reference-stealing operation.
2286 for arg in self.args:
2287 arg.generate_post_assignment_code(code)
2290 class DictNode(ExprNode):
2291 # Dictionary constructor.
2293 # key_value_pairs [(ExprNode, ExprNode)]
2295 def compile_time_value(self, denv):
2296 pairs = [(key.compile_time_value(denv), value.compile_time_value(denv))
2297 for (key, value) in self.key_value_pairs]
2298 try:
2299 return dict(pairs)
2300 except Exception, e:
2301 self.compile_time_value_error(e)
2303 def analyse_types(self, env):
2304 new_pairs = []
2305 for key, value in self.key_value_pairs:
2306 key.analyse_types(env)
2307 value.analyse_types(env)
2308 key = key.coerce_to_pyobject(env)
2309 value = value.coerce_to_pyobject(env)
2310 new_pairs.append((key, value))
2311 self.key_value_pairs = new_pairs
2312 self.type = py_object_type
2313 self.gil_check(env)
2314 self.is_temp = 1
2316 gil_message = "Constructing Python dict"
2318 def allocate_temps(self, env, result = None):
2319 # Custom method used here because key-value
2320 # pairs are evaluated and used one at a time.
2321 self.allocate_temp(env, result)
2322 for key, value in self.key_value_pairs:
2323 key.allocate_temps(env)
2324 value.allocate_temps(env)
2325 key.release_temp(env)
2326 value.release_temp(env)
2328 def generate_evaluation_code(self, code):
2329 # Custom method used here because key-value
2330 # pairs are evaluated and used one at a time.
2331 result = self.result()
2332 code.putln(
2333 "%s = PyDict_New(); if (!%s) %s" % (
2334 result,
2335 result,
2336 code.error_goto(self.pos)))
2337 for key, value in self.key_value_pairs:
2338 key.generate_evaluation_code(code)
2339 value.generate_evaluation_code(code)
2340 code.putln(
2341 "if (PyDict_SetItem(%s, %s, %s) < 0) %s" % (
2342 result,
2343 key.py_result(),
2344 value.py_result(),
2345 code.error_goto(self.pos)))
2346 key.generate_disposal_code(code)
2347 value.generate_disposal_code(code)
2350 class ClassNode(ExprNode):
2351 # Helper class used in the implementation of Python
2352 # class definitions. Constructs a class object given
2353 # a name, tuple of bases and class dictionary.
2355 # name ExprNode Name of the class
2356 # bases ExprNode Base class tuple
2357 # dict ExprNode Class dict (not owned by this node)
2358 # doc ExprNode or None Doc string
2359 # module_name string Name of defining module
2361 subexprs = ['name', 'bases', 'doc']
2363 def analyse_types(self, env):
2364 self.name.analyse_types(env)
2365 self.name = self.name.coerce_to_pyobject(env)
2366 self.bases.analyse_types(env)
2367 if self.doc:
2368 self.doc.analyse_types(env)
2369 self.doc = self.doc.coerce_to_pyobject(env)
2370 self.module_name = env.global_scope().qualified_name
2371 self.type = py_object_type
2372 self.gil_check(env)
2373 self.is_temp = 1
2374 # env.use_utility_code(create_class_utility_code)
2376 gil_message = "Constructing Python class"
2378 def generate_result_code(self, code):
2379 result = self.result()
2380 if self.doc:
2381 code.putln(
2382 'if (PyDict_SetItemString(%s, "__doc__", %s) < 0) %s' % (
2383 self.dict.py_result(),
2384 self.doc.py_result(),
2385 code.error_goto(self.pos)))
2386 code.use_utility_code(create_class_utility_code)
2387 code.putln(
2388 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); if (!%s) %s' % (
2389 result,
2390 self.bases.py_result(),
2391 self.dict.py_result(),
2392 self.name.py_result(),
2393 self.module_name,
2394 result,
2395 code.error_goto(self.pos)))
2398 class UnboundMethodNode(ExprNode):
2399 # Helper class used in the implementation of Python
2400 # class definitions. Constructs an unbound method
2401 # object from a class and a function.
2403 # class_cname string C var holding the class object
2404 # function ExprNode Function object
2406 subexprs = ['function']
2408 def analyse_types(self, env):
2409 self.function.analyse_types(env)
2410 self.type = py_object_type
2411 self.gil_check(env)
2412 self.is_temp = 1
2414 gil_message = "Constructing an unbound method"
2416 def generate_result_code(self, code):
2417 result = self.result()
2418 code.putln(
2419 "%s = PyMethod_New(%s, 0, %s); if (!%s) %s" % (
2420 result,
2421 self.function.py_result(),
2422 self.class_cname,
2423 result,
2424 code.error_goto(self.pos)))
2427 class PyCFunctionNode(AtomicExprNode):
2428 # Helper class used in the implementation of Python
2429 # class definitions. Constructs a PyCFunction object
2430 # from a PyMethodDef struct.
2432 # pymethdef_cname string PyMethodDef structure
2434 def analyse_types(self, env):
2435 self.type = py_object_type
2436 self.gil_check(env)
2437 self.is_temp = 1
2439 gil_message = "Constructing Python function"
2441 def generate_result_code(self, code):
2442 result = self.result()
2443 code.putln(
2444 "%s = PyCFunction_New(&%s, 0); if (!%s) %s" % (
2445 result,
2446 self.pymethdef_cname,
2447 result,
2448 code.error_goto(self.pos)))
2450 #-------------------------------------------------------------------
2452 # Unary operator nodes
2454 #-------------------------------------------------------------------
2456 compile_time_unary_operators = {
2457 'not': operator.not_,
2458 '~': operator.inv,
2459 '-': operator.neg,
2460 '+': operator.pos,
2463 class UnopNode(ExprNode):
2464 # operator string
2465 # operand ExprNode
2467 # Processing during analyse_expressions phase:
2469 # analyse_c_operation
2470 # Called when the operand is not a pyobject.
2471 # - Check operand type and coerce if needed.
2472 # - Determine result type and result code fragment.
2473 # - Allocate temporary for result if needed.
2475 subexprs = ['operand']
2477 def compile_time_value(self, denv):
2478 func = compile_time_unary_operators.get(self.operator)
2479 if not func:
2480 error(self.pos,
2481 "Unary '%s' not supported in compile-time expression"
2482 % self.operator)
2483 operand = self.operand.compile_time_value(denv)
2484 try:
2485 return func(operand)
2486 except Exception, e:
2487 self.compile_time_value_error(e)
2489 def analyse_types(self, env):
2490 self.operand.analyse_types(env)
2491 if self.is_py_operation():
2492 self.coerce_operand_to_pyobject(env)
2493 self.type = py_object_type
2494 self.gil_check(env)
2495 self.is_temp = 1
2496 else:
2497 self.analyse_c_operation(env)
2499 def check_const(self):
2500 self.operand.check_const()
2502 def is_py_operation(self):
2503 return self.operand.type.is_pyobject
2505 def coerce_operand_to_pyobject(self, env):
2506 self.operand = self.operand.coerce_to_pyobject(env)
2508 def generate_result_code(self, code):
2509 if self.operand.type.is_pyobject:
2510 self.generate_py_operation_code(code)
2511 else:
2512 if self.is_temp:
2513 self.generate_c_operation_code(code)
2515 def generate_py_operation_code(self, code):
2516 function = self.py_operation_function()
2517 result = self.result()
2518 code.putln(
2519 "%s = %s(%s); if (!%s) %s" % (
2520 result,
2521 function,
2522 self.operand.py_result(),
2523 result,
2524 code.error_goto(self.pos)))
2526 def type_error(self):
2527 if not self.operand.type.is_error:
2528 error(self.pos, "Invalid operand type for '%s' (%s)" %
2529 (self.operator, self.operand.type))
2530 self.type = PyrexTypes.error_type
2533 class NotNode(ExprNode):
2534 # 'not' operator
2536 # operand ExprNode
2538 def compile_time_value(self, denv):
2539 operand = self.operand.compile_time_value(denv)
2540 try:
2541 return not operand
2542 except Exception, e:
2543 self.compile_time_value_error(e)
2545 subexprs = ['operand']
2547 def analyse_types(self, env):
2548 self.operand.analyse_types(env)
2549 self.operand = self.operand.coerce_to_boolean(env)
2550 self.type = PyrexTypes.c_int_type
2552 def calculate_result_code(self):
2553 return "(!%s)" % self.operand.result()
2555 def generate_result_code(self, code):
2556 pass
2559 class UnaryPlusNode(UnopNode):
2560 # unary '+' operator
2562 operator = '+'
2564 def analyse_c_operation(self, env):
2565 self.type = self.operand.type
2567 def py_operation_function(self):
2568 return "PyNumber_Positive"
2570 def calculate_result_code(self):
2571 return self.operand.result()
2574 class UnaryMinusNode(UnopNode):
2575 # unary '-' operator
2577 operator = '-'
2579 def analyse_c_operation(self, env):
2580 if self.operand.type.is_numeric:
2581 self.type = self.operand.type
2582 else:
2583 self.type_error()
2585 def py_operation_function(self):
2586 return "PyNumber_Negative"
2588 def calculate_result_code(self):
2589 return "(-%s)" % self.operand.result()
2592 class TildeNode(UnopNode):
2593 # unary '~' operator
2595 def analyse_c_operation(self, env):
2596 if self.operand.type.is_int:
2597 self.type = self.operand.type
2598 else:
2599 self.type_error()
2601 def py_operation_function(self):
2602 return "PyNumber_Invert"
2604 def calculate_result_code(self):
2605 return "(~%s)" % self.operand.result()
2608 class AmpersandNode(ExprNode):
2609 # The C address-of operator.
2611 # operand ExprNode
2613 subexprs = ['operand']
2615 def analyse_types(self, env):
2616 self.operand.analyse_types(env)
2617 argtype = self.operand.type
2618 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2619 self.error("Taking address of non-lvalue")
2620 return
2621 if argtype.is_pyobject:
2622 self.error("Cannot take address of Python variable")
2623 return
2624 self.type = PyrexTypes.c_ptr_type(argtype)
2626 def check_const(self):
2627 self.operand.check_const_addr()
2629 def error(self, mess):
2630 error(self.pos, mess)
2631 self.type = PyrexTypes.error_type
2632 self.result_code = "<error>"
2634 def calculate_result_code(self):
2635 return "(&%s)" % self.operand.result()
2637 def generate_result_code(self, code):
2638 pass
2641 unop_node_classes = {
2642 "+": UnaryPlusNode,
2643 "-": UnaryMinusNode,
2644 "~": TildeNode,
2647 def unop_node(pos, operator, operand):
2648 # Construct unnop node of appropriate class for
2649 # given operator.
2650 return unop_node_classes[operator](pos,
2651 operator = operator,
2652 operand = operand)
2655 class TypecastNode(ExprNode):
2656 # C type cast
2658 # base_type CBaseTypeNode
2659 # declarator CDeclaratorNode
2660 # operand ExprNode
2662 subexprs = ['operand']
2664 def analyse_types(self, env):
2665 base_type = self.base_type.analyse(env)
2666 _, self.type = self.declarator.analyse(base_type, env)
2667 if self.type.is_cfunction:
2668 error(self.pos,
2669 "Cannot cast to a function type")
2670 self.type = PyrexTypes.error_type
2671 self.operand.analyse_types(env)
2672 to_py = self.type.is_pyobject
2673 from_py = self.operand.type.is_pyobject
2674 if from_py and not to_py and self.operand.is_ephemeral():
2675 error(self.pos, "Casting temporary Python object to non-Python type")
2676 #if to_py and not from_py:
2677 # self.result_ctype = py_object_type
2678 # self.is_temp = 1
2680 def check_const(self):
2681 self.operand.check_const()
2683 def calculate_result_code(self):
2684 opnd = self.operand
2685 result_code = self.type.cast_code(opnd.result())
2686 return result_code
2688 def result_as(self, type):
2689 #if self.type.is_pyobject and not self.is_temp:
2690 if not self.is_temp:
2691 # Optimise away some unnecessary casting
2692 return self.operand.result_as(type)
2693 else:
2694 return ExprNode.result_as(self, type)
2696 def generate_result_code(self, code):
2697 if self.is_temp:
2698 code.putln(
2699 "%s = %s;" % (
2700 self.result(),
2701 self.operand.py_result()))
2702 code.put_incref(self.py_result())
2705 class SizeofNode(ExprNode):
2706 # Abstract base class for sizeof(x) expression nodes.
2708 def check_const(self):
2709 pass
2711 def generate_result_code(self, code):
2712 pass
2715 class SizeofTypeNode(SizeofNode):
2716 # C sizeof function applied to a type
2718 # base_type CBaseTypeNode
2719 # declarator CDeclaratorNode
2721 subexprs = []
2723 def analyse_types(self, env):
2724 base_type = self.base_type.analyse(env)
2725 _, arg_type = self.declarator.analyse(base_type, env)
2726 self.arg_type = arg_type
2727 if arg_type.is_pyobject:
2728 error(self.pos, "Cannot take sizeof Python object")
2729 elif arg_type.is_void:
2730 error(self.pos, "Cannot take sizeof void")
2731 elif not arg_type.is_complete():
2732 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2733 self.type = PyrexTypes.c_int_type
2735 def calculate_result_code(self):
2736 arg_code = self.arg_type.declaration_code("")
2737 return "(sizeof(%s))" % arg_code
2740 class SizeofVarNode(SizeofNode):
2741 # C sizeof function applied to a variable
2743 # operand ExprNode
2745 subexprs = ['operand']
2747 def analyse_types(self, env):
2748 self.operand.analyse_types(env)
2749 self.type = PyrexTypes.c_int_type
2751 def calculate_result_code(self):
2752 return "(sizeof(%s))" % self.operand.result()
2754 def generate_result_code(self, code):
2755 pass
2758 #-------------------------------------------------------------------
2760 # Binary operator nodes
2762 #-------------------------------------------------------------------
2764 compile_time_binary_operators = {
2765 '<': operator.lt,
2766 '<=': operator.le,
2767 '==': operator.eq,
2768 '!=': operator.ne,
2769 '>=': operator.ge,
2770 '>': operator.gt,
2771 'is': operator.is_,
2772 'is_not': operator.is_not,
2773 '+': operator.add,
2774 '&': operator.and_,
2775 '/': operator.div,
2776 '//': operator.floordiv,
2777 '<<': operator.lshift,
2778 '%': operator.mod,
2779 '*': operator.mul,
2780 '|': operator.or_,
2781 '**': operator.pow,
2782 '>>': operator.rshift,
2783 '-': operator.sub,
2784 #'/': operator.truediv,
2785 '^': operator.xor,
2786 'in': lambda x, y: x in y,
2787 'not_in': lambda x, y: x not in y,
2790 def get_compile_time_binop(node):
2791 func = compile_time_binary_operators.get(node.operator)
2792 if not func:
2793 error(node.pos,
2794 "Binary '%s' not supported in compile-time expression"
2795 % node.operator)
2796 return func
2798 class BinopNode(ExprNode):
2799 # operator string
2800 # operand1 ExprNode
2801 # operand2 ExprNode
2803 # Processing during analyse_expressions phase:
2805 # analyse_c_operation
2806 # Called when neither operand is a pyobject.
2807 # - Check operand types and coerce if needed.
2808 # - Determine result type and result code fragment.
2809 # - Allocate temporary for result if needed.
2811 subexprs = ['operand1', 'operand2']
2813 def compile_time_value(self, denv):
2814 func = get_compile_time_binop(self)
2815 operand1 = self.operand1.compile_time_value(denv)
2816 operand2 = self.operand2.compile_time_value(denv)
2817 try:
2818 return func(operand1, operand2)
2819 except Exception, e:
2820 self.compile_time_value_error(e)
2822 def analyse_types(self, env):
2823 self.operand1.analyse_types(env)
2824 self.operand2.analyse_types(env)
2825 if self.is_py_operation():
2826 self.coerce_operands_to_pyobjects(env)
2827 self.type = py_object_type
2828 self.gil_check(env)
2829 self.is_temp = 1
2830 else:
2831 self.analyse_c_operation(env)
2833 def is_py_operation(self):
2834 return (self.operand1.type.is_pyobject
2835 or self.operand2.type.is_pyobject)
2837 def coerce_operands_to_pyobjects(self, env):
2838 self.operand1 = self.operand1.coerce_to_pyobject(env)
2839 self.operand2 = self.operand2.coerce_to_pyobject(env)
2841 def check_const(self):
2842 self.operand1.check_const()
2843 self.operand2.check_const()
2845 def generate_result_code(self, code):
2846 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
2847 if self.operand1.type.is_pyobject:
2848 function = self.py_operation_function()
2849 if function == "PyNumber_Power":
2850 extra_args = ", Py_None"
2851 else:
2852 extra_args = ""
2853 result = self.result()
2854 code.putln(
2855 "%s = %s(%s, %s%s); if (!%s) %s" % (
2856 result,
2857 function,
2858 self.operand1.py_result(),
2859 self.operand2.py_result(),
2860 extra_args,
2861 result,
2862 code.error_goto(self.pos)))
2863 else:
2864 if self.is_temp:
2865 self.generate_c_operation_code(code)
2867 def type_error(self):
2868 if not (self.operand1.type.is_error
2869 or self.operand2.type.is_error):
2870 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
2871 (self.operator, self.operand1.type,
2872 self.operand2.type))
2873 self.type = PyrexTypes.error_type
2876 class NumBinopNode(BinopNode):
2877 # Binary operation taking numeric arguments.
2879 def analyse_c_operation(self, env):
2880 type1 = self.operand1.type
2881 type2 = self.operand2.type
2882 if self.operator == "**" and type1.is_int and type2.is_int:
2883 error(self.pos, "** with two C int types is ambiguous")
2884 self.type = error_type
2885 return
2886 self.type = self.compute_c_result_type(type1, type2)
2887 if not self.type:
2888 self.type_error()
2890 def compute_c_result_type(self, type1, type2):
2891 if self.c_types_okay(type1, type2):
2892 return PyrexTypes.widest_numeric_type(type1, type2)
2893 else:
2894 return None
2896 def c_types_okay(self, type1, type2):
2897 #print "NumBinopNode.c_types_okay:", type1, type2 ###
2898 return (type1.is_numeric or type1.is_enum) \
2899 and (type2.is_numeric or type2.is_enum)
2901 def calculate_result_code(self):
2902 return "(%s %s %s)" % (
2903 self.operand1.result(),
2904 self.operator,
2905 self.operand2.result())
2907 def py_operation_function(self):
2908 return self.py_functions[self.operator]
2910 py_functions = {
2911 "|": "PyNumber_Or",
2912 "^": "PyNumber_Xor",
2913 "&": "PyNumber_And",
2914 "<<": "PyNumber_Lshift",
2915 ">>": "PyNumber_Rshift",
2916 "+": "PyNumber_Add",
2917 "-": "PyNumber_Subtract",
2918 "*": "PyNumber_Multiply",
2919 "/": "PyNumber_Divide",
2920 "%": "PyNumber_Remainder",
2921 "**": "PyNumber_Power"
2925 class IntBinopNode(NumBinopNode):
2926 # Binary operation taking integer arguments.
2928 def c_types_okay(self, type1, type2):
2929 #print "IntBinopNode.c_types_okay:", type1, type2 ###
2930 return (type1.is_int or type1.is_enum) \
2931 and (type2.is_int or type2.is_enum)
2934 class AddNode(NumBinopNode):
2935 # '+' operator.
2937 def is_py_operation(self):
2938 if self.operand1.type.is_string \
2939 and self.operand2.type.is_string:
2940 return 1
2941 else:
2942 return NumBinopNode.is_py_operation(self)
2944 def compute_c_result_type(self, type1, type2):
2945 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
2946 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
2947 return type1
2948 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
2949 return type2
2950 else:
2951 return NumBinopNode.compute_c_result_type(
2952 self, type1, type2)
2955 class SubNode(NumBinopNode):
2956 # '-' operator.
2958 def compute_c_result_type(self, type1, type2):
2959 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
2960 return type1
2961 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
2962 return PyrexTypes.c_int_type
2963 else:
2964 return NumBinopNode.compute_c_result_type(
2965 self, type1, type2)
2968 class MulNode(NumBinopNode):
2969 # '*' operator.
2971 def is_py_operation(self):
2972 type1 = self.operand1.type
2973 type2 = self.operand2.type
2974 if (type1.is_string and type2.is_int) \
2975 or (type2.is_string and type1.is_int):
2976 return 1
2977 else:
2978 return NumBinopNode.is_py_operation(self)
2981 class ModNode(IntBinopNode):
2982 # '%' operator.
2984 def is_py_operation(self):
2985 return (self.operand1.type.is_string
2986 or self.operand2.type.is_string
2987 or IntBinopNode.is_py_operation(self))
2990 class PowNode(NumBinopNode):
2991 # '**' operator.
2993 def analyse_types(self, env):
2994 env.pow_function_used = 1
2995 NumBinopNode.analyse_types(self, env)
2997 def compute_c_result_type(self, type1, type2):
2998 if self.c_types_okay(type1, type2):
2999 return PyrexTypes.c_double_type
3000 else:
3001 return None
3003 def calculate_result_code(self):
3004 return "pow(%s, %s)" % (
3005 self.operand1.result(), self.operand2.result())
3008 class BoolBinopNode(ExprNode):
3009 # Short-circuiting boolean operation.
3011 # operator string
3012 # operand1 ExprNode
3013 # operand2 ExprNode
3014 # temp_bool ExprNode used internally
3016 temp_bool = None
3018 subexprs = ['operand1', 'operand2', 'temp_bool']
3020 def compile_time_value(self, denv):
3021 if self.operator == 'and':
3022 return self.operand1.compile_time_value(denv) \
3023 and self.operand2.compile_time_value(denv)
3024 else:
3025 return self.operand1.compile_time_value(denv) \
3026 or self.operand2.compile_time_value(denv)
3028 def analyse_types(self, env):
3029 self.operand1.analyse_types(env)
3030 self.operand2.analyse_types(env)
3031 if self.operand1.type.is_pyobject or \
3032 self.operand2.type.is_pyobject:
3033 self.operand1 = self.operand1.coerce_to_pyobject(env)
3034 self.operand2 = self.operand2.coerce_to_pyobject(env)
3035 self.temp_bool = TempNode(self.pos,
3036 PyrexTypes.c_int_type, env)
3037 self.type = py_object_type
3038 self.gil_check(env)
3039 else:
3040 self.operand1 = self.operand1.coerce_to_boolean(env)
3041 self.operand2 = self.operand2.coerce_to_boolean(env)
3042 self.type = PyrexTypes.c_int_type
3043 # For what we're about to do, it's vital that
3044 # both operands be temp nodes.
3045 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3046 self.operand2 = self.operand2.coerce_to_temp(env)
3047 self.is_temp = 1
3049 gil_message = "Truth-testing Python object"
3051 def allocate_temps(self, env, result_code = None):
3052 # We don't need both operands at the same time, and
3053 # one of the operands will also be our result. So we
3054 # use an allocation strategy here which results in
3055 # this node and both its operands sharing the same
3056 # result variable. This allows us to avoid some
3057 # assignments and increfs/decrefs that would otherwise
3058 # be necessary.
3059 self.allocate_temp(env, result_code)
3060 self.operand1.allocate_temps(env, self.result_code)
3061 if self.temp_bool:
3062 self.temp_bool.allocate_temp(env)
3063 self.temp_bool.release_temp(env)
3064 self.operand2.allocate_temps(env, self.result_code)
3065 # We haven't called release_temp on either operand,
3066 # because although they are temp nodes, they don't own
3067 # their result variable. And because they are temp
3068 # nodes, any temps in their subnodes will have been
3069 # released before their allocate_temps returned.
3070 # Therefore, they contain no temp vars that need to
3071 # be released.
3073 def check_const(self):
3074 self.operand1.check_const()
3075 self.operand2.check_const()
3077 def calculate_result_code(self):
3078 return "(%s %s %s)" % (
3079 self.operand1.result(),
3080 self.py_to_c_op[self.operator],
3081 self.operand2.result())
3083 py_to_c_op = {'and': "&&", 'or': "||"}
3085 def generate_evaluation_code(self, code):
3086 self.operand1.generate_evaluation_code(code)
3087 test_result = self.generate_operand1_test(code)
3088 if self.operator == 'and':
3089 sense = ""
3090 else:
3091 sense = "!"
3092 code.putln(
3093 "if (%s%s) {" % (
3094 sense,
3095 test_result))
3096 self.operand1.generate_disposal_code(code)
3097 self.operand2.generate_evaluation_code(code)
3098 code.putln(
3099 "}")
3101 def generate_operand1_test(self, code):
3102 # Generate code to test the truth of the first operand.
3103 if self.type.is_pyobject:
3104 test_result = self.temp_bool.result()
3105 code.putln(
3106 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
3107 test_result,
3108 self.operand1.py_result(),
3109 test_result,
3110 code.error_goto(self.pos)))
3111 else:
3112 test_result = self.operand1.result()
3113 return test_result
3116 class CmpNode:
3117 # Mixin class containing code common to PrimaryCmpNodes
3118 # and CascadedCmpNodes.
3120 def cascaded_compile_time_value(self, operand1, denv):
3121 func = get_compile_time_binop(self)
3122 operand2 = self.operand2.compile_time_value(denv)
3123 try:
3124 result = func(operand1, operand2)
3125 except Exception, e:
3126 self.compile_time_value_error(e)
3127 result = None
3128 if result:
3129 cascade = self.cascade
3130 if cascade:
3131 result = result and cascade.compile_time_value(operand2, denv)
3132 return result
3134 def is_python_comparison(self):
3135 return (self.has_python_operands()
3136 or (self.cascade and self.cascade.is_python_comparison())
3137 or self.operator in ('in', 'not_in'))
3139 def check_types(self, env, operand1, op, operand2):
3140 if not self.types_okay(operand1, op, operand2):
3141 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3142 (self.operator, operand1.type, operand2.type))
3144 def types_okay(self, operand1, op, operand2):
3145 type1 = operand1.type
3146 type2 = operand2.type
3147 if type1.is_error or type2.is_error:
3148 return 1
3149 if type1.is_pyobject: # type2 will be, too
3150 return 1
3151 elif type1.is_ptr or type1.is_array:
3152 return type1.is_null_ptr or type2.is_null_ptr \
3153 or ((type2.is_ptr or type2.is_array)
3154 and type1.base_type.same_as(type2.base_type))
3155 elif ((type1.is_numeric and type2.is_numeric
3156 or type1.is_enum and (type2.is_int or type1.same_as(type2))
3157 or type1.is_int and type2.is_enum)
3158 and op not in ('is', 'is_not')):
3159 return 1
3160 else:
3161 return 0
3163 def generate_operation_code(self, code, result,
3164 operand1, op , operand2):
3165 if op == 'in' or op == 'not_in':
3166 code.putln(
3167 "%s = PySequence_Contains(%s, %s); if (%s < 0) %s" % (
3168 result,
3169 operand2.py_result(),
3170 operand1.py_result(),
3171 result,
3172 code.error_goto(self.pos)))
3173 if op == 'not_in':
3174 code.putln(
3175 "%s = !%s;" % (
3176 result, result))
3177 elif (operand1.type.is_pyobject
3178 and op not in ('is', 'is_not')):
3179 code.putln(
3180 "if (PyObject_Cmp(%s, %s, &%s) < 0) %s" % (
3181 operand1.py_result(),
3182 operand2.py_result(),
3183 result,
3184 code.error_goto(self.pos)))
3185 code.putln(
3186 "%s = %s %s 0;" % (
3187 result, result, op))
3188 else:
3189 type1 = operand1.type
3190 type2 = operand2.type
3191 if (type1.is_extension_type or type2.is_extension_type) \
3192 and not operand1.ctype().same_as(operand2.ctype()):
3193 code1 = operand1.result_as(py_object_type)
3194 code2 = operand2.result_as(py_object_type)
3195 else:
3196 code1 = operand1.result()
3197 code2 = operand2.result()
3198 code.putln("%s = %s %s %s;" % (
3199 result,
3200 code1,
3201 self.c_operator(op),
3202 code2))
3204 def c_operator(self, op):
3205 if op == 'is':
3206 return "=="
3207 elif op == 'is_not':
3208 return "!="
3209 else:
3210 return op
3213 class PrimaryCmpNode(ExprNode, CmpNode):
3214 # Non-cascaded comparison or first comparison of
3215 # a cascaded sequence.
3217 # operator string
3218 # operand1 ExprNode
3219 # operand2 ExprNode
3220 # cascade CascadedCmpNode
3222 # We don't use the subexprs mechanism, because
3223 # things here are too complicated for it to handle.
3224 # Instead, we override all the framework methods
3225 # which use it.
3227 cascade = None
3229 def compile_time_value(self, denv):
3230 operand1 = self.operand1.compile_time_value(denv)
3231 return self.cascaded_compile_time_value(operand1, denv)
3233 def analyse_types(self, env):
3234 self.operand1.analyse_types(env)
3235 self.operand2.analyse_types(env)
3236 if self.cascade:
3237 self.cascade.analyse_types(env, self.operand2)
3238 self.is_pycmp = self.is_python_comparison()
3239 if self.is_pycmp:
3240 self.coerce_operands_to_pyobjects(env)
3241 if self.cascade:
3242 self.operand2 = self.operand2.coerce_to_simple(env)
3243 self.cascade.coerce_cascaded_operands_to_temp(env)
3244 self.check_operand_types(env)
3245 self.type = PyrexTypes.c_int_type
3246 if self.is_pycmp or self.cascade:
3247 self.is_temp = 1
3249 def check_operand_types(self, env):
3250 self.check_types(env,
3251 self.operand1, self.operator, self.operand2)
3252 if self.cascade:
3253 self.cascade.check_operand_types(env, self.operand2)
3255 def has_python_operands(self):
3256 return (self.operand1.type.is_pyobject
3257 or self.operand2.type.is_pyobject)
3259 def coerce_operands_to_pyobjects(self, env):
3260 self.operand1 = self.operand1.coerce_to_pyobject(env)
3261 self.operand2 = self.operand2.coerce_to_pyobject(env)
3262 if self.cascade:
3263 self.cascade.coerce_operands_to_pyobjects(env)
3265 def allocate_subexpr_temps(self, env):
3266 self.operand1.allocate_temps(env)
3267 self.operand2.allocate_temps(env)
3268 if self.cascade:
3269 self.cascade.allocate_subexpr_temps(env)
3271 def release_subexpr_temps(self, env):
3272 self.operand1.release_temp(env)
3273 self.operand2.release_temp(env)
3274 if self.cascade:
3275 self.cascade.release_subexpr_temps(env)
3277 def check_const(self):
3278 self.operand1.check_const()
3279 self.operand2.check_const()
3280 if self.cascade:
3281 self.not_const()
3283 def calculate_result_code(self):
3284 return "(%s %s %s)" % (
3285 self.operand1.result(),
3286 self.c_operator(self.operator),
3287 self.operand2.result())
3289 def generate_evaluation_code(self, code):
3290 self.operand1.generate_evaluation_code(code)
3291 self.operand2.generate_evaluation_code(code)
3292 if self.is_temp:
3293 result = self.result()
3294 self.generate_operation_code(code, result,
3295 self.operand1, self.operator, self.operand2)
3296 if self.cascade:
3297 self.cascade.generate_evaluation_code(code,
3298 result, self.operand2)
3299 self.operand1.generate_disposal_code(code)
3300 self.operand2.generate_disposal_code(code)
3302 def generate_subexpr_disposal_code(self, code):
3303 # If this is called, it is a non-cascaded cmp,
3304 # so only need to dispose of the two main operands.
3305 self.operand1.generate_disposal_code(code)
3306 self.operand2.generate_disposal_code(code)
3309 class CascadedCmpNode(Node, CmpNode):
3310 # A CascadedCmpNode is not a complete expression node. It
3311 # hangs off the side of another comparison node, shares
3312 # its left operand with that node, and shares its result
3313 # with the PrimaryCmpNode at the head of the chain.
3315 # operator string
3316 # operand2 ExprNode
3317 # cascade CascadedCmpNode
3319 cascade = None
3321 def analyse_types(self, env, operand1):
3322 self.operand2.analyse_types(env)
3323 if self.cascade:
3324 self.cascade.analyse_types(env, self.operand2)
3326 def check_operand_types(self, env, operand1):
3327 self.check_types(env,
3328 operand1, self.operator, self.operand2)
3329 if self.cascade:
3330 self.cascade.check_operand_types(env, self.operand2)
3332 def has_python_operands(self):
3333 return self.operand2.type.is_pyobject
3335 def coerce_operands_to_pyobjects(self, env):
3336 self.operand2 = self.operand2.coerce_to_pyobject(env)
3337 if self.cascade:
3338 self.cascade.coerce_operands_to_pyobjects(env)
3340 def coerce_cascaded_operands_to_temp(self, env):
3341 if self.cascade:
3342 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3343 self.operand2 = self.operand2.coerce_to_simple(env)
3344 self.cascade.coerce_cascaded_operands_to_temp(env)
3346 def allocate_subexpr_temps(self, env):
3347 self.operand2.allocate_temps(env)
3348 if self.cascade:
3349 self.cascade.allocate_subexpr_temps(env)
3351 def release_subexpr_temps(self, env):
3352 self.operand2.release_temp(env)
3353 if self.cascade:
3354 self.cascade.release_subexpr_temps(env)
3356 def generate_evaluation_code(self, code, result, operand1):
3357 code.putln("if (%s) {" % result)
3358 self.operand2.generate_evaluation_code(code)
3359 self.generate_operation_code(code, result,
3360 operand1, self.operator, self.operand2)
3361 if self.cascade:
3362 self.cascade.generate_evaluation_code(
3363 code, result, self.operand2)
3364 # Cascaded cmp result is always temp
3365 self.operand2.generate_disposal_code(code)
3366 code.putln("}")
3369 binop_node_classes = {
3370 "or": BoolBinopNode,
3371 "and": BoolBinopNode,
3372 "|": IntBinopNode,
3373 "^": IntBinopNode,
3374 "&": IntBinopNode,
3375 "<<": IntBinopNode,
3376 ">>": IntBinopNode,
3377 "+": AddNode,
3378 "-": SubNode,
3379 "*": MulNode,
3380 "/": NumBinopNode,
3381 "%": ModNode,
3382 "**": PowNode
3385 def binop_node(pos, operator, operand1, operand2):
3386 # Construct binop node of appropriate class for
3387 # given operator.
3388 return binop_node_classes[operator](pos,
3389 operator = operator,
3390 operand1 = operand1,
3391 operand2 = operand2)
3393 #-------------------------------------------------------------------
3395 # Coercion nodes
3397 # Coercion nodes are special in that they are created during
3398 # the analyse_types phase of parse tree processing.
3399 # Their __init__ methods consequently incorporate some aspects
3400 # of that phase.
3402 #-------------------------------------------------------------------
3404 class CoercionNode(ExprNode):
3405 # Abstract base class for coercion nodes.
3407 # arg ExprNode node being coerced
3409 subexprs = ['arg']
3411 def __init__(self, arg):
3412 self.pos = arg.pos
3413 self.arg = arg
3414 if debug_coercion:
3415 print self, "Coercing", self.arg
3418 class CastNode(CoercionNode):
3419 # Wrap a node in a C type cast.
3421 def __init__(self, arg, new_type):
3422 CoercionNode.__init__(self, arg)
3423 self.type = new_type
3425 def calculate_result_code(self):
3426 return self.arg.result_as(self.type)
3428 def generate_result_code(self, code):
3429 self.arg.generate_result_code(code)
3432 class PyTypeTestNode(CoercionNode):
3433 # This node is used to check that a generic Python
3434 # object is an instance of a particular extension type.
3435 # This node borrows the result of its argument node.
3437 def __init__(self, arg, dst_type, env):
3438 # The arg is know to be a Python object, and
3439 # the dst_type is known to be an extension type.
3440 assert dst_type.is_extension_type, "PyTypeTest on non extension type"
3441 CoercionNode.__init__(self, arg)
3442 self.type = dst_type
3443 self.result_ctype = arg.ctype()
3444 # env.use_utility_code(type_test_utility_code)
3445 self.gil_check(env)
3447 gil_message = "Python type test"
3449 def result_in_temp(self):
3450 return self.arg.result_in_temp()
3452 def is_ephemeral(self):
3453 return self.arg.is_ephemeral()
3455 def calculate_result_code(self):
3456 return self.arg.result()
3458 def generate_result_code(self, code):
3459 if self.type.typeobj_is_available():
3460 code.use_utility_code(type_test_utility_code)
3461 code.putln(
3462 "if (!__Pyx_TypeTest(%s, %s)) %s" % (
3463 self.arg.py_result(),
3464 self.type.typeptr_cname,
3465 code.error_goto(self.pos)))
3466 else:
3467 error(self.pos, "Cannot test type of extern C class "
3468 "without type object name specification")
3470 def generate_post_assignment_code(self, code):
3471 self.arg.generate_post_assignment_code(code)
3474 class CoerceToPyTypeNode(CoercionNode):
3475 # This node is used to convert a C data type
3476 # to a Python object.
3478 def __init__(self, arg, env):
3479 CoercionNode.__init__(self, arg)
3480 self.type = py_object_type
3481 self.gil_check(env)
3482 self.is_temp = 1
3483 if not arg.type.to_py_function:
3484 error(arg.pos,
3485 "Cannot convert '%s' to Python object" % arg.type)
3487 gil_message = "Converting to Python object"
3489 def generate_result_code(self, code):
3490 function = self.arg.type.to_py_function
3491 result = self.result()
3492 code.putln('%s = %s(%s); if (!%s) %s' % (
3493 result,
3494 function,
3495 self.arg.result(),
3496 result,
3497 code.error_goto(self.pos)))
3500 class CoerceFromPyTypeNode(CoercionNode):
3501 # This node is used to convert a Python object
3502 # to a C data type.
3504 def __init__(self, result_type, arg, env):
3505 CoercionNode.__init__(self, arg)
3506 self.type = result_type
3507 self.is_temp = 1
3508 if not result_type.from_py_function:
3509 error(arg.pos,
3510 "Cannot convert Python object to '%s'" % result_type)
3511 if self.type.is_string and self.arg.is_ephemeral():
3512 error(arg.pos,
3513 "Obtaining char * from temporary Python value")
3515 def generate_result_code(self, code):
3516 function = self.type.from_py_function
3517 operand = self.arg.py_result()
3518 rhs = "%s(%s)" % (function, operand)
3519 if self.type.is_enum:
3520 rhs = typecast(self.type, c_long_type, rhs)
3521 result = self.result()
3522 if self.type.is_string:
3523 err_code = "!%s" % result
3524 else:
3525 err_code = "PyErr_Occurred()"
3526 code.putln('%s = %s; if (%s) %s' % (
3527 result,
3528 rhs,
3529 err_code,
3530 code.error_goto(self.pos)))
3533 class CoerceToBooleanNode(CoercionNode):
3534 # This node is used when a result needs to be used
3535 # in a boolean context.
3537 def __init__(self, arg, env):
3538 CoercionNode.__init__(self, arg)
3539 self.type = PyrexTypes.c_int_type
3540 if arg.type.is_pyobject:
3541 if env.nogil:
3542 self.gil_error()
3543 self.is_temp = 1
3545 gil_message = "Truth-testing Python object"
3547 def check_const(self):
3548 if self.is_temp:
3549 self.not_const()
3550 self.arg.check_const()
3552 def calculate_result_code(self):
3553 return "(%s != 0)" % self.arg.result()
3555 def generate_result_code(self, code):
3556 if self.arg.type.is_pyobject:
3557 result = self.result()
3558 code.putln(
3559 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
3560 result,
3561 self.arg.py_result(),
3562 result,
3563 code.error_goto(self.pos)))
3566 class CoerceToTempNode(CoercionNode):
3567 # This node is used to force the result of another node
3568 # to be stored in a temporary. It is only used if the
3569 # argument node's result is not already in a temporary.
3571 def __init__(self, arg, env):
3572 CoercionNode.__init__(self, arg)
3573 self.type = self.arg.type
3574 self.is_temp = 1
3575 if self.type.is_pyobject:
3576 self.gil_check(env)
3577 self.result_ctype = py_object_type
3579 gil_message = "Creating temporary Python reference"
3582 def generate_result_code(self, code):
3583 #self.arg.generate_evaluation_code(code) # Already done
3584 # by generic generate_subexpr_evaluation_code!
3585 code.putln("%s = %s;" % (
3586 self.result(), self.arg.result_as(self.ctype())))
3587 if self.type.is_pyobject:
3588 code.put_incref(self.py_result())
3591 class CloneNode(CoercionNode):
3592 # This node is employed when the result of another node needs
3593 # to be used multiple times. The argument node's result must
3594 # be in a temporary. This node "borrows" the result from the
3595 # argument node, and does not generate any evaluation or
3596 # disposal code for it. The original owner of the argument
3597 # node is responsible for doing those things.
3599 subexprs = [] # Arg is not considered a subexpr
3601 def __init__(self, arg):
3602 CoercionNode.__init__(self, arg)
3603 self.type = arg.type
3604 self.result_ctype = arg.result_ctype
3606 def calculate_result_code(self):
3607 return self.arg.result()
3609 def generate_evaluation_code(self, code):
3610 pass
3612 def generate_result_code(self, code):
3613 pass
3615 #------------------------------------------------------------------------------------
3617 # Runtime support code
3619 #------------------------------------------------------------------------------------
3621 get_name_utility_code = [
3622 """
3623 static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/
3624 ""","""
3625 static PyObject *__Pyx_GetName(PyObject *dict, char *name) {
3626 PyObject *result;
3627 result = PyObject_GetAttrString(dict, name);
3628 if (!result)
3629 PyErr_SetString(PyExc_NameError, name);
3630 return result;
3632 """]
3634 get_name_interned_utility_code = [
3635 """
3636 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
3637 ""","""
3638 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
3639 PyObject *result;
3640 result = PyObject_GetAttr(dict, name);
3641 if (!result)
3642 PyErr_SetObject(PyExc_NameError, name);
3643 return result;
3645 """]
3647 #------------------------------------------------------------------------------------
3649 import_utility_code = [
3650 """
3651 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
3652 ""","""
3653 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
3654 PyObject *__import__ = 0;
3655 PyObject *empty_list = 0;
3656 PyObject *module = 0;
3657 PyObject *global_dict = 0;
3658 PyObject *empty_dict = 0;
3659 PyObject *list;
3660 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
3661 if (!__import__)
3662 goto bad;
3663 if (from_list)
3664 list = from_list;
3665 else {
3666 empty_list = PyList_New(0);
3667 if (!empty_list)
3668 goto bad;
3669 list = empty_list;
3671 global_dict = PyModule_GetDict(%(GLOBALS)s);
3672 if (!global_dict)
3673 goto bad;
3674 empty_dict = PyDict_New();
3675 if (!empty_dict)
3676 goto bad;
3677 module = PyObject_CallFunction(__import__, "OOOO",
3678 name, global_dict, empty_dict, list);
3679 bad:
3680 Py_XDECREF(empty_list);
3681 Py_XDECREF(__import__);
3682 Py_XDECREF(empty_dict);
3683 return module;
3685 """ % {
3686 "BUILTINS": Naming.builtins_cname,
3687 "GLOBALS": Naming.module_cname,
3688 }]
3690 #------------------------------------------------------------------------------------
3692 #get_exception_utility_code = [
3693 #"""
3694 #static PyObject *__Pyx_GetExcValue(void); /*proto*/
3695 #""","""
3696 #static PyObject *__Pyx_GetExcValue(void) {
3697 # PyObject *type = 0, *value = 0, *tb = 0;
3698 # PyObject *result = 0;
3699 # PyThreadState *tstate = PyThreadState_Get();
3700 # PyErr_Fetch(&type, &value, &tb);
3701 # PyErr_NormalizeException(&type, &value, &tb);
3702 # if (PyErr_Occurred())
3703 # goto bad;
3704 # if (!value) {
3705 # value = Py_None;
3706 # Py_INCREF(value);
3707 # }
3708 # Py_XDECREF(tstate->exc_type);
3709 # Py_XDECREF(tstate->exc_value);
3710 # Py_XDECREF(tstate->exc_traceback);
3711 # tstate->exc_type = type;
3712 # tstate->exc_value = value;
3713 # tstate->exc_traceback = tb;
3714 # result = value;
3715 # Py_XINCREF(result);
3716 # type = 0;
3717 # value = 0;
3718 # tb = 0;
3719 #bad:
3720 # Py_XDECREF(type);
3721 # Py_XDECREF(value);
3722 # Py_XDECREF(tb);
3723 # return result;
3724 #}
3725 #"""]
3727 #------------------------------------------------------------------------------------
3729 unpacking_utility_code = [
3730 """
3731 static PyObject *__Pyx_UnpackItem(PyObject *); /*proto*/
3732 static int __Pyx_EndUnpack(PyObject *); /*proto*/
3733 ""","""
3734 static void __Pyx_UnpackError(void) {
3735 PyErr_SetString(PyExc_ValueError, "unpack sequence of wrong size");
3738 static PyObject *__Pyx_UnpackItem(PyObject *iter) {
3739 PyObject *item;
3740 if (!(item = PyIter_Next(iter))) {
3741 if (!PyErr_Occurred())
3742 __Pyx_UnpackError();
3744 return item;
3747 static int __Pyx_EndUnpack(PyObject *iter) {
3748 PyObject *item;
3749 if ((item = PyIter_Next(iter))) {
3750 Py_DECREF(item);
3751 __Pyx_UnpackError();
3752 return -1;
3754 else if (!PyErr_Occurred())
3755 return 0;
3756 else
3757 return -1;
3759 """]
3761 #------------------------------------------------------------------------------------
3763 type_test_utility_code = [
3764 """
3765 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
3766 ""","""
3767 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
3768 if (!type) {
3769 PyErr_Format(PyExc_SystemError, "Missing type object");
3770 return 0;
3772 if (obj == Py_None || PyObject_TypeCheck(obj, type))
3773 return 1;
3774 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
3775 obj->ob_type->tp_name, type->tp_name);
3776 return 0;
3778 """]
3780 #------------------------------------------------------------------------------------
3782 create_class_utility_code = [
3783 """
3784 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
3785 ""","""
3786 static PyObject *__Pyx_CreateClass(
3787 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
3789 PyObject *py_modname;
3790 PyObject *result = 0;
3792 py_modname = PyString_FromString(modname);
3793 if (!py_modname)
3794 goto bad;
3795 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
3796 goto bad;
3797 result = PyClass_New(bases, dict, name);
3798 bad:
3799 Py_XDECREF(py_modname);
3800 return result;
3802 """]
3804 #------------------------------------------------------------------------------------
3806 getitem_int_utility_code = [
3807 """
3808 static PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i); /*proto*/
3809 ""","""
3810 static PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i) {
3811 PyTypeObject *t = o->ob_type;
3812 PyObject *r;
3813 if (t->tp_as_sequence && t->tp_as_sequence->sq_item)
3814 r = PySequence_GetItem(o, i);
3815 else {
3816 PyObject *j = PyInt_FromLong(i);
3817 if (!j)
3818 return 0;
3819 r = PyObject_GetItem(o, j);
3820 Py_DECREF(j);
3822 return r;
3824 """]
3826 #------------------------------------------------------------------------------------
3828 setitem_int_utility_code = [
3829 """
3830 static int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v); /*proto*/
3831 ""","""
3832 static int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v) {
3833 PyTypeObject *t = o->ob_type;
3834 int r;
3835 if (t->tp_as_sequence && t->tp_as_sequence->sq_item)
3836 r = PySequence_SetItem(o, i, v);
3837 else {
3838 PyObject *j = PyInt_FromLong(i);
3839 if (!j)
3840 return -1;
3841 r = PyObject_SetItem(o, j, v);
3842 Py_DECREF(j);
3844 return r;
3846 """]