Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 1217:7e25b2f3f235
Coercion of dict to struct.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Tue Oct 07 20:18:12 2008 -0700 (3 years ago) |
| parents | 89a0907f44d1 |
| children | 51eb93696d35 |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
6 from string import join
8 from Errors import error, warning, InternalError
9 from Errors import hold_errors, release_errors, held_errors, report_error
10 import StringEncoding
11 import Naming
12 from Nodes import Node
13 import PyrexTypes
14 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
15 from Builtin import list_type, tuple_type, dict_type, unicode_type
16 import Symtab
17 import Options
18 from Annotate import AnnotationItem
20 from Cython.Debugging import print_call_chain
21 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
22 debug_coercion
25 class ExprNode(Node):
26 # subexprs [string] Class var holding names of subexpr node attrs
27 # type PyrexType Type of the result
28 # result_code string Code fragment
29 # result_ctype string C type of result_code if different from type
30 # is_temp boolean Result is in a temporary variable
31 # is_sequence_constructor
32 # boolean Is a list or tuple constructor expression
33 # saved_subexpr_nodes
34 # [ExprNode or [ExprNode or None] or None]
35 # Cached result of subexpr_nodes()
37 result_ctype = None
38 type = None
40 # The Analyse Expressions phase for expressions is split
41 # into two sub-phases:
42 #
43 # Analyse Types
44 # Determines the result type of the expression based
45 # on the types of its sub-expressions, and inserts
46 # coercion nodes into the expression tree where needed.
47 # Marks nodes which will need to have temporary variables
48 # allocated.
49 #
50 # Allocate Temps
51 # Allocates temporary variables where needed, and fills
52 # in the result_code field of each node.
53 #
54 # ExprNode provides some convenience routines which
55 # perform both of the above phases. These should only
56 # be called from statement nodes, and only when no
57 # coercion nodes need to be added around the expression
58 # being analysed. In that case, the above two phases
59 # should be invoked separately.
60 #
61 # Framework code in ExprNode provides much of the common
62 # processing for the various phases. It makes use of the
63 # 'subexprs' class attribute of ExprNodes, which should
64 # contain a list of the names of attributes which can
65 # hold sub-nodes or sequences of sub-nodes.
66 #
67 # The framework makes use of a number of abstract methods.
68 # Their responsibilities are as follows.
69 #
70 # Declaration Analysis phase
71 #
72 # analyse_target_declaration
73 # Called during the Analyse Declarations phase to analyse
74 # the LHS of an assignment or argument of a del statement.
75 # Nodes which cannot be the LHS of an assignment need not
76 # implement it.
77 #
78 # Expression Analysis phase
79 #
80 # analyse_types
81 # - Call analyse_types on all sub-expressions.
82 # - Check operand types, and wrap coercion nodes around
83 # sub-expressions where needed.
84 # - Set the type of this node.
85 # - If a temporary variable will be required for the
86 # result, set the is_temp flag of this node.
87 #
88 # analyse_target_types
89 # Called during the Analyse Types phase to analyse
90 # the LHS of an assignment or argument of a del
91 # statement. Similar responsibilities to analyse_types.
92 #
93 # allocate_temps
94 # - Call allocate_temps for all sub-nodes.
95 # - Call allocate_temp for this node.
96 # - If a temporary was allocated, call release_temp on
97 # all sub-expressions.
98 #
99 # allocate_target_temps
100 # - Call allocate_temps on sub-nodes and allocate any other
101 # temps used during assignment.
102 # - Fill in result_code with a C lvalue if needed.
103 # - If a rhs node is supplied, call release_temp on it.
104 # - Call release_temp on sub-nodes and release any other
105 # temps used during assignment.
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 # - Call generate_evaluation_code for sub-expressions.
133 # - Perform the functions of generate_result_code
134 # (see below).
135 # - If result is temporary, call generate_disposal_code
136 # on all sub-expressions.
137 #
138 # A default implementation of generate_evaluation_code
139 # is provided which uses the following abstract methods:
140 #
141 # generate_result_code
142 # - Generate any C statements necessary to calculate
143 # the result of this node from the results of its
144 # sub-expressions.
145 #
146 # calculate_result_code
147 # - Should return a C code fragment evaluating to the
148 # result. This is only called when the result is not
149 # a temporary.
150 #
151 # generate_assignment_code
152 # Called on the LHS of an assignment.
153 # - Call generate_evaluation_code for sub-expressions.
154 # - Generate code to perform the assignment.
155 # - If the assignment absorbed a reference, call
156 # generate_post_assignment_code on the RHS,
157 # otherwise call generate_disposal_code on it.
158 #
159 # generate_deletion_code
160 # Called on an argument of a del statement.
161 # - Call generate_evaluation_code for sub-expressions.
162 # - Generate code to perform the deletion.
163 # - Call generate_disposal_code on all sub-expressions.
164 #
165 #
167 is_sequence_constructor = 0
168 is_attribute = 0
170 saved_subexpr_nodes = None
171 is_temp = 0
172 is_target = 0
174 def get_child_attrs(self):
175 return self.subexprs
176 child_attrs = property(fget=get_child_attrs)
178 def not_implemented(self, method_name):
179 print_call_chain(method_name, "not implemented") ###
180 raise InternalError(
181 "%s.%s not implemented" %
182 (self.__class__.__name__, method_name))
184 def is_lvalue(self):
185 return 0
187 def is_ephemeral(self):
188 # An ephemeral node is one whose result is in
189 # a Python temporary and we suspect there are no
190 # other references to it. Certain operations are
191 # disallowed on such values, since they are
192 # likely to result in a dangling pointer.
193 return self.type.is_pyobject and self.is_temp
195 def subexpr_nodes(self):
196 # Extract a list of subexpression nodes based
197 # on the contents of the subexprs class attribute.
198 if self.saved_subexpr_nodes is None:
199 nodes = []
200 for name in self.subexprs:
201 item = getattr(self, name)
202 if item:
203 if isinstance(item, ExprNode):
204 nodes.append(item)
205 else:
206 nodes.extend(item)
207 self.saved_subexpr_nodes = nodes
208 return self.saved_subexpr_nodes
210 def result(self):
211 if not self.is_temp or self.is_target:
212 return self.calculate_result_code()
213 else: # i.e. self.is_temp:
214 return self.result_code
216 def result_as(self, type = None):
217 # Return the result code cast to the specified C type.
218 return typecast(type, self.ctype(), self.result())
220 def py_result(self):
221 # Return the result code cast to PyObject *.
222 return self.result_as(py_object_type)
224 def ctype(self):
225 # Return the native C type of the result (i.e. the
226 # C type of the result_code expression).
227 return self.result_ctype or self.type
229 def compile_time_value(self, denv):
230 # Return value of compile-time expression, or report error.
231 error(self.pos, "Invalid compile-time expression")
233 def compile_time_value_error(self, e):
234 error(self.pos, "Error in compile-time expression: %s: %s" % (
235 e.__class__.__name__, e))
237 # ------------- Declaration Analysis ----------------
239 def analyse_target_declaration(self, env):
240 error(self.pos, "Cannot assign to or delete this")
242 # ------------- Expression Analysis ----------------
244 def analyse_const_expression(self, env):
245 # Called during the analyse_declarations phase of a
246 # constant expression. Analyses the expression's type,
247 # checks whether it is a legal const expression,
248 # and determines its value.
249 self.analyse_types(env)
250 self.allocate_temps(env)
251 self.check_const()
253 def analyse_expressions(self, env):
254 # Convenience routine performing both the Type
255 # Analysis and Temp Allocation phases for a whole
256 # expression.
257 self.analyse_types(env)
258 self.allocate_temps(env)
260 def analyse_target_expression(self, env, rhs):
261 # Convenience routine performing both the Type
262 # Analysis and Temp Allocation phases for the LHS of
263 # an assignment.
264 self.analyse_target_types(env)
265 self.allocate_target_temps(env, rhs)
267 def analyse_boolean_expression(self, env):
268 # Analyse expression and coerce to a boolean.
269 self.analyse_types(env)
270 bool = self.coerce_to_boolean(env)
271 bool.allocate_temps(env)
272 return bool
274 def analyse_temp_boolean_expression(self, env):
275 # Analyse boolean expression and coerce result into
276 # a temporary. This is used when a branch is to be
277 # performed on the result and we won't have an
278 # opportunity to ensure disposal code is executed
279 # afterwards. By forcing the result into a temporary,
280 # we ensure that all disposal has been done by the
281 # time we get the result.
282 self.analyse_types(env)
283 bool = self.coerce_to_boolean(env)
284 temp_bool = bool.coerce_to_temp(env)
285 temp_bool.allocate_temps(env)
286 return temp_bool
288 # --------------- Type Analysis ------------------
290 def analyse_as_module(self, env):
291 # If this node can be interpreted as a reference to a
292 # cimported module, return its scope, else None.
293 return None
295 def analyse_as_type(self, env):
296 # If this node can be interpreted as a reference to a
297 # type, return that type, else None.
298 return None
300 def analyse_as_extension_type(self, env):
301 # If this node can be interpreted as a reference to an
302 # extension type, return its type, else None.
303 return None
305 def analyse_types(self, env):
306 self.not_implemented("analyse_types")
308 def analyse_target_types(self, env):
309 self.analyse_types(env)
311 def gil_assignment_check(self, env):
312 if env.nogil and self.type.is_pyobject:
313 error(self.pos, "Assignment of Python object not allowed without gil")
315 def check_const(self):
316 self.not_const()
318 def not_const(self):
319 error(self.pos, "Not allowed in a constant expression")
321 def check_const_addr(self):
322 self.addr_not_const()
324 def addr_not_const(self):
325 error(self.pos, "Address is not constant")
327 def gil_check(self, env):
328 if env.nogil and self.type.is_pyobject:
329 self.gil_error()
331 # ----------------- Result Allocation -----------------
333 def result_in_temp(self):
334 # Return true if result is in a temporary owned by
335 # this node or one of its subexpressions. Overridden
336 # by certain nodes which can share the result of
337 # a subnode.
338 return self.is_temp
340 def allocate_target_temps(self, env, rhs):
341 # Perform temp allocation for the LHS of an assignment.
342 if debug_temp_alloc:
343 print("%s Allocating target temps" % self)
344 self.allocate_subexpr_temps(env)
345 self.is_target = True
346 if rhs:
347 rhs.release_temp(env)
348 self.release_subexpr_temps(env)
350 def allocate_temps(self, env, result = None):
351 # Allocate temporary variables for this node and
352 # all its sub-expressions. If a result is specified,
353 # this must be a temp node and the specified variable
354 # is used as the result instead of allocating a new
355 # one.
356 if debug_temp_alloc:
357 print("%s Allocating temps" % self)
358 self.allocate_subexpr_temps(env)
359 self.allocate_temp(env, result)
360 if self.is_temp:
361 self.release_subexpr_temps(env)
363 def allocate_subexpr_temps(self, env):
364 # Allocate temporary variables for all sub-expressions
365 # of this node.
366 if debug_temp_alloc:
367 print("%s Allocating temps for: %s" % (self, self.subexprs))
368 for node in self.subexpr_nodes():
369 if node:
370 if debug_temp_alloc:
371 print("%s Allocating temps for %s" % (self, node))
372 node.allocate_temps(env)
374 def allocate_temp(self, env, result = None):
375 # If this node requires a temporary variable for its
376 # result, allocate one, otherwise set the result to
377 # a C code fragment. If a result is specified,
378 # this must be a temp node and the specified variable
379 # is used as the result instead of allocating a new
380 # one.
381 if debug_temp_alloc:
382 print("%s Allocating temp" % self)
383 if result:
384 if not self.is_temp:
385 raise InternalError("Result forced on non-temp node")
386 self.result_code = result
387 elif self.is_temp:
388 type = self.type
389 if not type.is_void:
390 if type.is_pyobject:
391 type = PyrexTypes.py_object_type
392 self.result_code = env.allocate_temp(type)
393 else:
394 self.result_code = None
395 if debug_temp_alloc:
396 print("%s Allocated result %s" % (self, self.result_code))
398 def target_code(self):
399 # Return code fragment for use as LHS of a C assignment.
400 return self.calculate_result_code()
402 def calculate_result_code(self):
403 self.not_implemented("calculate_result_code")
405 # def release_target_temp(self, env):
406 # # Release temporaries used by LHS of an assignment.
407 # self.release_subexpr_temps(env)
409 def release_temp(self, env):
410 # If this node owns a temporary result, release it,
411 # otherwise release results of its sub-expressions.
412 if self.is_temp:
413 if debug_temp_alloc:
414 print("%s Releasing result %s" % (self, self.result_code))
415 env.release_temp(self.result_code)
416 else:
417 self.release_subexpr_temps(env)
419 def release_subexpr_temps(self, env):
420 # Release the results of all sub-expressions of
421 # this node.
422 for node in self.subexpr_nodes():
423 if node:
424 node.release_temp(env)
426 # ---------------- Code Generation -----------------
428 def make_owned_reference(self, code):
429 # If result is a pyobject, make sure we own
430 # a reference to it.
431 if self.type.is_pyobject and not self.result_in_temp():
432 code.put_incref(self.result(), self.ctype())
434 def generate_evaluation_code(self, code):
435 code.mark_pos(self.pos)
436 # Generate code to evaluate this node and
437 # its sub-expressions, and dispose of any
438 # temporary results of its sub-expressions.
439 self.generate_subexpr_evaluation_code(code)
440 self.pre_generate_result_code(code)
441 self.generate_result_code(code)
442 if self.is_temp:
443 self.generate_subexpr_disposal_code(code)
445 def pre_generate_result_code(self, code):
446 pass
448 def generate_subexpr_evaluation_code(self, code):
449 for node in self.subexpr_nodes():
450 node.generate_evaluation_code(code)
452 def generate_result_code(self, code):
453 self.not_implemented("generate_result_code")
455 def generate_disposal_code(self, code):
456 # If necessary, generate code to dispose of
457 # temporary Python reference.
458 if self.is_temp:
459 if self.type.is_pyobject:
460 code.put_decref_clear(self.result(), self.ctype())
461 else:
462 self.generate_subexpr_disposal_code(code)
464 def generate_subexpr_disposal_code(self, code):
465 # Generate code to dispose of temporary results
466 # of all sub-expressions.
467 for node in self.subexpr_nodes():
468 node.generate_disposal_code(code)
470 def generate_post_assignment_code(self, code):
471 # Same as generate_disposal_code except that
472 # assignment will have absorbed a reference to
473 # the result if it is a Python object.
474 if self.is_temp:
475 if self.type.is_pyobject:
476 code.putln("%s = 0;" % self.result())
477 else:
478 self.generate_subexpr_disposal_code(code)
480 def generate_assignment_code(self, rhs, code):
481 # Stub method for nodes which are not legal as
482 # the LHS of an assignment. An error will have
483 # been reported earlier.
484 pass
486 def generate_deletion_code(self, code):
487 # Stub method for nodes that are not legal as
488 # the argument of a del statement. An error
489 # will have been reported earlier.
490 pass
492 # ---------------- Annotation ---------------------
494 def annotate(self, code):
495 for node in self.subexpr_nodes():
496 node.annotate(code)
498 # ----------------- Coercion ----------------------
500 def coerce_to(self, dst_type, env):
501 # Coerce the result so that it can be assigned to
502 # something of type dst_type. If processing is necessary,
503 # wraps this node in a coercion node and returns that.
504 # Otherwise, returns this node unchanged.
505 #
506 # This method is called during the analyse_expressions
507 # phase of the src_node's processing.
508 src = self
509 src_type = self.type
510 src_is_py_type = src_type.is_pyobject
511 dst_is_py_type = dst_type.is_pyobject
513 if dst_type.is_pyobject:
514 if not src.type.is_pyobject:
515 src = CoerceToPyTypeNode(src, env)
516 if not src.type.subtype_of(dst_type):
517 if not isinstance(src, NoneNode):
518 src = PyTypeTestNode(src, dst_type, env)
519 elif src.type.is_pyobject:
520 src = CoerceFromPyTypeNode(dst_type, src, env)
521 else: # neither src nor dst are py types
522 # Added the string comparison, since for c types that
523 # is enough, but Cython gets confused when the types are
524 # in different files.
525 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
526 error(self.pos, "Cannot assign type '%s' to '%s'" %
527 (src.type, dst_type))
528 return src
530 def coerce_to_pyobject(self, env):
531 return self.coerce_to(PyrexTypes.py_object_type, env)
533 def coerce_to_boolean(self, env):
534 # Coerce result to something acceptable as
535 # a boolean value.
536 type = self.type
537 if type.is_pyobject or type.is_ptr or type.is_float:
538 return CoerceToBooleanNode(self, env)
539 else:
540 if not type.is_int and not type.is_error:
541 error(self.pos,
542 "Type '%s' not acceptable as a boolean" % type)
543 return self
545 def coerce_to_integer(self, env):
546 # If not already some C integer type, coerce to longint.
547 if self.type.is_int:
548 return self
549 else:
550 return self.coerce_to(PyrexTypes.c_long_type, env)
552 def coerce_to_temp(self, env):
553 # Ensure that the result is in a temporary.
554 if self.result_in_temp():
555 return self
556 else:
557 return CoerceToTempNode(self, env)
559 def coerce_to_simple(self, env):
560 # Ensure that the result is simple (see is_simple).
561 if self.is_simple():
562 return self
563 else:
564 return self.coerce_to_temp(env)
566 def is_simple(self):
567 # A node is simple if its result is something that can
568 # be referred to without performing any operations, e.g.
569 # a constant, local var, C global var, struct member
570 # reference, or temporary.
571 return self.result_in_temp()
573 def magic_cython_method(self):
574 return None
577 class NewTempExprNode(ExprNode):
578 backwards_compatible_result = None
580 def result(self):
581 if self.is_temp:
582 return self.temp_code
583 else:
584 return self.calculate_result_code()
586 def allocate_target_temps(self, env, rhs):
587 self.allocate_subexpr_temps(env)
588 rhs.release_temp(rhs)
589 self.release_subexpr_temps(env)
591 def allocate_temps(self, env, result = None):
592 self.allocate_subexpr_temps(env)
593 self.backwards_compatible_result = result
594 if self.is_temp:
595 self.release_subexpr_temps(env)
597 def allocate_temp(self, env, result = None):
598 assert result is None
600 def release_temp(self, env):
601 pass
603 def pre_generate_result_code(self, code):
604 if self.is_temp:
605 type = self.type
606 if not type.is_void:
607 if type.is_pyobject:
608 type = PyrexTypes.py_object_type
609 if self.backwards_compatible_result:
610 self.temp_code = self.backwards_compatible_result
611 else:
612 self.temp_code = code.funcstate.allocate_temp(type)
613 else:
614 self.temp_code = None
616 def generate_disposal_code(self, code):
617 if self.is_temp:
618 if self.type.is_pyobject:
619 code.put_decref_clear(self.result(), self.ctype())
620 if not self.backwards_compatible_result:
621 code.funcstate.release_temp(self.temp_code)
622 else:
623 self.generate_subexpr_disposal_code(code)
625 def generate_post_assignment_code(self, code):
626 if self.is_temp:
627 if self.type.is_pyobject:
628 code.putln("%s = 0;" % self.temp_code)
629 if not self.backwards_compatible_result:
630 code.funcstate.release_temp(self.temp_code)
631 else:
632 self.generate_subexpr_disposal_code(code)
637 class AtomicExprNode(ExprNode):
638 # Abstract base class for expression nodes which have
639 # no sub-expressions.
641 subexprs = []
644 class PyConstNode(AtomicExprNode):
645 # Abstract base class for constant Python values.
647 is_literal = 1
649 def is_simple(self):
650 return 1
652 def analyse_types(self, env):
653 self.type = py_object_type
655 def calculate_result_code(self):
656 return self.value
658 def generate_result_code(self, code):
659 pass
662 class NoneNode(PyConstNode):
663 # The constant value None
665 value = "Py_None"
667 def compile_time_value(self, denv):
668 return None
670 class EllipsisNode(PyConstNode):
671 # '...' in a subscript list.
673 value = "Py_Ellipsis"
675 def compile_time_value(self, denv):
676 return Ellipsis
679 class ConstNode(AtomicExprNode):
680 # Abstract base type for literal constant nodes.
681 #
682 # value string C code fragment
684 is_literal = 1
686 def is_simple(self):
687 return 1
689 def analyse_types(self, env):
690 pass # Types are held in class variables
692 def check_const(self):
693 pass
695 def calculate_result_code(self):
696 return str(self.value)
698 def generate_result_code(self, code):
699 pass
702 class BoolNode(ConstNode):
703 type = PyrexTypes.c_bint_type
704 # The constant value True or False
706 def compile_time_value(self, denv):
707 return self.value
709 def calculate_result_code(self):
710 return str(int(self.value))
712 class NullNode(ConstNode):
713 type = PyrexTypes.c_null_ptr_type
714 value = "NULL"
717 class CharNode(ConstNode):
718 type = PyrexTypes.c_char_type
720 def compile_time_value(self, denv):
721 return ord(self.value)
723 def calculate_result_code(self):
724 return "'%s'" % StringEncoding.escape_character(self.value)
727 class IntNode(ConstNode):
729 # unsigned "" or "U"
730 # longness "" or "L" or "LL"
732 unsigned = ""
733 longness = ""
734 type = PyrexTypes.c_long_type
736 def coerce_to(self, dst_type, env):
737 if dst_type.is_numeric:
738 self.type = PyrexTypes.c_long_type
739 return self
740 # Arrange for a Python version of the number to be pre-allocated
741 # when coercing to a Python type.
742 if dst_type.is_pyobject:
743 self.entry = env.get_py_num(self.value, self.longness)
744 self.type = PyrexTypes.py_object_type
745 # We still need to perform normal coerce_to processing on the
746 # result, because we might be coercing to an extension type,
747 # in which case a type test node will be needed.
748 return ConstNode.coerce_to(self, dst_type, env)
750 def calculate_result_code(self):
751 if self.type.is_pyobject:
752 return self.entry.cname
753 else:
754 return str(self.value) + self.unsigned + self.longness
756 def compile_time_value(self, denv):
757 return int(self.value, 0)
760 class FloatNode(ConstNode):
761 type = PyrexTypes.c_double_type
763 def compile_time_value(self, denv):
764 return float(self.value)
766 def calculate_result_code(self):
767 strval = str(self.value)
768 if strval == 'nan':
769 return "(Py_HUGE_VAL * 0)"
770 elif strval == 'inf':
771 return "Py_HUGE_VAL"
772 elif strval == '-inf':
773 return "(-Py_HUGE_VAL)"
774 else:
775 return strval
778 class StringNode(ConstNode):
779 # entry Symtab.Entry
781 type = PyrexTypes.c_char_ptr_type
783 def compile_time_value(self, denv):
784 return self.value
786 def analyse_types(self, env):
787 self.entry = env.add_string_const(self.value)
789 def analyse_as_type(self, env):
790 type = PyrexTypes.parse_basic_type(self.value)
791 if type is not None:
792 return type
793 from TreeFragment import TreeFragment
794 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
795 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
796 sizeof_node = declaration.root.stats[0].expr
797 sizeof_node.analyse_types(env)
798 if isinstance(sizeof_node, SizeofTypeNode):
799 return sizeof_node.arg_type
801 def coerce_to(self, dst_type, env):
802 if dst_type == PyrexTypes.c_char_ptr_type:
803 self.type = PyrexTypes.c_char_ptr_type
804 return self
806 if dst_type.is_int:
807 if not self.type.is_pyobject and len(self.entry.init) == 1:
808 return CharNode(self.pos, value=self.value)
809 else:
810 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
811 return self
812 # Arrange for a Python version of the string to be pre-allocated
813 # when coercing to a Python type.
814 if dst_type.is_pyobject and not self.type.is_pyobject:
815 node = self.as_py_string_node(env)
816 else:
817 node = self
818 # We still need to perform normal coerce_to processing on the
819 # result, because we might be coercing to an extension type,
820 # in which case a type test node will be needed.
821 return ConstNode.coerce_to(node, dst_type, env)
823 def as_py_string_node(self, env):
824 # Return a new StringNode with the same entry as this node
825 # but whose type is a Python type instead of a C type.
826 entry = self.entry
827 env.add_py_string(entry)
828 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
830 def calculate_result_code(self):
831 if self.type.is_pyobject:
832 return self.entry.pystring_cname
833 else:
834 return self.entry.cname
837 class UnicodeNode(PyConstNode):
838 # entry Symtab.Entry
840 type = unicode_type
842 def analyse_types(self, env):
843 self.entry = env.add_string_const(self.value)
844 env.add_py_string(self.entry)
846 def calculate_result_code(self):
847 return self.entry.pystring_cname
849 def _coerce_to(self, dst_type, env):
850 if not dst_type.is_pyobject:
851 node = StringNode(self.pos, entry = entry, type = py_object_type)
852 return ConstNode.coerce_to(node, dst_type, env)
853 else:
854 return self
855 # We still need to perform normal coerce_to processing on the
856 # result, because we might be coercing to an extension type,
857 # in which case a type test node will be needed.
859 def compile_time_value(self, env):
860 return self.value
863 class IdentifierStringNode(ConstNode):
864 # A Python string that behaves like an identifier, e.g. for
865 # keyword arguments in a call, or for imported names
866 type = PyrexTypes.py_object_type
868 def analyse_types(self, env):
869 self.cname = env.intern_identifier(self.value)
871 def calculate_result_code(self):
872 return self.cname
875 class LongNode(AtomicExprNode):
876 # Python long integer literal
877 #
878 # value string
880 def compile_time_value(self, denv):
881 return long(self.value)
883 gil_message = "Constructing Python long int"
885 def analyse_types(self, env):
886 self.type = py_object_type
887 self.gil_check(env)
888 self.is_temp = 1
890 gil_message = "Constructing Python long int"
892 def generate_evaluation_code(self, code):
893 code.putln(
894 '%s = PyLong_FromString("%s", 0, 0); %s' % (
895 self.result(),
896 self.value,
897 code.error_goto_if_null(self.result(), self.pos)))
900 class ImagNode(AtomicExprNode):
901 # Imaginary number literal
902 #
903 # value float imaginary part
905 def compile_time_value(self, denv):
906 return complex(0.0, self.value)
908 def analyse_types(self, env):
909 self.type = py_object_type
910 self.gil_check(env)
911 self.is_temp = 1
913 gil_message = "Constructing complex number"
915 def generate_evaluation_code(self, code):
916 code.putln(
917 "%s = PyComplex_FromDoubles(0.0, %s); %s" % (
918 self.result(),
919 self.value,
920 code.error_goto_if_null(self.result(), self.pos)))
923 class NameNode(AtomicExprNode):
924 # Reference to a local or global variable name.
925 #
926 # name string Python name of the variable
927 #
928 # entry Entry Symbol table entry
929 # interned_cname string
931 is_name = True
932 is_cython_module = False
933 cython_attribute = None
934 skip_assignment_decref = False
935 entry = None
937 def create_analysed_rvalue(pos, env, entry):
938 node = NameNode(pos)
939 node.analyse_types(env, entry=entry)
940 return node
942 def magic_cython_method(self):
943 return self.cython_attribute
945 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
947 def compile_time_value(self, denv):
948 try:
949 return denv.lookup(self.name)
950 except KeyError:
951 error(self.pos, "Compile-time name '%s' not defined" % self.name)
953 def coerce_to(self, dst_type, env):
954 # If coercing to a generic pyobject and this is a builtin
955 # C function with a Python equivalent, manufacture a NameNode
956 # referring to the Python builtin.
957 #print "NameNode.coerce_to:", self.name, dst_type ###
958 if dst_type is py_object_type:
959 entry = self.entry
960 if entry and entry.is_cfunction:
961 var_entry = entry.as_variable
962 if var_entry:
963 if var_entry.is_builtin and Options.cache_builtins:
964 var_entry = env.declare_builtin(var_entry.name, self.pos)
965 node = NameNode(self.pos, name = self.name)
966 node.entry = var_entry
967 node.analyse_rvalue_entry(env)
968 return node
969 return AtomicExprNode.coerce_to(self, dst_type, env)
971 def analyse_as_module(self, env):
972 # Try to interpret this as a reference to a cimported module.
973 # Returns the module scope, or None.
974 entry = self.entry
975 if not entry:
976 entry = env.lookup(self.name)
977 if entry and entry.as_module:
978 return entry.as_module
979 return None
981 def analyse_as_type(self, env):
982 type = PyrexTypes.parse_basic_type(self.name)
983 if type:
984 return type
985 entry = self.entry
986 if not entry:
987 entry = env.lookup(self.name)
988 if entry and entry.is_type:
989 return entry.type
990 else:
991 return None
993 def analyse_as_extension_type(self, env):
994 # Try to interpret this as a reference to an extension type.
995 # Returns the extension type, or None.
996 entry = self.entry
997 if not entry:
998 entry = env.lookup(self.name)
999 if entry and entry.is_type and entry.type.is_extension_type:
1000 return entry.type
1001 else:
1002 return None
1004 def analyse_target_declaration(self, env):
1005 if not self.entry:
1006 self.entry = env.lookup_here(self.name)
1007 if not self.entry:
1008 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1009 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1010 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1011 if self.entry.is_declared_generic:
1012 self.result_ctype = py_object_type
1014 def analyse_types(self, env):
1015 if self.entry is None:
1016 self.entry = env.lookup(self.name)
1017 if not self.entry:
1018 self.entry = env.declare_builtin(self.name, self.pos)
1019 if not self.entry:
1020 self.type = PyrexTypes.error_type
1021 return
1022 self.analyse_rvalue_entry(env)
1024 def analyse_target_types(self, env):
1025 self.analyse_entry(env)
1026 if not self.is_lvalue():
1027 error(self.pos, "Assignment to non-lvalue '%s'"
1028 % self.name)
1029 self.type = PyrexTypes.error_type
1030 self.entry.used = 1
1031 if self.entry.type.is_buffer:
1032 import Buffer
1033 Buffer.used_buffer_aux_vars(self.entry)
1035 def analyse_rvalue_entry(self, env):
1036 #print "NameNode.analyse_rvalue_entry:", self.name ###
1037 #print "Entry:", self.entry.__dict__ ###
1038 self.analyse_entry(env)
1039 entry = self.entry
1040 if entry.is_declared_generic:
1041 self.result_ctype = py_object_type
1042 if entry.is_pyglobal or entry.is_builtin:
1043 if Options.cache_builtins and entry.is_builtin:
1044 self.is_temp = 0
1045 else:
1046 self.is_temp = 1
1047 env.use_utility_code(get_name_interned_utility_code)
1048 self.gil_check(env)
1050 gil_message = "Accessing Python global or builtin"
1052 def analyse_entry(self, env):
1053 #print "NameNode.analyse_entry:", self.name ###
1054 self.check_identifier_kind()
1055 entry = self.entry
1056 type = entry.type
1057 self.type = type
1058 if entry.is_pyglobal or entry.is_builtin:
1059 assert type.is_pyobject, "Python global or builtin not a Python object"
1060 self.interned_cname = self.entry.interned_cname = \
1061 env.intern_identifier(self.entry.name)
1063 def check_identifier_kind(self):
1064 #print "NameNode.check_identifier_kind:", self.entry.name ###
1065 #print self.entry.__dict__ ###
1066 entry = self.entry
1067 #entry.used = 1
1068 if not (entry.is_const or entry.is_variable
1069 or entry.is_builtin or entry.is_cfunction):
1070 if self.entry.as_variable:
1071 self.entry = self.entry.as_variable
1072 else:
1073 error(self.pos,
1074 "'%s' is not a constant, variable or function identifier" % self.name)
1076 def is_simple(self):
1077 # If it's not a C variable, it'll be in a temp.
1078 return 1
1080 def calculate_target_results(self, env):
1081 pass
1083 def check_const(self):
1084 entry = self.entry
1085 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1086 self.not_const()
1088 def check_const_addr(self):
1089 entry = self.entry
1090 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1091 self.addr_not_const()
1093 def is_lvalue(self):
1094 return self.entry.is_variable and \
1095 not self.entry.type.is_array and \
1096 not self.entry.is_readonly
1098 def is_ephemeral(self):
1099 # Name nodes are never ephemeral, even if the
1100 # result is in a temporary.
1101 return 0
1103 def allocate_temp(self, env, result = None):
1104 AtomicExprNode.allocate_temp(self, env, result)
1105 entry = self.entry
1106 if entry:
1107 entry.used = 1
1108 if entry.type.is_buffer:
1109 import Buffer
1110 Buffer.used_buffer_aux_vars(entry)
1111 if entry.utility_code:
1112 env.use_utility_code(entry.utility_code)
1114 def calculate_result_code(self):
1115 entry = self.entry
1116 if not entry:
1117 return "<error>" # There was an error earlier
1118 return entry.cname
1120 def generate_result_code(self, code):
1121 assert hasattr(self, 'entry')
1122 entry = self.entry
1123 if entry is None:
1124 return # There was an error earlier
1125 if entry.is_builtin and Options.cache_builtins:
1126 return # Lookup already cached
1127 elif entry.is_pyglobal or entry.is_builtin:
1128 if entry.is_builtin:
1129 namespace = Naming.builtins_cname
1130 else: # entry.is_pyglobal
1131 namespace = entry.scope.namespace_cname
1132 code.putln(
1133 '%s = __Pyx_GetName(%s, %s); %s' % (
1134 self.result(),
1135 namespace,
1136 self.interned_cname,
1137 code.error_goto_if_null(self.result(), self.pos)))
1138 elif entry.is_local and False:
1139 # control flow not good enough yet
1140 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1141 if assigned is False:
1142 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1143 elif not Options.init_local_none and assigned is None:
1144 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
1145 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1147 def generate_assignment_code(self, rhs, code):
1148 #print "NameNode.generate_assignment_code:", self.name ###
1149 entry = self.entry
1150 if entry is None:
1151 return # There was an error earlier
1153 # is_pyglobal seems to be True for module level-globals only.
1154 # We use this to access class->tp_dict if necessary.
1155 if entry.is_pyglobal:
1156 namespace = self.entry.scope.namespace_cname
1157 if entry.is_member:
1158 # if the entry is a member we have to cheat: SetAttr does not work
1159 # on types, so we create a descriptor which is then added to tp_dict
1160 code.put_error_if_neg(self.pos,
1161 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1162 namespace,
1163 self.interned_cname,
1164 rhs.py_result()))
1165 # in Py2.6+, we need to invalidate the method cache
1166 code.putln("PyType_Modified(%s);" %
1167 entry.scope.parent_type.typeptr_cname)
1168 else:
1169 code.put_error_if_neg(self.pos,
1170 'PyObject_SetAttr(%s, %s, %s)' % (
1171 namespace,
1172 self.interned_cname,
1173 rhs.py_result()))
1174 if debug_disposal_code:
1175 print("NameNode.generate_assignment_code:")
1176 print("...generating disposal code for %s" % rhs)
1177 rhs.generate_disposal_code(code)
1179 else:
1180 if self.type.is_buffer:
1181 # Generate code for doing the buffer release/acquisition.
1182 # This might raise an exception in which case the assignment (done
1183 # below) will not happen.
1184 #
1185 # The reason this is not in a typetest-like node is because the
1186 # variables that the acquired buffer info is stored to is allocated
1187 # per entry and coupled with it.
1188 self.generate_acquire_buffer(rhs, code)
1190 if self.type.is_pyobject:
1191 rhs.make_owned_reference(code)
1192 #print "NameNode.generate_assignment_code: to", self.name ###
1193 #print "...from", rhs ###
1194 #print "...LHS type", self.type, "ctype", self.ctype() ###
1195 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1196 if not self.skip_assignment_decref:
1197 if entry.is_local and not Options.init_local_none:
1198 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1199 if initalized is True:
1200 code.put_decref(self.result(), self.ctype())
1201 elif initalized is None:
1202 code.put_xdecref(self.result(), self.ctype())
1203 else:
1204 code.put_decref(self.result(), self.ctype())
1205 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1206 if debug_disposal_code:
1207 print("NameNode.generate_assignment_code:")
1208 print("...generating post-assignment code for %s" % rhs)
1209 rhs.generate_post_assignment_code(code)
1211 def generate_acquire_buffer(self, rhs, code):
1212 rhstmp = code.funcstate.allocate_temp(self.entry.type)
1213 buffer_aux = self.entry.buffer_aux
1214 bufstruct = buffer_aux.buffer_info_var.cname
1215 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1217 import Buffer
1218 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1219 is_initialized=not self.skip_assignment_decref,
1220 pos=self.pos, code=code)
1221 code.putln("%s = 0;" % rhstmp)
1222 code.funcstate.release_temp(rhstmp)
1224 def generate_deletion_code(self, code):
1225 if self.entry is None:
1226 return # There was an error earlier
1227 if not self.entry.is_pyglobal:
1228 error(self.pos, "Deletion of local or C global name not supported")
1229 return
1230 code.put_error_if_neg(self.pos,
1231 'PyObject_DelAttrString(%s, "%s")' % (
1232 Naming.module_cname,
1233 self.entry.name))
1235 def annotate(self, code):
1236 if hasattr(self, 'is_called') and self.is_called:
1237 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1238 if self.type.is_pyobject:
1239 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1240 else:
1241 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1243 class BackquoteNode(ExprNode):
1244 # `expr`
1245 #
1246 # arg ExprNode
1248 subexprs = ['arg']
1250 def analyse_types(self, env):
1251 self.arg.analyse_types(env)
1252 self.arg = self.arg.coerce_to_pyobject(env)
1253 self.type = py_object_type
1254 self.gil_check(env)
1255 self.is_temp = 1
1257 gil_message = "Backquote expression"
1259 def generate_result_code(self, code):
1260 code.putln(
1261 "%s = PyObject_Repr(%s); %s" % (
1262 self.result(),
1263 self.arg.py_result(),
1264 code.error_goto_if_null(self.result(), self.pos)))
1267 class ImportNode(ExprNode):
1268 # Used as part of import statement implementation.
1269 # Implements result =
1270 # __import__(module_name, globals(), None, name_list)
1271 #
1272 # module_name IdentifierStringNode dotted name of module
1273 # name_list ListNode or None list of names to be imported
1275 subexprs = ['module_name', 'name_list']
1277 def analyse_types(self, env):
1278 self.module_name.analyse_types(env)
1279 self.module_name = self.module_name.coerce_to_pyobject(env)
1280 if self.name_list:
1281 self.name_list.analyse_types(env)
1282 self.name_list.coerce_to_pyobject(env)
1283 self.type = py_object_type
1284 self.gil_check(env)
1285 self.is_temp = 1
1286 env.use_utility_code(import_utility_code)
1288 gil_message = "Python import"
1290 def generate_result_code(self, code):
1291 if self.name_list:
1292 name_list_code = self.name_list.py_result()
1293 else:
1294 name_list_code = "0"
1295 code.putln(
1296 "%s = __Pyx_Import(%s, %s); %s" % (
1297 self.result(),
1298 self.module_name.py_result(),
1299 name_list_code,
1300 code.error_goto_if_null(self.result(), self.pos)))
1303 class IteratorNode(ExprNode):
1304 # Used as part of for statement implementation.
1305 # Implements result = iter(sequence)
1306 #
1307 # sequence ExprNode
1309 subexprs = ['sequence']
1311 def analyse_types(self, env):
1312 self.sequence.analyse_types(env)
1313 self.sequence = self.sequence.coerce_to_pyobject(env)
1314 self.type = py_object_type
1315 self.gil_check(env)
1316 self.is_temp = 1
1318 self.counter = TempNode(self.pos, PyrexTypes.c_py_ssize_t_type, env)
1319 self.counter.allocate_temp(env)
1321 gil_message = "Iterating over Python object"
1323 def release_temp(self, env):
1324 env.release_temp(self.result())
1325 self.counter.release_temp(env)
1327 def generate_result_code(self, code):
1328 code.putln(
1329 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1330 self.sequence.py_result(),
1331 self.sequence.py_result()))
1332 code.putln(
1333 "%s = 0; %s = %s; Py_INCREF(%s);" % (
1334 self.counter.result(),
1335 self.result(),
1336 self.sequence.py_result(),
1337 self.result()))
1338 code.putln("} else {")
1339 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1340 self.counter.result(),
1341 self.result(),
1342 self.sequence.py_result(),
1343 code.error_goto_if_null(self.result(), self.pos)))
1344 code.putln("}")
1347 class NextNode(AtomicExprNode):
1348 # Used as part of for statement implementation.
1349 # Implements result = iterator.next()
1350 # Created during analyse_types phase.
1351 # The iterator is not owned by this node.
1352 #
1353 # iterator ExprNode
1355 def __init__(self, iterator, env):
1356 self.pos = iterator.pos
1357 self.iterator = iterator
1358 self.type = py_object_type
1359 self.is_temp = 1
1361 def generate_result_code(self, code):
1362 for py_type in ["List", "Tuple"]:
1363 code.putln(
1364 "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
1365 code.putln(
1366 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1367 self.iterator.counter.result(),
1368 py_type,
1369 self.iterator.py_result()))
1370 code.putln(
1371 "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
1372 self.result(),
1373 py_type,
1374 self.iterator.py_result(),
1375 self.iterator.counter.result(),
1376 self.result(),
1377 self.iterator.counter.result()))
1378 code.put("} else ")
1379 code.putln("{")
1380 code.putln(
1381 "%s = PyIter_Next(%s);" % (
1382 self.result(),
1383 self.iterator.py_result()))
1384 code.putln(
1385 "if (!%s) {" %
1386 self.result())
1387 code.putln(code.error_goto_if_PyErr(self.pos))
1388 code.putln("break;")
1389 code.putln("}")
1390 code.putln("}")
1393 class ExcValueNode(AtomicExprNode):
1394 # Node created during analyse_types phase
1395 # of an ExceptClauseNode to fetch the current
1396 # exception value.
1398 def __init__(self, pos, env, var):
1399 ExprNode.__init__(self, pos)
1400 self.type = py_object_type
1401 self.var = var
1403 def calculate_result_code(self):
1404 return self.var
1406 def generate_result_code(self, code):
1407 pass
1409 def analyse_types(self, env):
1410 pass
1413 class TempNode(AtomicExprNode):
1414 # Node created during analyse_types phase
1415 # of some nodes to hold a temporary value.
1417 def __init__(self, pos, type, env):
1418 ExprNode.__init__(self, pos)
1419 self.type = type
1420 if type.is_pyobject:
1421 self.result_ctype = py_object_type
1422 self.is_temp = 1
1424 def analyse_types(self, env):
1425 return self.type
1427 def generate_result_code(self, code):
1428 pass
1431 class PyTempNode(TempNode):
1432 # TempNode holding a Python value.
1434 def __init__(self, pos, env):
1435 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1438 #-------------------------------------------------------------------
1439 #
1440 # Trailer nodes
1441 #
1442 #-------------------------------------------------------------------
1444 class IndexNode(ExprNode):
1445 # Sequence indexing.
1446 #
1447 # base ExprNode
1448 # index ExprNode
1449 # indices [ExprNode]
1450 # is_buffer_access boolean Whether this is a buffer access.
1451 #
1452 # indices is used on buffer access, index on non-buffer access.
1453 # The former contains a clean list of index parameters, the
1454 # latter whatever Python object is needed for index access.
1456 subexprs = ['base', 'index', 'indices']
1457 indices = None
1459 def __init__(self, pos, index, *args, **kw):
1460 ExprNode.__init__(self, pos, index=index, *args, **kw)
1461 self._index = index
1463 def compile_time_value(self, denv):
1464 base = self.base.compile_time_value(denv)
1465 index = self.index.compile_time_value(denv)
1466 try:
1467 return base[index]
1468 except Exception, e:
1469 self.compile_time_value_error(e)
1471 def is_ephemeral(self):
1472 return self.base.is_ephemeral()
1474 def analyse_target_declaration(self, env):
1475 pass
1477 def analyse_as_type(self, env):
1478 base_type = self.base.analyse_as_type(env)
1479 if base_type and not base_type.is_pyobject:
1480 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1481 return None
1483 def analyse_types(self, env):
1484 self.analyse_base_and_index_types(env, getting = 1)
1486 def analyse_target_types(self, env):
1487 self.analyse_base_and_index_types(env, setting = 1)
1489 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1490 # Note: This might be cleaned up by having IndexNode
1491 # parsed in a saner way and only construct the tuple if
1492 # needed.
1494 # Note that this function must leave IndexNode in a cloneable state.
1495 # For buffers, self.index is packed out on the initial analysis, and
1496 # when cloning self.indices is copied.
1497 self.is_buffer_access = False
1499 self.base.analyse_types(env)
1500 # Handle the case where base is a literal char* (and we expect a string, not an int)
1501 if isinstance(self.base, StringNode):
1502 self.base = self.base.coerce_to_pyobject(env)
1504 skip_child_analysis = False
1505 buffer_access = False
1506 if self.base.type.is_buffer:
1507 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1508 if self.indices:
1509 indices = self.indices
1510 else:
1511 # On cloning, indices is cloned. Otherwise, unpack index into indices
1512 assert not isinstance(self.index, CloneNode)
1513 if isinstance(self.index, TupleNode):
1514 indices = self.index.args
1515 else:
1516 indices = [self.index]
1517 if len(indices) == self.base.type.ndim:
1518 buffer_access = True
1519 skip_child_analysis = True
1520 for x in indices:
1521 x.analyse_types(env)
1522 if not x.type.is_int:
1523 buffer_access = False
1525 if buffer_access:
1526 self.indices = indices
1527 self.index = None
1528 self.type = self.base.type.dtype
1529 self.is_buffer_access = True
1530 self.buffer_type = self.base.entry.type
1532 if getting and self.type.is_pyobject:
1533 self.is_temp = True
1534 if setting:
1535 if not self.base.entry.type.writable:
1536 error(self.pos, "Writing to readonly buffer")
1537 else:
1538 self.base.entry.buffer_aux.writable_needed = True
1539 else:
1540 if isinstance(self.index, TupleNode):
1541 self.index.analyse_types(env, skip_children=skip_child_analysis)
1542 elif not skip_child_analysis:
1543 self.index.analyse_types(env)
1544 if self.base.type.is_pyobject:
1545 if self.index.type.is_int and not self.index.type.is_longlong:
1546 self.original_index_type = self.index.type
1547 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1548 if getting:
1549 env.use_utility_code(getitem_int_utility_code)
1550 if setting:
1551 env.use_utility_code(setitem_int_utility_code)
1552 else:
1553 self.index = self.index.coerce_to_pyobject(env)
1554 self.type = py_object_type
1555 self.gil_check(env)
1556 self.is_temp = 1
1557 else:
1558 if self.base.type.is_ptr or self.base.type.is_array:
1559 self.type = self.base.type.base_type
1560 else:
1561 error(self.pos,
1562 "Attempting to index non-array type '%s'" %
1563 self.base.type)
1564 self.type = PyrexTypes.error_type
1565 if self.index.type.is_pyobject:
1566 self.index = self.index.coerce_to(
1567 PyrexTypes.c_py_ssize_t_type, env)
1568 if not self.index.type.is_int:
1569 error(self.pos,
1570 "Invalid index type '%s'" %
1571 self.index.type)
1573 gil_message = "Indexing Python object"
1575 def check_const_addr(self):
1576 self.base.check_const_addr()
1577 self.index.check_const()
1579 def is_lvalue(self):
1580 return 1
1582 def calculate_result_code(self):
1583 if self.is_buffer_access:
1584 return "(*%s)" % self.buffer_ptr_code
1585 else:
1586 return "(%s[%s])" % (
1587 self.base.result(), self.index.result())
1589 def index_unsigned_parameter(self):
1590 if self.index.type.is_int:
1591 if self.original_index_type.signed:
1592 return ", 0"
1593 else:
1594 return ", sizeof(Py_ssize_t) <= sizeof(%s)" % self.original_index_type.declaration_code("")
1595 else:
1596 return ""
1598 def generate_subexpr_evaluation_code(self, code):
1599 self.base.generate_evaluation_code(code)
1600 if not self.indices:
1601 self.index.generate_evaluation_code(code)
1602 else:
1603 for i in self.indices:
1604 i.generate_evaluation_code(code)
1606 def generate_subexpr_disposal_code(self, code):
1607 self.base.generate_disposal_code(code)
1608 if not self.indices:
1609 self.index.generate_disposal_code(code)
1610 else:
1611 for i in self.indices:
1612 i.generate_disposal_code(code)
1614 def generate_result_code(self, code):
1615 if self.is_buffer_access:
1616 if code.globalstate.directives['nonecheck']:
1617 self.put_nonecheck(code)
1618 self.buffer_ptr_code = self.buffer_lookup_code(code)
1619 if self.type.is_pyobject:
1620 # is_temp is True, so must pull out value and incref it.
1621 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1622 code.putln("Py_INCREF((PyObject*)%s);" % self.result())
1623 elif self.type.is_pyobject:
1624 if self.index.type.is_int:
1625 function = "__Pyx_GetItemInt"
1626 index_code = self.index.result()
1627 else:
1628 function = "PyObject_GetItem"
1629 index_code = self.index.py_result()
1630 sign_code = ""
1631 code.putln(
1632 "%s = %s(%s, %s%s); if (!%s) %s" % (
1633 self.result(),
1634 function,
1635 self.base.py_result(),
1636 index_code,
1637 self.index_unsigned_parameter(),
1638 self.result(),
1639 code.error_goto(self.pos)))
1641 def generate_setitem_code(self, value_code, code):
1642 if self.index.type.is_int:
1643 function = "__Pyx_SetItemInt"
1644 index_code = self.index.result()
1645 else:
1646 function = "PyObject_SetItem"
1647 index_code = self.index.py_result()
1648 code.putln(
1649 "if (%s(%s, %s, %s%s) < 0) %s" % (
1650 function,
1651 self.base.py_result(),
1652 index_code,
1653 value_code,
1654 self.index_unsigned_parameter(),
1655 code.error_goto(self.pos)))
1657 def generate_buffer_setitem_code(self, rhs, code, op=""):
1658 # Used from generate_assignment_code and InPlaceAssignmentNode
1659 if code.globalstate.directives['nonecheck']:
1660 self.put_nonecheck(code)
1661 ptrexpr = self.buffer_lookup_code(code)
1662 if self.buffer_type.dtype.is_pyobject:
1663 # Must manage refcounts. Decref what is already there
1664 # and incref what we put in.
1665 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
1666 if rhs.is_temp:
1667 rhs_code = code.funcstate.allocate_temp(rhs.type)
1668 else:
1669 rhs_code = rhs.result()
1670 code.putln("%s = %s;" % (ptr, ptrexpr))
1671 code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
1672 ptr, rhs_code
1673 ))
1674 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1675 if rhs.is_temp:
1676 code.funcstate.release_temp(rhs_code)
1677 code.funcstate.release_temp(ptr)
1678 else:
1679 # Simple case
1680 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1682 def generate_assignment_code(self, rhs, code):
1683 self.generate_subexpr_evaluation_code(code)
1684 if self.is_buffer_access:
1685 self.generate_buffer_setitem_code(rhs, code)
1686 elif self.type.is_pyobject:
1687 self.generate_setitem_code(rhs.py_result(), code)
1688 else:
1689 code.putln(
1690 "%s = %s;" % (
1691 self.result(), rhs.result()))
1692 self.generate_subexpr_disposal_code(code)
1693 rhs.generate_disposal_code(code)
1695 def generate_deletion_code(self, code):
1696 self.generate_subexpr_evaluation_code(code)
1697 #if self.type.is_pyobject:
1698 if self.index.type.is_int:
1699 function = "PySequence_DelItem"
1700 index_code = self.index.result()
1701 else:
1702 function = "PyObject_DelItem"
1703 index_code = self.index.py_result()
1704 code.putln(
1705 "if (%s(%s, %s) < 0) %s" % (
1706 function,
1707 self.base.py_result(),
1708 index_code,
1709 code.error_goto(self.pos)))
1710 self.generate_subexpr_disposal_code(code)
1712 def buffer_lookup_code(self, code):
1713 # Assign indices to temps
1714 index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
1715 for temp, index in zip(index_temps, self.indices):
1716 code.putln("%s = %s;" % (temp, index.result()))
1717 # Generate buffer access code using these temps
1718 import Buffer
1719 # The above could happen because child_attrs is wrong somewhere so that
1720 # options are not propagated.
1721 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
1722 index_signeds=[i.type.signed for i in self.indices],
1723 index_cnames=index_temps,
1724 options=code.globalstate.directives,
1725 pos=self.pos, code=code)
1727 def put_nonecheck(self, code):
1728 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
1729 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
1730 code.putln("__Pyx_RaiseNoneIndexingError();")
1731 code.putln(code.error_goto(self.pos))
1732 code.putln("}")
1734 class SliceIndexNode(ExprNode):
1735 # 2-element slice indexing
1736 #
1737 # base ExprNode
1738 # start ExprNode or None
1739 # stop ExprNode or None
1741 subexprs = ['base', 'start', 'stop']
1743 def compile_time_value(self, denv):
1744 base = self.base.compile_time_value(denv)
1745 start = self.start.compile_time_value(denv)
1746 stop = self.stop.compile_time_value(denv)
1747 try:
1748 return base[start:stop]
1749 except Exception, e:
1750 self.compile_time_value_error(e)
1752 def analyse_target_declaration(self, env):
1753 pass
1755 def analyse_types(self, env):
1756 self.base.analyse_types(env)
1757 if self.start:
1758 self.start.analyse_types(env)
1759 if self.stop:
1760 self.stop.analyse_types(env)
1761 self.base = self.base.coerce_to_pyobject(env)
1762 c_int = PyrexTypes.c_py_ssize_t_type
1763 if self.start:
1764 self.start = self.start.coerce_to(c_int, env)
1765 if self.stop:
1766 self.stop = self.stop.coerce_to(c_int, env)
1767 self.type = py_object_type
1768 self.gil_check(env)
1769 self.is_temp = 1
1771 gil_message = "Slicing Python object"
1773 def generate_result_code(self, code):
1774 code.putln(
1775 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
1776 self.result(),
1777 self.base.py_result(),
1778 self.start_code(),
1779 self.stop_code(),
1780 code.error_goto_if_null(self.result(), self.pos)))
1782 def generate_assignment_code(self, rhs, code):
1783 self.generate_subexpr_evaluation_code(code)
1784 code.put_error_if_neg(self.pos,
1785 "PySequence_SetSlice(%s, %s, %s, %s)" % (
1786 self.base.py_result(),
1787 self.start_code(),
1788 self.stop_code(),
1789 rhs.result()))
1790 self.generate_subexpr_disposal_code(code)
1791 rhs.generate_disposal_code(code)
1793 def generate_deletion_code(self, code):
1794 self.generate_subexpr_evaluation_code(code)
1795 code.put_error_if_neg(self.pos,
1796 "PySequence_DelSlice(%s, %s, %s)" % (
1797 self.base.py_result(),
1798 self.start_code(),
1799 self.stop_code()))
1800 self.generate_subexpr_disposal_code(code)
1802 def start_code(self):
1803 if self.start:
1804 return self.start.result()
1805 else:
1806 return "0"
1808 def stop_code(self):
1809 if self.stop:
1810 return self.stop.result()
1811 else:
1812 return "PY_SSIZE_T_MAX"
1814 def calculate_result_code(self):
1815 # self.result() is not used, but this method must exist
1816 return "<unused>"
1819 class SliceNode(ExprNode):
1820 # start:stop:step in subscript list
1821 #
1822 # start ExprNode
1823 # stop ExprNode
1824 # step ExprNode
1826 def compile_time_value(self, denv):
1827 start = self.start.compile_time_value(denv)
1828 stop = self.stop.compile_time_value(denv)
1829 step = step.step.compile_time_value(denv)
1830 try:
1831 return slice(start, stop, step)
1832 except Exception, e:
1833 self.compile_time_value_error(e)
1835 subexprs = ['start', 'stop', 'step']
1837 def analyse_types(self, env):
1838 self.start.analyse_types(env)
1839 self.stop.analyse_types(env)
1840 self.step.analyse_types(env)
1841 self.start = self.start.coerce_to_pyobject(env)
1842 self.stop = self.stop.coerce_to_pyobject(env)
1843 self.step = self.step.coerce_to_pyobject(env)
1844 self.type = py_object_type
1845 self.gil_check(env)
1846 self.is_temp = 1
1848 gil_message = "Constructing Python slice object"
1850 def generate_result_code(self, code):
1851 code.putln(
1852 "%s = PySlice_New(%s, %s, %s); %s" % (
1853 self.result(),
1854 self.start.py_result(),
1855 self.stop.py_result(),
1856 self.step.py_result(),
1857 code.error_goto_if_null(self.result(), self.pos)))
1860 class CallNode(ExprNode):
1861 def gil_check(self, env):
1862 # Make sure we're not in a nogil environment
1863 if env.nogil:
1864 error(self.pos, "Calling gil-requiring function without gil")
1867 class SimpleCallNode(CallNode):
1868 # Function call without keyword, * or ** args.
1869 #
1870 # function ExprNode
1871 # args [ExprNode]
1872 # arg_tuple ExprNode or None used internally
1873 # self ExprNode or None used internally
1874 # coerced_self ExprNode or None used internally
1875 # wrapper_call bool used internally
1876 # has_optional_args bool used internally
1878 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1880 self = None
1881 coerced_self = None
1882 arg_tuple = None
1883 wrapper_call = False
1884 has_optional_args = False
1886 def compile_time_value(self, denv):
1887 function = self.function.compile_time_value(denv)
1888 args = [arg.compile_time_value(denv) for arg in self.args]
1889 try:
1890 return function(*args)
1891 except Exception, e:
1892 self.compile_time_value_error(e)
1894 def analyse_as_type(self, env):
1895 attr = self.function.magic_cython_method()
1896 if attr == 'pointer':
1897 if len(self.args) != 1:
1898 error(self.args.pos, "only one type allowed.")
1899 else:
1900 type = self.args[0].analyse_as_type(env)
1901 if not type:
1902 error(self.args[0].pos, "Unknown type")
1903 else:
1904 return PyrexTypes.CPtrType(type)
1906 def explicit_args_kwds(self):
1907 return self.args, None
1909 def analyse_types(self, env):
1910 function = self.function
1911 function.is_called = 1
1912 self.function.analyse_types(env)
1913 if function.is_attribute and function.is_py_attr and \
1914 function.attribute == "append" and len(self.args) == 1:
1915 # L.append(x) is almost always applied to a list
1916 self.py_func = self.function
1917 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
1918 self.function.analyse_types(env)
1919 self.self = self.py_func.obj
1920 function.obj = CloneNode(self.self)
1921 env.use_utility_code(append_utility_code)
1922 if function.is_attribute and function.entry and function.entry.is_cmethod:
1923 # Take ownership of the object from which the attribute
1924 # was obtained, because we need to pass it as 'self'.
1925 self.self = function.obj
1926 function.obj = CloneNode(self.self)
1927 func_type = self.function_type()
1928 if func_type.is_pyobject:
1929 self.arg_tuple = TupleNode(self.pos, args = self.args)
1930 self.arg_tuple.analyse_types(env)
1931 self.args = None
1932 self.type = py_object_type
1933 self.gil_check(env)
1934 self.is_temp = 1
1935 else:
1936 for arg in self.args:
1937 arg.analyse_types(env)
1938 if self.self and func_type.args:
1939 # Coerce 'self' to the type expected by the method.
1940 expected_type = func_type.args[0].type
1941 self.coerced_self = CloneNode(self.self).coerce_to(
1942 expected_type, env)
1943 # Insert coerced 'self' argument into argument list.
1944 self.args.insert(0, self.coerced_self)
1945 self.analyse_c_function_call(env)
1947 def function_type(self):
1948 # Return the type of the function being called, coercing a function
1949 # pointer to a function if necessary.
1950 func_type = self.function.type
1951 if func_type.is_ptr:
1952 func_type = func_type.base_type
1953 return func_type
1955 def analyse_c_function_call(self, env):
1956 func_type = self.function_type()
1957 # Check function type
1958 if not func_type.is_cfunction:
1959 if not func_type.is_error:
1960 error(self.pos, "Calling non-function type '%s'" %
1961 func_type)
1962 self.type = PyrexTypes.error_type
1963 self.result_code = "<error>"
1964 return
1965 # Check no. of args
1966 max_nargs = len(func_type.args)
1967 expected_nargs = max_nargs - func_type.optional_arg_count
1968 actual_nargs = len(self.args)
1969 if actual_nargs < expected_nargs \
1970 or (not func_type.has_varargs and actual_nargs > max_nargs):
1971 expected_str = str(expected_nargs)
1972 if func_type.has_varargs:
1973 expected_str = "at least " + expected_str
1974 elif func_type.optional_arg_count:
1975 if actual_nargs < max_nargs:
1976 expected_str = "at least " + expected_str
1977 else:
1978 expected_str = "at most " + str(max_nargs)
1979 error(self.pos,
1980 "Call with wrong number of arguments (expected %s, got %s)"
1981 % (expected_str, actual_nargs))
1982 self.args = None
1983 self.type = PyrexTypes.error_type
1984 self.result_code = "<error>"
1985 return
1986 if func_type.optional_arg_count and expected_nargs != actual_nargs:
1987 self.has_optional_args = 1
1988 self.is_temp = 1
1989 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
1990 env.release_temp(self.opt_arg_struct)
1991 # Coerce arguments
1992 for i in range(min(max_nargs, actual_nargs)):
1993 formal_type = func_type.args[i].type
1994 self.args[i] = self.args[i].coerce_to(formal_type, env)
1995 for i in range(max_nargs, actual_nargs):
1996 if self.args[i].type.is_pyobject:
1997 error(self.args[i].pos,
1998 "Python object cannot be passed as a varargs parameter")
1999 # Calc result type and code fragment
2000 self.type = func_type.return_type
2001 if self.type.is_pyobject \
2002 or func_type.exception_value is not None \
2003 or func_type.exception_check:
2004 self.is_temp = 1
2005 if self.type.is_pyobject:
2006 self.result_ctype = py_object_type
2007 # C++ exception handler
2008 if func_type.exception_check == '+':
2009 if func_type.exception_value is None:
2010 env.use_utility_code(cpp_exception_utility_code)
2011 # Check gil
2012 if not func_type.nogil:
2013 self.gil_check(env)
2015 def calculate_result_code(self):
2016 return self.c_call_code()
2018 def c_call_code(self):
2019 func_type = self.function_type()
2020 if self.args is None or not func_type.is_cfunction:
2021 return "<error>"
2022 formal_args = func_type.args
2023 arg_list_code = []
2024 args = zip(formal_args, self.args)
2025 max_nargs = len(func_type.args)
2026 expected_nargs = max_nargs - func_type.optional_arg_count
2027 actual_nargs = len(self.args)
2028 for formal_arg, actual_arg in args[:expected_nargs]:
2029 arg_code = actual_arg.result_as(formal_arg.type)
2030 arg_list_code.append(arg_code)
2032 if func_type.is_overridable:
2033 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2035 if func_type.optional_arg_count:
2036 if expected_nargs == actual_nargs:
2037 optional_args = 'NULL'
2038 else:
2039 optional_args = "&%s" % self.opt_arg_struct
2040 arg_list_code.append(optional_args)
2042 for actual_arg in self.args[len(formal_args):]:
2043 arg_list_code.append(actual_arg.result())
2044 result = "%s(%s)" % (self.function.result(),
2045 join(arg_list_code, ", "))
2046 # if self.wrapper_call or \
2047 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2048 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2049 return result
2051 def generate_result_code(self, code):
2052 func_type = self.function_type()
2053 if func_type.is_pyobject:
2054 arg_code = self.arg_tuple.py_result()
2055 code.putln(
2056 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2057 self.result(),
2058 self.function.py_result(),
2059 arg_code,
2060 code.error_goto_if_null(self.result(), self.pos)))
2061 elif func_type.is_cfunction:
2062 if self.has_optional_args:
2063 actual_nargs = len(self.args)
2064 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2065 code.putln("%s.%s = %s;" % (
2066 self.opt_arg_struct,
2067 Naming.pyrex_prefix + "n",
2068 len(self.args) - expected_nargs))
2069 args = zip(func_type.args, self.args)
2070 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2071 code.putln("%s.%s = %s;" % (
2072 self.opt_arg_struct,
2073 formal_arg.name,
2074 actual_arg.result_as(formal_arg.type)))
2075 exc_checks = []
2076 if self.type.is_pyobject:
2077 exc_checks.append("!%s" % self.result())
2078 else:
2079 exc_val = func_type.exception_value
2080 exc_check = func_type.exception_check
2081 if exc_val is not None:
2082 exc_checks.append("%s == %s" % (self.result(), exc_val))
2083 if exc_check:
2084 exc_checks.append("PyErr_Occurred()")
2085 if self.is_temp or exc_checks:
2086 rhs = self.c_call_code()
2087 if self.result():
2088 lhs = "%s = " % self.result()
2089 if self.is_temp and self.type.is_pyobject:
2090 #return_type = self.type # func_type.return_type
2091 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2092 # "from", return_type, "to pyobject" ###
2093 rhs = typecast(py_object_type, self.type, rhs)
2094 else:
2095 lhs = ""
2096 if func_type.exception_check == '+':
2097 if func_type.exception_value is None:
2098 raise_py_exception = "__Pyx_CppExn2PyErr()"
2099 elif func_type.exception_value.type.is_pyobject:
2100 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2101 else:
2102 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2103 code.putln(
2104 "try {%s%s;} catch(...) {%s; %s}" % (
2105 lhs,
2106 rhs,
2107 raise_py_exception,
2108 code.error_goto(self.pos)))
2109 else:
2110 if exc_checks:
2111 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2112 else:
2113 goto_error = ""
2114 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2116 class GeneralCallNode(CallNode):
2117 # General Python function call, including keyword,
2118 # * and ** arguments.
2119 #
2120 # function ExprNode
2121 # positional_args ExprNode Tuple of positional arguments
2122 # keyword_args ExprNode or None Dict of keyword arguments
2123 # starstar_arg ExprNode or None Dict of extra keyword args
2125 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2127 def compile_time_value(self, denv):
2128 function = self.function.compile_time_value(denv)
2129 positional_args = self.positional_args.compile_time_value(denv)
2130 keyword_args = self.keyword_args.compile_time_value(denv)
2131 starstar_arg = self.starstar_arg.compile_time_value(denv)
2132 try:
2133 keyword_args.update(starstar_arg)
2134 return function(*positional_args, **keyword_args)
2135 except Exception, e:
2136 self.compile_time_value_error(e)
2138 def explicit_args_kwds(self):
2139 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2140 raise PostParseError(self.pos,
2141 'Compile-time keyword arguments must be explicit.')
2142 return self.positional_args.args, self.keyword_args
2144 def analyse_types(self, env):
2145 self.function.analyse_types(env)
2146 self.positional_args.analyse_types(env)
2147 if self.keyword_args:
2148 self.keyword_args.analyse_types(env)
2149 if self.starstar_arg:
2150 self.starstar_arg.analyse_types(env)
2151 self.function = self.function.coerce_to_pyobject(env)
2152 self.positional_args = \
2153 self.positional_args.coerce_to_pyobject(env)
2154 if self.starstar_arg:
2155 self.starstar_arg = \
2156 self.starstar_arg.coerce_to_pyobject(env)
2157 self.type = py_object_type
2158 self.gil_check(env)
2159 self.is_temp = 1
2161 def generate_result_code(self, code):
2162 if self.keyword_args and self.starstar_arg:
2163 code.put_error_if_neg(self.pos,
2164 "PyDict_Update(%s, %s)" % (
2165 self.keyword_args.py_result(),
2166 self.starstar_arg.py_result()))
2167 keyword_code = self.keyword_args.py_result()
2168 elif self.keyword_args:
2169 keyword_code = self.keyword_args.py_result()
2170 elif self.starstar_arg:
2171 keyword_code = self.starstar_arg.py_result()
2172 else:
2173 keyword_code = None
2174 if not keyword_code:
2175 call_code = "PyObject_Call(%s, %s, NULL)" % (
2176 self.function.py_result(),
2177 self.positional_args.py_result())
2178 else:
2179 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2180 self.function.py_result(),
2181 self.positional_args.py_result(),
2182 keyword_code)
2183 code.putln(
2184 "%s = %s; %s" % (
2185 self.result(),
2186 call_code,
2187 code.error_goto_if_null(self.result(), self.pos)))
2190 class AsTupleNode(ExprNode):
2191 # Convert argument to tuple. Used for normalising
2192 # the * argument of a function call.
2193 #
2194 # arg ExprNode
2196 subexprs = ['arg']
2198 def compile_time_value(self, denv):
2199 arg = self.arg.compile_time_value(denv)
2200 try:
2201 return tuple(arg)
2202 except Exception, e:
2203 self.compile_time_value_error(e)
2205 def analyse_types(self, env):
2206 self.arg.analyse_types(env)
2207 self.arg = self.arg.coerce_to_pyobject(env)
2208 self.type = py_object_type
2209 self.gil_check(env)
2210 self.is_temp = 1
2212 gil_message = "Constructing Python tuple"
2214 def generate_result_code(self, code):
2215 code.putln(
2216 "%s = PySequence_Tuple(%s); %s" % (
2217 self.result(),
2218 self.arg.py_result(),
2219 code.error_goto_if_null(self.result(), self.pos)))
2222 class AttributeNode(ExprNode):
2223 # obj.attribute
2224 #
2225 # obj ExprNode
2226 # attribute string
2227 # needs_none_check boolean Used if obj is an extension type.
2228 # If set to True, it is known that the type is not None.
2229 #
2230 # Used internally:
2231 #
2232 # is_py_attr boolean Is a Python getattr operation
2233 # member string C name of struct member
2234 # is_called boolean Function call is being done on result
2235 # entry Entry Symbol table entry of attribute
2236 # interned_attr_cname string C name of interned attribute name
2238 is_attribute = 1
2239 subexprs = ['obj']
2241 type = PyrexTypes.error_type
2242 entry = None
2243 is_called = 0
2244 needs_none_check = True
2246 def magic_cython_method(self):
2247 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2248 return self.attribute
2250 def coerce_to(self, dst_type, env):
2251 # If coercing to a generic pyobject and this is a cpdef function
2252 # we can create the corresponding attribute
2253 if dst_type is py_object_type:
2254 entry = self.entry
2255 if entry and entry.is_cfunction and entry.as_variable:
2256 # must be a cpdef function
2257 self.is_temp = 1
2258 self.entry = entry.as_variable
2259 self.analyse_as_python_attribute(env)
2260 return self
2261 return ExprNode.coerce_to(self, dst_type, env)
2263 def compile_time_value(self, denv):
2264 attr = self.attribute
2265 if attr.beginswith("__") and attr.endswith("__"):
2266 self.error("Invalid attribute name '%s' in compile-time expression"
2267 % attr)
2268 return None
2269 obj = self.arg.compile_time_value(denv)
2270 try:
2271 return getattr(obj, attr)
2272 except Exception, e:
2273 self.compile_time_value_error(e)
2275 def analyse_target_declaration(self, env):
2276 pass
2278 def analyse_target_types(self, env):
2279 self.analyse_types(env, target = 1)
2281 def analyse_types(self, env, target = 0):
2282 if self.analyse_as_cimported_attribute(env, target):
2283 return
2284 if not target and self.analyse_as_unbound_cmethod(env):
2285 return
2286 self.analyse_as_ordinary_attribute(env, target)
2288 def analyse_as_cimported_attribute(self, env, target):
2289 # Try to interpret this as a reference to an imported
2290 # C const, type, var or function. If successful, mutates
2291 # this node into a NameNode and returns 1, otherwise
2292 # returns 0.
2293 module_scope = self.obj.analyse_as_module(env)
2294 if module_scope:
2295 entry = module_scope.lookup_here(self.attribute)
2296 if entry and (
2297 entry.is_cglobal or entry.is_cfunction
2298 or entry.is_type or entry.is_const):
2299 self.mutate_into_name_node(env, entry, target)
2300 return 1
2301 return 0
2303 def analyse_as_unbound_cmethod(self, env):
2304 # Try to interpret this as a reference to an unbound
2305 # C method of an extension type. If successful, mutates
2306 # this node into a NameNode and returns 1, otherwise
2307 # returns 0.
2308 type = self.obj.analyse_as_extension_type(env)
2309 if type:
2310 entry = type.scope.lookup_here(self.attribute)
2311 if entry and entry.is_cmethod:
2312 # Create a temporary entry describing the C method
2313 # as an ordinary function.
2314 ubcm_entry = Symtab.Entry(entry.name,
2315 "%s->%s" % (type.vtabptr_cname, entry.cname),
2316 entry.type)
2317 ubcm_entry.is_cfunction = 1
2318 ubcm_entry.func_cname = entry.func_cname
2319 ubcm_entry.is_unbound_cmethod = 1
2320 self.mutate_into_name_node(env, ubcm_entry, None)
2321 return 1
2322 return 0
2324 def analyse_as_type(self, env):
2325 module_scope = self.obj.analyse_as_module(env)
2326 if module_scope:
2327 return module_scope.lookup_type(self.attribute)
2328 return None
2330 def analyse_as_extension_type(self, env):
2331 # Try to interpret this as a reference to an extension type
2332 # in a cimported module. Returns the extension type, or None.
2333 module_scope = self.obj.analyse_as_module(env)
2334 if module_scope:
2335 entry = module_scope.lookup_here(self.attribute)
2336 if entry and entry.is_type and entry.type.is_extension_type:
2337 return entry.type
2338 return None
2340 def analyse_as_module(self, env):
2341 # Try to interpret this as a reference to a cimported module
2342 # in another cimported module. Returns the module scope, or None.
2343 module_scope = self.obj.analyse_as_module(env)
2344 if module_scope:
2345 entry = module_scope.lookup_here(self.attribute)
2346 if entry and entry.as_module:
2347 return entry.as_module
2348 return None
2350 def mutate_into_name_node(self, env, entry, target):
2351 # Mutate this node into a NameNode and complete the
2352 # analyse_types phase.
2353 self.__class__ = NameNode
2354 self.name = self.attribute
2355 self.entry = entry
2356 del self.obj
2357 del self.attribute
2358 if target:
2359 NameNode.analyse_target_types(self, env)
2360 else:
2361 NameNode.analyse_rvalue_entry(self, env)
2363 def analyse_as_ordinary_attribute(self, env, target):
2364 self.obj.analyse_types(env)
2365 self.analyse_attribute(env)
2366 if self.entry and self.entry.is_cmethod and not self.is_called:
2367 # error(self.pos, "C method can only be called")
2368 pass
2369 ## Reference to C array turns into pointer to first element.
2370 #while self.type.is_array:
2371 # self.type = self.type.element_ptr_type()
2372 if self.is_py_attr:
2373 if not target:
2374 self.is_temp = 1
2375 self.result_ctype = py_object_type
2377 def analyse_attribute(self, env):
2378 # Look up attribute and set self.type and self.member.
2379 self.is_py_attr = 0
2380 self.member = self.attribute
2381 if self.obj.type.is_string:
2382 self.obj = self.obj.coerce_to_pyobject(env)
2383 obj_type = self.obj.type
2384 if obj_type.is_ptr or obj_type.is_array:
2385 obj_type = obj_type.base_type
2386 self.op = "->"
2387 elif obj_type.is_extension_type:
2388 self.op = "->"
2389 else:
2390 self.op = "."
2391 if obj_type.has_attributes:
2392 entry = None
2393 if obj_type.attributes_known():
2394 entry = obj_type.scope.lookup_here(self.attribute)
2395 if entry and entry.is_member:
2396 entry = None
2397 else:
2398 error(self.pos,
2399 "Cannot select attribute of incomplete type '%s'"
2400 % obj_type)
2401 self.type = PyrexTypes.error_type
2402 return
2403 self.entry = entry
2404 if entry:
2405 if obj_type.is_extension_type and entry.name == "__weakref__":
2406 error(self.pos, "Illegal use of special attribute __weakref__")
2407 # methods need the normal attribute lookup
2408 # because they do not have struct entries
2409 if entry.is_variable or entry.is_cmethod:
2410 self.type = entry.type
2411 self.member = entry.cname
2412 return
2413 else:
2414 # If it's not a variable or C method, it must be a Python
2415 # method of an extension type, so we treat it like a Python
2416 # attribute.
2417 pass
2418 # If we get here, the base object is not a struct/union/extension
2419 # type, or it is an extension type and the attribute is either not
2420 # declared or is declared as a Python method. Treat it as a Python
2421 # attribute reference.
2422 self.analyse_as_python_attribute(env)
2424 def analyse_as_python_attribute(self, env):
2425 obj_type = self.obj.type
2426 self.member = self.attribute
2427 if obj_type.is_pyobject:
2428 self.type = py_object_type
2429 self.is_py_attr = 1
2430 self.interned_attr_cname = env.intern_identifier(self.attribute)
2431 self.gil_check(env)
2432 else:
2433 if not obj_type.is_error:
2434 error(self.pos,
2435 "Object of type '%s' has no attribute '%s'" %
2436 (obj_type, self.attribute))
2438 gil_message = "Accessing Python attribute"
2440 def is_simple(self):
2441 if self.obj:
2442 return self.result_in_temp() or self.obj.is_simple()
2443 else:
2444 return NameNode.is_simple(self)
2446 def is_lvalue(self):
2447 if self.obj:
2448 return 1
2449 else:
2450 return NameNode.is_lvalue(self)
2452 def is_ephemeral(self):
2453 if self.obj:
2454 return self.obj.is_ephemeral()
2455 else:
2456 return NameNode.is_ephemeral(self)
2458 def calculate_result_code(self):
2459 #print "AttributeNode.calculate_result_code:", self.member ###
2460 #print "...obj node =", self.obj, "code", self.obj.result() ###
2461 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2462 obj = self.obj
2463 obj_code = obj.result_as(obj.type)
2464 #print "...obj_code =", obj_code ###
2465 if self.entry and self.entry.is_cmethod:
2466 if obj.type.is_extension_type:
2467 return "((struct %s *)%s%s%s)->%s" % (
2468 obj.type.vtabstruct_cname, obj_code, self.op,
2469 obj.type.vtabslot_cname, self.member)
2470 else:
2471 return self.member
2472 else:
2473 return "%s%s%s" % (obj_code, self.op, self.member)
2475 def generate_result_code(self, code):
2476 if self.is_py_attr:
2477 code.putln(
2478 '%s = PyObject_GetAttr(%s, %s); %s' % (
2479 self.result(),
2480 self.obj.py_result(),
2481 self.interned_attr_cname,
2482 code.error_goto_if_null(self.result(), self.pos)))
2483 else:
2484 # result_code contains what is needed, but we may need to insert
2485 # a check and raise an exception
2486 if (self.obj.type.is_extension_type
2487 and self.needs_none_check
2488 and code.globalstate.directives['nonecheck']):
2489 self.put_nonecheck(code)
2491 def generate_assignment_code(self, rhs, code):
2492 self.obj.generate_evaluation_code(code)
2493 if self.is_py_attr:
2494 code.put_error_if_neg(self.pos,
2495 'PyObject_SetAttr(%s, %s, %s)' % (
2496 self.obj.py_result(),
2497 self.interned_attr_cname,
2498 rhs.py_result()))
2499 rhs.generate_disposal_code(code)
2500 else:
2501 if (self.obj.type.is_extension_type
2502 and self.needs_none_check
2503 and code.globalstate.directives['nonecheck']):
2504 self.put_nonecheck(code)
2506 select_code = self.result()
2507 if self.type.is_pyobject:
2508 rhs.make_owned_reference(code)
2509 code.put_decref(select_code, self.ctype())
2510 code.putln(
2511 "%s = %s;" % (
2512 select_code,
2513 rhs.result_as(self.ctype())))
2514 #rhs.result()))
2515 rhs.generate_post_assignment_code(code)
2516 self.obj.generate_disposal_code(code)
2518 def generate_deletion_code(self, code):
2519 self.obj.generate_evaluation_code(code)
2520 if self.is_py_attr:
2521 code.put_error_if_neg(self.pos,
2522 'PyObject_DelAttr(%s, %s)' % (
2523 self.obj.py_result(),
2524 self.interned_attr_cname))
2525 else:
2526 error(self.pos, "Cannot delete C attribute of extension type")
2527 self.obj.generate_disposal_code(code)
2529 def annotate(self, code):
2530 if self.is_py_attr:
2531 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
2532 else:
2533 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
2535 def put_nonecheck(self, code):
2536 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
2537 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
2538 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
2539 code.putln(code.error_goto(self.pos))
2540 code.putln("}")
2543 #-------------------------------------------------------------------
2544 #
2545 # Constructor nodes
2546 #
2547 #-------------------------------------------------------------------
2549 class SequenceNode(ExprNode):
2550 # Base class for list and tuple constructor nodes.
2551 # Contains common code for performing sequence unpacking.
2552 #
2553 # args [ExprNode]
2554 # iterator ExprNode
2555 # unpacked_items [ExprNode] or None
2556 # coerced_unpacked_items [ExprNode] or None
2558 subexprs = ['args']
2560 is_sequence_constructor = 1
2561 unpacked_items = None
2563 def compile_time_value_list(self, denv):
2564 return [arg.compile_time_value(denv) for arg in self.args]
2566 def analyse_target_declaration(self, env):
2567 for arg in self.args:
2568 arg.analyse_target_declaration(env)
2570 def analyse_types(self, env, skip_children=False):
2571 for i in range(len(self.args)):
2572 arg = self.args[i]
2573 if not skip_children: arg.analyse_types(env)
2574 self.args[i] = arg.coerce_to_pyobject(env)
2575 self.type = py_object_type
2576 self.gil_check(env)
2577 self.is_temp = 1
2579 def analyse_target_types(self, env):
2580 self.iterator = PyTempNode(self.pos, env)
2581 self.unpacked_items = []
2582 self.coerced_unpacked_items = []
2583 for arg in self.args:
2584 arg.analyse_target_types(env)
2585 unpacked_item = PyTempNode(self.pos, env)
2586 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
2587 self.unpacked_items.append(unpacked_item)
2588 self.coerced_unpacked_items.append(coerced_unpacked_item)
2589 self.type = py_object_type
2590 env.use_utility_code(unpacking_utility_code)
2592 def allocate_target_temps(self, env, rhs):
2593 self.iterator.allocate_temps(env)
2594 for arg, node in zip(self.args, self.coerced_unpacked_items):
2595 node.allocate_temps(env)
2596 arg.allocate_target_temps(env, node)
2597 #arg.release_target_temp(env)
2598 #node.release_temp(env)
2599 if rhs:
2600 rhs.release_temp(env)
2601 self.iterator.release_temp(env)
2603 # def release_target_temp(self, env):
2604 # #for arg in self.args:
2605 # # arg.release_target_temp(env)
2606 # #for node in self.coerced_unpacked_items:
2607 # # node.release_temp(env)
2608 # self.iterator.release_temp(env)
2610 def generate_result_code(self, code):
2611 self.generate_operation_code(code)
2613 def generate_assignment_code(self, rhs, code):
2614 code.putln(
2615 "if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {" % (
2616 rhs.py_result(),
2617 rhs.py_result(),
2618 len(self.args)))
2619 code.putln("PyObject* tuple = %s;" % rhs.py_result())
2620 for i in range(len(self.args)):
2621 item = self.unpacked_items[i]
2622 code.putln(
2623 "%s = PyTuple_GET_ITEM(tuple, %s);" % (
2624 item.result(),
2625 i))
2626 code.put_incref(item.result(), item.ctype())
2627 value_node = self.coerced_unpacked_items[i]
2628 value_node.generate_evaluation_code(code)
2629 self.args[i].generate_assignment_code(value_node, code)
2631 rhs.generate_disposal_code(code)
2632 code.putln("}")
2633 code.putln("else {")
2635 code.putln(
2636 "%s = PyObject_GetIter(%s); %s" % (
2637 self.iterator.result(),
2638 rhs.py_result(),
2639 code.error_goto_if_null(self.iterator.result(), self.pos)))
2640 rhs.generate_disposal_code(code)
2641 for i in range(len(self.args)):
2642 item = self.unpacked_items[i]
2643 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
2644 self.iterator.py_result(), i)
2645 code.putln(
2646 "%s = %s; %s" % (
2647 item.result(),
2648 typecast(item.ctype(), py_object_type, unpack_code),
2649 code.error_goto_if_null(item.result(), self.pos)))
2650 value_node = self.coerced_unpacked_items[i]
2651 value_node.generate_evaluation_code(code)
2652 self.args[i].generate_assignment_code(value_node, code)
2653 code.put_error_if_neg(self.pos,
2654 "__Pyx_EndUnpack(%s)" % (
2655 self.iterator.py_result()))
2656 if debug_disposal_code:
2657 print("UnpackNode.generate_assignment_code:")
2658 print("...generating disposal code for %s" % self.iterator)
2659 self.iterator.generate_disposal_code(code)
2661 code.putln("}")
2663 def annotate(self, code):
2664 for arg in self.args:
2665 arg.annotate(code)
2666 if self.unpacked_items:
2667 for arg in self.unpacked_items:
2668 arg.annotate(code)
2669 for arg in self.coerced_unpacked_items:
2670 arg.annotate(code)
2673 class TupleNode(SequenceNode):
2674 # Tuple constructor.
2676 gil_message = "Constructing Python tuple"
2678 def analyse_types(self, env, skip_children=False):
2679 if len(self.args) == 0:
2680 self.is_temp = 0
2681 self.is_literal = 1
2682 else:
2683 SequenceNode.analyse_types(self, env, skip_children)
2684 self.type = tuple_type
2686 def calculate_result_code(self):
2687 if len(self.args) > 0:
2688 error(self.pos, "Positive length tuples must be constructed.")
2689 else:
2690 return Naming.empty_tuple
2692 def compile_time_value(self, denv):
2693 values = self.compile_time_value_list(denv)
2694 try:
2695 return tuple(values)
2696 except Exception, e:
2697 self.compile_time_value_error(e)
2699 def generate_operation_code(self, code):
2700 if len(self.args) == 0:
2701 # result_code is Naming.empty_tuple
2702 return
2703 code.putln(
2704 "%s = PyTuple_New(%s); %s" % (
2705 self.result(),
2706 len(self.args),
2707 code.error_goto_if_null(self.result(), self.pos)))
2708 for i in range(len(self.args)):
2709 arg = self.args[i]
2710 if not arg.result_in_temp():
2711 code.put_incref(arg.result(), arg.ctype())
2712 code.putln(
2713 "PyTuple_SET_ITEM(%s, %s, %s);" % (
2714 self.result(),
2715 i,
2716 arg.py_result()))
2718 def generate_subexpr_disposal_code(self, code):
2719 # We call generate_post_assignment_code here instead
2720 # of generate_disposal_code, because values were stored
2721 # in the tuple using a reference-stealing operation.
2722 for arg in self.args:
2723 arg.generate_post_assignment_code(code)
2726 class ListNode(SequenceNode):
2727 # List constructor.
2729 # obj_conversion_errors [PyrexError] used internally
2730 # orignial_args [ExprNode] used internally
2732 gil_message = "Constructing Python list"
2734 def analyse_expressions(self, env):
2735 ExprNode.analyse_expressions(self, env)
2736 self.coerce_to_pyobject(env)
2738 def analyse_types(self, env):
2739 hold_errors()
2740 self.original_args = list(self.args)
2741 SequenceNode.analyse_types(self, env)
2742 self.type = list_type
2743 self.obj_conversion_errors = held_errors()
2744 release_errors(ignore=True)
2746 def coerce_to(self, dst_type, env):
2747 if dst_type.is_pyobject:
2748 for err in self.obj_conversion_errors:
2749 report_error(err)
2750 self.obj_conversion_errors = []
2751 if not self.type.subtype_of(dst_type):
2752 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2753 elif dst_type.is_ptr:
2754 base_type = dst_type.base_type
2755 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
2756 for i in range(len(self.original_args)):
2757 arg = self.args[i]
2758 if isinstance(arg, CoerceToPyTypeNode):
2759 arg = arg.arg
2760 self.args[i] = arg.coerce_to(base_type, env)
2761 elif dst_type.is_struct:
2762 if len(self.args) > len(dst_type.scope.var_entries):
2763 error(self.pos, "Too may members for '%s'" % dst_type)
2764 else:
2765 if len(self.args) < len(dst_type.scope.var_entries):
2766 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
2767 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
2768 if isinstance(arg, CoerceToPyTypeNode):
2769 arg = arg.arg
2770 self.args[i] = arg.coerce_to(member.type, env)
2771 self.type = dst_type
2772 else:
2773 self.type = error_type
2774 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
2775 return self
2777 def release_temp(self, env):
2778 if self.type.is_array:
2779 # To be valid C++, we must allocate the memory on the stack
2780 # manually and be sure not to reuse it for something else.
2781 pass
2782 else:
2783 SequenceNode.release_temp(self, env)
2785 def compile_time_value(self, denv):
2786 return self.compile_time_value_list(denv)
2788 def generate_operation_code(self, code):
2789 if self.type.is_pyobject:
2790 for err in self.obj_conversion_errors:
2791 report_error(err)
2792 code.putln("%s = PyList_New(%s); %s" %
2793 (self.result(),
2794 len(self.args),
2795 code.error_goto_if_null(self.result(), self.pos)))
2796 for i in range(len(self.args)):
2797 arg = self.args[i]
2798 #if not arg.is_temp:
2799 if not arg.result_in_temp():
2800 code.put_incref(arg.result(), arg.ctype())
2801 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
2802 (self.result(),
2803 i,
2804 arg.py_result()))
2805 elif self.type.is_array:
2806 for i, arg in enumerate(self.args):
2807 code.putln("%s[%s] = %s;" % (
2808 self.result(),
2809 i,
2810 arg.result()))
2811 elif self.type.is_struct or 1:
2812 for arg, member in zip(self.args, self.type.scope.var_entries):
2813 code.putln("%s.%s = %s;" % (
2814 self.result(),
2815 member.cname,
2816 arg.result()))
2817 else:
2818 raise InternalError("List type never specified")
2820 def generate_subexpr_disposal_code(self, code):
2821 # We call generate_post_assignment_code here instead
2822 # of generate_disposal_code, because values were stored
2823 # in the list using a reference-stealing operation.
2824 for arg in self.args:
2825 arg.generate_post_assignment_code(code)
2828 class ListComprehensionNode(SequenceNode):
2830 subexprs = []
2831 is_sequence_constructor = 0 # not unpackable
2833 child_attrs = ["loop", "append"]
2835 def analyse_types(self, env):
2836 self.type = list_type
2837 self.is_temp = 1
2838 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
2840 def allocate_temps(self, env, result = None):
2841 if debug_temp_alloc:
2842 print("%s Allocating temps" % self)
2843 self.allocate_temp(env, result)
2844 self.loop.analyse_declarations(env)
2845 self.loop.analyse_expressions(env)
2847 def generate_operation_code(self, code):
2848 code.putln("%s = PyList_New(%s); %s" %
2849 (self.result(),
2850 0,
2851 code.error_goto_if_null(self.result(), self.pos)))
2852 self.loop.generate_execution_code(code)
2854 def annotate(self, code):
2855 self.loop.annotate(code)
2858 class ListComprehensionAppendNode(ExprNode):
2860 # Need to be careful to avoid infinite recursion:
2861 # target must not be in child_attrs/subexprs
2862 subexprs = ['expr']
2864 def analyse_types(self, env):
2865 self.expr.analyse_types(env)
2866 if self.expr.type != py_object_type:
2867 self.expr = self.expr.coerce_to_pyobject(env)
2868 self.type = PyrexTypes.c_int_type
2869 self.is_temp = 1
2871 def generate_result_code(self, code):
2872 code.putln("%s = PyList_Append(%s, (PyObject*)%s); %s" %
2873 (self.result(),
2874 self.target.result(),
2875 self.expr.result(),
2876 code.error_goto_if(self.result(), self.pos)))
2879 class DictNode(ExprNode):
2880 # Dictionary constructor.
2881 #
2882 # key_value_pairs [DictItemNode]
2883 #
2884 # obj_conversion_errors [PyrexError] used internally
2886 subexprs = ['key_value_pairs']
2888 def compile_time_value(self, denv):
2889 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
2890 for item in self.key_value_pairs]
2891 try:
2892 return dict(pairs)
2893 except Exception, e:
2894 self.compile_time_value_error(e)
2896 def analyse_types(self, env):
2897 hold_errors()
2898 for item in self.key_value_pairs:
2899 item.analyse_types(env)
2900 self.gil_check(env)
2901 self.obj_conversion_errors = held_errors()
2902 release_errors(ignore=True)
2903 self.type = dict_type
2904 self.is_temp = 1
2906 def coerce_to(self, dst_type, env):
2907 if dst_type.is_pyobject:
2908 self.release_errors()
2909 if not self.type.subtype_of(dst_type):
2910 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
2911 elif dst_type.is_struct_or_union:
2912 self.type = dst_type
2913 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
2914 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
2915 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
2916 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
2917 for item in self.key_value_pairs:
2918 if isinstance(item.key, CoerceToPyTypeNode):
2919 item.key = item.key.arg
2920 if isinstance(item.key, (StringNode, IdentifierStringNode)):
2921 item.key = NameNode(pos=item.key.pos, name=item.key.value)
2922 if not isinstance(item.key, NameNode):
2923 print item.key
2924 error(item.key.pos, "Struct field must be a name")
2925 else:
2926 member = dst_type.scope.lookup_here(item.key.name)
2927 if not member:
2928 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.name))
2929 else:
2930 value = item.value
2931 if isinstance(value, CoerceToPyTypeNode):
2932 value = value.arg
2933 item.value = value.coerce_to(member.type, env)
2934 else:
2935 self.type = error_type
2936 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
2937 return self
2939 def release_errors(self):
2940 for err in self.obj_conversion_errors:
2941 report_error(err)
2942 self.obj_conversion_errors = []
2944 gil_message = "Constructing Python dict"
2946 def allocate_temps(self, env, result = None):
2947 # Custom method used here because key-value
2948 # pairs are evaluated and used one at a time.
2949 self.allocate_temp(env, result)
2950 for item in self.key_value_pairs:
2951 item.key.allocate_temps(env)
2952 item.value.allocate_temps(env)
2953 item.key.release_temp(env)
2954 item.value.release_temp(env)
2956 def generate_evaluation_code(self, code):
2957 # Custom method used here because key-value
2958 # pairs are evaluated and used one at a time.
2959 if self.type.is_pyobject:
2960 self.release_errors()
2961 code.putln(
2962 "%s = PyDict_New(); %s" % (
2963 self.result(),
2964 code.error_goto_if_null(self.result(), self.pos)))
2965 for item in self.key_value_pairs:
2966 item.generate_evaluation_code(code)
2967 if self.type.is_pyobject:
2968 code.put_error_if_neg(self.pos,
2969 "PyDict_SetItem(%s, %s, %s)" % (
2970 self.result(),
2971 item.key.py_result(),
2972 item.value.py_result()))
2973 else:
2974 code.putln("%s.%s = %s;" % (
2975 self.result(),
2976 item.key.name,
2977 item.value.result()))
2978 item.generate_disposal_code(code)
2980 def annotate(self, code):
2981 for item in self.key_value_pairs:
2982 item.annotate(code)
2984 class DictItemNode(ExprNode):
2985 # Represents a single item in a DictNode
2986 #
2987 # key ExprNode
2988 # value ExprNode
2989 subexprs = ['key', 'value']
2991 def analyse_types(self, env):
2992 self.key.analyse_types(env)
2993 self.value.analyse_types(env)
2994 self.key = self.key.coerce_to_pyobject(env)
2995 self.value = self.value.coerce_to_pyobject(env)
2997 def generate_evaluation_code(self, code):
2998 self.key.generate_evaluation_code(code)
2999 self.value.generate_evaluation_code(code)
3001 def generate_disposal_code(self, code):
3002 self.key.generate_disposal_code(code)
3003 self.value.generate_disposal_code(code)
3005 def __iter__(self):
3006 return iter([self.key, self.value])
3009 class ClassNode(ExprNode):
3010 # Helper class used in the implementation of Python
3011 # class definitions. Constructs a class object given
3012 # a name, tuple of bases and class dictionary.
3013 #
3014 # name EncodedString Name of the class
3015 # cname string Class name as a Python string
3016 # bases ExprNode Base class tuple
3017 # dict ExprNode Class dict (not owned by this node)
3018 # doc ExprNode or None Doc string
3019 # module_name string Name of defining module
3021 subexprs = ['bases', 'doc']
3023 def analyse_types(self, env):
3024 self.cname = env.intern_identifier(self.name)
3025 self.bases.analyse_types(env)
3026 if self.doc:
3027 self.doc.analyse_types(env)
3028 self.doc = self.doc.coerce_to_pyobject(env)
3029 self.module_name = env.global_scope().qualified_name
3030 self.type = py_object_type
3031 self.gil_check(env)
3032 self.is_temp = 1
3033 env.use_utility_code(create_class_utility_code);
3035 gil_message = "Constructing Python class"
3037 def generate_result_code(self, code):
3038 if self.doc:
3039 code.put_error_if_neg(self.pos,
3040 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3041 self.dict.py_result(),
3042 self.doc.py_result()))
3043 code.putln(
3044 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3045 self.result(),
3046 self.bases.py_result(),
3047 self.dict.py_result(),
3048 self.cname,
3049 self.module_name,
3050 code.error_goto_if_null(self.result(), self.pos)))
3053 class UnboundMethodNode(ExprNode):
3054 # Helper class used in the implementation of Python
3055 # class definitions. Constructs an unbound method
3056 # object from a class and a function.
3057 #
3058 # class_cname string C var holding the class object
3059 # function ExprNode Function object
3061 subexprs = ['function']
3063 def analyse_types(self, env):
3064 self.function.analyse_types(env)
3065 self.type = py_object_type
3066 self.gil_check(env)
3067 self.is_temp = 1
3069 gil_message = "Constructing an unbound method"
3071 def generate_result_code(self, code):
3072 code.putln(
3073 "%s = PyMethod_New(%s, 0, %s); %s" % (
3074 self.result(),
3075 self.function.py_result(),
3076 self.class_cname,
3077 code.error_goto_if_null(self.result(), self.pos)))
3080 class PyCFunctionNode(AtomicExprNode):
3081 # Helper class used in the implementation of Python
3082 # class definitions. Constructs a PyCFunction object
3083 # from a PyMethodDef struct.
3084 #
3085 # pymethdef_cname string PyMethodDef structure
3087 def analyse_types(self, env):
3088 self.type = py_object_type
3089 self.gil_check(env)
3090 self.is_temp = 1
3092 gil_message = "Constructing Python function"
3094 def generate_result_code(self, code):
3095 code.putln(
3096 "%s = PyCFunction_New(&%s, 0); %s" % (
3097 self.result(),
3098 self.pymethdef_cname,
3099 code.error_goto_if_null(self.result(), self.pos)))
3101 #-------------------------------------------------------------------
3102 #
3103 # Unary operator nodes
3104 #
3105 #-------------------------------------------------------------------
3107 compile_time_unary_operators = {
3108 'not': operator.not_,
3109 '~': operator.inv,
3110 '-': operator.neg,
3111 '+': operator.pos,
3112 }
3114 class UnopNode(ExprNode):
3115 # operator string
3116 # operand ExprNode
3117 #
3118 # Processing during analyse_expressions phase:
3119 #
3120 # analyse_c_operation
3121 # Called when the operand is not a pyobject.
3122 # - Check operand type and coerce if needed.
3123 # - Determine result type and result code fragment.
3124 # - Allocate temporary for result if needed.
3126 subexprs = ['operand']
3128 def compile_time_value(self, denv):
3129 func = compile_time_unary_operators.get(self.operator)
3130 if not func:
3131 error(self.pos,
3132 "Unary '%s' not supported in compile-time expression"
3133 % self.operator)
3134 operand = self.operand.compile_time_value(denv)
3135 try:
3136 return func(operand)
3137 except Exception, e:
3138 self.compile_time_value_error(e)
3140 def analyse_types(self, env):
3141 self.operand.analyse_types(env)
3142 if self.is_py_operation():
3143 self.coerce_operand_to_pyobject(env)
3144 self.type = py_object_type
3145 self.gil_check(env)
3146 self.is_temp = 1
3147 else:
3148 self.analyse_c_operation(env)
3150 def check_const(self):
3151 self.operand.check_const()
3153 def is_py_operation(self):
3154 return self.operand.type.is_pyobject
3156 def coerce_operand_to_pyobject(self, env):
3157 self.operand = self.operand.coerce_to_pyobject(env)
3159 def generate_result_code(self, code):
3160 if self.operand.type.is_pyobject:
3161 self.generate_py_operation_code(code)
3162 else:
3163 if self.is_temp:
3164 self.generate_c_operation_code(code)
3166 def generate_py_operation_code(self, code):
3167 function = self.py_operation_function()
3168 code.putln(
3169 "%s = %s(%s); %s" % (
3170 self.result(),
3171 function,
3172 self.operand.py_result(),
3173 code.error_goto_if_null(self.result(), self.pos)))
3175 def type_error(self):
3176 if not self.operand.type.is_error:
3177 error(self.pos, "Invalid operand type for '%s' (%s)" %
3178 (self.operator, self.operand.type))
3179 self.type = PyrexTypes.error_type
3182 class NotNode(ExprNode):
3183 # 'not' operator
3184 #
3185 # operand ExprNode
3187 def compile_time_value(self, denv):
3188 operand = self.operand.compile_time_value(denv)
3189 try:
3190 return not operand
3191 except Exception, e:
3192 self.compile_time_value_error(e)
3194 subexprs = ['operand']
3196 def analyse_types(self, env):
3197 self.operand.analyse_types(env)
3198 self.operand = self.operand.coerce_to_boolean(env)
3199 self.type = PyrexTypes.c_bint_type
3201 def calculate_result_code(self):
3202 return "(!%s)" % self.operand.result()
3204 def generate_result_code(self, code):
3205 pass
3208 class UnaryPlusNode(UnopNode):
3209 # unary '+' operator
3211 operator = '+'
3213 def analyse_c_operation(self, env):
3214 self.type = self.operand.type
3216 def py_operation_function(self):
3217 return "PyNumber_Positive"
3219 def calculate_result_code(self):
3220 return self.operand.result()
3223 class UnaryMinusNode(UnopNode):
3224 # unary '-' operator
3226 operator = '-'
3228 def analyse_c_operation(self, env):
3229 if self.operand.type.is_numeric:
3230 self.type = self.operand.type
3231 else:
3232 self.type_error()
3234 def py_operation_function(self):
3235 return "PyNumber_Negative"
3237 def calculate_result_code(self):
3238 return "(-%s)" % self.operand.result()
3241 class TildeNode(UnopNode):
3242 # unary '~' operator
3244 def analyse_c_operation(self, env):
3245 if self.operand.type.is_int:
3246 self.type = self.operand.type
3247 else:
3248 self.type_error()
3250 def py_operation_function(self):
3251 return "PyNumber_Invert"
3253 def calculate_result_code(self):
3254 return "(~%s)" % self.operand.result()
3257 class AmpersandNode(ExprNode):
3258 # The C address-of operator.
3259 #
3260 # operand ExprNode
3262 subexprs = ['operand']
3264 def analyse_types(self, env):
3265 self.operand.analyse_types(env)
3266 argtype = self.operand.type
3267 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3268 self.error("Taking address of non-lvalue")
3269 return
3270 if argtype.is_pyobject:
3271 self.error("Cannot take address of Python variable")
3272 return
3273 self.type = PyrexTypes.c_ptr_type(argtype)
3275 def check_const(self):
3276 self.operand.check_const_addr()
3278 def error(self, mess):
3279 error(self.pos, mess)
3280 self.type = PyrexTypes.error_type
3281 self.result_code = "<error>"
3283 def calculate_result_code(self):
3284 return "(&%s)" % self.operand.result()
3286 def generate_result_code(self, code):
3287 pass
3290 unop_node_classes = {
3291 "+": UnaryPlusNode,
3292 "-": UnaryMinusNode,
3293 "~": TildeNode,
3294 }
3296 def unop_node(pos, operator, operand):
3297 # Construct unnop node of appropriate class for
3298 # given operator.
3299 if isinstance(operand, IntNode) and operator == '-':
3300 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3301 elif isinstance(operand, UnopNode) and operand.operator == operator:
3302 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3303 return unop_node_classes[operator](pos,
3304 operator = operator,
3305 operand = operand)
3308 class TypecastNode(ExprNode):
3309 # C type cast
3310 #
3311 # operand ExprNode
3312 # base_type CBaseTypeNode
3313 # declarator CDeclaratorNode
3314 #
3315 # If used from a transform, one can if wanted specify the attribute
3316 # "type" directly and leave base_type and declarator to None
3318 subexprs = ['operand']
3319 base_type = declarator = type = None
3321 def analyse_types(self, env):
3322 if self.type is None:
3323 base_type = self.base_type.analyse(env)
3324 _, self.type = self.declarator.analyse(base_type, env)
3325 if self.type.is_cfunction:
3326 error(self.pos,
3327 "Cannot cast to a function type")
3328 self.type = PyrexTypes.error_type
3329 self.operand.analyse_types(env)
3330 to_py = self.type.is_pyobject
3331 from_py = self.operand.type.is_pyobject
3332 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3333 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3334 if to_py and not from_py:
3335 if self.operand.type.to_py_function:
3336 self.result_ctype = py_object_type
3337 self.operand = self.operand.coerce_to_pyobject(env)
3338 else:
3339 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3340 self.operand = self.operand.coerce_to_simple(env)
3341 elif from_py and not to_py:
3342 if self.type.from_py_function:
3343 self.operand = self.operand.coerce_to(self.type, env)
3344 else:
3345 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3346 elif from_py and to_py:
3347 if self.typecheck and self.type.is_extension_type:
3348 self.operand = PyTypeTestNode(self.operand, self.type, env)
3350 def check_const(self):
3351 self.operand.check_const()
3353 def calculate_result_code(self):
3354 opnd = self.operand
3355 return self.type.cast_code(opnd.result())
3357 def result_as(self, type):
3358 if self.type.is_pyobject and not self.is_temp:
3359 # Optimise away some unnecessary casting
3360 return self.operand.result_as(type)
3361 else:
3362 return ExprNode.result_as(self, type)
3364 def generate_result_code(self, code):
3365 if self.is_temp:
3366 code.putln(
3367 "%s = (PyObject *)%s;" % (
3368 self.result(),
3369 self.operand.result()))
3370 code.put_incref(self.result(), self.ctype())
3373 class SizeofNode(ExprNode):
3374 # Abstract base class for sizeof(x) expression nodes.
3376 type = PyrexTypes.c_int_type
3378 def check_const(self):
3379 pass
3381 def generate_result_code(self, code):
3382 pass
3385 class SizeofTypeNode(SizeofNode):
3386 # C sizeof function applied to a type
3387 #
3388 # base_type CBaseTypeNode
3389 # declarator CDeclaratorNode
3391 subexprs = []
3392 arg_type = None
3394 def analyse_types(self, env):
3395 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
3396 # this could be better handled by more uniformly treating types as runtime-available objects
3397 if 0 and self.base_type.module_path:
3398 path = self.base_type.module_path
3399 obj = env.lookup(path[0])
3400 if obj.as_module is None:
3401 operand = NameNode(pos=self.pos, name=path[0])
3402 for attr in path[1:]:
3403 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
3404 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
3405 self.operand = operand
3406 self.__class__ = SizeofVarNode
3407 self.analyse_types(env)
3408 return
3409 if self.arg_type is None:
3410 base_type = self.base_type.analyse(env)
3411 _, arg_type = self.declarator.analyse(base_type, env)
3412 self.arg_type = arg_type
3413 self.check_type()
3415 def check_type(self):
3416 arg_type = self.arg_type
3417 if arg_type.is_pyobject and not arg_type.is_extension_type:
3418 error(self.pos, "Cannot take sizeof Python object")
3419 elif arg_type.is_void:
3420 error(self.pos, "Cannot take sizeof void")
3421 elif not arg_type.is_complete():
3422 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
3424 def calculate_result_code(self):
3425 if self.arg_type.is_extension_type:
3426 # the size of the pointer is boring
3427 # we want the size of the actual struct
3428 arg_code = self.arg_type.declaration_code("", deref=1)
3429 else:
3430 arg_code = self.arg_type.declaration_code("")
3431 return "(sizeof(%s))" % arg_code
3434 class SizeofVarNode(SizeofNode):
3435 # C sizeof function applied to a variable
3436 #
3437 # operand ExprNode
3439 subexprs = ['operand']
3441 def analyse_types(self, env):
3442 # We may actually be looking at a type rather than a variable...
3443 # If we are, traditional analysis would fail...
3444 operand_as_type = self.operand.analyse_as_type(env)
3445 if operand_as_type:
3446 self.arg_type = operand_as_type
3447 self.__class__ = SizeofTypeNode
3448 self.check_type()
3449 else:
3450 self.operand.analyse_types(env)
3452 def calculate_result_code(self):
3453 return "(sizeof(%s))" % self.operand.result()
3455 def generate_result_code(self, code):
3456 pass
3459 #-------------------------------------------------------------------
3460 #
3461 # Binary operator nodes
3462 #
3463 #-------------------------------------------------------------------
3465 def _not_in(x, seq):
3466 return x not in seq
3468 compile_time_binary_operators = {
3469 '<': operator.lt,
3470 '<=': operator.le,
3471 '==': operator.eq,
3472 '!=': operator.ne,
3473 '>=': operator.ge,
3474 '>': operator.gt,
3475 'is': operator.is_,
3476 'is_not': operator.is_not,
3477 '+': operator.add,
3478 '&': operator.and_,
3479 '/': operator.div,
3480 '//': operator.floordiv,
3481 '<<': operator.lshift,
3482 '%': operator.mod,
3483 '*': operator.mul,
3484 '|': operator.or_,
3485 '**': operator.pow,
3486 '>>': operator.rshift,
3487 '-': operator.sub,
3488 #'/': operator.truediv,
3489 '^': operator.xor,
3490 'in': operator.contains,
3491 'not_in': _not_in,
3492 }
3494 def get_compile_time_binop(node):
3495 func = compile_time_binary_operators.get(node.operator)
3496 if not func:
3497 error(node.pos,
3498 "Binary '%s' not supported in compile-time expression"
3499 % node.operator)
3500 return func
3502 class BinopNode(NewTempExprNode):
3503 # operator string
3504 # operand1 ExprNode
3505 # operand2 ExprNode
3506 #
3507 # Processing during analyse_expressions phase:
3508 #
3509 # analyse_c_operation
3510 # Called when neither operand is a pyobject.
3511 # - Check operand types and coerce if needed.
3512 # - Determine result type and result code fragment.
3513 # - Allocate temporary for result if needed.
3515 subexprs = ['operand1', 'operand2']
3517 def compile_time_value(self, denv):
3518 func = get_compile_time_binop(self)
3519 operand1 = self.operand1.compile_time_value(denv)
3520 operand2 = self.operand2.compile_time_value(denv)
3521 try:
3522 return func(operand1, operand2)
3523 except Exception, e:
3524 self.compile_time_value_error(e)
3526 def analyse_types(self, env):
3527 self.operand1.analyse_types(env)
3528 self.operand2.analyse_types(env)
3529 if self.is_py_operation():
3530 self.coerce_operands_to_pyobjects(env)
3531 self.type = py_object_type
3532 self.gil_check(env)
3533 self.is_temp = 1
3534 if Options.incref_local_binop and self.operand1.type.is_pyobject:
3535 self.operand1 = self.operand1.coerce_to_temp(env)
3536 else:
3537 self.analyse_c_operation(env)
3539 def is_py_operation(self):
3540 return (self.operand1.type.is_pyobject
3541 or self.operand2.type.is_pyobject)
3543 def coerce_operands_to_pyobjects(self, env):
3544 self.operand1 = self.operand1.coerce_to_pyobject(env)
3545 self.operand2 = self.operand2.coerce_to_pyobject(env)
3547 def check_const(self):
3548 self.operand1.check_const()
3549 self.operand2.check_const()
3551 def generate_result_code(self, code):
3552 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
3553 if self.operand1.type.is_pyobject:
3554 function = self.py_operation_function()
3555 if function == "PyNumber_Power":
3556 extra_args = ", Py_None"
3557 else:
3558 extra_args = ""
3559 code.putln(
3560 "%s = %s(%s, %s%s); %s" % (
3561 self.result(),
3562 function,
3563 self.operand1.py_result(),
3564 self.operand2.py_result(),
3565 extra_args,
3566 code.error_goto_if_null(self.result(), self.pos)))
3567 else:
3568 if self.is_temp:
3569 self.generate_c_operation_code(code)
3571 def type_error(self):
3572 if not (self.operand1.type.is_error
3573 or self.operand2.type.is_error):
3574 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
3575 (self.operator, self.operand1.type,
3576 self.operand2.type))
3577 self.type = PyrexTypes.error_type
3580 class NumBinopNode(BinopNode):
3581 # Binary operation taking numeric arguments.
3583 def analyse_c_operation(self, env):
3584 type1 = self.operand1.type
3585 type2 = self.operand2.type
3586 if self.operator == "**" and type1.is_int and type2.is_int:
3587 error(self.pos, "** with two C int types is ambiguous")
3588 self.type = error_type
3589 return
3590 self.type = self.compute_c_result_type(type1, type2)
3591 if not self.type:
3592 self.type_error()
3594 def compute_c_result_type(self, type1, type2):
3595 if self.c_types_okay(type1, type2):
3596 return PyrexTypes.widest_numeric_type(type1, type2)
3597 else:
3598 return None
3600 def c_types_okay(self, type1, type2):
3601 #print "NumBinopNode.c_types_okay:", type1, type2 ###
3602 return (type1.is_numeric or type1.is_enum) \
3603 and (type2.is_numeric or type2.is_enum)
3605 def calculate_result_code(self):
3606 return "(%s %s %s)" % (
3607 self.operand1.result(),
3608 self.operator,
3609 self.operand2.result())
3611 def py_operation_function(self):
3612 return self.py_functions[self.operator]
3614 py_functions = {
3615 "|": "PyNumber_Or",
3616 "^": "PyNumber_Xor",
3617 "&": "PyNumber_And",
3618 "<<": "PyNumber_Lshift",
3619 ">>": "PyNumber_Rshift",
3620 "+": "PyNumber_Add",
3621 "-": "PyNumber_Subtract",
3622 "*": "PyNumber_Multiply",
3623 "/": "__Pyx_PyNumber_Divide",
3624 "//": "PyNumber_FloorDivide",
3625 "%": "PyNumber_Remainder",
3626 "**": "PyNumber_Power"
3627 }
3630 class IntBinopNode(NumBinopNode):
3631 # Binary operation taking integer arguments.
3633 def c_types_okay(self, type1, type2):
3634 #print "IntBinopNode.c_types_okay:", type1, type2 ###
3635 return (type1.is_int or type1.is_enum) \
3636 and (type2.is_int or type2.is_enum)
3639 class AddNode(NumBinopNode):
3640 # '+' operator.
3642 def is_py_operation(self):
3643 if self.operand1.type.is_string \
3644 and self.operand2.type.is_string:
3645 return 1
3646 else:
3647 return NumBinopNode.is_py_operation(self)
3649 def compute_c_result_type(self, type1, type2):
3650 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
3651 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3652 return type1
3653 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
3654 return type2
3655 else:
3656 return NumBinopNode.compute_c_result_type(
3657 self, type1, type2)
3660 class SubNode(NumBinopNode):
3661 # '-' operator.
3663 def compute_c_result_type(self, type1, type2):
3664 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
3665 return type1
3666 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
3667 return PyrexTypes.c_int_type
3668 else:
3669 return NumBinopNode.compute_c_result_type(
3670 self, type1, type2)
3673 class MulNode(NumBinopNode):
3674 # '*' operator.
3676 def is_py_operation(self):
3677 type1 = self.operand1.type
3678 type2 = self.operand2.type
3679 if (type1.is_string and type2.is_int) \
3680 or (type2.is_string and type1.is_int):
3681 return 1
3682 else:
3683 return NumBinopNode.is_py_operation(self)
3686 class FloorDivNode(NumBinopNode):
3687 # '//' operator.
3689 def calculate_result_code(self):
3690 return "(%s %s %s)" % (
3691 self.operand1.result(),
3692 "/", # c division is by default floor-div
3693 self.operand2.result())
3696 class ModNode(NumBinopNode):
3697 # '%' operator.
3699 def is_py_operation(self):
3700 return (self.operand1.type.is_string
3701 or self.operand2.type.is_string
3702 or NumBinopNode.is_py_operation(self))
3704 def calculate_result_code(self):
3705 if self.operand1.type.is_float or self.operand2.type.is_float:
3706 return "fmod(%s, %s)" % (
3707 self.operand1.result(),
3708 self.operand2.result())
3709 else:
3710 return "(%s %% %s)" % (
3711 self.operand1.result(),
3712 self.operand2.result())
3714 class PowNode(NumBinopNode):
3715 # '**' operator.
3717 def compute_c_result_type(self, type1, type2):
3718 if self.c_types_okay(type1, type2):
3719 return PyrexTypes.c_double_type
3720 else:
3721 return None
3723 def c_types_okay(self, type1, type2):
3724 return (type1.is_float or type2.is_float) and \
3725 NumBinopNode.c_types_okay(self, type1, type2)
3727 def type_error(self):
3728 if not (self.operand1.type.is_error or self.operand2.type.is_error):
3729 if self.operand1.type.is_int and self.operand2.type.is_int:
3730 error(self.pos, "C has no integer powering, use python ints or floats instead '%s' (%s; %s)" %
3731 (self.operator, self.operand1.type, self.operand2.type))
3732 else:
3733 NumBinopNode.type_error(self)
3734 self.type = PyrexTypes.error_type
3736 def calculate_result_code(self):
3737 return "pow(%s, %s)" % (
3738 self.operand1.result(), self.operand2.result())
3741 class BoolBinopNode(ExprNode):
3742 # Short-circuiting boolean operation.
3743 #
3744 # operator string
3745 # operand1 ExprNode
3746 # operand2 ExprNode
3747 # temp_bool ExprNode used internally
3749 temp_bool = None
3751 subexprs = ['operand1', 'operand2', 'temp_bool']
3753 def compile_time_value(self, denv):
3754 if self.operator == 'and':
3755 return self.operand1.compile_time_value(denv) \
3756 and self.operand2.compile_time_value(denv)
3757 else:
3758 return self.operand1.compile_time_value(denv) \
3759 or self.operand2.compile_time_value(denv)
3761 def analyse_types(self, env):
3762 self.operand1.analyse_types(env)
3763 self.operand2.analyse_types(env)
3764 if self.operand1.type.is_pyobject or \
3765 self.operand2.type.is_pyobject:
3766 self.operand1 = self.operand1.coerce_to_pyobject(env)
3767 self.operand2 = self.operand2.coerce_to_pyobject(env)
3768 self.temp_bool = TempNode(self.pos, PyrexTypes.c_bint_type, env)
3769 self.type = py_object_type
3770 self.gil_check(env)
3771 else:
3772 self.operand1 = self.operand1.coerce_to_boolean(env)
3773 self.operand2 = self.operand2.coerce_to_boolean(env)
3774 self.type = PyrexTypes.c_bint_type
3775 # For what we're about to do, it's vital that
3776 # both operands be temp nodes.
3777 self.operand1 = self.operand1.coerce_to_temp(env) #CTT
3778 self.operand2 = self.operand2.coerce_to_temp(env)
3779 self.is_temp = 1
3781 gil_message = "Truth-testing Python object"
3783 def allocate_temps(self, env, result_code = None):
3784 # We don't need both operands at the same time, and
3785 # one of the operands will also be our result. So we
3786 # use an allocation strategy here which results in
3787 # this node and both its operands sharing the same
3788 # result variable. This allows us to avoid some
3789 # assignments and increfs/decrefs that would otherwise
3790 # be necessary.
3791 self.allocate_temp(env, result_code)
3792 self.operand1.allocate_temps(env, self.result())
3793 if self.temp_bool:
3794 self.temp_bool.allocate_temp(env)
3795 self.temp_bool.release_temp(env)
3796 self.operand2.allocate_temps(env, self.result())
3797 # We haven't called release_temp on either operand,
3798 # because although they are temp nodes, they don't own
3799 # their result variable. And because they are temp
3800 # nodes, any temps in their subnodes will have been
3801 # released before their allocate_temps returned.
3802 # Therefore, they contain no temp vars that need to
3803 # be released.
3805 def check_const(self):
3806 self.operand1.check_const()
3807 self.operand2.check_const()
3809 def calculate_result_code(self):
3810 return "(%s %s %s)" % (
3811 self.operand1.result(),
3812 self.py_to_c_op[self.operator],
3813 self.operand2.result())
3815 py_to_c_op = {'and': "&&", 'or': "||"}
3817 def generate_evaluation_code(self, code):
3818 self.operand1.generate_evaluation_code(code)
3819 test_result = self.generate_operand1_test(code)
3820 if self.operator == 'and':
3821 sense = ""
3822 else:
3823 sense = "!"
3824 code.putln(
3825 "if (%s%s) {" % (
3826 sense,
3827 test_result))
3828 self.operand1.generate_disposal_code(code)
3829 self.operand2.generate_evaluation_code(code)
3830 code.putln(
3831 "}")
3833 def generate_operand1_test(self, code):
3834 # Generate code to test the truth of the first operand.
3835 if self.type.is_pyobject:
3836 test_result = self.temp_bool.result()
3837 code.putln(
3838 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
3839 test_result,
3840 self.operand1.py_result(),
3841 code.error_goto_if_neg(test_result, self.pos)))
3842 else:
3843 test_result = self.operand1.result()
3844 return test_result
3847 class CondExprNode(ExprNode):
3848 # Short-circuiting conditional expression.
3849 #
3850 # test ExprNode
3851 # true_val ExprNode
3852 # false_val ExprNode
3854 temp_bool = None
3855 true_val = None
3856 false_val = None
3858 subexprs = ['test', 'true_val', 'false_val']
3860 def analyse_types(self, env):
3861 self.test.analyse_types(env)
3862 self.test = self.test.coerce_to_boolean(env)
3863 self.true_val.analyse_types(env)
3864 self.false_val.analyse_types(env)
3865 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
3866 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
3867 self.true_val = self.true_val.coerce_to(self.type, env)
3868 self.false_val = self.false_val.coerce_to(self.type, env)
3869 # must be tmp variables so they can share a result
3870 self.true_val = self.true_val.coerce_to_temp(env)
3871 self.false_val = self.false_val.coerce_to_temp(env)
3872 self.is_temp = 1
3873 if self.type == PyrexTypes.error_type:
3874 self.type_error()
3876 def allocate_temps(self, env, result_code = None):
3877 # We only ever evaluate one side, and this is
3878 # after evaluating the truth value, so we may
3879 # use an allocation strategy here which results in
3880 # this node and both its operands sharing the same
3881 # result variable. This allows us to avoid some
3882 # assignments and increfs/decrefs that would otherwise
3883 # be necessary.
3884 self.allocate_temp(env, result_code)
3885 self.test.allocate_temps(env, result_code)
3886 self.true_val.allocate_temps(env, self.result())
3887 self.false_val.allocate_temps(env, self.result())
3888 # We haven't called release_temp on either value,
3889 # because although they are temp nodes, they don't own
3890 # their result variable. And because they are temp
3891 # nodes, any temps in their subnodes will have been
3892 # released before their allocate_temps returned.
3893 # Therefore, they contain no temp vars that need to
3894 # be released.
3896 def compute_result_type(self, type1, type2):
3897 if type1 == type2:
3898 return type1
3899 elif type1.is_numeric and type2.is_numeric:
3900 return PyrexTypes.widest_numeric_type(type1, type2)
3901 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
3902 return type2
3903 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
3904 return type1
3905 elif type1.is_pyobject or type2.is_pyobject:
3906 return py_object_type
3907 elif type1.assignable_from(type2):
3908 return type1
3909 elif type2.assignable_from(type1):
3910 return type2
3911 else:
3912 return PyrexTypes.error_type
3914 def type_error(self):
3915 if not (self.true_val.type.is_error or self.false_val.type.is_error):
3916 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
3917 (self.true_val.type, self.false_val.type))
3918 self.type = PyrexTypes.error_type
3920 def check_const(self):
3921 self.test.check_const()
3922 self.true_val.check_const()
3923 self.false_val.check_const()
3925 def generate_evaluation_code(self, code):
3926 self.test.generate_evaluation_code(code)
3927 code.putln("if (%s) {" % self.test.result() )
3928 self.true_val.generate_evaluation_code(code)
3929 code.putln("} else {")
3930 self.false_val.generate_evaluation_code(code)
3931 code.putln("}")
3932 self.test.generate_disposal_code(code)
3934 richcmp_constants = {
3935 "<" : "Py_LT",
3936 "<=": "Py_LE",
3937 "==": "Py_EQ",
3938 "!=": "Py_NE",
3939 "<>": "Py_NE",
3940 ">" : "Py_GT",
3941 ">=": "Py_GE",
3942 }
3944 class CmpNode:
3945 # Mixin class containing code common to PrimaryCmpNodes
3946 # and CascadedCmpNodes.
3948 def cascaded_compile_time_value(self, operand1, denv):
3949 func = get_compile_time_binop(self)
3950 operand2 = self.operand2.compile_time_value(denv)
3951 try:
3952 result = func(operand1, operand2)
3953 except Exception, e:
3954 self.compile_time_value_error(e)
3955 result = None
3956 if result:
3957 cascade = self.cascade
3958 if cascade:
3959 result = result and cascade.compile_time_value(operand2, denv)
3960 return result
3962 def is_python_comparison(self):
3963 return (self.has_python_operands()
3964 or (self.cascade and self.cascade.is_python_comparison())
3965 or self.operator in ('in', 'not_in'))
3967 def is_python_result(self):
3968 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
3969 or (self.cascade and self.cascade.is_python_result()))
3971 def check_types(self, env, operand1, op, operand2):
3972 if not self.types_okay(operand1, op, operand2):
3973 error(self.pos, "Invalid types for '%s' (%s, %s)" %
3974 (self.operator, operand1.type, operand2.type))
3976 def types_okay(self, operand1, op, operand2):
3977 type1 = operand1.type
3978 type2 = operand2.type
3979 if type1.is_error or type2.is_error:
3980 return 1
3981 if type1.is_pyobject: # type2 will be, too
3982 return 1
3983 elif type1.is_ptr or type1.is_array:
3984 return type1.is_null_ptr or type2.is_null_ptr \
3985 or ((type2.is_ptr or type2.is_array)
3986 and type1.base_type.same_as(type2.base_type))
3987 elif ((type1.is_numeric and type2.is_numeric
3988 or type1.is_enum and (type1 is type2 or type2.is_int)
3989 or type1.is_int and type2.is_enum)
3990 and op not in ('is', 'is_not')):
3991 return 1
3992 else:
3993 return type1.is_cfunction and type1.is_cfunction and type1 == type2
3995 def generate_operation_code(self, code, result_code,
3996 operand1, op , operand2):
3997 if self.type is PyrexTypes.py_object_type:
3998 coerce_result = "__Pyx_PyBool_FromLong"
3999 else:
4000 coerce_result = ""
4001 if 'not' in op: negation = "!"
4002 else: negation = ""
4003 if op == 'in' or op == 'not_in':
4004 code.putln(
4005 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4006 result_code,
4007 coerce_result,
4008 negation,
4009 operand2.py_result(),
4010 operand1.py_result(),
4011 code.error_goto_if_neg(result_code, self.pos)))
4012 elif (operand1.type.is_pyobject
4013 and op not in ('is', 'is_not')):
4014 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4015 result_code,
4016 operand1.py_result(),
4017 operand2.py_result(),
4018 richcmp_constants[op],
4019 code.error_goto_if_null(result_code, self.pos)))
4020 else:
4021 type1 = operand1.type
4022 type2 = operand2.type
4023 if (type1.is_extension_type or type2.is_extension_type) \
4024 and not type1.same_as(type2):
4025 common_type = py_object_type
4026 elif type1.is_numeric:
4027 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4028 else:
4029 common_type = type1
4030 code1 = operand1.result_as(common_type)
4031 code2 = operand2.result_as(common_type)
4032 code.putln("%s = %s(%s %s %s);" % (
4033 result_code,
4034 coerce_result,
4035 code1,
4036 self.c_operator(op),
4037 code2))
4039 def c_operator(self, op):
4040 if op == 'is':
4041 return "=="
4042 elif op == 'is_not':
4043 return "!="
4044 else:
4045 return op
4048 class PrimaryCmpNode(ExprNode, CmpNode):
4049 # Non-cascaded comparison or first comparison of
4050 # a cascaded sequence.
4051 #
4052 # operator string
4053 # operand1 ExprNode
4054 # operand2 ExprNode
4055 # cascade CascadedCmpNode
4057 # We don't use the subexprs mechanism, because
4058 # things here are too complicated for it to handle.
4059 # Instead, we override all the framework methods
4060 # which use it.
4062 child_attrs = ['operand1', 'operand2', 'cascade']
4064 cascade = None
4066 def compile_time_value(self, denv):
4067 operand1 = self.operand1.compile_time_value(denv)
4068 return self.cascaded_compile_time_value(operand1, denv)
4070 def analyse_types(self, env):
4071 self.operand1.analyse_types(env)
4072 self.operand2.analyse_types(env)
4073 if self.cascade:
4074 self.cascade.analyse_types(env, self.operand2)
4075 self.is_pycmp = self.is_python_comparison()
4076 if self.is_pycmp:
4077 self.coerce_operands_to_pyobjects(env)
4078 if self.has_int_operands():
4079 self.coerce_chars_to_ints(env)
4080 if self.cascade:
4081 self.operand2 = self.operand2.coerce_to_simple(env)
4082 self.cascade.coerce_cascaded_operands_to_temp(env)
4083 self.check_operand_types(env)
4084 if self.is_python_result():
4085 self.type = PyrexTypes.py_object_type
4086 else:
4087 self.type = PyrexTypes.c_bint_type
4088 cdr = self.cascade
4089 while cdr:
4090 cdr.type = self.type
4091 cdr = cdr.cascade
4092 if self.is_pycmp or self.cascade:
4093 self.is_temp = 1
4095 def check_operand_types(self, env):
4096 self.check_types(env,
4097 self.operand1, self.operator, self.operand2)
4098 if self.cascade:
4099 self.cascade.check_operand_types(env, self.operand2)
4101 def has_python_operands(self):
4102 return (self.operand1.type.is_pyobject
4103 or self.operand2.type.is_pyobject)
4105 def coerce_operands_to_pyobjects(self, env):
4106 self.operand1 = self.operand1.coerce_to_pyobject(env)
4107 self.operand2 = self.operand2.coerce_to_pyobject(env)
4108 if self.cascade:
4109 self.cascade.coerce_operands_to_pyobjects(env)
4111 def has_int_operands(self):
4112 return (self.operand1.type.is_int or self.operand2.type.is_int) \
4113 or (self.cascade and self.cascade.has_int_operands())
4115 def coerce_chars_to_ints(self, env):
4116 # coerce literal single-char strings to c chars
4117 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
4118 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
4119 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4120 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4121 if self.cascade:
4122 self.cascade.coerce_chars_to_ints(env)
4124 def allocate_subexpr_temps(self, env):
4125 self.operand1.allocate_temps(env)
4126 self.operand2.allocate_temps(env)
4127 if self.cascade:
4128 self.cascade.allocate_subexpr_temps(env)
4130 def release_subexpr_temps(self, env):
4131 self.operand1.release_temp(env)
4132 self.operand2.release_temp(env)
4133 if self.cascade:
4134 self.cascade.release_subexpr_temps(env)
4136 def check_const(self):
4137 self.operand1.check_const()
4138 self.operand2.check_const()
4139 if self.cascade:
4140 self.not_const()
4142 def calculate_result_code(self):
4143 return "(%s %s %s)" % (
4144 self.operand1.result(),
4145 self.c_operator(self.operator),
4146 self.operand2.result())
4148 def generate_evaluation_code(self, code):
4149 self.operand1.generate_evaluation_code(code)
4150 self.operand2.generate_evaluation_code(code)
4151 if self.is_temp:
4152 self.generate_operation_code(code, self.result(),
4153 self.operand1, self.operator, self.operand2)
4154 if self.cascade:
4155 self.cascade.generate_evaluation_code(code,
4156 self.result(), self.operand2)
4157 self.operand1.generate_disposal_code(code)
4158 self.operand2.generate_disposal_code(code)
4160 def generate_subexpr_disposal_code(self, code):
4161 # If this is called, it is a non-cascaded cmp,
4162 # so only need to dispose of the two main operands.
4163 self.operand1.generate_disposal_code(code)
4164 self.operand2.generate_disposal_code(code)
4166 def annotate(self, code):
4167 self.operand1.annotate(code)
4168 self.operand2.annotate(code)
4169 if self.cascade:
4170 self.cascade.annotate(code)
4173 class CascadedCmpNode(Node, CmpNode):
4174 # A CascadedCmpNode is not a complete expression node. It
4175 # hangs off the side of another comparison node, shares
4176 # its left operand with that node, and shares its result
4177 # with the PrimaryCmpNode at the head of the chain.
4178 #
4179 # operator string
4180 # operand2 ExprNode
4181 # cascade CascadedCmpNode
4183 child_attrs = ['operand2', 'cascade']
4185 cascade = None
4187 def analyse_types(self, env, operand1):
4188 self.operand2.analyse_types(env)
4189 if self.cascade:
4190 self.cascade.analyse_types(env, self.operand2)
4192 def check_operand_types(self, env, operand1):
4193 self.check_types(env,
4194 operand1, self.operator, self.operand2)
4195 if self.cascade:
4196 self.cascade.check_operand_types(env, self.operand2)
4198 def has_python_operands(self):
4199 return self.operand2.type.is_pyobject
4201 def coerce_operands_to_pyobjects(self, env):
4202 self.operand2 = self.operand2.coerce_to_pyobject(env)
4203 if self.cascade:
4204 self.cascade.coerce_operands_to_pyobjects(env)
4206 def has_int_operands(self):
4207 return self.operand2.type.is_int
4209 def coerce_chars_to_ints(self, env):
4210 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
4211 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
4213 def coerce_cascaded_operands_to_temp(self, env):
4214 if self.cascade:
4215 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
4216 self.operand2 = self.operand2.coerce_to_simple(env)
4217 self.cascade.coerce_cascaded_operands_to_temp(env)
4219 def allocate_subexpr_temps(self, env):
4220 self.operand2.allocate_temps(env)
4221 if self.cascade:
4222 self.cascade.allocate_subexpr_temps(env)
4224 def release_subexpr_temps(self, env):
4225 self.operand2.release_temp(env)
4226 if self.cascade:
4227 self.cascade.release_subexpr_temps(env)
4229 def generate_evaluation_code(self, code, result, operand1):
4230 if self.type.is_pyobject:
4231 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
4232 else:
4233 code.putln("if (%s) {" % result)
4234 self.operand2.generate_evaluation_code(code)
4235 self.generate_operation_code(code, result,
4236 operand1, self.operator, self.operand2)
4237 if self.cascade:
4238 self.cascade.generate_evaluation_code(
4239 code, result, self.operand2)
4240 # Cascaded cmp result is always temp
4241 self.operand2.generate_disposal_code(code)
4242 code.putln("}")
4244 def annotate(self, code):
4245 self.operand2.annotate(code)
4246 if self.cascade:
4247 self.cascade.annotate(code)
4250 binop_node_classes = {
4251 "or": BoolBinopNode,
4252 "and": BoolBinopNode,
4253 "|": IntBinopNode,
4254 "^": IntBinopNode,
4255 "&": IntBinopNode,
4256 "<<": IntBinopNode,
4257 ">>": IntBinopNode,
4258 "+": AddNode,
4259 "-": SubNode,
4260 "*": MulNode,
4261 "/": NumBinopNode,
4262 "//": FloorDivNode,
4263 "%": ModNode,
4264 "**": PowNode
4265 }
4267 def binop_node(pos, operator, operand1, operand2):
4268 # Construct binop node of appropriate class for
4269 # given operator.
4270 return binop_node_classes[operator](pos,
4271 operator = operator,
4272 operand1 = operand1,
4273 operand2 = operand2)
4275 #-------------------------------------------------------------------
4276 #
4277 # Coercion nodes
4278 #
4279 # Coercion nodes are special in that they are created during
4280 # the analyse_types phase of parse tree processing.
4281 # Their __init__ methods consequently incorporate some aspects
4282 # of that phase.
4283 #
4284 #-------------------------------------------------------------------
4286 class CoercionNode(ExprNode):
4287 # Abstract base class for coercion nodes.
4288 #
4289 # arg ExprNode node being coerced
4291 subexprs = ['arg']
4293 def __init__(self, arg):
4294 self.pos = arg.pos
4295 self.arg = arg
4296 if debug_coercion:
4297 print("%s Coercing %s" % (self, self.arg))
4299 def annotate(self, code):
4300 self.arg.annotate(code)
4301 if self.arg.type != self.type:
4302 file, line, col = self.pos
4303 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
4306 class CastNode(CoercionNode):
4307 # Wrap a node in a C type cast.
4309 def __init__(self, arg, new_type):
4310 CoercionNode.__init__(self, arg)
4311 self.type = new_type
4313 def calculate_result_code(self):
4314 return self.arg.result_as(self.type)
4316 def generate_result_code(self, code):
4317 self.arg.generate_result_code(code)
4320 class PyTypeTestNode(CoercionNode):
4321 # This node is used to check that a generic Python
4322 # object is an instance of a particular extension type.
4323 # This node borrows the result of its argument node.
4325 def __init__(self, arg, dst_type, env):
4326 # The arg is know to be a Python object, and
4327 # the dst_type is known to be an extension type.
4328 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
4329 CoercionNode.__init__(self, arg)
4330 self.type = dst_type
4331 self.gil_check(env)
4332 self.result_ctype = arg.ctype()
4333 env.use_utility_code(type_test_utility_code)
4335 gil_message = "Python type test"
4337 def analyse_types(self, env):
4338 pass
4340 def result_in_temp(self):
4341 return self.arg.result_in_temp()
4343 def is_ephemeral(self):
4344 return self.arg.is_ephemeral()
4346 def calculate_result_code(self):
4347 return self.arg.result()
4349 def generate_result_code(self, code):
4350 if self.type.typeobj_is_available():
4351 code.putln(
4352 "if (!(%s)) %s" % (
4353 self.type.type_test_code(self.arg.py_result()),
4354 code.error_goto(self.pos)))
4355 else:
4356 error(self.pos, "Cannot test type of extern C class "
4357 "without type object name specification")
4359 def generate_post_assignment_code(self, code):
4360 self.arg.generate_post_assignment_code(code)
4363 class CoerceToPyTypeNode(CoercionNode):
4364 # This node is used to convert a C data type
4365 # to a Python object.
4367 def __init__(self, arg, env):
4368 CoercionNode.__init__(self, arg)
4369 self.type = py_object_type
4370 self.gil_check(env)
4371 self.is_temp = 1
4372 if not arg.type.to_py_function:
4373 error(arg.pos,
4374 "Cannot convert '%s' to Python object" % arg.type)
4376 gil_message = "Converting to Python object"
4378 def analyse_types(self, env):
4379 # The arg is always already analysed
4380 pass
4382 def generate_result_code(self, code):
4383 function = self.arg.type.to_py_function
4384 code.putln('%s = %s(%s); %s' % (
4385 self.result(),
4386 function,
4387 self.arg.result(),
4388 code.error_goto_if_null(self.result(), self.pos)))
4391 class CoerceFromPyTypeNode(CoercionNode):
4392 # This node is used to convert a Python object
4393 # to a C data type.
4395 def __init__(self, result_type, arg, env):
4396 CoercionNode.__init__(self, arg)
4397 self.type = result_type
4398 self.is_temp = 1
4399 if not result_type.from_py_function:
4400 error(arg.pos,
4401 "Cannot convert Python object to '%s'" % result_type)
4402 if self.type.is_string and self.arg.is_ephemeral():
4403 error(arg.pos,
4404 "Obtaining char * from temporary Python value")
4406 def analyse_types(self, env):
4407 # The arg is always already analysed
4408 pass
4410 def generate_result_code(self, code):
4411 function = self.type.from_py_function
4412 operand = self.arg.py_result()
4413 rhs = "%s(%s)" % (function, operand)
4414 if self.type.is_enum:
4415 rhs = typecast(self.type, c_long_type, rhs)
4416 code.putln('%s = %s; %s' % (
4417 self.result(),
4418 rhs,
4419 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
4422 class CoerceToBooleanNode(CoercionNode):
4423 # This node is used when a result needs to be used
4424 # in a boolean context.
4426 def __init__(self, arg, env):
4427 CoercionNode.__init__(self, arg)
4428 self.type = PyrexTypes.c_bint_type
4429 if arg.type.is_pyobject:
4430 if env.nogil:
4431 self.gil_error()
4432 self.is_temp = 1
4434 gil_message = "Truth-testing Python object"
4436 def check_const(self):
4437 if self.is_temp:
4438 self.not_const()
4439 self.arg.check_const()
4441 def calculate_result_code(self):
4442 return "(%s != 0)" % self.arg.result()
4444 def generate_result_code(self, code):
4445 if self.arg.type.is_pyobject:
4446 code.putln(
4447 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4448 self.result(),
4449 self.arg.py_result(),
4450 code.error_goto_if_neg(self.result(), self.pos)))
4453 class CoerceToTempNode(CoercionNode):
4454 # This node is used to force the result of another node
4455 # to be stored in a temporary. It is only used if the
4456 # argument node's result is not already in a temporary.
4458 def __init__(self, arg, env):
4459 CoercionNode.__init__(self, arg)
4460 self.type = self.arg.type
4461 self.is_temp = 1
4462 if self.type.is_pyobject:
4463 self.gil_check(env)
4464 self.result_ctype = py_object_type
4466 gil_message = "Creating temporary Python reference"
4468 def analyse_types(self, env):
4469 # The arg is always already analysed
4470 pass
4472 def generate_result_code(self, code):
4473 #self.arg.generate_evaluation_code(code) # Already done
4474 # by generic generate_subexpr_evaluation_code!
4475 code.putln("%s = %s;" % (
4476 self.result(), self.arg.result_as(self.ctype())))
4477 if self.type.is_pyobject:
4478 code.put_incref(self.result(), self.ctype())
4481 class CloneNode(CoercionNode):
4482 # This node is employed when the result of another node needs
4483 # to be used multiple times. The argument node's result must
4484 # be in a temporary. This node "borrows" the result from the
4485 # argument node, and does not generate any evaluation or
4486 # disposal code for it. The original owner of the argument
4487 # node is responsible for doing those things.
4489 subexprs = [] # Arg is not considered a subexpr
4491 def __init__(self, arg):
4492 CoercionNode.__init__(self, arg)
4493 if hasattr(arg, 'type'):
4494 self.type = arg.type
4495 self.result_ctype = arg.result_ctype
4496 if hasattr(arg, 'entry'):
4497 self.entry = arg.entry
4499 def result(self):
4500 return self.arg.result()
4502 def analyse_types(self, env):
4503 self.type = self.arg.type
4504 self.result_ctype = self.arg.result_ctype
4505 self.is_temp = 1
4506 if hasattr(self.arg, 'entry'):
4507 self.entry = self.arg.entry
4509 def generate_evaluation_code(self, code):
4510 pass
4512 def generate_result_code(self, code):
4513 pass
4515 def generate_disposal_code(self, code):
4516 pass
4518 def allocate_temps(self, env):
4519 pass
4521 def release_temp(self, env):
4522 pass
4524 class PersistentNode(ExprNode):
4525 # A PersistentNode is like a CloneNode except it handles the temporary
4526 # allocation itself by keeping track of the number of times it has been
4527 # used.
4529 subexprs = ["arg"]
4530 temp_counter = 0
4531 generate_counter = 0
4532 analyse_counter = 0
4533 result_code = None
4535 def __init__(self, arg, uses):
4536 self.pos = arg.pos
4537 self.arg = arg
4538 self.uses = uses
4540 def analyse_types(self, env):
4541 if self.analyse_counter == 0:
4542 self.arg.analyse_types(env)
4543 self.type = self.arg.type
4544 self.result_ctype = self.arg.result_ctype
4545 self.is_temp = 1
4546 self.analyse_counter += 1
4548 def calculate_result_code(self):
4549 return self.result()
4551 def generate_evaluation_code(self, code):
4552 if self.generate_counter == 0:
4553 self.arg.generate_evaluation_code(code)
4554 code.putln("%s = %s;" % (
4555 self.result(), self.arg.result_as(self.ctype())))
4556 if self.type.is_pyobject:
4557 code.put_incref(self.result(), self.ctype())
4558 self.arg.generate_disposal_code(code)
4559 self.generate_counter += 1
4561 def generate_disposal_code(self, code):
4562 if self.generate_counter == self.uses:
4563 if self.type.is_pyobject:
4564 code.put_decref_clear(self.result(), self.ctype())
4566 def allocate_temps(self, env, result=None):
4567 if self.temp_counter == 0:
4568 self.arg.allocate_temps(env)
4569 self.allocate_temp(env, result)
4570 self.arg.release_temp(env)
4571 self.temp_counter += 1
4573 def allocate_temp(self, env, result=None):
4574 if result is None:
4575 self.result_code = env.allocate_temp(self.type)
4576 else:
4577 self.result_code = result
4579 def release_temp(self, env):
4580 if self.temp_counter == self.uses:
4581 env.release_temp(self.result())
4583 #------------------------------------------------------------------------------------
4584 #
4585 # Runtime support code
4586 #
4587 #------------------------------------------------------------------------------------
4589 get_name_interned_utility_code = [
4590 """
4591 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
4592 ""","""
4593 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
4594 PyObject *result;
4595 result = PyObject_GetAttr(dict, name);
4596 if (!result)
4597 PyErr_SetObject(PyExc_NameError, name);
4598 return result;
4599 }
4600 """]
4602 #------------------------------------------------------------------------------------
4604 import_utility_code = [
4605 """
4606 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
4607 ""","""
4608 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
4609 PyObject *__import__ = 0;
4610 PyObject *empty_list = 0;
4611 PyObject *module = 0;
4612 PyObject *global_dict = 0;
4613 PyObject *empty_dict = 0;
4614 PyObject *list;
4615 __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__");
4616 if (!__import__)
4617 goto bad;
4618 if (from_list)
4619 list = from_list;
4620 else {
4621 empty_list = PyList_New(0);
4622 if (!empty_list)
4623 goto bad;
4624 list = empty_list;
4625 }
4626 global_dict = PyModule_GetDict(%(GLOBALS)s);
4627 if (!global_dict)
4628 goto bad;
4629 empty_dict = PyDict_New();
4630 if (!empty_dict)
4631 goto bad;
4632 module = PyObject_CallFunction(__import__, "OOOO",
4633 name, global_dict, empty_dict, list);
4634 bad:
4635 Py_XDECREF(empty_list);
4636 Py_XDECREF(__import__);
4637 Py_XDECREF(empty_dict);
4638 return module;
4639 }
4640 """ % {
4641 "BUILTINS": Naming.builtins_cname,
4642 "GLOBALS": Naming.module_cname,
4643 }]
4645 #------------------------------------------------------------------------------------
4647 get_exception_utility_code = [
4648 """
4649 static PyObject *__Pyx_GetExcValue(void); /*proto*/
4650 ""","""
4651 static PyObject *__Pyx_GetExcValue(void) {
4652 PyObject *type = 0, *value = 0, *tb = 0;
4653 PyObject *tmp_type, *tmp_value, *tmp_tb;
4654 PyObject *result = 0;
4655 PyThreadState *tstate = PyThreadState_Get();
4656 PyErr_Fetch(&type, &value, &tb);
4657 PyErr_NormalizeException(&type, &value, &tb);
4658 if (PyErr_Occurred())
4659 goto bad;
4660 if (!value) {
4661 value = Py_None;
4662 Py_INCREF(value);
4663 }
4664 tmp_type = tstate->exc_type;
4665 tmp_value = tstate->exc_value;
4666 tmp_tb = tstate->exc_traceback;
4667 tstate->exc_type = type;
4668 tstate->exc_value = value;
4669 tstate->exc_traceback = tb;
4670 /* Make sure tstate is in a consistent state when we XDECREF
4671 these objects (XDECREF may run arbitrary code). */
4672 Py_XDECREF(tmp_type);
4673 Py_XDECREF(tmp_value);
4674 Py_XDECREF(tmp_tb);
4675 result = value;
4676 Py_XINCREF(result);
4677 type = 0;
4678 value = 0;
4679 tb = 0;
4680 bad:
4681 Py_XDECREF(type);
4682 Py_XDECREF(value);
4683 Py_XDECREF(tb);
4684 return result;
4685 }
4686 """]
4688 #------------------------------------------------------------------------------------
4690 unpacking_utility_code = [
4691 """
4692 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
4693 static int __Pyx_EndUnpack(PyObject *); /*proto*/
4694 ""","""
4695 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
4696 PyObject *item;
4697 if (!(item = PyIter_Next(iter))) {
4698 if (!PyErr_Occurred()) {
4699 PyErr_Format(PyExc_ValueError,
4700 #if PY_VERSION_HEX < 0x02050000
4701 "need more than %d values to unpack", (int)index);
4702 #else
4703 "need more than %zd values to unpack", index);
4704 #endif
4705 }
4706 }
4707 return item;
4708 }
4710 static int __Pyx_EndUnpack(PyObject *iter) {
4711 PyObject *item;
4712 if ((item = PyIter_Next(iter))) {
4713 Py_DECREF(item);
4714 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
4715 return -1;
4716 }
4717 else if (!PyErr_Occurred())
4718 return 0;
4719 else
4720 return -1;
4721 }
4722 """]
4724 #------------------------------------------------------------------------------------
4726 type_test_utility_code = [
4727 """
4728 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
4729 ""","""
4730 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
4731 if (!type) {
4732 PyErr_Format(PyExc_SystemError, "Missing type object");
4733 return 0;
4734 }
4735 if (obj == Py_None || PyObject_TypeCheck(obj, type))
4736 return 1;
4737 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
4738 Py_TYPE(obj)->tp_name, type->tp_name);
4739 return 0;
4740 }
4741 """]
4743 #------------------------------------------------------------------------------------
4745 create_class_utility_code = [
4746 """
4747 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
4748 ""","""
4749 static PyObject *__Pyx_CreateClass(
4750 PyObject *bases, PyObject *dict, PyObject *name, char *modname)
4751 {
4752 PyObject *py_modname;
4753 PyObject *result = 0;
4755 #if PY_MAJOR_VERSION < 3
4756 py_modname = PyString_FromString(modname);
4757 #else
4758 py_modname = PyUnicode_FromString(modname);
4759 #endif
4760 if (!py_modname)
4761 goto bad;
4762 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
4763 goto bad;
4764 #if PY_MAJOR_VERSION < 3
4765 result = PyClass_New(bases, dict, name);
4766 #else
4767 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
4768 #endif
4769 bad:
4770 Py_XDECREF(py_modname);
4771 return result;
4772 }
4773 """]
4775 #------------------------------------------------------------------------------------
4777 cpp_exception_utility_code = [
4778 """
4779 #ifndef __Pyx_CppExn2PyErr
4780 static void __Pyx_CppExn2PyErr() {
4781 try {
4782 if (PyErr_Occurred())
4783 ; // let the latest Python exn pass through and ignore the current one
4784 else
4785 throw;
4786 } catch (const std::out_of_range& exn) {
4787 // catch out_of_range explicitly so the proper Python exn may be raised
4788 PyErr_SetString(PyExc_IndexError, exn.what());
4789 } catch (const std::exception& exn) {
4790 PyErr_SetString(PyExc_RuntimeError, exn.what());
4791 }
4792 catch (...)
4793 {
4794 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
4795 }
4796 }
4797 #endif
4798 """,""]
4800 #------------------------------------------------------------------------------------
4802 append_utility_code = [
4803 """
4804 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
4805 if (likely(PyList_CheckExact(L))) {
4806 if (PyList_Append(L, x) < 0) return NULL;
4807 Py_INCREF(Py_None);
4808 return Py_None; // this is just to have an accurate signature
4809 }
4810 else {
4811 return PyObject_CallMethod(L, "append", "(O)", x);
4812 }
4813 }
4814 """,""
4815 ]
4817 #------------------------------------------------------------------------------------
4819 # If the is_unsigned flag is set, we need to do some extra work to make
4820 # sure the index doesn't become negative.
4822 getitem_int_utility_code = [
4823 """
4824 static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
4825 PyObject *r;
4826 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4827 r = PyList_GET_ITEM(o, i);
4828 Py_INCREF(r);
4829 }
4830 else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
4831 r = PyTuple_GET_ITEM(o, i);
4832 Py_INCREF(r);
4833 }
4834 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
4835 r = PySequence_GetItem(o, i);
4836 else {
4837 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
4838 if (!j)
4839 return 0;
4840 r = PyObject_GetItem(o, j);
4841 Py_DECREF(j);
4842 }
4843 return r;
4844 }
4845 """,
4846 """
4847 """]
4849 #------------------------------------------------------------------------------------
4851 setitem_int_utility_code = [
4852 """
4853 static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
4854 int r;
4855 if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
4856 Py_DECREF(PyList_GET_ITEM(o, i));
4857 Py_INCREF(v);
4858 PyList_SET_ITEM(o, i, v);
4859 return 1;
4860 }
4861 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
4862 r = PySequence_SetItem(o, i, v);
4863 else {
4864 PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
4865 if (!j)
4866 return -1;
4867 r = PyObject_SetItem(o, j, v);
4868 Py_DECREF(j);
4869 }
4870 return r;
4871 }
4872 """,
4873 """
4874 """]
4875 #------------------------------------------------------------------------------------
4877 raise_noneattr_error_utility_code = [
4878 """
4879 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname);
4880 """, """
4881 static INLINE void __Pyx_RaiseNoneAttributeError(char* attrname) {
4882 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
4883 }
4884 """]
4886 raise_noneindex_error_utility_code = [
4887 """
4888 static INLINE void __Pyx_RaiseNoneIndexingError();
4889 """, """
4890 static INLINE void __Pyx_RaiseNoneIndexingError() {
4891 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
4892 }
4893 """]
