Cython has moved to github.
cython-devel
view Cython/Compiler/ExprNodes.py @ 2469:268bd35aa827
Remove TempNode from OverrideCheckNode (fixes #411)
| author | Dag Sverre Seljebotn <dagss@student.matnat.uio.no> |
|---|---|
| date | Thu Oct 15 12:54:48 2009 +0200 (2 years ago) |
| parents | 8e09c5390d64 |
| children | 73d36c74e74c |
line source
1 #
2 # Pyrex - Parse tree nodes for expressions
3 #
5 import operator
7 from Errors import error, warning, warn_once, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Code import UtilityCode
10 import StringEncoding
11 import Naming
12 import Nodes
13 from Nodes import Node
14 import PyrexTypes
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type, bytes_type, type_type
17 import Builtin
18 import Symtab
19 import Options
20 from Annotate import AnnotationItem
22 from Cython.Debugging import print_call_chain
23 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
24 debug_coercion
26 try:
27 set
28 except NameError:
29 from sets import Set as set
31 class NotConstant(object): pass # just for the name
32 not_a_constant = NotConstant()
33 constant_value_not_set = object()
35 # error messages when coercing from key[0] to key[1]
36 find_coercion_error = {
37 # string related errors
38 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
39 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
40 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects do not support coercion to C types.",
41 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
42 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
43 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
44 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
45 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types.",
46 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
47 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
48 }.get
51 class ExprNode(Node):
52 # subexprs [string] Class var holding names of subexpr node attrs
53 # type PyrexType Type of the result
54 # result_code string Code fragment
55 # result_ctype string C type of result_code if different from type
56 # is_temp boolean Result is in a temporary variable
57 # is_sequence_constructor
58 # boolean Is a list or tuple constructor expression
59 # is_starred boolean Is a starred expression (e.g. '*a')
60 # saved_subexpr_nodes
61 # [ExprNode or [ExprNode or None] or None]
62 # Cached result of subexpr_nodes()
64 result_ctype = None
65 type = None
66 temp_code = None
67 old_temp = None # error checker for multiple frees etc.
69 # The Analyse Expressions phase for expressions is split
70 # into two sub-phases:
71 #
72 # Analyse Types
73 # Determines the result type of the expression based
74 # on the types of its sub-expressions, and inserts
75 # coercion nodes into the expression tree where needed.
76 # Marks nodes which will need to have temporary variables
77 # allocated.
78 #
79 # Allocate Temps
80 # Allocates temporary variables where needed, and fills
81 # in the result_code field of each node.
82 #
83 # ExprNode provides some convenience routines which
84 # perform both of the above phases. These should only
85 # be called from statement nodes, and only when no
86 # coercion nodes need to be added around the expression
87 # being analysed. In that case, the above two phases
88 # should be invoked separately.
89 #
90 # Framework code in ExprNode provides much of the common
91 # processing for the various phases. It makes use of the
92 # 'subexprs' class attribute of ExprNodes, which should
93 # contain a list of the names of attributes which can
94 # hold sub-nodes or sequences of sub-nodes.
95 #
96 # The framework makes use of a number of abstract methods.
97 # Their responsibilities are as follows.
98 #
99 # Declaration Analysis phase
100 #
101 # analyse_target_declaration
102 # Called during the Analyse Declarations phase to analyse
103 # the LHS of an assignment or argument of a del statement.
104 # Nodes which cannot be the LHS of an assignment need not
105 # implement it.
106 #
107 # Expression Analysis phase
108 #
109 # analyse_types
110 # - Call analyse_types on all sub-expressions.
111 # - Check operand types, and wrap coercion nodes around
112 # sub-expressions where needed.
113 # - Set the type of this node.
114 # - If a temporary variable will be required for the
115 # result, set the is_temp flag of this node.
116 #
117 # analyse_target_types
118 # Called during the Analyse Types phase to analyse
119 # the LHS of an assignment or argument of a del
120 # statement. Similar responsibilities to analyse_types.
121 #
122 # target_code
123 # Called by the default implementation of allocate_target_temps.
124 # Should return a C lvalue for assigning to the node. The default
125 # implementation calls calculate_result_code.
126 #
127 # check_const
128 # - Check that this node and its subnodes form a
129 # legal constant expression. If so, do nothing,
130 # otherwise call not_const.
131 #
132 # The default implementation of check_const
133 # assumes that the expression is not constant.
134 #
135 # check_const_addr
136 # - Same as check_const, except check that the
137 # expression is a C lvalue whose address is
138 # constant. Otherwise, call addr_not_const.
139 #
140 # The default implementation of calc_const_addr
141 # assumes that the expression is not a constant
142 # lvalue.
143 #
144 # Code Generation phase
145 #
146 # generate_evaluation_code
147 # - Call generate_evaluation_code for sub-expressions.
148 # - Perform the functions of generate_result_code
149 # (see below).
150 # - If result is temporary, call generate_disposal_code
151 # on all sub-expressions.
152 #
153 # A default implementation of generate_evaluation_code
154 # is provided which uses the following abstract methods:
155 #
156 # generate_result_code
157 # - Generate any C statements necessary to calculate
158 # the result of this node from the results of its
159 # sub-expressions.
160 #
161 # calculate_result_code
162 # - Should return a C code fragment evaluating to the
163 # result. This is only called when the result is not
164 # a temporary.
165 #
166 # generate_assignment_code
167 # Called on the LHS of an assignment.
168 # - Call generate_evaluation_code for sub-expressions.
169 # - Generate code to perform the assignment.
170 # - If the assignment absorbed a reference, call
171 # generate_post_assignment_code on the RHS,
172 # otherwise call generate_disposal_code on it.
173 #
174 # generate_deletion_code
175 # Called on an argument of a del statement.
176 # - Call generate_evaluation_code for sub-expressions.
177 # - Generate code to perform the deletion.
178 # - Call generate_disposal_code on all sub-expressions.
179 #
180 #
182 is_sequence_constructor = 0
183 is_attribute = 0
185 saved_subexpr_nodes = None
186 is_temp = 0
187 is_target = 0
188 is_starred = 0
190 constant_result = constant_value_not_set
192 try:
193 _get_child_attrs = operator.attrgetter('subexprs')
194 except AttributeError:
195 # Python 2.3
196 def _get_child_attrs(self):
197 return self.subexprs
198 child_attrs = property(fget=_get_child_attrs)
200 def not_implemented(self, method_name):
201 print_call_chain(method_name, "not implemented") ###
202 raise InternalError(
203 "%s.%s not implemented" %
204 (self.__class__.__name__, method_name))
206 def is_lvalue(self):
207 return 0
209 def is_ephemeral(self):
210 # An ephemeral node is one whose result is in
211 # a Python temporary and we suspect there are no
212 # other references to it. Certain operations are
213 # disallowed on such values, since they are
214 # likely to result in a dangling pointer.
215 return self.type.is_pyobject and self.is_temp
217 def subexpr_nodes(self):
218 # Extract a list of subexpression nodes based
219 # on the contents of the subexprs class attribute.
220 nodes = []
221 for name in self.subexprs:
222 item = getattr(self, name)
223 if item is not None:
224 if type(item) is list:
225 nodes.extend(item)
226 else:
227 nodes.append(item)
228 return nodes
230 def result(self):
231 if self.is_temp:
232 return self.temp_code
233 else:
234 return self.calculate_result_code()
236 def result_as(self, type = None):
237 # Return the result code cast to the specified C type.
238 return typecast(type, self.ctype(), self.result())
240 def py_result(self):
241 # Return the result code cast to PyObject *.
242 return self.result_as(py_object_type)
244 def ctype(self):
245 # Return the native C type of the result (i.e. the
246 # C type of the result_code expression).
247 return self.result_ctype or self.type
249 def get_constant_c_result_code(self):
250 # Return the constant value of this node as a result code
251 # string, or None if the node is not constant. This method
252 # can be called when the constant result code is required
253 # before the code generation phase.
254 #
255 # The return value is a string that can represent a simple C
256 # value, a constant C name or a constant C expression. If the
257 # node type depends on Python code, this must return None.
258 return None
260 def calculate_constant_result(self):
261 # Calculate the constant compile time result value of this
262 # expression and store it in ``self.constant_result``. Does
263 # nothing by default, thus leaving ``self.constant_result``
264 # unknown. If valid, the result can be an arbitrary Python
265 # value.
266 #
267 # This must only be called when it is assured that all
268 # sub-expressions have a valid constant_result value. The
269 # ConstantFolding transform will do this.
270 pass
272 def compile_time_value(self, denv):
273 # Return value of compile-time expression, or report error.
274 error(self.pos, "Invalid compile-time expression")
276 def compile_time_value_error(self, e):
277 error(self.pos, "Error in compile-time expression: %s: %s" % (
278 e.__class__.__name__, e))
280 # ------------- Declaration Analysis ----------------
282 def analyse_target_declaration(self, env):
283 error(self.pos, "Cannot assign to or delete this")
285 # ------------- Expression Analysis ----------------
287 def analyse_const_expression(self, env):
288 # Called during the analyse_declarations phase of a
289 # constant expression. Analyses the expression's type,
290 # checks whether it is a legal const expression,
291 # and determines its value.
292 self.analyse_types(env)
293 self.check_const()
295 def analyse_expressions(self, env):
296 # Convenience routine performing both the Type
297 # Analysis and Temp Allocation phases for a whole
298 # expression.
299 self.analyse_types(env)
301 def analyse_target_expression(self, env, rhs):
302 # Convenience routine performing both the Type
303 # Analysis and Temp Allocation phases for the LHS of
304 # an assignment.
305 self.analyse_target_types(env)
307 def analyse_boolean_expression(self, env):
308 # Analyse expression and coerce to a boolean.
309 self.analyse_types(env)
310 bool = self.coerce_to_boolean(env)
311 return bool
313 def analyse_temp_boolean_expression(self, env):
314 # Analyse boolean expression and coerce result into
315 # a temporary. This is used when a branch is to be
316 # performed on the result and we won't have an
317 # opportunity to ensure disposal code is executed
318 # afterwards. By forcing the result into a temporary,
319 # we ensure that all disposal has been done by the
320 # time we get the result.
321 self.analyse_types(env)
322 bool = self.coerce_to_boolean(env)
323 temp_bool = bool.coerce_to_temp(env)
324 return temp_bool
326 # --------------- Type Inference -----------------
328 def type_dependencies(self, env):
329 # Returns the list of entries whose types must be determined
330 # before the type of self can be infered.
331 if hasattr(self, 'type') and self.type is not None:
332 return ()
333 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
335 def infer_type(self, env):
336 # Attempt to deduce the type of self.
337 # Differs from analyse_types as it avoids unnecessary
338 # analysis of subexpressions, but can assume everything
339 # in self.type_dependencies() has been resolved.
340 if hasattr(self, 'type') and self.type is not None:
341 return self.type
342 elif hasattr(self, 'entry') and self.entry is not None:
343 return self.entry.type
344 else:
345 self.not_implemented("infer_type")
347 # --------------- Type Analysis ------------------
349 def analyse_as_module(self, env):
350 # If this node can be interpreted as a reference to a
351 # cimported module, return its scope, else None.
352 return None
354 def analyse_as_type(self, env):
355 # If this node can be interpreted as a reference to a
356 # type, return that type, else None.
357 return None
359 def analyse_as_extension_type(self, env):
360 # If this node can be interpreted as a reference to an
361 # extension type, return its type, else None.
362 return None
364 def analyse_types(self, env):
365 self.not_implemented("analyse_types")
367 def analyse_target_types(self, env):
368 self.analyse_types(env)
370 def nogil_check(self, env):
371 # By default, any expression based on Python objects is
372 # prevented in nogil environments. Subtypes must override
373 # this if they can work without the GIL.
374 if self.type.is_pyobject:
375 self.gil_error()
377 def gil_assignment_check(self, env):
378 if env.nogil and self.type.is_pyobject:
379 error(self.pos, "Assignment of Python object not allowed without gil")
381 def check_const(self):
382 self.not_const()
384 def not_const(self):
385 error(self.pos, "Not allowed in a constant expression")
387 def check_const_addr(self):
388 self.addr_not_const()
390 def addr_not_const(self):
391 error(self.pos, "Address is not constant")
393 # ----------------- Result Allocation -----------------
395 def result_in_temp(self):
396 # Return true if result is in a temporary owned by
397 # this node or one of its subexpressions. Overridden
398 # by certain nodes which can share the result of
399 # a subnode.
400 return self.is_temp
402 def target_code(self):
403 # Return code fragment for use as LHS of a C assignment.
404 return self.calculate_result_code()
406 def calculate_result_code(self):
407 self.not_implemented("calculate_result_code")
409 # def release_target_temp(self, env):
410 # # Release temporaries used by LHS of an assignment.
411 # self.release_subexpr_temps(env)
413 def allocate_temp_result(self, code):
414 if self.temp_code:
415 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos))
416 type = self.type
417 if not type.is_void:
418 if type.is_pyobject:
419 type = PyrexTypes.py_object_type
420 self.temp_code = code.funcstate.allocate_temp(
421 type, manage_ref=True)
422 else:
423 self.temp_code = None
425 def release_temp_result(self, code):
426 if not self.temp_code:
427 if self.old_temp:
428 raise RuntimeError("temp %s released multiple times in %s" % (
429 self.old_temp, self.__class__.__name__))
430 else:
431 raise RuntimeError("no temp, but release requested in %s" % (
432 self.__class__.__name__))
433 code.funcstate.release_temp(self.temp_code)
434 self.old_temp = self.temp_code
435 self.temp_code = None
437 # ---------------- Code Generation -----------------
439 def make_owned_reference(self, code):
440 # If result is a pyobject, make sure we own
441 # a reference to it.
442 if self.type.is_pyobject and not self.result_in_temp():
443 code.put_incref(self.result(), self.ctype())
445 def generate_evaluation_code(self, code):
446 code.mark_pos(self.pos)
448 # Generate code to evaluate this node and
449 # its sub-expressions, and dispose of any
450 # temporary results of its sub-expressions.
451 self.generate_subexpr_evaluation_code(code)
453 if self.is_temp:
454 self.allocate_temp_result(code)
456 self.generate_result_code(code)
457 if self.is_temp:
458 # If we are temp we do not need to wait until this node is disposed
459 # before disposing children.
460 self.generate_subexpr_disposal_code(code)
461 self.free_subexpr_temps(code)
463 def generate_subexpr_evaluation_code(self, code):
464 for node in self.subexpr_nodes():
465 node.generate_evaluation_code(code)
467 def generate_result_code(self, code):
468 self.not_implemented("generate_result_code")
470 def generate_disposal_code(self, code):
471 if self.is_temp:
472 if self.type.is_pyobject:
473 code.put_decref_clear(self.result(), self.ctype())
474 else:
475 # Already done if self.is_temp
476 self.generate_subexpr_disposal_code(code)
478 def generate_subexpr_disposal_code(self, code):
479 # Generate code to dispose of temporary results
480 # of all sub-expressions.
481 for node in self.subexpr_nodes():
482 node.generate_disposal_code(code)
484 def generate_post_assignment_code(self, code):
485 if self.is_temp:
486 if self.type.is_pyobject:
487 code.putln("%s = 0;" % self.result())
488 else:
489 self.generate_subexpr_disposal_code(code)
491 def generate_assignment_code(self, rhs, code):
492 # Stub method for nodes which are not legal as
493 # the LHS of an assignment. An error will have
494 # been reported earlier.
495 pass
497 def generate_deletion_code(self, code):
498 # Stub method for nodes that are not legal as
499 # the argument of a del statement. An error
500 # will have been reported earlier.
501 pass
503 def free_temps(self, code):
504 if self.is_temp:
505 if not self.type.is_void:
506 self.release_temp_result(code)
507 else:
508 self.free_subexpr_temps(code)
510 def free_subexpr_temps(self, code):
511 for sub in self.subexpr_nodes():
512 sub.free_temps(code)
514 # ---------------- Annotation ---------------------
516 def annotate(self, code):
517 for node in self.subexpr_nodes():
518 node.annotate(code)
520 # ----------------- Coercion ----------------------
522 def coerce_to(self, dst_type, env):
523 # Coerce the result so that it can be assigned to
524 # something of type dst_type. If processing is necessary,
525 # wraps this node in a coercion node and returns that.
526 # Otherwise, returns this node unchanged.
527 #
528 # This method is called during the analyse_expressions
529 # phase of the src_node's processing.
530 src = self
531 src_type = self.type
532 src_is_py_type = src_type.is_pyobject
533 dst_is_py_type = dst_type.is_pyobject
535 if self.check_for_coercion_error(dst_type):
536 return self
538 if dst_type.is_pyobject:
539 if not src.type.is_pyobject:
540 src = CoerceToPyTypeNode(src, env)
541 if not src.type.subtype_of(dst_type):
542 if not isinstance(src, NoneNode):
543 src = PyTypeTestNode(src, dst_type, env)
544 elif src.type.is_pyobject:
545 src = CoerceFromPyTypeNode(dst_type, src, env)
546 elif (dst_type.is_complex
547 and src_type != dst_type
548 and dst_type.assignable_from(src_type)):
549 src = CoerceToComplexNode(src, dst_type, env)
550 else: # neither src nor dst are py types
551 # Added the string comparison, since for c types that
552 # is enough, but Cython gets confused when the types are
553 # in different pxi files.
554 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
555 self.fail_assignment(dst_type)
556 return src
558 def fail_assignment(self, dst_type):
559 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type))
561 def check_for_coercion_error(self, dst_type, fail=False, default=None):
562 if fail and not default:
563 default = "Cannot assign type '%(FROM)s' to '%(TO)s'"
564 message = find_coercion_error((self.type, dst_type), default)
565 if message is not None:
566 error(self.pos, message % {'FROM': self.type, 'TO': dst_type})
567 return True
568 if fail:
569 self.fail_assignment(dst_type)
570 return True
571 return False
573 def coerce_to_pyobject(self, env):
574 return self.coerce_to(PyrexTypes.py_object_type, env)
576 def coerce_to_boolean(self, env):
577 # Coerce result to something acceptable as
578 # a boolean value.
579 type = self.type
580 if type.is_pyobject or type.is_ptr or type.is_float:
581 return CoerceToBooleanNode(self, env)
582 else:
583 if not type.is_int and not type.is_error:
584 error(self.pos,
585 "Type '%s' not acceptable as a boolean" % type)
586 return self
588 def coerce_to_integer(self, env):
589 # If not already some C integer type, coerce to longint.
590 if self.type.is_int:
591 return self
592 else:
593 return self.coerce_to(PyrexTypes.c_long_type, env)
595 def coerce_to_temp(self, env):
596 # Ensure that the result is in a temporary.
597 if self.result_in_temp():
598 return self
599 else:
600 return CoerceToTempNode(self, env)
602 def coerce_to_simple(self, env):
603 # Ensure that the result is simple (see is_simple).
604 if self.is_simple():
605 return self
606 else:
607 return self.coerce_to_temp(env)
609 def is_simple(self):
610 # A node is simple if its result is something that can
611 # be referred to without performing any operations, e.g.
612 # a constant, local var, C global var, struct member
613 # reference, or temporary.
614 return self.result_in_temp()
616 def as_cython_attribute(self):
617 return None
619 class AtomicExprNode(ExprNode):
620 # Abstract base class for expression nodes which have
621 # no sub-expressions.
623 subexprs = []
625 # Override to optimize -- we know we have no children
626 def generate_subexpr_evaluation_code(self, code):
627 pass
628 def generate_subexpr_disposal_code(self, code):
629 pass
631 class PyConstNode(AtomicExprNode):
632 # Abstract base class for constant Python values.
634 is_literal = 1
635 type = py_object_type
637 def is_simple(self):
638 return 1
640 def analyse_types(self, env):
641 pass
643 def calculate_result_code(self):
644 return self.value
646 def generate_result_code(self, code):
647 pass
650 class NoneNode(PyConstNode):
651 # The constant value None
653 value = "Py_None"
655 constant_result = None
657 nogil_check = None
659 def compile_time_value(self, denv):
660 return None
662 class EllipsisNode(PyConstNode):
663 # '...' in a subscript list.
665 value = "Py_Ellipsis"
667 constant_result = Ellipsis
669 def compile_time_value(self, denv):
670 return Ellipsis
673 class ConstNode(AtomicExprNode):
674 # Abstract base type for literal constant nodes.
675 #
676 # value string C code fragment
678 is_literal = 1
679 nogil_check = None
681 def is_simple(self):
682 return 1
684 def analyse_types(self, env):
685 pass # Types are held in class variables
687 def check_const(self):
688 pass
690 def get_constant_c_result_code(self):
691 return self.calculate_result_code()
693 def calculate_result_code(self):
694 return str(self.value)
696 def generate_result_code(self, code):
697 pass
700 class BoolNode(ConstNode):
701 type = PyrexTypes.c_bint_type
702 # The constant value True or False
704 def calculate_constant_result(self):
705 self.constant_result = self.value
707 def compile_time_value(self, denv):
708 return self.value
710 def calculate_result_code(self):
711 return str(int(self.value))
714 class NullNode(ConstNode):
715 type = PyrexTypes.c_null_ptr_type
716 value = "NULL"
717 constant_result = 0
719 def get_constant_c_result_code(self):
720 return self.value
723 class CharNode(ConstNode):
724 type = PyrexTypes.c_char_type
726 def calculate_constant_result(self):
727 self.constant_result = ord(self.value)
729 def compile_time_value(self, denv):
730 return ord(self.value)
732 def calculate_result_code(self):
733 return "'%s'" % StringEncoding.escape_char(self.value)
736 class IntNode(ConstNode):
738 # unsigned "" or "U"
739 # longness "" or "L" or "LL"
741 unsigned = ""
742 longness = ""
743 type = PyrexTypes.c_long_type
745 def coerce_to(self, dst_type, env):
746 if dst_type.is_numeric and not dst_type.is_complex:
747 self.type = PyrexTypes.c_long_type
748 return self
749 # Arrange for a Python version of the number to be pre-allocated
750 # when coercing to a Python type.
751 if dst_type.is_pyobject:
752 self.type = PyrexTypes.py_object_type
753 # We still need to perform normal coerce_to processing on the
754 # result, because we might be coercing to an extension type,
755 # in which case a type test node will be needed.
756 return ConstNode.coerce_to(self, dst_type, env)
758 def coerce_to_boolean(self, env):
759 self.type = PyrexTypes.c_bint_type
760 return self
762 def generate_evaluation_code(self, code):
763 if self.type.is_pyobject:
764 self.result_code = code.get_py_num(self.value, self.longness)
765 else:
766 self.result_code = self.get_constant_c_result_code()
768 def get_constant_c_result_code(self):
769 return str(self.value) + self.unsigned + self.longness
771 def calculate_result_code(self):
772 return self.result_code
774 def calculate_constant_result(self):
775 self.constant_result = int(self.value, 0)
777 def compile_time_value(self, denv):
778 return int(self.value, 0)
781 class FloatNode(ConstNode):
782 type = PyrexTypes.c_double_type
784 def calculate_constant_result(self):
785 self.constant_result = float(self.value)
787 def compile_time_value(self, denv):
788 return float(self.value)
790 def calculate_result_code(self):
791 strval = repr(float(self.value))
792 if strval == 'nan':
793 return "(Py_HUGE_VAL * 0)"
794 elif strval == 'inf':
795 return "Py_HUGE_VAL"
796 elif strval == '-inf':
797 return "(-Py_HUGE_VAL)"
798 else:
799 return strval
802 class BytesNode(ConstNode):
803 # A char* or bytes literal
804 #
805 # value BytesLiteral
807 type = PyrexTypes.c_char_ptr_type
809 def compile_time_value(self, denv):
810 return self.value
812 def analyse_as_type(self, env):
813 type = PyrexTypes.parse_basic_type(self.value)
814 if type is not None:
815 return type
816 from TreeFragment import TreeFragment
817 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
818 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
819 sizeof_node = declaration.root.stats[0].expr
820 sizeof_node.analyse_types(env)
821 if isinstance(sizeof_node, SizeofTypeNode):
822 return sizeof_node.arg_type
824 def coerce_to(self, dst_type, env):
825 if dst_type == PyrexTypes.c_char_ptr_type:
826 self.type = PyrexTypes.c_char_ptr_type
827 return self
828 elif dst_type == PyrexTypes.c_uchar_ptr_type:
829 self.type = PyrexTypes.c_char_ptr_type
830 return CastNode(self, PyrexTypes.c_uchar_ptr_type)
832 if dst_type.is_int:
833 if len(self.value) > 1:
834 error(self.pos, "Only single-character strings can be coerced into ints.")
835 return self
836 return CharNode(self.pos, value=self.value)
838 node = self
839 if not self.type.is_pyobject:
840 if dst_type in (py_object_type, Builtin.bytes_type):
841 node = self.as_py_string_node(env)
842 elif dst_type.is_pyobject:
843 self.fail_assignment(dst_type)
844 return self
845 else:
846 node = self
847 elif dst_type.is_pyobject and dst_type is not py_object_type:
848 self.check_for_coercion_error(dst_type, fail=True)
849 return self
851 # We still need to perform normal coerce_to processing on the
852 # result, because we might be coercing to an extension type,
853 # in which case a type test node will be needed.
854 return ConstNode.coerce_to(node, dst_type, env)
856 def as_py_string_node(self, env):
857 # Return a new BytesNode with the same value as this node
858 # but whose type is a Python type instead of a C type.
859 return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
861 def generate_evaluation_code(self, code):
862 if self.type.is_pyobject:
863 self.result_code = code.get_py_string_const(self.value)
864 else:
865 self.result_code = code.get_string_const(self.value)
867 def get_constant_c_result_code(self):
868 return None # FIXME
870 def calculate_result_code(self):
871 return self.result_code
874 class UnicodeNode(PyConstNode):
875 # A Python unicode object
876 #
877 # value EncodedString
879 type = unicode_type
881 def coerce_to(self, dst_type, env):
882 if dst_type is self.type:
883 pass
884 elif not dst_type.is_pyobject:
885 error(self.pos, "Unicode objects do not support coercion to C types.")
886 elif dst_type is not py_object_type:
887 if not self.check_for_coercion_error(dst_type):
888 self.fail_assignment(dst_type)
889 return self
891 def generate_evaluation_code(self, code):
892 self.result_code = code.get_py_string_const(self.value)
894 def calculate_result_code(self):
895 return self.result_code
897 def compile_time_value(self, env):
898 return self.value
901 class StringNode(PyConstNode):
902 # A Python str object, i.e. a byte string in Python 2.x and a
903 # unicode string in Python 3.x
904 #
905 # value BytesLiteral or EncodedString
906 # is_identifier boolean
908 type = Builtin.str_type
909 is_identifier = False
911 def coerce_to(self, dst_type, env):
912 if dst_type is not py_object_type and dst_type is not Builtin.str_type:
913 # if dst_type is Builtin.bytes_type:
914 # # special case: bytes = 'str literal'
915 # return BytesNode(self.pos, value=self.value)
916 if not dst_type.is_pyobject:
917 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env)
918 self.check_for_coercion_error(dst_type, fail=True)
920 # this will be a unicode string in Py3, so make sure we can decode it
921 if not self.is_identifier:
922 encoding = self.value.encoding or 'UTF-8'
923 try:
924 self.value.decode(encoding)
925 except UnicodeDecodeError:
926 error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
928 return self
930 def generate_evaluation_code(self, code):
931 self.result_code = code.get_py_string_const(
932 self.value, identifier=self.is_identifier, is_str=True)
934 def get_constant_c_result_code(self):
935 return None
937 def calculate_result_code(self):
938 return self.result_code
940 def compile_time_value(self, env):
941 return self.value
944 class IdentifierStringNode(StringNode):
945 # A special str value that represents an identifier (bytes in Py2,
946 # unicode in Py3).
947 is_identifier = True
950 class LongNode(AtomicExprNode):
951 # Python long integer literal
952 #
953 # value string
955 type = py_object_type
957 def calculate_constant_result(self):
958 self.constant_result = long(self.value)
960 def compile_time_value(self, denv):
961 return long(self.value)
963 def analyse_types(self, env):
964 self.is_temp = 1
966 gil_message = "Constructing Python long int"
968 def generate_result_code(self, code):
969 code.putln(
970 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
971 self.result(),
972 self.value,
973 code.error_goto_if_null(self.result(), self.pos)))
974 code.put_gotref(self.py_result())
977 class ImagNode(AtomicExprNode):
978 # Imaginary number literal
979 #
980 # value float imaginary part
982 type = PyrexTypes.c_double_complex_type
984 def calculate_constant_result(self):
985 self.constant_result = complex(0.0, self.value)
987 def compile_time_value(self, denv):
988 return complex(0.0, self.value)
990 def analyse_types(self, env):
991 self.type.create_declaration_utility_code(env)
993 def coerce_to(self, dst_type, env):
994 # Arrange for a Python version of the number to be pre-allocated
995 # when coercing to a Python type.
996 if dst_type.is_pyobject:
997 self.is_temp = 1
998 self.type = PyrexTypes.py_object_type
999 # We still need to perform normal coerce_to processing on the
1000 # result, because we might be coercing to an extension type,
1001 # in which case a type test node will be needed.
1002 return AtomicExprNode.coerce_to(self, dst_type, env)
1004 gil_message = "Constructing complex number"
1006 def calculate_result_code(self):
1007 if self.type.is_pyobject:
1008 return self.result()
1009 else:
1010 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1012 def generate_result_code(self, code):
1013 if self.type.is_pyobject:
1014 code.putln(
1015 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1016 self.result(),
1017 float(self.value),
1018 code.error_goto_if_null(self.result(), self.pos)))
1019 code.put_gotref(self.py_result())
1023 class NameNode(AtomicExprNode):
1024 # Reference to a local or global variable name.
1025 #
1026 # name string Python name of the variable
1027 # entry Entry Symbol table entry
1028 # type_entry Entry For extension type names, the original type entry
1030 is_name = True
1031 is_cython_module = False
1032 cython_attribute = None
1033 lhs_of_first_assignment = False
1034 is_used_as_rvalue = 0
1035 entry = None
1036 type_entry = None
1038 def create_analysed_rvalue(pos, env, entry):
1039 node = NameNode(pos)
1040 node.analyse_types(env, entry=entry)
1041 return node
1043 def as_cython_attribute(self):
1044 return self.cython_attribute
1046 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1048 def type_dependencies(self, env):
1049 if self.entry is None:
1050 self.entry = env.lookup(self.name)
1051 if self.entry is not None and self.entry.type.is_unspecified:
1052 return (self.entry,)
1053 else:
1054 return ()
1056 def infer_type(self, env):
1057 if self.entry is None:
1058 self.entry = env.lookup(self.name)
1059 if self.entry is None:
1060 return py_object_type
1061 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
1062 self.name == self.entry.type.name:
1063 # Unfortunately the type attribute of type objects
1064 # is used for the pointer to the type the represent.
1065 return type_type
1066 else:
1067 return self.entry.type
1069 def compile_time_value(self, denv):
1070 try:
1071 return denv.lookup(self.name)
1072 except KeyError:
1073 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1075 def get_constant_c_result_code(self):
1076 if not self.entry or self.entry.type.is_pyobject:
1077 return None
1078 return self.entry.cname
1080 def coerce_to(self, dst_type, env):
1081 # If coercing to a generic pyobject and this is a builtin
1082 # C function with a Python equivalent, manufacture a NameNode
1083 # referring to the Python builtin.
1084 #print "NameNode.coerce_to:", self.name, dst_type ###
1085 if dst_type is py_object_type:
1086 entry = self.entry
1087 if entry and entry.is_cfunction:
1088 var_entry = entry.as_variable
1089 if var_entry:
1090 if var_entry.is_builtin and Options.cache_builtins:
1091 var_entry = env.declare_builtin(var_entry.name, self.pos)
1092 node = NameNode(self.pos, name = self.name)
1093 node.entry = var_entry
1094 node.analyse_rvalue_entry(env)
1095 return node
1096 return super(NameNode, self).coerce_to(dst_type, env)
1098 def analyse_as_module(self, env):
1099 # Try to interpret this as a reference to a cimported module.
1100 # Returns the module scope, or None.
1101 entry = self.entry
1102 if not entry:
1103 entry = env.lookup(self.name)
1104 if entry and entry.as_module:
1105 return entry.as_module
1106 return None
1108 def analyse_as_type(self, env):
1109 if self.cython_attribute:
1110 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1111 else:
1112 type = PyrexTypes.parse_basic_type(self.name)
1113 if type:
1114 return type
1115 entry = self.entry
1116 if not entry:
1117 entry = env.lookup(self.name)
1118 if entry and entry.is_type:
1119 return entry.type
1120 else:
1121 return None
1123 def analyse_as_extension_type(self, env):
1124 # Try to interpret this as a reference to an extension type.
1125 # Returns the extension type, or None.
1126 entry = self.entry
1127 if not entry:
1128 entry = env.lookup(self.name)
1129 if entry and entry.is_type and entry.type.is_extension_type:
1130 return entry.type
1131 else:
1132 return None
1134 def analyse_target_declaration(self, env):
1135 if not self.entry:
1136 self.entry = env.lookup_here(self.name)
1137 if not self.entry:
1138 if env.directives['infer_types']:
1139 type = unspecified_type
1140 else:
1141 type = py_object_type
1142 self.entry = env.declare_var(self.name, type, self.pos)
1143 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1144 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1145 if self.entry.is_declared_generic:
1146 self.result_ctype = py_object_type
1148 def analyse_types(self, env):
1149 if self.entry is None:
1150 self.entry = env.lookup(self.name)
1151 if not self.entry:
1152 self.entry = env.declare_builtin(self.name, self.pos)
1153 if not self.entry:
1154 self.type = PyrexTypes.error_type
1155 return
1156 entry = self.entry
1157 if entry:
1158 entry.used = 1
1159 if entry.type.is_buffer:
1160 import Buffer
1161 Buffer.used_buffer_aux_vars(entry)
1162 if entry.utility_code:
1163 env.use_utility_code(entry.utility_code)
1164 self.analyse_rvalue_entry(env)
1166 def analyse_target_types(self, env):
1167 self.analyse_entry(env)
1168 if not self.is_lvalue():
1169 error(self.pos, "Assignment to non-lvalue '%s'"
1170 % self.name)
1171 self.type = PyrexTypes.error_type
1172 self.entry.used = 1
1173 if self.entry.type.is_buffer:
1174 import Buffer
1175 Buffer.used_buffer_aux_vars(self.entry)
1177 def analyse_rvalue_entry(self, env):
1178 #print "NameNode.analyse_rvalue_entry:", self.name ###
1179 #print "Entry:", self.entry.__dict__ ###
1180 self.analyse_entry(env)
1181 entry = self.entry
1182 if entry.is_declared_generic:
1183 self.result_ctype = py_object_type
1184 if entry.is_pyglobal or entry.is_builtin:
1185 if Options.cache_builtins and entry.is_builtin:
1186 self.is_temp = 0
1187 else:
1188 self.is_temp = 1
1189 self.is_used_as_rvalue = 1
1190 env.use_utility_code(get_name_interned_utility_code)
1192 def nogil_check(self, env):
1193 if self.is_used_as_rvalue:
1194 entry = self.entry
1195 if entry.is_builtin:
1196 # if not Options.cache_builtins: # cached builtins are ok
1197 self.gil_error()
1198 elif entry.is_pyglobal:
1199 self.gil_error()
1201 gil_message = "Accessing Python global or builtin"
1203 def analyse_entry(self, env):
1204 #print "NameNode.analyse_entry:", self.name ###
1205 self.check_identifier_kind()
1206 entry = self.entry
1207 type = entry.type
1208 self.type = type
1210 def check_identifier_kind(self):
1211 # Check that this is an appropriate kind of name for use in an
1212 # expression. Also finds the variable entry associated with
1213 # an extension type.
1214 entry = self.entry
1215 if entry.is_type and entry.type.is_extension_type:
1216 self.type_entry = entry
1217 if not (entry.is_const or entry.is_variable
1218 or entry.is_builtin or entry.is_cfunction):
1219 if self.entry.as_variable:
1220 self.entry = self.entry.as_variable
1221 else:
1222 error(self.pos,
1223 "'%s' is not a constant, variable or function identifier" % self.name)
1225 def is_simple(self):
1226 # If it's not a C variable, it'll be in a temp.
1227 return 1
1229 def calculate_target_results(self, env):
1230 pass
1232 def check_const(self):
1233 entry = self.entry
1234 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1235 self.not_const()
1237 def check_const_addr(self):
1238 entry = self.entry
1239 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1240 self.addr_not_const()
1242 def is_lvalue(self):
1243 return self.entry.is_variable and \
1244 not self.entry.type.is_array and \
1245 not self.entry.is_readonly
1247 def is_ephemeral(self):
1248 # Name nodes are never ephemeral, even if the
1249 # result is in a temporary.
1250 return 0
1252 def calculate_result_code(self):
1253 entry = self.entry
1254 if not entry:
1255 return "<error>" # There was an error earlier
1256 return entry.cname
1258 def generate_result_code(self, code):
1259 assert hasattr(self, 'entry')
1260 entry = self.entry
1261 if entry is None:
1262 return # There was an error earlier
1263 if entry.is_builtin and Options.cache_builtins:
1264 return # Lookup already cached
1265 elif entry.is_pyglobal or entry.is_builtin:
1266 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1267 interned_cname = code.intern_identifier(self.entry.name)
1268 if entry.is_builtin:
1269 namespace = Naming.builtins_cname
1270 else: # entry.is_pyglobal
1271 namespace = entry.scope.namespace_cname
1272 code.putln(
1273 '%s = __Pyx_GetName(%s, %s); %s' % (
1274 self.result(),
1275 namespace,
1276 interned_cname,
1277 code.error_goto_if_null(self.result(), self.pos)))
1278 code.put_gotref(self.py_result())
1280 elif entry.is_local and False:
1281 # control flow not good enough yet
1282 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1283 if assigned is False:
1284 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1285 elif not Options.init_local_none and assigned is None:
1286 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1287 (entry.cname, entry.name, code.error_goto(self.pos)))
1288 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1290 def generate_assignment_code(self, rhs, code):
1291 #print "NameNode.generate_assignment_code:", self.name ###
1292 entry = self.entry
1293 if entry is None:
1294 return # There was an error earlier
1296 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1297 and not self.lhs_of_first_assignment):
1298 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1300 # is_pyglobal seems to be True for module level-globals only.
1301 # We use this to access class->tp_dict if necessary.
1302 if entry.is_pyglobal:
1303 assert entry.type.is_pyobject, "Python global or builtin not a Python object"
1304 interned_cname = code.intern_identifier(self.entry.name)
1305 namespace = self.entry.scope.namespace_cname
1306 if entry.is_member:
1307 # if the entry is a member we have to cheat: SetAttr does not work
1308 # on types, so we create a descriptor which is then added to tp_dict
1309 code.put_error_if_neg(self.pos,
1310 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1311 namespace,
1312 interned_cname,
1313 rhs.py_result()))
1314 rhs.generate_disposal_code(code)
1315 rhs.free_temps(code)
1316 # in Py2.6+, we need to invalidate the method cache
1317 code.putln("PyType_Modified(%s);" %
1318 entry.scope.parent_type.typeptr_cname)
1319 else:
1320 code.put_error_if_neg(self.pos,
1321 'PyObject_SetAttr(%s, %s, %s)' % (
1322 namespace,
1323 interned_cname,
1324 rhs.py_result()))
1325 if debug_disposal_code:
1326 print("NameNode.generate_assignment_code:")
1327 print("...generating disposal code for %s" % rhs)
1328 rhs.generate_disposal_code(code)
1329 rhs.free_temps(code)
1330 else:
1331 if self.type.is_buffer:
1332 # Generate code for doing the buffer release/acquisition.
1333 # This might raise an exception in which case the assignment (done
1334 # below) will not happen.
1335 #
1336 # The reason this is not in a typetest-like node is because the
1337 # variables that the acquired buffer info is stored to is allocated
1338 # per entry and coupled with it.
1339 self.generate_acquire_buffer(rhs, code)
1341 if self.type.is_pyobject:
1342 rhs.make_owned_reference(code)
1343 #print "NameNode.generate_assignment_code: to", self.name ###
1344 #print "...from", rhs ###
1345 #print "...LHS type", self.type, "ctype", self.ctype() ###
1346 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1347 if entry.is_cglobal:
1348 code.put_gotref(self.py_result())
1349 if not self.lhs_of_first_assignment:
1350 if entry.is_local and not Options.init_local_none:
1351 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1352 if initalized is True:
1353 code.put_decref(self.result(), self.ctype())
1354 elif initalized is None:
1355 code.put_xdecref(self.result(), self.ctype())
1356 else:
1357 code.put_decref(self.result(), self.ctype())
1358 if entry.is_cglobal:
1359 code.put_giveref(rhs.py_result())
1360 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1361 if debug_disposal_code:
1362 print("NameNode.generate_assignment_code:")
1363 print("...generating post-assignment code for %s" % rhs)
1364 rhs.generate_post_assignment_code(code)
1365 rhs.free_temps(code)
1367 def generate_acquire_buffer(self, rhs, code):
1368 # rhstmp is only used in case the rhs is a complicated expression leading to
1369 # the object, to avoid repeating the same C expression for every reference
1370 # to the rhs. It does NOT hold a reference.
1371 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1372 if pretty_rhs:
1373 rhstmp = rhs.result_as(self.ctype())
1374 else:
1375 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1376 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1378 buffer_aux = self.entry.buffer_aux
1379 bufstruct = buffer_aux.buffer_info_var.cname
1380 import Buffer
1381 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1382 is_initialized=not self.lhs_of_first_assignment,
1383 pos=self.pos, code=code)
1385 if not pretty_rhs:
1386 code.putln("%s = 0;" % rhstmp)
1387 code.funcstate.release_temp(rhstmp)
1389 def generate_deletion_code(self, code):
1390 if self.entry is None:
1391 return # There was an error earlier
1392 if not self.entry.is_pyglobal:
1393 error(self.pos, "Deletion of local or C global name not supported")
1394 return
1395 code.put_error_if_neg(self.pos,
1396 '__Pyx_DelAttrString(%s, "%s")' % (
1397 Naming.module_cname,
1398 self.entry.name))
1400 def annotate(self, code):
1401 if hasattr(self, 'is_called') and self.is_called:
1402 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1403 if self.type.is_pyobject:
1404 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1405 else:
1406 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1408 class BackquoteNode(ExprNode):
1409 # `expr`
1410 #
1411 # arg ExprNode
1413 type = py_object_type
1415 subexprs = ['arg']
1417 def analyse_types(self, env):
1418 self.arg.analyse_types(env)
1419 self.arg = self.arg.coerce_to_pyobject(env)
1420 self.is_temp = 1
1422 gil_message = "Backquote expression"
1424 def calculate_constant_result(self):
1425 self.constant_result = repr(self.arg.constant_result)
1427 def generate_result_code(self, code):
1428 code.putln(
1429 "%s = PyObject_Repr(%s); %s" % (
1430 self.result(),
1431 self.arg.py_result(),
1432 code.error_goto_if_null(self.result(), self.pos)))
1433 code.put_gotref(self.py_result())
1437 class ImportNode(ExprNode):
1438 # Used as part of import statement implementation.
1439 # Implements result =
1440 # __import__(module_name, globals(), None, name_list)
1441 #
1442 # module_name StringNode dotted name of module
1443 # name_list ListNode or None list of names to be imported
1445 type = py_object_type
1447 subexprs = ['module_name', 'name_list']
1449 def analyse_types(self, env):
1450 self.module_name.analyse_types(env)
1451 self.module_name = self.module_name.coerce_to_pyobject(env)
1452 if self.name_list:
1453 self.name_list.analyse_types(env)
1454 self.name_list.coerce_to_pyobject(env)
1455 self.is_temp = 1
1456 env.use_utility_code(import_utility_code)
1458 gil_message = "Python import"
1460 def generate_result_code(self, code):
1461 if self.name_list:
1462 name_list_code = self.name_list.py_result()
1463 else:
1464 name_list_code = "0"
1465 code.putln(
1466 "%s = __Pyx_Import(%s, %s); %s" % (
1467 self.result(),
1468 self.module_name.py_result(),
1469 name_list_code,
1470 code.error_goto_if_null(self.result(), self.pos)))
1471 code.put_gotref(self.py_result())
1474 class IteratorNode(ExprNode):
1475 # Used as part of for statement implementation.
1476 #
1477 # allocate_counter_temp/release_counter_temp needs to be called
1478 # by parent (ForInStatNode)
1479 #
1480 # Implements result = iter(sequence)
1481 #
1482 # sequence ExprNode
1484 type = py_object_type
1486 subexprs = ['sequence']
1488 def analyse_types(self, env):
1489 self.sequence.analyse_types(env)
1490 self.sequence = self.sequence.coerce_to_pyobject(env)
1491 self.is_temp = 1
1493 gil_message = "Iterating over Python object"
1495 def allocate_counter_temp(self, code):
1496 self.counter_cname = code.funcstate.allocate_temp(
1497 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1499 def release_counter_temp(self, code):
1500 code.funcstate.release_temp(self.counter_cname)
1502 def generate_result_code(self, code):
1503 is_builtin_sequence = self.sequence.type is list_type or \
1504 self.sequence.type is tuple_type
1505 if is_builtin_sequence:
1506 code.putln(
1507 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1508 else:
1509 code.putln(
1510 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1511 self.sequence.py_result(),
1512 self.sequence.py_result()))
1513 code.putln(
1514 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1515 self.counter_cname,
1516 self.result(),
1517 self.sequence.py_result(),
1518 self.result()))
1519 code.putln("} else {")
1520 if is_builtin_sequence:
1521 code.putln(
1522 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1523 code.error_goto(self.pos))
1524 else:
1525 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1526 self.counter_cname,
1527 self.result(),
1528 self.sequence.py_result(),
1529 code.error_goto_if_null(self.result(), self.pos)))
1530 code.put_gotref(self.py_result())
1531 code.putln("}")
1534 class NextNode(AtomicExprNode):
1535 # Used as part of for statement implementation.
1536 # Implements result = iterator.next()
1537 # Created during analyse_types phase.
1538 # The iterator is not owned by this node.
1539 #
1540 # iterator ExprNode
1542 type = py_object_type
1544 def __init__(self, iterator, env):
1545 self.pos = iterator.pos
1546 self.iterator = iterator
1547 self.is_temp = 1
1549 def generate_result_code(self, code):
1550 if self.iterator.sequence.type is list_type:
1551 type_checks = [(list_type, "List")]
1552 elif self.iterator.sequence.type is tuple_type:
1553 type_checks = [(tuple_type, "Tuple")]
1554 else:
1555 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1557 for py_type, prefix in type_checks:
1558 if len(type_checks) > 1:
1559 code.putln(
1560 "if (likely(Py%s_CheckExact(%s))) {" % (
1561 prefix, self.iterator.py_result()))
1562 code.putln(
1563 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1564 self.iterator.counter_cname,
1565 prefix,
1566 self.iterator.py_result()))
1567 code.putln(
1568 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1569 self.result(),
1570 prefix,
1571 self.iterator.py_result(),
1572 self.iterator.counter_cname,
1573 self.result(),
1574 self.iterator.counter_cname))
1575 if len(type_checks) > 1:
1576 code.put("} else ")
1577 if len(type_checks) == 1:
1578 return
1579 code.putln("{")
1580 code.putln(
1581 "%s = PyIter_Next(%s);" % (
1582 self.result(),
1583 self.iterator.py_result()))
1584 code.putln(
1585 "if (!%s) {" %
1586 self.result())
1587 code.putln(code.error_goto_if_PyErr(self.pos))
1588 code.putln("break;")
1589 code.putln("}")
1590 code.put_gotref(self.py_result())
1591 code.putln("}")
1594 class ExcValueNode(AtomicExprNode):
1595 # Node created during analyse_types phase
1596 # of an ExceptClauseNode to fetch the current
1597 # exception value.
1599 type = py_object_type
1601 def __init__(self, pos, env):
1602 ExprNode.__init__(self, pos)
1604 def set_var(self, var):
1605 self.var = var
1607 def calculate_result_code(self):
1608 return self.var
1610 def generate_result_code(self, code):
1611 pass
1613 def analyse_types(self, env):
1614 pass
1617 class TempNode(ExprNode):
1618 # Node created during analyse_types phase
1619 # of some nodes to hold a temporary value.
1620 #
1621 # Note: One must call "allocate" and "release" on
1622 # the node during code generation to get/release the temp.
1623 # This is because the temp result is often used outside of
1624 # the regular cycle.
1626 subexprs = []
1628 def __init__(self, pos, type, env):
1629 ExprNode.__init__(self, pos)
1630 self.type = type
1631 if type.is_pyobject:
1632 self.result_ctype = py_object_type
1633 self.is_temp = 1
1635 def analyse_types(self, env):
1636 return self.type
1638 def generate_result_code(self, code):
1639 pass
1641 def allocate(self, code):
1642 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
1644 def release(self, code):
1645 code.funcstate.release_temp(self.temp_cname)
1646 self.temp_cname = None
1648 def result(self):
1649 try:
1650 return self.temp_cname
1651 except:
1652 assert False, "Remember to call allocate/release on TempNode"
1653 raise
1655 # Do not participate in normal temp alloc/dealloc:
1656 def allocate_temp_result(self, code):
1657 pass
1659 def release_temp_result(self, code):
1660 pass
1662 class PyTempNode(TempNode):
1663 # TempNode holding a Python value.
1665 def __init__(self, pos, env):
1666 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1668 class RawCNameExprNode(ExprNode):
1669 subexprs = []
1671 def __init__(self, pos, type=None):
1672 self.pos = pos
1673 self.type = type
1675 def analyse_types(self, env):
1676 return self.type
1678 def set_cname(self, cname):
1679 self.cname = cname
1681 def result(self):
1682 return self.cname
1684 def generate_result_code(self, code):
1685 pass
1688 #-------------------------------------------------------------------
1689 #
1690 # Trailer nodes
1691 #
1692 #-------------------------------------------------------------------
1694 class IndexNode(ExprNode):
1695 # Sequence indexing.
1696 #
1697 # base ExprNode
1698 # index ExprNode
1699 # indices [ExprNode]
1700 # is_buffer_access boolean Whether this is a buffer access.
1701 #
1702 # indices is used on buffer access, index on non-buffer access.
1703 # The former contains a clean list of index parameters, the
1704 # latter whatever Python object is needed for index access.
1706 subexprs = ['base', 'index', 'indices']
1707 indices = None
1709 def __init__(self, pos, index, *args, **kw):
1710 ExprNode.__init__(self, pos, index=index, *args, **kw)
1711 self._index = index
1713 def calculate_constant_result(self):
1714 self.constant_result = \
1715 self.base.constant_result[self.index.constant_result]
1717 def compile_time_value(self, denv):
1718 base = self.base.compile_time_value(denv)
1719 index = self.index.compile_time_value(denv)
1720 try:
1721 return base[index]
1722 except Exception, e:
1723 self.compile_time_value_error(e)
1725 def is_ephemeral(self):
1726 return self.base.is_ephemeral()
1728 def analyse_target_declaration(self, env):
1729 pass
1731 def analyse_as_type(self, env):
1732 base_type = self.base.analyse_as_type(env)
1733 if base_type and not base_type.is_pyobject:
1734 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1735 return None
1737 def type_dependencies(self, env):
1738 return self.base.type_dependencies(env)
1740 def infer_type(self, env):
1741 if isinstance(self.base, (StringNode, UnicodeNode)): # FIXME: BytesNode?
1742 return py_object_type
1743 base_type = self.base.infer_type(env)
1744 if base_type.is_ptr or base_type.is_array:
1745 return base_type.base_type
1746 else:
1747 # TODO: Handle buffers (hopefully without too much redundancy).
1748 return py_object_type
1750 def analyse_types(self, env):
1751 self.analyse_base_and_index_types(env, getting = 1)
1753 def analyse_target_types(self, env):
1754 self.analyse_base_and_index_types(env, setting = 1)
1756 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1757 # Note: This might be cleaned up by having IndexNode
1758 # parsed in a saner way and only construct the tuple if
1759 # needed.
1761 # Note that this function must leave IndexNode in a cloneable state.
1762 # For buffers, self.index is packed out on the initial analysis, and
1763 # when cloning self.indices is copied.
1764 self.is_buffer_access = False
1766 self.base.analyse_types(env)
1767 # Handle the case where base is a literal char* (and we expect a string, not an int)
1768 if isinstance(self.base, BytesNode):
1769 self.base = self.base.coerce_to_pyobject(env)
1771 skip_child_analysis = False
1772 buffer_access = False
1773 if self.base.type.is_buffer:
1774 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1775 if self.indices:
1776 indices = self.indices
1777 else:
1778 if isinstance(self.index, TupleNode):
1779 indices = self.index.args
1780 else:
1781 indices = [self.index]
1782 if len(indices) == self.base.type.ndim:
1783 buffer_access = True
1784 skip_child_analysis = True
1785 for x in indices:
1786 x.analyse_types(env)
1787 if not x.type.is_int:
1788 buffer_access = False
1790 # On cloning, indices is cloned. Otherwise, unpack index into indices
1791 assert not (buffer_access and isinstance(self.index, CloneNode))
1793 if buffer_access:
1794 self.indices = indices
1795 self.index = None
1796 self.type = self.base.type.dtype
1797 self.is_buffer_access = True
1798 self.buffer_type = self.base.entry.type
1800 if getting and self.type.is_pyobject:
1801 self.is_temp = True
1802 if setting:
1803 if not self.base.entry.type.writable:
1804 error(self.pos, "Writing to readonly buffer")
1805 else:
1806 self.base.entry.buffer_aux.writable_needed = True
1807 else:
1808 if isinstance(self.index, TupleNode):
1809 self.index.analyse_types(env, skip_children=skip_child_analysis)
1810 elif not skip_child_analysis:
1811 self.index.analyse_types(env)
1812 self.original_index_type = self.index.type
1813 if self.base.type.is_pyobject:
1814 if self.index.type.is_int:
1815 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1816 else:
1817 self.index = self.index.coerce_to_pyobject(env)
1818 self.type = py_object_type
1819 self.is_temp = 1
1820 else:
1821 if self.base.type.is_ptr or self.base.type.is_array:
1822 self.type = self.base.type.base_type
1823 else:
1824 error(self.pos,
1825 "Attempting to index non-array type '%s'" %
1826 self.base.type)
1827 self.type = PyrexTypes.error_type
1828 if self.index.type.is_pyobject:
1829 self.index = self.index.coerce_to(
1830 PyrexTypes.c_py_ssize_t_type, env)
1831 if not self.index.type.is_int:
1832 error(self.pos,
1833 "Invalid index type '%s'" %
1834 self.index.type)
1835 gil_message = "Indexing Python object"
1837 def nogil_check(self, env):
1838 if self.is_buffer_access:
1839 if env.directives['boundscheck']:
1840 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1841 return
1842 elif self.type.is_pyobject:
1843 error(self.pos, "Cannot access buffer with object dtype without gil")
1844 return
1845 super(IndexNode, self).nogil_check(env)
1848 def check_const_addr(self):
1849 self.base.check_const_addr()
1850 self.index.check_const()
1852 def is_lvalue(self):
1853 return 1
1855 def calculate_result_code(self):
1856 if self.is_buffer_access:
1857 return "(*%s)" % self.buffer_ptr_code
1858 else:
1859 return "(%s[%s])" % (
1860 self.base.result(), self.index.result())
1862 def extra_index_params(self):
1863 if self.index.type.is_int:
1864 if self.original_index_type.signed:
1865 size_adjustment = ""
1866 else:
1867 size_adjustment = "+1"
1868 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1869 else:
1870 return ""
1872 def generate_subexpr_evaluation_code(self, code):
1873 self.base.generate_evaluation_code(code)
1874 if not self.indices:
1875 self.index.generate_evaluation_code(code)
1876 else:
1877 for i in self.indices:
1878 i.generate_evaluation_code(code)
1880 def generate_subexpr_disposal_code(self, code):
1881 self.base.generate_disposal_code(code)
1882 if not self.indices:
1883 self.index.generate_disposal_code(code)
1884 else:
1885 for i in self.indices:
1886 i.generate_disposal_code(code)
1888 def free_subexpr_temps(self, code):
1889 self.base.free_temps(code)
1890 if not self.indices:
1891 self.index.free_temps(code)
1892 else:
1893 for i in self.indices:
1894 i.free_temps(code)
1896 def generate_result_code(self, code):
1897 if self.is_buffer_access:
1898 if code.globalstate.directives['nonecheck']:
1899 self.put_nonecheck(code)
1900 self.buffer_ptr_code = self.buffer_lookup_code(code)
1901 if self.type.is_pyobject:
1902 # is_temp is True, so must pull out value and incref it.
1903 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1904 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1905 elif self.type.is_pyobject:
1906 if self.index.type.is_int:
1907 index_code = self.index.result()
1908 if self.base.type is list_type:
1909 function = "__Pyx_GetItemInt_List"
1910 elif self.base.type is tuple_type:
1911 function = "__Pyx_GetItemInt_Tuple"
1912 else:
1913 function = "__Pyx_GetItemInt"
1914 code.globalstate.use_utility_code(getitem_int_utility_code)
1915 else:
1916 function = "PyObject_GetItem"
1917 index_code = self.index.py_result()
1918 sign_code = ""
1919 code.putln(
1920 "%s = %s(%s, %s%s); if (!%s) %s" % (
1921 self.result(),
1922 function,
1923 self.base.py_result(),
1924 index_code,
1925 self.extra_index_params(),
1926 self.result(),
1927 code.error_goto(self.pos)))
1928 code.put_gotref(self.py_result())
1930 def generate_setitem_code(self, value_code, code):
1931 if self.index.type.is_int:
1932 function = "__Pyx_SetItemInt"
1933 index_code = self.index.result()
1934 code.globalstate.use_utility_code(setitem_int_utility_code)
1935 else:
1936 index_code = self.index.py_result()
1937 if self.base.type is dict_type:
1938 function = "PyDict_SetItem"
1939 # It would seem that we could specalized lists/tuples, but that
1940 # shouldn't happen here.
1941 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1942 # not a PyObject*, and bad conversion here would give the wrong
1943 # exception. Also, tuples are supposed to be immutable, and raise
1944 # TypeErrors when trying to set their entries (PyTuple_SetItem
1945 # is for creating new tuples from).
1946 else:
1947 function = "PyObject_SetItem"
1948 code.putln(
1949 "if (%s(%s, %s, %s%s) < 0) %s" % (
1950 function,
1951 self.base.py_result(),
1952 index_code,
1953 value_code,
1954 self.extra_index_params(),
1955 code.error_goto(self.pos)))
1957 def generate_buffer_setitem_code(self, rhs, code, op=""):
1958 # Used from generate_assignment_code and InPlaceAssignmentNode
1959 if code.globalstate.directives['nonecheck']:
1960 self.put_nonecheck(code)
1961 ptrexpr = self.buffer_lookup_code(code)
1962 if self.buffer_type.dtype.is_pyobject:
1963 # Must manage refcounts. Decref what is already there
1964 # and incref what we put in.
1965 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1966 rhs_code = rhs.result()
1967 code.putln("%s = %s;" % (ptr, ptrexpr))
1968 code.put_gotref("*%s" % ptr)
1969 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1970 ptr, rhs_code
1971 ))
1972 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1973 code.put_giveref("*%s" % ptr)
1974 code.funcstate.release_temp(ptr)
1975 else:
1976 # Simple case
1977 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1979 def generate_assignment_code(self, rhs, code):
1980 self.generate_subexpr_evaluation_code(code)
1981 if self.is_buffer_access:
1982 self.generate_buffer_setitem_code(rhs, code)
1983 elif self.type.is_pyobject:
1984 self.generate_setitem_code(rhs.py_result(), code)
1985 else:
1986 code.putln(
1987 "%s = %s;" % (
1988 self.result(), rhs.result()))
1989 self.generate_subexpr_disposal_code(code)
1990 self.free_subexpr_temps(code)
1991 rhs.generate_disposal_code(code)
1992 rhs.free_temps(code)
1994 def generate_deletion_code(self, code):
1995 self.generate_subexpr_evaluation_code(code)
1996 #if self.type.is_pyobject:
1997 if self.index.type.is_int:
1998 function = "__Pyx_DelItemInt"
1999 index_code = self.index.result()
2000 code.globalstate.use_utility_code(delitem_int_utility_code)
2001 else:
2002 index_code = self.index.py_result()
2003 if self.base.type is dict_type:
2004 function = "PyDict_DelItem"
2005 else:
2006 function = "PyObject_DelItem"
2007 code.putln(
2008 "if (%s(%s, %s%s) < 0) %s" % (
2009 function,
2010 self.base.py_result(),
2011 index_code,
2012 self.extra_index_params(),
2013 code.error_goto(self.pos)))
2014 self.generate_subexpr_disposal_code(code)
2015 self.free_subexpr_temps(code)
2017 def buffer_lookup_code(self, code):
2018 # Assign indices to temps
2019 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2020 for temp, index in zip(index_temps, self.indices):
2021 code.putln("%s = %s;" % (temp, index.result()))
2022 # Generate buffer access code using these temps
2023 import Buffer
2024 # The above could happen because child_attrs is wrong somewhere so that
2025 # options are not propagated.
2026 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2027 index_signeds=[i.type.signed for i in self.indices],
2028 index_cnames=index_temps,
2029 directives=code.globalstate.directives,
2030 pos=self.pos, code=code)
2032 def put_nonecheck(self, code):
2033 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2034 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2035 code.putln("__Pyx_RaiseNoneIndexingError();")
2036 code.putln(code.error_goto(self.pos))
2037 code.putln("}")
2039 class SliceIndexNode(ExprNode):
2040 # 2-element slice indexing
2041 #
2042 # base ExprNode
2043 # start ExprNode or None
2044 # stop ExprNode or None
2046 subexprs = ['base', 'start', 'stop']
2048 def calculate_constant_result(self):
2049 self.constant_result = self.base.constant_result[
2050 self.start.constant_result : self.stop.constant_result]
2052 def compile_time_value(self, denv):
2053 base = self.base.compile_time_value(denv)
2054 if self.start is None:
2055 start = 0
2056 else:
2057 start = self.start.compile_time_value(denv)
2058 if self.stop is None:
2059 stop = None
2060 else:
2061 stop = self.stop.compile_time_value(denv)
2062 try:
2063 return base[start:stop]
2064 except Exception, e:
2065 self.compile_time_value_error(e)
2067 def analyse_target_declaration(self, env):
2068 pass
2070 def analyse_target_types(self, env):
2071 self.analyse_types(env)
2072 # when assigning, we must accept any Python type
2073 if self.type.is_pyobject:
2074 self.type = py_object_type
2076 def analyse_types(self, env):
2077 self.base.analyse_types(env)
2078 if self.start:
2079 self.start.analyse_types(env)
2080 if self.stop:
2081 self.stop.analyse_types(env)
2082 base_type = self.base.type
2083 if base_type.is_string:
2084 self.type = bytes_type
2085 elif base_type.is_array or base_type.is_ptr:
2086 # we need a ptr type here instead of an array type, as
2087 # array types can result in invalid type casts in the C
2088 # code
2089 self.type = PyrexTypes.CPtrType(base_type.base_type)
2090 else:
2091 self.base = self.base.coerce_to_pyobject(env)
2092 self.type = py_object_type
2093 if base_type.is_builtin_type:
2094 # slicing builtin types returns something of the same type
2095 self.type = base_type
2096 c_int = PyrexTypes.c_py_ssize_t_type
2097 if self.start:
2098 self.start = self.start.coerce_to(c_int, env)
2099 if self.stop:
2100 self.stop = self.stop.coerce_to(c_int, env)
2101 self.is_temp = 1
2103 nogil_check = Node.gil_error
2104 gil_message = "Slicing Python object"
2106 def generate_result_code(self, code):
2107 if not self.type.is_pyobject:
2108 error(self.pos,
2109 "Slicing is not currently supported for '%s'." % self.type)
2110 return
2111 if self.base.type.is_string:
2112 if self.stop is None:
2113 code.putln(
2114 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2115 self.result(),
2116 self.base.result(),
2117 self.start_code(),
2118 code.error_goto_if_null(self.result(), self.pos)))
2119 else:
2120 code.putln(
2121 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2122 self.result(),
2123 self.base.result(),
2124 self.start_code(),
2125 self.stop_code(),
2126 self.start_code(),
2127 code.error_goto_if_null(self.result(), self.pos)))
2128 else:
2129 code.putln(
2130 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2131 self.result(),
2132 self.base.py_result(),
2133 self.start_code(),
2134 self.stop_code(),
2135 code.error_goto_if_null(self.result(), self.pos)))
2136 code.put_gotref(self.py_result())
2138 def generate_assignment_code(self, rhs, code):
2139 self.generate_subexpr_evaluation_code(code)
2140 if self.type.is_pyobject:
2141 code.put_error_if_neg(self.pos,
2142 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2143 self.base.py_result(),
2144 self.start_code(),
2145 self.stop_code(),
2146 rhs.result()))
2147 else:
2148 start_offset = ''
2149 if self.start:
2150 start_offset = self.start_code()
2151 if start_offset == '0':
2152 start_offset = ''
2153 else:
2154 start_offset += '+'
2155 if rhs.type.is_array:
2156 array_length = rhs.type.size
2157 self.generate_slice_guard_code(code, array_length)
2158 else:
2159 error(self.pos,
2160 "Slice assignments from pointers are not yet supported.")
2161 # FIXME: fix the array size according to start/stop
2162 array_length = self.base.type.size
2163 for i in range(array_length):
2164 code.putln("%s[%s%s] = %s[%d];" % (
2165 self.base.result(), start_offset, i,
2166 rhs.result(), i))
2167 self.generate_subexpr_disposal_code(code)
2168 self.free_subexpr_temps(code)
2169 rhs.generate_disposal_code(code)
2170 rhs.free_temps(code)
2172 def generate_deletion_code(self, code):
2173 if not self.base.type.is_pyobject:
2174 error(self.pos,
2175 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2176 return
2177 self.generate_subexpr_evaluation_code(code)
2178 code.put_error_if_neg(self.pos,
2179 "PySequence_DelSlice(%s, %s, %s)" % (
2180 self.base.py_result(),
2181 self.start_code(),
2182 self.stop_code()))
2183 self.generate_subexpr_disposal_code(code)
2185 def generate_slice_guard_code(self, code, target_size):
2186 if not self.base.type.is_array:
2187 return
2188 slice_size = self.base.type.size
2189 start = stop = None
2190 if self.stop:
2191 stop = self.stop.result()
2192 try:
2193 stop = int(stop)
2194 if stop < 0:
2195 slice_size = self.base.type.size + stop
2196 else:
2197 slice_size = stop
2198 stop = None
2199 except ValueError:
2200 pass
2201 if self.start:
2202 start = self.start.result()
2203 try:
2204 start = int(start)
2205 if start < 0:
2206 start = self.base.type.size + start
2207 slice_size -= start
2208 start = None
2209 except ValueError:
2210 pass
2211 check = None
2212 if slice_size < 0:
2213 if target_size > 0:
2214 error(self.pos, "Assignment to empty slice.")
2215 elif start is None and stop is None:
2216 # we know the exact slice length
2217 if target_size != slice_size:
2218 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2219 slice_size, target_size))
2220 elif start is not None:
2221 if stop is None:
2222 stop = slice_size
2223 check = "(%s)-(%s)" % (stop, start)
2224 else: # stop is not None:
2225 check = stop
2226 if check:
2227 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2228 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%"PY_FORMAT_SIZE_T"d, got %%"PY_FORMAT_SIZE_T"d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
2229 target_size, check))
2230 code.putln(code.error_goto(self.pos))
2231 code.putln("}")
2233 def start_code(self):
2234 if self.start:
2235 return self.start.result()
2236 else:
2237 return "0"
2239 def stop_code(self):
2240 if self.stop:
2241 return self.stop.result()
2242 elif self.base.type.is_array:
2243 return self.base.type.size
2244 else:
2245 return "PY_SSIZE_T_MAX"
2247 def calculate_result_code(self):
2248 # self.result() is not used, but this method must exist
2249 return "<unused>"
2252 class SliceNode(ExprNode):
2253 # start:stop:step in subscript list
2254 #
2255 # start ExprNode
2256 # stop ExprNode
2257 # step ExprNode
2259 type = py_object_type
2260 is_temp = 1
2262 def calculate_constant_result(self):
2263 self.constant_result = self.base.constant_result[
2264 self.start.constant_result : \
2265 self.stop.constant_result : \
2266 self.step.constant_result]
2268 def compile_time_value(self, denv):
2269 start = self.start.compile_time_value(denv)
2270 if self.stop is None:
2271 stop = None
2272 else:
2273 stop = self.stop.compile_time_value(denv)
2274 if self.step is None:
2275 step = None
2276 else:
2277 step = self.step.compile_time_value(denv)
2278 try:
2279 return slice(start, stop, step)
2280 except Exception, e:
2281 self.compile_time_value_error(e)
2283 subexprs = ['start', 'stop', 'step']
2285 def analyse_types(self, env):
2286 self.start.analyse_types(env)
2287 self.stop.analyse_types(env)
2288 self.step.analyse_types(env)
2289 self.start = self.start.coerce_to_pyobject(env)
2290 self.stop = self.stop.coerce_to_pyobject(env)
2291 self.step = self.step.coerce_to_pyobject(env)
2293 gil_message = "Constructing Python slice object"
2295 def generate_result_code(self, code):
2296 code.putln(
2297 "%s = PySlice_New(%s, %s, %s); %s" % (
2298 self.result(),
2299 self.start.py_result(),
2300 self.stop.py_result(),
2301 self.step.py_result(),
2302 code.error_goto_if_null(self.result(), self.pos)))
2303 code.put_gotref(self.py_result())
2306 class CallNode(ExprNode):
2308 def analyse_as_type_constructor(self, env):
2309 type = self.function.analyse_as_type(env)
2310 if type and type.is_struct_or_union:
2311 args, kwds = self.explicit_args_kwds()
2312 items = []
2313 for arg, member in zip(args, type.scope.var_entries):
2314 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg))
2315 if kwds:
2316 items += kwds.key_value_pairs
2317 self.key_value_pairs = items
2318 self.__class__ = DictNode
2319 self.analyse_types(env)
2320 self.coerce_to(type, env)
2321 return True
2323 def nogil_check(self, env):
2324 func_type = self.function_type()
2325 if func_type.is_pyobject:
2326 self.gil_error()
2327 elif not getattr(func_type, 'nogil', False):
2328 self.gil_error()
2330 gil_message = "Calling gil-requiring function"
2333 class SimpleCallNode(CallNode):
2334 # Function call without keyword, * or ** args.
2335 #
2336 # function ExprNode
2337 # args [ExprNode]
2338 # arg_tuple ExprNode or None used internally
2339 # self ExprNode or None used internally
2340 # coerced_self ExprNode or None used internally
2341 # wrapper_call bool used internally
2342 # has_optional_args bool used internally
2344 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2346 self = None
2347 coerced_self = None
2348 arg_tuple = None
2349 wrapper_call = False
2350 has_optional_args = False
2352 def compile_time_value(self, denv):
2353 function = self.function.compile_time_value(denv)
2354 args = [arg.compile_time_value(denv) for arg in self.args]
2355 try:
2356 return function(*args)
2357 except Exception, e:
2358 self.compile_time_value_error(e)
2360 def type_dependencies(self, env):
2361 # TODO: Update when Danilo's C++ code merged in to handle the
2362 # the case of function overloading.
2363 return self.function.type_dependencies(env)
2365 def infer_type(self, env):
2366 func_type = self.function.infer_type(env)
2367 if func_type.is_ptr:
2368 func_type = func_type.base_type
2369 if func_type.is_cfunction:
2370 return func_type.return_type
2371 else:
2372 return py_object_type
2374 def analyse_as_type(self, env):
2375 attr = self.function.as_cython_attribute()
2376 if attr == 'pointer':
2377 if len(self.args) != 1:
2378 error(self.args.pos, "only one type allowed.")
2379 else:
2380 type = self.args[0].analyse_as_type(env)
2381 if not type:
2382 error(self.args[0].pos, "Unknown type")
2383 else:
2384 return PyrexTypes.CPtrType(type)
2386 def explicit_args_kwds(self):
2387 return self.args, None
2389 def analyse_types(self, env):
2390 if self.analyse_as_type_constructor(env):
2391 return
2392 function = self.function
2393 function.is_called = 1
2394 self.function.analyse_types(env)
2395 if function.is_attribute and function.entry and function.entry.is_cmethod:
2396 # Take ownership of the object from which the attribute
2397 # was obtained, because we need to pass it as 'self'.
2398 self.self = function.obj
2399 function.obj = CloneNode(self.self)
2400 func_type = self.function_type()
2401 if func_type.is_pyobject:
2402 self.arg_tuple = TupleNode(self.pos, args = self.args)
2403 self.arg_tuple.analyse_types(env)
2404 self.args = None
2405 if function.is_name and function.type_entry:
2406 # We are calling an extension type constructor. As
2407 # long as we do not support __new__(), the result type
2408 # is clear
2409 self.type = function.type_entry.type
2410 self.result_ctype = py_object_type
2411 else:
2412 self.type = py_object_type
2413 self.is_temp = 1
2414 else:
2415 for arg in self.args:
2416 arg.analyse_types(env)
2417 if self.self and func_type.args:
2418 # Coerce 'self' to the type expected by the method.
2419 expected_type = func_type.args[0].type
2420 self.coerced_self = CloneNode(self.self).coerce_to(
2421 expected_type, env)
2422 # Insert coerced 'self' argument into argument list.
2423 self.args.insert(0, self.coerced_self)
2424 self.analyse_c_function_call(env)
2426 def function_type(self):
2427 # Return the type of the function being called, coercing a function
2428 # pointer to a function if necessary.
2429 func_type = self.function.type
2430 if func_type.is_ptr:
2431 func_type = func_type.base_type
2432 return func_type
2434 def analyse_c_function_call(self, env):
2435 func_type = self.function_type()
2436 # Check function type
2437 if not func_type.is_cfunction:
2438 if not func_type.is_error:
2439 error(self.pos, "Calling non-function type '%s'" %
2440 func_type)
2441 self.type = PyrexTypes.error_type
2442 self.result_code = "<error>"
2443 return
2444 # Check no. of args
2445 max_nargs = len(func_type.args)
2446 expected_nargs = max_nargs - func_type.optional_arg_count
2447 actual_nargs = len(self.args)
2448 if actual_nargs < expected_nargs \
2449 or (not func_type.has_varargs and actual_nargs > max_nargs):
2450 expected_str = str(expected_nargs)
2451 if func_type.has_varargs:
2452 expected_str = "at least " + expected_str
2453 elif func_type.optional_arg_count:
2454 if actual_nargs < max_nargs:
2455 expected_str = "at least " + expected_str
2456 else:
2457 expected_str = "at most " + str(max_nargs)
2458 error(self.pos,
2459 "Call with wrong number of arguments (expected %s, got %s)"
2460 % (expected_str, actual_nargs))
2461 self.args = None
2462 self.type = PyrexTypes.error_type
2463 self.result_code = "<error>"
2464 return
2465 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2466 self.has_optional_args = 1
2467 self.is_temp = 1
2468 # Coerce arguments
2469 for i in range(min(max_nargs, actual_nargs)):
2470 formal_type = func_type.args[i].type
2471 self.args[i] = self.args[i].coerce_to(formal_type, env)
2472 for i in range(max_nargs, actual_nargs):
2473 if self.args[i].type.is_pyobject:
2474 error(self.args[i].pos,
2475 "Python object cannot be passed as a varargs parameter")
2476 # Calc result type and code fragment
2477 self.type = func_type.return_type
2478 if self.type.is_pyobject:
2479 self.result_ctype = py_object_type
2480 self.is_temp = 1
2481 elif func_type.exception_value is not None \
2482 or func_type.exception_check:
2483 self.is_temp = 1
2484 # C++ exception handler
2485 if func_type.exception_check == '+':
2486 if func_type.exception_value is None:
2487 env.use_utility_code(cpp_exception_utility_code)
2489 def calculate_result_code(self):
2490 return self.c_call_code()
2492 def c_call_code(self):
2493 func_type = self.function_type()
2494 if self.args is None or not func_type.is_cfunction:
2495 return "<error>"
2496 formal_args = func_type.args
2497 arg_list_code = []
2498 args = zip(formal_args, self.args)
2499 max_nargs = len(func_type.args)
2500 expected_nargs = max_nargs - func_type.optional_arg_count
2501 actual_nargs = len(self.args)
2502 for formal_arg, actual_arg in args[:expected_nargs]:
2503 arg_code = actual_arg.result_as(formal_arg.type)
2504 arg_list_code.append(arg_code)
2506 if func_type.is_overridable:
2507 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2509 if func_type.optional_arg_count:
2510 if expected_nargs == actual_nargs:
2511 optional_args = 'NULL'
2512 else:
2513 optional_args = "&%s" % self.opt_arg_struct
2514 arg_list_code.append(optional_args)
2516 for actual_arg in self.args[len(formal_args):]:
2517 arg_list_code.append(actual_arg.result())
2518 result = "%s(%s)" % (self.function.result(),
2519 ', '.join(arg_list_code))
2520 return result
2522 def generate_result_code(self, code):
2523 func_type = self.function_type()
2524 if func_type.is_pyobject:
2525 arg_code = self.arg_tuple.py_result()
2526 code.putln(
2527 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2528 self.result(),
2529 self.function.py_result(),
2530 arg_code,
2531 code.error_goto_if_null(self.result(), self.pos)))
2532 code.put_gotref(self.py_result())
2533 elif func_type.is_cfunction:
2534 if self.has_optional_args:
2535 actual_nargs = len(self.args)
2536 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2537 self.opt_arg_struct = code.funcstate.allocate_temp(
2538 func_type.op_arg_struct.base_type, manage_ref=True)
2539 code.putln("%s.%s = %s;" % (
2540 self.opt_arg_struct,
2541 Naming.pyrex_prefix + "n",
2542 len(self.args) - expected_nargs))
2543 args = zip(func_type.args, self.args)
2544 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2545 code.putln("%s.%s = %s;" % (
2546 self.opt_arg_struct,
2547 formal_arg.name,
2548 actual_arg.result_as(formal_arg.type)))
2549 exc_checks = []
2550 if self.type.is_pyobject:
2551 exc_checks.append("!%s" % self.result())
2552 else:
2553 exc_val = func_type.exception_value
2554 exc_check = func_type.exception_check
2555 if exc_val is not None:
2556 exc_checks.append("%s == %s" % (self.result(), exc_val))
2557 if exc_check:
2558 exc_checks.append("PyErr_Occurred()")
2559 if self.is_temp or exc_checks:
2560 rhs = self.c_call_code()
2561 if self.result():
2562 lhs = "%s = " % self.result()
2563 if self.is_temp and self.type.is_pyobject:
2564 #return_type = self.type # func_type.return_type
2565 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2566 # "from", return_type, "to pyobject" ###
2567 rhs = typecast(py_object_type, self.type, rhs)
2568 else:
2569 lhs = ""
2570 if func_type.exception_check == '+':
2571 if func_type.exception_value is None:
2572 raise_py_exception = "__Pyx_CppExn2PyErr()"
2573 elif func_type.exception_value.type.is_pyobject:
2574 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2575 else:
2576 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2577 code.putln(
2578 "try {%s%s;} catch(...) {%s; %s}" % (
2579 lhs,
2580 rhs,
2581 raise_py_exception,
2582 code.error_goto(self.pos)))
2583 else:
2584 if exc_checks:
2585 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2586 else:
2587 goto_error = ""
2588 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2589 if self.type.is_pyobject and self.result():
2590 code.put_gotref(self.py_result())
2591 if self.has_optional_args:
2592 code.funcstate.release_temp(self.opt_arg_struct)
2595 class PythonCapiFunctionNode(ExprNode):
2596 subexprs = []
2597 def __init__(self, pos, name, func_type, utility_code = None):
2598 self.pos = pos
2599 self.name = name
2600 self.type = func_type
2601 self.utility_code = utility_code
2603 def generate_result_code(self, code):
2604 if self.utility_code:
2605 code.globalstate.use_utility_code(self.utility_code)
2607 def calculate_result_code(self):
2608 return self.name
2610 class PythonCapiCallNode(SimpleCallNode):
2611 # Python C-API Function call (only created in transforms)
2613 def __init__(self, pos, function_name, func_type,
2614 utility_code = None, **kwargs):
2615 self.type = func_type.return_type
2616 self.result_ctype = self.type
2617 self.function = PythonCapiFunctionNode(
2618 pos, function_name, func_type,
2619 utility_code = utility_code)
2620 # call this last so that we can override the constructed
2621 # attributes above with explicit keyword arguments if required
2622 SimpleCallNode.__init__(self, pos, **kwargs)
2625 class GeneralCallNode(CallNode):
2626 # General Python function call, including keyword,
2627 # * and ** arguments.
2628 #
2629 # function ExprNode
2630 # positional_args ExprNode Tuple of positional arguments
2631 # keyword_args ExprNode or None Dict of keyword arguments
2632 # starstar_arg ExprNode or None Dict of extra keyword args
2634 type = py_object_type
2636 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2638 nogil_check = Node.gil_error
2640 def compile_time_value(self, denv):
2641 function = self.function.compile_time_value(denv)
2642 positional_args = self.positional_args.compile_time_value(denv)
2643 keyword_args = self.keyword_args.compile_time_value(denv)
2644 starstar_arg = self.starstar_arg.compile_time_value(denv)
2645 try:
2646 keyword_args.update(starstar_arg)
2647 return function(*positional_args, **keyword_args)
2648 except Exception, e:
2649 self.compile_time_value_error(e)
2651 def explicit_args_kwds(self):
2652 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2653 raise PostParseError(self.pos,
2654 'Compile-time keyword arguments must be explicit.')
2655 return self.positional_args.args, self.keyword_args
2657 def analyse_types(self, env):
2658 if self.analyse_as_type_constructor(env):
2659 return
2660 self.function.analyse_types(env)
2661 self.positional_args.analyse_types(env)
2662 if self.keyword_args:
2663 self.keyword_args.analyse_types(env)
2664 if self.starstar_arg:
2665 self.starstar_arg.analyse_types(env)
2666 if not self.function.type.is_pyobject:
2667 if self.function.type.is_error:
2668 self.type = error_type
2669 return error_type
2670 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2671 error(self.pos, "Keyword arguments not allowed in cdef functions.")
2672 else:
2673 self.function = self.function.coerce_to_pyobject(env)
2674 self.positional_args = \
2675 self.positional_args.coerce_to_pyobject(env)
2676 if self.starstar_arg:
2677 self.starstar_arg = \
2678 self.starstar_arg.coerce_to_pyobject(env)
2679 function = self.function
2680 if function.is_name and function.type_entry:
2681 # We are calling an extension type constructor. As long
2682 # as we do not support __new__(), the result type is clear
2683 self.type = function.type_entry.type
2684 self.result_ctype = py_object_type
2685 else:
2686 self.type = py_object_type
2687 self.is_temp = 1
2689 def generate_result_code(self, code):
2690 if self.type.is_error: return
2691 if self.keyword_args and self.starstar_arg:
2692 code.put_error_if_neg(self.pos,
2693 "PyDict_Update(%s, %s)" % (
2694 self.keyword_args.py_result(),
2695 self.starstar_arg.py_result()))
2696 keyword_code = self.keyword_args.py_result()
2697 elif self.keyword_args:
2698 keyword_code = self.keyword_args.py_result()
2699 elif self.starstar_arg:
2700 keyword_code = self.starstar_arg.py_result()
2701 else:
2702 keyword_code = None
2703 if not keyword_code:
2704 call_code = "PyObject_Call(%s, %s, NULL)" % (
2705 self.function.py_result(),
2706 self.positional_args.py_result())
2707 else:
2708 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2709 self.function.py_result(),
2710 self.positional_args.py_result(),
2711 keyword_code)
2712 code.putln(
2713 "%s = %s; %s" % (
2714 self.result(),
2715 call_code,
2716 code.error_goto_if_null(self.result(), self.pos)))
2717 code.put_gotref(self.py_result())
2720 class AsTupleNode(ExprNode):
2721 # Convert argument to tuple. Used for normalising
2722 # the * argument of a function call.
2723 #
2724 # arg ExprNode
2726 subexprs = ['arg']
2728 def calculate_constant_result(self):
2729 self.constant_result = tuple(self.base.constant_result)
2731 def compile_time_value(self, denv):
2732 arg = self.arg.compile_time_value(denv)
2733 try:
2734 return tuple(arg)
2735 except Exception, e:
2736 self.compile_time_value_error(e)
2738 def analyse_types(self, env):
2739 self.arg.analyse_types(env)
2740 self.arg = self.arg.coerce_to_pyobject(env)
2741 self.type = tuple_type
2742 self.is_temp = 1
2744 nogil_check = Node.gil_error
2745 gil_message = "Constructing Python tuple"
2747 def generate_result_code(self, code):
2748 code.putln(
2749 "%s = PySequence_Tuple(%s); %s" % (
2750 self.result(),
2751 self.arg.py_result(),
2752 code.error_goto_if_null(self.result(), self.pos)))
2753 code.put_gotref(self.py_result())
2756 class AttributeNode(ExprNode):
2757 # obj.attribute
2758 #
2759 # obj ExprNode
2760 # attribute string
2761 # needs_none_check boolean Used if obj is an extension type.
2762 # If set to True, it is known that the type is not None.
2763 #
2764 # Used internally:
2765 #
2766 # is_py_attr boolean Is a Python getattr operation
2767 # member string C name of struct member
2768 # is_called boolean Function call is being done on result
2769 # entry Entry Symbol table entry of attribute
2771 is_attribute = 1
2772 subexprs = ['obj']
2774 type = PyrexTypes.error_type
2775 entry = None
2776 is_called = 0
2777 needs_none_check = True
2779 def as_cython_attribute(self):
2780 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2781 return self.attribute
2783 def coerce_to(self, dst_type, env):
2784 # If coercing to a generic pyobject and this is a cpdef function
2785 # we can create the corresponding attribute
2786 if dst_type is py_object_type:
2787 entry = self.entry
2788 if entry and entry.is_cfunction and entry.as_variable:
2789 # must be a cpdef function
2790 self.is_temp = 1
2791 self.entry = entry.as_variable
2792 self.analyse_as_python_attribute(env)
2793 return self
2794 return ExprNode.coerce_to(self, dst_type, env)
2796 def calculate_constant_result(self):
2797 attr = self.attribute
2798 if attr.startswith("__") and attr.endswith("__"):
2799 return
2800 self.constant_result = getattr(self.obj.constant_result, attr)
2802 def compile_time_value(self, denv):
2803 attr = self.attribute
2804 if attr.startswith("__") and attr.endswith("__"):
2805 error(self.pos,
2806 "Invalid attribute name '%s' in compile-time expression" % attr)
2807 return None
2808 obj = self.obj.compile_time_value(denv)
2809 try:
2810 return getattr(obj, attr)
2811 except Exception, e:
2812 self.compile_time_value_error(e)
2814 def type_dependencies(self, env):
2815 return self.obj.type_dependencies(env)
2817 def infer_type(self, env):
2818 if self.analyse_as_cimported_attribute(env, 0):
2819 return self.entry.type
2820 elif self.analyse_as_unbound_cmethod(env):
2821 return self.entry.type
2822 else:
2823 self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
2824 return self.type
2826 def analyse_target_declaration(self, env):
2827 pass
2829 def analyse_target_types(self, env):
2830 self.analyse_types(env, target = 1)
2832 def analyse_types(self, env, target = 0):
2833 if self.analyse_as_cimported_attribute(env, target):
2834 return
2835 if not target and self.analyse_as_unbound_cmethod(env):
2836 return
2837 self.analyse_as_ordinary_attribute(env, target)
2839 def analyse_as_cimported_attribute(self, env, target):
2840 # Try to interpret this as a reference to an imported
2841 # C const, type, var or function. If successful, mutates
2842 # this node into a NameNode and returns 1, otherwise
2843 # returns 0.
2844 module_scope = self.obj.analyse_as_module(env)
2845 if module_scope:
2846 entry = module_scope.lookup_here(self.attribute)
2847 if entry and (
2848 entry.is_cglobal or entry.is_cfunction
2849 or entry.is_type or entry.is_const):
2850 self.mutate_into_name_node(env, entry, target)
2851 return 1
2852 return 0
2854 def analyse_as_unbound_cmethod(self, env):
2855 # Try to interpret this as a reference to an unbound
2856 # C method of an extension type. If successful, mutates
2857 # this node into a NameNode and returns 1, otherwise
2858 # returns 0.
2859 type = self.obj.analyse_as_extension_type(env)
2860 if type:
2861 entry = type.scope.lookup_here(self.attribute)
2862 if entry and entry.is_cmethod:
2863 # Create a temporary entry describing the C method
2864 # as an ordinary function.
2865 ubcm_entry = Symtab.Entry(entry.name,
2866 "%s->%s" % (type.vtabptr_cname, entry.cname),
2867 entry.type)
2868 ubcm_entry.is_cfunction = 1
2869 ubcm_entry.func_cname = entry.func_cname
2870 ubcm_entry.is_unbound_cmethod = 1
2871 self.mutate_into_name_node(env, ubcm_entry, None)
2872 return 1
2873 return 0
2875 def analyse_as_type(self, env):
2876 module_scope = self.obj.analyse_as_module(env)
2877 if module_scope:
2878 return module_scope.lookup_type(self.attribute)
2879 return None
2881 def analyse_as_extension_type(self, env):
2882 # Try to interpret this as a reference to an extension type
2883 # in a cimported module. Returns the extension type, or None.
2884 module_scope = self.obj.analyse_as_module(env)
2885 if module_scope:
2886 entry = module_scope.lookup_here(self.attribute)
2887 if entry and entry.is_type and entry.type.is_extension_type:
2888 return entry.type
2889 return None
2891 def analyse_as_module(self, env):
2892 # Try to interpret this as a reference to a cimported module
2893 # in another cimported module. Returns the module scope, or None.
2894 module_scope = self.obj.analyse_as_module(env)
2895 if module_scope:
2896 entry = module_scope.lookup_here(self.attribute)
2897 if entry and entry.as_module:
2898 return entry.as_module
2899 return None
2901 def mutate_into_name_node(self, env, entry, target):
2902 # Mutate this node into a NameNode and complete the
2903 # analyse_types phase.
2904 self.__class__ = NameNode
2905 self.name = self.attribute
2906 self.entry = entry
2907 del self.obj
2908 del self.attribute
2909 if target:
2910 NameNode.analyse_target_types(self, env)
2911 else:
2912 NameNode.analyse_rvalue_entry(self, env)
2914 def analyse_as_ordinary_attribute(self, env, target):
2915 self.obj.analyse_types(env)
2916 self.analyse_attribute(env)
2917 if self.entry and self.entry.is_cmethod and not self.is_called:
2918 # error(self.pos, "C method can only be called")
2919 pass
2920 ## Reference to C array turns into pointer to first element.
2921 #while self.type.is_array:
2922 # self.type = self.type.element_ptr_type()
2923 if self.is_py_attr:
2924 if not target:
2925 self.is_temp = 1
2926 self.result_ctype = py_object_type
2928 def analyse_attribute(self, env, obj_type = None):
2929 # Look up attribute and set self.type and self.member.
2930 self.is_py_attr = 0
2931 self.member = self.attribute
2932 if obj_type is None:
2933 if self.obj.type.is_string:
2934 self.obj = self.obj.coerce_to_pyobject(env)
2935 obj_type = self.obj.type
2936 else:
2937 if obj_type.is_string:
2938 obj_type = py_object_type
2939 if obj_type.is_ptr or obj_type.is_array:
2940 obj_type = obj_type.base_type
2941 self.op = "->"
2942 elif obj_type.is_extension_type:
2943 self.op = "->"
2944 else:
2945 self.op = "."
2946 if obj_type.has_attributes:
2947 entry = None
2948 if obj_type.attributes_known():
2949 entry = obj_type.scope.lookup_here(self.attribute)
2950 if entry and entry.is_member:
2951 entry = None
2952 else:
2953 error(self.pos,
2954 "Cannot select attribute of incomplete type '%s'"
2955 % obj_type)
2956 self.type = PyrexTypes.error_type
2957 return
2958 self.entry = entry
2959 if entry:
2960 if obj_type.is_extension_type and entry.name == "__weakref__":
2961 error(self.pos, "Illegal use of special attribute __weakref__")
2962 # methods need the normal attribute lookup
2963 # because they do not have struct entries
2964 if entry.is_variable or entry.is_cmethod:
2965 self.type = entry.type
2966 self.member = entry.cname
2967 return
2968 else:
2969 # If it's not a variable or C method, it must be a Python
2970 # method of an extension type, so we treat it like a Python
2971 # attribute.
2972 pass
2973 # If we get here, the base object is not a struct/union/extension
2974 # type, or it is an extension type and the attribute is either not
2975 # declared or is declared as a Python method. Treat it as a Python
2976 # attribute reference.
2977 self.analyse_as_python_attribute(env, obj_type)
2979 def analyse_as_python_attribute(self, env, obj_type = None):
2980 if obj_type is None:
2981 obj_type = self.obj.type
2982 self.member = self.attribute
2983 if obj_type.is_pyobject:
2984 self.type = py_object_type
2985 self.is_py_attr = 1
2986 else:
2987 if not obj_type.is_error:
2988 error(self.pos,
2989 "Object of type '%s' has no attribute '%s'" %
2990 (obj_type, self.attribute))
2992 def nogil_check(self, env):
2993 if self.is_py_attr:
2994 self.gil_error()
2996 gil_message = "Accessing Python attribute"
2998 def is_simple(self):
2999 if self.obj:
3000 return self.result_in_temp() or self.obj.is_simple()
3001 else:
3002 return NameNode.is_simple(self)
3004 def is_lvalue(self):
3005 if self.obj:
3006 return 1
3007 else:
3008 return NameNode.is_lvalue(self)
3010 def is_ephemeral(self):
3011 if self.obj:
3012 return self.obj.is_ephemeral()
3013 else:
3014 return NameNode.is_ephemeral(self)
3016 def calculate_result_code(self):
3017 #print "AttributeNode.calculate_result_code:", self.member ###
3018 #print "...obj node =", self.obj, "code", self.obj.result() ###
3019 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
3020 obj = self.obj
3021 obj_code = obj.result_as(obj.type)
3022 #print "...obj_code =", obj_code ###
3023 if self.entry and self.entry.is_cmethod:
3024 if obj.type.is_extension_type:
3025 return "((struct %s *)%s%s%s)->%s" % (
3026 obj.type.vtabstruct_cname, obj_code, self.op,
3027 obj.type.vtabslot_cname, self.member)
3028 else:
3029 return self.member
3030 elif obj.type.is_complex:
3031 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
3032 else:
3033 return "%s%s%s" % (obj_code, self.op, self.member)
3035 def generate_result_code(self, code):
3036 interned_attr_cname = code.intern_identifier(self.attribute)
3037 if self.is_py_attr:
3038 code.putln(
3039 '%s = PyObject_GetAttr(%s, %s); %s' % (
3040 self.result(),
3041 self.obj.py_result(),
3042 interned_attr_cname,
3043 code.error_goto_if_null(self.result(), self.pos)))
3044 code.put_gotref(self.py_result())
3045 else:
3046 # result_code contains what is needed, but we may need to insert
3047 # a check and raise an exception
3048 if (self.obj.type.is_extension_type
3049 and self.needs_none_check
3050 and code.globalstate.directives['nonecheck']):
3051 self.put_nonecheck(code)
3053 def generate_assignment_code(self, rhs, code):
3054 interned_attr_cname = code.intern_identifier(self.attribute)
3055 self.obj.generate_evaluation_code(code)
3056 if self.is_py_attr:
3057 code.put_error_if_neg(self.pos,
3058 'PyObject_SetAttr(%s, %s, %s)' % (
3059 self.obj.py_result(),
3060 interned_attr_cname,
3061 rhs.py_result()))
3062 rhs.generate_disposal_code(code)
3063 rhs.free_temps(code)
3064 else:
3065 if (self.obj.type.is_extension_type
3066 and self.needs_none_check
3067 and code.globalstate.directives['nonecheck']):
3068 self.put_nonecheck(code)
3070 select_code = self.result()
3071 if self.type.is_pyobject:
3072 rhs.make_owned_reference(code)
3073 code.put_giveref(rhs.py_result())
3074 code.put_gotref(select_code)
3075 code.put_decref(select_code, self.ctype())
3076 code.putln(
3077 "%s = %s;" % (
3078 select_code,
3079 rhs.result_as(self.ctype())))
3080 #rhs.result()))
3081 rhs.generate_post_assignment_code(code)
3082 rhs.free_temps(code)
3083 self.obj.generate_disposal_code(code)
3084 self.obj.free_temps(code)
3086 def generate_deletion_code(self, code):
3087 interned_attr_cname = code.intern_identifier(self.attribute)
3088 self.obj.generate_evaluation_code(code)
3089 if self.is_py_attr:
3090 code.put_error_if_neg(self.pos,
3091 'PyObject_DelAttr(%s, %s)' % (
3092 self.obj.py_result(),
3093 interned_attr_cname))
3094 else:
3095 error(self.pos, "Cannot delete C attribute of extension type")
3096 self.obj.generate_disposal_code(code)
3097 self.obj.free_temps(code)
3099 def annotate(self, code):
3100 if self.is_py_attr:
3101 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3102 else:
3103 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3105 def put_nonecheck(self, code):
3106 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3107 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3108 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute)
3109 code.putln(code.error_goto(self.pos))
3110 code.putln("}")
3113 #-------------------------------------------------------------------
3114 #
3115 # Constructor nodes
3116 #
3117 #-------------------------------------------------------------------
3119 class StarredTargetNode(ExprNode):
3120 # A starred expression like "*a"
3121 #
3122 # This is only allowed in sequence assignment targets such as
3123 #
3124 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
3125 #
3126 # and will be removed during type analysis (or generate an error
3127 # if it's found at unexpected places).
3128 #
3129 # target ExprNode
3131 subexprs = ['target']
3132 is_starred = 1
3133 type = py_object_type
3134 is_temp = 1
3136 def __init__(self, pos, target):
3137 self.pos = pos
3138 self.target = target
3140 def analyse_declarations(self, env):
3141 error(self.pos, "can use starred expression only as assignment target")
3142 self.target.analyse_declarations(env)
3144 def analyse_types(self, env):
3145 error(self.pos, "can use starred expression only as assignment target")
3146 self.target.analyse_types(env)
3147 self.type = self.target.type
3149 def analyse_target_declaration(self, env):
3150 self.target.analyse_target_declaration(env)
3152 def analyse_target_types(self, env):
3153 self.target.analyse_target_types(env)
3154 self.type = self.target.type
3156 def calculate_result_code(self):
3157 return ""
3159 def generate_result_code(self, code):
3160 pass
3163 class SequenceNode(ExprNode):
3164 # Base class for list and tuple constructor nodes.
3165 # Contains common code for performing sequence unpacking.
3166 #
3167 # args [ExprNode]
3168 # iterator ExprNode
3169 # unpacked_items [ExprNode] or None
3170 # coerced_unpacked_items [ExprNode] or None
3172 subexprs = ['args']
3174 is_sequence_constructor = 1
3175 unpacked_items = None
3177 def compile_time_value_list(self, denv):
3178 return [arg.compile_time_value(denv) for arg in self.args]
3180 def replace_starred_target_node(self):
3181 # replace a starred node in the targets by the contained expression
3182 self.starred_assignment = False
3183 args = []
3184 for arg in self.args:
3185 if arg.is_starred:
3186 if self.starred_assignment:
3187 error(arg.pos, "more than 1 starred expression in assignment")
3188 self.starred_assignment = True
3189 arg = arg.target
3190 arg.is_starred = True
3191 args.append(arg)
3192 self.args = args
3194 def analyse_target_declaration(self, env):
3195 self.replace_starred_target_node()
3196 for arg in self.args:
3197 arg.analyse_target_declaration(env)
3199 def analyse_types(self, env, skip_children=False):
3200 for i in range(len(self.args)):
3201 arg = self.args[i]
3202 if not skip_children: arg.analyse_types(env)
3203 self.args[i] = arg.coerce_to_pyobject(env)
3204 self.type = py_object_type
3205 self.is_temp = 1
3207 def analyse_target_types(self, env):
3208 self.iterator = PyTempNode(self.pos, env)
3209 self.unpacked_items = []
3210 self.coerced_unpacked_items = []
3211 for arg in self.args:
3212 arg.analyse_target_types(env)
3213 if arg.is_starred:
3214 if not arg.type.assignable_from(Builtin.list_type):
3215 error(arg.pos,
3216 "starred target must have Python object (list) type")
3217 if arg.type is py_object_type:
3218 arg.type = Builtin.list_type
3219 unpacked_item = PyTempNode(self.pos, env)
3220 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3221 self.unpacked_items.append(unpacked_item)
3222 self.coerced_unpacked_items.append(coerced_unpacked_item)
3223 self.type = py_object_type
3225 def generate_result_code(self, code):
3226 self.generate_operation_code(code)
3228 def generate_assignment_code(self, rhs, code):
3229 if self.starred_assignment:
3230 self.generate_starred_assignment_code(rhs, code)
3231 else:
3232 self.generate_parallel_assignment_code(rhs, code)
3234 for item in self.unpacked_items:
3235 item.release(code)
3236 rhs.free_temps(code)
3238 def generate_parallel_assignment_code(self, rhs, code):
3239 # Need to work around the fact that generate_evaluation_code
3240 # allocates the temps in a rather hacky way -- the assignment
3241 # is evaluated twice, within each if-block.
3243 code.globalstate.use_utility_code(unpacking_utility_code)
3245 if rhs.type is tuple_type:
3246 tuple_check = "likely(%s != Py_None)"
3247 else:
3248 tuple_check = "PyTuple_CheckExact(%s)"
3249 code.putln(
3250 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3251 tuple_check % rhs.py_result(),
3252 rhs.py_result(),
3253 len(self.args)))
3254 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3255 for item in self.unpacked_items:
3256 item.allocate(code)
3257 for i in range(len(self.args)):
3258 item = self.unpacked_items[i]
3259 code.put(
3260 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3261 item.result(),
3262 i))
3263 code.put_incref(item.result(), item.ctype())
3264 value_node = self.coerced_unpacked_items[i]
3265 value_node.generate_evaluation_code(code)
3266 rhs.generate_disposal_code(code)
3268 for i in range(len(self.args)):
3269 self.args[i].generate_assignment_code(
3270 self.coerced_unpacked_items[i], code)
3272 code.putln("} else {")
3274 if rhs.type is tuple_type:
3275 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3276 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3277 rhs.py_result(), len(self.args)))
3278 code.putln(code.error_goto(self.pos))
3279 else:
3280 self.iterator.allocate(code)
3281 code.putln(
3282 "%s = PyObject_GetIter(%s); %s" % (
3283 self.iterator.result(),
3284 rhs.py_result(),
3285 code.error_goto_if_null(self.iterator.result(), self.pos)))
3286 code.put_gotref(self.iterator.py_result())
3287 rhs.generate_disposal_code(code)
3288 for i in range(len(self.args)):
3289 item = self.unpacked_items[i]
3290 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3291 self.iterator.py_result(), i)
3292 code.putln(
3293 "%s = %s; %s" % (
3294 item.result(),
3295 typecast(item.ctype(), py_object_type, unpack_code),
3296 code.error_goto_if_null(item.result(), self.pos)))
3297 code.put_gotref(item.py_result())
3298 value_node = self.coerced_unpacked_items[i]
3299 value_node.generate_evaluation_code(code)
3300 code.put_error_if_neg(self.pos,
3301 "__Pyx_EndUnpack(%s)" % (
3302 self.iterator.py_result()))
3303 if debug_disposal_code:
3304 print("UnpackNode.generate_assignment_code:")
3305 print("...generating disposal code for %s" % self.iterator)
3306 self.iterator.generate_disposal_code(code)
3307 self.iterator.free_temps(code)
3308 self.iterator.release(code)
3310 for i in range(len(self.args)):
3311 self.args[i].generate_assignment_code(
3312 self.coerced_unpacked_items[i], code)
3314 code.putln("}")
3316 def generate_starred_assignment_code(self, rhs, code):
3317 code.globalstate.use_utility_code(unpacking_utility_code)
3319 for i, arg in enumerate(self.args):
3320 if arg.is_starred:
3321 starred_target = self.unpacked_items[i]
3322 fixed_args_left = self.args[:i]
3323 fixed_args_right = self.args[i+1:]
3324 break
3326 self.iterator.allocate(code)
3327 code.putln(
3328 "%s = PyObject_GetIter(%s); %s" % (
3329 self.iterator.result(),
3330 rhs.py_result(),
3331 code.error_goto_if_null(self.iterator.result(), self.pos)))
3332 code.put_gotref(self.iterator.py_result())
3333 rhs.generate_disposal_code(code)
3335 for item in self.unpacked_items:
3336 item.allocate(code)
3337 for i in range(len(fixed_args_left)):
3338 item = self.unpacked_items[i]
3339 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3340 self.iterator.py_result(), i)
3341 code.putln(
3342 "%s = %s; %s" % (
3343 item.result(),
3344 typecast(item.ctype(), py_object_type, unpack_code),
3345 code.error_goto_if_null(item.result(), self.pos)))
3346 code.put_gotref(item.py_result())
3347 value_node = self.coerced_unpacked_items[i]
3348 value_node.generate_evaluation_code(code)
3350 target_list = starred_target.result()
3351 code.putln("%s = PySequence_List(%s); %s" % (
3352 target_list, self.iterator.py_result(),
3353 code.error_goto_if_null(target_list, self.pos)))
3354 code.put_gotref(target_list)
3355 if fixed_args_right:
3356 code.globalstate.use_utility_code(raise_need_more_values_to_unpack)
3357 unpacked_right_args = self.unpacked_items[-len(fixed_args_right):]
3358 code.putln("if (unlikely(PyList_GET_SIZE(%s) < %d)) {" % (
3359 (target_list, len(unpacked_right_args))))
3360 code.put("__Pyx_RaiseNeedMoreValuesError(%d+PyList_GET_SIZE(%s)); %s" % (
3361 len(fixed_args_left), target_list,
3362 code.error_goto(self.pos)))
3363 code.putln('}')
3364 for i, (arg, coerced_arg) in enumerate(zip(unpacked_right_args[::-1],
3365 self.coerced_unpacked_items[::-1])):
3366 code.putln(
3367 "%s = PyList_GET_ITEM(%s, PyList_GET_SIZE(%s)-1); " % (
3368 arg.py_result(),
3369 target_list, target_list))
3370 # resize the list the hard way
3371 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list)
3372 code.put_gotref(arg.py_result())
3373 coerced_arg.generate_evaluation_code(code)
3375 self.iterator.generate_disposal_code(code)
3376 self.iterator.free_temps(code)
3377 self.iterator.release(code)
3379 for i in range(len(self.args)):
3380 self.args[i].generate_assignment_code(
3381 self.coerced_unpacked_items[i], code)
3383 def annotate(self, code):
3384 for arg in self.args:
3385 arg.annotate(code)
3386 if self.unpacked_items:
3387 for arg in self.unpacked_items:
3388 arg.annotate(code)
3389 for arg in self.coerced_unpacked_items:
3390 arg.annotate(code)
3393 class TupleNode(SequenceNode):
3394 # Tuple constructor.
3396 type = tuple_type
3398 gil_message = "Constructing Python tuple"
3400 def analyse_types(self, env, skip_children=False):
3401 if len(self.args) == 0:
3402 self.is_temp = 0
3403 self.is_literal = 1
3404 else:
3405 SequenceNode.analyse_types(self, env, skip_children)
3407 def calculate_result_code(self):
3408 if len(self.args) > 0:
3409 error(self.pos, "Positive length tuples must be constructed.")
3410 else:
3411 return Naming.empty_tuple
3413 def calculate_constant_result(self):
3414 self.constant_result = tuple([
3415 arg.constant_result for arg in self.args])
3417 def compile_time_value(self, denv):
3418 values = self.compile_time_value_list(denv)
3419 try:
3420 return tuple(values)
3421 except Exception, e:
3422 self.compile_time_value_error(e)
3424 def generate_operation_code(self, code):
3425 if len(self.args) == 0:
3426 # result_code is Naming.empty_tuple
3427 return
3428 code.putln(
3429 "%s = PyTuple_New(%s); %s" % (
3430 self.result(),
3431 len(self.args),
3432 code.error_goto_if_null(self.result(), self.pos)))
3433 code.put_gotref(self.py_result())
3434 for i in range(len(self.args)):
3435 arg = self.args[i]
3436 if not arg.result_in_temp():
3437 code.put_incref(arg.result(), arg.ctype())
3438 code.putln(
3439 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3440 self.result(),
3441 i,
3442 arg.py_result()))
3443 code.put_giveref(arg.py_result())
3445 def generate_subexpr_disposal_code(self, code):
3446 # We call generate_post_assignment_code here instead
3447 # of generate_disposal_code, because values were stored
3448 # in the tuple using a reference-stealing operation.
3449 for arg in self.args:
3450 arg.generate_post_assignment_code(code)
3451 # Should NOT call free_temps -- this is invoked by the default
3452 # generate_evaluation_code which will do that.
3455 class ListNode(SequenceNode):
3456 # List constructor.
3458 # obj_conversion_errors [PyrexError] used internally
3459 # orignial_args [ExprNode] used internally
3461 obj_conversion_errors = []
3463 gil_message = "Constructing Python list"
3465 def type_dependencies(self, env):
3466 return ()
3468 def infer_type(self, env):
3469 # TOOD: Infer non-object list arrays.
3470 return list_type
3472 def analyse_expressions(self, env):
3473 SequenceNode.analyse_expressions(self, env)
3474 self.coerce_to_pyobject(env)
3476 def analyse_types(self, env):
3477 hold_errors()
3478 self.original_args = list(self.args)
3479 SequenceNode.analyse_types(self, env)
3480 self.type = list_type
3481 self.obj_conversion_errors = held_errors()
3482 release_errors(ignore=True)
3484 def coerce_to(self, dst_type, env):
3485 if dst_type.is_pyobject:
3486 for err in self.obj_conversion_errors:
3487 report_error(err)
3488 self.obj_conversion_errors = []
3489 if not self.type.subtype_of(dst_type):
3490 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3491 elif dst_type.is_ptr:
3492 base_type = dst_type.base_type
3493 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3494 for i in range(len(self.original_args)):
3495 arg = self.args[i]
3496 if isinstance(arg, CoerceToPyTypeNode):
3497 arg = arg.arg
3498 self.args[i] = arg.coerce_to(base_type, env)
3499 elif dst_type.is_struct:
3500 if len(self.args) > len(dst_type.scope.var_entries):
3501 error(self.pos, "Too may members for '%s'" % dst_type)
3502 else:
3503 if len(self.args) < len(dst_type.scope.var_entries):
3504 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3505 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3506 if isinstance(arg, CoerceToPyTypeNode):
3507 arg = arg.arg
3508 self.args[i] = arg.coerce_to(member.type, env)
3509 self.type = dst_type
3510 else:
3511 self.type = error_type
3512 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3513 return self
3515 def release_temp(self, env):
3516 if self.type.is_array:
3517 # To be valid C++, we must allocate the memory on the stack
3518 # manually and be sure not to reuse it for something else.
3519 pass
3520 else:
3521 SequenceNode.release_temp(self, env)
3523 def calculate_constant_result(self):
3524 self.constant_result = [
3525 arg.constant_result for arg in self.args]
3527 def compile_time_value(self, denv):
3528 return self.compile_time_value_list(denv)
3530 def generate_operation_code(self, code):
3531 if self.type.is_pyobject:
3532 for err in self.obj_conversion_errors:
3533 report_error(err)
3534 code.putln("%s = PyList_New(%s); %s" %
3535 (self.result(),
3536 len(self.args),
3537 code.error_goto_if_null(self.result(), self.pos)))
3538 code.put_gotref(self.py_result())
3539 for i in range(len(self.args)):
3540 arg = self.args[i]
3541 #if not arg.is_temp:
3542 if not arg.result_in_temp():
3543 code.put_incref(arg.result(), arg.ctype())
3544 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3545 (self.result(),
3546 i,
3547 arg.py_result()))
3548 code.put_giveref(arg.py_result())
3549 elif self.type.is_array:
3550 for i, arg in enumerate(self.args):
3551 code.putln("%s[%s] = %s;" % (
3552 self.result(),
3553 i,
3554 arg.result()))
3555 elif self.type.is_struct:
3556 for arg, member in zip(self.args, self.type.scope.var_entries):
3557 code.putln("%s.%s = %s;" % (
3558 self.result(),
3559 member.cname,
3560 arg.result()))
3561 else:
3562 raise InternalError("List type never specified")
3564 def generate_subexpr_disposal_code(self, code):
3565 # We call generate_post_assignment_code here instead
3566 # of generate_disposal_code, because values were stored
3567 # in the list using a reference-stealing operation.
3568 for arg in self.args:
3569 arg.generate_post_assignment_code(code)
3570 # Should NOT call free_temps -- this is invoked by the default
3571 # generate_evaluation_code which will do that.
3574 class ComprehensionNode(ExprNode):
3575 subexprs = ["target"]
3576 child_attrs = ["loop", "append"]
3578 def infer_type(self, env):
3579 return self.target.infer_type(env)
3581 def analyse_types(self, env):
3582 self.target.analyse_expressions(env)
3583 self.type = self.target.type
3584 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3585 # We are analysing declarations to late.
3586 self.loop.target.analyse_target_declaration(env)
3587 env.infer_types()
3588 self.loop.analyse_declarations(env)
3589 self.loop.analyse_expressions(env)
3591 def calculate_result_code(self):
3592 return self.target.result()
3594 def generate_result_code(self, code):
3595 self.generate_operation_code(code)
3597 def generate_operation_code(self, code):
3598 self.loop.generate_execution_code(code)
3600 def annotate(self, code):
3601 self.loop.annotate(code)
3604 class ComprehensionAppendNode(ExprNode):
3605 # Need to be careful to avoid infinite recursion:
3606 # target must not be in child_attrs/subexprs
3607 subexprs = ['expr']
3609 type = PyrexTypes.c_int_type
3611 def analyse_types(self, env):
3612 self.expr.analyse_types(env)
3613 if not self.expr.type.is_pyobject:
3614 self.expr = self.expr.coerce_to_pyobject(env)
3615 self.is_temp = 1
3617 def generate_result_code(self, code):
3618 if self.target.type is list_type:
3619 function = "PyList_Append"
3620 elif self.target.type is set_type:
3621 function = "PySet_Add"
3622 else:
3623 raise InternalError(
3624 "Invalid type for comprehension node: %s" % self.target.type)
3626 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3627 (self.result(),
3628 function,
3629 self.target.result(),
3630 self.expr.result(),
3631 code.error_goto_if(self.result(), self.pos)))
3633 class DictComprehensionAppendNode(ComprehensionAppendNode):
3634 subexprs = ['key_expr', 'value_expr']
3636 def analyse_types(self, env):
3637 self.key_expr.analyse_types(env)
3638 if not self.key_expr.type.is_pyobject:
3639 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3640 self.value_expr.analyse_types(env)
3641 if not self.value_expr.type.is_pyobject:
3642 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3643 self.is_temp = 1
3645 def generate_result_code(self, code):
3646 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3647 (self.result(),
3648 self.target.result(),
3649 self.key_expr.result(),
3650 self.value_expr.result(),
3651 code.error_goto_if(self.result(), self.pos)))
3654 class SetNode(ExprNode):
3655 # Set constructor.
3657 type = set_type
3659 subexprs = ['args']
3661 gil_message = "Constructing Python set"
3663 def analyse_types(self, env):
3664 for i in range(len(self.args)):
3665 arg = self.args[i]
3666 arg.analyse_types(env)
3667 self.args[i] = arg.coerce_to_pyobject(env)
3668 self.type = set_type
3669 self.is_temp = 1
3671 def calculate_constant_result(self):
3672 self.constant_result = set([
3673 arg.constant_result for arg in self.args])
3675 def compile_time_value(self, denv):
3676 values = [arg.compile_time_value(denv) for arg in self.args]
3677 try:
3678 return set(values)
3679 except Exception, e:
3680 self.compile_time_value_error(e)
3682 def generate_evaluation_code(self, code):
3683 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3684 self.allocate_temp_result(code)
3685 code.putln(
3686 "%s = PySet_New(0); %s" % (
3687 self.result(),
3688 code.error_goto_if_null(self.result(), self.pos)))
3689 code.put_gotref(self.py_result())
3690 for arg in self.args:
3691 arg.generate_evaluation_code(code)
3692 code.putln(
3693 code.error_goto_if_neg(
3694 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3695 self.pos))
3696 arg.generate_disposal_code(code)
3697 arg.free_temps(code)
3700 class DictNode(ExprNode):
3701 # Dictionary constructor.
3702 #
3703 # key_value_pairs [DictItemNode]
3704 #
3705 # obj_conversion_errors [PyrexError] used internally
3707 subexprs = ['key_value_pairs']
3708 is_temp = 1
3709 type = dict_type
3711 type = dict_type
3712 obj_conversion_errors = []
3714 def calculate_constant_result(self):
3715 self.constant_result = dict([
3716 item.constant_result for item in self.key_value_pairs])
3718 def compile_time_value(self, denv):
3719 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3720 for item in self.key_value_pairs]
3721 try:
3722 return dict(pairs)
3723 except Exception, e:
3724 self.compile_time_value_error(e)
3726 def type_dependencies(self, env):
3727 return ()
3729 def infer_type(self, env):
3730 # TOOD: Infer struct constructors.
3731 return dict_type
3733 def analyse_types(self, env):
3734 hold_errors()
3735 for item in self.key_value_pairs:
3736 item.analyse_types(env)
3737 self.obj_conversion_errors = held_errors()
3738 release_errors(ignore=True)
3740 def coerce_to(self, dst_type, env):
3741 if dst_type.is_pyobject:
3742 self.release_errors()
3743 if not self.type.subtype_of(dst_type):
3744 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3745 elif dst_type.is_struct_or_union:
3746 self.type = dst_type
3747 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3748 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3749 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3750 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3751 for item in self.key_value_pairs:
3752 if isinstance(item.key, CoerceToPyTypeNode):
3753 item.key = item.key.arg
3754 if not isinstance(item.key, (UnicodeNode, StringNode, BytesNode)):
3755 error(item.key.pos, "Invalid struct field identifier")
3756 item.key = StringNode(item.key.pos, value="<error>")
3757 else:
3758 key = str(item.key.value) # converts string literals to unicode in Py3
3759 member = dst_type.scope.lookup_here(key)
3760 if not member:
3761 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key))
3762 else:
3763 value = item.value
3764 if isinstance(value, CoerceToPyTypeNode):
3765 value = value.arg
3766 item.value = value.coerce_to(member.type, env)
3767 else:
3768 self.type = error_type
3769 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3770 return self
3772 def release_errors(self):
3773 for err in self.obj_conversion_errors:
3774 report_error(err)
3775 self.obj_conversion_errors = []
3777 gil_message = "Constructing Python dict"
3779 def generate_evaluation_code(self, code):
3780 # Custom method used here because key-value
3781 # pairs are evaluated and used one at a time.
3782 code.mark_pos(self.pos)
3783 self.allocate_temp_result(code)
3784 if self.type.is_pyobject:
3785 self.release_errors()
3786 code.putln(
3787 "%s = PyDict_New(); %s" % (
3788 self.result(),
3789 code.error_goto_if_null(self.result(), self.pos)))
3790 code.put_gotref(self.py_result())
3791 for item in self.key_value_pairs:
3792 item.generate_evaluation_code(code)
3793 if self.type.is_pyobject:
3794 code.put_error_if_neg(self.pos,
3795 "PyDict_SetItem(%s, %s, %s)" % (
3796 self.result(),
3797 item.key.py_result(),
3798 item.value.py_result()))
3799 else:
3800 code.putln("%s.%s = %s;" % (
3801 self.result(),
3802 item.key.value,
3803 item.value.result()))
3804 item.generate_disposal_code(code)
3805 item.free_temps(code)
3807 def annotate(self, code):
3808 for item in self.key_value_pairs:
3809 item.annotate(code)
3811 class DictItemNode(ExprNode):
3812 # Represents a single item in a DictNode
3813 #
3814 # key ExprNode
3815 # value ExprNode
3816 subexprs = ['key', 'value']
3818 nogil_check = None # Parent DictNode takes care of it
3820 def calculate_constant_result(self):
3821 self.constant_result = (
3822 self.key.constant_result, self.value.constant_result)
3824 def analyse_types(self, env):
3825 self.key.analyse_types(env)
3826 self.value.analyse_types(env)
3827 self.key = self.key.coerce_to_pyobject(env)
3828 self.value = self.value.coerce_to_pyobject(env)
3830 def generate_evaluation_code(self, code):
3831 self.key.generate_evaluation_code(code)
3832 self.value.generate_evaluation_code(code)
3834 def generate_disposal_code(self, code):
3835 self.key.generate_disposal_code(code)
3836 self.value.generate_disposal_code(code)
3838 def free_temps(self, code):
3839 self.key.free_temps(code)
3840 self.value.free_temps(code)
3842 def __iter__(self):
3843 return iter([self.key, self.value])
3846 class ClassNode(ExprNode):
3847 # Helper class used in the implementation of Python
3848 # class definitions. Constructs a class object given
3849 # a name, tuple of bases and class dictionary.
3850 #
3851 # name EncodedString Name of the class
3852 # bases ExprNode Base class tuple
3853 # dict ExprNode Class dict (not owned by this node)
3854 # doc ExprNode or None Doc string
3855 # module_name string Name of defining module
3857 subexprs = ['bases', 'doc']
3859 def analyse_types(self, env):
3860 self.bases.analyse_types(env)
3861 if self.doc:
3862 self.doc.analyse_types(env)
3863 self.doc = self.doc.coerce_to_pyobject(env)
3864 self.module_name = env.global_scope().qualified_name
3865 self.type = py_object_type
3866 self.is_temp = 1
3867 env.use_utility_code(create_class_utility_code);
3869 gil_message = "Constructing Python class"
3871 def generate_result_code(self, code):
3872 cname = code.intern_identifier(self.name)
3873 if self.doc:
3874 code.put_error_if_neg(self.pos,
3875 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3876 self.dict.py_result(),
3877 self.doc.py_result()))
3878 code.putln(
3879 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3880 self.result(),
3881 self.bases.py_result(),
3882 self.dict.py_result(),
3883 cname,
3884 self.module_name,
3885 code.error_goto_if_null(self.result(), self.pos)))
3886 code.put_gotref(self.py_result())
3889 class UnboundMethodNode(ExprNode):
3890 # Helper class used in the implementation of Python
3891 # class definitions. Constructs an unbound method
3892 # object from a class and a function.
3893 #
3894 # function ExprNode Function object
3896 type = py_object_type
3897 is_temp = 1
3899 subexprs = ['function']
3901 def analyse_types(self, env):
3902 self.function.analyse_types(env)
3904 gil_message = "Constructing an unbound method"
3906 def generate_result_code(self, code):
3907 class_cname = code.pyclass_stack[-1].classobj.result()
3908 code.putln(
3909 "%s = PyMethod_New(%s, 0, %s); %s" % (
3910 self.result(),
3911 self.function.py_result(),
3912 class_cname,
3913 code.error_goto_if_null(self.result(), self.pos)))
3914 code.put_gotref(self.py_result())
3916 class PyCFunctionNode(AtomicExprNode):
3917 # Helper class used in the implementation of Python
3918 # class definitions. Constructs a PyCFunction object
3919 # from a PyMethodDef struct.
3920 #
3921 # pymethdef_cname string PyMethodDef structure
3923 type = py_object_type
3924 is_temp = 1
3926 def analyse_types(self, env):
3927 pass
3929 gil_message = "Constructing Python function"
3931 def generate_result_code(self, code):
3932 code.putln(
3933 "%s = PyCFunction_New(&%s, 0); %s" % (
3934 self.result(),
3935 self.pymethdef_cname,
3936 code.error_goto_if_null(self.result(), self.pos)))
3937 code.put_gotref(self.py_result())
3939 #-------------------------------------------------------------------
3940 #
3941 # Unary operator nodes
3942 #
3943 #-------------------------------------------------------------------
3945 compile_time_unary_operators = {
3946 'not': operator.not_,
3947 '~': operator.inv,
3948 '-': operator.neg,
3949 '+': operator.pos,
3950 }
3952 class UnopNode(ExprNode):
3953 # operator string
3954 # operand ExprNode
3955 #
3956 # Processing during analyse_expressions phase:
3957 #
3958 # analyse_c_operation
3959 # Called when the operand is not a pyobject.
3960 # - Check operand type and coerce if needed.
3961 # - Determine result type and result code fragment.
3962 # - Allocate temporary for result if needed.
3964 subexprs = ['operand']
3965 infix = True
3967 def calculate_constant_result(self):
3968 func = compile_time_unary_operators[self.operator]
3969 self.constant_result = func(self.operand.constant_result)
3971 def compile_time_value(self, denv):
3972 func = compile_time_unary_operators.get(self.operator)
3973 if not func:
3974 error(self.pos,
3975 "Unary '%s' not supported in compile-time expression"
3976 % self.operator)
3977 operand = self.operand.compile_time_value(denv)
3978 try:
3979 return func(operand)
3980 except Exception, e:
3981 self.compile_time_value_error(e)
3983 def infer_type(self, env):
3984 return self.operand.infer_type(env)
3986 def analyse_types(self, env):
3987 self.operand.analyse_types(env)
3988 if self.is_py_operation():
3989 self.coerce_operand_to_pyobject(env)
3990 self.type = py_object_type
3991 self.is_temp = 1
3992 else:
3993 self.analyse_c_operation(env)
3995 def check_const(self):
3996 self.operand.check_const()
3998 def is_py_operation(self):
3999 return self.operand.type.is_pyobject
4001 def nogil_check(self, env):
4002 if self.is_py_operation():
4003 self.gil_error()
4005 def coerce_operand_to_pyobject(self, env):
4006 self.operand = self.operand.coerce_to_pyobject(env)
4008 def generate_result_code(self, code):
4009 if self.operand.type.is_pyobject:
4010 self.generate_py_operation_code(code)
4012 def generate_py_operation_code(self, code):
4013 function = self.py_operation_function()
4014 code.putln(
4015 "%s = %s(%s); %s" % (
4016 self.result(),
4017 function,
4018 self.operand.py_result(),
4019 code.error_goto_if_null(self.result(), self.pos)))
4020 code.put_gotref(self.py_result())
4022 def type_error(self):
4023 if not self.operand.type.is_error:
4024 error(self.pos, "Invalid operand type for '%s' (%s)" %
4025 (self.operator, self.operand.type))
4026 self.type = PyrexTypes.error_type
4029 class NotNode(ExprNode):
4030 # 'not' operator
4031 #
4032 # operand ExprNode
4034 type = PyrexTypes.c_bint_type
4036 subexprs = ['operand']
4038 def calculate_constant_result(self):
4039 self.constant_result = not self.operand.constant_result
4041 def compile_time_value(self, denv):
4042 operand = self.operand.compile_time_value(denv)
4043 try:
4044 return not operand
4045 except Exception, e:
4046 self.compile_time_value_error(e)
4048 def infer_type(self, env):
4049 return PyrexTypes.c_bint_type
4051 def analyse_types(self, env):
4052 self.operand.analyse_types(env)
4053 self.operand = self.operand.coerce_to_boolean(env)
4055 def calculate_result_code(self):
4056 return "(!%s)" % self.operand.result()
4058 def generate_result_code(self, code):
4059 pass
4062 class UnaryPlusNode(UnopNode):
4063 # unary '+' operator
4065 operator = '+'
4067 def analyse_c_operation(self, env):
4068 self.type = self.operand.type
4070 def py_operation_function(self):
4071 return "PyNumber_Positive"
4073 def calculate_result_code(self):
4074 return self.operand.result()
4077 class UnaryMinusNode(UnopNode):
4078 # unary '-' operator
4080 operator = '-'
4082 def analyse_c_operation(self, env):
4083 if self.operand.type.is_numeric:
4084 self.type = self.operand.type
4085 else:
4086 self.type_error()
4087 if self.type.is_complex:
4088 self.infix = False
4090 def py_operation_function(self):
4091 return "PyNumber_Negative"
4093 def calculate_result_code(self):
4094 if self.infix:
4095 return "(-%s)" % self.operand.result()
4096 else:
4097 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
4099 class TildeNode(UnopNode):
4100 # unary '~' operator
4102 def analyse_c_operation(self, env):
4103 if self.operand.type.is_int:
4104 self.type = self.operand.type
4105 else:
4106 self.type_error()
4108 def py_operation_function(self):
4109 return "PyNumber_Invert"
4111 def calculate_result_code(self):
4112 return "(~%s)" % self.operand.result()
4115 class AmpersandNode(ExprNode):
4116 # The C address-of operator.
4117 #
4118 # operand ExprNode
4120 subexprs = ['operand']
4122 def infer_type(self, env):
4123 return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
4125 def analyse_types(self, env):
4126 self.operand.analyse_types(env)
4127 argtype = self.operand.type
4128 if not (argtype.is_cfunction or self.operand.is_lvalue()):
4129 self.error("Taking address of non-lvalue")
4130 return
4131 if argtype.is_pyobject:
4132 self.error("Cannot take address of Python variable")
4133 return
4134 self.type = PyrexTypes.c_ptr_type(argtype)
4136 def check_const(self):
4137 self.operand.check_const_addr()
4139 def error(self, mess):
4140 error(self.pos, mess)
4141 self.type = PyrexTypes.error_type
4142 self.result_code = "<error>"
4144 def calculate_result_code(self):
4145 return "(&%s)" % self.operand.result()
4147 def generate_result_code(self, code):
4148 pass
4151 unop_node_classes = {
4152 "+": UnaryPlusNode,
4153 "-": UnaryMinusNode,
4154 "~": TildeNode,
4155 }
4157 def unop_node(pos, operator, operand):
4158 # Construct unnop node of appropriate class for
4159 # given operator.
4160 if isinstance(operand, IntNode) and operator == '-':
4161 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
4162 elif isinstance(operand, UnopNode) and operand.operator == operator:
4163 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
4164 return unop_node_classes[operator](pos,
4165 operator = operator,
4166 operand = operand)
4169 class TypecastNode(ExprNode):
4170 # C type cast
4171 #
4172 # operand ExprNode
4173 # base_type CBaseTypeNode
4174 # declarator CDeclaratorNode
4175 #
4176 # If used from a transform, one can if wanted specify the attribute
4177 # "type" directly and leave base_type and declarator to None
4179 subexprs = ['operand']
4180 base_type = declarator = type = None
4182 def type_dependencies(self, env):
4183 return ()
4185 def infer_type(self, env):
4186 if self.type is None:
4187 base_type = self.base_type.analyse(env)
4188 _, self.type = self.declarator.analyse(base_type, env)
4189 return self.type
4191 def analyse_types(self, env):
4192 if self.type is None:
4193 base_type = self.base_type.analyse(env)
4194 _, self.type = self.declarator.analyse(base_type, env)
4195 if self.type.is_cfunction:
4196 error(self.pos,
4197 "Cannot cast to a function type")
4198 self.type = PyrexTypes.error_type
4199 self.operand.analyse_types(env)
4200 to_py = self.type.is_pyobject
4201 from_py = self.operand.type.is_pyobject
4202 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
4203 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
4204 if to_py and not from_py:
4205 if self.operand.type.create_to_py_utility_code(env):
4206 self.result_ctype = py_object_type
4207 self.operand = self.operand.coerce_to_pyobject(env)
4208 else:
4209 if not (self.operand.type.is_ptr and self.operand.type.base_type.is_void):
4210 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
4211 self.operand = self.operand.coerce_to_simple(env)
4212 elif from_py and not to_py:
4213 if self.type.create_from_py_utility_code(env):
4214 self.operand = self.operand.coerce_to(self.type, env)
4215 elif self.type.is_ptr and not (self.type.base_type.is_void or self.type.base_type.is_struct):
4216 error(self.pos, "Python objects cannot be casted to pointers of primitive types")
4217 else:
4218 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
4219 elif from_py and to_py:
4220 if self.typecheck and self.type.is_extension_type:
4221 self.operand = PyTypeTestNode(self.operand, self.type, env)
4223 def nogil_check(self, env):
4224 if self.type and self.type.is_pyobject and self.is_temp:
4225 self.gil_error()
4227 def check_const(self):
4228 self.operand.check_const()
4230 def calculate_constant_result(self):
4231 # we usually do not know the result of a type cast at code
4232 # generation time
4233 pass
4235 def calculate_result_code(self):
4236 opnd = self.operand
4237 return self.type.cast_code(opnd.result())
4239 def result_as(self, type):
4240 if self.type.is_pyobject and not self.is_temp:
4241 # Optimise away some unnecessary casting
4242 return self.operand.result_as(type)
4243 else:
4244 return ExprNode.result_as(self, type)
4246 def generate_result_code(self, code):
4247 if self.is_temp:
4248 code.putln(
4249 "%s = (PyObject *)%s;" % (
4250 self.result(),
4251 self.operand.result()))
4252 code.put_incref(self.result(), self.ctype())
4255 class SizeofNode(ExprNode):
4256 # Abstract base class for sizeof(x) expression nodes.
4258 type = PyrexTypes.c_size_t_type
4260 def check_const(self):
4261 pass
4263 def generate_result_code(self, code):
4264 pass
4267 class SizeofTypeNode(SizeofNode):
4268 # C sizeof function applied to a type
4269 #
4270 # base_type CBaseTypeNode
4271 # declarator CDeclaratorNode
4273 subexprs = []
4274 arg_type = None
4276 def analyse_types(self, env):
4277 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4278 # this could be better handled by more uniformly treating types as runtime-available objects
4279 if 0 and self.base_type.module_path:
4280 path = self.base_type.module_path
4281 obj = env.lookup(path[0])
4282 if obj.as_module is None:
4283 operand = NameNode(pos=self.pos, name=path[0])
4284 for attr in path[1:]:
4285 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4286 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4287 self.operand = operand
4288 self.__class__ = SizeofVarNode
4289 self.analyse_types(env)
4290 return
4291 if self.arg_type is None:
4292 base_type = self.base_type.analyse(env)
4293 _, arg_type = self.declarator.analyse(base_type, env)
4294 self.arg_type = arg_type
4295 self.check_type()
4297 def check_type(self):
4298 arg_type = self.arg_type
4299 if arg_type.is_pyobject and not arg_type.is_extension_type:
4300 error(self.pos, "Cannot take sizeof Python object")
4301 elif arg_type.is_void:
4302 error(self.pos, "Cannot take sizeof void")
4303 elif not arg_type.is_complete():
4304 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4306 def calculate_result_code(self):
4307 if self.arg_type.is_extension_type:
4308 # the size of the pointer is boring
4309 # we want the size of the actual struct
4310 arg_code = self.arg_type.declaration_code("", deref=1)
4311 else:
4312 arg_code = self.arg_type.declaration_code("")
4313 return "(sizeof(%s))" % arg_code
4316 class SizeofVarNode(SizeofNode):
4317 # C sizeof function applied to a variable
4318 #
4319 # operand ExprNode
4321 subexprs = ['operand']
4323 def analyse_types(self, env):
4324 # We may actually be looking at a type rather than a variable...
4325 # If we are, traditional analysis would fail...
4326 operand_as_type = self.operand.analyse_as_type(env)
4327 if operand_as_type:
4328 self.arg_type = operand_as_type
4329 self.__class__ = SizeofTypeNode
4330 self.check_type()
4331 else:
4332 self.operand.analyse_types(env)
4334 def calculate_result_code(self):
4335 return "(sizeof(%s))" % self.operand.result()
4337 def generate_result_code(self, code):
4338 pass
4340 class TypeofNode(ExprNode):
4341 # Compile-time type of an expression, as a string.
4342 #
4343 # operand ExprNode
4344 # literal StringNode # internal
4346 literal = None
4347 type = py_object_type
4349 subexprs = ['operand', 'literal']
4351 def analyse_types(self, env):
4352 self.operand.analyse_types(env)
4353 self.literal = StringNode(
4354 self.pos, value=StringEncoding.EncodedString(str(self.operand.type)))
4355 self.literal.analyse_types(env)
4356 self.literal = self.literal.coerce_to_pyobject(env)
4358 def generate_evaluation_code(self, code):
4359 self.literal.generate_evaluation_code(code)
4361 def calculate_result_code(self):
4362 return self.literal.calculate_result_code()
4364 #-------------------------------------------------------------------
4365 #
4366 # Binary operator nodes
4367 #
4368 #-------------------------------------------------------------------
4370 def _not_in(x, seq):
4371 return x not in seq
4373 compile_time_binary_operators = {
4374 '<': operator.lt,
4375 '<=': operator.le,
4376 '==': operator.eq,
4377 '!=': operator.ne,
4378 '>=': operator.ge,
4379 '>': operator.gt,
4380 'is': operator.is_,
4381 'is_not': operator.is_not,
4382 '+': operator.add,
4383 '&': operator.and_,
4384 '/': operator.truediv,
4385 '//': operator.floordiv,
4386 '<<': operator.lshift,
4387 '%': operator.mod,
4388 '*': operator.mul,
4389 '|': operator.or_,
4390 '**': operator.pow,
4391 '>>': operator.rshift,
4392 '-': operator.sub,
4393 '^': operator.xor,
4394 'in': operator.contains,
4395 'not_in': _not_in,
4396 }
4398 def get_compile_time_binop(node):
4399 func = compile_time_binary_operators.get(node.operator)
4400 if not func:
4401 error(node.pos,
4402 "Binary '%s' not supported in compile-time expression"
4403 % node.operator)
4404 return func
4406 class BinopNode(ExprNode):
4407 # operator string
4408 # operand1 ExprNode
4409 # operand2 ExprNode
4410 #
4411 # Processing during analyse_expressions phase:
4412 #
4413 # analyse_c_operation
4414 # Called when neither operand is a pyobject.
4415 # - Check operand types and coerce if needed.
4416 # - Determine result type and result code fragment.
4417 # - Allocate temporary for result if needed.
4419 subexprs = ['operand1', 'operand2']
4421 def calculate_constant_result(self):
4422 func = compile_time_binary_operators[self.operator]
4423 self.constant_result = func(
4424 self.operand1.constant_result,
4425 self.operand2.constant_result)
4427 def compile_time_value(self, denv):
4428 func = get_compile_time_binop(self)
4429 operand1 = self.operand1.compile_time_value(denv)
4430 operand2 = self.operand2.compile_time_value(denv)
4431 try:
4432 return func(operand1, operand2)
4433 except Exception, e:
4434 self.compile_time_value_error(e)
4436 def infer_type(self, env):
4437 return self.result_type(self.operand1.infer_type(env),
4438 self.operand2.infer_type(env))
4440 def analyse_types(self, env):
4441 self.operand1.analyse_types(env)
4442 self.operand2.analyse_types(env)
4443 if self.is_py_operation():
4444 self.coerce_operands_to_pyobjects(env)
4445 self.type = py_object_type
4446 self.is_temp = 1
4447 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4448 self.operand1 = self.operand1.coerce_to_temp(env)
4449 else:
4450 self.analyse_c_operation(env)
4452 def is_py_operation(self):
4453 return self.is_py_operation_types(self.operand1.type, self.operand2.type)
4455 def is_py_operation_types(self, type1, type2):
4456 return type1.is_pyobject or type2.is_pyobject
4458 def result_type(self, type1, type2):
4459 if self.is_py_operation_types(type1, type2):
4460 return py_object_type
4461 else:
4462 return self.compute_c_result_type(type1, type2)
4464 def nogil_check(self, env):
4465 if self.is_py_operation():
4466 self.gil_error()
4468 def coerce_operands_to_pyobjects(self, env):
4469 self.operand1 = self.operand1.coerce_to_pyobject(env)
4470 self.operand2 = self.operand2.coerce_to_pyobject(env)
4472 def check_const(self):
4473 self.operand1.check_const()
4474 self.operand2.check_const()
4476 def generate_result_code(self, code):
4477 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4478 if self.operand1.type.is_pyobject:
4479 function = self.py_operation_function()
4480 if function == "PyNumber_Power":
4481 extra_args = ", Py_None"
4482 else:
4483 extra_args = ""
4484 code.putln(
4485 "%s = %s(%s, %s%s); %s" % (
4486 self.result(),
4487 function,
4488 self.operand1.py_result(),
4489 self.operand2.py_result(),
4490 extra_args,
4491 code.error_goto_if_null(self.result(), self.pos)))
4492 code.put_gotref(self.py_result())
4494 def type_error(self):
4495 if not (self.operand1.type.is_error
4496 or self.operand2.type.is_error):
4497 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4498 (self.operator, self.operand1.type,
4499 self.operand2.type))
4500 self.type = PyrexTypes.error_type
4503 class NumBinopNode(BinopNode):
4504 # Binary operation taking numeric arguments.
4506 infix = True
4508 def analyse_c_operation(self, env):
4509 type1 = self.operand1.type
4510 type2 = self.operand2.type
4511 self.type = self.compute_c_result_type(type1, type2)
4512 if not self.type:
4513 self.type_error()
4514 return
4515 if self.type.is_complex:
4516 self.infix = False
4517 if not self.infix:
4518 self.operand1 = self.operand1.coerce_to(self.type, env)
4519 self.operand2 = self.operand2.coerce_to(self.type, env)
4521 def compute_c_result_type(self, type1, type2):
4522 if self.c_types_okay(type1, type2):
4523 return PyrexTypes.widest_numeric_type(type1, type2)
4524 else:
4525 return None
4527 def get_constant_c_result_code(self):
4528 value1 = self.operand1.get_constant_c_result_code()
4529 value2 = self.operand2.get_constant_c_result_code()
4530 if value1 and value2:
4531 return "(%s %s %s)" % (value1, self.operator, value2)
4532 else:
4533 return None
4535 def c_types_okay(self, type1, type2):
4536 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4537 return (type1.is_numeric or type1.is_enum) \
4538 and (type2.is_numeric or type2.is_enum)
4540 def calculate_result_code(self):
4541 if self.infix:
4542 return "(%s %s %s)" % (
4543 self.operand1.result(),
4544 self.operator,
4545 self.operand2.result())
4546 else:
4547 func = self.type.binary_op(self.operator)
4548 if func is None:
4549 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4550 return "%s(%s, %s)" % (
4551 func,
4552 self.operand1.result(),
4553 self.operand2.result())
4555 def py_operation_function(self):
4556 return self.py_functions[self.operator]
4558 py_functions = {
4559 "|": "PyNumber_Or",
4560 "^": "PyNumber_Xor",
4561 "&": "PyNumber_And",
4562 "<<": "PyNumber_Lshift",
4563 ">>": "PyNumber_Rshift",
4564 "+": "PyNumber_Add",
4565 "-": "PyNumber_Subtract",
4566 "*": "PyNumber_Multiply",
4567 "/": "__Pyx_PyNumber_Divide",
4568 "//": "PyNumber_FloorDivide",
4569 "%": "PyNumber_Remainder",
4570 "**": "PyNumber_Power"
4571 }
4574 class IntBinopNode(NumBinopNode):
4575 # Binary operation taking integer arguments.
4577 def c_types_okay(self, type1, type2):
4578 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4579 return (type1.is_int or type1.is_enum) \
4580 and (type2.is_int or type2.is_enum)
4583 class AddNode(NumBinopNode):
4584 # '+' operator.
4586 def is_py_operation_types(self, type1, type2):
4587 if type1.is_string and type2.is_string:
4588 return 1
4589 else:
4590 return NumBinopNode.is_py_operation_types(self, type1, type2)
4592 def compute_c_result_type(self, type1, type2):
4593 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4594 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4595 return type1
4596 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4597 return type2
4598 else:
4599 return NumBinopNode.compute_c_result_type(
4600 self, type1, type2)
4603 class SubNode(NumBinopNode):
4604 # '-' operator.
4606 def compute_c_result_type(self, type1, type2):
4607 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4608 return type1
4609 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4610 return PyrexTypes.c_int_type
4611 else:
4612 return NumBinopNode.compute_c_result_type(
4613 self, type1, type2)
4616 class MulNode(NumBinopNode):
4617 # '*' operator.
4619 def is_py_operation_types(self, type1, type2):
4620 if (type1.is_string and type2.is_int) \
4621 or (type2.is_string and type1.is_int):
4622 return 1
4623 else:
4624 return NumBinopNode.is_py_operation_types(self, type1, type2)
4627 class DivNode(NumBinopNode):
4628 # '/' or '//' operator.
4630 cdivision = None
4631 truedivision = None # == "unknown" if operator == '/'
4632 ctruedivision = False
4633 cdivision_warnings = False
4634 zerodivision_check = None
4636 def find_compile_time_binary_operator(self, op1, op2):
4637 func = compile_time_binary_operators[self.operator]
4638 if self.operator == '/' and self.truedivision is None:
4639 # => true div for floats, floor div for integers
4640 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)):
4641 func = compile_time_binary_operators['//']
4642 return func
4644 def calculate_constant_result(self):
4645 op1 = self.operand1.constant_result
4646 op2 = self.operand2.constant_result
4647 func = self.find_compile_time_binary_operator(op1, op2)
4648 self.constant_result = func(
4649 self.operand1.constant_result,
4650 self.operand2.constant_result)
4652 def compile_time_value(self, denv):
4653 operand1 = self.operand1.compile_time_value(denv)
4654 operand2 = self.operand2.compile_time_value(denv)
4655 try:
4656 func = self.find_compile_time_binary_operator(
4657 self, operand1, operand2)
4658 return func(operand1, operand2)
4659 except Exception, e:
4660 self.compile_time_value_error(e)
4662 def analyse_types(self, env):
4663 if self.cdivision or env.directives['cdivision']:
4664 self.ctruedivision = False
4665 else:
4666 self.ctruedivision = self.truedivision
4667 NumBinopNode.analyse_types(self, env)
4668 if not self.type.is_pyobject:
4669 self.zerodivision_check = (
4670 self.cdivision is None and not env.directives['cdivision']
4671 and (self.operand2.constant_result is not_a_constant or
4672 self.operand2.constant_result == 0))
4673 if self.zerodivision_check or env.directives['cdivision_warnings']:
4674 # Need to check ahead of time to warn or raise zero division error
4675 self.operand1 = self.operand1.coerce_to_simple(env)
4676 self.operand2 = self.operand2.coerce_to_simple(env)
4677 if env.nogil:
4678 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4680 def compute_c_result_type(self, type1, type2):
4681 if self.operator == '/' and self.ctruedivision:
4682 if not type1.is_float and not type2.is_float:
4683 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type)
4684 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type)
4685 return widest_type
4686 return NumBinopNode.compute_c_result_type(self, type1, type2)
4688 def zero_division_message(self):
4689 if self.type.is_int:
4690 return "integer division or modulo by zero"
4691 else:
4692 return "float division"
4694 def generate_evaluation_code(self, code):
4695 if not self.type.is_pyobject and not self.type.is_complex:
4696 if self.cdivision is None:
4697 self.cdivision = (code.globalstate.directives['cdivision']
4698 or not self.type.signed
4699 or self.type.is_float)
4700 if not self.cdivision:
4701 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4702 NumBinopNode.generate_evaluation_code(self, code)
4703 self.generate_div_warning_code(code)
4705 def generate_div_warning_code(self, code):
4706 if not self.type.is_pyobject:
4707 if self.zerodivision_check:
4708 if not self.infix:
4709 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4710 else:
4711 zero_test = "%s == 0" % self.operand2.result()
4712 code.putln("if (unlikely(%s)) {" % zero_test)
4713 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4714 code.putln(code.error_goto(self.pos))
4715 code.putln("}")
4716 if self.type.is_int and self.type.signed and self.operator != '%':
4717 code.globalstate.use_utility_code(division_overflow_test_code)
4718 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4719 self.type.declaration_code(''),
4720 self.operand2.result(),
4721 self.operand1.result()))
4722 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4723 code.putln(code.error_goto(self.pos))
4724 code.putln("}")
4725 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4726 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4727 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4728 self.operand1.result(),
4729 self.operand2.result()))
4730 code.putln(code.set_error_info(self.pos));
4731 code.put("if (__Pyx_cdivision_warning()) ")
4732 code.put_goto(code.error_label)
4733 code.putln("}")
4735 def calculate_result_code(self):
4736 if self.type.is_complex:
4737 return NumBinopNode.calculate_result_code(self)
4738 elif self.type.is_float and self.operator == '//':
4739 return "floor(%s / %s)" % (
4740 self.operand1.result(),
4741 self.operand2.result())
4742 elif self.truedivision or self.cdivision:
4743 op1 = self.operand1.result()
4744 op2 = self.operand2.result()
4745 if self.truedivision:
4746 if self.type != self.operand1.type:
4747 op1 = self.type.cast_code(op1)
4748 if self.type != self.operand2.type:
4749 op2 = self.type.cast_code(op2)
4750 return "(%s / %s)" % (op1, op2)
4751 else:
4752 return "__Pyx_div_%s(%s, %s)" % (
4753 self.type.specalization_name(),
4754 self.operand1.result(),
4755 self.operand2.result())
4758 class ModNode(DivNode):
4759 # '%' operator.
4761 def is_py_operation_types(self, type1, type2):
4762 return (type1.is_string
4763 or type2.is_string
4764 or NumBinopNode.is_py_operation_types(self, type1, type2))
4766 def zero_division_message(self):
4767 if self.type.is_int:
4768 return "integer division or modulo by zero"
4769 else:
4770 return "float divmod()"
4772 def generate_evaluation_code(self, code):
4773 if not self.type.is_pyobject:
4774 if self.cdivision is None:
4775 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4776 if not self.cdivision:
4777 if self.type.is_int:
4778 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4779 else:
4780 code.globalstate.use_utility_code(
4781 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4782 NumBinopNode.generate_evaluation_code(self, code)
4783 self.generate_div_warning_code(code)
4785 def calculate_result_code(self):
4786 if self.cdivision:
4787 if self.type.is_float:
4788 return "fmod%s(%s, %s)" % (
4789 self.type.math_h_modifier,
4790 self.operand1.result(),
4791 self.operand2.result())
4792 else:
4793 return "(%s %% %s)" % (
4794 self.operand1.result(),
4795 self.operand2.result())
4796 else:
4797 return "__Pyx_mod_%s(%s, %s)" % (
4798 self.type.specalization_name(),
4799 self.operand1.result(),
4800 self.operand2.result())
4802 class PowNode(NumBinopNode):
4803 # '**' operator.
4805 def analyse_c_operation(self, env):
4806 NumBinopNode.analyse_c_operation(self, env)
4807 if self.type.is_complex:
4808 error(self.pos, "complex powers not yet supported")
4809 self.pow_func = "<error>"
4810 elif self.type.is_float:
4811 self.pow_func = "pow"
4812 else:
4813 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4814 env.use_utility_code(
4815 int_pow_utility_code.specialize(func_name=self.pow_func,
4816 type=self.type.declaration_code('')))
4818 def calculate_result_code(self):
4819 return "%s(%s, %s)" % (
4820 self.pow_func,
4821 self.operand1.result(),
4822 self.operand2.result())
4825 # Note: This class is temporary "shut down" into an ineffective mode temp
4826 # allocation mode.
4827 #
4828 # More sophisticated temp reuse was going on before,
4829 # one could have a look at adding this again after /all/ classes
4830 # are converted to the new temp scheme. (The temp juggling cannot work
4831 # otherwise).
4832 class BoolBinopNode(ExprNode):
4833 # Short-circuiting boolean operation.
4834 #
4835 # operator string
4836 # operand1 ExprNode
4837 # operand2 ExprNode
4839 subexprs = ['operand1', 'operand2']
4841 def infer_type(self, env):
4842 if (self.operand1.infer_type(env).is_pyobject or
4843 self.operand2.infer_type(env).is_pyobject):
4844 return py_object_type
4845 else:
4846 return PyrexTypes.c_bint_type
4848 def calculate_constant_result(self):
4849 if self.operator == 'and':
4850 self.constant_result = \
4851 self.operand1.constant_result and \
4852 self.operand2.constant_result
4853 else:
4854 self.constant_result = \
4855 self.operand1.constant_result or \
4856 self.operand2.constant_result
4858 def compile_time_value(self, denv):
4859 if self.operator == 'and':
4860 return self.operand1.compile_time_value(denv) \
4861 and self.operand2.compile_time_value(denv)
4862 else:
4863 return self.operand1.compile_time_value(denv) \
4864 or self.operand2.compile_time_value(denv)
4866 def coerce_to_boolean(self, env):
4867 self.operand1 = self.operand1.coerce_to_boolean(env)
4868 self.operand2 = self.operand2.coerce_to_boolean(env)
4869 self.type = PyrexTypes.c_bint_type
4870 return self
4872 def analyse_types(self, env):
4873 self.operand1.analyse_types(env)
4874 self.operand2.analyse_types(env)
4875 if self.operand1.type.is_pyobject or \
4876 self.operand2.type.is_pyobject:
4877 self.operand1 = self.operand1.coerce_to_pyobject(env)
4878 self.operand2 = self.operand2.coerce_to_pyobject(env)
4879 self.type = py_object_type
4880 else:
4881 self.operand1 = self.operand1.coerce_to_boolean(env)
4882 self.operand2 = self.operand2.coerce_to_boolean(env)
4883 self.type = PyrexTypes.c_bint_type
4885 # Below disabled for
4887 # For what we're about to do, it's vital that
4888 # both operands be temp nodes.
4889 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4890 # self.operand2 = self.operand2.coerce_to_temp(env)
4891 self.is_temp = 1
4893 gil_message = "Truth-testing Python object"
4895 def check_const(self):
4896 self.operand1.check_const()
4897 self.operand2.check_const()
4899 def calculate_result_code(self):
4900 return "(%s %s %s)" % (
4901 self.operand1.result(),
4902 self.py_to_c_op[self.operator],
4903 self.operand2.result())
4905 py_to_c_op = {'and': "&&", 'or': "||"}
4907 def generate_evaluation_code(self, code):
4908 code.mark_pos(self.pos)
4909 self.operand1.generate_evaluation_code(code)
4910 test_result, uses_temp = self.generate_operand1_test(code)
4911 if self.operator == 'and':
4912 sense = ""
4913 else:
4914 sense = "!"
4915 code.putln(
4916 "if (%s%s) {" % (
4917 sense,
4918 test_result))
4919 if uses_temp:
4920 code.funcstate.release_temp(test_result)
4921 self.operand1.generate_disposal_code(code)
4922 self.operand2.generate_evaluation_code(code)
4923 self.allocate_temp_result(code)
4924 self.operand2.make_owned_reference(code)
4925 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4926 self.operand2.generate_post_assignment_code(code)
4927 self.operand2.free_temps(code)
4928 code.putln("} else {")
4929 self.operand1.make_owned_reference(code)
4930 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4931 self.operand1.generate_post_assignment_code(code)
4932 self.operand1.free_temps(code)
4933 code.putln("}")
4935 def generate_operand1_test(self, code):
4936 # Generate code to test the truth of the first operand.
4937 if self.type.is_pyobject:
4938 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4939 manage_ref=False)
4940 code.putln(
4941 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4942 test_result,
4943 self.operand1.py_result(),
4944 code.error_goto_if_neg(test_result, self.pos)))
4945 else:
4946 test_result = self.operand1.result()
4947 return (test_result, self.type.is_pyobject)
4950 class CondExprNode(ExprNode):
4951 # Short-circuiting conditional expression.
4952 #
4953 # test ExprNode
4954 # true_val ExprNode
4955 # false_val ExprNode
4957 true_val = None
4958 false_val = None
4960 subexprs = ['test', 'true_val', 'false_val']
4962 def type_dependencies(self, env):
4963 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
4965 def infer_type(self, env):
4966 return self.compute_result_type(self.true_val.infer_type(env),
4967 self.false_val.infer_type(env))
4969 def calculate_constant_result(self):
4970 if self.test.constant_result:
4971 self.constant_result = self.true_val.constant_result
4972 else:
4973 self.constant_result = self.false_val.constant_result
4975 def analyse_types(self, env):
4976 self.test.analyse_types(env)
4977 self.test = self.test.coerce_to_boolean(env)
4978 self.true_val.analyse_types(env)
4979 self.false_val.analyse_types(env)
4980 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4981 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4982 self.true_val = self.true_val.coerce_to(self.type, env)
4983 self.false_val = self.false_val.coerce_to(self.type, env)
4984 self.is_temp = 1
4985 if self.type == PyrexTypes.error_type:
4986 self.type_error()
4988 def compute_result_type(self, type1, type2):
4989 if type1 == type2:
4990 return type1
4991 elif type1.is_numeric and type2.is_numeric:
4992 return PyrexTypes.widest_numeric_type(type1, type2)
4993 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4994 return type2
4995 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4996 return type1
4997 elif type1.is_pyobject or type2.is_pyobject:
4998 return py_object_type
4999 elif type1.assignable_from(type2):
5000 return type1
5001 elif type2.assignable_from(type1):
5002 return type2
5003 else:
5004 return PyrexTypes.error_type
5006 def type_error(self):
5007 if not (self.true_val.type.is_error or self.false_val.type.is_error):
5008 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
5009 (self.true_val.type, self.false_val.type))
5010 self.type = PyrexTypes.error_type
5012 def check_const(self):
5013 self.test.check_const()
5014 self.true_val.check_const()
5015 self.false_val.check_const()
5017 def generate_evaluation_code(self, code):
5018 # Because subexprs may not be evaluated we can use a more optimal
5019 # subexpr allocation strategy than the default, so override evaluation_code.
5021 code.mark_pos(self.pos)
5022 self.allocate_temp_result(code)
5023 self.test.generate_evaluation_code(code)
5024 code.putln("if (%s) {" % self.test.result() )
5025 self.eval_and_get(code, self.true_val)
5026 code.putln("} else {")
5027 self.eval_and_get(code, self.false_val)
5028 code.putln("}")
5029 self.test.generate_disposal_code(code)
5030 self.test.free_temps(code)
5032 def eval_and_get(self, code, expr):
5033 expr.generate_evaluation_code(code)
5034 expr.make_owned_reference(code)
5035 code.putln("%s = %s;" % (self.result(), expr.result()))
5036 expr.generate_post_assignment_code(code)
5037 expr.free_temps(code)
5039 richcmp_constants = {
5040 "<" : "Py_LT",
5041 "<=": "Py_LE",
5042 "==": "Py_EQ",
5043 "!=": "Py_NE",
5044 "<>": "Py_NE",
5045 ">" : "Py_GT",
5046 ">=": "Py_GE",
5047 }
5049 class CmpNode(object):
5050 # Mixin class containing code common to PrimaryCmpNodes
5051 # and CascadedCmpNodes.
5053 def infer_types(self, env):
5054 # TODO: Actually implement this (after merging with -unstable).
5055 return py_object_type
5057 def calculate_cascaded_constant_result(self, operand1_result):
5058 func = compile_time_binary_operators[self.operator]
5059 operand2_result = self.operand2.constant_result
5060 result = func(operand1_result, operand2_result)
5061 if result and self.cascade:
5062 result = result and \
5063 self.cascade.cascaded_compile_time_value(operand2_result)
5064 self.constant_result = result
5066 def cascaded_compile_time_value(self, operand1, denv):
5067 func = get_compile_time_binop(self)
5068 operand2 = self.operand2.compile_time_value(denv)
5069 try:
5070 result = func(operand1, operand2)
5071 except Exception, e:
5072 self.compile_time_value_error(e)
5073 result = None
5074 if result:
5075 cascade = self.cascade
5076 if cascade:
5077 # FIXME: I bet this must call cascaded_compile_time_value()
5078 result = result and cascade.compile_time_value(operand2, denv)
5079 return result
5081 def is_python_comparison(self):
5082 return (self.has_python_operands()
5083 or (self.cascade and self.cascade.is_python_comparison())
5084 or self.operator in ('in', 'not_in'))
5086 def is_python_result(self):
5087 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
5088 or (self.cascade and self.cascade.is_python_result()))
5090 def check_types(self, env, operand1, op, operand2):
5091 if operand1.type.is_complex or operand2.type.is_complex:
5092 if op not in ('==', '!='):
5093 error(self.pos, "complex types unordered")
5094 common_type = PyrexTypes.widest_numeric_type(operand1.type, operand2.type)
5095 self.operand1 = operand1.coerce_to(common_type, env)
5096 self.operand2 = operand2.coerce_to(common_type, env)
5097 elif not self.types_okay(operand1, op, operand2):
5098 error(self.pos, "Invalid types for '%s' (%s, %s)" %
5099 (self.operator, operand1.type, operand2.type))
5101 def types_okay(self, operand1, op, operand2):
5102 type1 = operand1.type
5103 type2 = operand2.type
5104 if type1.is_error or type2.is_error:
5105 return 1
5106 if type1.is_pyobject: # type2 will be, too
5107 return 1
5108 elif type1.is_ptr or type1.is_array:
5109 return type1.is_null_ptr or type2.is_null_ptr \
5110 or ((type2.is_ptr or type2.is_array)
5111 and type1.base_type.same_as(type2.base_type))
5112 elif ((type1.is_numeric and type2.is_numeric
5113 or type1.is_enum and (type1 is type2 or type2.is_int)
5114 or type1.is_int and type2.is_enum)
5115 and op not in ('is', 'is_not')):
5116 return 1
5117 else:
5118 return type1.is_cfunction and type1.is_cfunction and type1 == type2
5120 def generate_operation_code(self, code, result_code,
5121 operand1, op , operand2):
5122 if self.type is PyrexTypes.py_object_type:
5123 coerce_result = "__Pyx_PyBool_FromLong"
5124 else:
5125 coerce_result = ""
5126 if 'not' in op: negation = "!"
5127 else: negation = ""
5128 if op == 'in' or op == 'not_in':
5129 if operand2.type is dict_type:
5130 code.globalstate.use_utility_code(
5131 raise_none_iter_error_utility_code)
5132 code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
5133 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
5134 code.error_goto(self.pos))
5135 code.putln("} else {")
5136 code.putln(
5137 "%s = %s(%sPyDict_Contains(%s, %s)); %s" % (
5138 result_code,
5139 coerce_result,
5140 negation,
5141 operand2.py_result(),
5142 operand1.py_result(),
5143 code.error_goto_if_neg(result_code, self.pos)))
5144 code.putln("}")
5145 else:
5146 code.putln(
5147 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
5148 result_code,
5149 coerce_result,
5150 negation,
5151 operand2.py_result(),
5152 operand1.py_result(),
5153 code.error_goto_if_neg(result_code, self.pos)))
5154 elif (operand1.type.is_pyobject
5155 and op not in ('is', 'is_not')):
5156 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
5157 result_code,
5158 operand1.py_result(),
5159 operand2.py_result(),
5160 richcmp_constants[op],
5161 code.error_goto_if_null(result_code, self.pos)))
5162 code.put_gotref(result_code)
5163 elif operand1.type.is_complex:
5164 if op == "!=":
5165 negation = "!"
5166 else:
5167 negation = ""
5168 code.putln("%s = %s(%s%s(%s, %s));" % (
5169 result_code,
5170 coerce_result,
5171 negation,
5172 operand1.type.unary_op('eq'),
5173 operand1.result(),
5174 operand2.result()))
5175 else:
5176 type1 = operand1.type
5177 type2 = operand2.type
5178 if (type1.is_extension_type or type2.is_extension_type) \
5179 and not type1.same_as(type2):
5180 common_type = py_object_type
5181 elif type1.is_numeric:
5182 common_type = PyrexTypes.widest_numeric_type(type1, type2)
5183 else:
5184 common_type = type1
5185 code1 = operand1.result_as(common_type)
5186 code2 = operand2.result_as(common_type)
5187 code.putln("%s = %s(%s %s %s);" % (
5188 result_code,
5189 coerce_result,
5190 code1,
5191 self.c_operator(op),
5192 code2))
5194 def c_operator(self, op):
5195 if op == 'is':
5196 return "=="
5197 elif op == 'is_not':
5198 return "!="
5199 else:
5200 return op
5203 class PrimaryCmpNode(ExprNode, CmpNode):
5204 # Non-cascaded comparison or first comparison of
5205 # a cascaded sequence.
5206 #
5207 # operator string
5208 # operand1 ExprNode
5209 # operand2 ExprNode
5210 # cascade CascadedCmpNode
5212 # We don't use the subexprs mechanism, because
5213 # things here are too complicated for it to handle.
5214 # Instead, we override all the framework methods
5215 # which use it.
5217 child_attrs = ['operand1', 'operand2', 'cascade']
5219 cascade = None
5221 def infer_type(self, env):
5222 # TODO: Actually implement this (after merging with -unstable).
5223 return py_object_type
5225 def type_dependencies(self, env):
5226 return ()
5228 def calculate_constant_result(self):
5229 self.constant_result = self.calculate_cascaded_constant_result(
5230 self.operand1.constant_result)
5232 def compile_time_value(self, denv):
5233 operand1 = self.operand1.compile_time_value(denv)
5234 return self.cascaded_compile_time_value(operand1, denv)
5236 def analyse_types(self, env):
5237 self.operand1.analyse_types(env)
5238 self.operand2.analyse_types(env)
5239 if self.cascade:
5240 self.cascade.analyse_types(env, self.operand2)
5241 self.is_pycmp = self.is_python_comparison()
5242 if self.is_pycmp:
5243 self.coerce_operands_to_pyobjects(env)
5244 if self.has_int_operands():
5245 self.coerce_chars_to_ints(env)
5246 if self.cascade:
5247 self.operand2 = self.operand2.coerce_to_simple(env)
5248 self.cascade.coerce_cascaded_operands_to_temp(env)
5249 self.check_operand_types(env)
5250 if self.is_python_result():
5251 self.type = PyrexTypes.py_object_type
5252 else:
5253 self.type = PyrexTypes.c_bint_type
5254 cdr = self.cascade
5255 while cdr:
5256 cdr.type = self.type
5257 cdr = cdr.cascade
5258 if self.is_pycmp or self.cascade:
5259 self.is_temp = 1
5261 def check_operand_types(self, env):
5262 self.check_types(env,
5263 self.operand1, self.operator, self.operand2)
5264 if self.cascade:
5265 self.cascade.check_operand_types(env, self.operand2)
5267 def has_python_operands(self):
5268 return (self.operand1.type.is_pyobject
5269 or self.operand2.type.is_pyobject)
5271 def coerce_operands_to_pyobjects(self, env):
5272 self.operand1 = self.operand1.coerce_to_pyobject(env)
5273 self.operand2 = self.operand2.coerce_to_pyobject(env)
5274 if self.cascade:
5275 self.cascade.coerce_operands_to_pyobjects(env)
5277 def has_int_operands(self):
5278 return (self.operand1.type.is_int or self.operand2.type.is_int) \
5279 or (self.cascade and self.cascade.has_int_operands())
5281 def coerce_chars_to_ints(self, env):
5282 # coerce literal single-char strings to c chars
5283 if self.operand1.type.is_string and isinstance(self.operand1, BytesNode):
5284 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
5285 if self.operand2.type.is_string and isinstance(self.operand2, BytesNode):
5286 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
5287 if self.cascade:
5288 self.cascade.coerce_chars_to_ints(env)
5290 def check_const(self):
5291 self.operand1.check_const()
5292 self.operand2.check_const()
5293 if self.cascade:
5294 self.not_const()
5296 def calculate_result_code(self):
5297 if self.operand1.type.is_complex:
5298 if self.operator == "!=":
5299 negation = "!"
5300 else:
5301 negation = ""
5302 return "(%s%s(%s, %s))" % (
5303 negation,
5304 self.operand1.type.binary_op('=='),
5305 self.operand1.result(),
5306 self.operand2.result())
5307 else:
5308 return "(%s %s %s)" % (
5309 self.operand1.result(),
5310 self.c_operator(self.operator),
5311 self.operand2.result())
5313 def generate_evaluation_code(self, code):
5314 self.operand1.generate_evaluation_code(code)
5315 self.operand2.generate_evaluation_code(code)
5316 if self.is_temp:
5317 self.allocate_temp_result(code)
5318 self.generate_operation_code(code, self.result(),
5319 self.operand1, self.operator, self.operand2)
5320 if self.cascade:
5321 self.cascade.generate_evaluation_code(code,
5322 self.result(), self.operand2)
5323 self.operand1.generate_disposal_code(code)
5324 self.operand1.free_temps(code)
5325 self.operand2.generate_disposal_code(code)
5326 self.operand2.free_temps(code)
5328 def generate_subexpr_disposal_code(self, code):
5329 # If this is called, it is a non-cascaded cmp,
5330 # so only need to dispose of the two main operands.
5331 self.operand1.generate_disposal_code(code)
5332 self.operand2.generate_disposal_code(code)
5334 def free_subexpr_temps(self, code):
5335 # If this is called, it is a non-cascaded cmp,
5336 # so only need to dispose of the two main operands.
5337 self.operand1.free_temps(code)
5338 self.operand2.free_temps(code)
5340 def annotate(self, code):
5341 self.operand1.annotate(code)
5342 self.operand2.annotate(code)
5343 if self.cascade:
5344 self.cascade.annotate(code)
5347 class CascadedCmpNode(Node, CmpNode):
5348 # A CascadedCmpNode is not a complete expression node. It
5349 # hangs off the side of another comparison node, shares
5350 # its left operand with that node, and shares its result
5351 # with the PrimaryCmpNode at the head of the chain.
5352 #
5353 # operator string
5354 # operand2 ExprNode
5355 # cascade CascadedCmpNode
5357 child_attrs = ['operand2', 'cascade']
5359 cascade = None
5360 constant_result = constant_value_not_set # FIXME: where to calculate this?
5362 def infer_type(self, env):
5363 # TODO: Actually implement this (after merging with -unstable).
5364 return py_object_type
5366 def type_dependencies(self, env):
5367 return ()
5369 def analyse_types(self, env, operand1):
5370 self.operand2.analyse_types(env)
5371 if self.cascade:
5372 self.cascade.analyse_types(env, self.operand2)
5374 def check_operand_types(self, env, operand1):
5375 self.check_types(env,
5376 operand1, self.operator, self.operand2)
5377 if self.cascade:
5378 self.cascade.check_operand_types(env, self.operand2)
5380 def has_python_operands(self):
5381 return self.operand2.type.is_pyobject
5383 def coerce_operands_to_pyobjects(self, env):
5384 self.operand2 = self.operand2.coerce_to_pyobject(env)
5385 if self.cascade:
5386 self.cascade.coerce_operands_to_pyobjects(env)
5388 def has_int_operands(self):
5389 return self.operand2.type.is_int
5391 def coerce_chars_to_ints(self, env):
5392 if self.operand2.type.is_string and isinstance(self.operand2, BytesNode):
5393 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
5395 def coerce_cascaded_operands_to_temp(self, env):
5396 if self.cascade:
5397 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5398 self.operand2 = self.operand2.coerce_to_simple(env)
5399 self.cascade.coerce_cascaded_operands_to_temp(env)
5401 def generate_evaluation_code(self, code, result, operand1):
5402 if self.type.is_pyobject:
5403 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5404 code.put_decref(result, self.type)
5405 else:
5406 code.putln("if (%s) {" % result)
5407 self.operand2.generate_evaluation_code(code)
5408 self.generate_operation_code(code, result,
5409 operand1, self.operator, self.operand2)
5410 if self.cascade:
5411 self.cascade.generate_evaluation_code(
5412 code, result, self.operand2)
5413 # Cascaded cmp result is always temp
5414 self.operand2.generate_disposal_code(code)
5415 self.operand2.free_temps(code)
5416 code.putln("}")
5418 def annotate(self, code):
5419 self.operand2.annotate(code)
5420 if self.cascade:
5421 self.cascade.annotate(code)
5424 binop_node_classes = {
5425 "or": BoolBinopNode,
5426 "and": BoolBinopNode,
5427 "|": IntBinopNode,
5428 "^": IntBinopNode,
5429 "&": IntBinopNode,
5430 "<<": IntBinopNode,
5431 ">>": IntBinopNode,
5432 "+": AddNode,
5433 "-": SubNode,
5434 "*": MulNode,
5435 "/": DivNode,
5436 "//": DivNode,
5437 "%": ModNode,
5438 "**": PowNode
5439 }
5441 def binop_node(pos, operator, operand1, operand2):
5442 # Construct binop node of appropriate class for
5443 # given operator.
5444 return binop_node_classes[operator](pos,
5445 operator = operator,
5446 operand1 = operand1,
5447 operand2 = operand2)
5449 #-------------------------------------------------------------------
5450 #
5451 # Coercion nodes
5452 #
5453 # Coercion nodes are special in that they are created during
5454 # the analyse_types phase of parse tree processing.
5455 # Their __init__ methods consequently incorporate some aspects
5456 # of that phase.
5457 #
5458 #-------------------------------------------------------------------
5460 class CoercionNode(ExprNode):
5461 # Abstract base class for coercion nodes.
5462 #
5463 # arg ExprNode node being coerced
5465 subexprs = ['arg']
5467 def __init__(self, arg):
5468 self.pos = arg.pos
5469 self.arg = arg
5470 if debug_coercion:
5471 print("%s Coercing %s" % (self, self.arg))
5473 def calculate_constant_result(self):
5474 # constant folding can break type coercion, so this is disabled
5475 pass
5477 def annotate(self, code):
5478 self.arg.annotate(code)
5479 if self.arg.type != self.type:
5480 file, line, col = self.pos
5481 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5484 class CastNode(CoercionNode):
5485 # Wrap a node in a C type cast.
5487 def __init__(self, arg, new_type):
5488 CoercionNode.__init__(self, arg)
5489 self.type = new_type
5491 def calculate_result_code(self):
5492 return self.arg.result_as(self.type)
5494 def generate_result_code(self, code):
5495 self.arg.generate_result_code(code)
5498 class PyTypeTestNode(CoercionNode):
5499 # This node is used to check that a generic Python
5500 # object is an instance of a particular extension type.
5501 # This node borrows the result of its argument node.
5503 def __init__(self, arg, dst_type, env):
5504 # The arg is know to be a Python object, and
5505 # the dst_type is known to be an extension type.
5506 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5507 CoercionNode.__init__(self, arg)
5508 self.type = dst_type
5509 self.result_ctype = arg.ctype()
5511 nogil_check = Node.gil_error
5512 gil_message = "Python type test"
5514 def analyse_types(self, env):
5515 pass
5517 def result_in_temp(self):
5518 return self.arg.result_in_temp()
5520 def is_ephemeral(self):
5521 return self.arg.is_ephemeral()
5523 def calculate_constant_result(self):
5524 # FIXME
5525 pass
5527 def calculate_result_code(self):
5528 return self.arg.result()
5530 def generate_result_code(self, code):
5531 if self.type.typeobj_is_available():
5532 if not self.type.is_builtin_type:
5533 code.globalstate.use_utility_code(type_test_utility_code)
5534 code.putln(
5535 "if (!(%s)) %s" % (
5536 self.type.type_test_code(self.arg.py_result()),
5537 code.error_goto(self.pos)))
5538 else:
5539 error(self.pos, "Cannot test type of extern C class "
5540 "without type object name specification")
5542 def generate_post_assignment_code(self, code):
5543 self.arg.generate_post_assignment_code(code)
5545 def free_temps(self, code):
5546 self.arg.free_temps(code)
5549 class NoneCheckNode(CoercionNode):
5550 # This node is used to check that a Python object is not None and
5551 # raises an appropriate exception (as specified by the creating
5552 # transform).
5554 def __init__(self, arg, exception_type_cname, exception_message):
5555 CoercionNode.__init__(self, arg)
5556 self.type = arg.type
5557 self.result_ctype = arg.ctype()
5558 self.exception_type_cname = exception_type_cname
5559 self.exception_message = exception_message
5561 def analyse_types(self, env):
5562 pass
5564 def result_in_temp(self):
5565 return self.arg.result_in_temp()
5567 def calculate_result_code(self):
5568 return self.arg.result()
5570 def generate_result_code(self, code):
5571 code.putln(
5572 "if (unlikely(%s == Py_None)) {" % self.arg.result())
5573 code.putln('PyErr_SetString(%s, "%s"); %s ' % (
5574 self.exception_type_cname,
5575 StringEncoding.escape_byte_string(
5576 self.exception_message.encode('UTF-8')),
5577 code.error_goto(self.pos)))
5578 code.putln("}")
5580 def generate_post_assignment_code(self, code):
5581 self.arg.generate_post_assignment_code(code)
5583 def free_temps(self, code):
5584 self.arg.free_temps(code)
5587 class CoerceToPyTypeNode(CoercionNode):
5588 # This node is used to convert a C data type
5589 # to a Python object.
5591 type = py_object_type
5592 is_temp = 1
5594 def __init__(self, arg, env):
5595 CoercionNode.__init__(self, arg)
5596 if not arg.type.create_to_py_utility_code(env):
5597 error(arg.pos,
5598 "Cannot convert '%s' to Python object" % arg.type)
5600 gil_message = "Converting to Python object"
5602 def coerce_to_boolean(self, env):
5603 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5605 def coerce_to_integer(self, env):
5606 # If not already some C integer type, coerce to longint.
5607 if self.arg.type.is_int:
5608 return self.arg
5609 else:
5610 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5612 def analyse_types(self, env):
5613 # The arg is always already analysed
5614 pass
5616 def generate_result_code(self, code):
5617 function = self.arg.type.to_py_function
5618 code.putln('%s = %s(%s); %s' % (
5619 self.result(),
5620 function,
5621 self.arg.result(),
5622 code.error_goto_if_null(self.result(), self.pos)))
5623 code.put_gotref(self.py_result())
5626 class CoerceFromPyTypeNode(CoercionNode):
5627 # This node is used to convert a Python object
5628 # to a C data type.
5630 def __init__(self, result_type, arg, env):
5631 CoercionNode.__init__(self, arg)
5632 self.type = result_type
5633 self.is_temp = 1
5634 if not result_type.create_from_py_utility_code(env):
5635 error(arg.pos,
5636 "Cannot convert Python object to '%s'" % result_type)
5637 if self.type.is_string and self.arg.is_ephemeral():
5638 error(arg.pos,
5639 "Obtaining char * from temporary Python value")
5641 def analyse_types(self, env):
5642 # The arg is always already analysed
5643 pass
5645 def generate_result_code(self, code):
5646 function = self.type.from_py_function
5647 operand = self.arg.py_result()
5648 rhs = "%s(%s)" % (function, operand)
5649 if self.type.is_enum:
5650 rhs = typecast(self.type, c_long_type, rhs)
5651 code.putln('%s = %s; %s' % (
5652 self.result(),
5653 rhs,
5654 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5655 if self.type.is_pyobject:
5656 code.put_gotref(self.py_result())
5659 class CoerceToBooleanNode(CoercionNode):
5660 # This node is used when a result needs to be used
5661 # in a boolean context.
5663 type = PyrexTypes.c_bint_type
5665 def __init__(self, arg, env):
5666 CoercionNode.__init__(self, arg)
5667 if arg.type.is_pyobject:
5668 self.is_temp = 1
5670 def nogil_check(self, env):
5671 if self.arg.type.is_pyobject:
5672 self.gil_error()
5674 gil_message = "Truth-testing Python object"
5676 def check_const(self):
5677 if self.is_temp:
5678 self.not_const()
5679 self.arg.check_const()
5681 def calculate_result_code(self):
5682 return "(%s != 0)" % self.arg.result()
5684 def generate_result_code(self, code):
5685 if self.arg.type.is_pyobject:
5686 code.putln(
5687 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5688 self.result(),
5689 self.arg.py_result(),
5690 code.error_goto_if_neg(self.result(), self.pos)))
5692 class CoerceToComplexNode(CoercionNode):
5694 def __init__(self, arg, dst_type, env):
5695 if arg.type.is_complex:
5696 arg = arg.coerce_to_simple(env)
5697 self.type = dst_type
5698 CoercionNode.__init__(self, arg)
5699 dst_type.create_declaration_utility_code(env)
5701 def calculate_result_code(self):
5702 if self.arg.type.is_complex:
5703 real_part = "__Pyx_CREAL(%s)" % self.arg.result()
5704 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result()
5705 else:
5706 real_part = self.arg.result()
5707 imag_part = "0"
5708 return "%s(%s, %s)" % (
5709 self.type.from_parts,
5710 real_part,
5711 imag_part)
5713 def generate_result_code(self, code):
5714 pass
5716 class CoerceToTempNode(CoercionNode):
5717 # This node is used to force the result of another node
5718 # to be stored in a temporary. It is only used if the
5719 # argument node's result is not already in a temporary.
5721 def __init__(self, arg, env):
5722 CoercionNode.__init__(self, arg)
5723 self.type = self.arg.type
5724 self.is_temp = 1
5725 if self.type.is_pyobject:
5726 self.result_ctype = py_object_type
5728 gil_message = "Creating temporary Python reference"
5730 def analyse_types(self, env):
5731 # The arg is always already analysed
5732 pass
5734 def coerce_to_boolean(self, env):
5735 self.arg = self.arg.coerce_to_boolean(env)
5736 self.type = self.arg.type
5737 self.result_ctype = self.type
5738 return self
5740 def generate_result_code(self, code):
5741 #self.arg.generate_evaluation_code(code) # Already done
5742 # by generic generate_subexpr_evaluation_code!
5743 code.putln("%s = %s;" % (
5744 self.result(), self.arg.result_as(self.ctype())))
5745 if self.type.is_pyobject:
5746 code.put_incref(self.result(), self.ctype())
5749 class CloneNode(CoercionNode):
5750 # This node is employed when the result of another node needs
5751 # to be used multiple times. The argument node's result must
5752 # be in a temporary. This node "borrows" the result from the
5753 # argument node, and does not generate any evaluation or
5754 # disposal code for it. The original owner of the argument
5755 # node is responsible for doing those things.
5757 subexprs = [] # Arg is not considered a subexpr
5758 nogil_check = None
5760 def __init__(self, arg):
5761 CoercionNode.__init__(self, arg)
5762 if hasattr(arg, 'type'):
5763 self.type = arg.type
5764 self.result_ctype = arg.result_ctype
5765 if hasattr(arg, 'entry'):
5766 self.entry = arg.entry
5768 def result(self):
5769 return self.arg.result()
5771 def type_dependencies(self, env):
5772 return self.arg.type_dependencies(env)
5774 def infer_type(self, env):
5775 return self.arg.infer_type(env)
5777 def analyse_types(self, env):
5778 self.type = self.arg.type
5779 self.result_ctype = self.arg.result_ctype
5780 self.is_temp = 1
5781 if hasattr(self.arg, 'entry'):
5782 self.entry = self.arg.entry
5784 def generate_evaluation_code(self, code):
5785 pass
5787 def generate_result_code(self, code):
5788 pass
5790 def generate_disposal_code(self, code):
5791 pass
5793 def free_temps(self, code):
5794 pass
5797 class ModuleRefNode(ExprNode):
5798 # Simple returns the module object
5800 type = py_object_type
5801 is_temp = False
5802 subexprs = []
5804 def analyse_types(self, env):
5805 pass
5807 def calculate_result_code(self):
5808 return Naming.module_cname
5810 def generate_result_code(self, code):
5811 pass
5813 class DocstringRefNode(ExprNode):
5814 # Extracts the docstring of the body element
5816 subexprs = ['body']
5817 type = py_object_type
5818 is_temp = True
5820 def __init__(self, pos, body):
5821 ExprNode.__init__(self, pos)
5822 assert body.type.is_pyobject
5823 self.body = body
5825 def analyse_types(self, env):
5826 pass
5828 def generate_result_code(self, code):
5829 code.putln('%s = __Pyx_GetAttrString(%s, "__doc__");' %
5830 (self.result(), self.body.result()))
5831 code.put_gotref(self.result())
5835 #------------------------------------------------------------------------------------
5836 #
5837 # Runtime support code
5838 #
5839 #------------------------------------------------------------------------------------
5841 get_name_interned_utility_code = UtilityCode(
5842 proto = """
5843 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5844 """,
5845 impl = """
5846 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5847 PyObject *result;
5848 result = PyObject_GetAttr(dict, name);
5849 if (!result)
5850 PyErr_SetObject(PyExc_NameError, name);
5851 return result;
5852 }
5853 """)
5855 #------------------------------------------------------------------------------------
5857 import_utility_code = UtilityCode(
5858 proto = """
5859 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5860 """,
5861 impl = """
5862 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5863 PyObject *__import__ = 0;
5864 PyObject *empty_list = 0;
5865 PyObject *module = 0;
5866 PyObject *global_dict = 0;
5867 PyObject *empty_dict = 0;
5868 PyObject *list;
5869 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5870 if (!__import__)
5871 goto bad;
5872 if (from_list)
5873 list = from_list;
5874 else {
5875 empty_list = PyList_New(0);
5876 if (!empty_list)
5877 goto bad;
5878 list = empty_list;
5879 }
5880 global_dict = PyModule_GetDict(%(GLOBALS)s);
5881 if (!global_dict)
5882 goto bad;
5883 empty_dict = PyDict_New();
5884 if (!empty_dict)
5885 goto bad;
5886 module = PyObject_CallFunctionObjArgs(__import__,
5887 name, global_dict, empty_dict, list, NULL);
5888 bad:
5889 Py_XDECREF(empty_list);
5890 Py_XDECREF(__import__);
5891 Py_XDECREF(empty_dict);
5892 return module;
5893 }
5894 """ % {
5895 "BUILTINS": Naming.builtins_cname,
5896 "GLOBALS": Naming.module_cname,
5897 })
5899 #------------------------------------------------------------------------------------
5901 get_exception_utility_code = UtilityCode(
5902 proto = """
5903 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5904 """,
5905 impl = """
5906 static PyObject *__Pyx_GetExcValue(void) {
5907 PyObject *type = 0, *value = 0, *tb = 0;
5908 PyObject *tmp_type, *tmp_value, *tmp_tb;
5909 PyObject *result = 0;
5910 PyThreadState *tstate = PyThreadState_Get();
5911 PyErr_Fetch(&type, &value, &tb);
5912 PyErr_NormalizeException(&type, &value, &tb);
5913 if (PyErr_Occurred())
5914 goto bad;
5915 if (!value) {
5916 value = Py_None;
5917 Py_INCREF(value);
5918 }
5919 tmp_type = tstate->exc_type;
5920 tmp_value = tstate->exc_value;
5921 tmp_tb = tstate->exc_traceback;
5922 tstate->exc_type = type;
5923 tstate->exc_value = value;
5924 tstate->exc_traceback = tb;
5925 /* Make sure tstate is in a consistent state when we XDECREF
5926 these objects (XDECREF may run arbitrary code). */
5927 Py_XDECREF(tmp_type);
5928 Py_XDECREF(tmp_value);
5929 Py_XDECREF(tmp_tb);
5930 result = value;
5931 Py_XINCREF(result);
5932 type = 0;
5933 value = 0;
5934 tb = 0;
5935 bad:
5936 Py_XDECREF(type);
5937 Py_XDECREF(value);
5938 Py_XDECREF(tb);
5939 return result;
5940 }
5941 """)
5943 #------------------------------------------------------------------------------------
5945 type_test_utility_code = UtilityCode(
5946 proto = """
5947 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5948 """,
5949 impl = """
5950 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5951 if (!type) {
5952 PyErr_Format(PyExc_SystemError, "Missing type object");
5953 return 0;
5954 }
5955 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5956 return 1;
5957 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5958 Py_TYPE(obj)->tp_name, type->tp_name);
5959 return 0;
5960 }
5961 """)
5963 #------------------------------------------------------------------------------------
5965 create_class_utility_code = UtilityCode(
5966 proto = """
5967 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5968 """,
5969 impl = """
5970 static PyObject *__Pyx_CreateClass(
5971 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5972 {
5973 PyObject *py_modname;
5974 PyObject *result = 0;
5976 #if PY_MAJOR_VERSION < 3
5977 py_modname = PyString_FromString(modname);
5978 #else
5979 py_modname = PyUnicode_FromString(modname);
5980 #endif
5981 if (!py_modname)
5982 goto bad;
5983 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5984 goto bad;
5985 #if PY_MAJOR_VERSION < 3
5986 result = PyClass_New(bases, dict, name);
5987 #else
5988 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5989 #endif
5990 bad:
5991 Py_XDECREF(py_modname);
5992 return result;
5993 }
5994 """)
5996 #------------------------------------------------------------------------------------
5998 cpp_exception_utility_code = UtilityCode(
5999 proto = """
6000 #ifndef __Pyx_CppExn2PyErr
6001 static void __Pyx_CppExn2PyErr() {
6002 try {
6003 if (PyErr_Occurred())
6004 ; // let the latest Python exn pass through and ignore the current one
6005 else
6006 throw;
6007 } catch (const std::out_of_range& exn) {
6008 // catch out_of_range explicitly so the proper Python exn may be raised
6009 PyErr_SetString(PyExc_IndexError, exn.what());
6010 } catch (const std::exception& exn) {
6011 PyErr_SetString(PyExc_RuntimeError, exn.what());
6012 }
6013 catch (...)
6014 {
6015 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
6016 }
6017 }
6018 #endif
6019 """,
6020 impl = ""
6021 )
6023 #------------------------------------------------------------------------------------
6025 # If the is_unsigned flag is set, we need to do some extra work to make
6026 # sure the index doesn't become negative.
6028 getitem_int_utility_code = UtilityCode(
6029 proto = """
6031 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
6032 PyObject *r;
6033 if (!j) return NULL;
6034 r = PyObject_GetItem(o, j);
6035 Py_DECREF(j);
6036 return r;
6037 }
6039 """ + ''.join([
6040 """
6041 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6042 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
6043 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6045 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6046 if (likely(o != Py_None)) {
6047 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
6048 PyObject *r = Py%(type)s_GET_ITEM(o, i);
6049 Py_INCREF(r);
6050 return r;
6051 }
6052 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
6053 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
6054 Py_INCREF(r);
6055 return r;
6056 }
6057 }
6058 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6059 }
6060 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
6061 ]) + """
6063 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6064 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
6065 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
6067 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6068 PyObject *r;
6069 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6070 r = PyList_GET_ITEM(o, i);
6071 Py_INCREF(r);
6072 }
6073 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
6074 r = PyTuple_GET_ITEM(o, i);
6075 Py_INCREF(r);
6076 }
6077 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
6078 r = PySequence_GetItem(o, i);
6079 }
6080 else {
6081 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
6082 }
6083 return r;
6084 }
6085 """,
6086 impl = """
6087 """)
6091 #------------------------------------------------------------------------------------
6093 setitem_int_utility_code = UtilityCode(
6094 proto = """
6095 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6096 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
6097 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
6099 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
6100 int r;
6101 if (!j) return -1;
6102 r = PyObject_SetItem(o, j, v);
6103 Py_DECREF(j);
6104 return r;
6105 }
6107 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
6108 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
6109 Py_INCREF(v);
6110 Py_DECREF(PyList_GET_ITEM(o, i));
6111 PyList_SET_ITEM(o, i, v);
6112 return 1;
6113 }
6114 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
6115 return PySequence_SetItem(o, i, v);
6116 else {
6117 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6118 return __Pyx_SetItemInt_Generic(o, j, v);
6119 }
6120 }
6121 """,
6122 impl = """
6123 """)
6125 #------------------------------------------------------------------------------------
6127 delitem_int_utility_code = UtilityCode(
6128 proto = """
6129 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
6130 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
6131 __Pyx_DelItem_Generic(o, to_py_func(i)))
6133 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
6134 int r;
6135 if (!j) return -1;
6136 r = PyObject_DelItem(o, j);
6137 Py_DECREF(j);
6138 return r;
6139 }
6141 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
6142 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
6143 return PySequence_DelItem(o, i);
6144 else {
6145 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
6146 return __Pyx_DelItem_Generic(o, j);
6147 }
6148 }
6149 """,
6150 impl = """
6151 """)
6153 #------------------------------------------------------------------------------------
6155 raise_noneattr_error_utility_code = UtilityCode(
6156 proto = """
6157 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
6158 """,
6159 impl = '''
6160 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
6161 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
6162 }
6163 ''')
6165 raise_noneindex_error_utility_code = UtilityCode(
6166 proto = """
6167 static INLINE void __Pyx_RaiseNoneIndexingError(void);
6168 """,
6169 impl = '''
6170 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
6171 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
6172 }
6173 ''')
6175 raise_none_iter_error_utility_code = UtilityCode(
6176 proto = """
6177 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
6178 """,
6179 impl = '''
6180 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
6181 PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
6182 }
6183 ''')
6185 raise_too_many_values_to_unpack = UtilityCode(
6186 proto = """
6187 static INLINE void __Pyx_RaiseTooManyValuesError(void);
6188 """,
6189 impl = '''
6190 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
6191 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
6192 }
6193 ''')
6195 raise_need_more_values_to_unpack = UtilityCode(
6196 proto = """
6197 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
6198 """,
6199 impl = '''
6200 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
6201 PyErr_Format(PyExc_ValueError,
6202 #if PY_VERSION_HEX < 0x02050000
6203 "need more than %d value%s to unpack", (int)index,
6204 #else
6205 "need more than %zd value%s to unpack", index,
6206 #endif
6207 (index == 1) ? "" : "s");
6208 }
6209 ''')
6211 #------------------------------------------------------------------------------------
6213 tuple_unpacking_error_code = UtilityCode(
6214 proto = """
6215 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
6216 """,
6217 impl = """
6218 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
6219 if (t == Py_None) {
6220 __Pyx_RaiseNoneNotIterableError();
6221 } else if (PyTuple_GET_SIZE(t) < index) {
6222 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
6223 } else {
6224 __Pyx_RaiseTooManyValuesError();
6225 }
6226 }
6227 """,
6228 requires = [raise_none_iter_error_utility_code,
6229 raise_need_more_values_to_unpack,
6230 raise_too_many_values_to_unpack]
6231 )
6233 unpacking_utility_code = UtilityCode(
6234 proto = """
6235 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
6236 static int __Pyx_EndUnpack(PyObject *); /*proto*/
6237 """,
6238 impl = """
6239 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
6240 PyObject *item;
6241 if (!(item = PyIter_Next(iter))) {
6242 if (!PyErr_Occurred()) {
6243 __Pyx_RaiseNeedMoreValuesError(index);
6244 }
6245 }
6246 return item;
6247 }
6249 static int __Pyx_EndUnpack(PyObject *iter) {
6250 PyObject *item;
6251 if ((item = PyIter_Next(iter))) {
6252 Py_DECREF(item);
6253 __Pyx_RaiseTooManyValuesError();
6254 return -1;
6255 }
6256 else if (!PyErr_Occurred())
6257 return 0;
6258 else
6259 return -1;
6260 }
6261 """,
6262 requires = [raise_need_more_values_to_unpack,
6263 raise_too_many_values_to_unpack]
6264 )
6267 #------------------------------------------------------------------------------------
6269 int_pow_utility_code = UtilityCode(
6270 proto="""
6271 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
6272 """,
6273 impl="""
6274 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
6275 %(type)s t = b;
6276 switch (e) {
6277 case 3:
6278 t *= b;
6279 case 2:
6280 t *= b;
6281 case 1:
6282 return t;
6283 case 0:
6284 return 1;
6285 }
6286 if (unlikely(e<0)) return 0;
6287 t = 1;
6288 while (likely(e)) {
6289 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
6290 b *= b;
6291 e >>= 1;
6292 }
6293 return t;
6294 }
6295 """)
6297 # ------------------------------ Division ------------------------------------
6299 div_int_utility_code = UtilityCode(
6300 proto="""
6301 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
6302 """,
6303 impl="""
6304 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6305 %(type)s q = a / b;
6306 %(type)s r = a - q*b;
6307 q -= ((r != 0) & ((r ^ b) < 0));
6308 return q;
6309 }
6310 """)
6312 mod_int_utility_code = UtilityCode(
6313 proto="""
6314 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6315 """,
6316 impl="""
6317 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6318 %(type)s r = a %% b;
6319 r += ((r != 0) & ((r ^ b) < 0)) * b;
6320 return r;
6321 }
6322 """)
6324 mod_float_utility_code = UtilityCode(
6325 proto="""
6326 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6327 """,
6328 impl="""
6329 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6330 %(type)s r = fmod%(math_h_modifier)s(a, b);
6331 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6332 return r;
6333 }
6334 """)
6336 cdivision_warning_utility_code = UtilityCode(
6337 proto="""
6338 static int __Pyx_cdivision_warning(void); /* proto */
6339 """,
6340 impl="""
6341 static int __Pyx_cdivision_warning(void) {
6342 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6343 "division with oppositely signed operands, C and Python semantics differ",
6344 %(FILENAME)s,
6345 %(LINENO)s,
6346 __Pyx_MODULE_NAME,
6347 NULL);
6348 }
6349 """ % {
6350 'FILENAME': Naming.filename_cname,
6351 'LINENO': Naming.lineno_cname,
6352 })
6354 # from intobject.c
6355 division_overflow_test_code = UtilityCode(
6356 proto="""
6357 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6358 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
6359 """)
