Cython has moved to github.

pyrex

view Pyrex/Compiler/ExprNodes.py @ 104:955ec491fcfc

Fix hex compile-time constants
author Gregory Ewing <greg.ewing@canterbury.ac.nz>
date Wed Aug 27 19:05:46 2008 +1200 (3 years ago)
parents ac76d2c45aa1
children 58d1294b169e
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, 0)
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 itype = self.index.type
1260 if not (itype.is_int and itype.signed):
1261 self.index = self.index.coerce_to_pyobject(env)
1262 self.type = py_object_type
1263 self.gil_check(env)
1264 self.is_temp = 1
1265 else:
1266 if self.base.type.is_ptr or self.base.type.is_array:
1267 self.type = self.base.type.base_type
1268 else:
1269 error(self.pos,
1270 "Attempting to index non-array type '%s'" %
1271 self.base.type)
1272 self.type = PyrexTypes.error_type
1273 if self.index.type.is_pyobject:
1274 self.index = self.index.coerce_to(
1275 PyrexTypes.c_py_ssize_t_type, env)
1276 if not self.index.type.is_int:
1277 error(self.pos,
1278 "Invalid index type '%s'" %
1279 self.index.type)
1281 gil_message = "Indexing Python object"
1283 def check_const_addr(self):
1284 self.base.check_const_addr()
1285 self.index.check_const()
1287 def is_lvalue(self):
1288 return 1
1290 def is_inplace_lvalue(self):
1291 return 1
1293 def calculate_result_code(self):
1294 return "(%s[%s])" % (
1295 self.base.result(), self.index.result())
1297 def generate_result_code(self, code):
1298 if self.type.is_pyobject:
1299 itype = self.index.type
1300 if itype.is_int and itype.signed:
1301 code.use_utility_code(getitem_int_utility_code)
1302 function = "__Pyx_GetItemInt"
1303 index_code = self.index.result()
1304 else:
1305 function = "PyObject_GetItem"
1306 index_code = self.index.py_result()
1307 result = self.result()
1308 code.putln(
1309 "%s = %s(%s, %s); if (!%s) %s" % (
1310 result,
1311 function,
1312 self.base.py_result(),
1313 index_code,
1314 result,
1315 code.error_goto(self.pos)))
1317 def generate_setitem_code(self, value_code, code):
1318 itype = self.index.type
1319 if itype.is_int and itype.signed:
1320 code.use_utility_code(setitem_int_utility_code)
1321 function = "__Pyx_SetItemInt"
1322 index_code = self.index.result()
1323 else:
1324 function = "PyObject_SetItem"
1325 index_code = self.index.py_result()
1326 code.putln(
1327 "if (%s(%s, %s, %s) < 0) %s" % (
1328 function,
1329 self.base.py_result(),
1330 index_code,
1331 value_code,
1332 code.error_goto(self.pos)))
1334 def generate_assignment_code(self, rhs, code):
1335 self.generate_subexpr_evaluation_code(code)
1336 if self.type.is_pyobject:
1337 self.generate_setitem_code(rhs.py_result(), code)
1338 else:
1339 code.putln(
1340 "%s = %s;" % (
1341 self.result(), rhs.result()))
1342 self.generate_subexpr_disposal_code(code)
1343 rhs.generate_disposal_code(code)
1345 def generate_inplace_assignment_code(self, operator, rhs, code):
1346 self.generate_subexpr_evaluation_code(code)
1347 if self.type.is_pyobject:
1348 self.generate_result_code(code)
1349 self.generate_inplace_operation_code(operator, rhs, code)
1350 self.generate_setitem_code(self.inplace_result, code)
1351 self.generate_inplace_result_disposal_code(code)
1352 else:
1353 code.putln("%s %s %s;" % (self.result(), operator, rhs.result()))
1354 rhs.generate_disposal_code(code)
1355 self.generate_subexpr_disposal_code(code)
1357 def generate_deletion_code(self, code):
1358 self.generate_subexpr_evaluation_code(code)
1359 #if self.type.is_pyobject:
1360 if self.index.type.is_int:
1361 function = "PySequence_DelItem"
1362 index_code = self.index.result()
1363 else:
1364 function = "PyObject_DelItem"
1365 index_code = self.index.py_result()
1366 code.putln(
1367 "if (%s(%s, %s) < 0) %s" % (
1368 function,
1369 self.base.py_result(),
1370 index_code,
1371 code.error_goto(self.pos)))
1372 #else:
1373 # error(self.pos, "Cannot delete non-Python variable")
1374 self.generate_subexpr_disposal_code(code)
1377 class SliceIndexNode(ExprNode):
1378 # 2-element slice indexing
1380 # base ExprNode
1381 # start ExprNode or None
1382 # stop ExprNode or None
1384 subexprs = ['base', 'start', 'stop']
1386 def is_inplace_lvalue(self):
1387 return 1
1389 def compile_time_value(self, denv):
1390 base = self.base.compile_time_value(denv)
1391 start = self.start.compile_time_value(denv)
1392 stop = self.stop.compile_time_value(denv)
1393 try:
1394 return base[start:stop]
1395 except Exception, e:
1396 self.compile_time_value_error(e)
1398 def analyse_target_declaration(self, env):
1399 pass
1401 def analyse_types(self, env):
1402 self.base.analyse_types(env)
1403 if self.start:
1404 self.start.analyse_types(env)
1405 if self.stop:
1406 self.stop.analyse_types(env)
1407 self.base = self.base.coerce_to_pyobject(env)
1408 c_int = PyrexTypes.c_py_ssize_t_type
1409 if self.start:
1410 self.start = self.start.coerce_to(c_int, env)
1411 if self.stop:
1412 self.stop = self.stop.coerce_to(c_int, env)
1413 self.type = py_object_type
1414 self.gil_check(env)
1415 self.is_temp = 1
1417 gil_message = "Slicing Python object"
1419 def generate_result_code(self, code):
1420 result = self.result()
1421 code.putln(
1422 "%s = PySequence_GetSlice(%s, %s, %s); if (!%s) %s" % (
1423 result,
1424 self.base.py_result(),
1425 self.start_code(),
1426 self.stop_code(),
1427 result,
1428 code.error_goto(self.pos)))
1430 def generate_setslice_code(self, value_code, code):
1431 code.putln(
1432 "if (PySequence_SetSlice(%s, %s, %s, %s) < 0) %s" % (
1433 self.base.py_result(),
1434 self.start_code(),
1435 self.stop_code(),
1436 value_code,
1437 code.error_goto(self.pos)))
1439 def generate_assignment_code(self, rhs, code):
1440 self.generate_subexpr_evaluation_code(code)
1441 self.generate_setslice_code(rhs.result(), code)
1442 self.generate_subexpr_disposal_code(code)
1443 rhs.generate_disposal_code(code)
1445 def generate_inplace_assignment_code(self, operator, rhs, code):
1446 self.generate_subexpr_evaluation_code(code)
1447 self.generate_result_code(code)
1448 self.generate_inplace_operation_code(operator, rhs, code)
1449 self.generate_setslice_code(self.inplace_result, code)
1450 self.generate_inplace_result_disposal_code(code)
1451 self.generate_subexpr_disposal_code(code)
1453 def generate_deletion_code(self, code):
1454 self.generate_subexpr_evaluation_code(code)
1455 code.putln(
1456 "if (PySequence_DelSlice(%s, %s, %s) < 0) %s" % (
1457 self.base.py_result(),
1458 self.start_code(),
1459 self.stop_code(),
1460 code.error_goto(self.pos)))
1461 self.generate_subexpr_disposal_code(code)
1463 def start_code(self):
1464 if self.start:
1465 return self.start.result()
1466 else:
1467 return "0"
1469 def stop_code(self):
1470 if self.stop:
1471 return self.stop.result()
1472 else:
1473 return "PY_SSIZE_T_MAX"
1475 # def calculate_result_code(self):
1476 # # self.result_code is not used, but this method must exist
1477 # return "<unused>"
1480 class SliceNode(ExprNode):
1481 # start:stop:step in subscript list
1483 # start ExprNode
1484 # stop ExprNode
1485 # step ExprNode
1487 def compile_time_value(self, denv):
1488 start = self.start.compile_time_value(denv)
1489 stop = self.stop.compile_time_value(denv)
1490 step = step.step.compile_time_value(denv)
1491 try:
1492 return slice(start, stop, step)
1493 except Exception, e:
1494 self.compile_time_value_error(e)
1496 subexprs = ['start', 'stop', 'step']
1498 def analyse_types(self, env):
1499 self.start.analyse_types(env)
1500 self.stop.analyse_types(env)
1501 self.step.analyse_types(env)
1502 self.start = self.start.coerce_to_pyobject(env)
1503 self.stop = self.stop.coerce_to_pyobject(env)
1504 self.step = self.step.coerce_to_pyobject(env)
1505 self.type = py_object_type
1506 self.gil_check(env)
1507 self.is_temp = 1
1509 gil_message = "Constructing Python slice object"
1511 def generate_result_code(self, code):
1512 result = self.result()
1513 code.putln(
1514 "%s = PySlice_New(%s, %s, %s); if (!%s) %s" % (
1515 result,
1516 self.start.py_result(),
1517 self.stop.py_result(),
1518 self.step.py_result(),
1519 result,
1520 code.error_goto(self.pos)))
1523 class CallNode(ExprNode):
1525 def gil_check(self, env):
1526 # Make sure we're not in a nogil environment
1527 if env.nogil:
1528 error(self.pos, "Calling gil-requiring function without gil")
1531 class SimpleCallNode(CallNode):
1532 # Function call without keyword, * or ** args.
1534 # function ExprNode
1535 # args [ExprNode]
1536 # arg_tuple ExprNode or None used internally
1537 # self ExprNode or None used internally
1538 # coerced_self ExprNode or None used internally
1540 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1542 self = None
1543 coerced_self = None
1544 arg_tuple = None
1546 def compile_time_value(self, denv):
1547 function = self.function.compile_time_value(denv)
1548 args = [arg.compile_time_value(denv) for arg in self.args]
1549 try:
1550 return function(*args)
1551 except Exception, e:
1552 self.compile_time_value_error(e)
1554 def analyse_types(self, env):
1555 #print "SimpleCallNode.analyse_types:", self.pos ###
1556 function = self.function
1557 function.is_called = 1
1558 function.analyse_types(env)
1559 if function.is_name or function.is_attribute:
1560 func_entry = function.entry
1561 if func_entry:
1562 if func_entry.is_cmethod or func_entry.is_builtin_method:
1563 # Take ownership of the object from which the attribute
1564 # was obtained, because we need to pass it as 'self'.
1565 #print "SimpleCallNode: Snarfing self argument" ###
1566 self.self = function.obj
1567 function.obj = CloneNode(self.self)
1568 func_type = self.function_type()
1569 if func_type.is_pyobject:
1570 if self.args:
1571 self.arg_tuple = TupleNode(self.pos, args = self.args)
1572 self.arg_tuple.analyse_types(env)
1573 else:
1574 self.arg_tuple = None
1575 self.args = None
1576 if function.is_name and function.type_entry:
1577 # We are calling an extension type constructor
1578 self.type = function.type_entry.type
1579 self.result_ctype = py_object_type
1580 else:
1581 self.type = py_object_type
1582 self.gil_check(env)
1583 self.is_temp = 1
1584 else:
1585 for arg in self.args:
1586 arg.analyse_types(env)
1587 if self.self and func_type.args:
1588 #print "SimpleCallNode: Inserting self into argument list" ###
1589 # Coerce 'self' to the type expected by the method.
1590 expected_type = func_type.args[0].type
1591 self.coerced_self = CloneNode(self.self).coerce_to(
1592 expected_type, env)
1593 # Insert coerced 'self' argument into argument list.
1594 self.args.insert(0, self.coerced_self)
1595 self.analyse_c_function_call(env)
1597 def function_type(self):
1598 # Return the type of the function being called, coercing a function
1599 # pointer to a function if necessary.
1600 func_type = self.function.type
1601 if func_type.is_ptr:
1602 func_type = func_type.base_type
1603 return func_type
1605 def analyse_c_function_call(self, env):
1606 func_type = self.function_type()
1607 # Check function type
1608 if not func_type.is_cfunction:
1609 if not func_type.is_error:
1610 error(self.pos, "Calling non-function type '%s'" %
1611 func_type)
1612 self.type = PyrexTypes.error_type
1613 #self.result_code = "<error>"
1614 return
1615 # Check no. of args
1616 expected_nargs = len(func_type.args)
1617 actual_nargs = len(self.args)
1618 if actual_nargs < expected_nargs \
1619 or (not func_type.has_varargs and actual_nargs > expected_nargs):
1620 expected_str = str(expected_nargs)
1621 if func_type.has_varargs:
1622 expected_str = "at least " + expected_str
1623 error(self.pos,
1624 "Call with wrong number of arguments (expected %s, got %s)"
1625 % (expected_str, actual_nargs))
1626 self.args = None
1627 self.type = PyrexTypes.error_type
1628 #self.result_code = "<error>"
1629 return
1630 # Coerce arguments
1631 for i in range(expected_nargs):
1632 formal_type = func_type.args[i].type
1633 self.args[i] = self.args[i].coerce_to(formal_type, env)
1634 for i in range(expected_nargs, actual_nargs):
1635 if self.args[i].type.is_pyobject:
1636 error(self.args[i].pos,
1637 "Python object cannot be passed as a varargs parameter")
1638 # Calc result type and code fragment
1639 self.type = func_type.return_type
1640 if self.type.is_pyobject \
1641 or func_type.exception_value is not None \
1642 or func_type.exception_check:
1643 self.is_temp = 1
1644 if self.type.is_pyobject:
1645 self.result_ctype = py_object_type
1646 # Check gil
1647 if not func_type.nogil:
1648 self.gil_check(env)
1650 def calculate_result_code(self):
1651 return self.c_call_code()
1653 def c_call_code(self):
1654 func_type = self.function_type()
1655 if self.args is None or not func_type.is_cfunction:
1656 return "<error>"
1657 formal_args = func_type.args
1658 arg_list_code = []
1659 for (formal_arg, actual_arg) in zip(formal_args, self.args):
1660 arg_code = actual_arg.result_as(formal_arg.type)
1661 arg_list_code.append(arg_code)
1662 for actual_arg in self.args[len(formal_args):]:
1663 arg_list_code.append(actual_arg.result())
1664 result = "%s(%s)" % (self.function.result(),
1665 join(arg_list_code, ","))
1666 return result
1668 def generate_result_code(self, code):
1669 func_type = self.function_type()
1670 result = self.result()
1671 if func_type.is_pyobject:
1672 if self.arg_tuple:
1673 arg_code = self.arg_tuple.py_result()
1674 else:
1675 arg_code = "0"
1676 code.putln(
1677 "%s = PyObject_CallObject(%s, %s); if (!%s) %s" % (
1678 result,
1679 self.function.py_result(),
1680 arg_code,
1681 result,
1682 code.error_goto(self.pos)))
1683 elif func_type.is_cfunction:
1684 exc_checks = []
1685 if self.type.is_pyobject:
1686 exc_checks.append("!%s" % result)
1687 else:
1688 exc_val = func_type.exception_value
1689 exc_check = func_type.exception_check
1690 if exc_val is not None:
1691 exc_checks.append("%s == %s" % (self.result(), exc_val))
1692 if exc_check:
1693 exc_checks.append("PyErr_Occurred()")
1694 if self.is_temp or exc_checks:
1695 rhs = self.c_call_code()
1696 result = self.result()
1697 if result:
1698 lhs = "%s = " % result
1699 if self.is_temp and self.type.is_pyobject:
1700 #return_type = self.type # func_type.return_type
1701 #print "SimpleCallNode.generate_result_code: casting", rhs, \
1702 # "from", return_type, "to pyobject" ###
1703 rhs = typecast(py_object_type, self.type, rhs)
1704 else:
1705 lhs = ""
1706 code.putln(
1707 "%s%s; if (%s) %s" % (
1708 lhs,
1709 rhs,
1710 " && ".join(exc_checks),
1711 code.error_goto(self.pos)))
1714 class GeneralCallNode(CallNode):
1715 # General Python function call, including keyword,
1716 # * and ** arguments.
1718 # function ExprNode
1719 # positional_args ExprNode Tuple of positional arguments
1720 # keyword_args ExprNode or None Dict of keyword arguments
1721 # starstar_arg ExprNode or None Dict of extra keyword args
1723 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
1725 def compile_time_value(self, denv):
1726 function = self.function.compile_time_value(denv)
1727 positional_args = self.positional_args.compile_time_value(denv)
1728 keyword_args = self.keyword_args.compile_time_value(denv)
1729 starstar_arg = self.starstar_arg.compile_time_value(denv)
1730 try:
1731 keyword_args.update(starstar_arg)
1732 return function(*positional_args, **keyword_args)
1733 except Exception, e:
1734 self.compile_time_value_error(e)
1736 def analyse_types(self, env):
1737 function = self.function
1738 function.analyse_types(env)
1739 self.positional_args.analyse_types(env)
1740 if self.keyword_args:
1741 self.keyword_args.analyse_types(env)
1742 if self.starstar_arg:
1743 self.starstar_arg.analyse_types(env)
1744 self.function = self.function.coerce_to_pyobject(env)
1745 self.positional_args = \
1746 self.positional_args.coerce_to_pyobject(env)
1747 if self.starstar_arg:
1748 self.starstar_arg = \
1749 self.starstar_arg.coerce_to_pyobject(env)
1750 if function.is_name and function.type_entry:
1751 # We are calling an extension type constructor
1752 self.type = function.type_entry.type
1753 self.result_ctype = py_object_type
1754 else:
1755 self.type = py_object_type
1756 self.gil_check(env)
1757 self.is_temp = 1
1759 def generate_result_code(self, code):
1760 if self.keyword_args and self.starstar_arg:
1761 code.putln(
1762 "if (PyDict_Update(%s, %s) < 0) %s" % (
1763 self.keyword_args.py_result(),
1764 self.starstar_arg.py_result(),
1765 code.error_goto(self.pos)))
1766 keyword_code = self.keyword_args.py_result()
1767 elif self.keyword_args:
1768 keyword_code = self.keyword_args.py_result()
1769 elif self.starstar_arg:
1770 keyword_code = self.starstar_arg.py_result()
1771 else:
1772 keyword_code = None
1773 if not keyword_code:
1774 call_code = "PyObject_CallObject(%s, %s)" % (
1775 self.function.py_result(),
1776 self.positional_args.py_result())
1777 else:
1778 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
1779 self.function.py_result(),
1780 self.positional_args.py_result(),
1781 keyword_code)
1782 result = self.result()
1783 code.putln(
1784 "%s = %s; if (!%s) %s" % (
1785 result,
1786 call_code,
1787 result,
1788 code.error_goto(self.pos)))
1791 class AsTupleNode(ExprNode):
1792 # Convert argument to tuple. Used for normalising
1793 # the * argument of a function call.
1795 # arg ExprNode
1797 subexprs = ['arg']
1799 def compile_time_value(self, denv):
1800 arg = self.arg.compile_time_value(denv)
1801 try:
1802 return tuple(arg)
1803 except Exception, e:
1804 self.compile_time_value_error(e)
1806 def analyse_types(self, env):
1807 self.arg.analyse_types(env)
1808 self.arg = self.arg.coerce_to_pyobject(env)
1809 self.type = py_object_type
1810 self.gil_check(env)
1811 self.is_temp = 1
1813 gil_message = "Constructing Python tuple"
1815 def generate_result_code(self, code):
1816 result = self.result()
1817 code.putln(
1818 "%s = PySequence_Tuple(%s); if (!%s) %s" % (
1819 result,
1820 self.arg.py_result(),
1821 result,
1822 code.error_goto(self.pos)))
1825 class AttributeNode(ExprNode):
1826 # obj.attribute
1828 # obj ExprNode
1829 # attribute string
1831 # Used internally:
1833 # is_py_attr boolean Is a Python getattr operation
1834 # member string C name of struct member
1835 # is_called boolean Function call is being done on result
1836 # entry Entry Symbol table entry of attribute
1837 # interned_attr_cname string C name of interned attribute name
1839 is_attribute = 1
1840 subexprs = ['obj']
1842 type = PyrexTypes.error_type
1843 result_code = "<error>"
1844 entry = None
1845 is_called = 0
1847 def compile_time_value(self, denv):
1848 attr = self.attribute
1849 if attr.beginswith("__") and attr.endswith("__"):
1850 self.error("Invalid attribute name '%s' in compile-time expression"
1851 % attr)
1852 return None
1853 obj = self.arg.compile_time_value(denv)
1854 try:
1855 return getattr(obj, attr)
1856 except Exception, e:
1857 self.compile_time_value_error(e)
1859 def analyse_target_declaration(self, env):
1860 pass
1862 def analyse_target_types(self, env):
1863 self.analyse_types(env, target = 1)
1865 def analyse_types(self, env, target = 0):
1866 if self.analyse_as_cimported_attribute(env, target):
1867 return
1868 if not target and self.analyse_as_unbound_cmethod(env):
1869 return
1870 self.analyse_as_ordinary_attribute(env, target)
1872 def analyse_as_cimported_attribute(self, env, target):
1873 # Try to interpret this as a reference to an imported
1874 # C const, type, var or function. If successful, mutates
1875 # this node into a NameNode and returns 1, otherwise
1876 # returns 0.
1877 module_scope = self.obj.analyse_as_module(env)
1878 if module_scope:
1879 entry = module_scope.lookup_here(self.attribute)
1880 if entry and (
1881 entry.is_cglobal or entry.is_cfunction
1882 or entry.is_type or entry.is_const):
1883 self.mutate_into_name_node(env, entry, target)
1884 return 1
1885 return 0
1887 def analyse_as_unbound_cmethod(self, env):
1888 # Try to interpret this as a reference to an unbound
1889 # C method of an extension type. If successful, mutates
1890 # this node into a NameNode and returns 1, otherwise
1891 # returns 0.
1892 type = self.obj.analyse_as_extension_type(env)
1893 if type:
1894 entry = type.scope.lookup_here(self.attribute)
1895 if entry and entry.is_cmethod:
1896 # Create a temporary entry describing the C method
1897 # as an ordinary function.
1898 ubcm_entry = Symtab.Entry(entry.name,
1899 "%s->%s" % (type.vtabptr_cname, entry.cname),
1900 entry.type)
1901 ubcm_entry.is_cfunction = 1
1902 ubcm_entry.func_cname = entry.func_cname
1903 self.mutate_into_name_node(env, ubcm_entry, None)
1904 return 1
1905 return 0
1907 def analyse_as_extension_type(self, env):
1908 # Try to interpret this as a reference to an extension type
1909 # in a cimported module. Returns the extension type, or None.
1910 module_scope = self.obj.analyse_as_module(env)
1911 if module_scope:
1912 entry = module_scope.lookup_here(self.attribute)
1913 if entry and entry.is_type and entry.type.is_extension_type:
1914 return entry.type
1915 return None
1917 def analyse_as_module(self, env):
1918 # Try to interpret this as a reference to a cimported module
1919 # in another cimported module. Returns the module scope, or None.
1920 module_scope = self.obj.analyse_as_module(env)
1921 if module_scope:
1922 entry = module_scope.lookup_here(self.attribute)
1923 if entry and entry.as_module:
1924 return entry.as_module
1925 return None
1927 def mutate_into_name_node(self, env, entry, target):
1928 # Mutate this node into a NameNode and complete the
1929 # analyse_types phase.
1930 self.__class__ = NameNode
1931 self.name = self.attribute
1932 self.entry = entry
1933 del self.obj
1934 del self.attribute
1935 if target:
1936 NameNode.analyse_target_types(self, env)
1937 else:
1938 NameNode.analyse_rvalue_entry(self, env)
1940 def analyse_as_ordinary_attribute(self, env, target):
1941 self.obj.analyse_types(env)
1942 self.analyse_attribute(env)
1943 if self.entry and self.entry.is_cmethod and not self.is_called:
1944 error(self.pos, "C method can only be called")
1945 if self.is_py_attr:
1946 if not target:
1947 self.is_temp = 1
1948 self.result_ctype = py_object_type
1950 def analyse_attribute(self, env):
1951 # Look up attribute and set self.type and self.member.
1952 self.is_py_attr = 0
1953 self.member = self.attribute
1954 if self.obj.type.is_string:
1955 self.obj = self.obj.coerce_to_pyobject(env)
1956 obj_type = self.obj.type
1957 if obj_type.is_ptr:
1958 obj_type = obj_type.base_type
1959 self.op = "->"
1960 elif obj_type.is_extension_type:
1961 self.op = "->"
1962 else:
1963 self.op = "."
1964 if obj_type.has_attributes:
1965 entry = None
1966 if obj_type.attributes_known():
1967 entry = obj_type.scope.lookup_here(self.attribute)
1968 else:
1969 error(self.pos,
1970 "Cannot select attribute of incomplete type '%s'"
1971 % obj_type)
1972 obj_type = PyrexTypes.error_type
1973 self.entry = entry
1974 if entry:
1975 if obj_type.is_extension_type and entry.name == "__weakref__":
1976 error(self.pos, "Illegal use of special attribute __weakref__")
1977 if entry.is_variable or entry.is_cmethod:
1978 self.type = entry.type
1979 self.member = entry.cname
1980 return
1981 if entry.is_builtin_method and self.is_called:
1982 # Mutate into NameNode referring to C function
1983 #print "AttributeNode: Mutating builtin method into NameNode" ###
1984 self.type = entry.type
1985 self.__class__ = NameNode
1986 return
1987 else:
1988 # If it's not a variable or C method, it must be a Python
1989 # method of an extension type, so we treat it like a Python
1990 # attribute.
1991 pass
1992 # If we get here, the base object is not a struct/union/extension
1993 # type, or it is an extension type and the attribute is either not
1994 # declared or is declared as a Python method. Treat it as a Python
1995 # attribute reference.
1996 if obj_type.is_pyobject:
1997 self.type = py_object_type
1998 self.is_py_attr = 1
1999 #self.interned_attr_cname = env.intern(self.attribute)
2000 self.gil_check(env)
2001 else:
2002 if not obj_type.is_error:
2003 error(self.pos,
2004 "Object of type '%s' has no attribute '%s'" %
2005 (obj_type, self.attribute))
2007 gil_message = "Accessing Python attribute"
2009 def is_simple(self):
2010 if self.obj:
2011 return self.result_in_temp() or self.obj.is_simple()
2012 else:
2013 return NameNode.is_simple(self)
2015 def is_lvalue(self):
2016 if self.obj:
2017 return 1
2018 else:
2019 return NameNode.is_lvalue(self)
2021 def is_inplace_lvalue(self):
2022 return self.is_lvalue()
2024 def is_ephemeral(self):
2025 if self.obj:
2026 return self.obj.is_ephemeral()
2027 else:
2028 return NameNode.is_ephemeral(self)
2030 def calculate_result_code(self):
2031 obj = self.obj
2032 obj_code = obj.result_as(obj.type)
2033 if self.entry and self.entry.is_cmethod:
2034 return "((struct %s *)%s%s%s)->%s" % (
2035 obj.type.vtabstruct_cname, obj_code, self.op,
2036 obj.type.vtabslot_cname, self.member)
2037 else:
2038 return "%s%s%s" % (obj_code, self.op, self.member)
2040 def generate_result_code(self, code):
2041 if self.is_py_attr:
2042 result = self.result()
2043 cname = code.intern(self.attribute)
2044 code.putln(
2045 '%s = PyObject_GetAttr(%s, %s); if (!%s) %s' % (
2046 result,
2047 self.obj.py_result(),
2048 cname,
2049 result,
2050 code.error_goto(self.pos)))
2052 def generate_setattr_code(self, value_code, code):
2053 cname = code.intern(self.attribute)
2054 code.putln(
2055 'if (PyObject_SetAttr(%s, %s, %s) < 0) %s' % (
2056 self.obj.py_result(),
2057 cname,
2058 value_code,
2059 code.error_goto(self.pos)))
2061 def generate_assignment_code(self, rhs, code):
2062 self.obj.generate_evaluation_code(code)
2063 if self.is_py_attr:
2064 self.generate_setattr_code(rhs.py_result(), code)
2065 rhs.generate_disposal_code(code)
2066 else:
2067 select_code = self.result()
2068 if self.type.is_pyobject:
2069 rhs.make_owned_reference(code)
2070 code.put_decref(select_code, self.ctype())
2071 code.putln(
2072 "%s = %s;" % (
2073 select_code,
2074 rhs.result_as(self.ctype())))
2075 rhs.generate_post_assignment_code(code)
2076 self.obj.generate_disposal_code(code)
2078 def generate_inplace_assignment_code(self, operator, rhs, code):
2079 self.obj.generate_evaluation_code(code)
2080 select_code = self.result()
2081 if self.type.is_pyobject:
2082 self.generate_result_code(code)
2083 self.generate_inplace_operation_code(operator, rhs, code)
2084 if self.is_py_attr:
2085 self.generate_setattr_code(self.inplace_result, code)
2086 self.generate_inplace_result_disposal_code(code)
2087 else:
2088 code.put_decref(select_code, self.ctype())
2089 cast_inplace_result = typecast(self.ctype(), py_object_type, self.inplace_result)
2090 code.putln("%s = %s;" % (select_code, cast_inplace_result))
2091 else:
2092 code.putln("%s %s %s;" % (select_code, operator, rhs.result()))
2093 rhs.generate_disposal_code(code)
2094 self.obj.generate_disposal_code(code)
2096 def generate_deletion_code(self, code):
2097 self.obj.generate_evaluation_code(code)
2098 if self.is_py_attr:
2099 cname = code.intern(self.attribute)
2100 code.putln(
2101 'if (PyObject_DelAttr(%s, %s) < 0) %s' % (
2102 self.obj.py_result(),
2103 cname,
2104 code.error_goto(self.pos)))
2105 else:
2106 error(self.pos, "Cannot delete C attribute of extension type")
2107 self.obj.generate_disposal_code(code)
2109 #-------------------------------------------------------------------
2111 # Constructor nodes
2113 #-------------------------------------------------------------------
2115 class SequenceNode(ExprNode):
2116 # Base class for list and tuple constructor nodes.
2117 # Contains common code for performing sequence unpacking.
2119 # args [ExprNode]
2120 # iterator ExprNode
2121 # unpacked_items [ExprNode] or None
2122 # coerced_unpacked_items [ExprNode] or None
2124 subexprs = ['args']
2126 is_sequence_constructor = 1
2127 unpacked_items = None
2129 def compile_time_value_list(self, denv):
2130 return [arg.compile_time_value(denv) for arg in self.args]
2132 def analyse_target_declaration(self, env):
2133 for arg in self.args:
2134 arg.analyse_target_declaration(env)
2136 def analyse_types(self, env):
2137 for i in range(len(self.args)):
2138 arg = self.args[i]
2139 arg.analyse_types(env)
2140 self.args[i] = arg.coerce_to_pyobject(env)
2141 self.type = py_object_type
2142 self.gil_check(env)
2143 self.is_temp = 1
2145 def analyse_target_types(self, env):
2146 self.iterator = PyTempNode(self.pos, env)
2147 self.unpacked_items = []
2148 self.coerced_unpacked_items = []
2149 for arg in self.args:
2150 arg.analyse_target_types(env)
2151 unpacked_item = PyTempNode(self.pos, env)
2152 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2153 self.unpacked_items.append(unpacked_item)
2154 self.coerced_unpacked_items.append(coerced_unpacked_item)
2155 self.type = py_object_type
2156 # env.use_utility_code(unpacking_utility_code)
2158 def allocate_target_temps(self, env, rhs):
2159 self.iterator.allocate_temps(env)
2160 if rhs:
2161 rhs.release_temp(env)
2162 for arg, node in zip(self.args, self.coerced_unpacked_items):
2163 node.allocate_temps(env)
2164 arg.allocate_target_temps(env, node)
2165 #arg.release_target_temp(env)
2166 #node.release_temp(env)
2167 self.iterator.release_temp(env)
2169 # def release_target_temp(self, env):
2170 # #for arg in self.args:
2171 # # arg.release_target_temp(env)
2172 # #for node in self.coerced_unpacked_items:
2173 # # node.release_temp(env)
2174 # self.iterator.release_temp(env)
2176 def generate_result_code(self, code):
2177 self.generate_operation_code(code)
2179 def generate_assignment_code(self, rhs, code):
2180 iter_result = self.iterator.result()
2181 code.putln(
2182 "%s = PyObject_GetIter(%s); if (!%s) %s" % (
2183 iter_result,
2184 rhs.py_result(),
2185 iter_result,
2186 code.error_goto(self.pos)))
2187 rhs.generate_disposal_code(code)
2188 for i in range(len(self.args)):
2189 item = self.unpacked_items[i]
2190 code.use_utility_code(unpacking_utility_code)
2191 unpack_code = "__Pyx_UnpackItem(%s)" % (
2192 self.iterator.py_result())
2193 item_result = item.result()
2194 code.putln(
2195 "%s = %s; if (!%s) %s" % (
2196 item_result,
2197 typecast(item.ctype(), py_object_type, unpack_code),
2198 item_result,
2199 code.error_goto(self.pos)))
2200 value_node = self.coerced_unpacked_items[i]
2201 value_node.generate_evaluation_code(code)
2202 self.args[i].generate_assignment_code(value_node, code)
2203 code.putln(
2204 "if (__Pyx_EndUnpack(%s) < 0) %s" % (
2205 self.iterator.py_result(),
2206 code.error_goto(self.pos)))
2207 if debug_disposal_code:
2208 print "UnpackNode.generate_assignment_code:"
2209 print "...generating disposal code for", rhs
2210 self.iterator.generate_disposal_code(code)
2213 class TupleNode(SequenceNode):
2214 # Tuple constructor.
2216 gil_message = "Constructing Python tuple"
2218 def compile_time_value(self, denv):
2219 values = self.compile_time_value_list(denv)
2220 try:
2221 return tuple(values)
2222 except Exception, e:
2223 self.compile_time_value_error(e)
2225 def generate_operation_code(self, code):
2226 result = self.result()
2227 code.putln(
2228 "%s = PyTuple_New(%s); if (!%s) %s" % (
2229 result,
2230 len(self.args),
2231 result,
2232 code.error_goto(self.pos)))
2233 for i in range(len(self.args)):
2234 arg = self.args[i]
2235 arg_result = arg.py_result()
2236 # ??? Change this to use make_owned_reference?
2237 if not arg.result_in_temp():
2238 code.put_incref(arg_result)
2239 code.putln(
2240 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2241 result,
2242 i,
2243 arg_result))
2245 def generate_subexpr_disposal_code(self, code):
2246 # We call generate_post_assignment_code here instead
2247 # of generate_disposal_code, because values were stored
2248 # in the tuple using a reference-stealing operation.
2249 for arg in self.args:
2250 arg.generate_post_assignment_code(code)
2253 class ListNode(SequenceNode):
2254 # List constructor.
2256 gil_message = "Constructing Python list"
2258 def compile_time_value(self, denv):
2259 return self.compile_time_value_list(denv)
2261 def generate_operation_code(self, code):
2262 result = self.result()
2263 code.putln("%s = PyList_New(%s); if (!%s) %s" %
2264 (result,
2265 len(self.args),
2266 result,
2267 code.error_goto(self.pos)))
2268 for i in range(len(self.args)):
2269 arg = self.args[i]
2270 arg_result = arg.py_result()
2271 #if not arg.is_temp:
2272 if not arg.result_in_temp():
2273 code.put_incref(arg_result)
2274 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2275 (result,
2276 i,
2277 arg_result))
2279 def generate_subexpr_disposal_code(self, code):
2280 # We call generate_post_assignment_code here instead
2281 # of generate_disposal_code, because values were stored
2282 # in the list using a reference-stealing operation.
2283 for arg in self.args:
2284 arg.generate_post_assignment_code(code)
2287 class DictNode(ExprNode):
2288 # Dictionary constructor.
2290 # key_value_pairs [(ExprNode, ExprNode)]
2292 def compile_time_value(self, denv):
2293 pairs = [(key.compile_time_value(denv), value.compile_time_value(denv))
2294 for (key, value) in self.key_value_pairs]
2295 try:
2296 return dict(pairs)
2297 except Exception, e:
2298 self.compile_time_value_error(e)
2300 def analyse_types(self, env):
2301 new_pairs = []
2302 for key, value in self.key_value_pairs:
2303 key.analyse_types(env)
2304 value.analyse_types(env)
2305 key = key.coerce_to_pyobject(env)
2306 value = value.coerce_to_pyobject(env)
2307 new_pairs.append((key, value))
2308 self.key_value_pairs = new_pairs
2309 self.type = py_object_type
2310 self.gil_check(env)
2311 self.is_temp = 1
2313 gil_message = "Constructing Python dict"
2315 def allocate_temps(self, env, result = None):
2316 # Custom method used here because key-value
2317 # pairs are evaluated and used one at a time.
2318 self.allocate_temp(env, result)
2319 for key, value in self.key_value_pairs:
2320 key.allocate_temps(env)
2321 value.allocate_temps(env)
2322 key.release_temp(env)
2323 value.release_temp(env)
2325 def generate_evaluation_code(self, code):
2326 # Custom method used here because key-value
2327 # pairs are evaluated and used one at a time.
2328 result = self.result()
2329 code.putln(
2330 "%s = PyDict_New(); if (!%s) %s" % (
2331 result,
2332 result,
2333 code.error_goto(self.pos)))
2334 for key, value in self.key_value_pairs:
2335 key.generate_evaluation_code(code)
2336 value.generate_evaluation_code(code)
2337 code.putln(
2338 "if (PyDict_SetItem(%s, %s, %s) < 0) %s" % (
2339 result,
2340 key.py_result(),
2341 value.py_result(),
2342 code.error_goto(self.pos)))
2343 key.generate_disposal_code(code)
2344 value.generate_disposal_code(code)
2347 class ClassNode(ExprNode):
2348 # Helper class used in the implementation of Python
2349 # class definitions. Constructs a class object given
2350 # a name, tuple of bases and class dictionary.
2352 # name ExprNode Name of the class
2353 # bases ExprNode Base class tuple
2354 # dict ExprNode Class dict (not owned by this node)
2355 # doc ExprNode or None Doc string
2356 # module_name string Name of defining module
2358 subexprs = ['name', 'bases', 'doc']
2360 def analyse_types(self, env):
2361 self.name.analyse_types(env)
2362 self.name = self.name.coerce_to_pyobject(env)
2363 self.bases.analyse_types(env)
2364 if self.doc:
2365 self.doc.analyse_types(env)
2366 self.doc = self.doc.coerce_to_pyobject(env)
2367 self.module_name = env.global_scope().qualified_name
2368 self.type = py_object_type
2369 self.gil_check(env)
2370 self.is_temp = 1
2371 # env.use_utility_code(create_class_utility_code)
2373 gil_message = "Constructing Python class"
2375 def generate_result_code(self, code):
2376 result = self.result()
2377 if self.doc:
2378 code.putln(
2379 'if (PyDict_SetItemString(%s, "__doc__", %s) < 0) %s' % (
2380 self.dict.py_result(),
2381 self.doc.py_result(),
2382 code.error_goto(self.pos)))
2383 code.use_utility_code(create_class_utility_code)
2384 code.putln(
2385 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); if (!%s) %s' % (
2386 result,
2387 self.bases.py_result(),
2388 self.dict.py_result(),
2389 self.name.py_result(),
2390 self.module_name,
2391 result,
2392 code.error_goto(self.pos)))
2395 class UnboundMethodNode(ExprNode):
2396 # Helper class used in the implementation of Python
2397 # class definitions. Constructs an unbound method
2398 # object from a class and a function.
2400 # class_cname string C var holding the class object
2401 # function ExprNode Function object
2403 subexprs = ['function']
2405 def analyse_types(self, env):
2406 self.function.analyse_types(env)
2407 self.type = py_object_type
2408 self.gil_check(env)
2409 self.is_temp = 1
2411 gil_message = "Constructing an unbound method"
2413 def generate_result_code(self, code):
2414 result = self.result()
2415 code.putln(
2416 "%s = PyMethod_New(%s, 0, %s); if (!%s) %s" % (
2417 result,
2418 self.function.py_result(),
2419 self.class_cname,
2420 result,
2421 code.error_goto(self.pos)))
2424 class PyCFunctionNode(AtomicExprNode):
2425 # Helper class used in the implementation of Python
2426 # class definitions. Constructs a PyCFunction object
2427 # from a PyMethodDef struct.
2429 # pymethdef_cname string PyMethodDef structure
2431 def analyse_types(self, env):
2432 self.type = py_object_type
2433 self.gil_check(env)
2434 self.is_temp = 1
2436 gil_message = "Constructing Python function"
2438 def generate_result_code(self, code):
2439 result = self.result()
2440 code.putln(
2441 "%s = PyCFunction_New(&%s, 0); if (!%s) %s" % (
2442 result,
2443 self.pymethdef_cname,
2444 result,
2445 code.error_goto(self.pos)))
2447 #-------------------------------------------------------------------
2449 # Unary operator nodes
2451 #-------------------------------------------------------------------
2453 compile_time_unary_operators = {
2454 'not': operator.not_,
2455 '~': operator.inv,
2456 '-': operator.neg,
2457 '+': operator.pos,
2460 class UnopNode(ExprNode):
2461 # operator string
2462 # operand ExprNode
2464 # Processing during analyse_expressions phase:
2466 # analyse_c_operation
2467 # Called when the operand is not a pyobject.
2468 # - Check operand type and coerce if needed.
2469 # - Determine result type and result code fragment.
2470 # - Allocate temporary for result if needed.
2472 subexprs = ['operand']
2474 def compile_time_value(self, denv):
2475 func = compile_time_unary_operators.get(self.operator)
2476 if not func:
2477 error(self.pos,
2478 "Unary '%s' not supported in compile-time expression"
2479 % self.operator)
2480 operand = self.operand.compile_time_value(denv)
2481 try:
2482 return func(operand)
2483 except Exception, e:
2484 self.compile_time_value_error(e)
2486 def analyse_types(self, env):
2487 self.operand.analyse_types(env)
2488 if self.is_py_operation():
2489 self.coerce_operand_to_pyobject(env)
2490 self.type = py_object_type
2491 self.gil_check(env)
2492 self.is_temp = 1
2493 else:
2494 self.analyse_c_operation(env)
2496 def check_const(self):
2497 self.operand.check_const()
2499 def is_py_operation(self):
2500 return self.operand.type.is_pyobject
2502 def coerce_operand_to_pyobject(self, env):
2503 self.operand = self.operand.coerce_to_pyobject(env)
2505 def generate_result_code(self, code):
2506 if self.operand.type.is_pyobject:
2507 self.generate_py_operation_code(code)
2508 else:
2509 if self.is_temp:
2510 self.generate_c_operation_code(code)
2512 def generate_py_operation_code(self, code):
2513 function = self.py_operation_function()
2514 result = self.result()
2515 code.putln(
2516 "%s = %s(%s); if (!%s) %s" % (
2517 result,
2518 function,
2519 self.operand.py_result(),
2520 result,
2521 code.error_goto(self.pos)))
2523 def type_error(self):
2524 if not self.operand.type.is_error:
2525 error(self.pos, "Invalid operand type for '%s' (%s)" %
2526 (self.operator, self.operand.type))
2527 self.type = PyrexTypes.error_type
2530 class NotNode(ExprNode):
2531 # 'not' operator
2533 # operand ExprNode
2535 def compile_time_value(self, denv):
2536 operand = self.operand.compile_time_value(denv)
2537 try:
2538 return not operand
2539 except Exception, e:
2540 self.compile_time_value_error(e)
2542 subexprs = ['operand']
2544 def analyse_types(self, env):
2545 self.operand.analyse_types(env)
2546 self.operand = self.operand.coerce_to_boolean(env)
2547 self.type = PyrexTypes.c_int_type
2549 def calculate_result_code(self):
2550 return "(!%s)" % self.operand.result()
2552 def generate_result_code(self, code):
2553 pass
2556 class UnaryPlusNode(UnopNode):
2557 # unary '+' operator
2559 operator = '+'
2561 def analyse_c_operation(self, env):
2562 self.type = self.operand.type
2564 def py_operation_function(self):
2565 return "PyNumber_Positive"
2567 def calculate_result_code(self):
2568 return self.operand.result()
2571 class UnaryMinusNode(UnopNode):
2572 # unary '-' operator
2574 operator = '-'
2576 def analyse_c_operation(self, env):
2577 if self.operand.type.is_numeric:
2578 self.type = self.operand.type
2579 else:
2580 self.type_error()
2582 def py_operation_function(self):
2583 return "PyNumber_Negative"
2585 def calculate_result_code(self):
2586 return "(-%s)" % self.operand.result()
2589 class TildeNode(UnopNode):
2590 # unary '~' operator
2592 def analyse_c_operation(self, env):
2593 if self.operand.type.is_int:
2594 self.type = self.operand.type
2595 else:
2596 self.type_error()
2598 def py_operation_function(self):
2599 return "PyNumber_Invert"
2601 def calculate_result_code(self):
2602 return "(~%s)" % self.operand.result()
2605 class AmpersandNode(ExprNode):
2606 # The C address-of operator.
2608 # operand ExprNode
2610 subexprs = ['operand']
2612 def analyse_types(self, env):
2613 self.operand.analyse_types(env)
2614 argtype = self.operand.type
2615 if not (argtype.is_cfunction or self.operand.is_lvalue()):
2616 self.error("Taking address of non-lvalue")
2617 return
2618 if argtype.is_pyobject:
2619 self.error("Cannot take address of Python variable")
2620 return
2621 self.type = PyrexTypes.c_ptr_type(argtype)
2623 def check_const(self):
2624 self.operand.check_const_addr()
2626 def error(self, mess):
2627 error(self.pos, mess)
2628 self.type = PyrexTypes.error_type
2629 self.result_code = "<error>"
2631 def calculate_result_code(self):
2632 return "(&%s)" % self.operand.result()
2634 def generate_result_code(self, code):
2635 pass
2638 unop_node_classes = {
2639 "+": UnaryPlusNode,
2640 "-": UnaryMinusNode,
2641 "~": TildeNode,
2644 def unop_node(pos, operator, operand):
2645 # Construct unnop node of appropriate class for
2646 # given operator.
2647 return unop_node_classes[operator](pos,
2648 operator = operator,
2649 operand = operand)
2652 class TypecastNode(ExprNode):
2653 # C type cast
2655 # base_type CBaseTypeNode
2656 # declarator CDeclaratorNode
2657 # operand ExprNode
2659 subexprs = ['operand']
2661 def analyse_types(self, env):
2662 base_type = self.base_type.analyse(env)
2663 _, self.type = self.declarator.analyse(base_type, env)
2664 if self.type.is_cfunction:
2665 error(self.pos,
2666 "Cannot cast to a function type")
2667 self.type = PyrexTypes.error_type
2668 self.operand.analyse_types(env)
2669 to_py = self.type.is_pyobject
2670 from_py = self.operand.type.is_pyobject
2671 if from_py and not to_py and self.operand.is_ephemeral():
2672 error(self.pos, "Casting temporary Python object to non-Python type")
2673 #if to_py and not from_py:
2674 # self.result_ctype = py_object_type
2675 # self.is_temp = 1
2677 def check_const(self):
2678 self.operand.check_const()
2680 def calculate_result_code(self):
2681 opnd = self.operand
2682 result_code = self.type.cast_code(opnd.result())
2683 return result_code
2685 def result_as(self, type):
2686 #if self.type.is_pyobject and not self.is_temp:
2687 if not self.is_temp:
2688 # Optimise away some unnecessary casting
2689 return self.operand.result_as(type)
2690 else:
2691 return ExprNode.result_as(self, type)
2693 def generate_result_code(self, code):
2694 if self.is_temp:
2695 code.putln(
2696 "%s = %s;" % (
2697 self.result(),
2698 self.operand.py_result()))
2699 code.put_incref(self.py_result())
2702 class SizeofNode(ExprNode):
2703 # Abstract base class for sizeof(x) expression nodes.
2705 def check_const(self):
2706 pass
2708 def generate_result_code(self, code):
2709 pass
2712 class SizeofTypeNode(SizeofNode):
2713 # C sizeof function applied to a type
2715 # base_type CBaseTypeNode
2716 # declarator CDeclaratorNode
2718 subexprs = []
2720 def analyse_types(self, env):
2721 base_type = self.base_type.analyse(env)
2722 _, arg_type = self.declarator.analyse(base_type, env)
2723 self.arg_type = arg_type
2724 if arg_type.is_pyobject:
2725 error(self.pos, "Cannot take sizeof Python object")
2726 elif arg_type.is_void:
2727 error(self.pos, "Cannot take sizeof void")
2728 elif not arg_type.is_complete():
2729 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
2730 self.type = PyrexTypes.c_int_type
2732 def calculate_result_code(self):
2733 arg_code = self.arg_type.declaration_code("")
2734 return "(sizeof(%s))" % arg_code
2737 class SizeofVarNode(SizeofNode):
2738 # C sizeof function applied to a variable
2740 # operand ExprNode
2742 subexprs = ['operand']
2744 def analyse_types(self, env):
2745 self.operand.analyse_types(env)
2746 self.type = PyrexTypes.c_int_type
2748 def calculate_result_code(self):
2749 return "(sizeof(%s))" % self.operand.result()
2751 def generate_result_code(self, code):
2752 pass
2755 #-------------------------------------------------------------------
2757 # Binary operator nodes
2759 #-------------------------------------------------------------------
2761 compile_time_binary_operators = {
2762 '<': operator.lt,
2763 '<=': operator.le,
2764 '==': operator.eq,
2765 '!=': operator.ne,
2766 '>=': operator.ge,
2767 '>': operator.gt,
2768 'is': operator.is_,
2769 'is_not': operator.is_not,
2770 '+': operator.add,
2771 '&': operator.and_,
2772 '/': operator.div,
2773 '//': operator.floordiv,
2774 '<<': operator.lshift,
2775 '%': operator.mod,
2776 '*': operator.mul,
2777 '|': operator.or_,
2778 '**': operator.pow,
2779 '>>': operator.rshift,
2780 '-': operator.sub,
2781 #'/': operator.truediv,
2782 '^': operator.xor,
2783 'in': lambda x, y: x in y,
2784 'not_in': lambda x, y: x not in y,
2787 def get_compile_time_binop(node):
2788 func = compile_time_binary_operators.get(node.operator)
2789 if not func:
2790 error(node.pos,
2791 "Binary '%s' not supported in compile-time expression"
2792 % node.operator)
2793 return func
2795 class BinopNode(ExprNode):
2796 # operator string
2797 # operand1 ExprNode
2798 # operand2 ExprNode
2800 # Processing during analyse_expressions phase:
2802 # analyse_c_operation
2803 # Called when neither operand is a pyobject.
2804 # - Check operand types and coerce if needed.
2805 # - Determine result type and result code fragment.
2806 # - Allocate temporary for result if needed.
2808 subexprs = ['operand1', 'operand2']
2810 def compile_time_value(self, denv):
2811 func = get_compile_time_binop(self)
2812 operand1 = self.operand1.compile_time_value(denv)
2813 operand2 = self.operand2.compile_time_value(denv)
2814 try:
2815 return func(operand1, operand2)
2816 except Exception, e:
2817 self.compile_time_value_error(e)
2819 def analyse_types(self, env):
2820 self.operand1.analyse_types(env)
2821 self.operand2.analyse_types(env)
2822 if self.is_py_operation():
2823 self.coerce_operands_to_pyobjects(env)
2824 self.type = py_object_type
2825 self.gil_check(env)
2826 self.is_temp = 1
2827 else:
2828 self.analyse_c_operation(env)
2830 def is_py_operation(self):
2831 return (self.operand1.type.is_pyobject
2832 or self.operand2.type.is_pyobject)
2834 def coerce_operands_to_pyobjects(self, env):
2835 self.operand1 = self.operand1.coerce_to_pyobject(env)
2836 self.operand2 = self.operand2.coerce_to_pyobject(env)
2838 def check_const(self):
2839 self.operand1.check_const()
2840 self.operand2.check_const()
2842 def generate_result_code(self, code):
2843 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
2844 if self.operand1.type.is_pyobject:
2845 function = self.py_operation_function()
2846 if function == "PyNumber_Power":
2847 extra_args = ", Py_None"
2848 else:
2849 extra_args = ""
2850 result = self.result()
2851 code.putln(
2852 "%s = %s(%s, %s%s); if (!%s) %s" % (
2853 result,
2854 function,
2855 self.operand1.py_result(),
2856 self.operand2.py_result(),
2857 extra_args,
2858 result,
2859 code.error_goto(self.pos)))
2860 else:
2861 if self.is_temp:
2862 self.generate_c_operation_code(code)
2864 def type_error(self):
2865 if not (self.operand1.type.is_error
2866 or self.operand2.type.is_error):
2867 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
2868 (self.operator, self.operand1.type,
2869 self.operand2.type))
2870 self.type = PyrexTypes.error_type
2873 class NumBinopNode(BinopNode):
2874 # Binary operation taking numeric arguments.
2876 def analyse_c_operation(self, env):
2877 type1 = self.operand1.type
2878 type2 = self.operand2.type
2879 if self.operator == "**" and type1.is_int and type2.is_int:
2880 error(self.pos, "** with two C int types is ambiguous")
2881 self.type = error_type
2882 return
2883 self.type = self.compute_c_result_type(type1, type2)
2884 if not self.type:
2885 self.type_error()
2887 def compute_c_result_type(self, type1, type2):
2888 if self.c_types_okay(type1, type2):
2889 return PyrexTypes.widest_numeric_type(type1, type2)
2890 else:
2891 return None
2893 def c_types_okay(self, type1, type2):
2894 #print "NumBinopNode.c_types_okay:", type1, type2 ###
2895 return (type1.is_numeric or type1.is_enum) \
2896 and (type2.is_numeric or type2.is_enum)
2898 def calculate_result_code(self):
2899 return "(%s %s %s)" % (
2900 self.operand1.result(),
2901 self.operator,
2902 self.operand2.result())
2904 def py_operation_function(self):
2905 return self.py_functions[self.operator]
2907 py_functions = {
2908 "|": "PyNumber_Or",
2909 "^": "PyNumber_Xor",
2910 "&": "PyNumber_And",
2911 "<<": "PyNumber_Lshift",
2912 ">>": "PyNumber_Rshift",
2913 "+": "PyNumber_Add",
2914 "-": "PyNumber_Subtract",
2915 "*": "PyNumber_Multiply",
2916 "/": "PyNumber_Divide",
2917 "%": "PyNumber_Remainder",
2918 "**": "PyNumber_Power"
2922 class IntBinopNode(NumBinopNode):
2923 # Binary operation taking integer arguments.
2925 def c_types_okay(self, type1, type2):
2926 #print "IntBinopNode.c_types_okay:", type1, type2 ###
2927 return (type1.is_int or type1.is_enum) \
2928 and (type2.is_int or type2.is_enum)
2931 class AddNode(NumBinopNode):
2932 # '+' operator.
2934 def is_py_operation(self):
2935 if self.operand1.type.is_string \
2936 and self.operand2.type.is_string:
2937 return 1
2938 else:
2939 return NumBinopNode.is_py_operation(self)
2941 def compute_c_result_type(self, type1, type2):
2942 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
2943 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
2944 return type1
2945 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
2946 return type2
2947 else:
2948 return NumBinopNode.compute_c_result_type(
2949 self, type1, type2)
2952 class SubNode(NumBinopNode):
2953 # '-' operator.
2955 def compute_c_result_type(self, type1, type2):
2956 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
2957 return type1
2958 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
2959 return PyrexTypes.c_int_type
2960 else:
2961 return NumBinopNode.compute_c_result_type(
2962 self, type1, type2)
2965 class MulNode(NumBinopNode):
2966 # '*' operator.
2968 def is_py_operation(self):
2969 type1 = self.operand1.type
2970 type2 = self.operand2.type
2971 if (type1.is_string and type2.is_int) \
2972 or (type2.is_string and type1.is_int):
2973 return 1
2974 else:
2975 return NumBinopNode.is_py_operation(self)
2978 class ModNode(IntBinopNode):
2979 # '%' operator.
2981 def is_py_operation(self):
2982 return (self.operand1.type.is_string
2983 or self.operand2.type.is_string
2984 or IntBinopNode.is_py_operation(self))
2987 class PowNode(NumBinopNode):
2988 # '**' operator.
2990 def analyse_types(self, env):
2991 env.pow_function_used = 1
2992 NumBinopNode.analyse_types(self, env)
2994 def compute_c_result_type(self, type1, type2):
2995 if self.c_types_okay(type1, type2):
2996 return PyrexTypes.c_double_type
2997 else:
2998 return None
3000 def calculate_result_code(self):
3001 return "pow(%s, %s)" % (
3002 self.operand1.result(), self.operand2.result())
3005 class BoolBinopNode(ExprNode):
3006 # Short-circuiting boolean operation.
3008 # operator string
3009 # operand1 ExprNode
3010 # operand2 ExprNode
3011 # temp_bool ExprNode used internally
3013 temp_bool = None
3015 subexprs = ['operand1', 'operand2', 'temp_bool']
3017 def compile_time_value(self, denv):
3018 if self.operator == 'and':
3019 return self.operand1.compile_time_value(denv) \
3020 and self.operand2.compile_time_value(denv)
3021 else:
3022 return self.operand1.compile_time_value(denv) \
3023 or self.operand2.compile_time_value(denv)
3025 def analyse_types(self, env):
3026 self.operand1.analyse_types(env)
3027 self.operand2.analyse_types(env)
3028 if self.operand1.type.is_pyobject or \
3029 self.operand2.type.is_pyobject:
3030 self.operand1 = self.operand1.coerce_to_pyobject(env)
3031 self.operand2 = self.operand2.coerce_to_pyobject(env)
3032 self.temp_bool = TempNode(self.pos,
3033 PyrexTypes.c_int_type, env)
3034 self.type = py_object_type
3035 self.gil_check(env)
3036 else:
3037 self.operand1 = self.operand1.coerce_to_boolean(env)
3038 self.operand2 = self.operand2.coerce_to_boolean(env)
3039 self.type = PyrexTypes.c_int_type
3040 # For what we're about to do, it's vital that
3041 # both operands be temp nodes.
3042 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3043 self.operand2 = self.operand2.coerce_to_temp(env)
3044 self.is_temp = 1
3046 gil_message = "Truth-testing Python object"
3048 def allocate_temps(self, env, result_code = None):
3049 # We don't need both operands at the same time, and
3050 # one of the operands will also be our result. So we
3051 # use an allocation strategy here which results in
3052 # this node and both its operands sharing the same
3053 # result variable. This allows us to avoid some
3054 # assignments and increfs/decrefs that would otherwise
3055 # be necessary.
3056 self.allocate_temp(env, result_code)
3057 self.operand1.allocate_temps(env, self.result_code)
3058 if self.temp_bool:
3059 self.temp_bool.allocate_temp(env)
3060 self.temp_bool.release_temp(env)
3061 self.operand2.allocate_temps(env, self.result_code)
3062 # We haven't called release_temp on either operand,
3063 # because although they are temp nodes, they don't own
3064 # their result variable. And because they are temp
3065 # nodes, any temps in their subnodes will have been
3066 # released before their allocate_temps returned.
3067 # Therefore, they contain no temp vars that need to
3068 # be released.
3070 def check_const(self):
3071 self.operand1.check_const()
3072 self.operand2.check_const()
3074 def calculate_result_code(self):
3075 return "(%s %s %s)" % (
3076 self.operand1.result(),
3077 self.py_to_c_op[self.operator],
3078 self.operand2.result())
3080 py_to_c_op = {'and': "&&", 'or': "||"}
3082 def generate_evaluation_code(self, code):
3083 self.operand1.generate_evaluation_code(code)
3084 test_result = self.generate_operand1_test(code)
3085 if self.operator == 'and':
3086 sense = ""
3087 else:
3088 sense = "!"
3089 code.putln(
3090 "if (%s%s) {" % (
3091 sense,
3092 test_result))
3093 self.operand1.generate_disposal_code(code)
3094 self.operand2.generate_evaluation_code(code)
3095 code.putln(
3096 "}")
3098 def generate_operand1_test(self, code):
3099 # Generate code to test the truth of the first operand.
3100 if self.type.is_pyobject:
3101 test_result = self.temp_bool.result()
3102 code.putln(
3103 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
3104 test_result,
3105 self.operand1.py_result(),
3106 test_result,
3107 code.error_goto(self.pos)))
3108 else:
3109 test_result = self.operand1.result()
3110 return test_result
3113 class CmpNode:
3114 # Mixin class containing code common to PrimaryCmpNodes
3115 # and CascadedCmpNodes.
3117 def cascaded_compile_time_value(self, operand1, denv):
3118 func = get_compile_time_binop(self)
3119 operand2 = self.operand2.compile_time_value(denv)
3120 try:
3121 result = func(operand1, operand2)
3122 except Exception, e:
3123 self.compile_time_value_error(e)
3124 result = None
3125 if result:
3126 cascade = self.cascade
3127 if cascade:
3128 result = result and cascade.compile_time_value(operand2, denv)
3129 return result
3131 def is_python_comparison(self):
3132 return (self.has_python_operands()
3133 or (self.cascade and self.cascade.is_python_comparison())
3134 or self.operator in ('in', 'not_in'))
3136 def check_types(self, env, operand1, op, operand2):
3137 if not self.types_okay(operand1, op, operand2):
3138 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3139 (self.operator, operand1.type, operand2.type))
3141 def types_okay(self, operand1, op, operand2):
3142 type1 = operand1.type
3143 type2 = operand2.type
3144 if type1.is_error or type2.is_error:
3145 return 1
3146 if type1.is_pyobject: # type2 will be, too
3147 return 1
3148 elif type1.is_ptr or type1.is_array:
3149 return type1.is_null_ptr or type2.is_null_ptr \
3150 or ((type2.is_ptr or type2.is_array)
3151 and type1.base_type.same_as(type2.base_type))
3152 elif ((type1.is_numeric and type2.is_numeric
3153 or type1.is_enum and (type2.is_int or type1.same_as(type2))
3154 or type1.is_int and type2.is_enum)
3155 and op not in ('is', 'is_not')):
3156 return 1
3157 else:
3158 return 0
3160 def generate_operation_code(self, code, result,
3161 operand1, op , operand2):
3162 if op == 'in' or op == 'not_in':
3163 code.putln(
3164 "%s = PySequence_Contains(%s, %s); if (%s < 0) %s" % (
3165 result,
3166 operand2.py_result(),
3167 operand1.py_result(),
3168 result,
3169 code.error_goto(self.pos)))
3170 if op == 'not_in':
3171 code.putln(
3172 "%s = !%s;" % (
3173 result, result))
3174 elif (operand1.type.is_pyobject
3175 and op not in ('is', 'is_not')):
3176 code.putln(
3177 "if (PyObject_Cmp(%s, %s, &%s) < 0) %s" % (
3178 operand1.py_result(),
3179 operand2.py_result(),
3180 result,
3181 code.error_goto(self.pos)))
3182 code.putln(
3183 "%s = %s %s 0;" % (
3184 result, result, op))
3185 else:
3186 type1 = operand1.type
3187 type2 = operand2.type
3188 if (type1.is_extension_type or type2.is_extension_type) \
3189 and not operand1.ctype().same_as(operand2.ctype()):
3190 code1 = operand1.result_as(py_object_type)
3191 code2 = operand2.result_as(py_object_type)
3192 else:
3193 code1 = operand1.result()
3194 code2 = operand2.result()
3195 code.putln("%s = %s %s %s;" % (
3196 result,
3197 code1,
3198 self.c_operator(op),
3199 code2))
3201 def c_operator(self, op):
3202 if op == 'is':
3203 return "=="
3204 elif op == 'is_not':
3205 return "!="
3206 else:
3207 return op
3210 class PrimaryCmpNode(ExprNode, CmpNode):
3211 # Non-cascaded comparison or first comparison of
3212 # a cascaded sequence.
3214 # operator string
3215 # operand1 ExprNode
3216 # operand2 ExprNode
3217 # cascade CascadedCmpNode
3219 # We don't use the subexprs mechanism, because
3220 # things here are too complicated for it to handle.
3221 # Instead, we override all the framework methods
3222 # which use it.
3224 cascade = None
3226 def compile_time_value(self, denv):
3227 operand1 = self.operand1.compile_time_value(denv)
3228 return self.cascaded_compile_time_value(operand1, denv)
3230 def analyse_types(self, env):
3231 self.operand1.analyse_types(env)
3232 self.operand2.analyse_types(env)
3233 if self.cascade:
3234 self.cascade.analyse_types(env, self.operand2)
3235 self.is_pycmp = self.is_python_comparison()
3236 if self.is_pycmp:
3237 self.coerce_operands_to_pyobjects(env)
3238 if self.cascade:
3239 self.operand2 = self.operand2.coerce_to_simple(env)
3240 self.cascade.coerce_cascaded_operands_to_temp(env)
3241 self.check_operand_types(env)
3242 self.type = PyrexTypes.c_int_type
3243 if self.is_pycmp or self.cascade:
3244 self.is_temp = 1
3246 def check_operand_types(self, env):
3247 self.check_types(env,
3248 self.operand1, self.operator, self.operand2)
3249 if self.cascade:
3250 self.cascade.check_operand_types(env, self.operand2)
3252 def has_python_operands(self):
3253 return (self.operand1.type.is_pyobject
3254 or self.operand2.type.is_pyobject)
3256 def coerce_operands_to_pyobjects(self, env):
3257 self.operand1 = self.operand1.coerce_to_pyobject(env)
3258 self.operand2 = self.operand2.coerce_to_pyobject(env)
3259 if self.cascade:
3260 self.cascade.coerce_operands_to_pyobjects(env)
3262 def allocate_subexpr_temps(self, env):
3263 self.operand1.allocate_temps(env)
3264 self.operand2.allocate_temps(env)
3265 if self.cascade:
3266 self.cascade.allocate_subexpr_temps(env)
3268 def release_subexpr_temps(self, env):
3269 self.operand1.release_temp(env)
3270 self.operand2.release_temp(env)
3271 if self.cascade:
3272 self.cascade.release_subexpr_temps(env)
3274 def check_const(self):
3275 self.operand1.check_const()
3276 self.operand2.check_const()
3277 if self.cascade:
3278 self.not_const()
3280 def calculate_result_code(self):
3281 return "(%s %s %s)" % (
3282 self.operand1.result(),
3283 self.c_operator(self.operator),
3284 self.operand2.result())
3286 def generate_evaluation_code(self, code):
3287 self.operand1.generate_evaluation_code(code)
3288 self.operand2.generate_evaluation_code(code)
3289 if self.is_temp:
3290 result = self.result()
3291 self.generate_operation_code(code, result,
3292 self.operand1, self.operator, self.operand2)
3293 if self.cascade:
3294 self.cascade.generate_evaluation_code(code,
3295 result, self.operand2)
3296 self.operand1.generate_disposal_code(code)
3297 self.operand2.generate_disposal_code(code)
3299 def generate_subexpr_disposal_code(self, code):
3300 # If this is called, it is a non-cascaded cmp,
3301 # so only need to dispose of the two main operands.
3302 self.operand1.generate_disposal_code(code)
3303 self.operand2.generate_disposal_code(code)
3306 class CascadedCmpNode(Node, CmpNode):
3307 # A CascadedCmpNode is not a complete expression node. It
3308 # hangs off the side of another comparison node, shares
3309 # its left operand with that node, and shares its result
3310 # with the PrimaryCmpNode at the head of the chain.
3312 # operator string
3313 # operand2 ExprNode
3314 # cascade CascadedCmpNode
3316 cascade = None
3318 def analyse_types(self, env, operand1):
3319 self.operand2.analyse_types(env)
3320 if self.cascade:
3321 self.cascade.analyse_types(env, self.operand2)
3323 def check_operand_types(self, env, operand1):
3324 self.check_types(env,
3325 operand1, self.operator, self.operand2)
3326 if self.cascade:
3327 self.cascade.check_operand_types(env, self.operand2)
3329 def has_python_operands(self):
3330 return self.operand2.type.is_pyobject
3332 def coerce_operands_to_pyobjects(self, env):
3333 self.operand2 = self.operand2.coerce_to_pyobject(env)
3334 if self.cascade:
3335 self.cascade.coerce_operands_to_pyobjects(env)
3337 def coerce_cascaded_operands_to_temp(self, env):
3338 if self.cascade:
3339 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
3340 self.operand2 = self.operand2.coerce_to_simple(env)
3341 self.cascade.coerce_cascaded_operands_to_temp(env)
3343 def allocate_subexpr_temps(self, env):
3344 self.operand2.allocate_temps(env)
3345 if self.cascade:
3346 self.cascade.allocate_subexpr_temps(env)
3348 def release_subexpr_temps(self, env):
3349 self.operand2.release_temp(env)
3350 if self.cascade:
3351 self.cascade.release_subexpr_temps(env)
3353 def generate_evaluation_code(self, code, result, operand1):
3354 code.putln("if (%s) {" % result)
3355 self.operand2.generate_evaluation_code(code)
3356 self.generate_operation_code(code, result,
3357 operand1, self.operator, self.operand2)
3358 if self.cascade:
3359 self.cascade.generate_evaluation_code(
3360 code, result, self.operand2)
3361 # Cascaded cmp result is always temp
3362 self.operand2.generate_disposal_code(code)
3363 code.putln("}")
3366 binop_node_classes = {
3367 "or": BoolBinopNode,
3368 "and": BoolBinopNode,
3369 "|": IntBinopNode,
3370 "^": IntBinopNode,
3371 "&": IntBinopNode,
3372 "<<": IntBinopNode,
3373 ">>": IntBinopNode,
3374 "+": AddNode,
3375 "-": SubNode,
3376 "*": MulNode,
3377 "/": NumBinopNode,
3378 "%": ModNode,
3379 "**": PowNode
3382 def binop_node(pos, operator, operand1, operand2):
3383 # Construct binop node of appropriate class for
3384 # given operator.
3385 return binop_node_classes[operator](pos,
3386 operator = operator,
3387 operand1 = operand1,
3388 operand2 = operand2)
3390 #-------------------------------------------------------------------
3392 # Coercion nodes
3394 # Coercion nodes are special in that they are created during
3395 # the analyse_types phase of parse tree processing.
3396 # Their __init__ methods consequently incorporate some aspects
3397 # of that phase.
3399 #-------------------------------------------------------------------
3401 class CoercionNode(ExprNode):
3402 # Abstract base class for coercion nodes.
3404 # arg ExprNode node being coerced
3406 subexprs = ['arg']
3408 def __init__(self, arg):
3409 self.pos = arg.pos
3410 self.arg = arg
3411 if debug_coercion:
3412 print self, "Coercing", self.arg
3415 class CastNode(CoercionNode):
3416 # Wrap a node in a C type cast.
3418 def __init__(self, arg, new_type):
3419 CoercionNode.__init__(self, arg)
3420 self.type = new_type
3422 def calculate_result_code(self):
3423 return self.arg.result_as(self.type)
3425 def generate_result_code(self, code):
3426 self.arg.generate_result_code(code)
3429 class PyTypeTestNode(CoercionNode):
3430 # This node is used to check that a generic Python
3431 # object is an instance of a particular extension type.
3432 # This node borrows the result of its argument node.
3434 def __init__(self, arg, dst_type, env):
3435 # The arg is know to be a Python object, and
3436 # the dst_type is known to be an extension type.
3437 assert dst_type.is_extension_type, "PyTypeTest on non extension type"
3438 CoercionNode.__init__(self, arg)
3439 self.type = dst_type
3440 self.result_ctype = arg.ctype()
3441 # env.use_utility_code(type_test_utility_code)
3442 self.gil_check(env)
3444 gil_message = "Python type test"
3446 def result_in_temp(self):
3447 return self.arg.result_in_temp()
3449 def is_ephemeral(self):
3450 return self.arg.is_ephemeral()
3452 def calculate_result_code(self):
3453 return self.arg.result()
3455 def generate_result_code(self, code):
3456 if self.type.typeobj_is_available():
3457 code.use_utility_code(type_test_utility_code)
3458 code.putln(
3459 "if (!__Pyx_TypeTest(%s, %s)) %s" % (
3460 self.arg.py_result(),
3461 self.type.typeptr_cname,
3462 code.error_goto(self.pos)))
3463 else:
3464 error(self.pos, "Cannot test type of extern C class "
3465 "without type object name specification")
3467 def generate_post_assignment_code(self, code):
3468 self.arg.generate_post_assignment_code(code)
3471 class CoerceToPyTypeNode(CoercionNode):
3472 # This node is used to convert a C data type
3473 # to a Python object.
3475 def __init__(self, arg, env):
3476 CoercionNode.__init__(self, arg)
3477 self.type = py_object_type
3478 self.gil_check(env)
3479 self.is_temp = 1
3480 if not arg.type.to_py_function:
3481 error(arg.pos,
3482 "Cannot convert '%s' to Python object" % arg.type)
3484 gil_message = "Converting to Python object"
3486 def generate_result_code(self, code):
3487 function = self.arg.type.to_py_function
3488 result = self.result()
3489 code.putln('%s = %s(%s); if (!%s) %s' % (
3490 result,
3491 function,
3492 self.arg.result(),
3493 result,
3494 code.error_goto(self.pos)))
3497 class CoerceFromPyTypeNode(CoercionNode):
3498 # This node is used to convert a Python object
3499 # to a C data type.
3501 def __init__(self, result_type, arg, env):
3502 CoercionNode.__init__(self, arg)
3503 self.type = result_type
3504 self.is_temp = 1
3505 if not result_type.from_py_function:
3506 error(arg.pos,
3507 "Cannot convert Python object to '%s'" % result_type)
3508 if self.type.is_string and self.arg.is_ephemeral():
3509 error(arg.pos,
3510 "Obtaining char * from temporary Python value")
3512 def generate_result_code(self, code):
3513 function = self.type.from_py_function
3514 operand = self.arg.py_result()
3515 rhs = "%s(%s)" % (function, operand)
3516 if self.type.is_enum:
3517 rhs = typecast(self.type, c_long_type, rhs)
3518 result = self.result()
3519 if self.type.is_string:
3520 err_code = "!%s" % result
3521 else:
3522 err_code = "PyErr_Occurred()"
3523 code.putln('%s = %s; if (%s) %s' % (
3524 result,
3525 rhs,
3526 err_code,
3527 code.error_goto(self.pos)))
3530 class CoerceToBooleanNode(CoercionNode):
3531 # This node is used when a result needs to be used
3532 # in a boolean context.
3534 def __init__(self, arg, env):
3535 CoercionNode.__init__(self, arg)
3536 self.type = PyrexTypes.c_int_type
3537 if arg.type.is_pyobject:
3538 if env.nogil:
3539 self.gil_error()
3540 self.is_temp = 1
3542 gil_message = "Truth-testing Python object"
3544 def check_const(self):
3545 if self.is_temp:
3546 self.not_const()
3547 self.arg.check_const()
3549 def calculate_result_code(self):
3550 return "(%s != 0)" % self.arg.result()
3552 def generate_result_code(self, code):
3553 if self.arg.type.is_pyobject:
3554 result = self.result()
3555 code.putln(
3556 "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % (
3557 result,
3558 self.arg.py_result(),
3559 result,
3560 code.error_goto(self.pos)))
3563 class CoerceToTempNode(CoercionNode):
3564 # This node is used to force the result of another node
3565 # to be stored in a temporary. It is only used if the
3566 # argument node's result is not already in a temporary.
3568 def __init__(self, arg, env):
3569 CoercionNode.__init__(self, arg)
3570 self.type = self.arg.type
3571 self.is_temp = 1
3572 if self.type.is_pyobject:
3573 self.gil_check(env)
3574 self.result_ctype = py_object_type
3576 gil_message = "Creating temporary Python reference"
3579 def generate_result_code(self, code):
3580 #self.arg.generate_evaluation_code(code) # Already done
3581 # by generic generate_subexpr_evaluation_code!
3582 code.putln("%s = %s;" % (
3583 self.result(), self.arg.result_as(self.ctype())))
3584 if self.type.is_pyobject:
3585 code.put_incref(self.py_result())
3588 class CloneNode(CoercionNode):
3589 # This node is employed when the result of another node needs
3590 # to be used multiple times. The argument node's result must
3591 # be in a temporary. This node "borrows" the result from the
3592 # argument node, and does not generate any evaluation or
3593 # disposal code for it. The original owner of the argument
3594 # node is responsible for doing those things.
3596 subexprs = [] # Arg is not considered a subexpr
3598 def __init__(self, arg):
3599 CoercionNode.__init__(self, arg)
3600 self.type = arg.type
3601 self.result_ctype = arg.result_ctype
3603 def calculate_result_code(self):
3604 return self.arg.result()
3606 def generate_evaluation_code(self, code):
3607 pass
3609 def generate_result_code(self, code):
3610 pass
3612 #------------------------------------------------------------------------------------
3614 # Runtime support code
3616 #------------------------------------------------------------------------------------
3618 get_name_utility_code = [
3619 """
3620 static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/
3621 ""","""
3622 static PyObject *__Pyx_GetName(PyObject *dict, char *name) {
3623 PyObject *result;
3624 result = PyObject_GetAttrString(dict, name);
3625 if (!result)
3626 PyErr_SetString(PyExc_NameError, name);
3627 return result;
3629 """]
3631 get_name_interned_utility_code = [
3632 """
3633 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
3634 ""","""
3635 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
3636 PyObject *result;
3637 result = PyObject_GetAttr(dict, name);
3638 if (!result)
3639 PyErr_SetObject(PyExc_NameError, name);
3640 return result;
3642 """]
3644 #------------------------------------------------------------------------------------
3646 import_utility_code = [
3647 """
3648 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
3649 ""","""
3650 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
3651 PyObject *__import__ = 0;
3652 PyObject *empty_list = 0;
3653 PyObject *module = 0;
3654 PyObject *global_dict = 0;
3655 PyObject *empty_dict = 0;
3656 PyObject *list;
3657 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
3658 if (!__import__)
3659 goto bad;
3660 if (from_list)
3661 list = from_list;
3662 else {
3663 empty_list = PyList_New(0);
3664 if (!empty_list)
3665 goto bad;
3666 list = empty_list;
3668 global_dict = PyModule_GetDict(%(GLOBALS)s);
3669 if (!global_dict)
3670 goto bad;
3671 empty_dict = PyDict_New();
3672 if (!empty_dict)
3673 goto bad;
3674 module = PyObject_CallFunction(__import__, "OOOO",
3675 name, global_dict, empty_dict, list);
3676 bad:
3677 Py_XDECREF(empty_list);
3678 Py_XDECREF(__import__);
3679 Py_XDECREF(empty_dict);
3680 return module;
3682 """ % {
3683 "BUILTINS": Naming.builtins_cname,
3684 "GLOBALS": Naming.module_cname,
3685 }]
3687 #------------------------------------------------------------------------------------
3689 #get_exception_utility_code = [
3690 #"""
3691 #static PyObject *__Pyx_GetExcValue(void); /*proto*/
3692 #""","""
3693 #static PyObject *__Pyx_GetExcValue(void) {
3694 # PyObject *type = 0, *value = 0, *tb = 0;
3695 # PyObject *result = 0;
3696 # PyThreadState *tstate = PyThreadState_Get();
3697 # PyErr_Fetch(&type, &value, &tb);
3698 # PyErr_NormalizeException(&type, &value, &tb);
3699 # if (PyErr_Occurred())
3700 # goto bad;
3701 # if (!value) {
3702 # value = Py_None;
3703 # Py_INCREF(value);
3704 # }
3705 # Py_XDECREF(tstate->exc_type);
3706 # Py_XDECREF(tstate->exc_value);
3707 # Py_XDECREF(tstate->exc_traceback);
3708 # tstate->exc_type = type;
3709 # tstate->exc_value = value;
3710 # tstate->exc_traceback = tb;
3711 # result = value;
3712 # Py_XINCREF(result);
3713 # type = 0;
3714 # value = 0;
3715 # tb = 0;
3716 #bad:
3717 # Py_XDECREF(type);
3718 # Py_XDECREF(value);
3719 # Py_XDECREF(tb);
3720 # return result;
3721 #}
3722 #"""]
3724 #------------------------------------------------------------------------------------
3726 unpacking_utility_code = [
3727 """
3728 static PyObject *__Pyx_UnpackItem(PyObject *); /*proto*/
3729 static int __Pyx_EndUnpack(PyObject *); /*proto*/
3730 ""","""
3731 static void __Pyx_UnpackError(void) {
3732 PyErr_SetString(PyExc_ValueError, "unpack sequence of wrong size");
3735 static PyObject *__Pyx_UnpackItem(PyObject *iter) {
3736 PyObject *item;
3737 if (!(item = PyIter_Next(iter))) {
3738 if (!PyErr_Occurred())
3739 __Pyx_UnpackError();
3741 return item;
3744 static int __Pyx_EndUnpack(PyObject *iter) {
3745 PyObject *item;
3746 if ((item = PyIter_Next(iter))) {
3747 Py_DECREF(item);
3748 __Pyx_UnpackError();
3749 return -1;
3751 else if (!PyErr_Occurred())
3752 return 0;
3753 else
3754 return -1;
3756 """]
3758 #------------------------------------------------------------------------------------
3760 type_test_utility_code = [
3761 """
3762 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
3763 ""","""
3764 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
3765 if (!type) {
3766 PyErr_Format(PyExc_SystemError, "Missing type object");
3767 return 0;
3769 if (obj == Py_None || PyObject_TypeCheck(obj, type))
3770 return 1;
3771 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
3772 obj->ob_type->tp_name, type->tp_name);
3773 return 0;
3775 """]
3777 #------------------------------------------------------------------------------------
3779 create_class_utility_code = [
3780 """
3781 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
3782 ""","""
3783 static PyObject *__Pyx_CreateClass(
3784 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
3786 PyObject *py_modname;
3787 PyObject *result = 0;
3789 py_modname = PyString_FromString(modname);
3790 if (!py_modname)
3791 goto bad;
3792 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
3793 goto bad;
3794 result = PyClass_New(bases, dict, name);
3795 bad:
3796 Py_XDECREF(py_modname);
3797 return result;
3799 """]
3801 #------------------------------------------------------------------------------------
3803 getitem_int_utility_code = [
3804 """
3805 static PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i); /*proto*/
3806 ""","""
3807 static PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i) {
3808 PyTypeObject *t = o->ob_type;
3809 PyObject *r;
3810 if (t->tp_as_sequence && t->tp_as_sequence->sq_item)
3811 r = PySequence_GetItem(o, i);
3812 else {
3813 PyObject *j = PyInt_FromLong(i);
3814 if (!j)
3815 return 0;
3816 r = PyObject_GetItem(o, j);
3817 Py_DECREF(j);
3819 return r;
3821 """]
3823 #------------------------------------------------------------------------------------
3825 setitem_int_utility_code = [
3826 """
3827 static int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v); /*proto*/
3828 ""","""
3829 static int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v) {
3830 PyTypeObject *t = o->ob_type;
3831 int r;
3832 if (t->tp_as_sequence && t->tp_as_sequence->sq_item)
3833 r = PySequence_SetItem(o, i, v);
3834 else {
3835 PyObject *j = PyInt_FromLong(i);
3836 if (!j)
3837 return -1;
3838 r = PyObject_SetItem(o, j, v);
3839 Py_DECREF(j);
3841 return r;
3843 """]